s3-auth: Add a way to get an auth4_context from the auth stack
authorAndrew Bartlett <abartlet@samba.org>
Fri, 3 Feb 2012 05:14:42 +0000 (16:14 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 24 Feb 2012 00:23:18 +0000 (11:23 +1100)
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
source3/auth/auth_generic.c
source3/auth/auth_samba4.c
source3/auth/proto.h
source3/include/auth.h

index 1e1ede4..1c813a4 100644 (file)
@@ -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;
                }
        }
index 65b83f0..681989e 100644 (file)
@@ -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) {
index 971f9d6..6692f18 100644 (file)
@@ -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;
index 1697eda..2d123b0 100644 (file)
@@ -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);
 
index 5fae94c..894b7df 100644 (file)
@@ -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;