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