diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2010-02-06 16:13:15 +0300 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2010-02-06 16:13:15 +0300 |
commit | b96600ef91059d539260c1b223c80c02072bf84d (patch) | |
tree | 8e9530c385cb321895850b5762e0eeaf847bbc4b /winsup/cygwin/sec_auth.cc | |
parent | ff348d86cc9ecbd5377afe4bb2d2f61e3e6bf1dc (diff) |
* 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.
Diffstat (limited to 'winsup/cygwin/sec_auth.cc')
-rw-r--r-- | winsup/cygwin/sec_auth.cc | 114 |
1 files changed, 62 insertions, 52 deletions
diff --git a/winsup/cygwin/sec_auth.cc b/winsup/cygwin/sec_auth.cc index 2a557a532..2cdf35235 100644 --- a/winsup/cygwin/sec_auth.cc +++ b/winsup/cygwin/sec_auth.cc @@ -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,13 +156,15 @@ 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); - hToken = INVALID_HANDLE_VALUE; + /* 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 (); debug_printf ("%d = logon_user(%s,...)", hToken, pw->pw_name); @@ -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); |