* 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.
This commit is contained in:
Corinna Vinschen 2001-04-25 09:43:25 +00:00
parent 3a6e96682d
commit d551169a9f
13 changed files with 276 additions and 153 deletions

View File

@ -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> Mon Apr 16 23:20:00 2001 Andy Younger <andylyounger@hotmail.com>
* fhandler_dsp.cc: Improved handling of 8 bit playback modes. * fhandler_dsp.cc: Improved handling of 8 bit playback modes.

View File

@ -318,6 +318,7 @@ LoadDLLfunc (SetSecurityDescriptorControl, 12, advapi32)
LoadDLLfunc (SetSecurityDescriptorDacl, 16, advapi32) LoadDLLfunc (SetSecurityDescriptorDacl, 16, advapi32)
LoadDLLfunc (SetSecurityDescriptorGroup, 12, advapi32) LoadDLLfunc (SetSecurityDescriptorGroup, 12, advapi32)
LoadDLLfunc (SetSecurityDescriptorOwner, 12, advapi32) LoadDLLfunc (SetSecurityDescriptorOwner, 12, advapi32)
LoadDLLfunc (SetTokenInformation, 16, advapi32)
LoadDLLinit (netapi32) LoadDLLinit (netapi32)
LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32) LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)

View File

@ -20,6 +20,7 @@
#include "cygerrno.h" #include "cygerrno.h"
#include "sync.h" #include "sync.h"
#include "shared_info.h" #include "shared_info.h"
#include "security.h"
init_cygheap NO_COPY *cygheap; init_cygheap NO_COPY *cygheap;
void NO_COPY *cygheap_max = NULL; void NO_COPY *cygheap_max = NULL;

View File

