1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-08 21:18:16 +03:00

s3: smbd: Factor out code that calls getgroups_unix_user() into a separate function.

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.

Found by <linux@kukkukk.com>.

Second part of the bugfix for:

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

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by:  Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Jeremy Allison 2014-03-22 21:23:48 -07:00
parent 547111b2cf
commit a9fa09723b

View File

@ -389,72 +389,112 @@ 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, ("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)
{
struct dom_sid dom_sid;
gid_t gid;
uid_t uid;
NTSTATUS status;
/* result->sids[0] is always the user sid. */
if (sid_to_uid(&result->sids[0], &uid)) {
/*
* 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.
*/
struct passwd *pass = NULL;
gid_t *gids = NULL;
uint32_t getgroups_num_group_sids = 0;
int i;
TALLOC_CTX *tmp_ctx = talloc_stackframe();
/* Add any local groups. */
pass = getpwuid_alloc(tmp_ctx, uid);
if (pass == NULL) {
DEBUG(1, ("getpwuid(%u) failed\n",
(unsigned int)uid));
TALLOC_FREE(tmp_ctx);
return NT_STATUS_UNSUCCESSFUL;
}
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++) {
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);
status = add_local_groups(result, is_guest);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* Add in BUILTIN sids */