s3:auth create nt token from info3 directly
authorSimo Sorce <ssorce@redhat.com>
Fri, 28 May 2010 20:16:53 +0000 (16:16 -0400)
committerSimo Sorce <ssorce@redhat.com>
Mon, 31 May 2010 15:14:40 +0000 (11:14 -0400)
source3/auth/auth_util.c
source3/auth/token_util.c
source3/include/proto.h

index d3bcf0216d70f53cea45f51138dc2c3a40ca1e23..fb30f9cae2de79d1ee43e492c0d10524132581dd 100644 (file)
@@ -463,7 +463,6 @@ NTSTATUS create_local_token(struct auth_serversupplied_info *server_info)
        NTSTATUS status;
        size_t i;
        struct dom_sid tmp_sid;
-       struct dom_sid user_sid;
 
        /*
         * If winbind is not around, we can not make much use of the SIDs the
@@ -482,17 +481,10 @@ NTSTATUS create_local_token(struct auth_serversupplied_info *server_info)
                                                    &server_info->ptok);
 
        } else {
-               sid_compose(&user_sid,
-                           server_info->info3->base.domain_sid,
-                           server_info->info3->base.rid);
-
-               server_info->ptok = create_local_nt_token(
-                       server_info,
-                       &user_sid,
-                       server_info->guest,
-                       server_info->num_sids, server_info->sids);
-               status = server_info->ptok ?
-                       NT_STATUS_OK : NT_STATUS_NO_SUCH_USER;
+               status = create_local_nt_token_from_info3(server_info,
+                                                         server_info->guest,
+                                                         server_info->info3,
+                                                         &server_info->ptok);
        }
 
        if (!NT_STATUS_IS_OK(status)) {
index d2a03b4031a5045b2a00672718191842e040fda9..4336b2f24a2d2d384298619f57a9d584c129c10a 100644 (file)
@@ -335,6 +335,134 @@ NTSTATUS create_builtin_administrators(const struct dom_sid *dom_sid)
        return status;
 }
 
+static NTSTATUS finalize_local_nt_token(struct nt_user_token *result,
+                                       bool is_guest);
+
+NTSTATUS create_local_nt_token_from_info3(TALLOC_CTX *mem_ctx,
+                                         bool is_guest,
+                                         struct netr_SamInfo3 *info3,
+                                         struct nt_user_token **ntok)
+{
+       struct nt_user_token *usrtok = NULL;
+       NTSTATUS status;
+       int i;
+
+       DEBUG(10, ("Create local NT token for %s\n",
+                  info3->base.account_name.string));
+
+       usrtok = talloc_zero(mem_ctx, struct nt_user_token);
+       if (!usrtok) {
+               DEBUG(0, ("talloc failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* Add the user and primary group sid FIRST */
+       /* check if the user rid is the special "Domain Guests" rid.
+        * If so pick the first sid for the extra sids instead as it
+        * is a local fake account */
+       usrtok->user_sids = talloc_array(usrtok, struct dom_sid, 2);
+       if (!usrtok->user_sids) {
+               TALLOC_FREE(usrtok);
+               return NT_STATUS_NO_MEMORY;
+       }
+       usrtok->num_sids = 2;
+
+       /* USER SID */
+       if (info3->base.rid == (uint32_t)(-1)) {
+               /* this is a signal the user was fake and generated,
+                * the actual SID we want to use is stored in the extra
+                * sids */
+               for (i = 0; i < info3->sidcount; i++) {
+                       if (info3->sids[i].attributes == SE_SAMBA_USER_SID) {
+                               break;
+                       }
+               }
+               if (i >= info3->sidcount) {
+                       /* we couldn't find the user sid, bail out */
+                       DEBUG(3, ("Unable to find user SID "
+                                 "(Extra sids = %d)!\n", info3->sidcount));
+                       TALLOC_FREE(usrtok);
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+               sid_copy(&usrtok->user_sids[0], info3->sids[i].sid);
+       } else {
+               sid_copy(&usrtok->user_sids[0], info3->base.domain_sid);
+               sid_append_rid(&usrtok->user_sids[0], info3->base.rid);
+       }
+
+       /* GROUP SID */
+       if (info3->base.primary_gid == (uint32_t)(-1)) {
+               /* this is a signal the user was fake and generated,
+                * the actual SID we want to use is stored in the extra
+                * sids */
+               for (i = 0; i < info3->sidcount; i++) {
+                       if (info3->sids[i].attributes == SE_SAMBA_PGID_SID) {
+                               break;
+                       }
+               }
+               if (i >= info3->sidcount) {
+                       /* we couldn't find the user sid, bail out */
+                       DEBUG(3, ("Unable to find group SID "
+                                 "(Extra sids = %d)!\n", info3->sidcount));
+                       TALLOC_FREE(usrtok);
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+               sid_copy(&usrtok->user_sids[1], info3->sids[i].sid);
+       } else {
+               sid_copy(&usrtok->user_sids[1], info3->base.domain_sid);
+               sid_append_rid(&usrtok->user_sids[1],
+                               info3->base.primary_gid);
+       }
+
+       /* Now the SIDs we got from authentication. These are the ones from
+        * the info3 struct or from the pdb_enum_group_memberships, depending
+        * on who authenticated the user.
+        * Note that we start the for loop at "1" here, we already added the
+        * first group sid as primary above. */
+
+       for (i = 0; i < info3->base.groups.count; i++) {
+               struct dom_sid tmp_sid;
+
+               sid_copy(&tmp_sid, info3->base.domain_sid);
+               sid_append_rid(&tmp_sid, info3->base.groups.rids[i].rid);
+
+               status = add_sid_to_array_unique(usrtok, &tmp_sid,
+                                                &usrtok->user_sids,
+                                                &usrtok->num_sids);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(3, ("Failed to add SID to nt token\n"));
+                       TALLOC_FREE(usrtok);
+                       return status;
+               }
+       }
+
+       /* now also add extra sids if they are not the special user/group
+        * sids */
+       for (i = 0; i < info3->sidcount; i++) {
+               if (info3->sids[i].attributes & SE_SAMBA_USER_SID) continue;
+               if (info3->sids[i].attributes & SE_SAMBA_PGID_SID) continue;
+
+               status = add_sid_to_array_unique(usrtok,
+                                                info3->sids[i].sid,
+                                                &usrtok->user_sids,
+                                                &usrtok->num_sids);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(3, ("Failed to add SID to nt token\n"));
+                       TALLOC_FREE(usrtok);
+                       return status;
+               }
+       }
+
+       status = finalize_local_nt_token(usrtok, is_guest);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3, ("Failed to finalize nt token\n"));
+               TALLOC_FREE(usrtok);
+               return status;
+       }
+
+       *ntok = usrtok;
+       return NT_STATUS_OK;
+}
 
 /*******************************************************************
  Create a NT token for the user, expanding local aliases
@@ -349,8 +477,6 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
        struct nt_user_token *result = NULL;
        int i;
        NTSTATUS status;
-       gid_t gid;
-       struct dom_sid dom_sid;
 
        DEBUG(10, ("Create local NT token for %s\n",
                   sid_string_dbg(user_sid)));
@@ -365,6 +491,7 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
        status = add_sid_to_array(result, user_sid,
                                  &result->user_sids, &result->num_sids);
        if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(result);
                return NULL;
        }
 
@@ -374,21 +501,54 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
                                          &result->user_sids,
                                          &result->num_sids);
                if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(result);
+                       return NULL;
+               }
+       }
+
+       /* Now the SIDs we got from authentication. These are the ones from
+        * the info3 struct or from the pdb_enum_group_memberships, depending
+        * on who authenticated the user.
+        * Note that we start the for loop at "1" here, we already added the
+        * first group sid as primary above. */
+
+       for (i=1; i<num_groupsids; i++) {
+               status = add_sid_to_array_unique(result, &groupsids[i],
+                                                &result->user_sids,
+                                                &result->num_sids);
+               if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(result);
                        return NULL;
                }
        }
 
