* 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.
This commit is contained in:
		@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -1938,274 +1938,248 @@ extern struct passwd *internal_getlogin (cygheap_user &user);
 | 
			
		||||
extern "C" int
 | 
			
		||||
seteuid (__uid16_t uid)
 | 
			
		||||
{
 | 
			
		||||
  sigframe thisframe (mainthread);
 | 
			
		||||
  if (wincap.has_security ())
 | 
			
		||||
  if (!wincap.has_security ()) return 0;
 | 
			
		||||
 | 
			
		||||
  if (uid == ILLEGAL_UID)
 | 
			
		||||
    {
 | 
			
		||||
      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;
 | 
			
		||||
      debug_printf ("new euid == illegal euid, nothing happens");
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
      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;
 | 
			
		||||
  sigframe thisframe (mainthread);
 | 
			
		||||
  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))))
 | 
			
		||||
    {
 | 
			
		||||
      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));
 | 
			
		||||
 | 
			
		||||
  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 cygheap->user.token = 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);
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
	{
 | 
			
		||||
	  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;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	  /* 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;
 | 
			
		||||
 | 
			
		||||
	      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);
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
        {
 | 
			
		||||
	  /* 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;
 | 
			
		||||
 | 
			
		||||
	  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);
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
      set_errno (EINVAL);
 | 
			
		||||
      return -1;
 | 
			
		||||
    }
 | 
			
		||||
  myself->gid = gid;
 | 
			
		||||
 | 
			
		||||
  /* 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user