From 8a9b6fe26dc347afd6dc17570354e0af391b351d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Feb 2012 16:14:42 +1100 Subject: s3-auth: Add a way to get an auth4_context from the auth stack This will allow us to use the same layer that auth_ntlmssp does in the non-SPNEGO session setup, which will in turn make the authentication code more consistent in the AD server case. Andrew Bartlett --- source3/auth/auth.c | 6 +++-- source3/auth/auth_generic.c | 58 ++++++++++++++++++++++++++++++++++++++------- source3/auth/auth_samba4.c | 54 +++++++++++++++++++++++++++++++++++++++++ source3/auth/proto.h | 1 + source3/include/auth.h | 7 +++++- 5 files changed, 114 insertions(+), 12 deletions(-) (limited to 'source3') diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 1e1ede45a4..1c813a429a 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -460,10 +460,12 @@ static NTSTATUS make_auth_context_text_list(TALLOC_CTX *mem_ctx, (*auth_context)->auth_method_list = list; - /* Look for the first module to provide a start_gensec hook, and set that if provided */ + /* Look for the first module to provide a prepare_gensec and + * make_auth4_context hook, and set that if provided */ for (method = (*auth_context)->auth_method_list; method; method = method->next) { - if (method->prepare_gensec) { + if (method->prepare_gensec && method->make_auth4_context) { (*auth_context)->prepare_gensec = method->prepare_gensec; + (*auth_context)->make_auth4_context = method->make_auth4_context; break; } } diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 65b83f035f..681989e16b 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -154,6 +154,54 @@ done: return status; } +static struct auth4_context *make_auth4_context_s3(TALLOC_CTX *mem_ctx, struct auth_context *auth_context) +{ + struct auth4_context *auth4_context = talloc_zero(mem_ctx, struct auth4_context); + if (auth4_context == NULL) { + DEBUG(10, ("failed to allocate auth4_context failed\n")); + return NULL; + } + auth4_context->generate_session_info_pac = auth3_generate_session_info_pac; + auth4_context->generate_session_info = auth3_generate_session_info; + auth4_context->get_challenge = auth3_get_challenge; + auth4_context->set_challenge = auth3_set_challenge; + auth4_context->challenge_may_be_modified = auth3_may_set_challenge; + auth4_context->check_password = auth3_check_password; + auth4_context->private_data = talloc_steal(auth4_context, auth_context); + return auth4_context; +} + +NTSTATUS make_auth4_context(TALLOC_CTX *mem_ctx, struct auth4_context **auth4_context_out) +{ + struct auth_context *auth_context; + NTSTATUS nt_status; + + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); + + nt_status = make_auth_context_subsystem(tmp_ctx, &auth_context); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(tmp_ctx); + return nt_status; + } + + if (auth_context->make_auth4_context) { + nt_status = auth_context->make_auth4_context(mem_ctx, auth4_context_out); + TALLOC_FREE(tmp_ctx); + return nt_status; + + } else { + struct auth4_context *auth4_context = make_auth4_context_s3(tmp_ctx, auth_context); + if (auth4_context == NULL) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_NO_MEMORY; + } + *auth4_context_out = talloc_steal(mem_ctx, auth4_context); + TALLOC_FREE(tmp_ctx); + return NT_STATUS_OK; + } +} + NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, const struct tsocket_address *remote_address, struct gensec_security **gensec_security_out) @@ -185,19 +233,11 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, struct cli_credentials *server_credentials; const char *dns_name; const char *dns_domain; - struct auth4_context *auth4_context = talloc_zero(tmp_ctx, struct auth4_context); + struct auth4_context *auth4_context = make_auth4_context_s3(tmp_ctx, auth_context); if (auth4_context == NULL) { - DEBUG(10, ("failed to allocate auth4_context failed\n")); TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } - auth4_context->generate_session_info_pac = auth3_generate_session_info_pac; - auth4_context->generate_session_info = auth3_generate_session_info; - auth4_context->get_challenge = auth3_get_challenge; - auth4_context->set_challenge = auth3_set_challenge; - auth4_context->challenge_may_be_modified = auth3_may_set_challenge; - auth4_context->check_password = auth3_check_password; - auth4_context->private_data = talloc_steal(auth4_context, auth_context); lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_context()); if (lp_ctx == NULL) { diff --git a/source3/auth/auth_samba4.c b/source3/auth/auth_samba4.c index 971f9d6898..6692f187be 100644 --- a/source3/auth/auth_samba4.c +++ b/source3/auth/auth_samba4.c @@ -169,6 +169,59 @@ static NTSTATUS prepare_gensec(TALLOC_CTX *mem_ctx, return status; } +/* Hook to allow handling of NTLM authentication for AD operation + * without directly linking the s4 auth stack */ +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; + + 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; + } + + 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; +} + /* module initialisation */ static NTSTATUS auth_init_samba4(struct auth_context *auth_context, const char *param, @@ -185,6 +238,7 @@ static NTSTATUS auth_init_samba4(struct auth_context *auth_context, result->name = "samba4"; result->auth = check_samba4_security; result->prepare_gensec = prepare_gensec; + result->make_auth4_context = make_auth4_context_s4; *auth_method = result; return NT_STATUS_OK; diff --git a/source3/auth/proto.h b/source3/auth/proto.h index 1697eda5be..2d123b0264 100644 --- a/source3/auth/proto.h +++ b/source3/auth/proto.h @@ -69,6 +69,7 @@ NTSTATUS auth_netlogond_init(void); /* The following definitions come from auth/auth_generic.c */ +NTSTATUS make_auth4_context(TALLOC_CTX *mem_ctx, struct auth4_context **auth4_context_out); NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx, const struct tsocket_address *remote_address, struct gensec_security **gensec_security_out); diff --git a/source3/include/auth.h b/source3/include/auth.h index 5fae94ca84..894b7dff81 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -69,6 +69,9 @@ struct auth_serversupplied_info { typedef NTSTATUS (*prepare_gensec_fn)(TALLOC_CTX *mem_ctx, struct gensec_security **gensec_context); +typedef NTSTATUS (*make_auth4_context_fn)(TALLOC_CTX *mem_ctx, + struct auth4_context **auth4_context); + struct auth_context { DATA_BLOB challenge; @@ -88,6 +91,7 @@ struct auth_context { struct auth_serversupplied_info **server_info); prepare_gensec_fn prepare_gensec; + make_auth4_context_fn make_auth4_context; }; typedef struct auth_methods @@ -109,8 +113,9 @@ typedef struct auth_methods void **my_private_data, TALLOC_CTX *mem_ctx); - /* Optional methods allowing this module to provide a way to get a gensec context */ + /* Optional methods allowing this module to provide a way to get a gensec context and an auth4_context */ prepare_gensec_fn prepare_gensec; + make_auth4_context_fn make_auth4_context; /* Used to keep tabs on things like the cli for SMB server authentication */ void *private_data; -- cgit