コード例 #1
0
/*
 * Hook to allow handling of NTLM authentication for AD operation
 * without directly linking the s4 auth stack
 *
 * This ensures we use the source4 authentication stack, as well as
 * the authorization stack to create the user's token.  This ensures
 * consistency between NTLM logins and NTLMSSP logins, as NTLMSSP is
 * handled by the hook above.
 */
static NTSTATUS make_auth4_context_s4(TALLOC_CTX *mem_ctx,
				      struct auth4_context **auth4_context)
{
	NTSTATUS status;
	struct loadparm_context *lp_ctx;
	struct tevent_context *event_ctx;
	TALLOC_CTX *frame = talloc_stackframe();
	struct imessaging_context *msg_ctx;
	struct server_id *server_id;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
	if (lp_ctx == NULL) {
		DEBUG(1, ("loadparm_init_s3 failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	event_ctx = s4_event_context_init(frame);
	if (event_ctx == NULL) {
		DEBUG(1, ("s4_event_context_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	server_id = new_server_id_task(frame);
	if (server_id == NULL) {
		DEBUG(1, ("new_server_id_task failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	msg_ctx = imessaging_init(frame,
				  lp_ctx,
				  *server_id,
				  event_ctx, true);
	if (msg_ctx == NULL) {
		DEBUG(1, ("imessaging_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	talloc_reparent(frame, msg_ctx, server_id);

	status = auth_context_create(mem_ctx,
					event_ctx,
					msg_ctx,
					lp_ctx,
					auth4_context);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to start auth server code: %s\n", nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	talloc_reparent(frame, *auth4_context, msg_ctx);
	talloc_reparent(frame, *auth4_context, event_ctx);
	talloc_reparent(frame, *auth4_context, lp_ctx);

	TALLOC_FREE(frame);
	return status;
}
コード例 #2
0
ファイル: cbuf.c プロジェクト: ElijahLuk/samba
void cbuf_swap(cbuf* b1, cbuf* b2)
{
    if (b1 == b2) {
        return;
    }
    talloc_reparent(b1, b2, b1->buf);
    talloc_reparent(b2, b1, b2->buf);
    SWAP(b1->buf,  b2->buf, char*);
    SWAP(b1->pos,  b2->pos, size_t);
    SWAP(b1->size, b2->size, size_t);
}
コード例 #3
0
ファイル: wb_init_domain.c プロジェクト: AllardJ/Tomato
/* Having make a netlogon connection (possibly secured with schannel),
 * make an LSA connection to the same DC, on the same IPC$ share */
static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
{
	struct init_domain_state *state =
		talloc_get_type(ctx->async.private_data,
				struct init_domain_state);

	state->ctx->status = dcerpc_pipe_connect_b_recv(ctx, state->domain, 
						   &state->domain->netlogon_pipe);
	
	if (!composite_is_ok(state->ctx)) {
		return;
	}
	talloc_reparent(state, state->domain->netlogon_pipe, state->domain->netlogon_binding);

	state->domain->lsa_binding = init_domain_binding(state, &ndr_table_lsarpc);

	/* For debugging, it can be a real pain if all the traffic is encrypted */
	if (lp_winbind_sealed_pipes(state->service->task->lp_ctx)) {
		state->domain->lsa_binding->flags |= (DCERPC_SIGN | DCERPC_SEAL );
	} else {
		state->domain->lsa_binding->flags |= (DCERPC_SIGN);
	}

	state->domain->libnet_ctx->lsa.pipe = NULL;

	/* this will make the secondary connection on the same IPC$ share, 
	   secured with SPNEGO or NTLMSSP */
	ctx = dcerpc_secondary_auth_connection_send(state->domain->netlogon_pipe,
						    state->domain->lsa_binding,
						    &ndr_table_lsarpc,
						    state->domain->libnet_ctx->cred,
						    state->domain->libnet_ctx->lp_ctx
		);
	composite_continue(state->ctx, ctx, init_domain_recv_lsa_pipe, state);
}
コード例 #4
0
ファイル: cbuf.c プロジェクト: ElijahLuk/samba
cbuf* cbuf_takeover(cbuf* b1, cbuf* b2)
{
    talloc_reparent(b2, b1, b2->buf);
    b1->buf = b2->buf;
    b1->pos = b2->pos;
    b1->size = b2->size;
    cbuf_delete(b2);
    return b1;
}
コード例 #5
0
ファイル: clitrans.c プロジェクト: AIdrifter/samba
static int cli_trans_state_ptr_destructor(struct cli_trans_state **ptr)
{
	struct cli_trans_state *state = *ptr;
	void *parent = talloc_parent(state);

	talloc_set_destructor(state, NULL);

	talloc_reparent(state, parent, state->req);
	talloc_free(state);
	return 0;
}
コード例 #6
0
ファイル: exit.c プロジェクト: MatthewTighe/GNURootDebian
/**
 * Bind content of @vectors over /proc/{@ptracee->pid}/auxv.  This
 * function returns -1 if an error occurred, otherwise 0.
 */
static int bind_proc_pid_auxv(const Tracee *ptracee)
{
	word_t vectors_address;
	ElfAuxVector *vectors;

	const char *guest_path;
	const char *host_path;
	Binding *binding;
	int status;

	vectors_address = get_elf_aux_vectors_address(ptracee);
	if (vectors_address == 0)
		return -1;

	vectors = fetch_elf_aux_vectors(ptracee, vectors_address);
	if (vectors == NULL)
		return -1;

	/* Path to these ELF auxiliary vectors.  */
	guest_path = talloc_asprintf(ptracee->ctx, "/proc/%d/auxv", ptracee->pid);
	if (guest_path == NULL)
		return -1;

	/* Remove binding to this path, if any.  It contains ELF
	 * auxiliary vectors of the previous execve(2).  */
	binding = get_binding(ptracee, GUEST, guest_path);
	if (binding != NULL && compare_paths(binding->guest.path, guest_path) == PATHS_ARE_EQUAL) {
		remove_binding_from_all_lists(ptracee, binding);
		TALLOC_FREE(binding);
	}

	host_path = create_temp_file(ptracee->ctx, "auxv");
	if (host_path == NULL)
		return -1;

	status = fill_file_with_auxv(ptracee, host_path, vectors);
	if (status < 0)
		return -1;

	/* Note: this binding will be removed once ptracee gets freed.  */
	binding = insort_binding3(ptracee, ptracee->life_context, host_path, guest_path);
	if (binding == NULL)
		return -1;

	/* This temporary file (host_path) will be removed once the
	 * binding is freed.  */
	talloc_reparent(ptracee->ctx, binding, host_path);

	return 0;
}
コード例 #7
0
ファイル: clitrans.c プロジェクト: AIdrifter/samba
struct tevent_req *cli_trans_send(
	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
	struct cli_state *cli, uint8_t cmd,
	const char *pipe_name, uint16_t fid, uint16_t function, int flags,
	uint16_t *setup, uint8_t num_setup, uint8_t max_setup,
	uint8_t *param, uint32_t num_param, uint32_t max_param,
	uint8_t *data, uint32_t num_data, uint32_t max_data)
{
	struct cli_trans_state *state;
	uint8_t additional_flags = 0;
	uint8_t clear_flags = 0;
	uint16_t additional_flags2 = 0;
	uint16_t clear_flags2 = 0;

	state = talloc_zero(mem_ctx, struct cli_trans_state);
	if (state == NULL) {
		return NULL;
	}
	state->cli = cli;
	state->ptr = talloc(state, struct cli_trans_state *);
	if (state->ptr == NULL) {
		talloc_free(state);
		return NULL;
	}
	*state->ptr = state;

	state->req = smb1cli_trans_send(state, ev,
					cli->conn, cmd,
					additional_flags, clear_flags,
					additional_flags2, clear_flags2,
					cli->timeout,
					cli->smb1.pid,
					cli->smb1.tcon,
					cli->smb1.session,
					pipe_name, fid, function, flags,
					setup, num_setup, max_setup,
					param, num_param, max_param,
					data, num_data, max_data);
	if (state->req == NULL) {
		talloc_free(state);
		return NULL;
	}

	talloc_reparent(state, state->req, state->ptr);
	talloc_set_destructor(state, cli_trans_state_destructor);
	talloc_set_destructor(state->ptr, cli_trans_state_ptr_destructor);

	return state->req;
}
コード例 #8
0
ファイル: schema_set.c プロジェクト: sprymak/samba
void dsdb_make_schema_global(struct ldb_context *ldb, struct dsdb_schema *schema)
{
	if (!schema) {
		return;
	}

	if (global_schema) {
		talloc_unlink(talloc_autofree_context(), global_schema);
	}

	/* we want the schema to be around permanently */
	talloc_reparent(ldb, talloc_autofree_context(), schema);
	global_schema = schema;

	/* This calls the talloc_reference() of the global schema back onto the ldb */
	dsdb_set_global_schema(ldb);
}
コード例 #9
0
ファイル: schema_set.c プロジェクト: 0x24bin/winexe-1
void dsdb_make_schema_global(struct ldb_context *ldb)
{
	struct dsdb_schema *schema = dsdb_get_schema(ldb);
	if (!schema) {
		return;
	}

	if (global_schema) {
		talloc_unlink(talloc_autofree_context(), global_schema);
	}

	/* we want the schema to be around permanently */
	talloc_reparent(talloc_parent(schema), talloc_autofree_context(), schema);

	global_schema = schema;

	dsdb_set_global_schema(ldb);
}
コード例 #10
0
/* We should now have either an authenticated LSA pipe, or an error.  
 * On success, open a policy handle
 */	
static void init_domain_recv_lsa_pipe(struct composite_context *ctx)
{
	struct init_domain_state *state =
		talloc_get_type(ctx->async.private_data,
				struct init_domain_state);
	struct tevent_req *subreq;

	state->ctx->status = dcerpc_secondary_auth_connection_recv(ctx, state->domain,
								   &state->domain->libnet_ctx->lsa.pipe);
	if (NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_LOGON_FAILURE)) {
		if (retry_with_schannel(state, state->domain->lsa_binding, 
					&ndr_table_lsarpc,
					init_domain_recv_lsa_pipe)) {
			return;
		}
	}
	if (!composite_is_ok(state->ctx)) return;

	talloc_steal(state->domain->libnet_ctx, state->domain->libnet_ctx->lsa.pipe);
	talloc_reparent(state, state->domain->libnet_ctx->lsa.pipe, state->domain->lsa_binding);
	state->domain->libnet_ctx->lsa.lsa_handle =
		state->domain->libnet_ctx->lsa.pipe->binding_handle;
	state->domain->libnet_ctx->lsa.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	state->domain->libnet_ctx->lsa.name = state->domain->info->name;

	ZERO_STRUCT(state->domain->libnet_ctx->lsa.handle);
	state->lsa_openpolicy.in.system_name =
		talloc_asprintf(state, "\\\\%s",
				dcerpc_server_name(state->domain->libnet_ctx->lsa.pipe));
	ZERO_STRUCT(state->objectattr);
	state->lsa_openpolicy.in.attr = &state->objectattr;
	state->lsa_openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	state->lsa_openpolicy.out.handle = &state->domain->libnet_ctx->lsa.handle;

	subreq = dcerpc_lsa_OpenPolicy2_r_send(state,
					       state->ctx->event_ctx,
					       state->domain->libnet_ctx->lsa.pipe->binding_handle,
					       &state->lsa_openpolicy);
	if (composite_nomem(subreq, state->ctx)) return;
	tevent_req_set_callback(subreq, init_domain_recv_lsa_policy, state);
}
コード例 #11
0
ファイル: wb_init_domain.c プロジェクト: AllardJ/Tomato
/* Recv the SAMR details (SamrConnect and SamrOpenDomain handle) and
 * open an LDAP connection */
static void init_domain_recv_samr(struct composite_context *ctx)
{
	struct init_domain_state *state =
		talloc_get_type(ctx->async.private_data,
				struct init_domain_state);

	state->ctx->status = wb_connect_samr_recv(
		ctx, state->domain,
		&state->domain->libnet_ctx->samr.pipe,
		&state->domain->libnet_ctx->samr.connect_handle,
		&state->domain->libnet_ctx->samr.handle);
	if (!composite_is_ok(state->ctx)) return;

	talloc_reparent(state, state->domain->libnet_ctx->samr.pipe, state->domain->samr_binding);
	state->domain->libnet_ctx->samr.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	state->domain->libnet_ctx->samr.name = state->domain->info->name;
	state->domain->libnet_ctx->samr.sid = dom_sid_dup(
						state->domain->libnet_ctx,
						state->domain->info->sid);

	composite_done(state->ctx);
}
コード例 #12
0
ファイル: ldap_bind.c プロジェクト: kordano/samba-ldb-mdb
/*
  perform a sasl bind using the given credentials
*/
_PUBLIC_ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn,
			struct cli_credentials *creds,
			struct loadparm_context *lp_ctx)
{
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx = NULL;

	DATA_BLOB input = data_blob(NULL, 0);
	DATA_BLOB output = data_blob(NULL, 0);

	struct ldap_message **sasl_mechs_msgs;
	struct ldap_SearchResEntry *search;
	int count, i;

	const char **sasl_names;
	uint32_t old_gensec_features;
	static const char *supported_sasl_mech_attrs[] = {
		"supportedSASLMechanisms", 
		NULL 
	};
	unsigned int logon_retries = 0;

	status = ildap_search(conn, "", LDAP_SEARCH_SCOPE_BASE, "", supported_sasl_mech_attrs,
			      false, NULL, NULL, &sasl_mechs_msgs);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: %s\n",
			  nt_errstr(status)));
		goto failed;
	}

	count = ildap_count_entries(conn, sasl_mechs_msgs);
	if (count != 1) {
		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: wrong number of replies: %d\n",
			  count));
		goto failed;
	}

	tmp_ctx = talloc_new(conn);
	if (tmp_ctx == NULL) goto failed;

	search = &sasl_mechs_msgs[0]->r.SearchResultEntry;
	if (search->num_attributes != 1) {
		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: wrong number of attributes: %d != 1\n",
			  search->num_attributes));
		goto failed;
	}

	sasl_names = talloc_array(tmp_ctx, const char *, search->attributes[0].num_values + 1);
	if (!sasl_names) {
		DEBUG(1, ("talloc_arry(char *, %d) failed\n",
			  count));
		goto failed;
	}

	for (i=0; i<search->attributes[0].num_values; i++) {
		sasl_names[i] = (const char *)search->attributes[0].values[i].data;
	}
	sasl_names[i] = NULL;

	gensec_init();

try_logon_again:
	/*
	  we loop back here on a logon failure, and re-create the
	  gensec session. The logon_retries counter ensures we don't
	  loop forever.
	 */

	status = gensec_client_start(conn, &conn->gensec,
				     lpcfg_gensec_settings(conn, lp_ctx));
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
		goto failed;
	}

	/* require Kerberos SIGN/SEAL only if we don't use SSL
	 * Windows seem not to like double encryption */
	old_gensec_features = cli_credentials_get_gensec_features(creds);
	if (tls_enabled(conn->sock)) {
		cli_credentials_set_gensec_features(creds, old_gensec_features & ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL));
	}

