Esempio n. 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;
}
Esempio n. 2
0
NTSTATUS samba_server_gensec_start(TALLOC_CTX *mem_ctx,
				   struct tevent_context *event_ctx,
				   struct messaging_context *msg_ctx,
				   struct loadparm_context *lp_ctx,
				   struct cli_credentials *server_credentials,
				   const char *target_service,
				   struct gensec_security **gensec_context)
{ 
	NTSTATUS nt_status;
	struct gensec_security *gensec_ctx;
	struct auth_context *auth_context;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}
	
	nt_status = auth_context_create(tmp_ctx,
					event_ctx, 
					msg_ctx, 
					lp_ctx,
					&auth_context);
	
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(1, ("Failed to start auth server code: %s\n", nt_errstr(nt_status)));
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = gensec_server_start(tmp_ctx,
					event_ctx,
					lpcfg_gensec_settings(mem_ctx, lp_ctx),
					auth_context,
					&gensec_ctx);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(nt_status)));
		return nt_status;
	}
	
	gensec_set_credentials(gensec_ctx, server_credentials);

	if (target_service) {
		gensec_set_target_service(gensec_ctx, target_service);
	}
	*gensec_context = talloc_steal(mem_ctx, gensec_ctx);
	talloc_free(tmp_ctx);
	return nt_status;
}
Esempio n. 3
0
/*
  handler for NT1 style session setup
*/
static void sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess)
{
	NTSTATUS status;
	struct auth_usersupplied_info *user_info = NULL;
	struct tsocket_address *remote_address;
	const char *remote_machine = NULL;
	struct tevent_req *subreq;
	struct sesssetup_context *state;

	sess->nt1.out.vuid = 0;
	sess->nt1.out.action = 0;

	sesssetup_common_strings(req, 
				 &sess->nt1.out.os,
				 &sess->nt1.out.lanman,
				 &sess->nt1.out.domain);

	if (!req->smb_conn->negotiate.done_sesssetup) {
		req->smb_conn->negotiate.max_send = sess->nt1.in.bufsize;
		req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
	}

	state = talloc(req, struct sesssetup_context);
	if (!state) goto nomem;

	state->req = req;

	if (req->smb_conn->negotiate.oid) {
		if (sess->nt1.in.user && *sess->nt1.in.user) {
			/* We can't accept a normal login, because we
			 * don't have a challenge */
			status = NT_STATUS_LOGON_FAILURE;
			goto failed;
		}

		/* TODO: should we use just "anonymous" here? */
		status = auth_context_create(state,
					     req->smb_conn->connection->event.ctx,
					     req->smb_conn->connection->msg_ctx,
					     req->smb_conn->lp_ctx,
					     &state->auth_context);
		if (!NT_STATUS_IS_OK(status)) goto failed;
	} else if (req->smb_conn->negotiate.auth_context) {
		state->auth_context = req->smb_conn->negotiate.auth_context;
	} else {
		/* TODO: should we use just "anonymous" here? */
		status = auth_context_create(state,
					     req->smb_conn->connection->event.ctx,
					     req->smb_conn->connection->msg_ctx,
					     req->smb_conn->lp_ctx,
					     &state->auth_context);
		if (!NT_STATUS_IS_OK(status)) goto failed;
	}

	if (req->smb_conn->negotiate.calling_name) {
		remote_machine = req->smb_conn->negotiate.calling_name->name;
	}

	remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
	if (!remote_address) goto nomem;

	if (!remote_machine) {
		remote_machine = tsocket_address_inet_addr_string(remote_address, req);
		if (!remote_machine) goto nomem;
	}

	user_info = talloc_zero(req, struct auth_usersupplied_info);
	if (!user_info) goto nomem;

	user_info->mapped_state = false;
	user_info->logon_parameters = 0;
	user_info->flags = 0;
	user_info->client.account_name = sess->nt1.in.user;
	user_info->client.domain_name = sess->nt1.in.domain;
	user_info->workstation_name = remote_machine;
	user_info->remote_host = talloc_steal(user_info, remote_address);
	
	user_info->password_state = AUTH_PASSWORD_RESPONSE;
	user_info->password.response.lanman = sess->nt1.in.password1;
	user_info->password.response.lanman.data = talloc_steal(user_info, sess->nt1.in.password1.data);
	user_info->password.response.nt = sess->nt1.in.password2;
	user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data);

	subreq = auth_check_password_send(state,
					  req->smb_conn->connection->event.ctx,
					  state->auth_context,
					  user_info);
	if (!subreq) goto nomem;
	tevent_req_set_callback(subreq, sesssetup_nt1_send, state);

	return;

