
                                 MOD_DIFFPRIVS

               A p a c h e      S e c u r i t y        M o d u l e

Make Apache configurable to work with diffrent uid/gid and chroot environment
for each <VirtualServer>. Distributed under GNU General Public License. 
Author: Lukasz Wojtow <lw@ftw.zamosc.pl>
Require: Apache httpd 1.3.x (it doesn't work for 2.0 yet)
Interesting ideas: Rafal Wijata <www.wijata.com>
Latest version available at: http://sourceforge.net/projects/moddiffprivs/ and
			     http://lw.ftw.zamosc.pl/mdp

This module provides three configuration directives: 
- "Privs", 
- "PrivsGroups", 
- "PrivsUser"
- "PrivsAllowJumpVisits"	-	obsoleted, now always Off

All directives may be used in main server configuration or/and in 
<VirtualServer> section.

1. Privs
   This is a core directive in mod_diffprivs. It takes one, two or three 
   arguments. 
      First is an user on what Apache should call setuid() before serving file. 
   This parameter can be given as username, or #uid. When You decide to use
   "username", then Apache will try to find this user in /etc/passwd file when 
   starting. This parameter can be also "DoNothing", what mean don't call 
   setuid(). Setuid can be call only for numbers equal or above hardcoded 
   constant MIN_UID. You can change this value by editing file config.h.
     Second parameter is a group on what apache should call setgid() before
   serving file. This parameter can be groupname or #gid. When You decide
   to use "groupname", then Apache will find this group in file /etc/groups 
   when starting. This parameter can be also "DoNothing", what mean don't call
   setgid.  Setgid() can be call only for numbers equal or above the hardcoded 
   constant MIN_GID. You can change this value be editing file config.h
     Third parameter for directive "Privs" is a path to dir where chroot() will
   be call before serving file. When You use it, remember about changing all 
   paths in this configuration section. For example, was:
        DocumentRoot "/www/htdocs/tris"
        ScriptAlias  /cgi-bin/ "/www/htdocs/tris/cgi-bin"
   and You want use
        Privs nobody nobody "/www/htdocs/"
   You must change DocumentRoot and ScriptAlias (and others) to:
        DocumentRoot "/tris/"
        ScriptAlias /cgi-bin/ "/tris/cgi-bin/"
   This directory must be under hardcoded constant UNDER_HERE. You can change
   this value by editing (well.. guess) config.h file. This directive affects 
   only requests like www.whatever.com/blablabla.html but not 
   www.whatever.com/~user.

2. PrivsGroups
   When You use directive Privs for some server and want to change gid, 
   then probably setgid() leaves groups[0] to old gid. This is bad for security 
   reasons, beacuse when You want change only gid (as me), then changes are 
   don't take effect. Normally processes have to call setgroups(0,NULL) to 
   clear their groups table. This is done by this directive, it takes flag 
   "On" or "Off", and make Apache call (or not) setgroups(0,NULL). The default 
   value is Off. Remember about security consequences: sometimes You add some 
   user to some group to _remove_ acces for this user (ie when file perms are: 
   rw----rw-, then group can't read this file). If user may call 
   setgroups(0,NULL) then after that he/she is able to read such file.
     
3. PrivsUser
   This directive is almost the same as Privs but it affects requests for
   ~user files. If you don't use it - then such requests will be disallowed
   for this server. This directive get 3 parameters: uid gid chrootdir.
   Uid and Gid can be #number or name (as in Privs directive) but can be also
   AsUserUid and AsUserGid. In this case, module will get username from 
   ~user/file.html request and will do setgid() and setuid() for this user
   gid/uid (but still uid and gid cannot be less than MIN_GID and MIN_UID). 
   Third parameter is dir (as in Privs) but can be also "AsUserHome", then
   module will get user (from ~user/file.html request) home dir, and call 
   chroot for this dir. You can also do chroot for dir relative to user's 
   home, ie AsUserHome.. or AsUserHome../../some_dir (and similar) In dir 
   where chroot will be called, /etc/passwd have to exist, and there user's 
   home dir have to be without chrootdir, ie:
   in /etc/passwd is:
   lw:x:1000:100:Lukasz W:/home/lw:/bin/bash
   You want call chroot for /home for all user's requests, and setuid for 
   user uid, setgid for user gid.
   In httpd.conf:
   PrivsUser AsUserUid AsUserGid AsUserHome..
   You have to create file /home/etc/passwd and there:
   lw:x:1000:100:Lukasz W:/lw:/bin/bash
                          ^^^^
   Similar for other users. If You have any problems, use DEBUG (define 
   ISDEBUG 1 in config.h) or use strace.

4. PrivsAllowJumpVisits
   Take one argument, "On" or "Off".
   What is 'JumpVisit'? When You have few virtual servers on one IP, then
   client may do the following:
   1. connect to one of them, request site and set Connection: keep-alive
   2. at the same connection request site form other virtual server
   First site was victim site, after request child has privileges of victim's
   user. Second site is attacker's site, and attacker scripts are executed with
   victims privileges. It is only possible for name based virtual or ~user
   requests. If You aren't using them, then You don't have to care about 
   'jumpvisits'. If You want to allow jump visits and You are using name based
   virtuals, You have to set Keep-Alive to Off. This control directive don't
   take effect for ~user requests. If You have ~user requests, You have to
   set Keep-Alive to Off. Setting this to Off for name based may cause some 
   smart borwsers to get '403 Forbidden Error', but Opera and Lynx works well.
   
Mod_diffprivs has not defined 'merge' function, so directives from main server
are NOT inherited by virtual servers. This mean, if You set whatever directive
in main server, it won't take effect in virtual servers. If You want it in
virtual servers, You have to set it there explicit. Also, when You use this
module, You have to change "MaxRequestPerChild" to 1. For ~User requests You 
have to set KeepAlive to Off. This may decrase Your Apache performance, so 
better increase "StartServers", "MinSpareServers" and "MaxSpareServers" 
something about 40% of current values. This module require from Apache some 
root's privileges. If You don't want run Apache as root and You are using 
Linux 2.2.x or 2.4.x, You can use tool "erup" by Rafal Wijata.
Erup allow You to set some users who can do setuid/setgid for other users,
and users who can call chroot for some dirs. This is very nice tool, and I'm
strongly encourage You to use this instead running Apache as root
(unfortunelly, erup works only on Linux). You can find erup on
http://www.wijata.com/erup. If You are using FreeBSD, I have for You very
similar module. It's called 'norm' (NORootModule) and may be a solution
when You don't want run Apache as root. You can find it on
http://lw.ftw.zamosc.pl/norm.tgz. If You don't using Linux or FreeBSD, You
have to run Apache as root or use other OS-specific mechanism. Mod_diffprivs
call's chroot/setgid/setgroups/setuid (in this order) as soon as it's possible,
so ensure the mod_diffprivs is first loaded module (last line "LoadModule ..."
in httpd.conf when You are using DSO support).

If You are using this module, please subscribe to mailing list. In future all 
information about mod_diffprivs will be sent to mailing list only. 
You can find this list on http://sourceforge.net/projects/moddiffprivs/

If You have any interesting ideas, You found any bugs or You are simply
interesting to contact with me, feel free, my email is on top.
Sorry for my broken english, I'm not native engish speaker.
To install see INSTALL file.

Dedicate to:	Creed

	/* I'm looking down now that it's over
	 * Reflecting on all of my mistakes
	 * I thought I found the road to somewhere
	 * Somewhere in His grace
	 */

Regards and enjoy
	Lukasz Wojtow.
