s3-auth: Add passwd_to_SamInfo3().
authorAndreas Schneider <asn@samba.org>
Fri, 13 Dec 2013 18:19:02 +0000 (19:19 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 5 Feb 2014 00:40:37 +0000 (01:40 +0100)
Correctly lookup users which come from smb.conf. passwd_to_SamInfo3()
tries to contact winbind if the user is a domain user to get
valid information about it. If winbind isn't running it will try to
create everything from the passwd struct. This is not always reliable
but works in most cases. It improves the current situation which doesn't
talk to winbind at all.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=8598

Pair-Programmed-With: Guenther Deschner <gd@samba.org>
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Wed Feb  5 01:40:38 CET 2014 on sn-devel-104

source3/auth/auth_util.c
source3/auth/server_info.c

index b225b0d5eb23c07097abbf352497a40a23f5b56a..24190afb491d661b0e8ef8b84aabadf919d27dcb 100644 (file)
@@ -645,98 +645,43 @@ NTSTATUS make_server_info_pw(TALLOC_CTX *mem_ctx,
                             struct auth_serversupplied_info **server_info)
 {
        NTSTATUS status;
-       struct samu *sampass = NULL;
-       char *qualified_name = NULL;
-       TALLOC_CTX *tmp_ctx;
-       struct dom_sid u_sid;
-       enum lsa_SidType type;
+       TALLOC_CTX *tmp_ctx = NULL;
        struct auth_serversupplied_info *result;
 
-       /*
-        * The SID returned in server_info->sam_account is based
-        * on our SAM sid even though for a pure UNIX account this should
-        * not be the case as it doesn't really exist in the SAM db.
-        * This causes lookups on "[in]valid users" to fail as they
-        * will lookup this name as a "Unix User" SID to check against
-        * the user token. Fix this by adding the "Unix User"\unix_username
-        * SID to the sid array. The correct fix should probably be
-        * changing the server_info->sam_account user SID to be a
-        * S-1-22 Unix SID, but this might break old configs where
-        * plaintext passwords were used with no SAM backend.
-        */
-
        tmp_ctx = talloc_stackframe();
        if (tmp_ctx == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       qualified_name = talloc_asprintf(tmp_ctx, "%s\\%s",
-                                       unix_users_domain_name(),
-                                       unix_username );
-       if (!qualified_name) {
-               TALLOC_FREE(tmp_ctx);
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (!lookup_name(tmp_ctx, qualified_name, LOOKUP_NAME_ALL,
-                                               NULL, NULL,
-                                               &u_sid, &type)) {
-               TALLOC_FREE(tmp_ctx);
-               return NT_STATUS_NO_SUCH_USER;
-       }
-
-       TALLOC_FREE(tmp_ctx);
-
-       if (type != SID_NAME_USER) {
-               return NT_STATUS_NO_SUCH_USER;
-       }
-
-       if ( !(sampass = samu_new( NULL )) ) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       status = samu_set_unix( sampass, pwd );
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       /* In pathological cases the above call can set the account
-        * name to the DOMAIN\username form. Reset the account name
-        * using unix_username */
-       pdb_set_username(sampass, unix_username, PDB_SET);
-
-       /* set the user sid to be the calculated u_sid */
-       pdb_set_user_sid(sampass, &u_sid, PDB_SET);
-
-       result = make_server_info(mem_ctx);
+       result = make_server_info(tmp_ctx);
        if (result == NULL) {
-               TALLOC_FREE(sampass);
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_NO_MEMORY;
+               goto done;
        }
 
-       status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
-                                 &result->info3, &result->extra);
-       TALLOC_FREE(sampass);
+       status = passwd_to_SamInfo3(result,
+                                   unix_username,
+                                   pwd,
+                                   &result->info3);
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("Failed to convert samu to info3: %s\n",
-                          nt_errstr(status)));
-               TALLOC_FREE(result);
-               return status;
+               goto done;
        }
 
        result->unix_name = talloc_strdup(result, unix_username);
-
        if (result->unix_name == NULL) {
-               TALLOC_FREE(result);
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_NO_MEMORY;
+               goto done;
        }
 
        result->utok.uid = pwd->pw_uid;
        result->utok.gid = pwd->pw_gid;
 
-       *server_info = result;
+       *server_info = talloc_steal(mem_ctx, result);
+       status = NT_STATUS_OK;
+done:
+       talloc_free(tmp_ctx);
 
-       return NT_STATUS_OK;
+       return status;
 }
 
 static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
index 46d817880a05b4ee7e219a386294dd185d30738b..43711d5bc0eef9e6f16b92f4a4262dc09ed99663 100644 (file)
@@ -489,10 +489,28 @@ NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx,
                }
        } else {
                /*
-                * Winbind is not running, create the group_sid from the
-                * group id.
+                * Winbind is not running, try to create the group_sid from the
+                * passwd group id.
+                */
+
+               /*
+                * This can lead to a primary group of S-1-22-2-XX which
+                * will be rejected by other Samba code.
                 */
                gid_to_sid(&group_sid, pwd->pw_gid);
+
+               ZERO_STRUCT(domain_sid);
+
+               /*
+                * If we are a unix group, set the group_sid to the
+                * 'Domain Users' RID of 513 which will always resolve to a
+                * name.
+                */
+               if (sid_check_is_in_unix_groups(&group_sid)) {
+                       sid_compose(&group_sid,
+                                   get_global_sam_sid(),
+                                   DOMAIN_RID_USERS);
+               }
        }
 
        /* Make sure we have a valid group sid */