aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog29
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/cygheap.cc1
-rw-r--r--winsup/cygwin/grp.cc95
-rw-r--r--winsup/cygwin/passwd.cc12
-rw-r--r--winsup/cygwin/sec_acl.cc54
-rw-r--r--winsup/cygwin/sec_helper.cc48
-rw-r--r--winsup/cygwin/security.cc34
-rw-r--r--winsup/cygwin/security.h37
-rw-r--r--winsup/cygwin/shared.cc5
-rw-r--r--winsup/cygwin/syscalls.cc60
-rw-r--r--winsup/cygwin/uinfo.cc52
-rw-r--r--winsup/cygwin/winsup.h1
13 files changed, 276 insertions, 153 deletions
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 <corinna@vinschen.de>
+
+ * 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 <andylyounger@hotmail.com>
* 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 */