* security.cc: Change some formatting.

* include/cygwin/version.h: Bump API minor version.

        * cygheap.h (class cygheap_user): Add member groups.
        * security.h (class cygsidlist): Add members type and maxcount,
        methods position, addfromgr, alloc_sids and free_sids and
        operator+= (const PSID psid). Modify contains () to call
        position () and optimize add () to use maxcount.
        (class user_groups): Create.
        Update declarations of verify_token and create_token.
        * security.cc (cygsidlist::alloc_sids): New.
        (cygsidlist::free_sids): New.
        (get_token_group_sidlist): Create from get_group_sidlist.
        (get_initgroups_sidlist): Create from get_group_sidlist.
        (get_group_sidlist): Suppress.
        (get_setgroups_sidlist): Create.
        (verify_token): Modify arguments. Add setgroups case.
        (create_token): Modify arguments. Call get_initgroups_sidlist and
        get_setgroups_sidlist as needed. Set SE_GROUP_LOGON_ID from auth_pos
        outside of the loop. Rename the various group sid lists consistently.
        * syscalls.cc (seteuid32): Modify to use cygheap->user.groups.
        (setegid32): Call cygheap->user.groups.update_pgrp.
        * grp.cc (setgroups): Create.
        (setgroups32): Create.
        * uinfo.cc (internal_getlogin): Initialize and update user.groups.pgsid.
        * cygwin.din: Add setgroups and setgroups32.
This commit is contained in:
Corinna Vinschen 2002-07-29 12:51:52 +00:00
parent eb5720f255
commit 5519d54352
9 changed files with 458 additions and 227 deletions

View File

@ -1,3 +1,34 @@
2002-07-29 Corinna Vinschen <corinna@vinschen.de>
* security.cc: Change some formatting.
* include/cygwin/version.h: Bump API minor version.
2002-07-28 Pierre Humblet <Pierre.Humblet@ieee.org>
* cygheap.h (class cygheap_user): Add member groups.
* security.h (class cygsidlist): Add members type and maxcount,
methods position, addfromgr, alloc_sids and free_sids and
operator+= (const PSID psid). Modify contains () to call
position () and optimize add () to use maxcount.
(class user_groups): Create.
Update declarations of verify_token and create_token.
* security.cc (cygsidlist::alloc_sids): New.
(cygsidlist::free_sids): New.
(get_token_group_sidlist): Create from get_group_sidlist.
(get_initgroups_sidlist): Create from get_group_sidlist.
(get_group_sidlist): Suppress.
(get_setgroups_sidlist): Create.
(verify_token): Modify arguments. Add setgroups case.
(create_token): Modify arguments. Call get_initgroups_sidlist and
get_setgroups_sidlist as needed. Set SE_GROUP_LOGON_ID from auth_pos
outside of the loop. Rename the various group sid lists consistently.
* syscalls.cc (seteuid32): Modify to use cygheap->user.groups.
(setegid32): Call cygheap->user.groups.update_pgrp.
* grp.cc (setgroups): Create.
(setgroups32): Create.
* uinfo.cc (internal_getlogin): Initialize and update user.groups.pgsid.
* cygwin.din: Add setgroups and setgroups32.
2002-07-28 Christopher Faylor <cgf@redhat.com>
* fhandler_console.cc (fhandler_console::read): Use appropriate

View File

@ -113,6 +113,7 @@ public:
__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()'. */

View File

@ -678,6 +678,9 @@ _setdtablesize = setdtablesize
setgid
_setgid = setgid
setgid32
setgroups
_setgroups = setgroups
setgroups32
setjmp
_setjmp = setjmp
setlocale

View File

@ -457,3 +457,64 @@ initgroups (const char *, __gid16_t)
{
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);
}

View File

@ -154,12 +154,13 @@ details. */
54: Export __fpclassifyd, __fpclassifyf, __signbitd, __signbitf.
55: Export fcloseall, fcloseall_r.
56: Make ntsec on by default.
57: Export setgroups.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 56
#define CYGWIN_VERSION_API_MINOR 57
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible

View File

