summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2010-02-06 13:13:15 +0000
committerCorinna Vinschen <corinna@vinschen.de>2010-02-06 13:13:15 +0000
commitb96600ef91059d539260c1b223c80c02072bf84d (patch)
tree8e9530c385cb321895850b5762e0eeaf847bbc4b
parentff348d86cc9ecbd5377afe4bb2d2f61e3e6bf1dc (diff)
downloadcygnal-b96600ef91059d539260c1b223c80c02072bf84d.tar.gz
cygnal-b96600ef91059d539260c1b223c80c02072bf84d.tar.bz2
cygnal-b96600ef91059d539260c1b223c80c02072bf84d.zip
* 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.
-rw-r--r--winsup/cygwin/ChangeLog12
-rw-r--r--winsup/cygwin/sec_auth.cc114
2 files changed, 74 insertions, 52 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3de4f4465..a4a66b310 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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
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);