Sometimes you want a CGI script to run as a different user than what the web server process is running as. This could be for added security, or to allow a certain script to have capabilities you’d never let the web server user have.
Cut back to OS X. In OS 9 and earlier, CGIs were controlled (mostly) by Apple Events. Apple Events were the (primary) Interapplication Communication method on OS 9, and, as a lesser extent, on OS X.
On OS 9, if a web user accessed a CGI script, Apple Events would be dispatched from the webserver to the appropriate CGI, and the CGI would do something. Now, if this was an Applescript CGI, it would (usually) talk to other applications via Apple Events.
In the brave new world of OS X, we have other ways of talking to processes, but some applications (ie: GUI applications) can only talk to external programs via Apple Events.
This poses a problem. Most routines in the Apple Event Manager require a window manager session - except, if you’ve been good, security-savvy admins, the currently logged in user is not the owner of the web server (usually Apache).
There is however a solution… Apache comes suexec, an application that will run certain CGI scripts as a different user. The disadvantage to suexec is that it has to be compiled when you compile Apache. This requirement assumes you have a forward thinking administrator that thinks about enabling suexec while they’re updating to the latest Apache.
Because of (well founded) security concerns, suexec is compiled off by default (even in the Apache install on OS X).
Seemingly at a dead-end, found cgiwrap. This wonderful piece of software plugs right into an existing Apache installation, correctly executes specified CGI scripts as another user, and is a very useful debugging aid for when your scripts go wrong.
The setup process was fairly easy - the hard part, like so many open-source projects, was deciphering/changing-instructions-for-my-setup/ignoring-parts-that-I-know-won’t-work-on-OSX the documentation. After I had everything set up, I was able to run my Apple Event CGI script as the logged in user - and it worked!
Here then, is how I did it:
Compiling And Setting Up cgiwrap
Download the cgiwrap package, untar it, then go into the newly created directory. `curl http://telia.dl.sourceforge.net/sourceforge/cgiwrap/cgiwrap-3.8.tar.gz > cgiwrap-3.8.tar.gz
tar -xzvf cgiwrap-3.8.tar.gz
Configure, the first
Now we need to configure the software. However, cgiwrap doesn’t know about OS X, so we have to copy config.guess and config.sub from packages that do understand about OS X. You can go find copies of these files yourself, or download both files here.
After you’ve download and extracted these files, copy them into the cgiwrap-3.8 folder, replacing existing.
Configure, the second
Now, we configure the software:
./configure --with-vhost-override --with-cgi-dir=/Library/WebServer/CGI-Executables/ --with-httpd-user=www --with-install-dir=/Library/WebServer/CGI-Executables
This command sets up cgiwrap to work in the default environment provided by OS X: Apache runs as the ‘www’ user, and the files should be installed in /Library/WebServer/CGI-Executables.
Notice the with-cgi-dir parameter. Currently this value means that cgiwrap will look for CGIs to execute in the the Library/WebServer/CGI-Executables folder of the specified user. This could, of course, be changed, but this seems like a safe place for these scripts (and away from the Sites folder).
Making the software is just like any other piece of unix software. Nothing special to see here.
make sudo make install
The second make command may give you the following error:
chgrp root /Library/WebServer/CGI-Executables/cgiwrap chgrp: root: Invalid argument make: *** [install] Error 1
If so, do the following commands, finishing the install steps manually:
cd /Library/WebServer/CGI-Executables/ chown root cgiwrap chmod 4755 cgiwrap ln -s cgiwrap cgiwrapd ln -s cgiwrap nph-cgiwrap ln -s cgiwrap nph-cgiwrapd
Now, we configure Apache to use cgiwrap. Open up /etc/httpd/httpd.conf in your favorite text editor and enter the following lines (and inserting the name the user you want to execute scripts as in the indicated place):
AddHandler cgi-wrapper .cgi AddHandler cgi-wrapper .py Action cgi-wrapper /cgi-bin/cgiwrapd
<Directory “/Users/[USER TO EXEC SCRIPTS AS]/Library/WebServer/CGI-Executables/”> Options All AllowOverride All
You also need to find the following chunk of code in httpd.conf:
<Directory "/Library/WebServer/CGI-Executables"> AllowOverride None Options None Order allow,deny Allow from all </Directory>
and change the Options line to:
After the editing you’ll have to restart apache. Execute the following commands:
sudo apachectl configtest sudo apachectl graceful
One last command to create the directories cgiwrap will look for our scripts in:
mkdir /Users/[USER TO EXEC SCRIPT AS]/Library/WebServer/ mkdir /Users/[USER TO EXEC SCRIPT AS]/Library/WebServer/CGI-Executables
Now We just need to copy a cgi script to /Users/[USER TO EXEC SCRIPT AS]/Library/WebServer/CGI-Executables/ to test your new cgiwrap enabled site out. Make sure this cgi has the permissions of 755.
Now, visit the following URL in your webbrowser, replacing the parts in brackets with things from your setup: http://\[localhost\]/cgi-bin/cgiwrap/\[USER TO EXEC SCRIPT AS]/[THE CGI FILE YOU MOVED].cgi
How cgiwrap works (and what it gives you)
cgiwrap does several (good) things:
First it will redirect requests for /cgi-bin/cgiwrap/ to a directory in [USER TO EXEC SCRIPT AS] (or UTESA)‘s home directory. A bit of security through obscurity here - while cgiwrap uses the home directory of UTESA, one would think this is hard to find out for a hacker trying to break in. You can use mod_rewrite to rewrite the URL displayed to the user, so they don’t know what (if anything) is going on
Execute As User
Secondly, it executes the requested CGI as UTESA. This means it can do all the things UTESA can - so extra care must be made while writing a cgi-script. (However, only files YOU have access to can get messed up). NOTE: you don’t want to have Admin (or, in unix: wheel) users running cgiwraped scripts. This could be bad. However, if you’re on OS X and writing CGI scripts that require the window manager (scripts that use AppleEvents, as we mentioned at the beginning of this article, for example) having the logged in user execute the cgi scripts is both useful and easy (and required, since most AE calls require an active window manager)
Thirdly, it (seems to?) provide as much security as suexec, without making the site admin recompile Apache themselves
Lastly, testing your scripts with cgiwrapd (http://127.0.0.1/cgi-bin/cgiwrapd/\[USER TO EXEC SCRIPT AS]/thefile.cgi) gives you WAY more debugging information than the standard apache error log/error message does.
I hope this entry is helpful to those people trying to run Apache servers on OS X - especially my fellow CGI coders that require AppleEvents for their work.
Updated 01-16-04 to include the following:
- Commands to make the /Users/[USER To..]/Library/ directories needed
- Added some missed options from the httpd.conf file
- Fixed non-html encoded entities (now encoded)
- Added additional commands to execute if make install fails