From d551169a9fa38d2499840f409e0ca90992d6881a Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 25 Apr 2001 09:43:25 +0000 Subject: * autoload.cc: Add LoadDLLfunc statements for SetTokenInformation@16. * cygheap.cc: Include security.h. * grp.cc (internal_getgrent): New function. (getgroups): Rearranged using `internal_getgrent' and the new `cygsid' class. * passwd.cc (internal_getpwent): New function. * sec_acl.cc: Use new `cygsid' class throughout. (acl_access): Use `internal_getgrent' instead of `getgrent'. * sec_helper.cc: Use new `cygsid' class throughout. (get_id_from_sid): Use `internal_getgrent' instead of `getgrent'. Use `internal_getpwent' instead of `getpwent'. * security.cc: Use new `cygsid' class throughout. * security.h: Move `MAX_SID_LEN' from winsup.h to here. Add extern declarations for `internal_getgrent' and `internal_getpwent'. (class cygsid): New class. * shared.cc (sec_user): Use new `cygsid' class. * syscalls.cc (seteuid): Try to set owner to user and primary group to current group in impersonation token before performing impersonation. (setegid): Try to set primary group in process token to the new group if ntsec is on. * uinfo.cc (internal_getlogin): Use new `cygsid' class. Try to set owner to user and primary group to current group in process token if the process has been started from a non cygwin process. (uinfo_init): Set primary group only if the process has been started from a non cygwin process. * winsup.h: Move define for `MAX_SID_LEN' to security.h. --- winsup/cygwin/ChangeLog | 29 ++++++++++++++ winsup/cygwin/autoload.cc | 1 + winsup/cygwin/cygheap.cc | 1 + winsup/cygwin/grp.cc | 95 ++++++++++++++++++++++++++------------------- winsup/cygwin/passwd.cc | 12 ++++++ winsup/cygwin/sec_acl.cc | 54 +++++++++----------------- winsup/cygwin/sec_helper.cc | 48 +++++++---------------- winsup/cygwin/security.cc | 34 +++++++--------- winsup/cygwin/security.h | 37 ++++++++++++++++++ winsup/cygwin/shared.cc | 5 +-- winsup/cygwin/syscalls.cc | 60 +++++++++++++++++++++++++--- winsup/cygwin/uinfo.cc | 52 +++++++++++++++++-------- winsup/cygwin/winsup.h | 1 - 13 files changed, 276 insertions(+), 153 deletions(-) (limited to 'winsup') diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b520edc..84c1b15 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,32 @@ +Tue Apr 25 11:08:00 2001 Corinna Vinschen + + * autoload.cc: Add LoadDLLfunc statements for SetTokenInformation@16. + * cygheap.cc: Include security.h. + * grp.cc (internal_getgrent): New function. + (getgroups): Rearranged using `internal_getgrent' and the new + `cygsid' class. + * passwd.cc (internal_getpwent): New function. + * sec_acl.cc: Use new `cygsid' class throughout. + (acl_access): Use `internal_getgrent' instead of `getgrent'. + * sec_helper.cc: Use new `cygsid' class throughout. + (get_id_from_sid): Use `internal_getgrent' instead of `getgrent'. + Use `internal_getpwent' instead of `getpwent'. + * security.cc: Use new `cygsid' class throughout. + * security.h: Move `MAX_SID_LEN' from winsup.h to here. + Add extern declarations for `internal_getgrent' and `internal_getpwent'. + (class cygsid): New class. + * shared.cc (sec_user): Use new `cygsid' class. + * syscalls.cc (seteuid): Try to set owner to user and primary group to + current group in impersonation token before performing impersonation. + (setegid): Try to set primary group in process token to the new group + if ntsec is on. + * uinfo.cc (internal_getlogin): Use new `cygsid' class. + Try to set owner to user and primary group to current group in process + token if the process has been started from a non cygwin process. + (uinfo_init): Set primary group only if the process has been started + from a non cygwin process. + * winsup.h: Move define for `MAX_SID_LEN' to security.h. + Mon Apr 16 23:20:00 2001 Andy Younger * fhandler_dsp.cc: Improved handling of 8 bit playback modes. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 8a99ea5..3748539 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -318,6 +318,7 @@ LoadDLLfunc (SetSecurityDescriptorControl, 12, advapi32) LoadDLLfunc (SetSecurityDescriptorDacl, 16, advapi32) LoadDLLfunc (SetSecurityDescriptorGroup, 12, advapi32) LoadDLLfunc (SetSecurityDescriptorOwner, 12, advapi32) +LoadDLLfunc (SetTokenInformation, 16, advapi32) LoadDLLinit (netapi32) LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 24df5a9..bfba14e 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -20,6 +20,7 @@ #include "cygerrno.h" #include "sync.h" #include "shared_info.h" +#include "security.h" init_cygheap NO_COPY *cygheap; void NO_COPY *cygheap_max = NULL; diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc index 9b068f7..2cd8b5e 100644 --- a/winsup/cygwin/grp.cc +++ b/winsup/cygwin/grp.cc @@ -258,69 +258,86 @@ setgrent () grp_pos = 0; } +/* Internal function. ONLY USE THIS INTERNALLY, NEVER `getgrent'!!! */ +struct group * +internal_getgrent (int pos) +{ + if (group_state <= initializing) + read_etc_group(); + + if (pos < curr_lines) + return group_buf + pos; + return NULL; +} + int getgroups (int gidsetsize, gid_t *grouplist, gid_t gid, const char *username) { HANDLE hToken = NULL; - char buf[4096]; DWORD size; int cnt = 0; + struct group *gr; if (group_state <= initializing) read_etc_group(); if (allow_ntsec && - OpenProcessToken (hMainProc, TOKEN_QUERY, &hToken) && - GetTokenInformation (hToken, TokenGroups, buf, 4096, &size)) + OpenProcessToken (hMainProc, TOKEN_QUERY, &hToken)) { - TOKEN_GROUPS *groups = (TOKEN_GROUPS *) buf; - char ssid[MAX_SID_LEN]; - PSID sid = (PSID) ssid; - - for (DWORD pg = 0; pg < groups->GroupCount; ++pg) + if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size) + || GetLastError () == ERROR_INSUFFICIENT_BUFFER) { - struct group *gr; - while ((gr = getgrent ()) != NULL) + char buf[size]; + TOKEN_GROUPS *groups = (TOKEN_GROUPS *) buf; + + if (GetTokenInformation (hToken, TokenGroups, buf, size, &size)) { - if (get_gr_sid (sid, gr) && - EqualSid (sid, groups->Groups[pg].Sid)) - { - if (cnt < gidsetsize) - grouplist[cnt] = gr->gr_gid; - ++cnt; - if (gidsetsize && cnt > gidsetsize) - goto error; - break; - } + cygsid sid; + + for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx) + if (get_gr_sid (sid, gr)) + for (DWORD pg = 0; pg < groups->GroupCount; ++pg) + if (sid == groups->Groups[pg].Sid) + { + if (cnt < gidsetsize) + grouplist[cnt] = gr->gr_gid; + ++cnt; + if (gidsetsize && cnt > gidsetsize) + { + CloseHandle (hToken); + goto error; + } + break; + } } - endgrent (); } + else + debug_printf ("%d = GetTokenInformation(NULL) %E", size); CloseHandle (hToken); - return cnt; + if (cnt) + return cnt; } - else - { - for (int i = 0; i < curr_lines; ++i) - if (gid == group_buf[i].gr_gid) + + for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx) + if (gid == gr->gr_gid) + { + if (cnt < gidsetsize) + grouplist[cnt] = gr->gr_gid; + ++cnt; + if (gidsetsize && cnt > gidsetsize) + goto error; + } + else if (gr->gr_mem) + for (int gi = 0; gr->gr_mem[gi]; ++gi) + if (strcasematch (username, gr->gr_mem[gi])) { if (cnt < gidsetsize) - grouplist[cnt] = group_buf[i].gr_gid; + grouplist[cnt] = gr->gr_gid; ++cnt; if (gidsetsize && cnt > gidsetsize) goto error; } - else if (group_buf[i].gr_mem) - for (int gi = 0; group_buf[i].gr_mem[gi]; ++gi) - if (strcasematch (username, group_buf[i].gr_mem[gi])) - { - if (cnt < gidsetsize) - grouplist[cnt] = group_buf[i].gr_gid; - ++cnt; - if (gidsetsize && cnt > gidsetsize) - goto error; - } - return cnt; - } + return cnt; error: set_errno (EINVAL); diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc index 8440864..3b6494c 100644 --- a/winsup/cygwin/passwd.cc +++ b/winsup/cygwin/passwd.cc @@ -359,6 +359,18 @@ setpassent () return 0; } +/* Internal function. ONLY USE THIS INTERNALLY, NEVER `getpwent'!!! */ +struct passwd * +internal_getpwent (int pos) +{ + if (passwd_state <= initializing) + read_etc_passwd (); + + if (pos < curr_lines) + return passwd_buf + pos; + return NULL; +} + extern "C" char * getpass (const char * prompt) { diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc index 0ae0a69..f4d004c 100644 --- a/winsup/cygwin/sec_acl.cc +++ b/winsup/cygwin/sec_acl.cc @@ -68,13 +68,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) __seterrno (); return -1; } - char owner_buf[MAX_SID_LEN]; - if (!CopySid (MAX_SID_LEN, (PSID) owner_buf, owner_sid)) - { - __seterrno (); - return -1; - } - owner_sid = (PSID) owner_buf; + cygsid owner (owner_sid); /* Get group SID. */ PSID group_sid = NULL; @@ -83,13 +77,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) __seterrno (); return -1; } - char group_buf[MAX_SID_LEN]; - if (!CopySid (MAX_SID_LEN, (PSID) group_buf, group_sid)) - { - __seterrno (); - return -1; - } - group_sid = (PSID) group_buf; + cygsid group (group_sid); /* Initialize local security descriptor. */ SECURITY_DESCRIPTOR sd; @@ -98,13 +86,13 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) __seterrno (); return -1; } - if (!SetSecurityDescriptorOwner(&sd, owner_sid, FALSE)) + if (!SetSecurityDescriptorOwner(&sd, owner, FALSE)) { __seterrno (); return -1; } - if (group_sid - && !SetSecurityDescriptorGroup(&sd, group_sid, FALSE)) + if (group + && !SetSecurityDescriptorGroup(&sd, group, FALSE)) { __seterrno (); return -1; @@ -116,8 +104,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) size_t acl_len = sizeof (ACL); int ace_off = 0; - char sidbuf[MAX_SID_LEN]; - PSID sid = (PSID) sidbuf; + cygsid sid; struct passwd *pw; struct group *gr; int pos; @@ -164,7 +151,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) case DEF_USER_OBJ: allow |= STANDARD_RIGHTS_ALL & ~DELETE; if (!add_access_allowed_ace (acl, ace_off++, allow, - owner_sid, acl_len, inheritance)) + owner, acl_len, inheritance)) return -1; break; case USER: @@ -178,7 +165,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) case GROUP_OBJ: case DEF_GROUP_OBJ: if (!add_access_allowed_ace (acl, ace_off++, allow, - group_sid, acl_len, inheritance)) + group, acl_len, inheritance)) return -1; break; case GROUP: @@ -320,21 +307,21 @@ getacl (const char *file, DWORD attr, int nentries, aclent_t *aclbufp) if (!GetAce (acl, i, (PVOID *) &ace)) continue; - PSID ace_sid = (PSID) &ace->SidStart; + cygsid ace_sid ((PSID) &ace->SidStart); int id; int type = 0; - if (EqualSid (ace_sid, owner_sid)) + if (ace_sid == owner_sid) { type = USER_OBJ; id = uid; } - else if (EqualSid (ace_sid, group_sid)) + else if (ace_sid == group_sid) { type = GROUP_OBJ; id = gid; } - else if (EqualSid (ace_sid, get_world_sid ())) + else if (ace_sid == get_world_sid ()) { type = OTHER_OBJ; id = 0; @@ -431,23 +418,20 @@ acl_access (const char *path, int flags) * Check if user is a NT group: * Take SID from passwd, search SID in group, check is_grp_member. */ - char owner_sidbuf[MAX_SID_LEN]; - PSID owner_sid = (PSID) owner_sidbuf; - char group_sidbuf[MAX_SID_LEN]; - PSID group_sid = (PSID) group_sidbuf; + cygsid owner; + cygsid group; struct passwd *pw; struct group *gr = NULL; if ((pw = getpwuid (acls[i].a_id)) != NULL - && get_pw_sid (owner_sid, pw)) + && get_pw_sid (owner, pw)) { - while ((gr = getgrent ())) - if (get_gr_sid (group_sid, gr) - && EqualSid (owner_sid, group_sid) + for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx) + if (get_gr_sid (group, gr) + && owner == group && is_grp_member (myself->uid, gr->gr_gid)) break; - endgrent (); - } + } if (!gr) continue; } diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index 19ab471..d360641 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -120,56 +120,40 @@ get_gr_sid (PSID sid, struct group *gr) PSID get_admin_sid () { - static NO_COPY char admin_sid_buf[MAX_SID_LEN]; - static NO_COPY PSID admin_sid = NULL; + static NO_COPY cygsid admin_sid (NULL); if (!admin_sid) - { - admin_sid = (PSID) admin_sid_buf; - convert_string_sid_to_sid (admin_sid, "S-1-5-32-544"); - } + convert_string_sid_to_sid (admin_sid.set (), "S-1-5-32-544"); return admin_sid; } PSID get_system_sid () { - static NO_COPY char system_sid_buf[MAX_SID_LEN]; - static NO_COPY PSID system_sid = NULL; + static NO_COPY cygsid system_sid (NULL); if (!system_sid) - { - system_sid = (PSID) system_sid_buf; - convert_string_sid_to_sid (system_sid, "S-1-5-18"); - } + convert_string_sid_to_sid (system_sid.set (), "S-1-5-18"); return system_sid; } PSID get_creator_owner_sid () { - static NO_COPY char owner_sid_buf[MAX_SID_LEN]; - static NO_COPY PSID owner_sid = NULL; + static NO_COPY cygsid owner_sid (NULL); if (!owner_sid) - { - owner_sid = (PSID) owner_sid_buf; - convert_string_sid_to_sid (owner_sid, "S-1-3-0"); - } + convert_string_sid_to_sid (owner_sid.set (), "S-1-3-0"); return owner_sid; } PSID get_world_sid () { - static NO_COPY char world_sid_buf[MAX_SID_LEN]; - static NO_COPY PSID world_sid = NULL; + static NO_COPY cygsid world_sid (NULL); if (!world_sid) - { - world_sid = (PSID) world_sid_buf; - convert_string_sid_to_sid (world_sid, "S-1-1-0"); - } + convert_string_sid_to_sid (world_sid.set (), "S-1-1-0"); return world_sid; } @@ -186,22 +170,20 @@ get_id_from_sid (PSID psid, BOOL search_grp, int *type) /* First try to get SID from passwd or group entry */ if (allow_ntsec) { - char sidbuf[MAX_SID_LEN]; - PSID sid = (PSID) sidbuf; + cygsid sid; int id = -1; if (!search_grp) { struct passwd *pw; - while ((pw = getpwent ()) != NULL) + for (int pidx = 0; (pw = internal_getpwent (pidx)); ++pidx) { - if (get_pw_sid (sid, pw) && EqualSid (psid, sid)) + if (get_pw_sid (sid, pw) && sid == psid) { id = pw->pw_uid; break; } } - endpwent (); if (id >= 0) { if (type) @@ -212,15 +194,14 @@ get_id_from_sid (PSID psid, BOOL search_grp, int *type) if (search_grp || type) { struct group *gr; - while ((gr = getgrent ()) != NULL) + for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx) { - if (get_gr_sid (sid, gr) && EqualSid (psid, sid)) + if (get_gr_sid (sid, gr) && sid == psid) { id = gr->gr_gid; break; } } - endgrent (); if (id >= 0) { if (type) @@ -321,8 +302,7 @@ is_grp_member (uid_t uid, gid_t gid) BOOL lookup_name (const char *name, const char *logsrv, PSID ret_sid) { - char sidbuf[MAX_SID_LEN]; - PSID sid = (PSID) sidbuf; + cygsid sid; DWORD sidlen; char domuser[MAX_COMPUTERNAME_LENGTH+MAX_USER_NAME+1]; char dom[MAX_COMPUTERNAME_LENGTH+1]; diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 33d466e..c814379 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -333,8 +333,8 @@ get_nt_attribute (const char *file, int *attribute, continue; } - PSID ace_sid = (PSID) &ace->SidStart; - if (owner_sid && EqualSid (ace_sid, owner_sid)) + cygsid ace_sid ((PSID) &ace->SidStart); + if (owner_sid && ace_sid == owner_sid) { if (ace->Mask & FILE_READ_DATA) *flags |= S_IRUSR; @@ -343,7 +343,7 @@ get_nt_attribute (const char *file, int *attribute, if (ace->Mask & FILE_EXECUTE) *flags |= S_IXUSR; } - else if (group_sid && EqualSid (ace_sid, group_sid)) + else if (group_sid && ace_sid == group_sid) { if (ace->Mask & FILE_READ_DATA) *flags |= S_IRGRP @@ -355,7 +355,7 @@ get_nt_attribute (const char *file, int *attribute, *flags |= S_IXGRP | ((grp_member && !(*anti & S_IXUSR)) ? S_IXUSR : 0); } - else if (EqualSid (ace_sid, get_world_sid ())) + else if (ace_sid == get_world_sid ()) { if (ace->Mask & FILE_READ_DATA) *flags |= S_IROTH @@ -469,26 +469,22 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, /* Get SID and name of new owner. */ char owner[MAX_USER_NAME]; - char *owner_sid_buf[MAX_SID_LEN]; - PSID owner_sid = NULL; + cygsid owner_sid; struct passwd *pw = getpwuid (uid); strcpy (owner, pw ? pw->pw_name : getlogin ()); - owner_sid = (PSID) owner_sid_buf; if ((!pw || !get_pw_sid (owner_sid, pw)) && !lookup_name (owner, logsrv, owner_sid)) return NULL; debug_printf ("owner: %s [%d]", owner, - *GetSidSubAuthority((PSID) owner_sid, - *GetSidSubAuthorityCount((PSID) owner_sid) - 1)); + *GetSidSubAuthority(owner_sid, + *GetSidSubAuthorityCount(owner_sid) - 1)); /* Get SID and name of new group. */ - char *group_sid_buf[MAX_SID_LEN]; - PSID group_sid = NULL; + cygsid group_sid (NULL); struct group *grp = getgrgid (gid); if (grp) { - group_sid = (PSID) group_sid_buf; - if ((!grp || !get_gr_sid (group_sid, grp)) + if ((!grp || !get_gr_sid (group_sid.set (), grp)) && !lookup_name (grp->gr_name, logsrv, group_sid)) return NULL; } @@ -643,13 +639,13 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, for (DWORD i = 0; i < oacl->AceCount; ++i) if (GetAce (oacl, i, (PVOID *) &ace)) { - PSID ace_sid = (PSID) &ace->SidStart; + cygsid ace_sid ((PSID) &ace->SidStart); /* Check for related ACEs. */ - if ((cur_owner_sid && EqualSid (ace_sid, cur_owner_sid)) - || (owner_sid && EqualSid (ace_sid, owner_sid)) - || (cur_group_sid && EqualSid (ace_sid, cur_group_sid)) - || (group_sid && EqualSid (ace_sid, group_sid)) - || (EqualSid (ace_sid, get_world_sid ()))) + if ((cur_owner_sid && ace_sid == cur_owner_sid) + || (owner_sid && ace_sid == owner_sid) + || (cur_group_sid && ace_sid == cur_group_sid) + || (group_sid && ace_sid == group_sid) + || (ace_sid == get_world_sid ())) continue; /* * Add unrelated ACCESS_DENIED_ACE to the beginning but diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 3c1f75f..98545b6 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -12,9 +12,46 @@ details. */ #define INHERIT_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE) #define INHERIT_ONLY (INHERIT_ONLY_ACE|CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE) +#define MAX_SID_LEN 40 + +class cygsid { + PSID psid; + char sbuf[MAX_SID_LEN]; +public: + inline cygsid () : psid ((PSID) sbuf) {} + inline cygsid (PSID nsid) { *this = nsid; } + + inline PSID set () { return psid = (PSID) sbuf; } + + inline const PSID operator= (PSID nsid) + { + if (!nsid) + psid = NULL; + else + { + psid = (PSID) sbuf; + CopySid (MAX_SID_LEN, psid, nsid); + } + return psid; + } + inline BOOL operator== (PSID nsid) + { + if (!psid || !nsid) + return nsid == psid; + return EqualSid (psid, nsid); + } + inline operator const PSID () { return psid; } +}; + extern BOOL allow_ntsec; extern BOOL allow_smbntsec; +/* These both functions are needed to allow walking through the passwd + and group lists so they are somehow security related. Besides that + I didn't find a better place to declare them. */ +extern struct passwd *internal_getpwent (int); +extern struct group *internal_getgrent (int); + /* File manipulation */ int __stdcall set_process_privileges (); int __stdcall get_file_attribute (int, const char *, int *, diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index b86d68b..599685c 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -239,11 +239,10 @@ sec_user (PVOID sa_buf, PSID sid2, BOOL inherit) ((char *) sa_buf + sizeof (*psa)); PACL acl = (PACL) ((char *) sa_buf + sizeof (*psa) + sizeof (*psd)); - char sid_buf[MAX_SID_LEN]; - PSID sid = (PSID) sid_buf; + cygsid sid; if (cygheap->user.sid ()) - CopySid (MAX_SID_LEN, sid, (void *) cygheap->user.sid ()); + sid = cygheap->user.sid (); else if (! lookup_name (getlogin (), cygheap->user.logsrv (), sid)) return inherit ? &sec_none_nih : &sec_none; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 191b3a9..142873b 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1977,11 +1977,36 @@ seteuid (uid_t uid) debug_printf ("Impersonate (uid == %d)", uid); RevertToSelf (); if (cygheap->user.token != INVALID_HANDLE_VALUE) - if (!ImpersonateLoggedOnUser (cygheap->user.token)) - system_printf ("Impersonate (%d) in set (e)uid failed: %E", - cygheap->user.token); - else - cygheap->user.impersonated = TRUE; + { + struct group *gr; + cygsid sid; + DWORD siz; + + /* Try setting owner to same value as user. */ + if (!GetTokenInformation (cygheap->user.token, TokenUser, + &sid, sizeof sid, &siz)) + debug_printf ("GetTokenInformation(): %E"); + else if (!SetTokenInformation (cygheap->user.token, + TokenOwner, + &sid, sizeof sid)) + debug_printf ("SetTokenInformation(user.token, " + "TokenOwner): %E"); + /* Try setting primary group in token to current group. */ + if ((gr = getgrgid (myself->gid)) && + get_gr_sid (sid, gr) && + !SetTokenInformation (cygheap->user.token, + TokenPrimaryGroup, + &sid, sizeof sid)) + debug_printf ("SetTokenInformation(user.token, " + "TokenPrimaryGroup): %E"); + + /* Now try to impersonate. */ + if (!ImpersonateLoggedOnUser (cygheap->user.token)) + system_printf ("Impersonate (%d) in set(e)uid failed: %E", + cygheap->user.token); + else + cygheap->user.impersonated = TRUE; + } } cygheap_user user; @@ -2018,12 +2043,35 @@ setegid (gid_t gid) { if (gid != (gid_t) -1) { - if (!getgrgid (gid)) + struct group *gr; + + if (!(gr = getgrgid (gid))) { set_errno (EINVAL); return -1; } myself->gid = gid; + if (allow_ntsec) + { + cygsid gsid; + HANDLE ptok; + + if (get_gr_sid (gsid, gr)) + { + if (!OpenProcessToken (GetCurrentProcess (), + TOKEN_ADJUST_DEFAULT, + &ptok)) + debug_printf ("OpenProcessToken(): %E\n"); + else + { + if (!SetTokenInformation (ptok, TokenPrimaryGroup, + &gsid, sizeof gsid)) + debug_printf ("SetTokenInformation(myself, " + "TokenPrimaryGroup): %E"); + CloseHandle (ptok); + } + } + } } } else diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index 6bf5deb..eb3f6ff 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -115,7 +115,7 @@ internal_getlogin (cygheap_user &user) HANDLE ptok = user.token; /* Which is INVALID_HANDLE_VALUE if no impersonation took place. */ DWORD siz; - char tu[1024]; + cygsid tu; int ret = 0; /* Try to get the SID either from already impersonated token @@ -123,18 +123,14 @@ internal_getlogin (cygheap_user &user) important, because you can't rely on the user information in a process token of a currently impersonated process. */ if (ptok == INVALID_HANDLE_VALUE - && !OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &ptok)) + && !OpenProcessToken (GetCurrentProcess (), + TOKEN_ADJUST_DEFAULT | TOKEN_QUERY, + &ptok)) debug_printf ("OpenProcessToken(): %E\n"); - else if (!GetTokenInformation (ptok, TokenUser, (LPVOID) &tu, - sizeof tu, &siz)) + else if (!GetTokenInformation (ptok, TokenUser, &tu, sizeof tu, &siz)) debug_printf ("GetTokenInformation(): %E"); - else if (!(ret = user.set_sid (((TOKEN_USER *) &tu)->User.Sid))) + else if (!(ret = user.set_sid (tu))) debug_printf ("Couldn't retrieve SID from access token!"); - /* Close token only if it's a result from OpenProcessToken(). */ - if (ptok != INVALID_HANDLE_VALUE - && user.token == INVALID_HANDLE_VALUE) - CloseHandle (ptok); - /* If that failes, try to get the SID from localhost. This can only be done if a domain is given because there's a chance that a local and a domain user may have the same name. */ @@ -146,7 +142,7 @@ internal_getlogin (cygheap_user &user) debug_printf ("Couldn't retrieve SID locally!"); } - /* If that failes, too, as a last resort try to get the SID from + /* If that fails, too, as a last resort try to get the SID from the logon server. */ if (!ret && !(ret = lookup_name (user.name (), user.logsrv (), user.sid ()))) @@ -154,11 +150,11 @@ internal_getlogin (cygheap_user &user) /* If we have a SID, try to get the corresponding Cygwin user name which can be different from the Windows user name. */ + cygsid gsid (NULL); if (ret) { struct passwd *pw; - char psidbuf[MAX_SID_LEN]; - PSID psid = (PSID) psidbuf; + cygsid psid; if (!strcasematch (user.name (), "SYSTEM") && user.domain () && user.logsrv ()) @@ -166,14 +162,35 @@ internal_getlogin (cygheap_user &user) if (get_registry_hive_path (user.sid (), buf)) setenv ("USERPROFILE", buf, 1); } - while ((pw = getpwent ()) != NULL) + for (int pidx = 0; (pw = internal_getpwent (pidx)); ++pidx) if (get_pw_sid (psid, pw) && EqualSid (user.sid (), psid)) { user.set_name (pw->pw_name); + struct group *gr = getgrgid (pw->pw_gid); + if (gr) + if (!get_gr_sid (gsid.set (), gr)) + gsid = NULL; break; } - endpwent (); } + + /* If this process is started from a non Cygwin process, + set token owner to the same value as token user and + primary group to the group which is set as primary group + in /etc/passwd. */ + if (ptok != INVALID_HANDLE_VALUE && myself->ppid == 1) + { + 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"); + } + + /* Close token only if it's a result from OpenProcessToken(). */ + if (ptok != INVALID_HANDLE_VALUE + && user.token == INVALID_HANDLE_VALUE) + CloseHandle (ptok); } } debug_printf ("Cygwins Username: %s", user.name ()); @@ -198,7 +215,10 @@ uinfo_init () if ((p = getpwnam (internal_getlogin (cygheap->user))) != NULL) { myself->uid = p->pw_uid; - myself->gid = p->pw_gid; + /* Set primary group only if ntsec is off or the process has been + started from a non cygwin process. */ + if (!allow_ntsec || myself->ppid == 1) + myself->gid = p->pw_gid; } else { diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 51c340d..85fda80 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -101,7 +101,6 @@ extern int dynamically_loaded; #define DEFAULT_UID 500 #define DEFAULT_GID 544 -#define MAX_SID_LEN 40 #define MAX_HOST_NAME 256 /* status bit manipulation */ -- cgit v1.1