nomem:
	status = NT_STATUS_NO_MEMORY;
failed:
	status = nt_status_squash(status);
	smbsrv_sesssetup_backend_send(req, sess, status);
}
Esempio n. 4
0
/*
  handler for old style session setup
*/
static void sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *sess)
{
	struct auth_usersupplied_info *user_info = NULL;
	struct tsocket_address *remote_address;
	const char *remote_machine = NULL;
	struct tevent_req *subreq;
	struct sesssetup_context *state;

	sess->old.out.vuid = 0;
	sess->old.out.action = 0;

	sesssetup_common_strings(req, 
				 &sess->old.out.os,
				 &sess->old.out.lanman,
				 &sess->old.out.domain);

	if (!req->smb_conn->negotiate.done_sesssetup) {
		req->smb_conn->negotiate.max_send = sess->old.in.bufsize;
	}

	if (req->smb_conn->negotiate.calling_name) {
		remote_machine = req->smb_conn->negotiate.calling_name->name;
	}
	
	remote_address = socket_get_remote_addr(req->smb_conn->connection->socket, req);
	if (!remote_address) goto nomem;

	if (!remote_machine) {
		remote_machine = tsocket_address_inet_addr_string(remote_address, req);
		if (!remote_machine) goto nomem;
	}

	user_info = talloc_zero(req, struct auth_usersupplied_info);
	if (!user_info) goto nomem;
	
	user_info->mapped_state = false;
	user_info->logon_parameters = 0;
	user_info->flags = 0;
	user_info->client.account_name = sess->old.in.user;
	user_info->client.domain_name = sess->old.in.domain;
	user_info->workstation_name = remote_machine;
	user_info->remote_host = talloc_steal(user_info, remote_address);
	
	user_info->password_state = AUTH_PASSWORD_RESPONSE;
	user_info->password.response.lanman = sess->old.in.password;
	user_info->password.response.lanman.data = talloc_steal(user_info, sess->old.in.password.data);
	user_info->password.response.nt = data_blob(NULL, 0);

	state = talloc(req, struct sesssetup_context);
	if (!state) goto nomem;

	if (req->smb_conn->negotiate.auth_context) {
		state->auth_context = req->smb_conn->negotiate.auth_context;
	} else {
		/* TODO: should we use just "anonymous" here? */
		NTSTATUS status = auth_context_create(state,
						      req->smb_conn->connection->event.ctx,
						      req->smb_conn->connection->msg_ctx,
						      req->smb_conn->lp_ctx,
						      &state->auth_context);
		if (!NT_STATUS_IS_OK(status)) {
			smbsrv_sesssetup_backend_send(req, sess, status);
			return;
		}
	}

	state->req = req;

	subreq = auth_check_password_send(state,
					  req->smb_conn->connection->event.ctx,
					  req->smb_conn->negotiate.auth_context,
					  user_info);
	if (!subreq) goto nomem;
	tevent_req_set_callback(subreq, sesssetup_old_send, state);
	return;

nomem:
	smbsrv_sesssetup_backend_send(req, sess, NT_STATUS_NO_MEMORY);
}
Esempio n. 5
0
static NTSTATUS check_samba4_security(const struct auth_context *auth_context,
				      void *my_private_data,
				      TALLOC_CTX *mem_ctx,
				      const struct auth_usersupplied_info *user_info,
				      struct auth_serversupplied_info **server_info)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct netr_SamInfo3 *info3 = NULL;
	NTSTATUS nt_status;
	struct auth_user_info_dc *user_info_dc;
	struct auth4_context *auth4_context;
	struct loadparm_context *lp_ctx;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_context());
	if (lp_ctx == NULL) {
		DEBUG(10, ("loadparm_init_s3 failed\n"));
		talloc_free(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	/* We create a private tevent context here to avoid nested loops in
	 * the s3 one, as that may not be expected */
	nt_status = auth_context_create(mem_ctx,
					s4_event_context_init(frame), NULL, 
					lp_ctx,
					&auth4_context);
	NT_STATUS_NOT_OK_RETURN(nt_status);
		
	nt_status = auth_context_set_challenge(auth4_context, auth_context->challenge.data, "auth_samba4");
	NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, auth4_context);

	nt_status = auth_check_password(auth4_context, auth4_context, user_info, &user_info_dc);
	NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, auth4_context);
	
	nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
						       user_info_dc,
						       &info3);
	if (NT_STATUS_IS_OK(nt_status)) {
		/* We need the strings from the server_info to be valid as long as the info3 is around */
		talloc_steal(info3, user_info_dc);
	}
	talloc_free(auth4_context);

	if (!NT_STATUS_IS_OK(nt_status)) {
		goto done;
	}

	nt_status = make_server_info_info3(mem_ctx, user_info->client.account_name,
					   user_info->mapped.domain_name, server_info,
					info3);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(10, ("make_server_info_info3 failed: %s\n",
			   nt_errstr(nt_status)));
		TALLOC_FREE(frame);
		return nt_status;
	}

	nt_status = NT_STATUS_OK;

 done:
	TALLOC_FREE(frame);
	return nt_status;
}
Esempio n. 6
0
/*
 It's allowed to pass NULL as session_info,
 when the caller doesn't need a session_info
*/
_PUBLIC_ NTSTATUS authenticate_username_pw(TALLOC_CTX *mem_ctx,
					   struct tevent_context *ev,
					   struct imessaging_context *msg,
					   struct loadparm_context *lp_ctx,
					   const char *nt4_domain,
					   const char *nt4_username,
					   const char *password,
					   const uint32_t logon_parameters,
					   struct auth_session_info **session_info) 
{
	struct auth4_context *auth_context;
	struct auth_usersupplied_info *user_info;
	struct auth_user_info_dc *user_info_dc;
	NTSTATUS nt_status;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);

	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = auth_context_create(tmp_ctx, 
					ev, msg,
					lp_ctx,
					&auth_context);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	user_info = talloc_zero(tmp_ctx, struct auth_usersupplied_info);
	if (!user_info) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	user_info->mapped_state = true;
	user_info->client.account_name = nt4_username;
	user_info->mapped.account_name = nt4_username;
	user_info->client.domain_name = nt4_domain;
	user_info->mapped.domain_name = nt4_domain;

	user_info->workstation_name = NULL;

	user_info->remote_host = NULL;

	user_info->password_state = AUTH_PASSWORD_PLAIN;
	user_info->password.plaintext = talloc_strdup(user_info, password);

	user_info->flags = USER_INFO_CASE_INSENSITIVE_USERNAME |
		USER_INFO_DONT_CHECK_UNIX_ACCOUNT;

	user_info->logon_parameters = logon_parameters |
		MSV1_0_CLEARTEXT_PASSWORD_ALLOWED |
		MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED;

	nt_status = auth_check_password(auth_context, tmp_ctx, user_info, &user_info_dc);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	if (session_info) {
		uint32_t flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
		if (user_info_dc->info->authenticated) {
			flags |= AUTH_SESSION_INFO_AUTHENTICATED;
		}
		nt_status = auth_context->generate_session_info(auth_context,
								tmp_ctx, 
								user_info_dc,
								nt4_username,
								flags,
								session_info);

		if (NT_STATUS_IS_OK(nt_status)) {
			talloc_steal(mem_ctx, *session_info);
		}
	}

	talloc_free(tmp_ctx);
	return nt_status;
}
Esempio n. 7
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(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;
}
Esempio n. 8
0
_PUBLIC_ NTSTATUS authenticate_username_pw(TALLOC_CTX *mem_ctx,
					   struct event_context *ev,
					   struct messaging_context *msg,
					   const char *nt4_domain,
					   const char *nt4_username,
					   const char *password,
					   struct auth_session_info **session_info) 
{
	struct auth_context *auth_context;
	struct auth_usersupplied_info *user_info;
	struct auth_serversupplied_info *server_info;
	NTSTATUS nt_status;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);

	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = auth_context_create(tmp_ctx, lp_auth_methods(),
					ev, msg,
					&auth_context);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	user_info = talloc(tmp_ctx, struct auth_usersupplied_info);
	if (!user_info) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	user_info->mapped_state = True;
	user_info->client.account_name = nt4_username;
	user_info->mapped.account_name = nt4_username;
	user_info->client.domain_name = nt4_domain;
	user_info->mapped.domain_name = nt4_domain;

	user_info->workstation_name = NULL;

	user_info->remote_host = NULL;

	user_info->password_state = AUTH_PASSWORD_PLAIN;
	user_info->password.plaintext = talloc_strdup(user_info, password);

	user_info->flags = USER_INFO_CASE_INSENSITIVE_USERNAME |
		USER_INFO_DONT_CHECK_UNIX_ACCOUNT;

	user_info->logon_parameters = 0;

	nt_status = auth_check_password(auth_context, tmp_ctx, user_info, &server_info);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = auth_generate_session_info(tmp_ctx, server_info, session_info);

	if (NT_STATUS_IS_OK(nt_status)) {
		talloc_steal(mem_ctx, *session_info);
	}

	return nt_status;
}