@ -258,69 +258,86 @@ setgrent ()
grp_pos = 0; 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 int
getgroups (int gidsetsize, gid_t *grouplist, gid_t gid, const char *username) getgroups (int gidsetsize, gid_t *grouplist, gid_t gid, const char *username)
{ {
HANDLE hToken = NULL; HANDLE hToken = NULL;
char buf[4096];
DWORD size; DWORD size;
int cnt = 0; int cnt = 0;
struct group *gr;
if (group_state <= initializing) if (group_state <= initializing)
read_etc_group(); read_etc_group();
if (allow_ntsec && if (allow_ntsec &&
OpenProcessToken (hMainProc, TOKEN_QUERY, &hToken) && OpenProcessToken (hMainProc, TOKEN_QUERY, &hToken))
GetTokenInformation (hToken, TokenGroups, buf, 4096, &size))
{ {
if (GetTokenInformation (hToken, TokenGroups, NULL, 0, &size)
|| GetLastError () == ERROR_INSUFFICIENT_BUFFER)
{
char buf[size];
TOKEN_GROUPS *groups = (TOKEN_GROUPS *) buf; TOKEN_GROUPS *groups = (TOKEN_GROUPS *) buf;
char ssid[MAX_SID_LEN];
PSID sid = (PSID) ssid;
if (GetTokenInformation (hToken, TokenGroups, buf, size, &size))
{
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) for (DWORD pg = 0; pg < groups->GroupCount; ++pg)
if (sid == groups->Groups[pg].Sid)
{ {
struct group *gr; if (cnt < gidsetsize)
while ((gr = getgrent ()) != NULL) grouplist[cnt] = gr->gr_gid;
++cnt;
if (gidsetsize && cnt > gidsetsize)
{ {
if (get_gr_sid (sid, gr) && CloseHandle (hToken);
EqualSid (sid, groups->Groups[pg].Sid)) goto error;
}
break;
}
}
}
else
debug_printf ("%d = GetTokenInformation(NULL) %E", size);
CloseHandle (hToken);
if (cnt)
return cnt;
}
for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
if (gid == gr->gr_gid)
{ {
if (cnt < gidsetsize) if (cnt < gidsetsize)
grouplist[cnt] = gr->gr_gid; grouplist[cnt] = gr->gr_gid;
++cnt; ++cnt;
if (gidsetsize && cnt > gidsetsize) if (gidsetsize && cnt > gidsetsize)
goto error; goto error;
break;
} }
} else if (gr->gr_mem)
endgrent (); for (int gi = 0; gr->gr_mem[gi]; ++gi)
} if (strcasematch (username, gr->gr_mem[gi]))
CloseHandle (hToken);
return cnt;
}
else
{
for (int i = 0; i < curr_lines; ++i)
if (gid == group_buf[i].gr_gid)
{ {
if (cnt < gidsetsize) 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; ++cnt;
if (gidsetsize && cnt > gidsetsize) if (gidsetsize && cnt > gidsetsize)
goto error; goto error;
} }
return cnt; return cnt;
}
error: error:
set_errno (EINVAL); set_errno (EINVAL);

View File

@ -359,6 +359,18 @@ setpassent ()
return 0; 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 * extern "C" char *
getpass (const char * prompt) getpass (const char * prompt)
{ {

View File

@ -68,13 +68,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp)
__seterrno (); __seterrno ();
return -1; return -1;
} }
char owner_buf[MAX_SID_LEN]; cygsid owner (owner_sid);
if (!CopySid (MAX_SID_LEN, (PSID) owner_buf, owner_sid))
{
__seterrno ();
return -1;
}
owner_sid = (PSID) owner_buf;
/* Get group SID. */ /* Get group SID. */
PSID group_sid = NULL; PSID group_sid = NULL;
@ -83,13 +77,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp)
__seterrno (); __seterrno ();
return -1; return -1;
} }
char group_buf[MAX_SID_LEN]; cygsid group (group_sid);
if (!CopySid (MAX_SID_LEN, (PSID) group_buf, group_sid))
{
__seterrno ();
return -1;
}
group_sid = (PSID) group_buf;
/* Initialize local security descriptor. */ /* Initialize local security descriptor. */
SECURITY_DESCRIPTOR sd; SECURITY_DESCRIPTOR sd;
@ -98,13 +86,13 @@ setacl (const char *file, int nentries, aclent_t *aclbufp)
__seterrno (); __seterrno ();
return -1; return -1;
} }
if (!SetSecurityDescriptorOwner(&sd, owner_sid, FALSE)) if (!SetSecurityDescriptorOwner(&sd, owner, FALSE))
{ {
__seterrno (); __seterrno ();
return -1; return -1;
} }
if (group_sid if (group
&& !SetSecurityDescriptorGroup(&sd, group_sid, FALSE)) && !SetSecurityDescriptorGroup(&sd, group, FALSE))
{ {
__seterrno (); __seterrno ();
return -1; return -1;
@ -116,8 +104,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp)
size_t acl_len = sizeof (ACL); size_t acl_len = sizeof (ACL);
int ace_off = 0; int ace_off = 0;
char sidbuf[MAX_SID_LEN]; cygsid sid;
PSID sid = (PSID) sidbuf;
struct passwd *pw; struct passwd *pw;
struct group *gr; struct group *gr;
int pos; int pos;
@ -164,7 +151,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp)
case DEF_USER_OBJ: case DEF_USER_OBJ:
allow |= STANDARD_RIGHTS_ALL & ~DELETE; allow |= STANDARD_RIGHTS_ALL & ~DELETE;
if (!add_access_allowed_ace (acl, ace_off++, allow, if (!add_access_allowed_ace (acl, ace_off++, allow,
owner_sid, acl_len, inheritance)) owner, acl_len, inheritance))
return -1; return -1;
break; break;
case USER: case USER:
@ -178,7 +165,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp)
case GROUP_OBJ: case GROUP_OBJ:
case DEF_GROUP_OBJ: case DEF_GROUP_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow, if (!add_access_allowed_ace (acl, ace_off++, allow,
group_sid, acl_len, inheritance)) group, acl_len, inheritance))
return -1; return -1;
break; break;
case GROUP: case GROUP:
@ -320,21 +307,21 @@ getacl (const char *file, DWORD attr, int nentries, aclent_t *aclbufp)
if (!GetAce (acl, i, (PVOID *) &ace)) if (!GetAce (acl, i, (PVOID *) &ace))
continue; continue;
PSID ace_sid = (PSID) &ace->SidStart; cygsid ace_sid ((PSID) &ace->SidStart);
int id; int id;
int type = 0; int type = 0;
if (EqualSid (ace_sid, owner_sid)) if (ace_sid == owner_sid)
{ {
type = USER_OBJ; type = USER_OBJ;
id = uid; id = uid;
} }
else if (EqualSid (ace_sid, group_sid)) else if (ace_sid == group_sid)
{ {
type = GROUP_OBJ; type = GROUP_OBJ;
id = gid; id = gid;
} }
else if (EqualSid (ace_sid, get_world_sid ())) else if (ace_sid == get_world_sid ())
{ {
type = OTHER_OBJ; type = OTHER_OBJ;
id = 0; id = 0;
@ -431,22 +418,19 @@ acl_access (const char *path, int flags)
* Check if user is a NT group: * Check if user is a NT group:
* Take SID from passwd, search SID in group, check is_grp_member. * Take SID from passwd, search SID in group, check is_grp_member.
*/ */
char owner_sidbuf[MAX_SID_LEN]; cygsid owner;
PSID owner_sid = (PSID) owner_sidbuf; cygsid group;
char group_sidbuf[MAX_SID_LEN];
PSID group_sid = (PSID) group_sidbuf;
struct passwd *pw; struct passwd *pw;
struct group *gr = NULL; struct group *gr = NULL;
if ((pw = getpwuid (acls[i].a_id)) != NULL if ((pw = getpwuid (acls[i].a_id)) != NULL
&& get_pw_sid (owner_sid, pw)) && get_pw_sid (owner, pw))
{ {
while ((gr = getgrent ())) for (int gidx = 0; (gr = internal_getgrent (gidx)); ++gidx)
if (get_gr_sid (group_sid, gr) if (get_gr_sid (group, gr)
&& EqualSid (owner_sid, group_sid) && owner == group
&& is_grp_member (myself->uid, gr->gr_gid)) && is_grp_member (myself->uid, gr->gr_gid))
break; break;
endgrent ();
} }
if (!gr) if (!gr)
continue; continue;

View File

@ -120,56 +120,40 @@ get_gr_sid (PSID sid, struct group *gr)
PSID PSID
get_admin_sid () get_admin_sid ()
{ {
static NO_COPY char admin_sid_buf[MAX_SID_LEN]; static NO_COPY cygsid admin_sid (NULL);
static NO_COPY PSID admin_sid = NULL;
if (!admin_sid) if (!admin_sid)
{ convert_string_sid_to_sid (admin_sid.set (), "S-1-5-32-544");
admin_sid = (PSID) admin_sid_buf;
convert_string_sid_to_sid (admin_sid, "S-1-5-32-544");
}
return admin_sid; return admin_sid;
} }
PSID PSID
get_system_sid () get_system_sid ()
{ {
static NO_COPY char system_sid_buf[MAX_SID_LEN]; static NO_COPY cygsid system_sid (NULL);
static NO_COPY PSID system_sid = NULL;
if (!system_sid) if (!system_sid)
{ convert_string_sid_to_sid (system_sid.set (), "S-1-5-18");
system_sid = (PSID) system_sid_buf;
convert_string_sid_to_sid (system_sid, "S-1-5-18");
}
return system_sid; return system_sid;
} }
PSID PSID
get_creator_owner_sid () get_creator_owner_sid ()
{ {
static NO_COPY char owner_sid_buf[MAX_SID_LEN]; static NO_COPY cygsid owner_sid (NULL);
static NO_COPY PSID owner_sid = NULL;
if (!owner_sid) if (!owner_sid)
{ convert_string_sid_to_sid (owner_sid.set (), "S-1-3-0");
owner_sid = (PSID) owner_sid_buf;
convert_string_sid_to_sid (owner_sid, "S-1-3-0");
}
return owner_sid; return owner_sid;
} }
PSID PSID
get_world_sid () get_world_sid ()
{ {
static NO_COPY char world_sid_buf[MAX_SID_LEN]; static NO_COPY cygsid world_sid (NULL);
static NO_COPY PSID world_sid = NULL;
if (!world_sid) if (!world_sid)
{ convert_string_sid_to_sid (world_sid.set (), "S-1-1-0");
world_sid = (PSID) world_sid_buf;
convert_string_sid_to_sid (world_sid, "S-1-1-0");
}
return world_sid; 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 */ /* First try to get SID from passwd or group entry */
if (allow_ntsec) if (allow_ntsec)
{ {
char sidbuf[MAX_SID_LEN]; cygsid sid;
PSID sid = (PSID) sidbuf;
int id = -1; int id = -1;
if (!search_grp) if (!search_grp)
{ {
struct passwd *pw; 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; id = pw->pw_uid;
break; break;
} }
} }
endpwent ();
if (id >= 0) if (id >= 0)
{ {
if (type) if (type)
@ -212,15 +194,14 @@ get_id_from_sid (PSID psid, BOOL search_grp, int *type)
if (search_grp || type) if (search_grp || type)
{ {
struct group *gr; 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; id = gr->gr_gid;
break; break;
} }
} }
endgrent ();
if (id >= 0) if (id >= 0)
{ {
if (type) if (type)
@ -321,8 +302,7 @@ is_grp_member (uid_t uid, gid_t gid)
BOOL BOOL
lookup_name (const char *name, const char *logsrv, PSID ret_sid) lookup_name (const char *name, const char *logsrv, PSID ret_sid)
{ {
char sidbuf[MAX_SID_LEN]; cygsid sid;
PSID sid = (PSID) sidbuf;
DWORD sidlen; DWORD sidlen;
char domuser[MAX_COMPUTERNAME_LENGTH+MAX_USER_NAME+1]; char domuser[MAX_COMPUTERNAME_LENGTH+MAX_USER_NAME+1];
char dom[MAX_COMPUTERNAME_LENGTH+1]; char dom[MAX_COMPUTERNAME_LENGTH+1];

View File

@ -333,8 +333,8 @@ get_nt_attribute (const char *file, int *attribute,
continue; continue;
} }
PSID ace_sid = (PSID) &ace->SidStart; cygsid ace_sid ((PSID) &ace->SidStart);
if (owner_sid && EqualSid (ace_sid, owner_sid)) if (owner_sid && ace_sid == owner_sid)
{ {
if (ace->Mask & FILE_READ_DATA) if (ace->Mask & FILE_READ_DATA)
*flags |= S_IRUSR; *flags |= S_IRUSR;
@ -343,7 +343,7 @@ get_nt_attribute (const char *file, int *attribute,
if (ace->Mask & FILE_EXECUTE) if (ace->Mask & FILE_EXECUTE)
*flags |= S_IXUSR; *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) if (ace->Mask & FILE_READ_DATA)
*flags |= S_IRGRP *flags |= S_IRGRP
@ -355,7 +355,7 @@ get_nt_attribute (const char *file, int *attribute,
*flags |= S_IXGRP *flags |= S_IXGRP
| ((grp_member && !(*anti & S_IXUSR)) ? S_IXUSR : 0); | ((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) if (ace->Mask & FILE_READ_DATA)
*flags |= S_IROTH *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. */ /* Get SID and name of new owner. */
char owner[MAX_USER_NAME]; char owner[MAX_USER_NAME];
char *owner_sid_buf[MAX_SID_LEN]; cygsid owner_sid;
PSID owner_sid = NULL;
struct passwd *pw = getpwuid (uid); struct passwd *pw = getpwuid (uid);
strcpy (owner, pw ? pw->pw_name : getlogin ()); strcpy (owner, pw ? pw->pw_name : getlogin ());
owner_sid = (PSID) owner_sid_buf;
if ((!pw || !get_pw_sid (owner_sid, pw)) if ((!pw || !get_pw_sid (owner_sid, pw))
&& !lookup_name (owner, logsrv, owner_sid)) && !lookup_name (owner, logsrv, owner_sid))
return NULL; return NULL;
debug_printf ("owner: %s [%d]", owner, debug_printf ("owner: %s [%d]", owner,
*GetSidSubAuthority((PSID) owner_sid, *GetSidSubAuthority(owner_sid,
*GetSidSubAuthorityCount((PSID) owner_sid) - 1)); *GetSidSubAuthorityCount(owner_sid) - 1));
/* Get SID and name of new group. */ /* Get SID and name of new group. */
char *group_sid_buf[MAX_SID_LEN]; cygsid group_sid (NULL);
PSID group_sid = NULL;
struct group *grp = getgrgid (gid); struct group *grp = getgrgid (gid);
if (grp) if (grp)
{ {
group_sid = (PSID) group_sid_buf; if ((!grp || !get_gr_sid (group_sid.set (), grp))
if ((!grp || !get_gr_sid (group_sid, grp))
&& !lookup_name (grp->gr_name, logsrv, group_sid)) && !lookup_name (grp->gr_name, logsrv, group_sid))
return NULL; 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) for (DWORD i = 0; i < oacl->AceCount; ++i)
if (GetAce (oacl, i, (PVOID *) &ace)) if (GetAce (oacl, i, (PVOID *) &ace))
{ {
PSID ace_sid = (PSID) &ace->SidStart; cygsid ace_sid ((PSID) &ace->SidStart);
/* Check for related ACEs. */ /* Check for related ACEs. */
if ((cur_owner_sid && EqualSid (ace_sid, cur_owner_sid)) if ((cur_owner_sid && ace_sid == cur_owner_sid)
|| (owner_sid && EqualSid (ace_sid, owner_sid)) || (owner_sid && ace_sid == owner_sid)
|| (cur_group_sid && EqualSid (ace_sid, cur_group_sid)) || (cur_group_sid && ace_sid == cur_group_sid)
|| (group_sid && EqualSid (ace_sid, group_sid)) || (group_sid && ace_sid == group_sid)
|| (EqualSid (ace_sid, get_world_sid ()))) || (ace_sid == get_world_sid ()))
continue; continue;
/* /*
* Add unrelated ACCESS_DENIED_ACE to the beginning but * Add unrelated ACCESS_DENIED_ACE to the beginning but

View File

@ -12,9 +12,46 @@ details. */
#define INHERIT_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE) #define INHERIT_ALL (CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
#define INHERIT_ONLY (INHERIT_ONLY_ACE|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_ntsec;
extern BOOL allow_smbntsec; 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 */ /* File manipulation */
int __stdcall set_process_privileges (); int __stdcall set_process_privileges ();
int __stdcall get_file_attribute (int, const char *, int *, int __stdcall get_file_attribute (int, const char *, int *,

View File

@ -239,11 +239,10 @@ sec_user (PVOID sa_buf, PSID sid2, BOOL inherit)
((char *) sa_buf + sizeof (*psa)); ((char *) sa_buf + sizeof (*psa));
PACL acl = (PACL) ((char *) sa_buf + sizeof (*psa) + sizeof (*psd)); PACL acl = (PACL) ((char *) sa_buf + sizeof (*psa) + sizeof (*psd));
char sid_buf[MAX_SID_LEN]; cygsid sid;
PSID sid = (PSID) sid_buf;
if (cygheap->user.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)) else if (! lookup_name (getlogin (), cygheap->user.logsrv (), sid))
return inherit ? &sec_none_nih : &sec_none; return inherit ? &sec_none_nih : &sec_none;

View File

@ -1977,12 +1977,37 @@ seteuid (uid_t uid)
debug_printf ("Impersonate (uid == %d)", uid); debug_printf ("Impersonate (uid == %d)", uid);
RevertToSelf (); RevertToSelf ();
if (cygheap->user.token != INVALID_HANDLE_VALUE) if (cygheap->user.token != INVALID_HANDLE_VALUE)
{
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)) if (!ImpersonateLoggedOnUser (cygheap->user.token))
system_printf ("Impersonate (%d) in set(e)uid failed: %E", system_printf ("Impersonate (%d) in set(e)uid failed: %E",
cygheap->user.token); cygheap->user.token);
else else
cygheap->user.impersonated = TRUE; cygheap->user.impersonated = TRUE;
} }
}
cygheap_user user; cygheap_user user;
/* user.token is used in internal_getlogin () to determine if /* user.token is used in internal_getlogin () to determine if
@ -2018,12 +2043,35 @@ setegid (gid_t gid)
{ {
if (gid != (gid_t) -1) if (gid != (gid_t) -1)
{ {
if (!getgrgid (gid)) struct group *gr;
if (!(gr = getgrgid (gid)))
{ {
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
myself->gid = gid; 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 else

View File

@ -115,7 +115,7 @@ internal_getlogin (cygheap_user &user)
HANDLE ptok = user.token; /* Which is INVALID_HANDLE_VALUE if no HANDLE ptok = user.token; /* Which is INVALID_HANDLE_VALUE if no
impersonation took place. */ impersonation took place. */
DWORD siz; DWORD siz;
char tu[1024]; cygsid tu;
int ret = 0; int ret = 0;
/* Try to get the SID either from already impersonated token /* 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 important, because you can't rely on the user information
in a process token of a currently impersonated process. */ in a process token of a currently impersonated process. */
if (ptok == INVALID_HANDLE_VALUE if (ptok == INVALID_HANDLE_VALUE
&& !OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &ptok)) && !OpenProcessToken (GetCurrentProcess (),
TOKEN_ADJUST_DEFAULT | TOKEN_QUERY,
&ptok))
debug_printf ("OpenProcessToken(): %E\n"); debug_printf ("OpenProcessToken(): %E\n");
else if (!GetTokenInformation (ptok, TokenUser, (LPVOID) &tu, else if (!GetTokenInformation (ptok, TokenUser, &tu, sizeof tu, &siz))
sizeof tu, &siz))
debug_printf ("GetTokenInformation(): %E"); 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!"); 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 /* 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 be done if a domain is given because there's a chance that a local
and a domain user may have the same name. */ 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!"); 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. */ the logon server. */
if (!ret && !(ret = lookup_name (user.name (), user.logsrv (), if (!ret && !(ret = lookup_name (user.name (), user.logsrv (),
user.sid ()))) user.sid ())))
@ -154,11 +150,11 @@ internal_getlogin (cygheap_user &user)
/* If we have a SID, try to get the corresponding Cygwin user name /* If we have a SID, try to get the corresponding Cygwin user name
which can be different from the Windows user name. */ which can be different from the Windows user name. */
cygsid gsid (NULL);
if (ret) if (ret)
{ {
struct passwd *pw; struct passwd *pw;
char psidbuf[MAX_SID_LEN]; cygsid psid;
PSID psid = (PSID) psidbuf;
if (!strcasematch (user.name (), "SYSTEM") if (!strcasematch (user.name (), "SYSTEM")
&& user.domain () && user.logsrv ()) && user.domain () && user.logsrv ())
@ -166,14 +162,35 @@ internal_getlogin (cygheap_user &user)
if (get_registry_hive_path (user.sid (), buf)) if (get_registry_hive_path (user.sid (), buf))
setenv ("USERPROFILE", buf, 1); 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)) if (get_pw_sid (psid, pw) && EqualSid (user.sid (), psid))
{ {
user.set_name (pw->pw_name); 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; 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 ()); debug_printf ("Cygwins Username: %s", user.name ());
@ -198,6 +215,9 @@ uinfo_init ()
if ((p = getpwnam (internal_getlogin (cygheap->user))) != NULL) if ((p = getpwnam (internal_getlogin (cygheap->user))) != NULL)
{ {
myself->uid = p->pw_uid; myself->uid = p->pw_uid;
/* 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; myself->gid = p->pw_gid;
} }
else else

View File

@ -101,7 +101,6 @@ extern int dynamically_loaded;
#define DEFAULT_UID 500 #define DEFAULT_UID 500
#define DEFAULT_GID 544 #define DEFAULT_GID 544
#define MAX_SID_LEN 40
#define MAX_HOST_NAME 256 #define MAX_HOST_NAME 256
/* status bit manipulation */ /* status bit manipulation */