Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2001-05-01 01:19:42 +0400
committerCorinna Vinschen <corinna@vinschen.de>2001-05-01 01:19:42 +0400
commit57ff940dd40a53ec03e5f2b079239b41bd9c2859 (patch)
tree4de2380c00e04343fe81f4113a9142540901c4d4 /winsup/cygwin
parent965cecdfca617f99b5fab536e6f960201b12b2a4 (diff)
* autoload.cc: Add LoadDLLinitfunc for secur32.dll.
Add LoadDLLfuncEx statements for AllocateLocallyUniqueId@4, DuplicateTokenEx@24, LsaNtStatusToWinError@4, LsaDeregisterLogonProcess@4, LsaFreeReturnBuffer@4, LsaLogonUser@56, LsaLookupAuthenticationPackage@12, LsaRegisterLogonProcess@12, * environ.cc: Add extern declaration for `subauth_id'. (subauth_id_init): New function for setting `subauth_id'. (struct parse_thing): Add entry for `subauth_id'. * fork.cc (fork_parent): Call `RevertToSelf' and `ImpersonateLoggedOnUser' instead of `seteuid'. * security.cc: Define global variable `subauth_id'. (extract_nt_dom_user): New function. (cygwin_logon_user): Call `extract_nt_dom_user' now. (str2lsa): New static function. (str2buf2lsa): Ditto. (str2buf2uni): Ditto. (subauth): Ditto. * security.h: Add prototype for `subauth'. * spawn.cc (spawn_guts): Use cygheap->user.token only if impersonated. Use `cygsid' type. Remove impersonation before allowing access to workstation/desktop to everyone. Call `RevertToSelf' and `ImpersonateLoggedOnUser' instead of `seteuid'. * syscalls.cc (seteuid): Rearranged to allow using subauthentication to retrieve user tokens when needed.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog28
-rw-r--r--winsup/cygwin/autoload.cc32
-rw-r--r--winsup/cygwin/environ.cc15
-rw-r--r--winsup/cygwin/fork.cc6
-rw-r--r--winsup/cygwin/security.cc183
-rw-r--r--winsup/cygwin/security.h2
-rw-r--r--winsup/cygwin/spawn.cc52
-rw-r--r--winsup/cygwin/syscalls.cc148
8 files changed, 353 insertions, 113 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 309bcb267..4a868a8b5 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,31 @@
+Mon Apr 30 22:09:00 2001 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc: Add LoadDLLinitfunc for secur32.dll.
+ Add LoadDLLfuncEx statements for AllocateLocallyUniqueId@4,
+ DuplicateTokenEx@24, LsaNtStatusToWinError@4,
+ LsaDeregisterLogonProcess@4, LsaFreeReturnBuffer@4,
+ LsaLogonUser@56, LsaLookupAuthenticationPackage@12,
+ LsaRegisterLogonProcess@12,
+ * environ.cc: Add extern declaration for `subauth_id'.
+ (subauth_id_init): New function for setting `subauth_id'.
+ (struct parse_thing): Add entry for `subauth_id'.
+ * fork.cc (fork_parent): Call `RevertToSelf' and
+ `ImpersonateLoggedOnUser' instead of `seteuid'.
+ * security.cc: Define global variable `subauth_id'.
+ (extract_nt_dom_user): New function.
+ (cygwin_logon_user): Call `extract_nt_dom_user' now.
+ (str2lsa): New static function.
+ (str2buf2lsa): Ditto.
+ (str2buf2uni): Ditto.
+ (subauth): Ditto.
+ * security.h: Add prototype for `subauth'.
+ * spawn.cc (spawn_guts): Use cygheap->user.token only if impersonated.
+ Use `cygsid' type. Remove impersonation before allowing access to
+ workstation/desktop to everyone. Call `RevertToSelf' and
+ `ImpersonateLoggedOnUser' instead of `seteuid'.
+ * syscalls.cc (seteuid): Rearranged to allow using subauthentication
+ to retrieve user tokens when needed.
+
Mon Apr 30 20:26:00 2001 Corinna Vinschen <corinna@vinschen.de>
* uinfo.cc (internal_getlogin): Formatting change.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 374853977..4555d786f 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -129,6 +129,28 @@ LoadDLLinitfunc (ntdll)
return 0;
}
+LoadDLLinitfunc (secur32)
+{
+ HANDLE h;
+ static NO_COPY LONG here = -1L;
+
+ while (InterlockedIncrement (&here))
+ {
+ InterlockedDecrement (&here);
+ Sleep (0);
+ }
+
+ if (secur32_handle)
+ /* nothing to do */;
+ else if ((h = LoadLibrary ("secur32.dll")) != NULL)
+ secur32_handle = h;
+ else if (!secur32_handle)
+ api_fatal ("could not load secur32.dll, %E");
+
+ InterlockedDecrement (&here);
+ return 0; /* Already done by another thread? */
+}
+
LoadDLLinitfunc (user32)
{
HANDLE h;
@@ -271,12 +293,14 @@ LoadDLLfunc (AddAccessAllowedAce, 16, advapi32)
LoadDLLfunc (AddAccessDeniedAce, 16, advapi32)
LoadDLLfunc (AddAce, 20, advapi32)
LoadDLLfunc (AdjustTokenPrivileges, 24, advapi32)
+LoadDLLfuncEx (AllocateLocallyUniqueId, 4, advapi32, 1)
LoadDLLfunc (CopySid, 12, advapi32)
LoadDLLfunc (CreateProcessAsUserA, 44, advapi32)
LoadDLLfuncEx (CryptAcquireContextA, 20, advapi32, 1)
LoadDLLfuncEx (CryptGenRandom, 12, advapi32, 1)
LoadDLLfuncEx (CryptReleaseContext, 8, advapi32, 1)
LoadDLLfunc (DeregisterEventSource, 4, advapi32)
+LoadDLLfuncEx (DuplicateTokenEx, 24, advapi32, 1)
LoadDLLfunc (EqualSid, 8, advapi32)
LoadDLLfunc (GetAce, 12, advapi32)
LoadDLLfunc (GetFileSecurityA, 20, advapi32)
@@ -298,6 +322,7 @@ LoadDLLfunc (LogonUserA, 24, advapi32)
LoadDLLfunc (LookupAccountNameA, 28, advapi32)
LoadDLLfunc (LookupAccountSidA, 28, advapi32)
LoadDLLfunc (LookupPrivilegeValueA, 12, advapi32)
+LoadDLLfuncEx (LsaNtStatusToWinError, 4, advapi32, 1)
LoadDLLfunc (MakeSelfRelativeSD, 12, advapi32)
LoadDLLfunc (OpenProcessToken, 12, advapi32)
LoadDLLfunc (RegCloseKey, 4, advapi32)
@@ -334,6 +359,13 @@ LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)
LoadDLLfuncEx (ZwQuerySystemInformation, 16, ntdll, 1)
+LoadDLLinit (secur32)
+LoadDLLfuncEx (LsaDeregisterLogonProcess, 4, secur32, 1)
+LoadDLLfuncEx (LsaFreeReturnBuffer, 4, secur32, 1)
+LoadDLLfuncEx (LsaLogonUser, 56, secur32, 1)
+LoadDLLfuncEx (LsaLookupAuthenticationPackage, 12, secur32, 1)
+LoadDLLfuncEx (LsaRegisterLogonProcess, 12, secur32, 1)
+
LoadDLLinit (user32)
LoadDLLfunc (CharToOemA, 8, user32)
LoadDLLfunc (CharToOemBuffA, 12, user32)
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index 25985e614..cf2e75930 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -35,6 +35,7 @@ extern BOOL allow_winsymlinks;
extern BOOL strip_title_path;
extern int pcheck_case;
extern DWORD chunksize;
+extern int subauth_id;
BOOL reset_com = TRUE;
static BOOL envcache = TRUE;
@@ -446,6 +447,19 @@ codepage_init (const char *buf)
}
}
+static void
+subauth_id_init (const char *buf)
+{
+ if (!buf || !*buf)
+ return;
+
+ int i = strtol (buf, NULL, 0);
+
+ /* 0..127 are reserved by Microsoft, 132 is IIS subauthentication. */
+ if (i > 127 && i != 132 && i <= 255)
+ subauth_id = i;
+}
+
/* The structure below is used to set up an array which is used to
parse the CYGWIN environment variable or, if enabled, options from
the registry. */
@@ -482,6 +496,7 @@ struct parse_thing
{"smbntsec", {&allow_smbntsec}, justset, NULL, {{FALSE}, {TRUE}}},
{"reset_com", {&reset_com}, justset, NULL, {{FALSE}, {TRUE}}},
{"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
+ {"subauth_id", {func: &subauth_id_init}, isfunc, NULL, {{0}, {0}}},
{"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}},
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
{"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{FALSE}, {TRUE}}},
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 646dbee58..b3c96f7e5 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -436,7 +436,7 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll,
uid_t uid;
uid = geteuid();
if (cygheap->user.impersonated && cygheap->user.token != INVALID_HANDLE_VALUE)
- seteuid (cygheap->user.orig_uid);
+ RevertToSelf ();
ch.parent = hParent;
ch.cygheap = cygheap;
@@ -484,7 +484,7 @@ out:
/* Restore impersonation */
if (cygheap->user.impersonated
&& cygheap->user.token != INVALID_HANDLE_VALUE)
- seteuid (uid);
+ ImpersonateLoggedOnUser (cygheap->user.token);
return -1;
}
@@ -508,7 +508,7 @@ out:
/* Restore impersonation */
if (cygheap->user.impersonated && cygheap->user.token != INVALID_HANDLE_VALUE)
- seteuid (uid);
+ ImpersonateLoggedOnUser (cygheap->user.token);
ProtectHandle (pi.hThread);
/* Protect the handle but name it similarly to the way it will
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 9077676ac..9f5605ac0 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -24,6 +24,9 @@ details. */
#include <ctype.h>
#include <wingdi.h>
#include <winuser.h>
+#include <wininet.h>
+#include <ntsecapi.h>
+#include <subauth.h>
#include "cygerrno.h"
#include "perprocess.h"
#include "fhandler.h"
@@ -56,6 +59,39 @@ cygwin_set_impersonation_token (const HANDLE hToken)
}
}
+static void
+extract_nt_dom_user (const struct passwd *pw, char *domain, char *user)
+{
+ char buf[INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 2];
+ char *c;
+
+ strcpy (domain, "");
+ strcpy (buf, pw->pw_name);
+ debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos);
+ if (pw->pw_gecos)
+ {
+ if ((c = strstr (pw->pw_gecos, "U-")) != NULL &&
+ (c == pw->pw_gecos || c[-1] == ','))
+ {
+ buf[0] = '\0';
+ strncat (buf, c + 2, INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 1);
+ if ((c = strchr (buf, ',')) != NULL)
+ *c = '\0';
+ }
+ }
+ if ((c = strchr (buf, '\\')) != NULL)
+ {
+ *c++ = '\0';
+ strcpy (domain, buf);
+ strcpy (user, c);
+ }
+ else
+ {
+ strcpy (domain, "");
+ strcpy (user, buf);
+ }
+}
+
extern "C"
HANDLE
cygwin_logon_user (const struct passwd *pw, const char *password)
@@ -71,32 +107,13 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
return INVALID_HANDLE_VALUE;
}
- char *c, *nt_user, *nt_domain = NULL;
- char usernamebuf[256];
+ char nt_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ char nt_user[UNLEN + 1];
HANDLE hToken;
- strcpy (usernamebuf, pw->pw_name);
- debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos);
- if (pw->pw_gecos)
- {
- if ((c = strstr (pw->pw_gecos, "U-")) != NULL &&
- (c == pw->pw_gecos || c[-1] == ','))
- {
- usernamebuf[0] = '\0';
- strncat (usernamebuf, c + 2, 255);
- if ((c = strchr (usernamebuf, ',')) != NULL)
- *c = '\0';
- }
- }
- nt_user = usernamebuf;
- if ((c = strchr (nt_user, '\\')) != NULL)
- {
- nt_domain = nt_user;
- *c = '\0';
- nt_user = c + 1;
- }
+ extract_nt_dom_user (pw, nt_domain, nt_user);
debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password);
- if (!LogonUserA (nt_user, nt_domain, (char *) password,
+ if (!LogonUserA (nt_user, *nt_domain ? nt_domain : NULL, (char *) password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken)
@@ -111,6 +128,126 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
return hToken;
}
+static void
+str2lsa (LSA_STRING &tgt, const char *srcstr)
+{
+ tgt.Length = strlen(srcstr);
+ tgt.MaximumLength = tgt.Length + 1;
+ tgt.Buffer = (PCHAR) srcstr;
+}
+
+static void
+str2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr)
+{
+ tgt.Length = strlen(srcstr);
+ tgt.MaximumLength = tgt.Length + 1;
+ tgt.Buffer = (PCHAR) buf;
+ memcpy(buf, srcstr, tgt.MaximumLength);
+}
+
+static void
+str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr)
+{
+ tgt.Length = strlen(srcstr) * sizeof (WCHAR);
+ tgt.MaximumLength = tgt.Length + sizeof(WCHAR);
+ tgt.Buffer = (PWCHAR) buf;
+ mbstowcs (buf, srcstr, tgt.MaximumLength);
+}
+
+int subauth_id = 255;
+
+HANDLE
+subauth (struct passwd *pw)
+{
+ LSA_STRING name;
+ HANDLE lsa_hdl;
+ LSA_OPERATIONAL_MODE sec_mode;
+ NTSTATUS ret, ret2;
+ ULONG package_id, size;
+ struct {
+ LSA_STRING str;
+ CHAR buf[16];
+ } origin;
+ struct {
+ MSV1_0_LM20_LOGON auth;
+ WCHAR dombuf[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ WCHAR usrbuf[UNLEN + 1];
+ WCHAR wkstbuf[1];
+ CHAR authinf1[1];
+ CHAR authinf2[1];
+ } subbuf;
+ TOKEN_SOURCE ts;
+ PMSV1_0_LM20_LOGON_PROFILE profile;
+ LUID luid;
+ HANDLE user_token;
+ QUOTA_LIMITS quota;
+ char nt_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ char nt_user[UNLEN + 1];
+
+ set_process_privilege(SE_TCB_NAME);
+
+ /* Register as logon process. */
+ str2lsa (name, "Cygwin");
+ ret = LsaRegisterLogonProcess(&name, &lsa_hdl, &sec_mode);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaRegisterLogonProcess: %d", ret);
+ set_errno (LsaNtStatusToWinError(ret));
+ return INVALID_HANDLE_VALUE;
+ }
+ /* Get handle to MSV1_0 package. */
+ str2lsa (name, MSV1_0_PACKAGE_NAME);
+ ret = LsaLookupAuthenticationPackage(lsa_hdl, &name, &package_id);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaLookupAuthenticationPackage: %d", ret);
+ set_errno (LsaNtStatusToWinError(ret));
+ LsaDeregisterLogonProcess(lsa_hdl);
+ return INVALID_HANDLE_VALUE;
+ }
+ /* Create origin. */
+ str2buf2lsa (origin.str, origin.buf, "Cygwin");
+ /* Create token source. */
+ memcpy(ts.SourceName, "Cygwin.1", 8);
+ AllocateLocallyUniqueId(&ts.SourceIdentifier);
+ /* Get user information. */
+ extract_nt_dom_user (pw, nt_domain, nt_user);
+ /* Fill subauth with values. */
+ subbuf.auth.MessageType = MsV1_0NetworkLogon;
+ str2buf2uni(subbuf.auth.LogonDomainName, subbuf.dombuf, nt_domain);
+ str2buf2uni(subbuf.auth.UserName, subbuf.usrbuf, nt_user);
+ str2buf2uni(subbuf.auth.Workstation, subbuf.wkstbuf, "");
+ memcpy(subbuf.auth.ChallengeToClient, "12345678", MSV1_0_CHALLENGE_LENGTH);
+ str2buf2lsa(subbuf.auth.CaseSensitiveChallengeResponse, subbuf.authinf1, "");
+ str2buf2lsa(subbuf.auth.CaseInsensitiveChallengeResponse, subbuf.authinf2,"");
+ subbuf.auth.ParameterControl = 0 | (subauth_id << 24);
+ /* Try to logon... */
+ ret = LsaLogonUser(lsa_hdl, (PLSA_STRING) &origin, Network,
+ package_id, &subbuf, sizeof subbuf,
+ NULL, &ts, (PVOID *)&profile, &size,
+ &luid, &user_token, &quota, &ret2);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf ("LsaLogonUser: %d", ret);
+ set_errno (LsaNtStatusToWinError(ret));
+ LsaDeregisterLogonProcess(lsa_hdl);
+ return INVALID_HANDLE_VALUE;
+ }
+ LsaFreeReturnBuffer(profile);
+ /* Convert to primary token. */
+ SECURITY_ATTRIBUTES sa = { sizeof sa, NULL, TRUE };
+ HANDLE primary_token;
+ if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa,
+ SecurityImpersonation, TokenPrimary,
+ &primary_token))
+ {
+ CloseHandle (user_token);
+ return INVALID_HANDLE_VALUE;
+ }
+ CloseHandle (user_token);
+ return primary_token;
+}
+
/* read_sd reads a security descriptor from a file.
In case of error, -1 is returned and errno is set.
If sd_buf is too small, 0 is returned and sd_size
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index d56483b51..11bf7d938 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -66,6 +66,8 @@ LONG __stdcall write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_
BOOL __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
+/* Try a subauthentication. */
+HANDLE subauth (struct passwd *pw);
/* sec_helper.cc: Security helper functions. */
char *__stdcall convert_sid_to_string_sid (PSID psid, char *sid_str);
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 5ac823c8d..f67fa626a 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -578,7 +578,8 @@ skip_arg_parsing:
/* Preallocated buffer for `sec_user' call */
char sa_buf[1024];
- if (!hToken && cygheap->user.token != INVALID_HANDLE_VALUE)
+ if (!hToken && cygheap->user.impersonated
+ && cygheap->user.token != INVALID_HANDLE_VALUE)
hToken = cygheap->user.token;
const char *runpath = null_app_name ? NULL : (const char *) real_path;
@@ -607,6 +608,28 @@ skip_arg_parsing:
}
else
{
+ cygsid sid;
+ DWORD ret_len;
+ if (!GetTokenInformation (hToken, TokenUser, &sid, sizeof sid, &ret_len))
+ {
+ sid = NULL;
+ system_printf ("GetTokenInformation: %E");
+ }
+
+ /* Retrieve security attributes before setting psid to NULL
+ since it's value is needed by `sec_user'. */
+ PSECURITY_ATTRIBUTES sec_attribs = allow_ntsec && sid
+ ? sec_user (sa_buf, sid)
+ : &sec_all_nih;
+
+ /* Remove impersonation */
+ if (cygheap->user.impersonated
+ && cygheap->user.token != INVALID_HANDLE_VALUE)
+ RevertToSelf ();
+
+ /* Load users registry hive. */
+ load_registry_hive (sid);
+
/* allow the child to interact with our window station/desktop */
HANDLE hwst, hdsk;
SECURITY_INFORMATION dsi = DACL_SECURITY_INFORMATION;
@@ -625,31 +648,6 @@ skip_arg_parsing:
strcat (wstname, dskname);
si.lpDesktop = wstname;
- char tu[1024];
- PSID sid = NULL;
- DWORD ret_len;
- if (GetTokenInformation (hToken, TokenUser,
- (LPVOID) &tu, sizeof tu,
- &ret_len))
- sid = ((TOKEN_USER *) &tu)->User.Sid;
- else
- system_printf ("GetTokenInformation: %E");
-
- /* Retrieve security attributes before setting psid to NULL
- since it's value is needed by `sec_user'. */
- PSECURITY_ATTRIBUTES sec_attribs = allow_ntsec && sid
- ? sec_user (sa_buf, sid)
- : &sec_all_nih;
-
- /* Remove impersonation */
- uid_t uid = geteuid ();
- if (cygheap->user.impersonated
- && cygheap->user.token != INVALID_HANDLE_VALUE)
- seteuid (cygheap->user.orig_uid);
-
- /* Load users registry hive. */
- load_registry_hive (sid);
-
rc = CreateProcessAsUser (hToken,
runpath, /* image name - with full path */
one_line.buf, /* what was passed to exec */
@@ -666,7 +664,7 @@ skip_arg_parsing:
if (mode != _P_OVERLAY && mode != _P_VFORK
&& cygheap->user.impersonated
&& cygheap->user.token != INVALID_HANDLE_VALUE)
- seteuid (uid);
+ ImpersonateLoggedOnUser (cygheap->user.token);
}
MALLOC_CHECK;
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 48ffaf9ec..085c9cebb 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1964,68 +1964,96 @@ seteuid (uid_t uid)
}
if (uid != myself->uid)
- if (uid == cygheap->user.orig_uid)
- {
- debug_printf ("RevertToSelf () (uid == orig_uid, token=%d)",
- cygheap->user.token);
- RevertToSelf ();
- if (cygheap->user.token != INVALID_HANDLE_VALUE)
- cygheap->user.impersonated = FALSE;
- }
- else if (!cygheap->user.impersonated)
- {
- debug_printf ("Impersonate (uid == %d)", uid);
- RevertToSelf ();
- if (cygheap->user.token != INVALID_HANDLE_VALUE)
- {
- struct group *gr;
- cygsid sid;
- DWORD siz;
-
- /* Try setting owner to same value as user. */
- if (!GetTokenInformation (cygheap->user.token, TokenUser,
- &sid, sizeof sid, &siz))
- debug_printf ("GetTokenInformation(): %E");
- else if (!SetTokenInformation (cygheap->user.token,
- TokenOwner,
- &sid, sizeof sid))
- debug_printf ("SetTokenInformation(user.token, "
- "TokenOwner): %E");
- /* Try setting primary group in token to current group. */
- if ((gr = getgrgid (myself->gid)) &&
- get_gr_sid (sid, gr) &&
- !SetTokenInformation (cygheap->user.token,
- TokenPrimaryGroup,
- &sid, sizeof sid))
- debug_printf ("SetTokenInformation(user.token, "
- "TokenPrimaryGroup): %E");
-
- /* Now try to impersonate. */
- if (!ImpersonateLoggedOnUser (cygheap->user.token))
- system_printf ("Impersonate (%d) in set(e)uid failed: %E",
- cygheap->user.token);
- else
- cygheap->user.impersonated = TRUE;
- }
- }
-
- cygheap_user user;
- /* user.token is used in internal_getlogin () to determine if
- impersonation is active. If so, the token is used for
- retrieving user's SID. */
- user.token = cygheap->user.impersonated ? cygheap->user.token
- : INVALID_HANDLE_VALUE;
- struct passwd *pw_cur = internal_getlogin (user);
- if (pw_cur != pw_new)
{
- debug_printf ("Diffs!!! token: %d, cur: %d, new: %d, orig: %d",
- cygheap->user.token, pw_cur->pw_uid,
- pw_new->pw_uid, cygheap->user.orig_uid);
- set_errno (EPERM);
- return -1;
+ if (uid == cygheap->user.orig_uid)
+ {
+ debug_printf ("RevertToSelf () (uid == orig_uid, token=%d)",
+ cygheap->user.token);
+ RevertToSelf ();
+ if (cygheap->user.token != INVALID_HANDLE_VALUE)
+ cygheap->user.impersonated = FALSE;
+ }
+ else
+ {
+ cygsid tsid, psid, gsid;
+ DWORD siz;
+
+ /* Check if new user == user of impersonation token. */
+ if (cygheap->user.token != INVALID_HANDLE_VALUE)
+ {
+ if (!GetTokenInformation (cygheap->user.token, TokenUser,
+ &tsid, sizeof tsid, &siz))
+ debug_printf ("GetTokenInformation(): %E");
+ else if (get_pw_sid (psid, pw_new) && tsid != psid)
+ {
+ /* If not, RevertToSelf and close old token. */
+ RevertToSelf ();
+ cygwin_set_impersonation_token (INVALID_HANDLE_VALUE);
+ }
+ }
+ /* If no impersonation token is available, try to
+ authenticate using subauthentication. */
+ if (cygheap->user.token == INVALID_HANDLE_VALUE)
+ {
+ HANDLE ptok = subauth (pw_new);
+ if (ptok != INVALID_HANDLE_VALUE)
+ cygwin_set_impersonation_token (ptok);
+ else
+ cygheap->user.impersonated = TRUE;
+ }
+ /* If no impersonation is active but an impersonation
+ token is available, try to impersonate. */
+ if (!cygheap->user.impersonated)
+ {
+ debug_printf ("Impersonate (uid == %d)", uid);
+ RevertToSelf ();
+ if (cygheap->user.token != INVALID_HANDLE_VALUE)
+ {
+ struct group *gr;
+
+ /* Try setting owner to same value as user. */
+ if (!SetTokenInformation (cygheap->user.token,
+ TokenOwner,
+ &tsid, sizeof tsid))
+ debug_printf ("SetTokenInformation(user.token, "
+ "TokenOwner): %E");
+ /* Try setting primary group in token to current group. */
+ if ((gr = getgrgid (myself->gid)) &&
+ get_gr_sid (gsid, gr) &&
+ !SetTokenInformation (cygheap->user.token,
+ TokenPrimaryGroup,
+ &gsid, sizeof gsid))
+ debug_printf ("SetTokenInformation(user.token, "
+ "TokenPrimaryGroup): %E");
+
+ /* Now try to impersonate. */
+ if (!ImpersonateLoggedOnUser (cygheap->user.token))
+ system_printf ("Impersonating (%d) in set(e)uid "
+ "failed: %E", cygheap->user.token);
+ else
+ cygheap->user.impersonated = TRUE;
+ }
+ }
+ }
+
+ cygheap_user user;
+ /* user.token is used in internal_getlogin () to determine if
+ impersonation is active. If so, the token is used for
+ retrieving user's SID. */
+ user.token = cygheap->user.impersonated ? cygheap->user.token
+ : INVALID_HANDLE_VALUE;
+ struct passwd *pw_cur = internal_getlogin (user);
+ if (pw_cur != pw_new)
+ {
+ debug_printf ("Diffs!!! token: %d, cur: %d, new: %d, orig: %d",
+ cygheap->user.token, pw_cur->pw_uid,
+ pw_new->pw_uid, cygheap->user.orig_uid);
+ set_errno (EPERM);
+ return -1;
+ }
+ myself->uid = uid;
+ cygheap->user = user;
}
- myself->uid = uid;
- cygheap->user = user;
}
}
else