auth: Provide a way to use the auth stack for winbindd authentication
authorAndrew Bartlett <abartlet@samba.org>
Wed, 26 Mar 2014 23:58:05 +0000 (12:58 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 11 Jun 2014 08:18:26 +0000 (10:18 +0200)
This adds in flags that allow winbindd to request authentication
without directly calling into the auth_sam module.

That in turn will allow winbindd to call auth_samba4 and so permit
winbindd operation in the AD DC.

Andrew Bartlett

Change-Id: I27d11075eb8e1a54f034ee2fdcb05360b4203567
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
auth/common_auth.h
source3/auth/auth.c
source3/auth/auth_sam.c
source3/auth/auth_samba4.c
source3/include/auth.h
source3/winbindd/winbindd_pam.c
source4/auth/auth.h
source4/auth/ntlm/auth.c
source4/auth/ntlm/auth_sam.c

index a40f7c2b3d7010517f5a5e91c789f92846917e03..d9bde018bf383b2ea35074cd7515ecfae623cba8 100644 (file)
@@ -25,7 +25,9 @@
 #define USER_INFO_CASE_INSENSITIVE_USERNAME 0x01 /* username may be in any case */
 #define USER_INFO_CASE_INSENSITIVE_PASSWORD 0x02 /* password may be in any case */
 #define USER_INFO_DONT_CHECK_UNIX_ACCOUNT   0x04 /* don't check unix account status */
-#define USER_INFO_INTERACTIVE_LOGON         0x08 /* don't check unix account status */
+#define USER_INFO_INTERACTIVE_LOGON         0x08 /* Interactive logon */
+#define USER_INFO_LOCAL_SAM_ONLY            0x10 /* Only authenticate against the local SAM */
+#define USER_INFO_INFO3_AND_NO_AUTHZ        0x20 /* Only fill in server_info->info3 and do not do any authorization steps */
 
 enum auth_password_state {
        AUTH_PASSWORD_PLAIN = 1,
@@ -77,6 +79,8 @@ struct loadparm_context;
 struct ldb_context;
 struct smb_krb5_context;
 
+#define AUTH_METHOD_LOCAL_SAM 0x01
+
 struct auth4_context {
        struct {
                /* Who set this up in the first place? */
index 7718142fc11a6b101ef06a263270fa5a4faea1ef..6d1192ededddb1131e43a50a2b2b571e4e3919a6 100644 (file)
@@ -210,6 +210,11 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
                TALLOC_CTX *tmp_ctx;
                NTSTATUS result;
 
+               if (user_info->flags & USER_INFO_LOCAL_SAM_ONLY
+                   && !(auth_method->flags & AUTH_METHOD_LOCAL_SAM)) {
+                       continue;
+               }
+
                tmp_ctx = talloc_named(mem_ctx,
                                       0,
                                       "%s authentication for user %s\\%s",
@@ -253,7 +258,10 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
 
        if (NT_STATUS_IS_OK(nt_status)) {
                unix_username = (*pserver_info)->unix_name;
-               if (!(*pserver_info)->guest) {
+
+               /* We skip doing this step if the caller asked us not to */
+               if (!(user_info->flags & USER_INFO_INFO3_AND_NO_AUTHZ)
+                   && !(*pserver_info)->guest) {
                        const char *rhost;
 
                        if (tsocket_address_is_inet(user_info->remote_host, "ip")) {
index a34f9a585217e0288b199ab320b152d7589a37fd..c4100d5a4e1756c67fe7e357b4e88deae5454db2 100644 (file)
@@ -121,7 +121,7 @@ static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *par
        }
        result->auth = auth_samstrict_auth;
        result->name = "sam";
-
+       result->flags = AUTH_METHOD_LOCAL_SAM;
         *auth_method = result;
        return NT_STATUS_OK;
 }
index d9d71512a2baa493fb191244d6afa28a2d3537a7..284a91f30b11c97a7df63dd0353ebdb151f308e1 100644 (file)
@@ -145,14 +145,23 @@ static NTSTATUS check_samba4_security(const struct auth_context *auth_context,
                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;
+       if (user_info->flags & USER_INFO_INFO3_AND_NO_AUTHZ) {
+               *server_info = make_server_info(mem_ctx);
+               if (*server_info == NULL) {
+                       nt_status = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+               (*server_info)->info3 = talloc_steal(*server_info, info3);
+
+       } else {
+               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)));
+                       goto done;
+               }
        }
 
        nt_status = NT_STATUS_OK;
@@ -356,6 +365,7 @@ static NTSTATUS auth_init_samba4(struct auth_context *auth_context,
        result->auth = check_samba4_security;
        result->prepare_gensec = prepare_gensec;
        result->make_auth4_context = make_auth4_context_s4;
+       result->flags = AUTH_METHOD_LOCAL_SAM;
 
        if (param && *param) {
                auth_context->forced_samba4_methods = talloc_strdup(result, param);
index acae5a83c6cdbfb6770a1c59cf2ad327d02dd976..d35936b243ca6a2a25723d7bdc6021be9279aec1 100644 (file)
@@ -107,6 +107,8 @@ typedef struct auth_methods
        /* Used to keep tabs on things like the cli for SMB server authentication */
        void *private_data;
 
+       uint32_t flags;
+
 } auth_methods;
 
 typedef NTSTATUS (*auth_init_function)(struct auth_context *, const char *, struct auth_methods **);
@@ -130,7 +132,8 @@ enum session_key_use_intent {
 
 /* Changed from 1 -> 2 to add the logon_parameters field. */
 /* Changed from 2 -> 3 when we reworked many auth structures to use IDL or be in common with Samba4 */
-#define AUTH_INTERFACE_VERSION 3
+/* Changed from 3 -> 4 when we reworked added the flags */
+#define AUTH_INTERFACE_VERSION 4
 
 #include "auth/proto.h"
 
index 65f27dfcadb6d66b27878577181078798e13108c..c432afac1a21464a7822041fddb3a86ae67b6795 100644 (file)
@@ -1212,13 +1212,16 @@ static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
                                          const DATA_BLOB *nt_resp,
                                          struct netr_SamInfo3 **pinfo3)
 {
+       struct auth_context *auth_context;
+       struct auth_serversupplied_info *server_info;
        struct auth_usersupplied_info *user_info = NULL;
        struct tsocket_address *local;
+       struct netr_SamInfo3 *info3;
        NTSTATUS status;
        int rc;
        TALLOC_CTX *frame = talloc_stackframe();
 
-       rc = tsocket_address_inet_from_strings(mem_ctx,
+       rc = tsocket_address_inet_from_strings(frame,
                                               "ip",
                                               "127.0.0.1",
                                               0,
@@ -1235,13 +1238,49 @@ static NTSTATUS winbindd_dual_auth_passdb(TALLOC_CTX *mem_ctx,
                TALLOC_FREE(frame);
                return status;
        }
+
        user_info->logon_parameters = logon_parameters;
 
        /* We don't want any more mapping of the username */
        user_info->mapped_state = True;
 
-       status = check_sam_security_info3(challenge, mem_ctx, user_info,
-                                         pinfo3);
+       /* We don't want to come back to winbindd or to do PAM account checks */
+       user_info->flags |= USER_INFO_LOCAL_SAM_ONLY | USER_INFO_INFO3_AND_NO_AUTHZ;
+
+       status = make_auth_context_fixed(frame, &auth_context, challenge->data);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Failed to test authentication with check_sam_security_info3: %s\n", nt_errstr(status)));
+               TALLOC_FREE(frame);
+               return status;
+       }
+
+       status = auth_check_ntlm_password(mem_ctx,
+                                         auth_context,
+                                         user_info,
+                                         &server_info);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               return status;
+       }
+
+       info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
+       if (info3 == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = serverinfo_to_SamInfo3(server_info, info3);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(frame);
+               TALLOC_FREE(info3);
+               DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
+                         nt_errstr(status)));
+               return status;
+       }
+
+       *pinfo3 = info3;
        DEBUG(10, ("Authenticaticating user %s\\%s returned %s\n", domain,
                   user, nt_errstr(status)));
        TALLOC_FREE(frame);
index 0b6b1d358313f3ac054ed313bcb38f02057728fa..c472d86d1ede16d88f9c48dd3fb8743a2d5a1ae4 100644 (file)
@@ -72,6 +72,7 @@ struct auth_operations {
                                                       const char *principal,
                                                       struct ldb_dn *user_dn,
                                                       struct auth_user_info_dc **interim_info);
+       uint32_t flags;
 };
 
 struct auth_method_context {
index 642d8684e5941ef50b392113edc1ed45e1ddf1ba..6d5747eb783318f1a9b53cbd3c6829d7493d0279 100644 (file)
@@ -342,6 +342,11 @@ static void auth_check_password_async_trigger(struct tevent_context *ev,
 
        for (method=state->auth_ctx->methods; method; method = method->next) {
 
+               if (state->user_info->flags & USER_INFO_LOCAL_SAM_ONLY
+                   && !(method->ops->flags & AUTH_METHOD_LOCAL_SAM)) {
+                       continue;
+               }
+
                /* we fill in state->method here so debug messages in
                   the callers know which method failed */
                state->method = method;
index 6b184f8d32e45aeeaaca84b7d0ac7ff629992c00..6e2dd440f7b73356c16da13e58d14dd07a240a38 100644 (file)
@@ -677,14 +677,16 @@ static const struct auth_operations sam_ignoredomain_ops = {
        .name                      = "sam_ignoredomain",
        .want_check                = authsam_ignoredomain_want_check,
        .check_password            = authsam_check_password_internals,
-       .get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper
+       .get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
+       .flags                     = AUTH_METHOD_LOCAL_SAM
 };
 
 static const struct auth_operations sam_ops = {
        .name                      = "sam",
        .want_check                = authsam_want_check,
        .check_password            = authsam_check_password_internals,
-       .get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper
+       .get_user_info_dc_principal = authsam_get_user_info_dc_principal_wrapper,
+       .flags                     = AUTH_METHOD_LOCAL_SAM
 };
 
 _PUBLIC_ NTSTATUS auth4_sam_init(void);