summaryrefslogtreecommitdiff
path: root/winsup/cygwin/syscalls.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/syscalls.cc')
-rw-r--r--winsup/cygwin/syscalls.cc125
1 files changed, 54 insertions, 71 deletions
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 5625f1a1eb8..91b533f19c4 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -29,7 +29,6 @@ details. */
#include <process.h>
#include <utmp.h>
#include <sys/uio.h>
-#include <errno.h>
#include <limits.h>
#include <unistd.h>
#include <setjmp.h>
@@ -1539,8 +1538,6 @@ getpagesize ()
static int
check_posix_perm (const char *fname, int v)
{
- extern int allow_ntea, allow_ntsec, allow_smbntsec;
-
/* Windows 95/98/ME don't support file system security at all. */
if (!wincap.has_security ())
return 0;
@@ -2123,66 +2120,52 @@ seteuid32 (__uid32_t uid)
sigframe thisframe (mainthread);
cygsid usersid;
user_groups &groups = cygheap->user.groups;
- HANDLE ptok, sav_token;
- BOOL sav_impersonated, sav_token_is_internal_token;
- BOOL process_ok, explicitly_created_token = FALSE;
+ HANDLE ptok, new_token = INVALID_HANDLE_VALUE;
struct passwd * pw_new;
PSID origpsid, psid2 = NO_SID;
+ enum impersonation new_state = IMP_BAD;
+ BOOL token_is_internal;
pw_new = internal_getpwuid (uid);
if (!wincap.has_security () && pw_new)
- goto success;
+ goto success_9x;
if (!usersid.getfrompw (pw_new))
{
set_errno (EINVAL);
return -1;
}
- /* Save current information */
- sav_token = cygheap->user.token;
- sav_impersonated = cygheap->user.impersonated;
RevertToSelf ();
if (!OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &ptok))
{
__seterrno ();
- goto failed;
+ goto failed_ptok;;
}
- /* Verify if the process token is suitable.
- Currently we do not try to differentiate between
- internal tokens and others */
- process_ok = verify_token (ptok, usersid, groups);
- debug_printf ("Process token %sverified", process_ok ? "" : "not ");
- if (process_ok)
+
+ /* Verify if the process token is suitable. */
+ if (verify_token (ptok, usersid, groups))
+ new_state = IMP_NONE;
+ /* Verify if a current token is suitable */
+ else if (cygheap->user.external_token
+ && verify_token (cygheap->user.external_token, usersid, groups))
{
- if (cygheap->user.issetuid ())
- cygheap->user.impersonated = FALSE;
- else
- {
- CloseHandle (ptok);
- goto success; /* No change */
- }
+ new_token = cygheap->user.external_token;
+ new_state = IMP_EXTERNAL;
+ }
+ else if (cygheap->user.internal_token
+ && verify_token (cygheap->user.internal_token, usersid, groups,
+ &token_is_internal))
+ {
+ new_token = cygheap->user.internal_token;
+ new_state = IMP_INTERNAL;
}
- if (!process_ok && cygheap->user.token != INVALID_HANDLE_VALUE)
+ debug_printf ("New token %d, state %d", new_token, new_state);
+ /* Return if current token is valid */
+ if (cygheap->user.impersonation_state == new_state)
{
- /* Verify if the current tokem is suitable */
- BOOL token_ok = verify_token (cygheap->user.token, usersid, groups,
- &sav_token_is_internal_token);
- debug_printf ("Thread token %d %sverified",
- cygheap->user.token, token_ok?"":"not ");
- if (!token_ok)
- cygheap->user.token = INVALID_HANDLE_VALUE;
- else
- {
- /* Return if current token is valid */
- if (cygheap->user.impersonated)
- {
- CloseHandle (ptok);
- if (!ImpersonateLoggedOnUser (cygheap->user.token))
- system_printf ("Impersonating in seteuid failed: %E");
- goto success; /* No change */
- }
- }
+ cygheap->user.reimpersonate ();
+ goto success; /* No change */
}
/* Set process def dacl to allow access to impersonated token */
@@ -2198,72 +2181,72 @@ seteuid32 (__uid32_t uid)
debug_printf ("SetTokenInformation"
"(TokenDefaultDacl): %E");
}
- CloseHandle (ptok);
- if (!process_ok && cygheap->user.token == INVALID_HANDLE_VALUE)
+ if (new_state == IMP_BAD)
{
/* If no impersonation token is available, try to
authenticate using NtCreateToken () or subauthentication. */
- cygheap->user.token = create_token (usersid, groups, pw_new);
- if (cygheap->user.token != INVALID_HANDLE_VALUE)
- explicitly_created_token = TRUE;
- else
+ new_token = create_token (usersid, groups, pw_new);
+ if (new_token == INVALID_HANDLE_VALUE)
{
/* create_token failed. Try subauthentication. */
debug_printf ("create token failed, try subauthentication.");
- cygheap->user.token = subauth (pw_new);
- if (cygheap->user.token == INVALID_HANDLE_VALUE)
+ new_token = subauth (pw_new);
+ if (new_token == INVALID_HANDLE_VALUE)
goto failed;
}
+ new_state = IMP_INTERNAL;
}
/* If using the token, set info and impersonate */
- if (!process_ok)
+ if (new_state != IMP_NONE)
{
/* If the token was explicitly created, all information has
already been set correctly. */
- if (!explicitly_created_token)
+ if (new_state == IMP_EXTERNAL)
{
/* Try setting owner to same value as user. */
- if (!SetTokenInformation (cygheap->user.token, TokenOwner,
+ if (!SetTokenInformation (new_token, TokenOwner,
&usersid, sizeof usersid))
debug_printf ("SetTokenInformation(user.token, "
"TokenOwner): %E");
/* Try setting primary group in token to current group */
- if (!SetTokenInformation (cygheap->user.token,
+ if (!SetTokenInformation (new_token,
TokenPrimaryGroup,
&groups.pgsid, sizeof (cygsid)))
debug_printf ("SetTokenInformation(user.token, "
"TokenPrimaryGroup): %E");
}
- /* Now try to impersonate. */
- if (!ImpersonateLoggedOnUser (cygheap->user.token))
+ /* Try to impersonate. */
+ if (!ImpersonateLoggedOnUser (new_token))
{
debug_printf ("ImpersonateLoggedOnUser %E");
__seterrno ();
goto failed;
}
- cygheap->user.impersonated = TRUE;
+ /* Keep at most one internal token */
+ if (new_state == IMP_INTERNAL)
+ {
+ if (cygheap->user.internal_token)
+ CloseHandle (cygheap->user.internal_token);
+ cygheap->user.internal_token = new_token;
+ }
}
-
- /* If sav_token was internally created and is replaced, destroy it. */
- if (sav_token != INVALID_HANDLE_VALUE &&
- sav_token != cygheap->user.token &&
- sav_token_is_internal_token)
- CloseHandle (sav_token);
cygheap->user.set_sid (usersid);
+
success:
+ CloseHandle (ptok);
+ cygheap->user.impersonation_state = new_state;
+success_9x:
cygheap->user.set_name (pw_new->pw_name);
myself->uid = uid;
groups.ischanged = FALSE;
return 0;
failed:
- cygheap->user.token = sav_token;
- cygheap->user.impersonated = sav_impersonated;
- if (cygheap->user.issetuid ()
- && !ImpersonateLoggedOnUser (cygheap->user.token))
- system_printf ("Impersonating in seteuid failed: %E");
+ CloseHandle (ptok);
+failed_ptok:
+ cygheap->user.reimpersonate ();
return -1;
}
@@ -2344,7 +2327,7 @@ setegid32 (__gid32_t gid)
/* If impersonated, update primary group and revert */
if (cygheap->user.issetuid ())
{
- if (!SetTokenInformation (cygheap->user.token,
+ if (!SetTokenInformation (cygheap->user.token (),
TokenPrimaryGroup,
&gsid, sizeof gsid))
debug_printf ("SetTokenInformation(thread, "
@@ -2362,7 +2345,7 @@ setegid32 (__gid32_t gid)
CloseHandle (ptok);
}
if (cygheap->user.issetuid ()
- && !ImpersonateLoggedOnUser (cygheap->user.token))
+ && !ImpersonateLoggedOnUser (cygheap->user.token ()))
system_printf ("Impersonating in setegid failed: %E");
return 0;
}