commit 3f465754610b7fca465bfdd904f592677c688368 Author: Jeremy Allison Date: Thu Mar 20 12:39:10 2014 -0700 s3: smbd: Ensure we always go via getgroups_unix_user() when creating an NT token. This has to be done in every code path that creates an NT token, as remote users may have been added to the local /etc/group database. Tokens created merely from the info3 structs (via the DC or via the krb5 PAC) won't have these local groups. Note, guest access has to be treated differently as sid[0] is set to DOMAIN\Guest in this case, so we go via the user name. https://bugzilla.samba.org/show_bug.cgi?id=10508 Signed-off-by: Jeremy Allison Reviewed-by: Simo Sorce (cherry picked from commit 6034ab521c47fc5f4732398652c9c6847ff92035) diff --git a/source3/auth/token_util.c b/source3/auth/token_util.c index 841bc52..4b901bdc 100644 --- a/source3/auth/token_util.c +++ b/source3/auth/token_util.c @@ -389,6 +389,100 @@ struct security_token *create_local_nt_token(TALLOC_CTX *mem_ctx, return result; } +/*************************************************** + Merge in any groups from /etc/group. +***************************************************/ + +static NTSTATUS add_local_groups(struct security_token *result, + bool is_guest) +{ + gid_t *gids = NULL; + uint32_t getgroups_num_group_sids = 0; + struct passwd *pass = NULL; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + int i; + + if (is_guest) { + /* + * Guest is a special case. It's always + * a user that can be looked up, but + * result->sids[0] is set to DOMAIN\Guest. + * Lookup by account name instead. + */ + pass = Get_Pwnam_alloc(tmp_ctx, lp_guest_account()); + } else { + uid_t uid; + + /* For non-guest result->sids[0] is always the user sid. */ + if (!sid_to_uid(&result->sids[0], &uid)) { + /* + * Non-mappable SID like SYSTEM. + * Can't be in any /etc/group groups. + */ + TALLOC_FREE(tmp_ctx); + return NT_STATUS_OK; + } + + pass = getpwuid_alloc(tmp_ctx, uid); + if (pass == NULL) { + DEBUG(1, ("getpwuid(%u) failed\n", + (unsigned int)uid)); + } + } + + if (!pass) { + TALLOC_FREE(tmp_ctx); + return NT_STATUS_UNSUCCESSFUL; + } + + /* + * Now we must get any groups this user has been + * added to in /etc/group and merge them in. + * This has to be done in every code path + * that creates an NT token, as remote users + * may have been added to the local /etc/group + * database. Tokens created merely from the + * info3 structs (via the DC or via the krb5 PAC) + * won't have these local groups. Note the + * groups added here will only be UNIX groups + * (S-1-22-2-XXXX groups) as getgroups_unix_user() + * turns off winbindd before calling getgroups(). + * + * NB. This is duplicating work already + * done in the 'unix_user:' case of + * create_token_from_sid() but won't + * do anything other than be inefficient + * in that case. + */ + + if (!getgroups_unix_user(tmp_ctx, pass->pw_name, pass->pw_gid, + &gids, &getgroups_num_group_sids)) { + DEBUG(1, ("getgroups_unix_user for user %s failed\n", + pass->pw_name)); + TALLOC_FREE(tmp_ctx); + return NT_STATUS_UNSUCCESSFUL; + } + + for (i=0; isids, + &result->num_sids); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("Failed to add UNIX SID to nt token\n")); + TALLOC_FREE(tmp_ctx); + return status; + } + } + TALLOC_FREE(tmp_ctx); + return NT_STATUS_OK; +} + + static NTSTATUS finalize_local_nt_token(struct security_token *result, bool is_guest) { @@ -396,6 +490,13 @@ static NTSTATUS finalize_local_nt_token(struct security_token *result, gid_t gid; NTSTATUS status; + /* Add any local groups. */ + + status = add_local_groups(result, is_guest); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* Add in BUILTIN sids */ status = add_sid_to_array(result, &global_sid_World,