* 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:
		| @@ -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> | 2002-07-28  Christopher Faylor  <cgf@redhat.com> | ||||||
|  |  | ||||||
| 	* fhandler_console.cc (fhandler_console::read): Use appropriate | 	* fhandler_console.cc (fhandler_console::read): Use appropriate | ||||||
|   | |||||||
| @@ -113,6 +113,7 @@ public: | |||||||
|   __gid32_t orig_gid;      /* Ditto */ |   __gid32_t orig_gid;      /* Ditto */ | ||||||
|   __uid32_t real_uid;      /* Remains intact on seteuid, replaced by setuid */ |   __uid32_t real_uid;      /* Remains intact on seteuid, replaced by setuid */ | ||||||
|   __gid32_t real_gid;      /* Ditto */ |   __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 |   /* token is needed if set(e)uid should be called. It can be set by a call | ||||||
|      to `set_impersonation_token()'. */ |      to `set_impersonation_token()'. */ | ||||||
|   | |||||||
| @@ -678,6 +678,9 @@ _setdtablesize = setdtablesize | |||||||
| setgid | setgid | ||||||
| _setgid = setgid | _setgid = setgid | ||||||
| setgid32 | setgid32 | ||||||
|  | setgroups | ||||||
|  | _setgroups = setgroups | ||||||
|  | setgroups32 | ||||||
| setjmp | setjmp | ||||||
| _setjmp = setjmp | _setjmp = setjmp | ||||||
| setlocale | setlocale | ||||||
|   | |||||||
| @@ -457,3 +457,64 @@ initgroups (const char *, __gid16_t) | |||||||
| { | { | ||||||
|   return 0; |   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); | ||||||
|  |  | ||||||
|  | } | ||||||
|   | |||||||
| @@ -154,12 +154,13 @@ details. */ | |||||||
|        54: Export __fpclassifyd, __fpclassifyf, __signbitd, __signbitf. |        54: Export __fpclassifyd, __fpclassifyf, __signbitd, __signbitf. | ||||||
|        55: Export fcloseall, fcloseall_r. |        55: Export fcloseall, fcloseall_r. | ||||||
|        56: Make ntsec on by default. |        56: Make ntsec on by default. | ||||||
|  |        57: Export setgroups. | ||||||
|      */ |      */ | ||||||
|  |  | ||||||
|      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ |      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ | ||||||
|  |  | ||||||
| #define CYGWIN_VERSION_API_MAJOR 0 | #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 |      /* There is also a compatibity version number associated with the | ||||||
| 	shared memory regions.  It is incremented when incompatible | 	shared memory regions.  It is incremented when incompatible | ||||||
|   | |||||||
| @@ -47,6 +47,22 @@ BOOL allow_ntsec = true; | |||||||
|    The default is TRUE to reflect the old behaviour. */ |    The default is TRUE to reflect the old behaviour. */ | ||||||
| BOOL allow_smbntsec; | 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 | extern "C" void | ||||||
| cygwin_set_impersonation_token (const HANDLE hToken) | 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; |   char *d, *u, *c; | ||||||
|  |  | ||||||
|   domain[0] = 0; |   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); |   debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos); | ||||||
|  |  | ||||||
|   if ((d = strstr (pw->pw_gecos, "U-")) != NULL && |   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)) |       if ((u = strchr (d + 2, '\\')) == NULL || (c != NULL && u > c)) | ||||||
| 	u = d + 1; | 	u = d + 1; | ||||||
|       else if (u - d <= INTERNET_MAX_HOST_NAME_LENGTH + 2) |       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) |       if (c == NULL) | ||||||
| 	c = u + UNLEN + 1; | 	c = u + UNLEN + 1; | ||||||
|       if (c - u <= UNLEN + 1) |       if (c - u <= UNLEN + 1) | ||||||
| 	strlcpy(user, u + 1, c - u); | 	strlcpy (user, u + 1, c - u); | ||||||
|     } |     } | ||||||
|   if (domain[0]) |   if (domain[0]) | ||||||
|     return; |     return; | ||||||
| @@ -112,9 +128,9 @@ cygwin_logon_user (const struct passwd *pw, const char *password) | |||||||
|   extract_nt_dom_user (pw, nt_domain, nt_user); |   extract_nt_dom_user (pw, nt_domain, nt_user); | ||||||
|   debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password); |   debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password); | ||||||
|   if (!LogonUserA (nt_user, *nt_domain ? nt_domain : NULL, (char *) password, |   if (!LogonUserA (nt_user, *nt_domain ? nt_domain : NULL, (char *) password, | ||||||
| 		    LOGON32_LOGON_INTERACTIVE, | 		   LOGON32_LOGON_INTERACTIVE, | ||||||
| 		    LOGON32_PROVIDER_DEFAULT, | 		   LOGON32_PROVIDER_DEFAULT, | ||||||
| 		    &hToken) | 		   &hToken) | ||||||
|       || !SetHandleInformation (hToken, |       || !SetHandleInformation (hToken, | ||||||
| 				HANDLE_FLAG_INHERIT, | 				HANDLE_FLAG_INHERIT, | ||||||
| 				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); |   sys_mbstowcs (buf, srcstr, tgt.MaximumLength); | ||||||
| } | } | ||||||
|  |  | ||||||
| #if 0 //unused | #if 0				/* unused */ | ||||||
| static void | static void | ||||||
| lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size) | lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size) | ||||||
| { | { | ||||||
| @@ -194,7 +210,7 @@ close_local_policy (LSA_HANDLE &lsa) | |||||||
|   lsa = INVALID_HANDLE_VALUE; |   lsa = INVALID_HANDLE_VALUE; | ||||||
| } | } | ||||||
|  |  | ||||||
| #if 0 // unused | #if 0 /* unused */ | ||||||
| static BOOL | static BOOL | ||||||
| get_lsa_srv_inf (LSA_HANDLE lsa, char *logonserver, char *domain) | 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 |      not member of a domain.  The name in the primary domain info is the | ||||||
|      name of the workgroup then. */ |      name of the workgroup then. */ | ||||||
|   if (pdi->Sid && |   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); |       sys_wcstombs (name, buf, INTERNET_MAX_HOST_NAME_LENGTH + 1); | ||||||
|       strcpy (logonserver, name); |       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); |       sys_wcstombs (server, buf, INTERNET_MAX_HOST_NAME_LENGTH + 1); | ||||||
|       if (wserver) |       if (wserver) | ||||||
| 	for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++); ) {} | 	for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++);) | ||||||
|  | 	  ; | ||||||
|       NetApiBufferFree (buf); |       NetApiBufferFree (buf); | ||||||
|       return TRUE; |       return TRUE; | ||||||
|     } |     } | ||||||
| @@ -280,7 +298,8 @@ get_logon_server (const char *domain, char *server, WCHAR *wserver) | |||||||
| } | } | ||||||
|  |  | ||||||
| static BOOL | 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]; |   char dgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; | ||||||
|   WCHAR wuser[UNLEN + 1]; |   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); |       sys_wcstombs (dgroup + len, buf[i].grui0_name, GNLEN + 1); | ||||||
|       if (!LookupAccountName (NULL, dgroup, gsid, &glen, domain, &dlen, &use)) |       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)) |       else if (legal_sid_type (use)) | ||||||
| 	  grp_list += gsid; | 	grp_list += gsid; | ||||||
|       else debug_printf ("Global group %s invalid. Domain: %s Use: %d", |       else | ||||||
| 			dgroup, domain, use); | 	debug_printf ("Global group %s invalid. Domain: %s Use: %d", | ||||||
|  | 		      dgroup, domain, use); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   NetApiBufferFree (buf); |   NetApiBufferFree (buf); | ||||||
| @@ -369,10 +389,10 @@ get_user_local_groups (cygsidlist &grp_list, PSID pusersid) | |||||||
|   char lgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; |   char lgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; | ||||||
|   const DWORD blen = sizeof ("BUILTIN\\") - 1; |   const DWORD blen = sizeof ("BUILTIN\\") - 1; | ||||||
|   DWORD llen = INTERNET_MAX_HOST_NAME_LENGTH + 1; |   DWORD llen = INTERNET_MAX_HOST_NAME_LENGTH + 1; | ||||||
|   if (!GetComputerNameA(lgroup, & llen)) |   if (!GetComputerNameA (lgroup, &llen)) | ||||||
|     { |     { | ||||||
|        __seterrno (); |       __seterrno (); | ||||||
|        return FALSE; |       return FALSE; | ||||||
|     } |     } | ||||||
|   lgroup[llen++] = '\\'; |   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 (!LookupAccountName (NULL, bgroup, gsid, &glen, domain, &dlen, &use)) | ||||||
| 	  { | 	  { | ||||||
| 	    if (GetLastError () != ERROR_NONE_MAPPED) | 	    if (GetLastError () != ERROR_NONE_MAPPED) | ||||||
|               debug_printf ("LookupAccountName(%s): %E", bgroup); | 	      debug_printf ("LookupAccountName(%s): %E", bgroup); | ||||||
| 	    strcpy (lgroup + llen, bgroup + blen); | 	    strcpy (lgroup + llen, bgroup + blen); | ||||||
| 	    if (!LookupAccountName (NULL, lgroup, gsid, &glen, | 	    if (!LookupAccountName (NULL, lgroup, gsid, &glen, | ||||||
| 				    domain, &dlen, &use)) | 				    domain, &dlen, &use)) | ||||||
|               debug_printf ("LookupAccountName(%s): %E", lgroup); | 	      debug_printf ("LookupAccountName(%s): %E", lgroup); | ||||||
| 	  } | 	  } | ||||||
| 	if (!legal_sid_type (use)) | 	if (!legal_sid_type (use)) | ||||||
| 	  debug_printf ("Rejecting local %s. use: %d", bgroup + blen, 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; |   return FALSE; | ||||||
| } | } | ||||||
|  |  | ||||||
| #if 0 /* Unused */ | #if 0				/* Unused */ | ||||||
| static BOOL | static BOOL | ||||||
| get_user_primary_group (WCHAR *wlogonserver, const char *user, | get_user_primary_group (WCHAR *wlogonserver, const char *user, | ||||||
| 			PSID pusersid, cygsid &pgrpsid) | 			PSID pusersid, cygsid &pgrpsid) | ||||||
| @@ -441,7 +461,8 @@ get_user_primary_group (WCHAR *wlogonserver, const char *user, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|   pgrpsid = pusersid; |   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; |       *GetSidSubAuthority (pgrpsid, count - 1) = buf->usri3_primary_group_id; | ||||||
|       retval = TRUE; |       retval = TRUE; | ||||||
| @@ -473,57 +494,63 @@ get_unix_group_sidlist (struct passwd *pw, cygsidlist &grp_list) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static BOOL | static void | ||||||
| get_group_sidlist (cygsidlist &grp_list, | get_token_group_sidlist (cygsidlist &grp_list, PTOKEN_GROUPS my_grps, | ||||||
| 		   cygsid &usersid, cygsid &pgrpsid, struct passwd *pw, | 			 LUID auth_luid, int &auth_pos) | ||||||
| 		   PTOKEN_GROUPS my_grps, LUID auth_luid, int &auth_pos, |  | ||||||
| 		   BOOL *special_pgrp) |  | ||||||
| { | { | ||||||
|   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; |   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_world_sid; | ||||||
|   grp_list += well_known_authenticated_users_sid; |   grp_list += well_known_authenticated_users_sid; | ||||||
|   if (usersid == well_known_system_sid) |   if (usersid == well_known_system_sid) | ||||||
|     { |     { | ||||||
|  |       auth_pos = -1; | ||||||
|       grp_list += well_known_admins_sid; |       grp_list += well_known_admins_sid; | ||||||
|       get_unix_group_sidlist (pw, grp_list); |       get_unix_group_sidlist (pw, grp_list); | ||||||
|     } |     } | ||||||
|   else |   else | ||||||
|     { |     { | ||||||
|       if (my_grps) |       char user[UNLEN + 1]; | ||||||
| 	{ |       char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; | ||||||
| 	  if (sid_in_token_groups (my_grps, well_known_local_sid)) |       WCHAR wserver[INTERNET_MAX_HOST_NAME_LENGTH + 3]; | ||||||
| 	    grp_list += well_known_local_sid; |       char server[INTERNET_MAX_HOST_NAME_LENGTH + 3]; | ||||||
| 	  if (sid_in_token_groups (my_grps, well_known_dialup_sid)) |  | ||||||
| 	    grp_list += well_known_dialup_sid; |       get_token_group_sidlist (grp_list, my_grps, auth_luid, auth_pos); | ||||||
| 	  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; |  | ||||||
| 	} |  | ||||||
|       extract_nt_dom_user (pw, domain, user); |       extract_nt_dom_user (pw, domain, user); | ||||||
|       if (get_logon_server (domain, server, wserver)) |       if (get_logon_server (domain, server, wserver)) | ||||||
| 	get_user_groups (wserver, grp_list, user, domain); | 	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)) |       if (!get_user_local_groups (grp_list, usersid)) | ||||||
| 	return FALSE; | 	return FALSE; | ||||||
|     } |     } | ||||||
|   /* special_pgrp true if pgrpsid is not null and not in normal groups */ |   /* special_pgrp true if pgrpsid is not in normal groups */ | ||||||
|   *special_pgrp = FALSE; |   if ((special_pgrp = !grp_list.contains (pgrpsid))) | ||||||
|   if (pgrpsid && !grp_list.contains (pgrpsid)) |     grp_list += pgrpsid; | ||||||
|     { |  | ||||||
|        *special_pgrp = TRUE; |  | ||||||
|        grp_list += pgrpsid; |  | ||||||
|     } |  | ||||||
|   return TRUE; |   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[] = { | static const char *sys_privs[] = { | ||||||
|   SE_TCB_NAME, |   SE_TCB_NAME, | ||||||
|   SE_ASSIGNPRIMARYTOKEN_NAME, |   SE_ASSIGNPRIMARYTOKEN_NAME, | ||||||
| @@ -569,8 +606,8 @@ PTOKEN_PRIVILEGES | |||||||
| get_system_priv_list (cygsidlist &grp_list) | get_system_priv_list (cygsidlist &grp_list) | ||||||
| { | { | ||||||
|   LUID priv; |   LUID priv; | ||||||
|   PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) malloc (sizeof (ULONG) + |   PTOKEN_PRIVILEGES privs = (PTOKEN_PRIVILEGES) | ||||||
| 					    20 * sizeof (LUID_AND_ATTRIBUTES)); |     malloc (sizeof (ULONG) + 20 * sizeof (LUID_AND_ATTRIBUTES)); | ||||||
|   if (!privs) |   if (!privs) | ||||||
|     { |     { | ||||||
|       debug_printf ("malloc (system_privs) failed."); |       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].Luid = priv; | ||||||
| 	privs->Privileges[privs->PrivilegeCount].Attributes = | 	privs->Privileges[privs->PrivilegeCount].Attributes = | ||||||
| 		      SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; | 	  SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; | ||||||
| 	++privs->PrivilegeCount; | 	++privs->PrivilegeCount; | ||||||
|       } |       } | ||||||
|   return privs; |   return privs; | ||||||
| @@ -605,8 +642,8 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list) | |||||||
|     { |     { | ||||||
|       if (grp == -1) |       if (grp == -1) | ||||||
| 	{ | 	{ | ||||||
| 	  if ((ret = LsaEnumerateAccountRights (lsa, usersid, &privstrs, &cnt)) | 	  if ((ret = LsaEnumerateAccountRights (lsa, usersid, &privstrs, | ||||||
| 	      != STATUS_SUCCESS) | 						&cnt)) != STATUS_SUCCESS) | ||||||
| 	    continue; | 	    continue; | ||||||
| 	} | 	} | ||||||
|       else if ((ret = LsaEnumerateAccountRights (lsa, grp_list.sids[grp], |       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_count = privs ? privs->PrivilegeCount : 0; | ||||||
| 	  tmp = (PTOKEN_PRIVILEGES) | 	  tmp = (PTOKEN_PRIVILEGES) | ||||||
| 		realloc (privs, sizeof (ULONG) + | 	    realloc (privs, sizeof (ULONG) + | ||||||
| 				(tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES)); | 		     (tmp_count + 1) * sizeof (LUID_AND_ATTRIBUTES)); | ||||||
| 	  if (!tmp) | 	  if (!tmp) | ||||||
| 	    { | 	    { | ||||||
| 	      if (privs) | 	      if (privs) | ||||||
| @@ -643,7 +680,7 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list) | |||||||
| 	  privs = tmp; | 	  privs = tmp; | ||||||
| 	  privs->Privileges[privs->PrivilegeCount].Luid = priv; | 	  privs->Privileges[privs->PrivilegeCount].Luid = priv; | ||||||
| 	  privs->Privileges[privs->PrivilegeCount].Attributes = | 	  privs->Privileges[privs->PrivilegeCount].Attributes = | ||||||
| 		      SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; | 	    SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT; | ||||||
| 	  ++privs->PrivilegeCount; | 	  ++privs->PrivilegeCount; | ||||||
|  |  | ||||||
| 	next_account_right: | 	next_account_right: | ||||||
| @@ -654,8 +691,21 @@ get_priv_list (LSA_HANDLE lsa, cygsid &usersid, cygsidlist &grp_list) | |||||||
|   return privs; |   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 | BOOL | ||||||
| verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL *pintern) | verify_token (HANDLE token, cygsid &usersid, user_groups &groups, BOOL *pintern) | ||||||
| { | { | ||||||
|   DWORD size; |   DWORD size; | ||||||
|   BOOL intern = FALSE; |   BOOL intern = FALSE; | ||||||
| @@ -666,36 +716,39 @@ verify_token (HANDLE token, cygsid &usersid, cygsid &pgrpsid, BOOL *pintern) | |||||||
|       if (!GetTokenInformation (cygheap->user.token, TokenSource, |       if (!GetTokenInformation (cygheap->user.token, TokenSource, | ||||||
| 				&ts, sizeof ts, &size)) | 				&ts, sizeof ts, &size)) | ||||||
| 	debug_printf ("GetTokenInformation(): %E"); | 	debug_printf ("GetTokenInformation(): %E"); | ||||||
|       else *pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8); |       else | ||||||
|  | 	*pintern = intern = !memcmp (ts.SourceName, "Cygwin.1", 8); | ||||||
|     } |     } | ||||||
|   /* Verify usersid */ |   /* Verify usersid */ | ||||||
|   cygsid tok_usersid = NO_SID; |   cygsid tok_usersid = NO_SID; | ||||||
|   if (!GetTokenInformation (token, TokenUser, |   if (!GetTokenInformation (token, TokenUser, | ||||||
| 			    &tok_usersid, sizeof tok_usersid, &size)) | 			    &tok_usersid, sizeof tok_usersid, &size)) | ||||||
|       debug_printf ("GetTokenInformation(): %E"); |     debug_printf ("GetTokenInformation(): %E"); | ||||||
|   if (usersid != tok_usersid) return FALSE; |   if (usersid != tok_usersid) | ||||||
|  |     return FALSE; | ||||||
|  |  | ||||||
|   /* In an internal token, if the sd group is not well_known_null_sid, |   /* For an internal token, if setgroups was not called and if the sd group | ||||||
|      it must match pgrpsid */ |      is not well_known_null_sid, it must match pgrpsid */ | ||||||
|   if (intern) |   if (intern && !groups.issetgroups ()) | ||||||
|     { |     { | ||||||
|        char sd_buf[MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR)]; |       char sd_buf[MAX_SID_LEN + sizeof (SECURITY_DESCRIPTOR)]; | ||||||
|        PSID gsid = NO_SID; |       PSID gsid = NO_SID; | ||||||
|        if (!GetKernelObjectSecurity (token, GROUP_SECURITY_INFORMATION, |       if (!GetKernelObjectSecurity (token, GROUP_SECURITY_INFORMATION, | ||||||
| 				    (PSECURITY_DESCRIPTOR) sd_buf, | 				    (PSECURITY_DESCRIPTOR) sd_buf, | ||||||
| 				    sizeof sd_buf, &size)) | 				    sizeof sd_buf, &size)) | ||||||
| 	   debug_printf ("GetKernelObjectSecurity(): %E"); | 	debug_printf ("GetKernelObjectSecurity(): %E"); | ||||||
|        else if (!GetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) sd_buf, |       else if (!GetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) sd_buf, | ||||||
| 					    &gsid, (BOOL *) &size)) | 					    &gsid, (BOOL *) &size)) | ||||||
| 	   debug_printf ("GetSecurityDescriptorGroup(): %E"); | 	debug_printf ("GetSecurityDescriptorGroup(): %E"); | ||||||
|        if (well_known_null_sid != gsid) return pgrpsid == gsid; |       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; |   PTOKEN_GROUPS my_grps = NULL; | ||||||
|   BOOL ret = FALSE; |   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) && |   if (!GetTokenInformation (token, TokenGroups, NULL, 0, &size) && | ||||||
|       GetLastError () != ERROR_INSUFFICIENT_BUFFER) |       GetLastError () != ERROR_INSUFFICIENT_BUFFER) | ||||||
|     debug_printf ("GetTokenInformation(token, TokenGroups): %E\n"); |     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."); |     debug_printf ("malloc (my_grps) failed."); | ||||||
|   else if (!GetTokenInformation (token, TokenGroups, my_grps, size, &size)) |   else if (!GetTokenInformation (token, TokenGroups, my_grps, size, &size)) | ||||||
|     debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); |     debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); | ||||||
|   else |   else if (!groups.issetgroups ()) /* setgroups was never called */ | ||||||
|     ret = sid_in_token_groups (my_grps, pgrpsid); |     { | ||||||
|  |       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) |   if (my_grps) | ||||||
|     free (my_grps); |     free (my_grps); | ||||||
|  |   if (saw != saw_buf) | ||||||
|  |     free (saw); | ||||||
|   return ret; |   return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| HANDLE | HANDLE | ||||||
| create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw) | create_token (cygsid &usersid, user_groups &new_groups, struct passwd *pw) | ||||||
| { | { | ||||||
|   NTSTATUS ret; |   NTSTATUS ret; | ||||||
|   LSA_HANDLE lsa = INVALID_HANDLE_VALUE; |   LSA_HANDLE lsa = INVALID_HANDLE_VALUE; | ||||||
|   int old_priv_state; |   int old_priv_state; | ||||||
|  |  | ||||||
|   cygsidlist grpsids; |   cygsidlist tmp_gsids (cygsidlist_auto, 12); | ||||||
|  |  | ||||||
|   SECURITY_QUALITY_OF_SERVICE sqos = |   SECURITY_QUALITY_OF_SERVICE sqos = | ||||||
|     { sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE }; |     { sizeof sqos, SecurityImpersonation, SECURITY_STATIC_TRACKING, FALSE }; | ||||||
|   OBJECT_ATTRIBUTES oa = |   OBJECT_ATTRIBUTES oa = { sizeof oa, 0, 0, 0, 0, &sqos }; | ||||||
|     { sizeof oa, 0, 0, 0, 0, &sqos }; |  | ||||||
|   PSECURITY_ATTRIBUTES psa; |   PSECURITY_ATTRIBUTES psa; | ||||||
|   BOOL special_pgrp; |   BOOL special_pgrp = FALSE; | ||||||
|   char sa_buf[1024]; |   char sa_buf[1024]; | ||||||
|   LUID auth_luid = SYSTEM_LUID; |   LUID auth_luid = SYSTEM_LUID; | ||||||
|   LARGE_INTEGER exp = { QuadPart:0x7fffffffffffffffLL  }; |   LARGE_INTEGER exp = { QuadPart:0x7fffffffffffffffLL }; | ||||||
|  |  | ||||||
|   TOKEN_USER user; |   TOKEN_USER user; | ||||||
|   PTOKEN_GROUPS grps = NULL; |   PTOKEN_GROUPS new_tok_gsids = NULL; | ||||||
|   PTOKEN_PRIVILEGES privs = NULL; |   PTOKEN_PRIVILEGES privs = NULL; | ||||||
|   TOKEN_OWNER owner; |   TOKEN_OWNER owner; | ||||||
|   TOKEN_PRIMARY_GROUP pgrp; |   TOKEN_PRIMARY_GROUP pgrp; | ||||||
|   char acl_buf[MAX_DACL_LEN(5)]; |   char acl_buf[MAX_DACL_LEN (5)]; | ||||||
|   TOKEN_DEFAULT_DACL dacl; |   TOKEN_DEFAULT_DACL dacl; | ||||||
|   TOKEN_SOURCE source; |   TOKEN_SOURCE source; | ||||||
|   TOKEN_STATISTICS stats; |   TOKEN_STATISTICS stats; | ||||||
| @@ -746,7 +831,7 @@ create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw) | |||||||
|   HANDLE primary_token = INVALID_HANDLE_VALUE; |   HANDLE primary_token = INVALID_HANDLE_VALUE; | ||||||
|  |  | ||||||
|   HANDLE my_token = INVALID_HANDLE_VALUE; |   HANDLE my_token = INVALID_HANDLE_VALUE; | ||||||
|   PTOKEN_GROUPS my_grps = NULL; |   PTOKEN_GROUPS my_tok_gsids = NULL; | ||||||
|   DWORD size; |   DWORD size; | ||||||
|  |  | ||||||
|   /* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */ |   /* SE_CREATE_TOKEN_NAME privilege needed to call NtCreateToken. */ | ||||||
| @@ -768,68 +853,73 @@ create_token (cygsid &usersid, cygsid &pgrpsid, struct passwd *pw) | |||||||
|   else |   else | ||||||
|     { |     { | ||||||
|       /* Switching user context to SYSTEM doesn't inherit the authentication |       /* 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 (usersid != well_known_system_sid) | ||||||
| 	if (!GetTokenInformation (my_token, TokenStatistics, | 	if (!GetTokenInformation (my_token, TokenStatistics, | ||||||
| 				  &stats, sizeof stats, &size)) | 				  &stats, sizeof stats, &size)) | ||||||
| 	  debug_printf ("GetTokenInformation(my_token, TokenStatistics): %E\n"); | 	  debug_printf | ||||||
|  | 	    ("GetTokenInformation(my_token, TokenStatistics): %E\n"); | ||||||
| 	else | 	else | ||||||
| 	  auth_luid = stats.AuthenticationId; | 	  auth_luid = stats.AuthenticationId; | ||||||
|  |  | ||||||
|       /* Retrieving current processes group list to be able to inherit |       /* 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) && |       if (!GetTokenInformation (my_token, TokenGroups, NULL, 0, &size) && | ||||||
| 	  GetLastError () != ERROR_INSUFFICIENT_BUFFER) | 	  GetLastError () != ERROR_INSUFFICIENT_BUFFER) | ||||||
| 	debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); | 	debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); | ||||||
|       else if (!(my_grps = (PTOKEN_GROUPS) malloc (size))) |       else if (!(my_tok_gsids = (PTOKEN_GROUPS) malloc (size))) | ||||||
| 	debug_printf ("malloc (my_grps) failed."); | 	debug_printf ("malloc (my_tok_gsids) failed."); | ||||||
|       else if (!GetTokenInformation (my_token, TokenGroups, my_grps, |       else if (!GetTokenInformation (my_token, TokenGroups, my_tok_gsids, | ||||||
| 				     size, &size)) | 				     size, &size)) | ||||||
| 	{ | 	{ | ||||||
| 	  debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); | 	  debug_printf ("GetTokenInformation(my_token, TokenGroups): %E\n"); | ||||||
| 	  free (my_grps); | 	  free (my_tok_gsids); | ||||||
| 	  my_grps = NULL; | 	  my_tok_gsids = NULL; | ||||||
| 	} | 	} | ||||||
|       CloseHandle (my_token); |       CloseHandle (my_token); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   /* Create list of groups, the user is member in. */ |   /* Create list of groups, the user is member in. */ | ||||||
|   int auth_pos; |   int auth_pos; | ||||||
|   if (!get_group_sidlist (grpsids, usersid, pgrpsid, pw, |   if (new_groups.issetgroups ()) | ||||||
| 			  my_grps, auth_luid, auth_pos, &special_pgrp)) |     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; |     goto out; | ||||||
|  |  | ||||||
|   /* Primary group. */ |   /* Primary group. */ | ||||||
|   pgrp.PrimaryGroup = pgrpsid; |   pgrp.PrimaryGroup = new_groups.pgsid; | ||||||
|  |  | ||||||
|   /* Create a TOKEN_GROUPS list from the above retrieved list of sids. */ |   /* Create a TOKEN_GROUPS list from the above retrieved list of sids. */ | ||||||
|   char grps_buf[sizeof (ULONG) + grpsids.count * sizeof (SID_AND_ATTRIBUTES)]; |   char grps_buf[sizeof (ULONG) + tmp_gsids.count * sizeof (SID_AND_ATTRIBUTES)]; | ||||||
|   grps = (PTOKEN_GROUPS) grps_buf; |   new_tok_gsids = (PTOKEN_GROUPS) grps_buf; | ||||||
|   grps->GroupCount = grpsids.count; |   new_tok_gsids->GroupCount = tmp_gsids.count; | ||||||
|   for (DWORD i = 0; i < grps->GroupCount; ++i) |   for (DWORD i = 0; i < new_tok_gsids->GroupCount; ++i) | ||||||
|     { |     { | ||||||
|       grps->Groups[i].Sid = grpsids.sids[i]; |       new_tok_gsids->Groups[i].Sid = tmp_gsids.sids[i]; | ||||||
|       grps->Groups[i].Attributes = SE_GROUP_MANDATORY | |       new_tok_gsids->Groups[i].Attributes = SE_GROUP_MANDATORY | | ||||||
| 				   SE_GROUP_ENABLED_BY_DEFAULT | | 	SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; | ||||||
| 				   SE_GROUP_ENABLED; |  | ||||||
|       if (auth_pos >= 0 && i == (DWORD) auth_pos) |  | ||||||
| 	grps->Groups[i].Attributes |= SE_GROUP_LOGON_ID; |  | ||||||
|     } |     } | ||||||
|  |   if (auth_pos >= 0) | ||||||
|  |     new_tok_gsids->Groups[auth_pos].Attributes |= SE_GROUP_LOGON_ID; | ||||||
|  |  | ||||||
|   /* Retrieve list of privileges of that user. */ |   /* 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; |     goto out; | ||||||
|  |  | ||||||
|   /* Create default dacl. */ |   /* Create default dacl. */ | ||||||
|   if (!sec_acl ((PACL) acl_buf, FALSE, |   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; |     goto out; | ||||||
|   dacl.DefaultDacl = (PACL) acl_buf; |   dacl.DefaultDacl = (PACL) acl_buf; | ||||||
|  |  | ||||||
|   /* Let's be heroic... */ |   /* Let's be heroic... */ | ||||||
|   ret = NtCreateToken (&token, TOKEN_ALL_ACCESS, &oa, TokenImpersonation, |   ret = NtCreateToken (&token, TOKEN_ALL_ACCESS, &oa, TokenImpersonation, | ||||||
| 		       &auth_luid, &exp, &user, grps, privs, &owner, &pgrp, | 		       &auth_luid, &exp, &user, new_tok_gsids, privs, &owner, | ||||||
| 		       &dacl, &source); | 		       &pgrp, &dacl, &source); | ||||||
|   if (ret) |   if (ret) | ||||||
|     __seterrno_from_win_error (RtlNtStatusToDosError (ret)); |     __seterrno_from_win_error (RtlNtStatusToDosError (ret)); | ||||||
|   else if (GetLastError () == ERROR_PROC_NOT_FOUND) |   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 */ |       /* Set security descriptor and primary group */ | ||||||
|       psa = __sec_user (sa_buf, usersid, TRUE); |       psa = __sec_user (sa_buf, usersid, TRUE); | ||||||
|       if (psa->lpSecurityDescriptor && |       if (psa->lpSecurityDescriptor && | ||||||
| 	  !SetSecurityDescriptorGroup ( | 	  !SetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) | ||||||
| 	      (PSECURITY_DESCRIPTOR) psa->lpSecurityDescriptor, | 				       psa->lpSecurityDescriptor, | ||||||
| 	      special_pgrp ? pgrpsid : well_known_null_sid, FALSE)) | 				       special_pgrp ? new_groups.pgsid | ||||||
| 	  debug_printf ("SetSecurityDescriptorGroup %E"); | 						    : well_known_null_sid, | ||||||
|  | 				       FALSE)) | ||||||
|  | 	debug_printf ("SetSecurityDescriptorGroup %E"); | ||||||
|       /* Convert to primary token. */ |       /* Convert to primary token. */ | ||||||
|       if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa, |       if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa, SecurityImpersonation, | ||||||
| 			     SecurityImpersonation, TokenPrimary, &primary_token)) | 			     TokenPrimary, &primary_token)) | ||||||
| 	{ | 	{ | ||||||
| 	  __seterrno (); | 	  __seterrno (); | ||||||
| 	  debug_printf ("DuplicateTokenEx %E"); | 	  debug_printf ("DuplicateTokenEx %E"); | ||||||
| @@ -862,8 +954,8 @@ out: | |||||||
|     CloseHandle (token); |     CloseHandle (token); | ||||||
|   if (privs) |   if (privs) | ||||||
|     free (privs); |     free (privs); | ||||||
|   if (my_grps) |   if (my_tok_gsids) | ||||||
|     free (my_grps); |     free (my_tok_gsids); | ||||||
|   close_local_policy (lsa); |   close_local_policy (lsa); | ||||||
|  |  | ||||||
|   debug_printf ("%d = create_token ()", primary_token); |   debug_printf ("%d = create_token ()", primary_token); | ||||||
| @@ -946,13 +1038,13 @@ subauth (struct passwd *pw) | |||||||
|   str2buf2uni (subbuf.auth.Workstation, subbuf.wkstbuf, ""); |   str2buf2uni (subbuf.auth.Workstation, subbuf.wkstbuf, ""); | ||||||
|   memcpy (subbuf.auth.ChallengeToClient, "12345678", MSV1_0_CHALLENGE_LENGTH); |   memcpy (subbuf.auth.ChallengeToClient, "12345678", MSV1_0_CHALLENGE_LENGTH); | ||||||
|   str2buf2lsa (subbuf.auth.CaseSensitiveChallengeResponse, subbuf.authinf1, ""); |   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); |   subbuf.auth.ParameterControl = 0 | (subauth_id << 24); | ||||||
|   /* Try to logon... */ |   /* Try to logon... */ | ||||||
|   ret = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Network, |   ret = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Network, | ||||||
| 		     package_id, &subbuf, sizeof subbuf, | 		      package_id, &subbuf, sizeof subbuf, | ||||||
| 		     NULL, &ts, (PVOID *)&profile, &size, | 		      NULL, &ts, (PVOID *) &profile, &size, | ||||||
| 		     &luid, &user_token, "a, &ret2); | 		      &luid, &user_token, "a, &ret2); | ||||||
|   if (ret != STATUS_SUCCESS) |   if (ret != STATUS_SUCCESS) | ||||||
|     { |     { | ||||||
|       debug_printf ("LsaLogonUser: %d", ret); |       debug_printf ("LsaLogonUser: %d", ret); | ||||||
| @@ -963,8 +1055,7 @@ subauth (struct passwd *pw) | |||||||
|   LsaFreeReturnBuffer (profile); |   LsaFreeReturnBuffer (profile); | ||||||
|   /* Convert to primary token. */ |   /* Convert to primary token. */ | ||||||
|   if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa, |   if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa, | ||||||
| 			 SecurityImpersonation, TokenPrimary, | 			 SecurityImpersonation, TokenPrimary, &primary_token)) | ||||||
| 			 &primary_token)) |  | ||||||
|     __seterrno (); |     __seterrno (); | ||||||
|  |  | ||||||
| out: | out: | ||||||
| @@ -1004,7 +1095,7 @@ read_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size) | |||||||
|  |  | ||||||
|   DWORD len = 0; |   DWORD len = 0; | ||||||
|   const char *pfile = file; |   const char *pfile = file; | ||||||
|   char fbuf [PATH_MAX]; |   char fbuf[PATH_MAX]; | ||||||
|   if (current_codepage == oem_cp) |   if (current_codepage == oem_cp) | ||||||
|     { |     { | ||||||
|       DWORD fname_len = min (sizeof (fbuf) - 1, strlen (file)); |       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, |   if (!GetFileSecurity (pfile, | ||||||
| 			OWNER_SECURITY_INFORMATION | 			OWNER_SECURITY_INFORMATION | ||||||
| 			 | GROUP_SECURITY_INFORMATION | 			| GROUP_SECURITY_INFORMATION | ||||||
| 			 | DACL_SECURITY_INFORMATION, | 			| DACL_SECURITY_INFORMATION, | ||||||
| 			 sd_buf, *sd_size, &len)) | 			sd_buf, *sd_size, &len)) | ||||||
|     { |     { | ||||||
|       __seterrno (); |       __seterrno (); | ||||||
|       return -1; |       return -1; | ||||||
| @@ -1090,8 +1181,8 @@ write_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size) | |||||||
| 		    &bytes_written, FALSE, TRUE, &context)) | 		    &bytes_written, FALSE, TRUE, &context)) | ||||||
|     { |     { | ||||||
|       /* Samba returns ERROR_NOT_SUPPORTED. |       /* Samba returns ERROR_NOT_SUPPORTED. | ||||||
| 	 FAT returns ERROR_INVALID_SECURITY_DESCR. |          FAT returns ERROR_INVALID_SECURITY_DESCR. | ||||||
| 	 This shouldn't return as error, but better be ignored. */ |          This shouldn't return as error, but better be ignored. */ | ||||||
|       DWORD ret = GetLastError (); |       DWORD ret = GetLastError (); | ||||||
|       if (ret != ERROR_NOT_SUPPORTED && ret != ERROR_INVALID_SECURITY_DESCR) |       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); |   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; |   DWORD sd_size = 4096; | ||||||
|   char sd_buf[4096]; |   char sd_buf[4096]; | ||||||
|   PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf; |   PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf; | ||||||
| @@ -1282,13 +1373,13 @@ get_file_attribute (int use_ntsec, const char *file, | |||||||
|   if (allow_ntea) |   if (allow_ntea) | ||||||
|     { |     { | ||||||
|       int oatt = *attribute; |       int oatt = *attribute; | ||||||
|       res = NTReadEA (file, ".UNIXATTR", (char *) attribute, sizeof (*attribute)); |       res = NTReadEA (file, ".UNIXATTR", (char *)attribute, sizeof(*attribute)); | ||||||
|       *attribute |= oatt; |       *attribute |= oatt; | ||||||
|     } |     } | ||||||
|   else |   else | ||||||
|     res = 0; |     res = 0; | ||||||
|  |  | ||||||
|   /* symlinks are everything for everyone!*/ |   /* symlinks are everything for everyone! */ | ||||||
|   if ((*attribute & S_IFLNK) == S_IFLNK) |   if ((*attribute & S_IFLNK) == S_IFLNK) | ||||||
|     *attribute |= S_IRWXU | S_IRWXG | S_IRWXO; |     *attribute |= S_IRWXU | S_IRWXG | S_IRWXO; | ||||||
|  |  | ||||||
| @@ -1296,8 +1387,8 @@ get_file_attribute (int use_ntsec, const char *file, | |||||||
| } | } | ||||||
|  |  | ||||||
| static int | static int | ||||||
| get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribute, | get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, | ||||||
| 		  __uid32_t *uidret, __gid32_t *gidret) | 			 int *attribute, __uid32_t *uidret, __gid32_t *gidret) | ||||||
| { | { | ||||||
|   if (!wincap.has_security ()) |   if (!wincap.has_security ()) | ||||||
|     return 0; |     return 0; | ||||||
| @@ -1308,18 +1399,15 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu | |||||||
|   PACL acl; |   PACL acl; | ||||||
|  |  | ||||||
|   if (ERROR_SUCCESS != GetSecurityInfo (handle, object_type, |   if (ERROR_SUCCESS != GetSecurityInfo (handle, object_type, | ||||||
|                                         DACL_SECURITY_INFORMATION | | 					DACL_SECURITY_INFORMATION | | ||||||
|                                         GROUP_SECURITY_INFORMATION | | 					GROUP_SECURITY_INFORMATION | | ||||||
|                                         OWNER_SECURITY_INFORMATION, | 					OWNER_SECURITY_INFORMATION, | ||||||
|                                         &owner_sid, | 					&owner_sid, &group_sid, | ||||||
|                                         &group_sid, | 					&acl, NULL, &psd)) | ||||||
|                                         &acl, |     { | ||||||
|                                         NULL, |       __seterrno (); | ||||||
|                                         &psd)) |       debug_printf ("GetSecurityInfo %E"); | ||||||
| 	{ |       return -1; | ||||||
| 	  __seterrno (); |  | ||||||
| 	  debug_printf ("GetSecurityInfo %E"); |  | ||||||
| 	  return -1; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   __uid32_t uid = cygsid (owner_sid).get_uid (); |   __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) |   if (!acl) | ||||||
|     { |     { | ||||||
|       *attribute |= S_IRWXU | S_IRWXG | S_IRWXO; |       *attribute |= S_IRWXU | S_IRWXG | S_IRWXO; | ||||||
|       syscall_printf ("No ACL = %x, uid %d, gid %d", |       syscall_printf ("No ACL = %x, uid %d, gid %d", *attribute, uid, gid); | ||||||
| 		      *attribute, uid, gid); |  | ||||||
|       LocalFree (psd); |       LocalFree (psd); | ||||||
|       return 0; |       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) |   for (DWORD i = 0; i < acl->AceCount; ++i) | ||||||
|     { |     { | ||||||
|       if (!GetAce (acl, i, (PVOID *) &ace)) |       if (!GetAce (acl, i, (PVOID *) & ace)) | ||||||
| 	continue; | 	continue; | ||||||
|       if (ace->Header.AceFlags & INHERIT_ONLY) |       if (ace->Header.AceFlags & INHERIT_ONLY) | ||||||
| 	continue; | 	continue; | ||||||
| @@ -1372,7 +1459,7 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu | |||||||
| 	  continue; | 	  continue; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|       cygsid ace_sid ((PSID) &ace->SidStart); |       cygsid ace_sid ((PSID) & ace->SidStart); | ||||||
|       if (owner_sid && ace_sid == owner_sid) |       if (owner_sid && ace_sid == owner_sid) | ||||||
| 	{ | 	{ | ||||||
| 	  if (ace->Mask & FILE_READ_DATA) | 	  if (ace->Mask & FILE_READ_DATA) | ||||||
| @@ -1438,11 +1525,12 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, int *attribu | |||||||
|  |  | ||||||
| int | int | ||||||
| get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, | 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) |   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) |       if (attribute && (*attribute & S_IFLNK) == S_IFLNK) | ||||||
| 	*attribute |= S_IRWXU | S_IRWXG | S_IRWXO; | 	*attribute |= S_IRWXU | S_IRWXG | S_IRWXO; | ||||||
|       return res; |       return res; | ||||||
| @@ -1456,7 +1544,7 @@ get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, | |||||||
|   if (!attribute) |   if (!attribute) | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   /* symlinks are everything for everyone!*/ |   /* symlinks are everything for everyone! */ | ||||||
|   if ((*attribute & S_IFLNK) == S_IFLNK) |   if ((*attribute & S_IFLNK) == S_IFLNK) | ||||||
|     *attribute |= S_IRWXU | S_IRWXG | S_IRWXO; |     *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; |   ACCESS_ALLOWED_ACE *ace; | ||||||
|   if (GetAce (acl, offset, (PVOID *) &ace)) |   if (GetAce (acl, offset, (PVOID *) &ace)) | ||||||
|     ace->Header.AceFlags |= inherit; |     ace->Header.AceFlags |= inherit; | ||||||
|   len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) |   len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + GetLengthSid (sid); | ||||||
| 	     + GetLengthSid (sid); |  | ||||||
|   return TRUE; |   return TRUE; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1492,8 +1579,7 @@ add_access_denied_ace (PACL acl, int offset, DWORD attributes, | |||||||
|   ACCESS_DENIED_ACE *ace; |   ACCESS_DENIED_ACE *ace; | ||||||
|   if (GetAce (acl, offset, (PVOID *) &ace)) |   if (GetAce (acl, offset, (PVOID *) &ace)) | ||||||
|     ace->Header.AceFlags |= inherit; |     ace->Header.AceFlags |= inherit; | ||||||
|   len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) |   len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + GetLengthSid (sid); | ||||||
| 	     + GetLengthSid (sid); |  | ||||||
|   return TRUE; |   return TRUE; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1614,8 +1700,7 @@ alloc_sd (__uid32_t uid, __gid32_t gid, int attribute, | |||||||
|   if (attribute & S_IXGRP) |   if (attribute & S_IXGRP) | ||||||
|     group_allow |= FILE_GENERIC_EXECUTE; |     group_allow |= FILE_GENERIC_EXECUTE; | ||||||
|   if ((attribute & (S_IFDIR | S_IWGRP | S_IXGRP)) |   if ((attribute & (S_IFDIR | S_IWGRP | S_IXGRP)) | ||||||
|       == (S_IFDIR | S_IWGRP | S_IXGRP) |       == (S_IFDIR | S_IWGRP | S_IXGRP) && !(attribute & S_ISVTX)) | ||||||
|       && !(attribute & S_ISVTX)) |  | ||||||
|     group_allow |= FILE_DELETE_CHILD; |     group_allow |= FILE_DELETE_CHILD; | ||||||
|  |  | ||||||
|   /* Construct allow attribute for everyone. */ |   /* Construct allow attribute for everyone. */ | ||||||
| @@ -1658,30 +1743,30 @@ alloc_sd (__uid32_t uid, __gid32_t gid, int attribute, | |||||||
|  |  | ||||||
|   /* Construct appropriate inherit attribute. */ |   /* Construct appropriate inherit attribute. */ | ||||||
|   DWORD inherit = (attribute & S_IFDIR) ? SUB_CONTAINERS_AND_OBJECTS_INHERIT |   DWORD inherit = (attribute & S_IFDIR) ? SUB_CONTAINERS_AND_OBJECTS_INHERIT | ||||||
|   					: NO_INHERITANCE; | 					: NO_INHERITANCE; | ||||||
|  |  | ||||||
|   /* Set deny ACE for owner. */ |   /* Set deny ACE for owner. */ | ||||||
|   if (owner_deny |   if (owner_deny | ||||||
|       && !add_access_denied_ace (acl, ace_off++, owner_deny, |       && !add_access_denied_ace (acl, ace_off++, owner_deny, | ||||||
| 				  owner_sid, acl_len, inherit)) | 				 owner_sid, acl_len, inherit)) | ||||||
|     return NULL; |     return NULL; | ||||||
|   /* Set allow ACE for owner. */ |   /* Set allow ACE for owner. */ | ||||||
|   if (!add_access_allowed_ace (acl, ace_off++, owner_allow, |   if (!add_access_allowed_ace (acl, ace_off++, owner_allow, | ||||||
| 				owner_sid, acl_len, inherit)) | 			       owner_sid, acl_len, inherit)) | ||||||
|     return NULL; |     return NULL; | ||||||
|   /* Set deny ACE for group. */ |   /* Set deny ACE for group. */ | ||||||
|   if (group_deny |   if (group_deny | ||||||
|       && !add_access_denied_ace (acl, ace_off++, group_deny, |       && !add_access_denied_ace (acl, ace_off++, group_deny, | ||||||
| 				  group_sid, acl_len, inherit)) | 				 group_sid, acl_len, inherit)) | ||||||
|     return NULL; |     return NULL; | ||||||
|   /* Set allow ACE for group. */ |   /* Set allow ACE for group. */ | ||||||
|   if (!add_access_allowed_ace (acl, ace_off++, group_allow, |   if (!add_access_allowed_ace (acl, ace_off++, group_allow, | ||||||
| 				group_sid, acl_len, inherit)) | 			       group_sid, acl_len, inherit)) | ||||||
|     return NULL; |     return NULL; | ||||||
|  |  | ||||||
|   /* Set allow ACE for everyone. */ |   /* Set allow ACE for everyone. */ | ||||||
|   if (!add_access_allowed_ace (acl, ace_off++, other_allow, |   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; |     return NULL; | ||||||
|   /* Set null ACE for special bits. */ |   /* Set null ACE for special bits. */ | ||||||
|   if (null_allow |   if (null_allow | ||||||
| @@ -1764,15 +1849,15 @@ void | |||||||
| set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa, | set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa, | ||||||
| 			void *sd_buf, DWORD sd_buf_size) | 			void *sd_buf, DWORD sd_buf_size) | ||||||
| { | { | ||||||
|   /* symlinks are anything for everyone!*/ |   /* symlinks are anything for everyone! */ | ||||||
|   if ((attribute & S_IFLNK) == S_IFLNK) |   if ((attribute & S_IFLNK) == S_IFLNK) | ||||||
|     attribute |= S_IRWXU | S_IRWXG | S_IRWXO; |     attribute |= S_IRWXU | S_IRWXG | S_IRWXO; | ||||||
|  |  | ||||||
|   psa->lpSecurityDescriptor = sd_buf; |   psa->lpSecurityDescriptor = sd_buf; | ||||||
|   InitializeSecurityDescriptor ((PSECURITY_DESCRIPTOR)sd_buf, |   InitializeSecurityDescriptor ((PSECURITY_DESCRIPTOR) sd_buf, | ||||||
| 				SECURITY_DESCRIPTOR_REVISION); | 				SECURITY_DESCRIPTOR_REVISION); | ||||||
|   psa->lpSecurityDescriptor = alloc_sd (geteuid32 (), getegid32 (), |   psa->lpSecurityDescriptor = alloc_sd (geteuid32 (), getegid32 (), attribute, | ||||||
| 					attribute, (PSECURITY_DESCRIPTOR)sd_buf, | 					(PSECURITY_DESCRIPTOR) sd_buf, | ||||||
| 					&sd_buf_size); | 					&sd_buf_size); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1803,8 +1888,7 @@ set_nt_attribute (const char *file, __uid32_t uid, __gid32_t gid, | |||||||
|  |  | ||||||
| int | int | ||||||
| set_file_attribute (int use_ntsec, const char *file, | set_file_attribute (int use_ntsec, const char *file, | ||||||
| 		    __uid32_t uid, __gid32_t gid, | 		    __uid32_t uid, __gid32_t gid, int attribute) | ||||||
| 		    int attribute) |  | ||||||
| { | { | ||||||
|   int ret = 0; |   int ret = 0; | ||||||
|  |  | ||||||
| @@ -1825,6 +1909,5 @@ int | |||||||
| set_file_attribute (int use_ntsec, const char *file, int attribute) | set_file_attribute (int use_ntsec, const char *file, int attribute) | ||||||
| { | { | ||||||
|   return set_file_attribute (use_ntsec, file, |   return set_file_attribute (use_ntsec, file, | ||||||
| 			     myself->uid, myself->gid, | 			     myself->uid, myself->gid, attribute); | ||||||
| 			     attribute); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -86,40 +86,63 @@ public: | |||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | typedef enum { cygsidlist_unknown, cygsidlist_alloc, cygsidlist_auto } cygsidlist_type; | ||||||
| class cygsidlist { | class cygsidlist { | ||||||
|  |   int maxcount; | ||||||
| public: | public: | ||||||
|   int count; |   int count; | ||||||
|   cygsid *sids; |   cygsid *sids; | ||||||
|  |   cygsidlist_type type; | ||||||
|  |  | ||||||
|   cygsidlist () : count (0), sids (NULL) {} |   cygsidlist (cygsidlist_type t, int m) | ||||||
|   ~cygsidlist () { delete [] sids; } |  | ||||||
|  |  | ||||||
|   BOOL add (cygsid &nsi) |  | ||||||
|     { |     { | ||||||
|       cygsid *tmp = new cygsid [count + 1]; |       type = t; | ||||||
|       if (!tmp) |       count = 0; | ||||||
| 	return FALSE; |       maxcount = m; | ||||||
|       for (int i = 0; i < count; ++i) |       if (t == cygsidlist_alloc) | ||||||
| 	tmp[i] = sids[i]; | 	sids = alloc_sids (m); | ||||||
|       delete [] sids; |       else | ||||||
|       sids = tmp; | 	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; |       sids[count++] = nsi; | ||||||
|       return TRUE; |       return TRUE; | ||||||
|     } |     } | ||||||
|   BOOL add (const PSID nsid) { return add (nsid); } |   BOOL add (cygsid &nsi) { return add ((PSID) nsi); } | ||||||
|   BOOL add (const char *sidstr) |   BOOL add (const char *sidstr) | ||||||
|     { cygsid nsi (sidstr); return add (nsi); } |     { 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+= (cygsid &si) { return add (si); } | ||||||
|   BOOL operator+= (const char *sidstr) { return add (sidstr); } |   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) |       for (int i = 0; i < count; ++i) | ||||||
| 	if (sids[i] == sid) | 	if (sids[i] == sid) | ||||||
| 	  return TRUE; | 	  return i; | ||||||
|       return FALSE; |       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 |   void debug_print (const char *prefix = NULL) const | ||||||
|     { |     { | ||||||
|       debug_printf ("-- begin sidlist ---"); |       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_null_sid; | ||||||
| extern cygsid well_known_world_sid; | extern cygsid well_known_world_sid; | ||||||
| extern cygsid well_known_local_sid; | extern cygsid well_known_local_sid; | ||||||
| @@ -180,9 +223,9 @@ void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa, | |||||||
| /* Try a subauthentication. */ | /* Try a subauthentication. */ | ||||||
| HANDLE subauth (struct passwd *pw); | HANDLE subauth (struct passwd *pw); | ||||||
| /* Try creating a token directly. */ | /* 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 */ | /* 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. */ | /* Extract U-domain\user field from passwd entry. */ | ||||||
| void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user); | void extract_nt_dom_user (const struct passwd *pw, char *domain, char *user); | ||||||
|   | |||||||
| @@ -1958,9 +1958,8 @@ seteuid32 (__uid32_t uid) | |||||||
|   debug_printf ("uid: %d myself->gid: %d", uid, myself->gid); |   debug_printf ("uid: %d myself->gid: %d", uid, myself->gid); | ||||||
|  |  | ||||||
|   if (!wincap.has_security () |   if (!wincap.has_security () | ||||||
|       || (!cygheap->user.issetuid () |       || (uid == myself->uid | ||||||
| 	  && uid == myself->uid | 	  && !cygheap->user.groups.ischanged) | ||||||
| 	  && myself->gid == cygheap->user.orig_gid) |  | ||||||
|       || uid == ILLEGAL_UID) |       || uid == ILLEGAL_UID) | ||||||
|     { |     { | ||||||
|       debug_printf ("Nothing happens"); |       debug_printf ("Nothing happens"); | ||||||
| @@ -1968,7 +1967,8 @@ seteuid32 (__uid32_t uid) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|   sigframe thisframe (mainthread); |   sigframe thisframe (mainthread); | ||||||
|   cygsid usersid, pgrpsid; |   cygsid usersid; | ||||||
|  |   user_groups &groups = cygheap->user.groups; | ||||||
|   HANDLE ptok, sav_token; |   HANDLE ptok, sav_token; | ||||||
|   BOOL sav_impersonated, sav_token_is_internal_token; |   BOOL sav_impersonated, sav_token_is_internal_token; | ||||||
|   BOOL process_ok, explicitly_created_token = FALSE; |   BOOL process_ok, explicitly_created_token = FALSE; | ||||||
| @@ -1976,8 +1976,7 @@ seteuid32 (__uid32_t uid) | |||||||
|   PSID origpsid, psid2 = NO_SID; |   PSID origpsid, psid2 = NO_SID; | ||||||
|  |  | ||||||
|   pw_new = getpwuid32 (uid); |   pw_new = getpwuid32 (uid); | ||||||
|   if (!usersid.getfrompw (pw_new) || |   if (!usersid.getfrompw (pw_new)) | ||||||
|       (!pgrpsid.getfromgr (getgrgid32 (myself->gid)))) |  | ||||||
|     { |     { | ||||||
|       set_errno (EINVAL); |       set_errno (EINVAL); | ||||||
|       return -1; |       return -1; | ||||||
| @@ -1995,7 +1994,7 @@ seteuid32 (__uid32_t uid) | |||||||
|   /* Verify if the process token is suitable. |   /* Verify if the process token is suitable. | ||||||
|      Currently we do not try to differentiate between |      Currently we do not try to differentiate between | ||||||
| 	 internal tokens and others */ | 	 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 "); |   debug_printf("Process token %sverified", process_ok ? "" : "not "); | ||||||
|   if (process_ok) |   if (process_ok) | ||||||
|     { |     { | ||||||
| @@ -2011,8 +2010,8 @@ seteuid32 (__uid32_t uid) | |||||||
|   if (!process_ok && cygheap->user.token != INVALID_HANDLE_VALUE) |   if (!process_ok && cygheap->user.token != INVALID_HANDLE_VALUE) | ||||||
|     { |     { | ||||||
|       /* Verify if the current tokem is suitable */ |       /* Verify if the current tokem is suitable */ | ||||||
|       BOOL token_ok = verify_token (cygheap->user.token, usersid, pgrpsid, |       BOOL token_ok = verify_token (cygheap->user.token, usersid, groups, | ||||||
| 				    & sav_token_is_internal_token); | 				    &sav_token_is_internal_token); | ||||||
|       debug_printf("Thread token %d %sverified", |       debug_printf("Thread token %d %sverified", | ||||||
| 		   cygheap->user.token, token_ok?"":"not "); | 		   cygheap->user.token, token_ok?"":"not "); | ||||||
|       if (!token_ok) |       if (!token_ok) | ||||||
| @@ -2048,7 +2047,7 @@ seteuid32 (__uid32_t uid) | |||||||
|     { |     { | ||||||
|       /* If no impersonation token is available, try to |       /* If no impersonation token is available, try to | ||||||
| 	 authenticate using NtCreateToken() or subauthentication. */ | 	 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) |       if (cygheap->user.token != INVALID_HANDLE_VALUE) | ||||||
| 	explicitly_created_token = TRUE; | 	explicitly_created_token = TRUE; | ||||||
|       else |       else | ||||||
| @@ -2076,7 +2075,7 @@ seteuid32 (__uid32_t uid) | |||||||
| 	  /* Try setting primary group in token to current group */ | 	  /* Try setting primary group in token to current group */ | ||||||
| 	  if (!SetTokenInformation (cygheap->user.token, | 	  if (!SetTokenInformation (cygheap->user.token, | ||||||
| 				    TokenPrimaryGroup, | 				    TokenPrimaryGroup, | ||||||
| 				    &pgrpsid, sizeof pgrpsid)) | 				    &groups.pgsid, sizeof(cygsid))) | ||||||
| 	    debug_printf ("SetTokenInformation(user.token, " | 	    debug_printf ("SetTokenInformation(user.token, " | ||||||
| 			  "TokenPrimaryGroup): %E"); | 			  "TokenPrimaryGroup): %E"); | ||||||
| 	} | 	} | ||||||
| @@ -2098,6 +2097,7 @@ seteuid32 (__uid32_t uid) | |||||||
|   cygheap->user.set_name (pw_new->pw_name); |   cygheap->user.set_name (pw_new->pw_name); | ||||||
|   cygheap->user.set_sid (usersid); |   cygheap->user.set_sid (usersid); | ||||||
|   myself->uid = uid; |   myself->uid = uid; | ||||||
|  |   groups.ischanged = FALSE; | ||||||
|   return 0; |   return 0; | ||||||
|  |  | ||||||
|  failed: |  failed: | ||||||
| @@ -2142,6 +2142,7 @@ setegid32 (__gid32_t gid) | |||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   sigframe thisframe (mainthread); |   sigframe thisframe (mainthread); | ||||||
|  |   user_groups * groups = &cygheap->user.groups; | ||||||
|   cygsid gsid; |   cygsid gsid; | ||||||
|   HANDLE ptok; |   HANDLE ptok; | ||||||
|  |  | ||||||
| @@ -2153,6 +2154,7 @@ setegid32 (__gid32_t gid) | |||||||
|     } |     } | ||||||
|   myself->gid = gid; |   myself->gid = gid; | ||||||
|  |  | ||||||
|  |   groups->update_pgrp (gsid); | ||||||
|   /* If impersonated, update primary group and revert */ |   /* If impersonated, update primary group and revert */ | ||||||
|   if (cygheap->user.issetuid ()) |   if (cygheap->user.issetuid ()) | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -48,9 +48,12 @@ internal_getlogin (cygheap_user &user) | |||||||
| 			     &ptok)) | 			     &ptok)) | ||||||
| 	system_printf ("OpenProcessToken(): %E\n"); | 	system_printf ("OpenProcessToken(): %E\n"); | ||||||
|       else if (!GetTokenInformation (ptok, TokenUser, &tu, sizeof tu, &siz)) |       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))) |       else if (!(ret = user.set_sid (tu))) | ||||||
| 	system_printf ("Couldn't retrieve SID from access token!"); | 	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. |        /* We must set the user name, uid and gid. | ||||||
| 	 If we have a SID, try to get the corresponding Cygwin | 	 If we have a SID, try to get the corresponding Cygwin | ||||||
| 	 password entry. Set user name which can be different | 	 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. */ | 	     primary group to the group in /etc/passwd. */ | ||||||
| 	  if (!SetTokenInformation (ptok, TokenOwner, &tu, sizeof tu)) | 	  if (!SetTokenInformation (ptok, TokenOwner, &tu, sizeof tu)) | ||||||
| 	    debug_printf ("SetTokenInformation(TokenOwner): %E"); | 	    debug_printf ("SetTokenInformation(TokenOwner): %E"); | ||||||
| 	  if (gsid && !SetTokenInformation (ptok, TokenPrimaryGroup, | 	  if (gsid) | ||||||
| 					    &gsid, sizeof gsid)) | 	    { | ||||||
| 	    debug_printf ("SetTokenInformation(TokenPrimaryGroup): %E"); | 	      user.groups.pgsid = gsid; | ||||||
|  | 	      if (!SetTokenInformation (ptok, TokenPrimaryGroup, | ||||||
|  | 					&gsid, sizeof gsid)) | ||||||
|  | 		debug_printf ("SetTokenInformation(TokenPrimaryGroup): %E"); | ||||||
|  | 	    } | ||||||
| 	 } | 	 } | ||||||
|  |  | ||||||
|       if (ptok != INVALID_HANDLE_VALUE) |       if (ptok != INVALID_HANDLE_VALUE) | ||||||
| 	CloseHandle (ptok); | 	CloseHandle (ptok); | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user