diff -u cygwin.orig/cygheap.cc cygwin/cygheap.cc --- cygwin.orig/cygheap.cc 2002-07-25 22:40:50.000000000 -0400 +++ cygwin/cygheap.cc 2002-07-24 21:21:20.000000000 -0400 @@ -491,3 +491,51 @@ } return FALSE; } + +BOOL +cygheap_user::gsids_set (PSID pgpsid) +{ + if (gsids == NULL) + { + gsids = (cygsidarray *) cmalloc (HEAP_STR, gsids->size (0)); + if (gsids != NULL) + { + gsids->suppcount = -1; + gsids->sids[0] = pgpsid; + return TRUE; + } + } + return FALSE; +} + +BOOL +cygheap_user::gsids_alloc (cygsidarray * & gsids, int scount) + { + gsids = (cygsidarray *) cmalloc (HEAP_STR, + gsids->size (scount)); + if (gsids != NULL) + { + gsids->suppcount = 0; + return TRUE; + } + return FALSE; + } +void +cygheap_user::gsids_free (cygsidarray * gsids) +{ + return cfree (gsids); +} +BOOL +cygheap_user::gsids_update (cygsidarray * newgsids) +{ + if (gsids) + { + newgsids->sids[0] = gsids->sids[0]; + cfree (gsids); + gsids = newgsids; + return TRUE; + } + return FALSE; +} + + diff -u cygwin.orig/cygheap.h cygwin/cygheap.h --- cygwin.orig/cygheap.h 2002-07-25 22:40:50.000000000 -0400 +++ cygwin/cygheap.h 2002-07-25 22:54:48.000000000 -0400 @@ -113,6 +113,7 @@ __gid32_t orig_gid; /* Ditto */ __uid32_t real_uid; /* Remains intact on seteuid, replaced by setuid */ __gid32_t real_gid; /* Ditto */ + cygsidarray *gsids; /* buffer for primary and supp SIDs */ /* token is needed if set(e)uid should be called. It can be set by a call to `set_impersonation_token()'. */ @@ -141,6 +142,11 @@ const char *env_userprofile (const char *, size_t); const char *env_domain (const char *, size_t); const char *env_name (const char *, size_t); + BOOL gsids_set (PSID pgsid); + BOOL gsids_alloc (cygsidarray * & gsids, int scount); + void gsids_free (cygsidarray *gsids); + BOOL gsids_update (cygsidarray *newgsids); + BOOL issetgroups () const { return gsids && gsids->issetgroups (); } const char *logsrv () { diff -u cygwin.orig/cygwin.din cygwin/cygwin.din --- cygwin.orig/cygwin.din 2002-07-25 22:40:50.000000000 -0400 +++ cygwin/cygwin.din 2002-07-25 22:49:08.000000000 -0400 @@ -678,6 +678,9 @@ setgid _setgid = setgid setgid32 +setgroups +_setgroups = setgroups +setgroups32 setjmp _setjmp = setjmp setlocale diff -u cygwin.orig/grp.cc cygwin/grp.cc --- cygwin.orig/grp.cc 2002-07-25 22:40:50.000000000 -0400 +++ cygwin/grp.cc 2002-07-25 22:41:34.000000000 -0400 @@ -457,3 +457,64 @@ { return 0; } + +/* setgroups32: standards? */ +extern "C" +int +setgroups32 (int ngroups, const __gid32_t *grouplist) +{ + if (ngroups < 0 || (ngroups > 0 && !grouplist)) + { + set_errno (EINVAL); + return -1; + } + + if (!wincap.has_security ()) + return 0; + + cygsidarray * gsids; + struct __group32 *gr; + + if (!cygheap->user.gsids_alloc(gsids, ngroups)) + return -1; + + for (int gidx = 0; gidx < ngroups; ++gidx) + { + for (int gidy = 0; gidy < gidx; gidy++) + if (grouplist[gidy] == grouplist[gidx]) + goto found; /* Duplicate */ + for (int gidy = 0; (gr = internal_getgrent (gidy)); ++gidy) + if (gr->gr_gid == (__gid32_t) grouplist[gidx]) + { + if (gsids->addsuppfromgr (gr)) + goto found; + break; + } + debug_printf ("No sid found for gid %d", grouplist[gidx]); + cygheap->user.gsids_free(gsids); + set_errno (EINVAL); + return -1; + found: + continue; + } + cygheap->user.gsids_update(gsids); + return 0; +} + +extern "C" +int +setgroups (int ngroups, const __gid16_t *grouplist) +{ + __gid32_t *grouplist32 = NULL; + + if (ngroups > 0 && grouplist) + { + grouplist32 = (__gid32_t *) alloca (ngroups * sizeof (__gid32_t)); + if (grouplist32 == NULL) + return -1; + for (int i = 0; i < ngroups; i++) + grouplist32[i] = grouplist[i]; + } + return setgroups32 (ngroups, grouplist32); + +} diff -u cygwin.orig/security.cc cygwin/security.cc --- cygwin.orig/security.cc 2002-07-25 22:40:50.000000000 -0400 +++ cygwin/security.cc 2002-07-25 23:14:12.000000000 -0400 @@ -473,57 +473,63 @@ } } -static BOOL -get_group_sidlist (cygsidlist &grp_list, - cygsid &usersid, cygsid &pgrpsid, struct passwd *pw, - PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos, - BOOL *special_pgrp) -{ - 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]; - cygsidlist sup_list; - +static void +get_token_group_sidlist(cygsidlist &grp_list, PTOKEN_GROUPS my_grps, + LUID auth_luid, int &auth_pos) +{ auth_pos = -1; + if (my_grps) + { + if (sid_in_token_groups (my_grps, well_known_local_sid)) + grp_list += well_known_local_sid; + if (sid_in_token_groups (my_grps, well_known_dialup_sid)) + grp_list += well_known_dialup_sid; + if (sid_in_token_groups (my_grps, well_known_network_sid)) + grp_list += well_known_network_sid; + if (sid_in_token_groups (my_grps, well_known_batch_sid)) + grp_list += well_known_batch_sid; + if (sid_in_token_groups (my_grps, well_known_interactive_sid)) + grp_list += well_known_interactive_sid; + if (sid_in_token_groups (my_grps, well_known_service_sid)) + grp_list += well_known_service_sid; + } + else + { + grp_list += well_known_local_sid; + grp_list += well_known_interactive_sid; + } + if (auth_luid.QuadPart != 999) /* != SYSTEM_LUID */ + { + char buf[64]; + __small_sprintf (buf, "S-1-5-5-%u-%u", auth_luid.HighPart, + auth_luid.LowPart); + grp_list += buf; + auth_pos = grp_list.count - 1; + } +} +static BOOL +get_initgroups_sidlist (cygsidlist &grp_list, + PSID usersid, PSID pgrpsid, struct passwd *pw, + PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos, + BOOL &special_pgrp) +{ grp_list += well_known_world_sid; grp_list += well_known_authenticated_users_sid; if (usersid == well_known_system_sid) { + auth_pos = -1; grp_list += well_known_admins_sid; get_unix_group_sidlist (pw, grp_list); } else { - if (my_grps) - { - if (sid_in_token_groups (my_grps, well_known_local_sid)) - grp_list += well_known_local_sid; - if (sid_in_token_groups (my_grps, well_known_dialup_sid)) - grp_list += well_known_dialup_sid; - if (sid_in_token_groups (my_grps, well_known_network_sid)) - grp_list += well_known_network_sid; - if (sid_in_token_groups (my_grps, well_known_batch_sid)) - grp_list += well_known_batch_sid; - if (sid_in_token_groups (my_grps, well_known_interactive_sid)) - grp_list += well_known_interactive_sid; - if (sid_in_token_groups (my_grps, well_known_service_sid)) - grp_list += well_known_service_sid; - } - else - { - grp_list += well_known_local_sid; - grp_list += well_known_interactive_sid; - } - if (auth_luid.QuadPart != 999) /* != SYSTEM_LUID */ - { - char buf[64]; - __small_sprintf (buf, "S-1-5-5-%u-%u", auth_luid.HighPart, - auth_luid.LowPart); - grp_list += buf; - auth_pos = grp_list.count - 1; - } + 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); extract_nt_dom_user (pw, domain, user); if (get_logon_server (domain, server, wserver)) get_user_groups (wserver, grp_list, user, domain); @@ -531,16 +537,26 @@ if (!get_user_local_groups (grp_list, usersid)) return FALSE; } - /* special_pgrp true if pgrpsid is not null and not in normal groups */ - *special_pgrp = FALSE; - if (pgrpsid && !grp_list.contains (pgrpsid)) - { - *special_pgrp = TRUE; - grp_list += pgrpsid; - } + /* special_pgrp true if pgrpsid is not in normal groups */ + if ((special_pgrp = !grp_list.contains (pgrpsid))) + grp_list += pgrpsid; return TRUE; } +static void +get_setgroups_sidlist(cygsidlist &grp_list, PTOKEN_GROUPS my_grps, + cygsidarray &gsids, LUID auth_luid, int &auth_pos) +{ + PSID pgpsid = gsids.pgpsid (); + grp_list += well_known_world_sid; + grp_list += well_known_authenticated_users_sid; + get_token_group_sidlist(grp_list, my_grps, auth_luid, auth_pos); + for (int gidx = 1; gidx <= gsids.suppcount; gidx++) + grp_list += gsids.sids[gidx]; + if (gsids.position (1, pgpsid) < 0) + grp_list += pgpsid; +} + static const char *sys_privs[] = { SE_TCB_NAME, SE_ASSIGNPRIMARYTOKEN_NAME, @@ -654,8 +670,21 @@ return privs; } +/* Accept a token if + - the requested usersid matches the TokenUser and + - if setgroups has been called: + the token groups that are listed in /etc/group match the union of + the requested primary and supplementary groups in gsids. + - else the (unknown) implicitly requested supplementary groups and those + in the token are the groups associated with the usersid. We assume + they match and verify only the primary groups. + The requested primary group must appear in the token. + The primary group in the token is a group associated with the usersid, + except if the token is internal and the group is in the token SD + (see create_token). In that latter case that group must match the + requested primary group. */ BOOL -verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL *pintern) +verify_token (HANDLE token, cygsid &usersid, cygsidarray &gsids, BOOL * pintern) { DWORD size; BOOL intern = FALSE; @@ -675,9 +704,9 @@ debug_printf ("GetTokenInformation(): %E"); if (usersid != tok_usersid) return FALSE; - /* In an internal token, if the sd group is not well_known_null_sid, - it must match pgrpsid */ - if (intern) + /* For an internal token, if setgroups was not called and if the sd group + is not well_known_null_sid, it must match pgrpsid */ + if (intern && !gsids.issetgroups ()) { char sd_buf[MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR)]; PSID gsid = NO_SID; @@ -688,14 +717,14 @@ else if (!GetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) sd_buf, &gsid, (BOOL *) &size)) debug_printf ("GetSecurityDescriptorGroup(): %E"); - if (well_known_null_sid != gsid) return pgrpsid == gsid; + if (well_known_null_sid != gsid) return gsid == gsids.pgpsid (); } - /* See if the pgrpsid is the tok_usersid in the token groups */ + PTOKEN_GROUPS my_grps = NULL; BOOL ret = FALSE; - - if ( pgrpsid == tok_usersid) - return TRUE; + char saw_buf[NGROUPS_MAX + 1] = {}; + char *saw = saw_buf; + if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) && GetLastError () != ERROR_INSUFFICIENT_BUFFER) debug_printf ("GetTokenInformation(token, TokenGroups): %E\n"); @@ -703,34 +732,63 @@ debug_printf ("malloc (my_grps) failed."); else if (!GetTokenInformation (token, TokenGroups, my_grps, size, &size)) debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); - else - ret = sid_in_token_groups (my_grps, pgrpsid); - if (my_grps) - free (my_grps); + else if (!gsids.issetgroups ()) /* setgroups was never called */ + { + ret = sid_in_token_groups (my_grps, *(gsids.pgcygsidptr ())); + if (ret == FALSE) ret = (gsids.pgpsid () == tok_usersid); + } + else /* setgroups was called */ + { + struct __group32 *gr; + cygsid gsid; + if (gsids.suppcount + 1 > (int) sizeof (saw_buf) && + !(saw = (char *) calloc (gsids.suppcount + 1, sizeof(char)))) + goto done; + + /* See if the pgid is also a supplementary group */ + int first = (gsids.position (1, gsids.pgpsid ()) >= 0)?1:0; + + /* 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 = gsids.position (first, gsid); + if (pos < 0) + goto done; + saw[pos] = TRUE; + } + for (int gidx = first; gidx <= gsids.suppcount; gidx++) + if (!saw[gidx]) + goto done; + ret = TRUE; + } + done: + if (my_grps) free (my_grps); + if (saw != saw_buf) free(saw); return ret; } HANDLE -create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw) +create_token (cygsid &usersid, cygsidarray &new_gsids, struct passwd *pw) { NTSTATUS ret; LSA_HANDLE lsa = INVALID_HANDLE_VALUE; int old_priv_state; - cygsidlist grpsids; + cygsidlist tmp_gsids; SECURITY_QUALITY_OF_SERVICE sqos = { sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE }; OBJECT_ATTRIBUTES oa = { sizeof oa, 0, 0, 0, 0, &sqos }; PSECURITY_ATTRIBUTES psa; - BOOL special_pgrp; + BOOL special_pgrp = FALSE; char sa_buf[1024]; LUID auth_luid = SYSTEM_LUID; LARGE_INTEGER exp = { QuadPart:0x7fffffffffffffffLL }; TOKEN_USER user; - PTOKEN_GROUPS grps = NULL; + PTOKEN_GROUPS new_tok_gsids = NULL; PTOKEN_PRIVILEGES privs = NULL; TOKEN_OWNER owner; TOKEN_PRIMARY_GROUP pgrp; @@ -746,7 +804,7 @@ HANDLE primary_token = INVALID_HANDLE_VALUE; HANDLE my_token = INVALID_HANDLE_VALUE; - PTOKEN_GROUPS my_grps = NULL; + PTOKEN_GROUPS my_tok_gsids = NULL; DWORD size; /* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */ @@ -781,54 +839,56 @@ if (!GetTokenInformation (my_token, TokenGroups, NULL, 0, &size) && GetLastError () != ERROR_INSUFFICIENT_BUFFER) debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); - else if (!(my_grps = (PTOKEN_GROUPS) malloc (size))) - debug_printf ("malloc (my_grps) failed."); - else if (!GetTokenInformation (my_token, TokenGroups, my_grps, + else if (!(my_tok_gsids = (PTOKEN_GROUPS) malloc (size))) + debug_printf ("malloc (my_tok_gsids) failed."); + else if (!GetTokenInformation (my_token, TokenGroups, my_tok_gsids, size, &size)) { debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); - free (my_grps); - my_grps = NULL; + free (my_tok_gsids); + my_tok_gsids = NULL; } CloseHandle (my_token); } /* Create list of groups, the user is member in. */ int auth_pos; - if (!get_group_sidlist (grpsids, usersid, pgrpsid, pw, - my_grps, auth_luid, auth_pos, &special_pgrp)) + if (new_gsids.issetgroups ()) + get_setgroups_sidlist (tmp_gsids, my_tok_gsids, new_gsids, auth_luid, auth_pos); + else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_gsids.pgpsid (), pw, + my_tok_gsids, auth_luid, auth_pos, special_pgrp)) goto out; /* Primary group. */ - pgrp.PrimaryGroup = pgrpsid; + pgrp.PrimaryGroup = new_gsids.pgpsid (); /* Create a TOKEN_GROUPS list from the above retrieved list of sids. */ - char grps_buf[sizeof (ULONG) + grpsids.count * sizeof (SID_AND_ATTRIBUTES)]; - grps = (PTOKEN_GROUPS) grps_buf; - grps->GroupCount = grpsids.count; - for (DWORD i = 0; i < grps->GroupCount; ++i) + char grps_buf[sizeof (ULONG) + tmp_gsids.count * sizeof (SID_AND_ATTRIBUTES)]; + new_tok_gsids = (PTOKEN_GROUPS) grps_buf; + new_tok_gsids->GroupCount = tmp_gsids.count; + for (DWORD i = 0; i < new_tok_gsids->GroupCount; ++i) { - grps->Groups[i].Sid = grpsids.sids[i]; - grps->Groups[i].Attributes = SE_GROUP_MANDATORY | + new_tok_gsids->Groups[i].Sid = tmp_gsids.sids[i]; + new_tok_gsids->Groups[i].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; - if (auth_pos >= 0 && i == (DWORD) auth_pos) - grps->Groups[i].Attributes |= SE_GROUP_LOGON_ID; } + if (auth_pos > 0) + new_tok_gsids->Groups[auth_pos].Attributes |= SE_GROUP_LOGON_ID; /* Retrieve list of privileges of that user. */ - if (!(privs = get_priv_list (lsa, usersid, grpsids))) + if (!(privs = get_priv_list (lsa, usersid, tmp_gsids))) goto out; /* Create default dacl. */ if (!sec_acl ((PACL) acl_buf, FALSE, - grpsids.contains (well_known_admins_sid)?well_known_admins_sid:usersid)) + tmp_gsids.contains (well_known_admins_sid)?well_known_admins_sid:usersid)) goto out; dacl.DefaultDacl = (PACL) acl_buf; /* Let's be heroic... */ ret = NtCreateToken (&token, TOKEN_ALL_ACCESS, &oa, TokenImpersonation, - &auth_luid, &exp, &user, grps, privs, &owner, &pgrp, + &auth_luid, &exp, &user, new_tok_gsids, privs, &owner, &pgrp, &dacl, &source); if (ret) __seterrno_from_win_error (RtlNtStatusToDosError (ret)); @@ -843,8 +903,8 @@ psa = __sec_user (sa_buf, usersid, TRUE); if (psa->lpSecurityDescriptor && !SetSecurityDescriptorGroup ( - (PSECURITY_DESCRIPTOR) psa->lpSecurityDescriptor, - special_pgrp ? pgrpsid : well_known_null_sid, FALSE)) + (PSECURITY_DESCRIPTOR) psa->lpSecurityDescriptor, + special_pgrp ? *(new_gsids.pgcygsidptr ()): well_known_null_sid, FALSE)) debug_printf ("SetSecurityDescriptorGroup %E"); /* Convert to primary token. */ if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa, @@ -862,8 +922,8 @@ CloseHandle (token); if (privs) free (privs); - if (my_grps) - free (my_grps); + if (my_tok_gsids) + free (my_tok_gsids); close_local_policy (lsa); debug_printf ("%d = create_token ()", primary_token); @@ -1828,3 +1888,4 @@ myself->uid, myself->gid, attribute); } + diff -u cygwin.orig/security.h cygwin/security.h --- cygwin.orig/security.h 2002-07-25 22:40:52.000000000 -0400 +++ cygwin/security.h 2002-07-25 22:37:24.000000000 -0400 @@ -87,33 +87,39 @@ }; class cygsidlist { + int maxcount; public: int count; cygsid *sids; - cygsidlist () : count (0), sids (NULL) {} + cygsidlist () : maxcount(12), count (0), sids (new cygsid [12]) {} ~cygsidlist () { delete [] sids; } - BOOL add (cygsid &nsi) + BOOL add (PSID nsi) { - cygsid *tmp = new cygsid [count + 1]; - if (!tmp) - return FALSE; - for (int i = 0; i < count; ++i) - tmp[i] = sids[i]; - delete [] sids; - sids = tmp; + if ( count >= maxcount) + { + cygsid *tmp = new cygsid [ 2 * maxcount]; + if (!tmp) + return FALSE; + maxcount *= 2; + for (int i = 0; i < count; ++i) + tmp[i] = sids[i]; + delete [] sids; + sids = tmp; + } sids[count++] = nsi; return TRUE; } - BOOL add (const PSID nsid) { return add (nsid); } + BOOL add (cygsid &nsi) { return add ((PSID) nsi); } BOOL add (const char *sidstr) { cygsid nsi (sidstr); return add (nsi); } BOOL operator+= (cygsid &si) { return add (si); } BOOL operator+= (const char *sidstr) { return add (sidstr); } + BOOL operator+= (const PSID psid) { return add (psid); } - BOOL contains (cygsid &sid) const + BOOL contains (PSID sid) const { for (int i = 0; i < count; ++i) if (sids[i] == sid) @@ -131,6 +137,34 @@ } }; +class cygsidarray { +public: + int suppcount; + cygsid sids[]; + + int size (int suppcount) const + { return sizeof(int) + (suppcount + 1) * sizeof(cygsid); } + BOOL addsuppfromgr(const struct __group32 *gr) + { + if (sids[1 + suppcount].getfromgr(gr)) + { + suppcount++; + return TRUE; + } + return FALSE; + } + int position (int from, PSID psid) const + { + for (int i = from; i <= suppcount; ++i) + if (sids[i] == psid) + return i; + return -1; + } + BOOL issetgroups () const { return (suppcount >= 0); } + PSID pgpsid () { return (PSID) sids[0]; } + cygsid * pgcygsidptr () { return &sids[0]; } +}; + extern cygsid well_known_null_sid; extern cygsid well_known_world_sid; extern cygsid well_known_local_sid; @@ -180,9 +214,9 @@ /* Try a subauthentication. */ HANDLE subauth (struct passwd *pw); /* Try creating a token directly. */ -HANDLE create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd * pw); +HANDLE create_token (cygsid &usersid, cygsidarray &gsids, struct passwd * pw); /* Verify an existing token */ -BOOL verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL * pintern = NULL); +BOOL verify_token (HANDLE token, cygsid &usersid, cygsidarray &gsids, BOOL * pintern = NULL); /* Extract U-domain\user field from passwd entry. */ void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user); diff -u cygwin.orig/syscalls.cc cygwin/syscalls.cc --- cygwin.orig/syscalls.cc 2002-07-25 22:40:52.000000000 -0400 +++ cygwin/syscalls.cc 2002-07-24 21:37:18.000000000 -0400 @@ -1960,6 +1960,7 @@ if (!wincap.has_security () || (!cygheap->user.issetuid () + && !cygheap->user.issetgroups () && uid == myself->uid && myself->gid == cygheap->user.orig_gid) || uid == ILLEGAL_UID) @@ -1969,7 +1970,8 @@ } sigframe thisframe (mainthread); - cygsid usersid, pgrpsid; + cygsid usersid; + cygsidarray *gsids = cygheap->user.gsids; HANDLE ptok, sav_token; BOOL sav_impersonated, sav_token_is_internal_token; BOOL process_ok, explicitly_created_token = FALSE; @@ -1977,8 +1979,7 @@ PSID origpsid, psid2 = NO_SID; pw_new = getpwuid32 (uid); - if (!usersid.getfrompw (pw_new) || - (!pgrpsid.getfromgr (getgrgid32 (myself->gid)))) + if (!usersid.getfrompw (pw_new) || !gsids) { set_errno (EINVAL); return -1; @@ -1996,7 +1997,7 @@ /* Verify if the process token is suitable. Currently we do not try to differentiate between internal tokens and others */ - process_ok = verify_token (ptok, usersid, pgrpsid); + process_ok = verify_token (ptok, usersid, *gsids); debug_printf("Process token %sverified", process_ok ? "" : "not "); if (process_ok) { @@ -2012,7 +2013,7 @@ if (!process_ok && cygheap->user.token != INVALID_HANDLE_VALUE) { /* Verify if the current tokem is suitable */ - BOOL token_ok = verify_token (cygheap->user.token, usersid, pgrpsid, + BOOL token_ok = verify_token (cygheap->user.token, usersid, *gsids, & sav_token_is_internal_token); debug_printf("Thread token %d %sverified", cygheap->user.token, token_ok?"":"not "); @@ -2049,7 +2050,7 @@ { /* If no impersonation token is available, try to authenticate using NtCreateToken() or subauthentication. */ - cygheap->user.token = create_token (usersid, pgrpsid, pw_new); + cygheap->user.token = create_token (usersid, *gsids, pw_new); if (cygheap->user.token != INVALID_HANDLE_VALUE) explicitly_created_token = TRUE; else @@ -2077,7 +2078,7 @@ /* Try setting primary group in token to current group */ if (!SetTokenInformation (cygheap->user.token, TokenPrimaryGroup, - &pgrpsid, sizeof pgrpsid)) + gsids->pgcygsidptr (), sizeof(cygsid))) debug_printf ("SetTokenInformation(user.token, " "TokenPrimaryGroup): %E"); } @@ -2143,17 +2144,19 @@ return 0; sigframe thisframe (mainthread); + cygsidarray *gsids = cygheap->user.gsids; cygsid gsid; HANDLE ptok; struct __group32 * gr = getgrgid32 (gid); - if (!gr || gr->gr_gid != gid || !gsid.getfromgr (gr)) + if (!gr || gr->gr_gid != gid || !gsid.getfromgr (gr) || !gsids) { set_errno (EINVAL); return -1; } myself->gid = gid; + *(gsids->pgcygsidptr ()) = gsid; /* If impersonated, update primary group and revert */ if (cygheap->user.issetuid ()) { diff -u cygwin.orig/uinfo.cc cygwin/uinfo.cc --- cygwin.orig/uinfo.cc 2002-07-25 22:40:54.000000000 -0400 +++ cygwin/uinfo.cc 2002-07-24 21:38:46.000000000 -0400 @@ -39,7 +39,7 @@ { HANDLE ptok = INVALID_HANDLE_VALUE; DWORD siz; - cygsid tu; + cygsid tu, tpg; DWORD ret = 0; /* Try to get the SID either from current process and @@ -50,7 +50,11 @@ else if (!GetTokenInformation (ptok, TokenUser, &tu, sizeof tu, &siz)) system_printf ("GetTokenInformation(): %E"); else if (!(ret = user.set_sid (tu))) - system_printf ("Couldn't retrieve SID from access token!"); + system_printf ("Couldn't retrieve user SID from access token!"); + else if (!GetTokenInformation (ptok, TokenPrimaryGroup, &tpg, sizeof tu, &siz)) + system_printf ("GetTokenInformation(): %E"); + else if (!(ret = user.gsids_set (tpg))) + system_printf ("Couldn't retrieve primary group SID from access token!"); /* We must set the user name, uid and gid. If we have a SID, try to get the corresponding Cygwin password entry. Set user name which can be different @@ -75,11 +79,14 @@ primary group to the group in /etc/passwd. */ if (!SetTokenInformation (ptok, TokenOwner, &tu, sizeof tu)) debug_printf ("SetTokenInformation(TokenOwner): %E"); - if (gsid && !SetTokenInformation (ptok, TokenPrimaryGroup, - &gsid, sizeof gsid)) - debug_printf ("SetTokenInformation(TokenPrimaryGroup): %E"); + if (gsid) + { + *(user.gsids->pgcygsidptr ()) = gsid; + if (!SetTokenInformation (ptok, TokenPrimaryGroup, + &gsid, sizeof gsid)) + debug_printf ("SetTokenInformation(TokenPrimaryGroup): %E"); + } } - if (ptok != INVALID_HANDLE_VALUE) CloseHandle (ptok); }