About the Unix privileges layer for Cygwin
------------------------------------------

This is a spin-off project from porting Sendmail and Procmail to Cygwin. These 
programs, as you may or may not know, rely heavily on the setuid  mechanism 
(impersonating as another user).
More formally, this is called 'running as an unprivileged user' in Linux and
'privilege separation' in OpenBSD. In Cygwin, this mechanism is already implemented
in the ssh daemon.

Sendmail takes this idea to the extreme. It starts up as the root user and waits for
connections. On connection, it starts the 'queue runner' program as an unprivileged
user called 'smmsp', which handles the conversation with the remote e-mail client. 

If the incoming e-mail has to be delivered locally (stored on disk), the queue
runner starts the procmail program, which in turn switches to the actual user the
e-mail is meant for and stores it in the user's inbox.

So, for instance sending an e-mail to myself involves switching through three users:
root -> smmsp -> daniel


The problem
-----------
Up to WinXP and Win2002, porting source code for Cygwin which performed this
switching of users, wasn't a big problem.

In Windows, it is the 'SYSTEM' user which starts up most services, thus in effect
acting as the Unix 'root' user. The difference is that SYSTEM has uid '18', while
root has uid '0' in Unix.

So, if porting from Unix to Cygwin one could just look for all occurances of uid '0'
and replace them with '18'. Actually, this technique has been used to create the
original Cygwin port of the Procmail program.

As of Win7 and Win2003 this will no longer work. For security reasons, the privilege
needed to impersonate another user (called 'SeCreateTokenPrivilege') has been
removed from the SYSTEM user.

Services (daemons) who need impersonation now have to be started by non-SYSTEM
users, which have been put in the 'Administrators' group and granted the
SeCreateTokenPrivilege. This works for most suid software, like the Apache
webserver, but not for Sendmail and Procmail.

Both programs *enforce* what is called the Privileges model in Unix. This means 
that both programs actually check if they are ran by root and if not, refuse 
to deliver e-mail. So, simply replacing '0' with '18' in the source code 
has no effect anymore.


The solution
------------ 
The solution to this problem turns out to be very simple and elegant: *tell*
Sendmail and Procmail who is the root user by overriding functions which involve
getting or setting user id's. 

For instance: make the getuid() function return '0' when the actual user id is '18'
and make the setuid() function change to uid '18' if the requested uid is '0'. Take 
this idea one step further and Sendmail and Procmail become 'multi-root aware'.

I created this library to do exacly that. On startup it assumes the root user id is
'18' (SYSTEM) and the root group id is '544' (Administrators). It overrides the
original getuid(), getgid(), etc. functions to return '0' if the actual uid/gid are
'18' or '544'.

The library makes its program 'multi-root aware' by checking if the non-SYSTEM user
is a member of the 'Administrators' group and if so, simply replacing *its* uid and
gid to be '0'. This totally satisfies Sendmail and Procmail.

More importantly: I didn't have to change a single line in their source code (which
would have been an awful lot), because the library is doing the swapping of
uids/gids in the background.


Usage
-----
To use this library, put '#include <fakesu.h>' and '-lfakesu' at a strategic
location in your source code and Makefile. To make your program 'multi-root' aware
and even do suid and/or sgid, place a call to 'fakesu(argv[0])' in your 'main()'
function and set the suid and/or sgid bits on the resulting binary.


2014, The Hague, The Netherlands
Daniel Boland
dboland@xs4all.nl


