aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-04-16 15:21:47 +0000
committerCorinna Vinschen <corinna@vinschen.de>2005-04-16 15:21:47 +0000
commit68a3f0d34af960ecb1da72ce70819189a3b6dd29 (patch)
treeb06e50bb18f618e2fccf7f3e8073662f1929a28d /winsup
parent00c05edcf1457ce2b6a03892c095ced9e4d15465 (diff)
downloadnewlib-68a3f0d34af960ecb1da72ce70819189a3b6dd29.zip
newlib-68a3f0d34af960ecb1da72ce70819189a3b6dd29.tar.gz
newlib-68a3f0d34af960ecb1da72ce70819189a3b6dd29.tar.bz2
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog14
-rw-r--r--winsup/cygwin/grp.cc57
-rw-r--r--winsup/cygwin/security.cc123
-rw-r--r--winsup/cygwin/security.h5
4 files changed, 132 insertions, 67 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index df933c2..64bb229 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,4 +1,18 @@
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>
* environ.cc (environ_init): Don't set traverse checking as default.
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index ae3c27a..c82a59f 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -344,14 +344,32 @@ internal_getgroups (int gidsetsize, __gid32_t *grouplist, cygpsid * srchsid)
__gid32_t gid;
const char *username;
- if (allow_ntsec)
+ if (!srchsid && cygheap->user.groups.issetgroups ())
{
- /* If impersonated, use impersonation token. */
- if (cygheap->user.issetuid ())
- hToken = cygheap->user.token ();
- else
- hToken = hProcImpToken;
+ 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 (cygheap->user.issetuid ())
+ hToken = cygheap->user.token ();
+ else
+ hToken = hProcImpToken;
+
if (hToken)
{
if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size)
@@ -450,9 +468,32 @@ getgroups (int gidsetsize, __gid16_t *grouplist)
extern "C" int
initgroups32 (const char *name, __gid32_t gid)
{
+ int ret;
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;
}
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index e74fd8d..e2a9426 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -42,8 +42,7 @@ details. */
bool allow_ntsec;
/* allow_smbntsec is handled exclusively in path.cc (path_conv::check).
- It's defined here because of it's strong relationship to allow_ntsec.
- The default is TRUE to reflect the old behaviour. */
+ It's defined here because of it's strong relationship to allow_ntsec. */
bool allow_smbntsec;
bool allow_traverse;
@@ -363,7 +362,6 @@ is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list)
LPLOCALGROUP_MEMBERS_INFO_0 buf;
DWORD cnt, tot;
NET_API_STATUS ret;
- bool retval = false;
/* Members can be users or global groups */
ret = NetLocalGroupGetMembers (NULL, wgroup, 0, (LPBYTE *) &buf,
@@ -371,14 +369,17 @@ is_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list)
if (ret)
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))
- retval = true;
+ goto done;
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))
- retval = true;
+ goto done;
+ retval = false;
+ done:
NetApiBufferFree (buf);
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
get_initgroups_sidlist (cygsidlist &grp_list,
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_authenticated_users_sid;
if (well_known_system_sid == usersid)
- {
- auth_pos = -1;
- grp_list += well_known_admins_sid;
- get_unix_group_sidlist (pw, grp_list);
- }
- 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];
+ auth_pos = -1;
+ else
+ get_token_group_sidlist (grp_list, my_grps, auth_luid, auth_pos);
+ if (!get_server_groups (grp_list, usersid, pw))
+ return false;
- get_token_group_sidlist (grp_list, my_grps, auth_luid, auth_pos);
- 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);
- if (!get_user_local_groups (grp_list, usersid))
- return false;
- }
/* special_pgrp true if pgrpsid is not in normal groups */
if ((special_pgrp = !grp_list.contains (pgrpsid)))
grp_list += pgrpsid;
@@ -775,8 +786,7 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
}
PTOKEN_GROUPS my_grps;
- bool saw_buf[NGROUPS_MAX] = {};
- bool *saw = saw_buf, sawpg = false, ret = false;
+ bool sawpg = false, ret = false;
if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) &&
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
@@ -785,40 +795,39 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
debug_printf ("alloca (my_grps) failed.");
else if (!GetTokenInformation (token, TokenGroups, my_grps, size, &size))
debug_printf ("GetTokenInformation(my_token, TokenGroups), %E");
- else if (!groups.issetgroups ()) /* setgroups was never called */
- ret = sid_in_token_groups (my_grps, groups.pgsid)
- || groups.pgsid == usersid;
- else /* setgroups was called */
+ else
{
- struct __group32 *gr;
- cygsid gsid;
- if (groups.sgsids.count > (int) (sizeof (saw_buf) / sizeof (*saw_buf))
- && !(saw = (bool *) calloc (groups.sgsids.count, sizeof (bool))))
- goto done;
-
- /* token groups found in /etc/group match the user.gsids ? */
- for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
- if (gsid.getfromgr (gr) && sid_in_token_groups (my_grps, gsid))
- {
- int pos = groups.sgsids.position (gsid);
- if (pos >= 0)
- saw[pos] = true;
- else if (groups.pgsid == gsid)
- sawpg = true;
- else if (gsid != well_known_world_sid
- && gsid != usersid)
+ if (groups.issetgroups ()) /* setgroups was called */
+ {
+ cygsid gsid;
+ struct __group32 *gr;
+ bool saw[groups.sgsids.count];
+ memset (saw, 0, sizeof(saw));
+
+ /* token groups found in /etc/group match the user.gsids ? */
+ for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
+ if (gsid.getfromgr (gr) && sid_in_token_groups (my_grps, gsid))
+ {
+ int pos = groups.sgsids.position (gsid);
+ if (pos >= 0)
+ saw[pos] = true;
+ else if (groups.pgsid == gsid)
+ sawpg = true;
+ else if (gsid != well_known_world_sid
+ && gsid != usersid)
+ goto done;
+ }
+ /* user.sgsids groups must be in the token */
+ for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
+ if (!saw[gidx] && !sid_in_token_groups (my_grps, groups.sgsids.sids[gidx]))
goto done;
- }
- for (int gidx = 0; gidx < groups.sgsids.count; gidx++)
- if (!saw[gidx])
- goto done;
+ }
+ /* The primary group must be in the token */
ret = sawpg
- || groups.sgsids.contains (groups.pgsid)
- || groups.pgsid == usersid;
+ || sid_in_token_groups (my_grps, groups.pgsid)
+ || groups.pgsid == usersid;
}
done:
- if (saw != saw_buf)
- free (saw);
return ret;
}
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 1c95d30..d304525 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -148,8 +148,7 @@ public:
BOOL add (const char *sidstr)
{ cygsid nsi (sidstr); return add (nsi); }
BOOL addfromgr (struct __group32 *gr) /* Only with alloc */
- { return sids[count].getfromgr (gr)
- && (contains (sids[count]) || ++count); }
+ { return sids[count].getfromgr (gr) && ++count; }
BOOL operator+= (cygsid &si) { return add (si); }
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);
/* Verify an existing token */
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. */
void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user);