Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2002-07-29 16:51:52 +0400
committerCorinna Vinschen <corinna@vinschen.de>2002-07-29 16:51:52 +0400
commit5519d54352e7bdc6d77186cef46dbafc86946bcf (patch)
tree7b69706b4f2ed5aa997ddff5a367d757bb7afb8e
parenteb5720f25501cd7e9b8115bb0220bef058bb5afd (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog31
-rw-r--r--winsup/cygwin/cygheap.h1
-rw-r--r--winsup/cygwin/cygwin.din3
-rw-r--r--winsup/cygwin/grp.cc61
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/security.cc469
-rw-r--r--winsup/cygwin/security.h75
-rw-r--r--winsup/cygwin/syscalls.cc24
-rw-r--r--winsup/cygwin/uinfo.cc16
9 files changed, 457 insertions, 226 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3e467ea54..01044e9fb 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index be8781038..7cd5becbc 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -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()'. */
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 7d69c43f7..0af8f43ac 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -678,6 +678,9 @@ _setdtablesize = setdtablesize
setgid
_setgid = setgid
setgid32
+setgroups
+_setgroups = setgroups
+setgroups32
setjmp
_setjmp = setjmp
setlocale
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index 62e0e76cf..c26a6b1c7 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -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);
+
+}
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index aafc2f932..e98462ddb 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -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
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index a89ff2972..d12e33359 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -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);
}
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 1edcc57fd..580d7c143 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -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; }
+ cygsidlist (cygsidlist_type t, int m)
+ {
+ type = t;
+ count = 0;
+ maxcount = m;
+ if (t == cygsidlist_alloc)
+ sids = alloc_sids (m);
+ else
+ sids = new cygsid [m];
+ }
+ ~cygsidlist () { if (type == cygsidlist_auto) delete [] sids; }
- BOOL add (cygsid &nsi)
+ BOOL add (const PSID nsi) /* Only with auto for now */
{
- cygsid *tmp = new cygsid [count + 1];
- if (!tmp)
- return FALSE;
- for (int i = 0; i < count; ++i)
- tmp[i] = sids[i];
- delete [] sids;
- sids = tmp;
+ if (count >= maxcount)
+ {
+ cygsid *tmp = new cygsid [ 2 * maxcount];
+ if (!tmp)
+ return FALSE;
+ maxcount *= 2;
+ for (int i = 0; i < count; ++i)
+ tmp[i] = sids[i];
+ delete [] sids;
+ sids = tmp;
+ }
sids[count++] = nsi;
return TRUE;
}
- BOOL add (const PSID nsid) { return add (nsid); }
+ BOOL add (cygsid &nsi) { return add ((PSID) nsi); }
BOOL add (const char *sidstr)
{ cygsid nsi (sidstr); return add (nsi); }
+ BOOL addfromgr (struct __group32 *gr) /* Only with alloc */
+ { return sids[count++].getfromgr (gr); }
BOOL operator+= (cygsid &si) { return add (si); }
BOOL operator+= (const char *sidstr) { return add (sidstr); }
+ BOOL operator+= (const PSID psid) { return add (psid); }
- BOOL contains (cygsid &sid) const
+ int position (const PSID sid) const
{
for (int i = 0; i < count; ++i)
if (sids[i] == sid)
- return TRUE;
- return FALSE;
+ return i;
+ return -1;
}
+
+ BOOL contains (const PSID sid) const { return position (sid) >= 0; }
+ cygsid *alloc_sids (int n);
+ void free_sids ();
void debug_print (const char *prefix = NULL) const
{
debug_printf ("-- begin sidlist ---");
@@ -131,6 +154,26 @@ 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);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 018f67dc6..2dc5f1776 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -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 ())
{
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index ec0420cc1..f273ee0b1 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -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);
}