	/* this call also sets the gensec_want_features */
	status = gensec_set_credentials(conn->gensec, creds);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to set GENSEC creds: %s\n", 
			  nt_errstr(status)));
		goto failed;
	}

	/* reset the original gensec_features (on the credentials
	 * context, so we don't tatoo it ) */
	cli_credentials_set_gensec_features(creds, old_gensec_features);

	if (conn->host) {
		status = gensec_set_target_hostname(conn->gensec, conn->host);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("Failed to set GENSEC target hostname: %s\n", 
				  nt_errstr(status)));
			goto failed;
		}
	}

	status = gensec_set_target_service(conn->gensec, "ldap");
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to set GENSEC target service: %s\n", 
			  nt_errstr(status)));
		goto failed;
	}

	status = gensec_start_mech_by_sasl_list(conn->gensec, sasl_names);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("None of the %d proposed SASL mechs were acceptable: %s\n",
			  count, nt_errstr(status)));
		goto failed;
	}

	while (1) {
		NTSTATUS gensec_status;
		struct ldap_message *response;
		struct ldap_message *msg;
		struct ldap_request *req;
		int result = LDAP_OTHER;
	
		status = gensec_update(conn->gensec, tmp_ctx,
				       conn->event.event_ctx,
				       input,
				       &output);
		/* The status value here, from GENSEC is vital to the security
		 * of the system.  Even if the other end accepts, if GENSEC
		 * claims 'MORE_PROCESSING_REQUIRED' then you must keep
		 * feeding it blobs, or else the remote host/attacker might
		 * avoid mutal authentication requirements.
		 *
		 * Likewise, you must not feed GENSEC too much (after the OK),
		 * it doesn't like that either
		 */

		gensec_status = status;

		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
		    !NT_STATUS_IS_OK(status)) {
			break;
		}
		if (NT_STATUS_IS_OK(status) && output.length == 0) {
			break;
		}

		/* Perhaps we should make gensec_start_mech_by_sasl_list() return the name we got? */
		msg = new_ldap_sasl_bind_msg(tmp_ctx, conn->gensec->ops->sasl_name, (output.data?&output:NULL));
		if (msg == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto failed;
		}

		req = ldap_request_send(conn, msg);
		if (req == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto failed;
		}
		talloc_reparent(conn, tmp_ctx, req);

		status = ldap_result_n(req, 0, &response);
		if (!NT_STATUS_IS_OK(status)) {
			goto failed;
		}
		
		if (response->type != LDAP_TAG_BindResponse) {
			status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
			goto failed;
		}

		result = response->r.BindResponse.response.resultcode;

		if (result == LDAP_INVALID_CREDENTIALS) {
			/*
			  try a second time on invalid credentials, to
			  give the user a chance to re-enter the
			  password and to handle the case where our
			  kerberos ticket is invalid as the server
			  password has changed
			*/
			const char *principal;

			principal = gensec_get_target_principal(conn->gensec);
			if (principal == NULL) {
				const char *hostname = gensec_get_target_hostname(conn->gensec);
				const char *service  = gensec_get_target_service(conn->gensec);
				if (hostname != NULL && service != NULL) {
					principal = talloc_asprintf(tmp_ctx, "%s/%s", service, hostname);
				}
			}

			if (cli_credentials_failed_kerberos_login(creds, principal, &logon_retries) ||
			    cli_credentials_wrong_password(creds)) {
				/*
				  destroy our gensec session and loop
				  back up to the top to retry,
				  offering the user a chance to enter
				  new credentials, or get a new ticket
				  if using kerberos
				 */
				talloc_free(conn->gensec);
				conn->gensec = NULL;
				goto try_logon_again;
			}
		}

		if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
			status = ldap_check_response(conn, 
						     &response->r.BindResponse.response);
			break;
		}

		/* This is where we check if GENSEC wanted to be fed more data */
		if (!NT_STATUS_EQUAL(gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			break;
		}
		if (response->r.BindResponse.SASL.secblob) {
			input = *response->r.BindResponse.SASL.secblob;
		} else {
			input = data_blob(NULL, 0);
		}
	}

	talloc_free(tmp_ctx);

	if (NT_STATUS_IS_OK(status)) {
		struct socket_context *sasl_socket;
		status = gensec_socket_init(conn->gensec, 
					    conn,
					    conn->sock,
					    conn->event.event_ctx, 
					    ldap_read_io_handler,
					    conn,
					    &sasl_socket);
		if (!NT_STATUS_IS_OK(status)) goto failed;

		conn->sock = sasl_socket;
		packet_set_socket(conn->packet, conn->sock);

		conn->bind.type = LDAP_BIND_SASL;
		conn->bind.creds = creds;
	}

	return status;

