aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2002-05-27 11:48:15 +0000
committerCorinna Vinschen <corinna@vinschen.de>2002-05-27 11:48:15 +0000
commit75bf29315323634e7e4258a9e1b417b5bd5d135c (patch)
tree459c818e0ffe9fe1aac5248f2a62ee3d2c956db6
parent31be92431487bf61d385a9499caf803ba49e4a05 (diff)
downloadnewlib-75bf29315323634e7e4258a9e1b417b5bd5d135c.zip
newlib-75bf29315323634e7e4258a9e1b417b5bd5d135c.tar.gz
newlib-75bf29315323634e7e4258a9e1b417b5bd5d135c.tar.bz2
* syscalls.cc (seteuid): Do not take allow_ntsec into account.
Attempt to use an existing or new token even when the uid matches orig_uid, but the gid is not in the process token. Major reorganization after several incremental changes. (setegid): Do not take allow_ntsec into account. Minor reorganization after several incremental changes.
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/syscalls.cc458
2 files changed, 225 insertions, 242 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 7eb4250..764f43a 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,12 @@
+2002-05-22 Pierre Humblet <pierre.humblet@ieee.org>
+
+ * syscalls.cc (seteuid): Do not take allow_ntsec into account.
+ Attempt to use an existing or new token even when the uid
+ matches orig_uid, but the gid is not in the process token.
+ Major reorganization after several incremental changes.
+ (setegid): Do not take allow_ntsec into account. Minor
+ reorganization after several incremental changes.
+
2002-05-26 Christopher Faylor <cgf@redhat.com>
* debug.h (being_debugged): New macro.
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index ff3a409..fb1aaba 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1938,274 +1938,248 @@ extern struct passwd *internal_getlogin (cygheap_user &user);
extern "C" int
seteuid (__uid16_t uid)
{
+ if (!wincap.has_security ()) return 0;
+
+ if (uid == ILLEGAL_UID)
+ {
+ debug_printf ("new euid == illegal euid, nothing happens");
+ return 0;
+ }
+
sigframe thisframe (mainthread);
- if (wincap.has_security ())
+ DWORD ulen = UNLEN + 1;
+ DWORD dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
+ char orig_username[UNLEN + 1];
+ char orig_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ char username[UNLEN + 1];
+ char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
+ cygsid usersid, pgrpsid;
+ HANDLE ptok, sav_token;
+ BOOL sav_impersonated, sav_token_is_internal_token;
+ BOOL process_ok, explicitly_created_token = FALSE;
+ struct passwd * pw_new, * pw_cur;
+ cygheap_user user;
+ PSID origpsid, psid2 = NO_SID;
+
+ debug_printf ("uid: %d myself->gid: %d", uid, myself->gid);
+
+ pw_new = getpwuid (uid);
+ if (!usersid.getfrompw (pw_new) ||
+ (!pgrpsid.getfromgr (getgrgid (myself->gid))))
{
- char orig_username[UNLEN + 1];
- char orig_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
- char username[UNLEN + 1];
- DWORD ulen = UNLEN + 1;
- char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1];
- DWORD dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1;
- SID_NAME_USE use;
+ set_errno (EINVAL);
+ return -1;
+ }
+ /* Save current information */
+ sav_token = cygheap->user.token;
+ sav_impersonated = cygheap->user.impersonated;
+ char *env;
+ orig_username[0] = orig_domain[0] = '\0';
+ if ((env = getenv ("USERNAME")))
+ strlcpy (orig_username, env, sizeof(orig_username));
+ if ((env = getenv ("USERDOMAIN")))
+ strlcpy (orig_domain, env, sizeof(orig_domain));
- if (uid == ILLEGAL_UID || uid == myself->uid)
- {
- debug_printf ("new euid == current euid, nothing happens");
- return 0;
- }
- struct passwd *pw_new = getpwuid (uid);
- if (!pw_new)
- {
- set_errno (EINVAL);
- return -1;
+ RevertToSelf();
+ if (!OpenProcessToken (GetCurrentProcess (),
+ TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &ptok))
+ {
+ __seterrno ();
+ goto failed;
+ }
+ /* 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, pgrpsid);
+ debug_printf("Process token %sverified", process_ok?"":"not ");
+ if (process_ok)
+ {
+ if (cygheap->user.token == INVALID_HANDLE_VALUE ||
+ ! cygheap->user.impersonated )
+ {
+ CloseHandle (ptok);
+ return 0; /* No change */
}
+ else cygheap->user.impersonated = FALSE;
+ }
- cygsid tok_usersid;
- DWORD siz;
-
- char *env;
- orig_username[0] = orig_domain[0] = '\0';
- if ((env = getenv ("USERNAME")))
- strncat (orig_username, env, UNLEN + 1);
- if ((env = getenv ("USERDOMAIN")))
- strncat (orig_domain, env, INTERNET_MAX_HOST_NAME_LENGTH + 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;
-
- HANDLE ptok = INVALID_HANDLE_VALUE;
- if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &ptok))
- debug_printf ("OpenProcessToken(): %E\n");
- else if (!GetTokenInformation (ptok, TokenUser, &tok_usersid,
- sizeof tok_usersid, &siz))
- debug_printf ("GetTokenInformation(): %E");
- else if (!LookupAccountSid (NULL, tok_usersid, username, &ulen,
- domain, &dlen, &use))
- debug_printf ("LookupAccountSid(): %E");
- else
- {
- setenv ("USERNAME", username, 1);
- setenv ("USERDOMAIN", domain, 1);
- }
- if (ptok != INVALID_HANDLE_VALUE)
+ if (!process_ok && cygheap->user.token != INVALID_HANDLE_VALUE)
+ {
+ /* Verify if the current tokem is suitable */
+ BOOL token_ok = verify_token (cygheap->user.token, usersid, pgrpsid,
+ & sav_token_is_internal_token);
+ debug_printf("Thread token %d %sverified",
+ cygheap->user.token, token_ok?"":"not ");
+ if (token_ok)
+ {
+ /* Return if current token is valid */
+ if (cygheap->user.impersonated)
+ {
CloseHandle (ptok);
+ if (!ImpersonateLoggedOnUser (cygheap->user.token))
+ system_printf ("Impersonating in seteuid failed: %E");
+ return 0; /* No change */
+ }
}
- else
- {
- cygsid usersid, pgrpsid, origsid;
- HANDLE sav_token = INVALID_HANDLE_VALUE;
- BOOL sav_impersonation;
- BOOL current_token_is_internal_token = FALSE;
- BOOL explicitely_created_token = FALSE;
-
- struct __group16 *gr = getgrgid (myself->gid);
- debug_printf ("myself->gid: %d, gr: %d", myself->gid, gr);
-
- usersid.getfrompw (pw_new);
- pgrpsid.getfromgr (gr);
-
- /* Only when ntsec is ON! */
- /* Check if new user == user of impersonation token and
- - if reasonable - new pgrp == pgrp of impersonation token. */
- if (allow_ntsec && cygheap->user.token != INVALID_HANDLE_VALUE)
- {
- if (!verify_token(cygheap->user.token, usersid, pgrpsid,
- & current_token_is_internal_token))
- {
- /* If not, RevertToSelf and close old token. */
- debug_printf ("tsid != usersid");
- RevertToSelf ();
- sav_token = cygheap->user.token;
- sav_impersonation = cygheap->user.impersonated;
- cygheap->user.token = INVALID_HANDLE_VALUE;
- cygheap->user.impersonated = FALSE;
- }
- }
+ else cygheap->user.token = INVALID_HANDLE_VALUE;
+ }
- /* Only when ntsec is ON! */
- /* If no impersonation token is available, try to
- authenticate using NtCreateToken() or subauthentication. */
- if (allow_ntsec && cygheap->user.token == INVALID_HANDLE_VALUE)
- {
- HANDLE ptok = INVALID_HANDLE_VALUE;
+ /* Set process def dacl to allow access to impersonated token */
+ char dacl_buf[MAX_DACL_LEN(5)];
+ if (usersid != (origpsid = cygheap->user.orig_sid())) psid2 = usersid;
+ if (sec_acl ((PACL) dacl_buf, FALSE, origpsid, psid2))
+ {
+ TOKEN_DEFAULT_DACL tdacl;
+ tdacl.DefaultDacl = (PACL) dacl_buf;
+ if (!SetTokenInformation (ptok, TokenDefaultDacl,
+ &tdacl, sizeof dacl_buf))
+ debug_printf ("SetTokenInformation"
+ "(TokenDefaultDacl): %E");
+ }
+ CloseHandle (ptok);
- ptok = create_token (usersid, pgrpsid);
- if (ptok != INVALID_HANDLE_VALUE)
- explicitely_created_token = TRUE;
- else
- {
- /* create_token failed. Try subauthentication. */
- debug_printf ("create token failed, try subauthentication.");
- ptok = subauth (pw_new);
- }
- if (ptok != INVALID_HANDLE_VALUE)
- {
- cygwin_set_impersonation_token (ptok);
- /* If sav_token was internally created, destroy it. */
- if (sav_token != INVALID_HANDLE_VALUE &&
- current_token_is_internal_token)
- CloseHandle (sav_token);
- }
- else if (sav_token != INVALID_HANDLE_VALUE)
- cygheap->user.token = sav_token;
- }
- /* If no impersonation is active but an impersonation
- token is available, try to impersonate. */
- if (cygheap->user.token != INVALID_HANDLE_VALUE &&
- !cygheap->user.impersonated)
- {
- debug_printf ("Impersonate (uid == %d)", uid);
- RevertToSelf ();
-
- /* If the token was explicitely created, all information has
- already been set correctly. */
- if (!explicitely_created_token)
- {
- /* Try setting owner to same value as user. */
- if (usersid &&
- !SetTokenInformation (cygheap->user.token, TokenOwner,
- &usersid, sizeof usersid))
- debug_printf ("SetTokenInformation(user.token, "
- "TokenOwner): %E");
- /* Try setting primary group in token to current group
- if token not explicitely created. */
- if (pgrpsid &&
- !SetTokenInformation (cygheap->user.token,
- TokenPrimaryGroup,
- &pgrpsid, sizeof pgrpsid))
- debug_printf ("SetTokenInformation(user.token, "
- "TokenPrimaryGroup): %E");
- }
- /* Set process def dacl to allow access to impersonated token */
- char dacl_buf[MAX_DACL_LEN(5)];
- origsid = cygheap->user.orig_sid ();
- if (usersid && origsid &&
- sec_acl((PACL) dacl_buf, FALSE, origsid, usersid))
- {
- HANDLE ptok = INVALID_HANDLE_VALUE;
- TOKEN_DEFAULT_DACL tdacl;
- tdacl.DefaultDacl = (PACL) dacl_buf;
- if (!OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_DEFAULT,
- &ptok))
- debug_printf ("OpenProcessToken(): %E");
- else
- {
- if (!SetTokenInformation (ptok, TokenDefaultDacl,
- &tdacl, sizeof dacl_buf))
- debug_printf ("SetTokenInformation"
- "(TokenDefaultDacl): %E");
- }
- if (ptok != INVALID_HANDLE_VALUE) CloseHandle (ptok);
- }
- /* Now try to impersonate. */
- if (!LookupAccountSid (NULL, usersid, username, &ulen,
- domain, &dlen, &use))
- debug_printf ("LookupAccountSid (): %E");
- else if (!ImpersonateLoggedOnUser (cygheap->user.token))
- system_printf ("Impersonating (%d) in set(e)uid failed: %E",
- cygheap->user.token);
- else
- {
- cygheap->user.impersonated = TRUE;
- setenv ("USERNAME", username, 1);
- setenv ("USERDOMAIN", domain, 1);
- }
- }
+ if (!process_ok && cygheap->user.token == INVALID_HANDLE_VALUE)
+ {
+ /* If no impersonation token is available, try to
+ authenticate using NtCreateToken() or subauthentication. */
+ cygheap->user.token = create_token (usersid, pgrpsid);
+ if (cygheap->user.token != INVALID_HANDLE_VALUE)
+ explicitly_created_token = TRUE;
+ else
+ {
+ /* 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) goto failed;
}
+ }
- 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;
- /* Unsetting these both env vars is necessary to get NetUserGetInfo()
- called in internal_getlogin (). Otherwise the wrong path is used
- after a user switch, probably. */
- unsetenv ("HOMEDRIVE");
- unsetenv ("HOMEPATH");
- 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);
- setenv ("USERNAME", orig_username, 1);
- setenv ("USERDOMAIN", orig_domain, 1);
- set_errno (EPERM);
- return -1;
+ /* Lookup username and domain before impersonating,
+ LookupAccountSid() returns a different answer afterwards. */
+ SID_NAME_USE use;
+ if (!LookupAccountSid (NULL, usersid, username, &ulen,
+ domain, &dlen, &use))
+ {
+ debug_printf ("LookupAccountSid (): %E");
+ __seterrno ();
+ goto failed;
+ }
+ /* If using the token, set info and impersonate */
+ if (! process_ok )
+ {
+ /* If the token was explicitly created, all information has
+ already been set correctly. */
+ if (!explicitly_created_token)
+ {
+ /* Try setting owner to same value as user. */
+ if (!SetTokenInformation (cygheap->user.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,
+ TokenPrimaryGroup,
+ &pgrpsid, sizeof pgrpsid))
+ debug_printf ("SetTokenInformation(user.token, "
+ "TokenPrimaryGroup): %E");
+ }
+ /* Now try to impersonate. */
+ if (!ImpersonateLoggedOnUser (cygheap->user.token))
+ {
+ debug_printf ("ImpersonateLoggedOnUser %E");
+ __seterrno ();
+ goto failed;
}
+ cygheap->user.impersonated = TRUE;
+ }
+
+ /* 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;
+ /* Unsetting these two env vars is necessary to get NetUserGetInfo()
+ called in internal_getlogin (). Otherwise the wrong path is used
+ after a user switch, probably. */
+ unsetenv ("HOMEDRIVE");
+ unsetenv ("HOMEPATH");
+ setenv ("USERDOMAIN", domain, 1);
+ setenv ("USERNAME", username, 1);
+ pw_cur = internal_getlogin (user);
+ if (pw_cur == pw_new)
+ {
+ /* 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);
myself->uid = uid;
cygheap->user = user;
+ return 0;
}
- else
- set_errno (ENOSYS);
- debug_printf ("real: %d, effective: %d", cygheap->user.real_uid, myself->uid);
- return 0;
+ 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);
+
+ failed:
+ setenv ("USERNAME", orig_username, 1);
+ setenv ("USERDOMAIN", orig_domain, 1);
+ cygheap->user.token = sav_token;
+ cygheap->user.impersonated = sav_impersonated;
+ if ( cygheap->user.token != INVALID_HANDLE_VALUE &&
+ cygheap->user.impersonated &&
+ !ImpersonateLoggedOnUser (cygheap->user.token))
+ system_printf ("Impersonating in seteuid failed: %E");
+ return -1;
}
/* setegid: from System V. */
extern "C" int
setegid (__gid16_t gid)
{
+ if ((!wincap.has_security ()) ||
+ (gid == ILLEGAL_GID))
+ return 0;
+
sigframe thisframe (mainthread);
- if (wincap.has_security ())
+ cygsid gsid;
+ HANDLE ptok;
+
+ if (!(gsid.getfromgr (getgrgid (gid))))
{
- if (gid != ILLEGAL_GID)
- {
- struct __group16 *gr;
+ set_errno (EINVAL);
+ return -1;
+ }
+ myself->gid = gid;
- if (!(gr = getgrgid (gid)))
- {
- set_errno (EINVAL);
- return -1;
- }
- myself->gid = gid;
- if (allow_ntsec)
- {
- cygsid gsid;
- HANDLE ptok;
-
- if (gsid.getfromgr (gr))
- {
- /* Remove impersonation */
- if (cygheap->user.token != INVALID_HANDLE_VALUE
- && cygheap->user.impersonated)
- {
- if (!SetTokenInformation (cygheap->user.token,
- TokenPrimaryGroup,
- &gsid, sizeof gsid))
- debug_printf ("SetTokenInformation(primary, "
- "TokenPrimaryGroup): %E");
- RevertToSelf ();
- }
- if (!OpenProcessToken (GetCurrentProcess (),
- TOKEN_ADJUST_DEFAULT,
- &ptok))
- debug_printf ("OpenProcessToken(): %E\n");
- else
- {
- if (!SetTokenInformation (ptok, TokenPrimaryGroup,
- &gsid, sizeof gsid))
- debug_printf ("SetTokenInformation(process, "
- "TokenPrimaryGroup): %E");
- CloseHandle (ptok);
- }
- if (cygheap->user.token != INVALID_HANDLE_VALUE
- && cygheap->user.impersonated)
- ImpersonateLoggedOnUser (cygheap->user.token);
- }
- }
- }
+ /* If impersonated, update primary group and revert */
+ if (cygheap->user.token != INVALID_HANDLE_VALUE
+ && cygheap->user.impersonated)
+ {
+ if (!SetTokenInformation (cygheap->user.token,
+ TokenPrimaryGroup,
+ &gsid, sizeof gsid))
+ debug_printf ("SetTokenInformation(thread, "
+ "TokenPrimaryGroup): %E");
+ RevertToSelf ();
}
+ if (!OpenProcessToken (GetCurrentProcess (),
+ TOKEN_ADJUST_DEFAULT,
+ &ptok))
+ debug_printf ("OpenProcessToken(): %E\n");
else
- set_errno (ENOSYS);
+ {
+ if (!SetTokenInformation (ptok, TokenPrimaryGroup,
+ &gsid, sizeof gsid))
+ debug_printf ("SetTokenInformation(process, "
+ "TokenPrimaryGroup): %E");
+ CloseHandle (ptok);
+ }
+ if (cygheap->user.token != INVALID_HANDLE_VALUE
+ && cygheap->user.impersonated
+ && !ImpersonateLoggedOnUser (cygheap->user.token))
+ system_printf ("Impersonating in setegid failed: %E");
return 0;
}