* security.h (cygsidlist::addfromgr): Allow duplicate entries.
(get_server_groups): Declare new function. * security.cc (is_group_member): Simplify. (get_server_groups): New function. (get_initgroups_sidlist): Call get_server_groups. (verify_token): Allow token when supplementary sids are not in /etc/group but are in the token. Streamline the code. * grp.cc (initgroups32): New implementation. (getgroups32): Handle case where the supplementary groups are set.
This commit is contained in:
parent
00c05edcf1
commit
68a3f0d34a
|
@ -1,3 +1,17 @@
|
||||||
|
2005-04-16 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
Pierre Humblet <pierre.humblet@ieee.org>
|
||||||
|
|
||||||
|
* security.h (cygsidlist::addfromgr): Allow duplicate entries.
|
||||||
|
(get_server_groups): Declare new function.
|
||||||
|
* security.cc (is_group_member): Simplify.
|
||||||
|
(get_server_groups): New function.
|
||||||
|
(get_initgroups_sidlist): Call get_server_groups.
|
||||||
|
(verify_token): Allow token when supplementary sids are not in
|
||||||
|
/etc/group but are in the token.
|
||||||
|
Streamline the code.
|
||||||
|
* grp.cc (initgroups32): New implementation.
|
||||||
|
(getgroups32): Handle case where the supplementary groups are set.
|
||||||
|
|
||||||
2005-04-16 Corinna Vinschen <corinna@vinschen.de>
|
2005-04-16 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* environ.cc (environ_init): Don't set traverse checking as default.
|
* environ.cc (environ_init): Don't set traverse checking as default.
|
||||||
|
|
|
@ -344,14 +344,32 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
|
||||||
__gid32_t gid;
|
__gid32_t gid;
|
||||||
const char *username;
|
const char *username;
|
||||||
|
|
||||||
if (allow_ntsec)
|
if (!srchsid && cygheap->user.groups.issetgroups ())
|
||||||
{
|
{
|
||||||
|
cygsid sid;
|
||||||
|
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
|
||||||
|
if (sid.getfromgr (gr))
|
||||||
|
for (int pg = 0; pg < cygheap->user.groups.sgsids.count; ++pg)
|
||||||
|
if (sid == cygheap->user.groups.sgsids.sids[pg] &&
|
||||||
|
sid != well_known_world_sid)
|
||||||
|
{
|
||||||
|
if (cnt < gidsetsize)
|
||||||
|
grouplist[cnt] = gr->gr_gid;
|
||||||
|
++cnt;
|
||||||
|
if (gidsetsize && cnt > gidsetsize)
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If impersonated, use impersonation token. */
|
/* If impersonated, use impersonation token. */
|
||||||
if (cygheap->user.issetuid ())
|
if (cygheap->user.issetuid ())
|
||||||
hToken = cygheap->user.token ();
|
hToken = cygheap->user.token ();
|
||||||
else
|
else
|
||||||
hToken = hProcImpToken;
|
hToken = hProcImpToken;
|
||||||
}
|
|
||||||
if (hToken)
|
if (hToken)
|
||||||
{
|
{
|
||||||
if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size)
|
if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size)
|
||||||
|
@ -450,9 +468,32 @@ getgroups (int gidsetsize, __gid16_t *grouplist)
|
||||||
extern "C" int
|
extern "C" int
|
||||||
initgroups32 (const char *name, __gid32_t gid)
|
initgroups32 (const char *name, __gid32_t gid)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
if (wincap.has_security ())
|
if (wincap.has_security ())
|
||||||
cygheap->user.groups.clear_supp ();
|
{
|
||||||
syscall_printf ( "0 = initgroups (%s, %u)", name, gid);
|
ret = -1;
|
||||||
|
struct passwd *pw = internal_getpwnam (name);
|
||||||
|
struct __group32 *gr = internal_getgrgid (gid);
|
||||||
|
cygsid usersid, grpsid;
|
||||||
|
if (!usersid.getfrompw (pw) || !grpsid.getfromgr (gr))
|
||||||
|
{
|
||||||
|
set_errno (EINVAL);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
cygsidlist tmp_gsids (cygsidlist_auto, 12);
|
||||||
|
if (!get_server_groups (tmp_gsids, usersid, pw))
|
||||||
|
goto out;
|
||||||
|
tmp_gsids += grpsid;
|
||||||
|
cygsidlist new_gsids (cygsidlist_alloc, tmp_gsids.count);
|
||||||
|
for (int i = 0; i < tmp_gsids.count; i++)
|
||||||
|
new_gsids.sids[i] = tmp_gsids.sids[i];
|
||||||
|
new_gsids.count = tmp_gsids.count;
|
||||||
|
cygheap->user.groups.update_supp (new_gsids);
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
syscall_printf ( "%d = initgroups (%s, %u)", ret, name, gid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,7 @@ details. */
|
||||||
|
|
||||||
bool allow_ntsec;
|
bool allow_ntsec;
|
||||||
/* allow_smbntsec is handled exclusively in path.cc (path_conv::check).
|
/* allow_smbntsec is handled exclusively in path.cc (path_conv::check).
|
||||||
It's defined here because of it's strong relationship to allow_ntsec.
|
It's defined here because of it's strong relationship to allow_ntsec. */
|
||||||
The default is TRUE to reflect the old behaviour. */
|
|
||||||
bool allow_smbntsec;
|
bool allow_smbntsec;
|
||||||
bool allow_traverse;
|
bool allow_traverse;
|
||||||
|
|
||||||
|
@ -363,7 +362,6 @@ is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list)
|
||||||
LPLOCALGROUP_MEMBERS_INFO_0 buf;
|
LPLOCALGROUP_MEMBERS_INFO_0 buf;
|
||||||
DWORD cnt, tot;
|
DWORD cnt, tot;
|
||||||
NET_API_STATUS ret;
|
NET_API_STATUS ret;
|
||||||
bool retval = false;
|
|
||||||
|
|
||||||
/* Members can be users or global groups */
|
/* Members can be users or global groups */
|
||||||
ret = NetLocalGroupGetMembers (NULL, wgroup, 0, (LPBYTE *) &buf,
|
ret = NetLocalGroupGetMembers (NULL, wgroup, 0, (LPBYTE *) &buf,
|
||||||
|
@ -371,14 +369,17 @@ is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list)
|
||||||
if (ret)
|
if (ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (DWORD bidx = 0; !retval && bidx < cnt; ++bidx)
|
bool retval = true;
|
||||||
|
for (DWORD bidx = 0; bidx < cnt; ++bidx)
|
||||||
if (EqualSid (pusersid, buf[bidx].lgrmi0_sid))
|
if (EqualSid (pusersid, buf[bidx].lgrmi0_sid))
|
||||||
retval = true;
|
goto done;
|
||||||
else
|
else
|
||||||
for (int glidx = 0; !retval && glidx < grp_list.count; ++glidx)
|
for (int glidx = 0; glidx < grp_list.count; ++glidx)
|
||||||
if (EqualSid (grp_list.sids[glidx], buf[bidx].lgrmi0_sid))
|
if (EqualSid (grp_list.sids[glidx], buf[bidx].lgrmi0_sid))
|
||||||
retval = true;
|
goto done;
|
||||||
|
|
||||||
|
retval = false;
|
||||||
|
done:
|
||||||
NetApiBufferFree (buf);
|
NetApiBufferFree (buf);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -545,6 +546,30 @@ get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw)
|
||||||
|
{
|
||||||
|
char user[UNLEN + 1];
|
||||||
|
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
||||||
|
WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 3];
|
||||||
|
char server[INTERNET_MAX_HOST_NAME_LENGTH + 3];
|
||||||
|
|
||||||
|
if (well_known_system_sid == usersid)
|
||||||
|
{
|
||||||
|
grp_list += well_known_admins_sid;
|
||||||
|
get_unix_group_sidlist (pw, grp_list);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
grp_list += well_known_world_sid;
|
||||||
|
grp_list += well_known_authenticated_users_sid;
|
||||||
|
extract_nt_dom_user (pw, domain, user);
|
||||||
|
if (get_logon_server (domain, server, wserver))
|
||||||
|
get_user_groups (wserver, grp_list, user, domain);
|
||||||
|
get_unix_group_sidlist (pw, grp_list);
|
||||||
|
return get_user_local_groups (grp_list, usersid);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
get_initgroups_sidlist (cygsidlist &grp_list,
|
get_initgroups_sidlist (cygsidlist &grp_list,
|
||||||
PSID usersid, PSID pgrpsid, struct passwd *pw,
|
PSID usersid, PSID pgrpsid, struct passwd *pw,
|
||||||
|
@ -554,26 +579,12 @@ get_initgroups_sidlist (cygsidlist &grp_list,
|
||||||
grp_list += well_known_world_sid;
|
grp_list += well_known_world_sid;
|
||||||
grp_list += well_known_authenticated_users_sid;
|
grp_list += well_known_authenticated_users_sid;
|
||||||
if (well_known_system_sid == usersid)
|
if (well_known_system_sid == usersid)
|
||||||
{
|
|
||||||
auth_pos = -1;
|
auth_pos = -1;
|
||||||
grp_list += well_known_admins_sid;
|
|
||||||
get_unix_group_sidlist (pw, grp_list);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
char user[UNLEN + 1];
|
|
||||||
char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
|
|
||||||
WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 3];
|
|
||||||
char server[INTERNET_MAX_HOST_NAME_LENGTH + 3];
|
|
||||||
|
|
||||||
get_token_group_sidlist (grp_list, my_grps, auth_luid, auth_pos);
|
get_token_group_sidlist (grp_list, my_grps, auth_luid, auth_pos);
|
||||||
extract_nt_dom_user (pw, domain, user);
|
if (!get_server_groups (grp_list, usersid, pw))
|
||||||
if (get_logon_server (domain, server, wserver))
|
|
||||||
get_user_groups (wserver, grp_list, user, domain);
|
|
||||||
get_unix_group_sidlist (pw, grp_list);
|
|
||||||
if (!get_user_local_groups (grp_list, usersid))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
/* special_pgrp true if pgrpsid is not in normal groups */
|
/* special_pgrp true if pgrpsid is not in normal groups */
|
||||||
if ((special_pgrp = !grp_list.contains (pgrpsid)))
|
if ((special_pgrp = !grp_list.contains (pgrpsid)))
|
||||||
grp_list += pgrpsid;
|
grp_list += pgrpsid;
|
||||||
|
@ -775,8 +786,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
|
||||||
}
|
}
|
||||||
|
|
||||||
PTOKEN_GROUPS my_grps;
|
PTOKEN_GROUPS my_grps;
|
||||||
bool saw_buf[NGROUPS_MAX] = {};
|
bool sawpg = false, ret = false;
|
||||||
bool *saw = saw_buf, sawpg = false, ret = false;
|
|
||||||
|
|
||||||
if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) &&
|
if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) &&
|
||||||
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
|
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
@ -785,16 +795,14 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
|
||||||
debug_printf ("alloca (my_grps) failed.");
|
debug_printf ("alloca (my_grps) failed.");
|
||||||
else if (!GetTokenInformation (token, TokenGroups, my_grps, size, &size))
|
else if (!GetTokenInformation (token, TokenGroups, my_grps, size, &size))
|
||||||
debug_printf ("GetTokenInformation(my_token, TokenGroups), %E");
|
debug_printf ("GetTokenInformation(my_token, TokenGroups), %E");
|
||||||
else if (!groups.issetgroups ()) /* setgroups was never called */
|
else
|
||||||
ret = sid_in_token_groups (my_grps, groups.pgsid)
|
{
|
||||||
|| groups.pgsid == usersid;
|
if (groups.issetgroups ()) /* setgroups was called */
|
||||||
else /* setgroups was called */
|
|
||||||
{
|
{
|
||||||
struct __group32 *gr;
|
|
||||||
cygsid gsid;
|
cygsid gsid;
|
||||||
if (groups.sgsids.count > (int) (sizeof (saw_buf) / sizeof (*saw_buf))
|
struct __group32 *gr;
|
||||||
&& !(saw = (bool *) calloc (groups.sgsids.count, sizeof (bool))))
|
bool saw[groups.sgsids.count];
|
||||||
goto done;
|
memset (saw, 0, sizeof(saw));
|
||||||
|
|
||||||
/* token groups found in /etc/group match the user.gsids ? */
|
/* token groups found in /etc/group match the user.gsids ? */
|
||||||
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
|
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
|
||||||
|
@ -809,16 +817,17 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
|
||||||
&& gsid != usersid)
|
&& gsid != usersid)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
/* user.sgsids groups must be in the token */
|
||||||
for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
|
for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
|
||||||
if (!saw[gidx])
|
if (!saw[gidx] && !sid_in_token_groups (my_grps, groups.sgsids.sids[gidx]))
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
/* The primary group must be in the token */
|
||||||
ret = sawpg
|
ret = sawpg
|
||||||
|| groups.sgsids.contains (groups.pgsid)
|
|| sid_in_token_groups (my_grps, groups.pgsid)
|
||||||
|| groups.pgsid == usersid;
|
|| groups.pgsid == usersid;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
if (saw != saw_buf)
|
|
||||||
free (saw);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,8 +148,7 @@ public:
|
||||||
BOOL add (const char *sidstr)
|
BOOL add (const char *sidstr)
|
||||||
{ cygsid nsi (sidstr); return add (nsi); }
|
{ cygsid nsi (sidstr); return add (nsi); }
|
||||||
BOOL addfromgr (struct __group32 *gr) /* Only with alloc */
|
BOOL addfromgr (struct __group32 *gr) /* Only with alloc */
|
||||||
{ return sids[count].getfromgr (gr)
|
{ return sids[count].getfromgr (gr) && ++count; }
|
||||||
&& (contains (sids[count]) || ++count); }
|
|
||||||
|
|
||||||
BOOL operator+= (cygsid &si) { return add (si); }
|
BOOL operator+= (cygsid &si) { return add (si); }
|
||||||
BOOL operator+= (const char *sidstr) { return add (sidstr); }
|
BOOL operator+= (const char *sidstr) { return add (sidstr); }
|
||||||
|
@ -326,6 +325,8 @@ HANDLE subauth (struct passwd *pw);
|
||||||
HANDLE create_token (cygsid &usersid, user_groups &groups, struct passwd * pw);
|
HANDLE create_token (cygsid &usersid, user_groups &groups, struct passwd * pw);
|
||||||
/* Verify an existing token */
|
/* Verify an existing token */
|
||||||
bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern = NULL);
|
bool verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern = NULL);
|
||||||
|
/* Get groups of a user */
|
||||||
|
bool get_server_groups (cygsidlist &grp_list, PSID usersid, struct passwd *pw);
|
||||||
|
|
||||||
/* Extract U-domain\user field from passwd entry. */
|
/* Extract U-domain\user field from passwd entry. */
|
||||||
void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user);
|
void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user);
|
||||||
|
|
Loading…
Reference in New Issue