failed:
	talloc_free(tmp_ctx);
	talloc_free(conn->gensec);
	conn->gensec = NULL;
	return status;
}
コード例 #13
0
ファイル: socket.c プロジェクト: BobbWu/PRoot
/**
 * Translate the pathname of the struct sockaddr_un currently stored
 * in the @tracee memory at the given @address.  See the documentation
 * of read_sockaddr_un() for the meaning of the @size parameter.
 * Also, the new address of the translated sockaddr_un is put in the
 * @address parameter.  This function returns -errno if an error
 * occurred, otherwise 0.
 */
int translate_socketcall_enter(Tracee *tracee, word_t *address, int size)
{
	struct sockaddr_un sockaddr;
	char user_path[PATH_MAX];
	char host_path[PATH_MAX];
	int status;

	if (*address == 0)
		return 0;

	status = read_sockaddr_un(tracee, &sockaddr, sizeof(sockaddr), user_path, *address, size);
	if (status <= 0)
		return status;

	status = translate_path(tracee, host_path, AT_FDCWD, user_path, true);
	if (status < 0)
		return status;

	/* Be careful: sun_path doesn't have to be null-terminated.  */
	if (strlen(host_path) > sizeof_path) {
		char *shorter_host_path;
		Binding *binding;

		/* The translated path is too long to fit the sun_path
		 * array, so let's bind it to a shorter path.  */
		shorter_host_path = create_temp_name(tracee->ctx, "proot");
		if (shorter_host_path == NULL || strlen(shorter_host_path) > sizeof_path)
			return -EINVAL;

		(void) mktemp(shorter_host_path);

		if (strlen(shorter_host_path) > sizeof_path)
			return -EINVAL;

		/* Ensure the guest path of this new binding is
		 * canonicalized, as it is always assumed.  */
		strcpy(user_path, host_path);
		status = detranslate_path(tracee, user_path, NULL);
		if (status < 0)
			return -EINVAL;

		/* Bing the guest path to a shorter host path.  */
		binding = insort_binding3(tracee, tracee->ctx, shorter_host_path, user_path);
		if (binding == NULL)
			return -EINVAL;

		/* This temporary file (shorter_host_path) will be removed once the
		 * binding is destroyed.  */
		talloc_reparent(tracee->ctx, binding, shorter_host_path);

		/* Let's use this shorter path now.  */
		strcpy(host_path, shorter_host_path);
	}
	strncpy(sockaddr.sun_path, host_path, sizeof_path);

	/* Push the updated sockaddr to a newly allocated space.  */
	*address = alloc_mem(tracee, sizeof(sockaddr));
	if (*address == 0)
		return -EFAULT;

	status = write_data(tracee, *address, &sockaddr, sizeof(sockaddr));
	if (status < 0)
		return status;

	return 1;
}
コード例 #14
0
ファイル: talloc_compat1.c プロジェクト: venkatarajasekhar/Qt
void *_talloc_steal(const void *new_ctx, const void *ptr)
{
	return talloc_reparent(talloc_parent(ptr), new_ctx, ptr);
}
コード例 #15
0
ファイル: auth_samba4.c プロジェクト: zentyal/samba
/*
 * Hook to allow handling of NTLM authentication for AD operation
 * without directly linking the s4 auth stack
 *
 * This ensures we use the source4 authentication stack, as well as
 * the authorization stack to create the user's token.  This ensures
 * consistency between NTLM logins and NTLMSSP logins, as NTLMSSP is
 * handled by the hook above.
 */
