* 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:
Corinna Vinschen 2010-02-06 13:13:15 +00:00
parent ff348d86cc
commit b96600ef91
2 changed files with 74 additions and 52 deletions

View File

@ -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

View File

@ -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);