@ -47,6 +47,22 @@ BOOL allow_ntsec = true;
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)
{
@ -64,7 +80,7 @@ extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
char *d, *u, *c;
domain[0] = 0;
strlcpy (user, pw->pw_name, UNLEN+1);
strlcpy (user, pw->pw_name, UNLEN + 1);
debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos);
if ((d = strstr (pw->pw_gecos, "U-")) != NULL &&
@ -74,11 +90,11 @@ extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
if ((u = strchr (d + 2, '\\')) == NULL || (c != NULL && u > c))
u = d + 1;
else if (u - d <= INTERNET_MAX_HOST_NAME_LENGTH + 2)
strlcpy(domain, d + 2, u - d - 1);
strlcpy (domain, d + 2, u - d - 1);
if (c == NULL)
c = u + UNLEN + 1;
if (c - u <= UNLEN + 1)
strlcpy(user, u + 1, c - u);
strlcpy (user, u + 1, c - u);
}
if (domain[0])
return;
@ -112,9 +128,9 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
extract_nt_dom_user (pw, nt_domain, nt_user);
debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password);
if (!LogonUserA (nt_user, *nt_domain ? nt_domain : NULL, (char *) password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken)
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken)
|| !SetHandleInformation (hToken,
HANDLE_FLAG_INHERIT,
HANDLE_FLAG_INHERIT))
@ -152,7 +168,7 @@ str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr)
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 +210,7 @@ close_local_policy (LSA_HANDLE &lsa)
lsa = INVALID_HANDLE_VALUE;
}
#if 0 // unused
#if 0 /* unused */
static BOOL
get_lsa_srv_inf (LSA_HANDLE lsa, char *logonserver, char *domain)
{
@ -226,7 +242,8 @@ get_lsa_srv_inf (LSA_HANDLE lsa, char *logonserver, char *domain)
not member of a domain. The name in the primary domain info is the
name of the workgroup then. */
if (pdi->Sid &&
(ret = NetGetDCName (NULL, primary, (LPBYTE *) &buf)) == STATUS_SUCCESS)
(ret =
NetGetDCName (NULL, primary, (LPBYTE *) &buf)) == STATUS_SUCCESS)
{
sys_wcstombs (name, buf, INTERNET_MAX_HOST_NAME_LENGTH + 1);
strcpy (logonserver, name);
@ -271,7 +288,8 @@ get_logon_server (const char *domain, char *server, WCHAR *wserver)
{
sys_wcstombs (server, buf, INTERNET_MAX_HOST_NAME_LENGTH + 1);
if (wserver)
for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++); ) {}
for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++);)
;
NetApiBufferFree (buf);
return TRUE;
}
@ -280,7 +298,8 @@ get_logon_server (const char *domain, char *server, WCHAR *wserver)
}
static BOOL
get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, char *domain)
get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user,
char *domain)
{
char dgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2];
WCHAR wuser[UNLEN + 1];
@ -313,11 +332,12 @@ get_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, char *do
sys_wcstombs (dgroup + len, buf[i].grui0_name, GNLEN + 1);
if (!LookupAccountName (NULL, dgroup, gsid, &glen, domain, &dlen, &use))
debug_printf ("LookupAccountName(%s): %E", dgroup);
debug_printf ("LookupAccountName(%s): %E", dgroup);
else if (legal_sid_type (use))
grp_list += gsid;
else debug_printf ("Global group %s invalid. Domain: %s Use: %d",
dgroup, domain, use);
grp_list += gsid;
else
debug_printf ("Global group %s invalid. Domain: %s Use: %d",
dgroup, domain, use);
}
NetApiBufferFree (buf);
@ -369,10 +389,10 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid)
char lgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2];
const DWORD blen = sizeof ("BUILTIN\\") - 1;
DWORD llen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
if (!GetComputerNameA(lgroup, & llen))
if (!GetComputerNameA (lgroup, &llen))
{
__seterrno ();
return FALSE;
__seterrno ();
return FALSE;
}
lgroup[llen++] = '\\';
@ -389,11 +409,11 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid)
if (!LookupAccountName (NULL, bgroup, gsid, &glen, domain, &dlen, &use))
{
if (GetLastError () != ERROR_NONE_MAPPED)
debug_printf ("LookupAccountName(%s): %E", bgroup);
debug_printf ("LookupAccountName(%s): %E", bgroup);
strcpy (lgroup + llen, bgroup + blen);
if (!LookupAccountName (NULL, lgroup, gsid, &glen,
domain, &dlen, &use))
debug_printf ("LookupAccountName(%s): %E", lgroup);
debug_printf ("LookupAccountName(%s): %E", lgroup);
}
if (!legal_sid_type (use))
debug_printf ("Rejecting local %s. use: %d", bgroup + blen, use);
@ -415,7 +435,7 @@ sid_in_token_groups (PTOKEN_GROUPS grps, cygsid &sid)
return FALSE;
}
#if 0 /* Unused */
#if 0 /* Unused */
static BOOL
get_user_primary_group (WCHAR *wlogonserver, const char *user,
PSID pusersid, cygsid &pgrpsid)
@ -441,7 +461,8 @@ get_user_primary_group (WCHAR *wlogonserver, const char *user,
}
pgrpsid = pusersid;
if (IsValidSid (pgrpsid) && (count = *GetSidSubAuthorityCount (pgrpsid)) > 1)
if (IsValidSid (pgrpsid)
&& (count = *GetSidSubAuthorityCount (pgrpsid)) > 1)
{
*GetSidSubAuthority (pgrpsid, count - 1) = buf->usri3_primary_group_id;
retval = TRUE;
@ -473,57 +494,63 @@ get_unix_group_sidlist (struct passwd *pw, cygsidlist &grp_list)
}
}
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)
static void
get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps,
LUID auth_luid, int &auth_pos)
{
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;
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 +558,26 @@ get_group_sidlist (cygsidlist &grp_list,
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,
@ -569,8 +606,8 @@ PTOKEN_PRIVILEGES
get_system_priv_list (cygsidlist &grp_list)
{
LUID priv;
PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) malloc (sizeof (ULONG) +
20 * sizeof (LUID_AND_ATTRIBUTES));
PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES)
malloc (sizeof (ULONG) + 20 * sizeof (LUID_AND_ATTRIBUTES));
if (!privs)
{
debug_printf ("malloc (system_privs) failed.");
@ -583,7 +620,7 @@ get_system_priv_list (cygsidlist &grp_list)
{
privs->Privileges[privs->PrivilegeCount].Luid = priv;
privs->Privileges[privs->PrivilegeCount].Attributes =
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
++privs->PrivilegeCount;
}
return privs;
@ -605,8 +642,8 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
{
if (grp == -1)
{
if ((ret = LsaEnumerateAccountRights (lsa, usersid, &privstrs, &cnt))
!= STATUS_SUCCESS)
if ((ret = LsaEnumerateAccountRights (lsa, usersid, &privstrs,
&cnt)) != STATUS_SUCCESS)
continue;
}
else if ((ret = LsaEnumerateAccountRights (lsa, grp_list.sids[grp],
@ -629,8 +666,8 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
tmp_count = privs ? privs->PrivilegeCount : 0;
tmp = (PTOKEN_PRIVILEGES)
realloc (privs, sizeof (ULONG) +
(tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES));
realloc (privs, sizeof (ULONG) +
(tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES));
if (!tmp)
{
if (privs)
@ -643,7 +680,7 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
privs = tmp;
privs->Privileges[privs->PrivilegeCount].Luid = priv;
privs->Privileges[privs->PrivilegeCount].Attributes =
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
++privs->PrivilegeCount;
next_account_right:
@ -654,8 +691,21 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list)
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;
@ -666,36 +716,39 @@ verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL *pintern)
if (!GetTokenInformation (cygheap->user.token, TokenSource,
&ts, sizeof ts, &size))
debug_printf ("GetTokenInformation(): %E");
else *pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8);
else
*pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8);
}
/* Verify usersid */
cygsid tok_usersid = NO_SID;
if (!GetTokenInformation (token, TokenUser,
&tok_usersid, sizeof tok_usersid, &size))
debug_printf ("GetTokenInformation(): %E");
if (usersid != tok_usersid) return FALSE;
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;
if (!GetKernelObjectSecurity (token, GROUP_SECURITY_INFORMATION,
char sd_buf[MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR)];
PSID gsid = NO_SID;
if (!GetKernelObjectSecurity (token, GROUP_SECURITY_INFORMATION,
(PSECURITY_DESCRIPTOR) sd_buf,
sizeof sd_buf, &size))
debug_printf ("GetKernelObjectSecurity(): %E");
else if (!GetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) sd_buf,
debug_printf ("GetKernelObjectSecurity(): %E");
else if (!GetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) sd_buf,
&gsid, (BOOL *) &size))
debug_printf ("GetSecurityDescriptorGroup(): %E");
if (well_known_null_sid != gsid) return pgrpsid == gsid;
debug_printf ("GetSecurityDescriptorGroup(): %E");
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;
char saw_buf[NGROUPS_MAX] = {};
char *saw = saw_buf, sawpg = FALSE;
if ( pgrpsid == tok_usersid)
return TRUE;
if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) &&
GetLastError () != ERROR_INSUFFICIENT_BUFFER)
debug_printf ("GetTokenInformation(token, TokenGroups): %E\n");
@ -703,38 +756,70 @@ verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL *pintern)
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);
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 };
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 };
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;
char acl_buf[MAX_DACL_LEN(5)];
char acl_buf[MAX_DACL_LEN (5)];
TOKEN_DEFAULT_DACL dacl;
TOKEN_SOURCE source;
TOKEN_STATISTICS stats;
@ -746,7 +831,7 @@ create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw)
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. */
@ -768,68 +853,73 @@ create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw)
else
{
/* Switching user context to SYSTEM doesn't inherit the authentication
id of the user account running current process. */
id of the user account running current process. */
if (usersid != well_known_system_sid)
if (!GetTokenInformation (my_token, TokenStatistics,
&stats, sizeof stats, &size))
debug_printf ("GetTokenInformation(my_token, TokenStatistics): %E\n");
debug_printf
("GetTokenInformation(my_token, TokenStatistics): %E\n");
else
auth_luid = stats.AuthenticationId;
/* Retrieving current processes group list to be able to inherit
some important well known group sids. */
some important well known group sids. */
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 |
SE_GROUP_ENABLED_BY_DEFAULT |
SE_GROUP_ENABLED;
if (auth_pos >= 0 && i == (DWORD) auth_pos)
grps->Groups[i].Attributes |= SE_GROUP_LOGON_ID;
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)
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,
&dacl, &source);
&auth_luid, &exp, &user, new_tok_gsids, privs, &owner,
&pgrp, &dacl, &source);
if (ret)
__seterrno_from_win_error (RtlNtStatusToDosError (ret));
else if (GetLastError () == ERROR_PROC_NOT_FOUND)
@ -842,13 +932,15 @@ create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw)
/* Set security descriptor and primary group */
psa = __sec_user (sa_buf, usersid, TRUE);
if (psa->lpSecurityDescriptor &&
!SetSecurityDescriptorGroup (
(PSECURITY_DESCRIPTOR) psa->lpSecurityDescriptor,
special_pgrp ? pgrpsid : well_known_null_sid, FALSE))
debug_printf ("SetSecurityDescriptorGroup %E");
!SetSecurityDescriptorGroup ((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,
SecurityImpersonation, TokenPrimary, &primary_token))
if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa, SecurityImpersonation,
TokenPrimary, &primary_token))
{
__seterrno ();
debug_printf ("DuplicateTokenEx %E");
@ -862,8 +954,8 @@ out:
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);
@ -946,13 +1038,13 @@ subauth (struct passwd *pw)
str2buf2uni (subbuf.auth.Workstation, subbuf.wkstbuf, "");
memcpy (subbuf.auth.ChallengeToClient, "12345678", MSV1_0_CHALLENGE_LENGTH);
str2buf2lsa (subbuf.auth.CaseSensitiveChallengeResponse, subbuf.authinf1, "");
str2buf2lsa (subbuf.auth.CaseInsensitiveChallengeResponse, subbuf.authinf2,"");
str2buf2lsa (subbuf.auth.CaseInsensitiveChallengeResponse,subbuf.authinf2,"");
subbuf.auth.ParameterControl = 0 | (subauth_id << 24);
/* Try to logon... */
ret = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Network,
package_id, &subbuf, sizeof subbuf,
NULL, &ts, (PVOID *)&profile, &size,
&luid, &user_token, &quota, &ret2);
package_id, &subbuf, sizeof subbuf,
NULL, &ts, (PVOID *) &profile, &size,
&luid, &user_token, &quota, &ret2);
if (ret != STATUS_SUCCESS)
{
debug_printf ("LsaLogonUser: %d", ret);
@ -963,8 +1055,7 @@ subauth (struct passwd *pw)
LsaFreeReturnBuffer (profile);
/* Convert to primary token. */
if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa,
SecurityImpersonation, TokenPrimary,
&primary_token))
SecurityImpersonation, TokenPrimary, &primary_token))
__seterrno ();
out:
@ -1004,7 +1095,7 @@ read_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size)
DWORD len = 0;
const char *pfile = file;
char fbuf [PATH_MAX];
char fbuf[PATH_MAX];
if (current_codepage == oem_cp)
{
DWORD fname_len = min (sizeof (fbuf) - 1, strlen (file));
@ -1015,9 +1106,9 @@ read_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size)
if (!GetFileSecurity (pfile,
OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION,
sd_buf, *sd_size, &len))
| GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION,
sd_buf, *sd_size, &len))
{
__seterrno ();
return -1;
@ -1090,8 +1181,8 @@ write_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size)
&bytes_written, FALSE, TRUE, &context))
{
/* Samba returns ERROR_NOT_SUPPORTED.
FAT returns ERROR_INVALID_SECURITY_DESCR.
This shouldn't return as error, but better be ignored. */
FAT returns ERROR_INVALID_SECURITY_DESCR.
This shouldn't return as error, but better be ignored. */
DWORD ret = GetLastError ();
if (ret != ERROR_NOT_SUPPORTED && ret != ERROR_INVALID_SECURITY_DESCR)
{
@ -1117,7 +1208,7 @@ get_nt_attribute (const char *file, int *attribute,
syscall_printf ("file: %s", file);
/* Yeah, sounds too much, but I've seen SDs of 2100 bytes!*/
/* Yeah, sounds too much, but I've seen SDs of 2100 bytes! */
DWORD sd_size = 4096;
char sd_buf[4096];
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
@ -1282,13 +1373,13 @@ get_file_attribute (int use_ntsec, const char *file,
if (allow_ntea)
{
int oatt = *attribute;
res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute));
res = NTReadEA (file, ".UNIXATTR", (char *)attribute, sizeof(*attribute));
*attribute |= oatt;
}
else
res = 0;
/* symlinks are everything for everyone!*/
/* symlinks are everything for everyone! */
if ((*attribute & S_IFLNK) == S_IFLNK)
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
@ -1296,8 +1387,8 @@ get_file_attribute (int use_ntsec, const char *file,
}
static int
get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribute,
__uid32_t *uidret, __gid32_t *gidret)
get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type,
int *attribute, __uid32_t *uidret, __gid32_t *gidret)
{
if (!wincap.has_security ())
return 0;
@ -1308,18 +1399,15 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
PACL acl;
if (ERROR_SUCCESS != GetSecurityInfo (handle, object_type,
DACL_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
OWNER_SECURITY_INFORMATION,
&owner_sid,
&group_sid,
&acl,
NULL,
&psd))
{
__seterrno ();
debug_printf ("GetSecurityInfo %E");
return -1;
DACL_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
OWNER_SECURITY_INFORMATION,
&owner_sid, &group_sid,
&acl, NULL, &psd))
{
__seterrno ();
debug_printf ("GetSecurityInfo %E");
return -1;
}
__uid32_t uid = cygsid (owner_sid).get_uid ();
@ -1341,8 +1429,7 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
if (!acl)
{
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
syscall_printf ("No ACL = %x, uid %d, gid %d",
*attribute, uid, gid);
syscall_printf ("No ACL = %x, uid %d, gid %d", *attribute, uid, gid);
LocalFree (psd);
return 0;
}
@ -1354,7 +1441,7 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
for (DWORD i = 0; i < acl->AceCount; ++i)
{
if (!GetAce (acl, i, (PVOID *) &ace))
if (!GetAce (acl, i, (PVOID *) & ace))
continue;
if (ace->Header.AceFlags & INHERIT_ONLY)
continue;
@ -1372,7 +1459,7 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
continue;
}
cygsid ace_sid ((PSID) &ace->SidStart);
cygsid ace_sid ((PSID) & ace->SidStart);
if (owner_sid && ace_sid == owner_sid)
{
if (ace->Mask & FILE_READ_DATA)
@ -1438,11 +1525,12 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu
int
get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type,
int *attribute, __uid32_t *uidret, __gid32_t *gidret)
int *attribute, __uid32_t *uidret, __gid32_t *gidret)
{
if (allow_ntsec)
{
int res = get_nt_object_attribute (handle, object_type, attribute, uidret, gidret);
int res = get_nt_object_attribute (handle, object_type, attribute,
uidret, gidret);
if (attribute && (*attribute & S_IFLNK) == S_IFLNK)
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
return res;
@ -1456,7 +1544,7 @@ get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type,
if (!attribute)
return 0;
/* symlinks are everything for everyone!*/
/* symlinks are everything for everyone! */
if ((*attribute & S_IFLNK) == S_IFLNK)
*attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
@ -1475,8 +1563,7 @@ add_access_allowed_ace (PACL acl, int offset, DWORD attributes,
ACCESS_ALLOWED_ACE *ace;
if (GetAce (acl, offset, (PVOID *) &ace))
ace->Header.AceFlags |= inherit;
len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD)
+ GetLengthSid (sid);
len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + GetLengthSid (sid);
return TRUE;
}
@ -1492,8 +1579,7 @@ add_access_denied_ace (PACL acl, int offset, DWORD attributes,
ACCESS_DENIED_ACE *ace;
if (GetAce (acl, offset, (PVOID *) &ace))
ace->Header.AceFlags |= inherit;
len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD)
+ GetLengthSid (sid);
len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + GetLengthSid (sid);
return TRUE;
}
@ -1614,8 +1700,7 @@ alloc_sd (__uid32_t uid, __gid32_t gid, int attribute,
if (attribute & S_IXGRP)
group_allow |= FILE_GENERIC_EXECUTE;
if ((attribute & (S_IFDIR | S_IWGRP | S_IXGRP))
== (S_IFDIR | S_IWGRP | S_IXGRP)
&& !(attribute & S_ISVTX))
== (S_IFDIR | S_IWGRP | S_IXGRP) && !(attribute & S_ISVTX))
group_allow |= FILE_DELETE_CHILD;
/* Construct allow attribute for everyone. */
@ -1658,30 +1743,30 @@ alloc_sd (__uid32_t uid, __gid32_t gid, int attribute,
/* Construct appropriate inherit attribute. */
DWORD inherit = (attribute & S_IFDIR) ? SUB_CONTAINERS_AND_OBJECTS_INHERIT
: NO_INHERITANCE;
: NO_INHERITANCE;
/* Set deny ACE for owner. */
if (owner_deny
&& !add_access_denied_ace (acl, ace_off++, owner_deny,
owner_sid, acl_len, inherit))
owner_sid, acl_len, inherit))
return NULL;
/* Set allow ACE for owner. */
if (!add_access_allowed_ace (acl, ace_off++, owner_allow,
owner_sid, acl_len, inherit))
owner_sid, acl_len, inherit))
return NULL;
/* Set deny ACE for group. */
if (group_deny
&& !add_access_denied_ace (acl, ace_off++, group_deny,
group_sid, acl_len, inherit))
group_sid, acl_len, inherit))
return NULL;
/* Set allow ACE for group. */
if (!add_access_allowed_ace (acl, ace_off++, group_allow,
group_sid, acl_len, inherit))
group_sid, acl_len, inherit))
return NULL;
/* Set allow ACE for everyone. */
if (!add_access_allowed_ace (acl, ace_off++, other_allow,
well_known_world_sid, acl_len, inherit))
well_known_world_sid, acl_len, inherit))
return NULL;
/* Set null ACE for special bits. */
if (null_allow
@ -1764,15 +1849,15 @@ void
set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa,
void *sd_buf, DWORD sd_buf_size)
{
/* symlinks are anything for everyone!*/
/* symlinks are anything for everyone! */
if ((attribute & S_IFLNK) == S_IFLNK)
attribute |= S_IRWXU | S_IRWXG | S_IRWXO;
psa->lpSecurityDescriptor = sd_buf;
InitializeSecurityDescriptor ((PSECURITY_DESCRIPTOR)sd_buf,
InitializeSecurityDescriptor ((PSECURITY_DESCRIPTOR) sd_buf,
SECURITY_DESCRIPTOR_REVISION);
psa->lpSecurityDescriptor = alloc_sd (geteuid32 (), getegid32 (),
attribute, (PSECURITY_DESCRIPTOR)sd_buf,
psa->lpSecurityDescriptor = alloc_sd (geteuid32 (), getegid32 (), attribute,
(PSECURITY_DESCRIPTOR) sd_buf,
&sd_buf_size);
}
@ -1803,8 +1888,7 @@ set_nt_attribute (const char *file, __uid32_t uid, __gid32_t gid,
int
set_file_attribute (int use_ntsec, const char *file,
__uid32_t uid, __gid32_t gid,
int attribute)
__uid32_t uid, __gid32_t gid, int attribute)
{
int ret = 0;
@ -1825,6 +1909,5 @@ int
set_file_attribute (int use_ntsec, const char *file, int attribute)
{
return set_file_attribute (use_ntsec, file,
myself->uid, myself->gid,
attribute);
myself->uid, myself->gid, attribute);
}

View File

@ -86,40 +86,63 @@ public:
}
};
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; }
BOOL add (cygsid &nsi)
cygsidlist (cygsidlist_type t, int m)
{
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;
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 (const PSID nsi) /* Only with auto for now */
{
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 @@ public:
}
};
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 @@ void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa,
/* 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);

View File

@ -1958,9 +1958,8 @@ seteuid32 (__uid32_t uid)
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");
@ -1968,7 +1967,8 @@ seteuid32 (__uid32_t uid)
}
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;
@ -1976,8 +1976,7 @@ seteuid32 (__uid32_t uid)
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;
@ -1995,7 +1994,7 @@ seteuid32 (__uid32_t uid)
/* 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)
{
@ -2011,8 +2010,8 @@ seteuid32 (__uid32_t uid)
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,
& sav_token_is_internal_token);
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 ");
if (!token_ok)
@ -2048,7 +2047,7 @@ seteuid32 (__uid32_t uid)
{
/* 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
@ -2076,7 +2075,7 @@ seteuid32 (__uid32_t uid)
/* 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");
}
@ -2098,6 +2097,7 @@ seteuid32 (__uid32_t uid)
cygheap->user.set_name (pw_new->pw_name);
cygheap->user.set_sid (usersid);
myself->uid = uid;
groups.ischanged = FALSE;
return 0;
failed:
@ -2142,6 +2142,7 @@ setegid32 (__gid32_t gid)
return 0;
sigframe thisframe (mainthread);
user_groups * groups = &cygheap->user.groups;
cygsid gsid;
HANDLE ptok;
@ -2153,6 +2154,7 @@ setegid32 (__gid32_t gid)
}
myself->gid = gid;
groups->update_pgrp (gsid);
/* If impersonated, update primary group and revert */
if (cygheap->user.issetuid ())
{

View File

@ -48,9 +48,12 @@ internal_getlogin (cygheap_user &user)
&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 @@ internal_getlogin (cygheap_user &user)
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);
}