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-27 17:16:58.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 */ + user_groups groups; /* 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()'. */ 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-28 11:26:20.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; + + cygsidlist gsids (cygsidlist_alloc, ngroups); + struct __group32 *gr; + + if (ngroups && !gsids.sids) + 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.addfromgr (gr)) + goto found; + break; + } + debug_printf ("No sid found for gid %d", grouplist[gidx]); + gsids.free_sids (); + set_errno (EINVAL); + return -1; + found: + continue; + } + cygheap->user.groups.update_supp (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-28 18:21:56.000000000 -0400 @@ -47,6 +47,21 @@ The default is TRUE to reflect the old behaviour. */ BOOL allow_smbntsec; +cygsid * +cygsidlist::alloc_sids (int n) +{ + if (n > 0) + return (cygsid *) cmalloc (HEAP_STR, n * sizeof (cygsid)); + else + return NULL; +} + +void +cygsidlist::free_sids () +{ + if (sids) cfree (sids); +} + extern "C" void cygwin_set_impersonation_token (const HANDLE hToken) { @@ -152,7 +167,7 @@ sys_mbstowcs (buf, srcstr, tgt.MaximumLength); } -#if 0 //unused +#if 0 /* unused */ static void lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size) { @@ -194,7 +209,7 @@ lsa = INVALID_HANDLE_VALUE; } -#if 0 // unused +#if 0 /* unused */ static BOOL get_lsa_srv_inf (LSA_HANDLE lsa, char *logonserver, char *domain) { @@ -473,57 +488,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 +552,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 &tmp_list, PTOKEN_GROUPS my_grps, + user_groups &groups, LUID auth_luid, int &auth_pos) +{ + PSID pgpsid = groups.pgsid; + tmp_list += well_known_world_sid; + tmp_list += well_known_authenticated_users_sid; + get_token_group_sidlist(tmp_list, my_grps, auth_luid, auth_pos); + for (int gidx = 0; gidx < groups.sgsids.count; gidx++) + tmp_list += groups.sgsids.sids[gidx]; + if (!groups.sgsids.contains (pgpsid)) + tmp_list += pgpsid; +} + static const char *sys_privs[] = { SE_TCB_NAME, SE_ASSIGNPRIMARYTOKEN_NAME, @@ -654,8 +685,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, user_groups &groups, BOOL * pintern) { DWORD size; BOOL intern = FALSE; @@ -675,9 +719,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 && !groups.issetgroups ()) { char sd_buf[MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR)]; PSID gsid = NO_SID; @@ -688,14 +732,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 == groups.pgsid; } - /* 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] = {}; + char *saw = saw_buf, sawpg = FALSE; + if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) && GetLastError () != ERROR_INSUFFICIENT_BUFFER) debug_printf ("GetTokenInformation(token, TokenGroups): %E\n"); @@ -703,34 +747,64 @@ 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 (!groups.issetgroups ()) /* setgroups was never called */ + { + ret = sid_in_token_groups (my_grps, groups.pgsid); + if (ret == FALSE) ret = (groups.pgsid == tok_usersid); + } + else /* setgroups was called */ + { + struct __group32 *gr; + cygsid gsid; + if (groups.sgsids.count > (int) sizeof (saw_buf) && + !(saw = (char *) calloc (groups.sgsids.count, sizeof(char)))) + 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 + goto done; + } + for (int gidx = 0; gidx < groups.sgsids.count; gidx++) + if (!saw[gidx]) + goto done; + if (sawpg || groups.sgsids.contains (groups.pgsid)) + 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, user_groups &new_groups, struct passwd *pw) { NTSTATUS ret; LSA_HANDLE lsa = INVALID_HANDLE_VALUE; int old_priv_state; - cygsidlist grpsids; + cygsidlist tmp_gsids(cygsidlist_auto ,12); 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 +820,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 +855,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_groups.issetgroups ()) + get_setgroups_sidlist (tmp_gsids, my_tok_gsids, new_groups, auth_luid, auth_pos); + else if (!get_initgroups_sidlist (tmp_gsids, usersid, new_groups.pgsid, pw, + my_tok_gsids, auth_luid, auth_pos, special_pgrp)) goto out; /* Primary group. */ - pgrp.PrimaryGroup = pgrpsid; + pgrp.PrimaryGroup = new_groups.pgsid; /* 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 +919,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_groups.pgsid: well_known_null_sid, FALSE)) debug_printf ("SetSecurityDescriptorGroup %E"); /* Convert to primary token. */ if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa, @@ -862,8 +938,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 +1904,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-28 18:27:22.000000000 -0400 @@ -86,40 +86,63 @@ } }; +typedef enum { cygsidlist_unknown, cygsidlist_alloc, cygsidlist_auto } cygsidlist_type; class cygsidlist { + int maxcount; public: int count; cygsid *sids; + cygsidlist_type type; - cygsidlist () : count (0), sids (NULL) {} - ~cygsidlist () { delete [] sids; } + cygsidlist (cygsidlist_type t, int m) + { + type = t; + count = 0; + maxcount = m; + if (t == cygsidlist_alloc) + sids = alloc_sids (m); + else + sids = new cygsid [m]; + } + ~cygsidlist () { if (type == cygsidlist_auto) delete [] sids; } - BOOL add (cygsid &nsi) + BOOL add (const PSID nsi) /* Only with auto for now */ { - 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 addfromgr (struct __group32 *gr) /* Only with alloc */ + { return sids[count++].getfromgr (gr); } + 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 + int position (const PSID sid) const { for (int i = 0; i < count; ++i) if (sids[i] == sid) - return TRUE; - return FALSE; + return i; + return -1; } + + BOOL contains (const PSID sid) const { return position (sid) >= 0; } + cygsid *alloc_sids (int n); + void free_sids (); void debug_print (const char *prefix = NULL) const { debug_printf ("-- begin sidlist ---"); @@ -131,6 +154,26 @@ } }; +class user_groups { +public: + cygsid pgsid; + cygsidlist sgsids; + BOOL ischanged; + + BOOL issetgroups () const { return (sgsids.type == cygsidlist_alloc); } + void update_supp (const cygsidlist &newsids) + { + sgsids.free_sids (); + sgsids = newsids; + ischanged = TRUE; + } + void update_pgrp (const PSID sid) + { + pgsid = sid; + ischanged = TRUE; + } +}; + extern cygsid well_known_null_sid; extern cygsid well_known_world_sid; extern cygsid well_known_local_sid; @@ -180,9 +223,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, user_groups &groups, 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, user_groups &groups, 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-27 19:04:54.000000000 -0400 @@ -1959,9 +1959,8 @@ debug_printf ("uid: %d myself->gid: %d", uid, myself->gid); if (!wincap.has_security () - || (!cygheap->user.issetuid () - && uid == myself->uid - && myself->gid == cygheap->user.orig_gid) + || (uid == myself->uid + && !cygheap->user.groups.ischanged) || uid == ILLEGAL_UID) { debug_printf ("Nothing happens"); @@ -1969,7 +1968,8 @@ } sigframe thisframe (mainthread); - cygsid usersid, pgrpsid; + cygsid usersid; + user_groups &groups = cygheap->user.groups; HANDLE ptok, sav_token; BOOL sav_impersonated, sav_token_is_internal_token; BOOL process_ok, explicitly_created_token = FALSE; @@ -1977,8 +1977,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)) { set_errno (EINVAL); return -1; @@ -1996,7 +1995,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, groups); debug_printf("Process token %sverified", process_ok ? "" : "not "); if (process_ok) { @@ -2012,7 +2011,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, groups, & sav_token_is_internal_token); debug_printf("Thread token %d %sverified", cygheap->user.token, token_ok?"":"not "); @@ -2049,7 +2048,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, groups, pw_new); if (cygheap->user.token != INVALID_HANDLE_VALUE) explicitly_created_token = TRUE; else @@ -2077,7 +2076,7 @@ /* Try setting primary group in token to current group */ if (!SetTokenInformation (cygheap->user.token, TokenPrimaryGroup, - &pgrpsid, sizeof pgrpsid)) + &groups.pgsid, sizeof(cygsid))) debug_printf ("SetTokenInformation(user.token, " "TokenPrimaryGroup): %E"); } @@ -2099,6 +2098,7 @@ cygheap->user.set_name (pw_new->pw_name); cygheap->user.set_sid (usersid); myself->uid = uid; + groups.ischanged = FALSE; return 0; failed: @@ -2143,6 +2143,7 @@ return 0; sigframe thisframe (mainthread); + user_groups * groups = &cygheap->user.groups; cygsid gsid; HANDLE ptok; @@ -2154,6 +2155,7 @@ } myself->gid = gid; + groups->update_pgrp (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-28 19:04:56.000000000 -0400 @@ -48,9 +48,12 @@ &ptok)) system_printf ("OpenProcessToken(): %E\n"); else if (!GetTokenInformation (ptok, TokenUser, &tu, sizeof tu, &siz)) - system_printf ("GetTokenInformation(): %E"); + system_printf ("GetTokenInformation (TokenUser): %E"); else if (!(ret = user.set_sid (tu))) system_printf ("Couldn't retrieve SID from access token!"); + else if (!GetTokenInformation (ptok, TokenPrimaryGroup, + &user.groups.pgsid, sizeof tu, &siz)) + system_printf ("GetTokenInformation (TokenPrimaryGroup): %E"); /* 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 +78,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.groups.pgsid = gsid; + if (!SetTokenInformation (ptok, TokenPrimaryGroup, + &gsid, sizeof gsid)) + debug_printf ("SetTokenInformation(TokenPrimaryGroup): %E"); + } } - if (ptok != INVALID_HANDLE_VALUE) CloseHandle (ptok); }