static NTSTATUS make_auth4_context_s4(const struct auth_context *auth_context,
				      TALLOC_CTX *mem_ctx,
				      struct auth4_context **auth4_context)
{
	NTSTATUS status;
	struct loadparm_context *lp_ctx;
	struct tevent_context *event_ctx;
	TALLOC_CTX *frame = talloc_stackframe();
	struct imessaging_context *msg_ctx;
	struct server_id *server_id;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
	if (lp_ctx == NULL) {
		DEBUG(1, ("loadparm_init_s3 failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	event_ctx = s4_event_context_init(frame);
	if (event_ctx == NULL) {
		DEBUG(1, ("s4_event_context_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	server_id = new_server_id_task(frame);
	if (server_id == NULL) {
		DEBUG(1, ("new_server_id_task failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	msg_ctx = imessaging_init(frame,
				  lp_ctx,
				  *server_id,
				  event_ctx, true);
	if (msg_ctx == NULL) {
		DEBUG(1, ("imessaging_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	talloc_reparent(frame, msg_ctx, server_id);

	/* Allow forcing a specific auth4 module */
	if (!auth_context->forced_samba4_methods) {
		status = auth_context_create(mem_ctx,
					     event_ctx,
					     msg_ctx,
					     lp_ctx,
					     auth4_context);
	} else {
		const char * const *forced_auth_methods = (const char * const *)str_list_make(mem_ctx, auth_context->forced_samba4_methods, NULL);
		status = auth_context_create_methods(mem_ctx, forced_auth_methods, event_ctx, msg_ctx, lp_ctx, NULL, auth4_context);
	}
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to start auth server code: %s\n", nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	talloc_reparent(frame, *auth4_context, msg_ctx);
	talloc_reparent(frame, *auth4_context, event_ctx);
	talloc_reparent(frame, *auth4_context, lp_ctx);

	TALLOC_FREE(frame);
	return status;
}
コード例 #16
0
/* Hook to allow GENSEC to handle blob-based authentication
 * mechanisms, without directly linking the mechansim code */
static NTSTATUS prepare_gensec(TALLOC_CTX *mem_ctx,
			       struct gensec_security **gensec_context)
{
	NTSTATUS status;
	struct loadparm_context *lp_ctx;
	struct tevent_context *event_ctx;
	TALLOC_CTX *frame = talloc_stackframe();
	struct gensec_security *gensec_ctx;
	struct imessaging_context *msg_ctx;
	struct cli_credentials *server_credentials;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_context());
	if (lp_ctx == NULL) {
		DEBUG(1, ("loadparm_init_s3 failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	event_ctx = s4_event_context_init(frame);
	if (event_ctx == NULL) {
		DEBUG(1, ("s4_event_context_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	msg_ctx = imessaging_client_init(frame,
					 lp_ctx,
					 event_ctx);
	if (msg_ctx == NULL) {
		DEBUG(1, ("imessaging_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	server_credentials
		= cli_credentials_init(frame);
	if (!server_credentials) {
		DEBUG(1, ("Failed to init server credentials"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	cli_credentials_set_conf(server_credentials, lp_ctx);
	status = cli_credentials_set_machine_account(server_credentials, lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
		talloc_free(server_credentials);
		server_credentials = NULL;
	}

	status = samba_server_gensec_start(mem_ctx,
					   event_ctx, msg_ctx,
					   lp_ctx, server_credentials, "cifs",
					   &gensec_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	talloc_reparent(frame, gensec_ctx, msg_ctx);
	talloc_reparent(frame, gensec_ctx, event_ctx);
	talloc_reparent(frame, gensec_ctx, lp_ctx);
	talloc_reparent(frame, gensec_ctx, server_credentials);

	gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
	gensec_want_feature(gensec_ctx, GENSEC_FEATURE_UNIX_TOKEN);

	*gensec_context = gensec_ctx;
	TALLOC_FREE(frame);
	return status;
}
コード例 #17
0
ファイル: ldap_bind.c プロジェクト: aixoss/samba
/*
  perform a sasl bind using the given credentials
*/
_PUBLIC_ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn,
			struct cli_credentials *creds,
			struct loadparm_context *lp_ctx)
{
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx = NULL;

	DATA_BLOB input = data_blob(NULL, 0);
	DATA_BLOB output = data_blob(NULL, 0);

	struct ldap_message **sasl_mechs_msgs;
	struct ldap_SearchResEntry *search;
	int count, i;
	bool first = true;
	int wrap_flags = 0;
	const char **sasl_names;
	uint32_t old_gensec_features;
	static const char *supported_sasl_mech_attrs[] = {
		"supportedSASLMechanisms", 
		NULL 
	};
	unsigned int logon_retries = 0;
	size_t queue_length;

	if (conn->sockets.active == NULL) {
		status = NT_STATUS_CONNECTION_DISCONNECTED;
		goto failed;
	}

	queue_length = tevent_queue_length(conn->sockets.send_queue);
	if (queue_length != 0) {
		status = NT_STATUS_INVALID_PARAMETER_MIX;
		DEBUG(1, ("SASL bind triggered with non empty send_queue[%zu]: %s\n",
			  queue_length, nt_errstr(status)));
		goto failed;
	}

	if (conn->pending != NULL) {
		status = NT_STATUS_INVALID_PARAMETER_MIX;
		DEBUG(1, ("SASL bind triggered with pending requests: %s\n",
			  nt_errstr(status)));
		goto failed;
	}

	status = ildap_search(conn, "", LDAP_SEARCH_SCOPE_BASE, "", supported_sasl_mech_attrs,
			      false, NULL, NULL, &sasl_mechs_msgs);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: %s\n",
			  nt_errstr(status)));
		goto failed;
	}

	count = ildap_count_entries(conn, sasl_mechs_msgs);
	if (count != 1) {
		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: wrong number of replies: %d\n",
			  count));
		goto failed;
	}

	tmp_ctx = talloc_new(conn);
	if (tmp_ctx == NULL) goto failed;

	search = &sasl_mechs_msgs[0]->r.SearchResultEntry;
	if (search->num_attributes != 1) {
		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: wrong number of attributes: %d != 1\n",
			  search->num_attributes));
		goto failed;
	}

	sasl_names = talloc_array(tmp_ctx, const char *, search->attributes[0].num_values + 1);
	if (!sasl_names) {
		DEBUG(1, ("talloc_arry(char *, %d) failed\n",
			  count));
		goto failed;
	}

	for (i=0; i<search->attributes[0].num_values; i++) {
		sasl_names[i] = (const char *)search->attributes[0].values[i].data;
	}
	sasl_names[i] = NULL;

	gensec_init();

	if (conn->sockets.active == conn->sockets.tls) {
		/*
		 * require Kerberos SIGN/SEAL only if we don't use SSL
		 * Windows seem not to like double encryption
		 */
		wrap_flags = 0;
	} else if (cli_credentials_is_anonymous(creds)) {
		/*
		 * anonymous isn't protected
		 */
		wrap_flags = 0;
	} else {
		wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
	}

try_logon_again:
	/*
	  we loop back here on a logon failure, and re-create the
	  gensec session. The logon_retries counter ensures we don't
	  loop forever.
	 */
	data_blob_free(&input);
	TALLOC_FREE(conn->gensec);

	status = gensec_client_start(conn, &conn->gensec,
				     lpcfg_gensec_settings(conn, lp_ctx));
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
		goto failed;
	}

	old_gensec_features = cli_credentials_get_gensec_features(creds);
	if (wrap_flags == 0) {
		cli_credentials_set_gensec_features(creds, old_gensec_features & ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL));
	}

	/* this call also sets the gensec_want_features */
	status = gensec_set_credentials(conn->gensec, creds);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to set GENSEC creds: %s\n", 
			  nt_errstr(status)));
		goto failed;
	}

	/* reset the original gensec_features (on the credentials
	 * context, so we don't tatoo it ) */
	cli_credentials_set_gensec_features(creds, old_gensec_features);

	if (wrap_flags & ADS_AUTH_SASL_SEAL) {
		gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
		gensec_want_feature(conn->gensec, GENSEC_FEATURE_SEAL);
	}
	if (wrap_flags & ADS_AUTH_SASL_SIGN) {
		gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
	}

	/*
	 * This is an indication for the NTLMSSP backend to
	 * also encrypt when only GENSEC_FEATURE_SIGN is requested
	 * in gensec_[un]wrap().
	 */
	gensec_want_feature(conn->gensec, GENSEC_FEATURE_LDAP_STYLE);

	if (conn->host) {
		status = gensec_set_target_hostname(conn->gensec, conn->host);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("Failed to set GENSEC target hostname: %s\n", 
				  nt_errstr(status)));
			goto failed;
		}
	}

	status = gensec_set_target_service(conn->gensec, "ldap");
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to set GENSEC target service: %s\n", 
			  nt_errstr(status)));
		goto failed;
	}

	status = gensec_start_mech_by_sasl_list(conn->gensec, sasl_names);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("None of the %d proposed SASL mechs were acceptable: %s\n",
			  count, nt_errstr(status)));
		goto failed;
	}

	while (1) {
		NTSTATUS gensec_status;
		struct ldap_message *response;
		struct ldap_message *msg;
		struct ldap_request *req;
		int result = LDAP_OTHER;
	
		status = gensec_update_ev(conn->gensec, tmp_ctx,
				       conn->event.event_ctx,
				       input,
				       &output);
		/* The status value here, from GENSEC is vital to the security
		 * of the system.  Even if the other end accepts, if GENSEC
		 * claims 'MORE_PROCESSING_REQUIRED' then you must keep
		 * feeding it blobs, or else the remote host/attacker might
		 * avoid mutal authentication requirements.
		 *
		 * Likewise, you must not feed GENSEC too much (after the OK),
		 * it doesn't like that either.
		 *
		 * For SASL/EXTERNAL, there is no data to send, but we still
		 * must send the actual Bind request the first time around.
		 * Otherwise, a result of NT_STATUS_OK with 0 output means the
		 * end of a multi-step authentication, and no message must be
		 * sent.
		 */

		gensec_status = status;

		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
		    !NT_STATUS_IS_OK(status)) {
			break;
		}
		if (NT_STATUS_IS_OK(status) && output.length == 0) {
			if (!first)
				break;
		}
		first = false;

		/* Perhaps we should make gensec_start_mech_by_sasl_list() return the name we got? */
		msg = new_ldap_sasl_bind_msg(tmp_ctx, conn->gensec->ops->sasl_name, (output.data?&output:NULL));
		if (msg == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto failed;
		}

		req = ldap_request_send(conn, msg);
		if (req == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto failed;
		}
		talloc_reparent(conn, tmp_ctx, req);

		status = ldap_result_n(req, 0, &response);
		if (!NT_STATUS_IS_OK(status)) {
			goto failed;
		}
		
		if (response->type != LDAP_TAG_BindResponse) {
			status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
			goto failed;
		}

		result = response->r.BindResponse.response.resultcode;

		if (result == LDAP_STRONG_AUTH_REQUIRED) {
			if (wrap_flags == 0) {
				wrap_flags = ADS_AUTH_SASL_SIGN;
				goto try_logon_again;
			}
		}

		if (result == LDAP_INVALID_CREDENTIALS) {
			/*
			  try a second time on invalid credentials, to
			  give the user a chance to re-enter the
			  password and to handle the case where our
			  kerberos ticket is invalid as the server
			  password has changed
			*/
			const char *principal;

			principal = gensec_get_target_principal(conn->gensec);
			if (principal == NULL) {
				const char *hostname = gensec_get_target_hostname(conn->gensec);
				const char *service  = gensec_get_target_service(conn->gensec);
				if (hostname != NULL && service != NULL) {
					principal = talloc_asprintf(tmp_ctx, "%s/%s", service, hostname);
				}
			}

			if (cli_credentials_failed_kerberos_login(creds, principal, &logon_retries) ||
			    cli_credentials_wrong_password(creds)) {
				/*
				  destroy our gensec session and loop
				  back up to the top to retry,
				  offering the user a chance to enter
				  new credentials, or get a new ticket
				  if using kerberos
				 */
				goto try_logon_again;
			}
		}

		if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
			status = ldap_check_response(conn, 
						     &response->r.BindResponse.response);
			break;
		}

		/* This is where we check if GENSEC wanted to be fed more data */
		if (!NT_STATUS_EQUAL(gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			break;
		}
		if (response->r.BindResponse.SASL.secblob) {
			input = *response->r.BindResponse.SASL.secblob;
		} else {
			input = data_blob(NULL, 0);
		}
	}

	TALLOC_FREE(tmp_ctx);

	if (!NT_STATUS_IS_OK(status)) {
		goto failed;
	}

	conn->bind.type = LDAP_BIND_SASL;
	conn->bind.creds = creds;

	if (wrap_flags & ADS_AUTH_SASL_SEAL) {
		if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN)) {
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}

		if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}
	} else if (wrap_flags & ADS_AUTH_SASL_SIGN) {
		if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN)) {
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}
	}

	if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) &&
	    !gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
		return NT_STATUS_OK;
	}

	status = gensec_create_tstream(conn->sockets.raw,
				       conn->gensec,
				       conn->sockets.raw,
				       &conn->sockets.sasl);
	if (!NT_STATUS_IS_OK(status)) {
		goto failed;
	}

	conn->sockets.active = conn->sockets.sasl;

	return NT_STATUS_OK;

failed:
	talloc_free(tmp_ctx);
	talloc_free(conn->gensec);
	conn->gensec = NULL;
	return status;
}