This is the mail archive of the cygwin-patches mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Patch] Allow to disable root privileges with CYGWIN=noroot


Hi Christian,

On Sep  1 20:32, Corinna Vinschen wrote:
> On Aug 30 21:38, Christian Franke wrote:
> > Corinna Vinschen wrote:
> >> If you plan to run a Cygwin application with restricted rights from your
> >> administrative account, the IMHO right way would be to start the Cygwin
> >> application through another application which creates a *really*
> >> restricted user token using the Win32 function CreateRestrictedToken and
> >> then call cygwin_set_impersonation_token/execv to start the restricted
> >> process.  A Cygwin tool which accomplishes that would be much more
> >> useful and much more generic than this patch, IMHO.
> >>
> >>   
> > I agree, let's forget the patch.
> >
> > But I'm not sure how cygwin_set_impersonation_token() could be of any  
> > help here. This function sets user.external_token which is only used in  
> > seteuid32(). Setuid/seteuid() cannot be used because the restricted  
> > token is not related to another user id.
> 
> I had a quick look into the seteuid code and I see the problem.  I don't
> see a quick way around it, unfortunately.  I'll have a deeper look into
> it when I'm back from vacation.

It took some time, but today it occured to me how we could solve this
issue.

The functionality we're talking about is not creating a new token from
scratch, like an external call to LogonUser would create.  It's just
creating a restricted token for the same user, and fortunately there's a
function IsTokenRestricted() in the Win32 API, available since Windows
2000.

However, we can't just simply test for a restricted token since
restricted tokens are used a lot under UAC starting with Windows Vista.
Therefore the idea is that a restricted token is only recogized as a
special case if you call setuid(getuid()) or seteuid(geteuid()).

So, to use a restricted token, you call code along these lines:

  restricted_token = CreateRestrictedToken();
  /* Switch to restricted token. */
  cygwin_set_impersonation_token (restricted_token);
  setuid (getuid ());
  /* Do stuff with restricted rights */
  [...]
  /* Revert process to original token. */
  cygwin_set_impersonation_token (INVALID_HANDLE_VALUE);
  setuid (getuid ());

I created a patch to seteuid32 which compiles fine.  It just needs
testing.  Since you're interested in this functionality in the first
place, I thought you might consider to give this a nice, thorough test.

Patch attached.  For simplicity I just applied the patch to the w32api
winbase.h header file which defines CreateRestrictedToken and
IsTokenRestricted.


Thanks,
Corinna


	* autoload.cc (IsTokenRestricted): Define.
	* syscalls.cc (seteuid32): Create special case for restricted
	external tokens to switch to a restricted token for the current
	user.


Index: autoload.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/autoload.cc,v
retrieving revision 1.165
diff -u -p -r1.165 autoload.cc
--- autoload.cc	22 Sep 2009 14:27:57 -0000	1.165
+++ autoload.cc	4 Oct 2009 12:24:56 -0000
@@ -422,6 +422,8 @@ LoadDLLfuncEx (GetSystemDEPPolicy, 0, ke
 LoadDLLfuncEx (GetProcessDEPPolicy, 12, kernel32, 1)
 LoadDLLfuncEx (SetProcessDEPPolicy, 4, kernel32, 1)
 
+LoadDLLfunc (IsTokenRestricted, 4, advapi32)
+
 LoadDLLfunc (SHGetDesktopFolder, 4, shell32)
 
 LoadDLLfuncEx (waveOutGetNumDevs, 0, winmm, 1)
Index: syscalls.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.540
diff -u -p -r1.540 syscalls.cc
--- syscalls.cc	4 Oct 2009 11:32:07 -0000	1.540
+++ syscalls.cc	4 Oct 2009 12:24:57 -0000
@@ -2664,7 +2664,30 @@ seteuid32 (__uid32_t uid)
   debug_printf ("uid: %u myself->uid: %u myself->gid: %u",
 		uid, myself->uid, myself->gid);
 
-  if (uid == myself->uid && !cygheap->user.groups.ischanged)
+  /* Same uid as we're just running under is usually a no-op.
+  
+     Except we have an external token which is a restricted token.  Or,
+     the external token is NULL, but the current impersonation token is
+     a restricted token.  This allows to restrict user rights temporarily
+     like this:
+
+       cygwin_set_impersonation_token (restricted_token);
+       setuid (getuid ());
+       [...do stuff with restricted rights...]
+       cygwin_set_impersonation_token (INVALID_HANDLE_VALUE);
+       setuid (getuid ());
+
+    Note that using the current uid is a requirement!  Starting with Windows
+    Vista, we have restricted tokens galore (UAC), so this is really just
+    a special case to restict your own processes to lesser rights. */
+  bool request_restricted_uid_switch =
+     uid == myself->uid
+     && (   (cygheap->user.external_token != NO_IMPERSONATION
+	     && IsTokenRestricted (cygheap->user.external_token))
+	 || (cygheap->user.external_token == NO_IMPERSONATION
+	     && IsTokenRestricted (cygheap->user.curr_primary_token)));
+  if (uid == myself->uid && !cygheap->user.groups.ischanged
+      && !request_restricted_uid_switch)
     {
       debug_printf ("Nothing happens");
       return 0;
@@ -2686,6 +2709,21 @@ seteuid32 (__uid32_t uid)
   cygheap->user.deimpersonate ();
 
   /* Verify if the process token is suitable. */
+  /* First of all, skip all checks if a switch to a restricted token has been
+     requested, or if trying to switch back from it. */
+  if (request_restricted_uid_switch)
+    {
+      if (cygheap->user.external_token != NO_IMPERSONATION)
+      	{
+	  debug_printf ("Switch to restricted token");
+	  new_token = cygheap->user.external_token;
+	}
+      else
+      	{
+	  debug_printf ("Switch back from restricted token");
+	  new_token = hProcToken;
+	}
+    }
   /* TODO, CV 2008-11-25: The check against saved_sid is a kludge and a
      shortcut.  We must check if it's really feasible in the long run.
      The reason to add this shortcut is this:  sshd switches back to the


-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]