@(#) 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