diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2005-04-16 15:21:47 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2005-04-16 15:21:47 +0000 |
commit | 68a3f0d34af960ecb1da72ce70819189a3b6dd29 (patch) | |
tree | b06e50bb18f618e2fccf7f3e8073662f1929a28d /winsup | |
parent | 00c05edcf1457ce2b6a03892c095ced9e4d15465 (diff) | |
download | newlib-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/ChangeLog | 14 | ||||
-rw-r--r-- | winsup/cygwin/grp.cc | 57 | ||||
-rw-r--r-- | winsup/cygwin/security.cc | 123 | ||||
-rw-r--r-- | winsup/cygwin/security.h | 5 |
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); |