packages icon
@(#) README 1.3 2001/07/25 10:15:32

chrootuid - run command in restricted environment

Description
===========

Chrootuid makes it easy to run a network service at low privilege
level and with restricted file system access.  In the past I used
this program to run the gopher and www (world-wide web) network
daemons in a restricted environment:  the daemons have access only
to their own directory tree, and run under a low-privileged userid.
Nowadays I also use it for proxy servers.  The arrangement greatly
reduces the impact of possible loopholes in network software.

Note: for security reasons, chrootuid uses the passwd and group
files from *outside* the chroot area. This idea was suggested by
Douglas Schales of Texas A&M University, now with IBM Research.

This software was initially released in 1993. However, chrootuid
is still being used after all those years, so I have released a
slightly updated version with a BSD-style license. The examples
below are still the original ones. Although the systems don't exist
anymore, the same ideas still apply.

	Wietse Venema
	wietse@porcupine.org
	IBM T.J. Watson Research Center
	Hawthorne, USA

Installation
============

The source of the chrootuid program is small and easy to verify.  In
order to build the program, run "make". If it compiles OK, edit the
destination pathnames in the Makefile and do a "make install".

Important: chrootuid should *not* be installed set-uid.

Using the chrootuid program
===========================

The use of the chrootuid program will be illustrated with the gopher
service. The examples are easily adapted to www (world-wide web) or any
other network service.

In the inetd.conf file, make a gopher entry like this:

    gopher  stream  tcp   nowait  root  /usr/local/lib/gopherd gopherd

If you like to run the daemon under control of my tcp/ip daemon
wrapper, use the following entry:

    gopher  stream  tcp   nowait  root  /some/where/tcpd /usr/local/lib/gopherd

On some systems you will have to omit the "root" field, because all
daemons are executed as root by default. 

The file /usr/local/lib/gopherd should be a shell script that is
maintained by the superuser, because inetd runs the script with root
privilege. It is this script that runs the real gopher daemon, as an
unprivileged process, in a restricted environment. Of course you can
specify any other pathname for the script, as long as it is fully
controlled by the superuser.

    #!/bin/sh

    exec /usr/local/bin/chrootuid /some/where/gopher nobody \
        /bin/gopherd -I -l /tmp/gopher.log \
                        -o /bin/gopherd.conf \
                     -c -C /gopherdata 70

I'll describe the contents of this script in some detail:

- Instead of /usr/local/bin/chrootuid, specify the absolute path to the
installed chrootuid executable. The program is executed by root so the
path should be fully controlled by the super user.

- Instead of /some/where/gopher, specify the absolute path to your
gopher directory tree. The gopher daemon will have access only to files
within this subtree. This arrangement is similar to anonymous FTP.

- The gopher daemon will be executed with the privileges of the "nobody"
account.  You can specify any unprivileged account, as long as it does
not own any files etc. within the gopher directory tree. The account
info will be extracted from the regular password database, so there is
no need for passwd or group files below the gopher directory tree.

- "/bin/gopherd -I -l ..." is the command that will be executed, after
access to the file system has been restricted to the gopher directory
tree, and after privileges have been reduced to those of "nobody" (or
whatever account name you choose).  All path names should be absolute
with respect to the root of the gopher directory tree. Thus,
/bin/gopherd corresponds to /some/where/gopher/bin/gopherd.

On systems with shared libraries it will be necessary to set up the
appropriate files in the gopher directory tree. The appendix below
shows [a slightly edited version of] what we have. It is very similar
to what one has to set up for anonymous FTP, except that no passwd or
group files are needed.

Finally, chrootuid reports all problems to the syslog daemon.  Have a
look at your syslog.conf file if you don't know where the errors are
logged.

Appendix: sample restricted gopher subtree
==========================================

This example is a slightly edited version of own gopher subtree.  Some
details (shared libs, DNS, and timezone stuff) are specific to SunOS;
hints are given for Ultrix 4.x.

The restricted gopher subtree is very similar to the tree used for
anonymous ftp, except that no passwd or group files are needed.  The
example assumes that the tree is located at /some/where/gopher, which
will sometimes be referred to as ~gopher for brevity.

SunOS notes:  the shared libraries in this example are specific to
SunOS 4.1.1. What you will need depends on the OS release and on the
compiler used to build the gopher executable (do `ldd gopherd' to find
out; you'll always need the ld.so runtime linker, though). The example
assumes that you are running DNS on top of NIS.  Otherwise, you will
need a ~gopher/etc/resolv.conf file.

Ultrix notes: you will need the following files in ~gopher/etc:  hosts,
resolv.conf, svc.conf, svcorder. Just copy them from a DNS client host.

Other systems: it may be necessary to install a ~gopher/etc/resolv.conf
file so that gopherd can find the domain name server (DNS).

It is convenient to have a symlink ~gopher/some/where/gopher -> ../..
so that old pathnames keep working after the installation of chrootuid.

Important: make sure that no files etc. are owned by the unprivileged
account ("nobody" or whatever you chose). The only exception that we
permit is the gopherd logfile, because no program depends on it.

~gopher:
drwxr-sr-x  2 exp           512 Aug 12 13:33 bin
dr-xr-sr-x  2 exp           512 Oct 12  1992 dev
drwxr-sr-x  9 exp           512 Aug  9 12:35 gopherdata
dr-xr-sr-x  2 exp           512 Apr 22 14:24 some
drwxrwsrwt  2 exp           512 Aug 12 13:48 tmp
dr-xr-sr-x  4 exp           512 Jan 25  1993 usr

~gopher/bin:
-rwx--x--x  1 exp        409600 Aug 12 13:39 gopherd
-rw-r--r--  1 exp          2299 Jun 15 10:12 gopherd.conf

~gopher/dev:
crw-rw-rw-  1 exp        3,  12 Oct 12  1992 zero

~gopher/gopherdata:
<our information data base omitted for brevity>

~gopher/some:
dr-xr-xr-x  2 exp           512 Apr 22 14:24 where

~gopher/some/where:
lrwxrwxrwx  1 exp             6 Apr 22 14:24 gopher -> ../../

~gopher/tmp:
-rw-r--r--  1 nobody     220563 Aug 12 14:46 gopher.log

~gopher/usr:
dr-xr-xr-x  2 exp           512 Oct 12  1992 lib
dr-xr-xr-x  3 exp           512 Jan 21  1993 share

~gopher/usr/lib:
-r-xr-xr-x  1 exp         40960 Oct 11  1990 ld.so
-r-xr-xr-x  1 exp        516096 Oct 12  1990 libc.so.1.6

~gopher/usr/share:
dr-xr-xr-x  3 exp           512 Jan 21  1993 lib

~gopher/usr/share/lib:
dr-xr-xr-x  2 exp           512 Jan 21  1993 zoneinfo

~gopher/usr/share/lib/zoneinfo:
-r--r--r--  1 exp           590 Oct 11  1990 MET
-r--r--r--  1 exp           590 Oct 11  1990 localtime