diff options
author | Jeremy Allison <jra@samba.org> | 2014-03-25 08:47:39 -0700 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2014-04-04 21:02:16 +0200 |
commit | b649fdb8d63a5b14bb9dc567de1ddd640ae165f3 (patch) | |
tree | b43d511e1be9684e920c0984e86e18142eb6cd37 | |
parent | fc185a5f4cb34f4a2488eb336844c32812f930e7 (diff) | |
download | samba-b649fdb8d63a5b14bb9dc567de1ddd640ae165f3.tar.gz |
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.
This code needs to special-case the guest user, as
this token can have the token_sid[0] set to the Guest
SID, not the mapping of UNIX uid -> SID.
Other users that may have a well-known SID
set in token_sid[0] (like SYSTEM) are usually
not mappable to UNIX users and can be ignored
when adding local groups from /etc/group.
Combined back-port of fixes
6034ab521c47fc5f4732398652c9c6847ff92035 and
a9fa09723bee3588db2168ac13f7ad0334452c11 from
master.
https://bugzilla.samba.org/show_bug.cgi?id=10508
Signed-off-by: Jeremy Allison <jra@samba.org>
-rw-r--r-- | source3/auth/token_util.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/source3/auth/token_util.c b/source3/auth/token_util.c index 841bc52792f..09959f41e22 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_guestaccount()); + } 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, ("SID %s -> getpwuid(%u) failed\n", + sid_string_dbg(&result->sids[0]), + (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; i<getgroups_num_group_sids; i++) { + NTSTATUS status; + struct dom_sid grp_sid; + gid_to_sid(&grp_sid, gids[i]); + + status = add_sid_to_array_unique(result, + &grp_sid, + &result->sids, + &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, |