Cygwin: get_user_groups: fetch a user's group list from identification token
NetUserGetGroups and NetUserGetLocalGroups sometimes take a lot of time (up to more than 2 mins) for no apparent reason. Call s4uauth to generate an identification token for the user and fetch the group list from there. This is *much* faster. Keep the old code only for the sake of WOW64 on Vista and Windows 7, which don't implement MsV1_0S4ULogon. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
		| @@ -535,7 +535,6 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, | |||||||
| { | { | ||||||
|   WCHAR user[UNLEN + 1]; |   WCHAR user[UNLEN + 1]; | ||||||
|   WCHAR domain[MAX_DOMAIN_NAME_LEN + 1]; |   WCHAR domain[MAX_DOMAIN_NAME_LEN + 1]; | ||||||
|   WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH + 3]; |  | ||||||
|   DWORD ulen = UNLEN + 1; |   DWORD ulen = UNLEN + 1; | ||||||
|   DWORD dlen = MAX_DOMAIN_NAME_LEN + 1; |   DWORD dlen = MAX_DOMAIN_NAME_LEN + 1; | ||||||
|   SID_NAME_USE use; |   SID_NAME_USE use; | ||||||
| @@ -546,41 +545,73 @@ get_server_groups (cygsidlist &grp_list, PSID usersid, | |||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   grp_list *= well_known_world_sid; |  | ||||||
|   grp_list *= well_known_authenticated_users_sid; |  | ||||||
|  |  | ||||||
|   if (!LookupAccountSidW (NULL, usersid, user, &ulen, domain, &dlen, &use)) |   if (!LookupAccountSidW (NULL, usersid, user, &ulen, domain, &dlen, &use)) | ||||||
|     { |     { | ||||||
|       __seterrno (); |       __seterrno (); | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|   /* If the SID does NOT start with S-1-5-21, the domain is some builtin |   /* If the SID does NOT start with S-1-5-21, the domain is some builtin | ||||||
|      domain.  The search for a logon server and fetching group accounts |      domain.  We don't fetch a group list then. */ | ||||||
|      is moot. */ |  | ||||||
|   if (sid_id_auth (usersid) == 5 /* SECURITY_NT_AUTHORITY */ |   if (sid_id_auth (usersid) == 5 /* SECURITY_NT_AUTHORITY */ | ||||||
|       && sid_sub_auth (usersid, 0) == SECURITY_NT_NON_UNIQUE |       && sid_sub_auth (usersid, 0) == SECURITY_NT_NON_UNIQUE) | ||||||
|       && get_logon_server (domain, server, DS_IS_FLAT_NAME)) |  | ||||||
|     { |     { | ||||||
|       if (check_account_disabled == CHK_DISABLED) |       if (wincap.no_msv1_0_s4u_logon_in_wow64 ()) | ||||||
| 	{ | 	{ | ||||||
| 	  NET_API_STATUS napi_stat; | 	  WCHAR server[INTERNET_MAX_HOST_NAME_LENGTH + 3]; | ||||||
| 	  USER_INFO_1 *ui1; |  | ||||||
| 	  bool allow_user = false; |  | ||||||
|  |  | ||||||
| 	  napi_stat = NetUserGetInfo (server, user, 1, (LPBYTE *) &ui1); | 	  if (!get_logon_server (domain, server, DS_IS_FLAT_NAME)) | ||||||
| 	  if (napi_stat == NERR_Success) | 	    return false; | ||||||
| 	    allow_user = !(ui1->usri1_flags & (UF_ACCOUNTDISABLE | UF_LOCKOUT)); | 	  if (check_account_disabled == CHK_DISABLED) | ||||||
| 	  if (ui1) |  | ||||||
| 	    NetApiBufferFree (ui1); |  | ||||||
| 	  if (!allow_user) |  | ||||||
| 	    { | 	    { | ||||||
| 	      debug_printf ("User denied: %W\\%W", domain, user); | 	      NET_API_STATUS napi_stat; | ||||||
| 	      set_errno (EACCES); | 	      USER_INFO_1 *ui1; | ||||||
| 	      return false; | 	      bool allow_user = false; | ||||||
|  |  | ||||||
|  | 	      napi_stat = NetUserGetInfo (server, user, 1, (LPBYTE *) &ui1); | ||||||
|  | 	      if (napi_stat == NERR_Success) | ||||||
|  | 		allow_user = !(ui1->usri1_flags & (UF_ACCOUNTDISABLE | UF_LOCKOUT)); | ||||||
|  | 	      if (ui1) | ||||||
|  | 		NetApiBufferFree (ui1); | ||||||
|  | 	      if (!allow_user) | ||||||
|  | 		{ | ||||||
|  | 		  debug_printf ("User denied: %W\\%W", domain, user); | ||||||
|  | 		  set_errno (EACCES); | ||||||
|  | 		  return false; | ||||||
|  | 		} | ||||||
| 	    } | 	    } | ||||||
|  | 	  grp_list *= well_known_world_sid; | ||||||
|  | 	  grp_list *= well_known_authenticated_users_sid; | ||||||
|  | 	  get_user_groups (server, grp_list, user, domain); | ||||||
|  | 	  get_user_local_groups (domain, grp_list, user); | ||||||
|  | 	  return true; | ||||||
| 	} | 	} | ||||||
|       get_user_groups (server, grp_list, user, domain); |  | ||||||
|       get_user_local_groups (domain, grp_list, user); |       tmp_pathbuf tp; | ||||||
|  |       HANDLE token; | ||||||
|  |       NTSTATUS status; | ||||||
|  |       PTOKEN_GROUPS groups; | ||||||
|  |       ULONG size; | ||||||
|  |  | ||||||
|  |       token = s4uauth (false, domain, user, status); | ||||||
|  |       if (!token) | ||||||
|  | 	return false; | ||||||
|  |  | ||||||
|  |       groups = (PTOKEN_GROUPS) tp.w_get (); | ||||||
|  |       status = NtQueryInformationToken (token, TokenGroups, groups, | ||||||
|  | 					2 * NT_MAX_PATH, &size); | ||||||
|  |       if (NT_SUCCESS (status)) | ||||||
|  | 	for (DWORD pg = 0; pg < groups->GroupCount; ++pg) | ||||||
|  | 	  { | ||||||
|  | 	    if (groups->Groups[pg].Attributes & SE_GROUP_USE_FOR_DENY_ONLY) | ||||||
|  | 	      continue; | ||||||
|  | 	    cygpsid grpsid = groups->Groups[pg].Sid; | ||||||
|  | 	    if (sid_id_auth (grpsid) == 5 /* SECURITY_NT_AUTHORITY */ | ||||||
|  | 		&& sid_sub_auth (grpsid, 0) == SECURITY_NT_NON_UNIQUE) | ||||||
|  | 	      grp_list += grpsid; | ||||||
|  | 	    else | ||||||
|  | 	      grp_list *= grpsid; | ||||||
|  | 	  } | ||||||
|  |       NtClose (token); | ||||||
|     } |     } | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| @@ -589,8 +620,6 @@ static bool | |||||||
| get_initgroups_sidlist (cygsidlist &grp_list, PSID usersid, PSID pgrpsid, | get_initgroups_sidlist (cygsidlist &grp_list, PSID usersid, PSID pgrpsid, | ||||||
| 			PTOKEN_GROUPS my_grps) | 			PTOKEN_GROUPS my_grps) | ||||||
| { | { | ||||||
|   grp_list *= well_known_world_sid; |  | ||||||
|   grp_list *= well_known_authenticated_users_sid; |  | ||||||
|   if (well_known_system_sid != usersid) |   if (well_known_system_sid != usersid) | ||||||
|     get_token_group_sidlist (grp_list, my_grps); |     get_token_group_sidlist (grp_list, my_grps); | ||||||
|   if (!get_server_groups (grp_list, usersid, CHK_DISABLED)) |   if (!get_server_groups (grp_list, usersid, CHK_DISABLED)) | ||||||
| @@ -605,8 +634,6 @@ static bool | |||||||
| get_setgroups_sidlist (cygsidlist &tmp_list, PSID usersid, | get_setgroups_sidlist (cygsidlist &tmp_list, PSID usersid, | ||||||
| 		       PTOKEN_GROUPS my_grps, user_groups &groups) | 		       PTOKEN_GROUPS my_grps, user_groups &groups) | ||||||
| { | { | ||||||
|   tmp_list *= well_known_world_sid; |  | ||||||
|   tmp_list *= well_known_authenticated_users_sid; |  | ||||||
|   get_token_group_sidlist (tmp_list, my_grps); |   get_token_group_sidlist (tmp_list, my_grps); | ||||||
|   if (!get_server_groups (tmp_list, usersid, CHK_DISABLED)) |   if (!get_server_groups (tmp_list, usersid, CHK_DISABLED)) | ||||||
|     return false; |     return false; | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|     has_posix_unlink_semantics:false, |     has_posix_unlink_semantics:false, | ||||||
|     has_case_sensitive_dirs:false, |     has_case_sensitive_dirs:false, | ||||||
|     has_posix_rename_semantics:false, |     has_posix_rename_semantics:false, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:true, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -63,6 +64,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|     has_posix_unlink_semantics:false, |     has_posix_unlink_semantics:false, | ||||||
|     has_case_sensitive_dirs:false, |     has_case_sensitive_dirs:false, | ||||||
|     has_posix_rename_semantics:false, |     has_posix_rename_semantics:false, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:true, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -87,6 +89,7 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = { | |||||||
|     has_posix_unlink_semantics:false, |     has_posix_unlink_semantics:false, | ||||||
|     has_case_sensitive_dirs:false, |     has_case_sensitive_dirs:false, | ||||||
|     has_posix_rename_semantics:false, |     has_posix_rename_semantics:false, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:false, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -111,6 +114,7 @@ wincaps  wincap_10_1507 __attribute__((section (".cygwin_dll_common"), shared)) | |||||||
|     has_posix_unlink_semantics:false, |     has_posix_unlink_semantics:false, | ||||||
|     has_case_sensitive_dirs:false, |     has_case_sensitive_dirs:false, | ||||||
|     has_posix_rename_semantics:false, |     has_posix_rename_semantics:false, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:false, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -135,6 +139,7 @@ wincaps wincap_10_1511 __attribute__((section (".cygwin_dll_common"), shared)) = | |||||||
|     has_posix_unlink_semantics:false, |     has_posix_unlink_semantics:false, | ||||||
|     has_case_sensitive_dirs:false, |     has_case_sensitive_dirs:false, | ||||||
|     has_posix_rename_semantics:false, |     has_posix_rename_semantics:false, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:false, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -159,6 +164,7 @@ wincaps wincap_10_1703 __attribute__((section (".cygwin_dll_common"), shared)) = | |||||||
|     has_posix_unlink_semantics:false, |     has_posix_unlink_semantics:false, | ||||||
|     has_case_sensitive_dirs:false, |     has_case_sensitive_dirs:false, | ||||||
|     has_posix_rename_semantics:false, |     has_posix_rename_semantics:false, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:false, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -183,6 +189,7 @@ wincaps wincap_10_1709 __attribute__((section (".cygwin_dll_common"), shared)) = | |||||||
|     has_posix_unlink_semantics:true, |     has_posix_unlink_semantics:true, | ||||||
|     has_case_sensitive_dirs:false, |     has_case_sensitive_dirs:false, | ||||||
|     has_posix_rename_semantics:false, |     has_posix_rename_semantics:false, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:false, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -207,6 +214,7 @@ wincaps wincap_10_1803 __attribute__((section (".cygwin_dll_common"), shared)) = | |||||||
|     has_posix_unlink_semantics:true, |     has_posix_unlink_semantics:true, | ||||||
|     has_case_sensitive_dirs:true, |     has_case_sensitive_dirs:true, | ||||||
|     has_posix_rename_semantics:false, |     has_posix_rename_semantics:false, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:false, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -231,6 +239,7 @@ wincaps wincap_10_1809 __attribute__((section (".cygwin_dll_common"), shared)) = | |||||||
|     has_posix_unlink_semantics:true, |     has_posix_unlink_semantics:true, | ||||||
|     has_case_sensitive_dirs:true, |     has_case_sensitive_dirs:true, | ||||||
|     has_posix_rename_semantics:true, |     has_posix_rename_semantics:true, | ||||||
|  |     no_msv1_0_s4u_logon_in_wow64:true, | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -303,6 +312,7 @@ wincapc::init () | |||||||
|       ((wincaps *)caps)->needs_count_in_si_lpres2 = false; |       ((wincaps *)caps)->needs_count_in_si_lpres2 = false; | ||||||
|       ((wincaps *)caps)->has_gaa_largeaddress_bug = false; |       ((wincaps *)caps)->has_gaa_largeaddress_bug = false; | ||||||
|       ((wincaps *)caps)->has_broken_prefetchvm = false; |       ((wincaps *)caps)->has_broken_prefetchvm = false; | ||||||
|  |       ((wincaps *)caps)->no_msv1_0_s4u_logon_in_wow64 = false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   __small_sprintf (osnam, "NT-%d.%d", version.dwMajorVersion, |   __small_sprintf (osnam, "NT-%d.%d", version.dwMajorVersion, | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ struct wincaps | |||||||
|     unsigned has_posix_unlink_semantics		: 1; |     unsigned has_posix_unlink_semantics		: 1; | ||||||
|     unsigned has_case_sensitive_dirs		: 1; |     unsigned has_case_sensitive_dirs		: 1; | ||||||
|     unsigned has_posix_rename_semantics		: 1; |     unsigned has_posix_rename_semantics		: 1; | ||||||
|  |     unsigned no_msv1_0_s4u_logon_in_wow64	: 1; | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -87,6 +88,7 @@ public: | |||||||
|   bool	IMPLEMENT (has_posix_unlink_semantics) |   bool	IMPLEMENT (has_posix_unlink_semantics) | ||||||
|   bool	IMPLEMENT (has_case_sensitive_dirs) |   bool	IMPLEMENT (has_case_sensitive_dirs) | ||||||
|   bool	IMPLEMENT (has_posix_rename_semantics) |   bool	IMPLEMENT (has_posix_rename_semantics) | ||||||
|  |   bool	IMPLEMENT (no_msv1_0_s4u_logon_in_wow64) | ||||||
|  |  | ||||||
|   void disable_case_sensitive_dirs () |   void disable_case_sensitive_dirs () | ||||||
|   { |   { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user