* sec_auth.cc (get_full_privileged_inheritable_token): New function
to fetch token with full privileges from logon token in Vista and later, and to make token inheritable. Add lengthy comments to explain the function's job. (cygwin_logon_user): Drop calling SetHandleInformation. Enable TCB privilege and call get_full_privileged_inheritable_token. (lsaauth): Don't fetch linked token and don't make handle inheritable here, just call get_full_privileged_inheritable_token instead. (lsaprivkeyauth): Ditto.
This commit is contained in:
		| @@ -1,3 +1,15 @@ | ||||
| 2010-02-06  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* sec_auth.cc (get_full_privileged_inheritable_token): New function | ||||
| 	to fetch token with full privileges from logon token in Vista and | ||||
| 	later, and to make token inheritable.  Add lengthy comments to explain | ||||
| 	the function's job. | ||||
| 	(cygwin_logon_user): Drop calling SetHandleInformation.  Enable TCB | ||||
| 	privilege and call get_full_privileged_inheritable_token. | ||||
| 	(lsaauth): Don't fetch linked token and don't make handle inheritable | ||||
| 	here, just call get_full_privileged_inheritable_token instead. | ||||
| 	(lsaprivkeyauth): Ditto. | ||||
|  | ||||
| 2010-02-05  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* nlsfuncs.cc (__set_charset_from_locale): Set default locale for | ||||
|   | ||||
| @@ -30,6 +30,58 @@ details. */ | ||||
| #include "cygserver_setpwd.h" | ||||
| #include <cygwin/version.h> | ||||
|  | ||||
| /* Starting with Windows Vista, the token returned by system functions | ||||
|    is a restricted token.  The full admin token is linked to it and can | ||||
|    be fetched with GetTokenInformation.  This function returns the original | ||||
|    token on pre-Vista, and the elevated token on Vista++ if it's available, | ||||
|    the original token otherwise.  The token handle is also made inheritable | ||||
|    since that's necessary anyway. */ | ||||
| static HANDLE | ||||
| get_full_privileged_inheritable_token (HANDLE token) | ||||
| { | ||||
|   if (wincap.has_mandatory_integrity_control ()) | ||||
|     { | ||||
|       TOKEN_LINKED_TOKEN linked; | ||||
|       DWORD size; | ||||
|  | ||||
|       /* When fetching the linked token without TCB privs, then the linked | ||||
| 	 token is not a primary token, only an impersonation token, which is | ||||
| 	 not suitable for CreateProcessAsUser.  Converting it to a primary | ||||
| 	 token using DuplicateTokenEx does NOT work for the linked token in | ||||
| 	 this case.  So we have to switch on TCB privs to get a primary token. | ||||
| 	 This is generally performed in the calling functions.  */ | ||||
|       if (GetTokenInformation (token, TokenLinkedToken, | ||||
| 			       (PVOID) &linked, sizeof linked, &size)) | ||||
| 	{ | ||||
| 	  debug_printf ("Linked Token: %p", linked.LinkedToken); | ||||
| 	  if (linked.LinkedToken) | ||||
| 	    { | ||||
| 	      TOKEN_TYPE type; | ||||
|  | ||||
| 	      /* At this point we don't know if the user actually had TCB | ||||
| 		 privileges.  Check if the linked token is a primary token. | ||||
| 		 If not, just return the original token. */ | ||||
| 	      if (GetTokenInformation (token, TokenType, (PVOID) &type, | ||||
| 				       sizeof type, &size) | ||||
| 		  && type != TokenPrimary) | ||||
| 		debug_printf ("Linked Token is not a primary token!"); | ||||
| 	      else | ||||
| 		{ | ||||
| 		  CloseHandle (token); | ||||
| 		  token = linked.LinkedToken; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   if (!SetHandleInformation (token, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) | ||||
|     { | ||||
|       __seterrno (); | ||||
|       CloseHandle (token); | ||||
|       token = NULL; | ||||
|     } | ||||
|   return token; | ||||
| } | ||||
|  | ||||
| void | ||||
| set_imp_token (HANDLE token, int type) | ||||
| { | ||||
| @@ -104,12 +156,14 @@ cygwin_logon_user (const struct passwd *pw, const char *password) | ||||
|       __seterrno (); | ||||
|       hToken = INVALID_HANDLE_VALUE; | ||||
|     } | ||||
|   else if (!SetHandleInformation (hToken, | ||||
| 				  HANDLE_FLAG_INHERIT, | ||||
| 				  HANDLE_FLAG_INHERIT)) | ||||
|   else | ||||
|     { | ||||
|       __seterrno (); | ||||
|       CloseHandle (hToken); | ||||
|       /* See the comment in get_full_privileged_inheritable_token for a | ||||
|       description why we enable TCB privileges here. */ | ||||
|       push_self_privilege (SE_TCB_PRIVILEGE, true); | ||||
|       hToken = get_full_privileged_inheritable_token (hToken); | ||||
|       pop_self_privilege (); | ||||
|       if (!hToken) | ||||
| 	hToken = INVALID_HANDLE_VALUE; | ||||
|     } | ||||
|   cygheap->user.reimpersonate (); | ||||
| @@ -1086,27 +1140,7 @@ lsaauth (cygsid &usersid, user_groups &new_groups, struct passwd *pw) | ||||
| #endif /* JUST_ANOTHER_NONWORKING_SOLUTION */ | ||||
|       LsaFreeReturnBuffer (profile); | ||||
|     } | ||||
|  | ||||
|   if (wincap.has_mandatory_integrity_control ()) | ||||
|     { | ||||
|       TOKEN_LINKED_TOKEN linked; | ||||
|  | ||||
|       if (GetTokenInformation (user_token, TokenLinkedToken, | ||||
| 			       (PVOID) &linked, sizeof linked, &size)) | ||||
| 	{ | ||||
| 	  debug_printf ("Linked Token: %p", linked.LinkedToken); | ||||
| 	  if (linked.LinkedToken) | ||||
| 	    { | ||||
| 	      CloseHandle (user_token); | ||||
| 	      user_token = linked.LinkedToken; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   /* The token returned by LsaLogonUser is not inheritable.  Make it so. */ | ||||
|   if (!SetHandleInformation (user_token, HANDLE_FLAG_INHERIT, | ||||
| 			     HANDLE_FLAG_INHERIT)) | ||||
|     system_printf ("SetHandleInformation %E"); | ||||
|   user_token = get_full_privileged_inheritable_token (user_token); | ||||
|  | ||||
| out: | ||||
|   if (privs) | ||||
| @@ -1179,31 +1213,7 @@ lsaprivkeyauth (struct passwd *pw) | ||||
|       token = NULL; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (wincap.has_mandatory_integrity_control ()) | ||||
| 	{ | ||||
| 	  TOKEN_LINKED_TOKEN linked; | ||||
| 	  DWORD size; | ||||
|  | ||||
| 	  if (GetTokenInformation (token, TokenLinkedToken, | ||||
| 				   (PVOID) &linked, sizeof linked, &size)) | ||||
| 	    { | ||||
| 	      debug_printf ("Linked Token: %p", linked.LinkedToken); | ||||
| 	      if (linked.LinkedToken) | ||||
| 		{ | ||||
| 		  CloseHandle (token); | ||||
| 		  token = linked.LinkedToken; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|       if (!SetHandleInformation (token, HANDLE_FLAG_INHERIT, | ||||
| 				 HANDLE_FLAG_INHERIT)) | ||||
| 	{ | ||||
| 	  __seterrno (); | ||||
| 	  CloseHandle (token); | ||||
| 	  token = NULL; | ||||
| 	} | ||||
|     } | ||||
|     token = get_full_privileged_inheritable_token (token); | ||||
|  | ||||
| out: | ||||
|   close_local_policy (lsa); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user