+       status = finalize_local_nt_token(result, is_guest);
+       if (!NT_STATUS_IS_OK(status)) {
+               TALLOC_FREE(result);
+               return NULL;
+       }
+
+       return result;
+}
+
+static NTSTATUS finalize_local_nt_token(struct nt_user_token *result,
+                                       bool is_guest)
+{
+       struct dom_sid dom_sid;
+       gid_t gid;
+       NTSTATUS status;
+
        /* Add in BUILTIN sids */
 
        status = add_sid_to_array(result, &global_sid_World,
                                  &result->user_sids, &result->num_sids);
        if (!NT_STATUS_IS_OK(status)) {
-               return NULL;
+               return status;
        }
        status = add_sid_to_array(result, &global_sid_Network,
                                  &result->user_sids, &result->num_sids);
        if (!NT_STATUS_IS_OK(status)) {
-               return NULL;
+               return status;
        }
 
        if (is_guest) {
@@ -396,7 +556,7 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
                                          &result->user_sids,
                                          &result->num_sids);
                if (!NT_STATUS_IS_OK(status)) {
-                       return NULL;
+                       return status;
                }
        } else {
                status = add_sid_to_array(result,
@@ -404,22 +564,7 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
                                          &result->user_sids,
                                          &result->num_sids);
                if (!NT_STATUS_IS_OK(status)) {
-                       return NULL;
-               }
-       }
-
-       /* Now the SIDs we got from authentication. These are the ones from
-        * the info3 struct or from the pdb_enum_group_memberships, depending
-        * on who authenticated the user.
-        * Note that we start the for loop at "1" here, we already added the
-        * first group sid as primary above. */
-
-       for (i=1; i<num_groupsids; i++) {
-               status = add_sid_to_array_unique(result, &groupsids[i],
-                                                &result->user_sids,
-                                                &result->num_sids);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return NULL;
+                       return status;
                }
        }
 
@@ -490,8 +635,7 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
 
                if (!NT_STATUS_IS_OK(status)) {
                        unbecome_root();
-                       TALLOC_FREE(result);
-                       return NULL;
+                       return status;
                }
 
                /* Finally the builtin ones */
@@ -500,17 +644,18 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
 
                if (!NT_STATUS_IS_OK(status)) {
                        unbecome_root();
-                       TALLOC_FREE(result);
-                       return NULL;
+                       return status;
                }
 
                unbecome_root();
        }
 
+       /* Add privileges based on current user sids */
 
        get_privileges_for_sids(&result->privileges, result->user_sids,
                                result->num_sids);
-       return result;
+
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
index 237772e9bd1096dc361ff69b0c94346fa217fd10..deb836579704750b7980a11a333ebf7e9dc3a87c 100644 (file)
@@ -262,6 +262,10 @@ struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
                                            bool is_guest,
                                            int num_groupsids,
                                            const struct dom_sid *groupsids);
+NTSTATUS create_local_nt_token_from_info3(TALLOC_CTX *mem_ctx,
+                                         bool is_guest,
+                                         struct netr_SamInfo3 *info3,
+                                         struct nt_user_token **ntok);
 void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token);
 void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
                           int n_groups, gid_t *groups);