Overview of class twelve

by Torleif Mohling
CU Boulder, dept of Computer Science
(04/20/2001)

0 Contents

1 FTP

Everyone should be familiar with FTP, the timeless File Transfer Protocol. Setting up a secure FTP server is expectedly easy under OpenBSD. I'll go over the 'BSD setup further below. Before that, let's look at some issues, particularly security, surrounding FTP.

The FTP server is frequently called ftpd. You may run it as a standalone daemon process that gets fired up at boot or you may choose to have it startup as needed by running it out of inetd. Generally, unless you are running a high-use, dedicated ftp server, you should run it out of inetd to save system resources. There are hooks for both setups in the OpenBSD /etc/rc.conf and /etc/inetd.conf files.

There are two main types of security issues when you are dealing with FTP. One type is shared with all server daemons: buggy code for which exploits can be developed. To guard against this sort of problem you simply have to pay attention to relevant mailing lists or websites so that you know immediately when an exploit for the server you use has been discovered. The second type of problem arises from mis-configuration errors that provide read or (worse) write permissions where such permissions shouldn't have been granted.

There several RFC documents that describe actual File Transfer Protocol. In particular, there is RFC-959, See: http://www.rfc-editor.org/rfc/rfc959.txt. The RFC defines, among other things, a series of 'requests' or commands, such as the following:

           Request    Description
           ABOR       abort previous command
           CDUP       change to parent of current working directory
           CWD        change working directory
           DELE       delete a file
           HELP       give help information
           LIST       give list files in a directory (``ls -lgA'')
           MKD        make a directory
           PASS       specify password
           PASV       prepare for server-to-server transfer
           PORT       specify data connection port
           PWD        print the current working directory
           QUIT       terminate session
           RETR       retrieve a file
           STOR       store a file
There are other commands (quite a few) and some servers support other commands; generally there is a standard set that are always supported, though!

1.1 Passive Versus Active Mode FTP

Traditional FTP is known as active FTP. Let's use tcpdump to watch the traffic associated with an active FTP session.

I will be using an FTP client on xibalba and connecting to an FTP server on coatlicue. Here is the initial text of the client session:

    xibalba % ftp coatlicue
    Connected to coatlicue.
    220 coatlicue FTP server (Version 6.4/OpenBSD) ready.
    Name (coatlicue:tor): anonymous
    331 Guest login ok, type your name as password.
    Password: 
    230 Guest login ok, access restrictions apply.
    ftp> 
And the initial tcpdump output:

    coatlicue% sudo tcpdump -t -i le1 not ip src or dst 10.0.0.3
    tcpdump: listening on le1
    xibalba.4443 > coatlicue.ftp: S 657303158:657303158(0) win 32120 <mss
    coatlicue.ftp > xibalba.4443: S 1666789549:1666789549(0) ack 65730315
    xibalba.4443 > coatlicue.ftp: . ack 1 win 32120 <nop,nop,timestamp 63
    coatlicue.ftp > xibalba.4443: P 1:56(55) ack 1 win 17376 <nop,nop,tim
    xibalba.4443 > coatlicue.ftp: . ack 56 win 32120 <nop,nop,timestamp 6
    xibalba.4443 > coatlicue.ftp: P 1:17(16) ack 56 win 32120 <nop,nop,ti
    coatlicue.ftp > xibalba.4443: . ack 17 win 17376 <nop,nop,timestamp 4
    coatlicue.ftp > xibalba.4443: P 56:105(49) ack 17 win 17376 <nop,nop,
    xibalba.4443 > coatlicue.ftp: . ack 105 win 32120 <nop,nop,timestamp 
    xibalba.4443 > coatlicue.ftp: P 17:28(11) ack 105 win 32120 <nop,nop,
    coatlicue.ftp > xibalba.4443: . ack 28 win 17376 <nop,nop,timestamp 4
    coatlicue.ftp > xibalba.4443: P 105:153(48) ack 28 win 17376 <nop,nop
    xibalba.4443 > coatlicue.ftp: P 28:34(6) ack 153 win 32120 <nop,nop,t
    coatlicue.ftp > xibalba.4443: . ack 34 win 17370 <nop,nop,timestamp 4
    coatlicue.ftp > xibalba.4443: P 153:192(39) ack 34 win 17376 <nop,nop
    xibalba.4443 > coatlicue.ftp: . ack 192 win 32120 <nop,nop,timestamp 
Next, if you do an ls command, watch what happens:

    ftp> ls
    200 PORT command successful.
    150 Opening ASCII mode data connection for '/bin/ls'.
    total 14
    drwxr-xr-x  2 ftp  1003  512 Apr 26 14:32 bin
    drwxr-xr-x  2 ftp  1003  512 Apr 26 14:36 etc
    drwxr-xr-x  2 ftp  1003  512 Apr 26 14:33 pub
    226 Transfer complete.
    ftp> 
The 'ls' command is transmitted on the already established FTP command session:

    xibalba.4443 > coatlicue.ftp: P 34:55(21) ack 192 win 32120 <nop,nop,
    coatlicue.ftp > xibalba.4443: . ack 55 win 17376 <nop,nop,timestamp 4
    coatlicue.ftp > xibalba.4443: P 192:222(30) ack 55 win 17376 <nop,nop
    xibalba.4443 > coatlicue.ftp: P 55:61(6) ack 222 win 32120 <nop,nop,t
    coatlicue.ftp > xibalba.4443: . ack 61 win 17370 <nop,nop,timestamp 4
Then, a second TCP connection is setup to transmit the data. The catch, that defines an active FTP session, is that this data connection is initiated by the FTP server:

    coatlicue.ftp-data > xibalba.4444: S 1772957978:1772957978(0) win 163
    xibalba.4444 > coatlicue.ftp-data: S 1520016762:1520016762(0) ack 177
    coatlicue.ftp-data > xibalba.4444: . ack 1 win 18824 <nop,nop,timesta
    coatlicue.ftp > xibalba.4443: P 222:277(55) ack 61 win 17376 <nop,nop
    xibalba.4443 > coatlicue.ftp: . ack 277 win 32120 <nop,nop,timestamp 
    coatlicue.ftp-data > xibalba.4444: P 1:355(354) ack 1 win 18824 <nop,
    xibalba.4444 > coatlicue.ftp-data: . ack 355 win 32120 <nop,nop,times
    coatlicue.ftp > xibalba.4443: P 277:301(24) ack 61 win 17376 <nop,nop
    coatlicue.ftp-data > xibalba.4444: F 355:355(0) ack 1 win 18824 <nop,
    xibalba.4444 > coatlicue.ftp-data: . ack 356 win 32120 <nop,nop,times
    xibalba.4444 > coatlicue.ftp-data: F 1:1(0) ack 356 win 32120 <nop,no
    coatlicue.ftp-data > xibalba.4444: . ack 2 win 18824 <nop,nop,timesta

xibalba.4443 > coatlicue.ftp: . ack 301 win 32120 <nop,nop,timestamp

The fact that active FTP functions by having the data connections initiated by the server makes it incompatible with most firewalls that only allow return traffic for connections initiated on the inside. One alternative is to rip a big hole in your firewall that allows an TCP traffic through that comes from TCP port ftp-data. I don't recommend you do that. A better alternative is to use passive mode FTP.

Let's change to passive mode FTP and watch the traffic for the same ls command:

    ftp> pass
    Passive mode on.
    ftp> ls
    227 Entering Passive Mode (10,0,0,1,138,68)
    ...
The tcpdump output for the transmit of the 'ls' command:

    xibalba.4445 > coatlicue.ftp: P 34:40(6) ack 192 win 32120 <nop,nop,ti
    coatlicue.ftp > xibalba.4445: . ack 40 win 17376 <nop,nop,timestamp 46
    coatlicue.ftp > xibalba.4445: P 192:237(45) ack 40 win 17376 <nop,nop,
    xibalba.4445 > coatlicue.ftp: . ack 237 win 32120 <nop,nop,timestamp 6
And then the data connection is made. This time the connection is initiated by the client (the definition of passive mode FTP):

    xibalba.4446 > coatlicue.35396: S 2564476744:2564476744(0) win 32120 <
    coatlicue.35396 > xibalba.4446: S 1901498010:1901498010(0) ack 2564476
    xibalba.4446 > coatlicue.35396: . ack 1 win 32120 <nop,nop,timestamp 6
    xibalba.4445 > coatlicue.ftp: P 40:46(6) ack 237 win 32120 <nop,nop,ti
    coatlicue.ftp > xibalba.4445: . ack 46 win 17376 <nop,nop,timestamp 46
    coatlicue.ftp > xibalba.4445: P 237:292(55) ack 46 win 17376 <nop,nop,
    xibalba.4445 > coatlicue.ftp: . ack 292 win 32120 <nop,nop,timestamp 6
    coatlicue.35396 > xibalba.4446: P 1:355(354) ack 1 win 17376 <nop,nop,
    xibalba.4446 > coatlicue.35396: . ack 355 win 32120 <nop,nop,timestamp
    coatlicue.ftp > xibalba.4445: P 292:316(24) ack 46 win 17376 <nop,nop,
    coatlicue.35396 > xibalba.4446: F 355:355(0) ack 1 win 17376 <nop,nop,
    xibalba.4446 > coatlicue.35396: . ack 356 win 32120 <nop,nop,timestamp
    xibalba.4446 > coatlicue.35396: F 1:1(0) ack 356 win 32120 <nop,nop,ti

coatlicue.35396 > xibalba.4446: . ack 2 win 17376 <nop,nop,timestamp 4 xibalba.4445 > coatlicue.ftp: . ack 316 win 32120 <nop,nop,timestamp 6

You can see there is a big difference between the two modes of FTP. It shouldn't be surprising that many sites do not allow active FTP through their firewalls. Also, passive mode FTP will simply 'work' with the firewall setups that we have talked about in class.

1.2 Anonymous FTP

We just saw an example of anonymous FTP in the previous section. The point of anonymous FTP is to provide a 'guest' account that anyone may use. This of course brings in a boatload of security implications (but not many more than FTP has already, given the fact that it is an insecure protocol - passwords and data are passed as cleartext). In particular, you must ensure that the anonymous user does not have access to sensitive system files.

When you use anonymous FTP, the server still requires you to enter a password. The convention is that the user enters her email address as a password. Some FTP servers will accept any old string of text, while others require the address to be an RFC compliant address.

The typical way that access to a machine is restricted, with modern FTP servers, is to use the chroot(2) system call. In this way, the root directory of the FTP process can be changed to be the anonymous FTP user homedirectory. What this means is that, because the new directory (the FTP homedir) is the root, no access what-so-ever is allowed to the rest of the system.

The anonymous user homedirectory may need some special setup done to it ahead of time. For example, you need to recreate a bit of the hierarchy of a real system with in the chrooted environment (like a fake /etc/passwd file and any binaries that might be needed in /bin. Binaries that might be needed are gzip and tar that can be used to archive and compress "on the fly" as files are being downloaded.

1.3 FTP Uploading

The FTP upload scenario is fraught with danger. What uploading means is that an FTP user may perform the STORE command (among other things; aka the put command) to install arbitrary files on the FTP server machine. Unlimited upload servers are a hacker heaven because the upload site can be used to store stolen software or other binaries (like mp3 audio files) without danger to the hacker. (The site then gets advertised on hacker IRC channels...)

I recommend that you do not use this function of FTP unless you absolutely have to. If you do have to allow FTP uploading then there are some things you can do to alleviate the risks.

1.4 FTP User Access

In general, FTP user access (i.e. normal users, not the anonymous user) is a very bad idea. FTP is totally insecure and requires the use of users' standard Unix passwords! Some FTP servers (notably OpenBSD's ftpd) will allow you to use a One Time Password scheme like skey(1); although even if you set up the OTP (skey) stuff, the user may still use their normal password if they choose to.

A much better alternative to allowing user access is to provide each local user with their own public_ftp directory. The public_ftp directories are then mounted within the chrooted anonymous FTP directory. It is important that this is done in such a fashion that the FTP user doesn't have access to any other parts of the local users' homedirectories.

If you have to allow FTP user access then consider using some sort of FTP proxy host that requires a seperate form of authentication (like Skey). One such proxy is available with the T.I.S. firewall toolkit. I haven't personally set this up, but I understand it to be a royal pain. However, it does offer a secure proxy host setup which can be invaluable, despite the painful configuration.

1.5 WU-FTPD

If you are not running OpenBSD, then consider using the FTP server from Washington University: wu-ftpd. It has many of the same features as the OpenBSD server and has even more configuration options.

1.6 Configuring FTPD on OpenBSD

Here, I will go over what I did to get FTP running on my home gateway box coatlicue. I am not allowing FTP through my firewall from the outside world at all, so this server is only for internal use. (In particular, I have a housemate who likes to ftp files to the gateway from his macintosh, and then transfer them securely to other machines on the 'net using scp.) Anyway, the result is that I am setting up the ftpd to be both an anonymous server and permit local user access.

First is the question about how ftpd will be started: as a standalone daemon at boot time or as needed out of inetd? Since I think this server will almost never be used I will of course choose to run it out of inetd.

    coatlicue% grep ftp /etc/rc.conf
    # Set to NO if ftpd is running out of inetd
    ftpd_flags=NO           # for non-inetd use: "-D"
    coatlicue% grep ftp /etc/inetd.conf
    ftp     stream  tcp   nowait  root  /usr/libexec/ftpd    ftpd -USll
    #tftp   dgram   udp   wait    root  /usr/libexec/tftpd   tftpd -s /tftpboot
    coatlicue% 
I added the -ll flags to the ftpd invocation in inetd.conf to provide maximum logging of all ftp activity: I think that every ftp command gets logged. Note from the ftpd(8) manpage:

    ...
      -l      Each successful and failed ftp(1) session is logged using syslog
              with a facility of LOG_FTP.  If this option is specified twice,
              the retrieve (get), store (put), append, delete, make directory,
              remove directory and rename operations and their filename argu-
              ments are also logged.
    ...
      -S      With this option set, ftpd logs all anonymous downloads to the
              file /var/log/ftpd when this file exists.
    ...
So be sure to create the log files and make sure /etc/syslog.conf has the right stuff:

    coatlicue% sudo touch /var/log/ftpd
    Password:
    coatlicue% grep ftp /etc/syslog.conf
    *.notice;auth,authpriv,cron,ftp,kern,lpr,mail,user.none /var/log/messages
    ftp.info                                                /var/log/xferlog
The important line in the /etc/syslog.conf file is the second one. Keep in mind, regarding syslog, that ftp.info specifies that all messages that come in for ftp will be logged to the file /var/log/xferlog if they are of a severity level of info or greater (i.e. pretty much all the severity levels except 'debug'). Also HUP syslogd if you have edited the syslog.conf file:

    coatlicue% ps aux | grep syslog
    tor   13472  0.0  0.3   124   200 p5  S+  10:41PM   0:00.14 grep syslog 
    root  15592  0.0  0.2    96   120 ??  Ss   4Apr00   0:52.44 syslogd 
    coatlicue% sudo kill -1 15592
Then make sure you have an ftp user (the username required by the OpenBSD ftpd server). Run adduser or whatever.

    coatlicue% sudo grep ftp /etc/master.passwd
    ftp:*:1003:1003::0:0:anon y mous:/home/ftp:/sbin/nologin
After you run adduser you will definately want to run vipw and change the password to an asterisk (i.e. "starred-out") and the shell to /sbin/nologin, as in the above example. Both of these changes are important for security reasons, and don't affect the functionality of the anonymous ftp sessions.

After adding the ftp user you need to spend a bit of time setting up what will be the chrooted ftp session environment in the ftp home directory. The ftpd(8) manpage has this to say about it:

    In [the anonymous user] case, ftpd takes special measures to restrict the
    client's access privileges.  The server performs a chroot(2) to the home
    directory of the ``ftp'' user.  In order that system security is not
    breached, it is recommended that the ``ftp'' subtree be constructed with
    care, following these rules:

~ftp Make the home directory owned by ``root'' and unwritable by anyone (mode 555).

~ftp/bin Make this directory owned by ``root'' and unwritable by anyone (mode 511). This directory is optional unless you have commands you wish the anonymous ftp user to be able to run (the ls(1) command exists as a builtin). Any pro- grams in this directory should be mode 111 (executable only)

~ftp/etc Make this directory owned by ``root'' and unwritable by anyone (mode 511). The files pwd.db (see pwd_mkdb(8)) and group(5) must be present for the ls command to be able to produce owner names rather than numbers. The password field in pwd.db is not used, and should not con- tain real passwords. The file motd, if present, will be printed after a successful login. These files should be mode 444.

~ftp/pub Make this directory mode 555 and owned by ``root''. This is traditionally where publically accessible files are stored for download.

So, first I'll do some of the easy stuff:

    coatlicue% cd ~ftp
    coatlicue% sudo chown root .
    Password:
    coatlicue% sudo chmod 555 .
    coatlicue% sudo mkdir pub etc bin
    coatlicue% sudo chmod 511 bin etc
    coatlicue% sudo chmod 555 pub
    coatlicue% sudo cp /etc/group etc
    coatlicue% sudo cp /etc/master.passwd etc
At this point you have to edit the copy of the master.passwd file that you copy into the ~ftp/etc directory. Specifically, as noted, star-out or alter the passwords. When you are done, issue the following incantation (read the manpages, too!):

    coatlicue% sudo pwd_mkdb -p -d /home/ftp/etc /home/ftp/etc/master.passwd
To create the actual .db files as recommended in the ftpd manpage. I also created a motd file. Finally, make sure the etc files have the right permissions, too:

    coatlicue% foreach f (`sudo ls etc`)
    foreach? sudo chmod 444 etc/$f
    foreach? end
    coatlicue% sudo ls -l etc
    total 168
    -r--r--r--  1 root  ftp    378 May  3 22:59 group
    -r--r--r--  1 root  ftp    845 Apr 26 14:35 master.passwd
    -r--r--r--  1 root  ftp     93 May  3 23:01 motd
    -r--r--r--  1 root  ftp    780 May  3 23:05 passwd
    -r--r--r--  1 root  ftp  40960 May  3 23:05 pwd.db
    -r--r--r--  1 root  ftp  40960 May  3 23:05 spwd.db
Finally, I need to put a document in the pub directory, so I can test the server.

    coatlicue% ls pub
    README
    coatlicue% 
All right, let's test it out from xibalba:

    xibalba % ftp coatlicue
    Connected to coatlicue.
    220 coatlicue FTP server (Version 6.4/OpenBSD) ready.
    Name (coatlicue:tor): anonymous
    331 Guest login ok, type your name as password.
    Password:
    230- Welcome to the Coatlicue FTP Server
    230- Please note that all connections and commands are logged
    230 Guest login ok, access restrictions apply.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp> ls
    200 PORT command successful.
    150 Opening ASCII mode data connection for '/bin/ls'.
    total 6
    dr-x--x--x  2 ftp  ftp  512 Apr 26 14:32 bin
    dr-x--x--x  2 ftp  ftp  512 May  3 23:05 etc
    dr-xr-xr-x  2 ftp  ftp  512 Apr 26 14:33 pub
    226 Transfer complete.
    ftp> cd pub
    250 CWD command successful.
    ftp> get README
    local: README remote: README
    200 PORT command successful.
    150 Opening BINARY mode data connection for 'README' (68 bytes).
    226 Transfer complete.
    68 bytes received in 0.0278 secs (2.4 Kbytes/sec)
    ftp> quit
    221 Goodbye.
    xibalba % 
Yeah! It's that easy! User access FTP ought to just work, I don't recommend ever using it unless you have set up the S/Key stuff. Here is a transcript just in case you don't believe that it just works:

    xibalba % ftp coatlicue
    Connected to coatlicue.
    220 coatlicue FTP server (Version 6.4/OpenBSD) ready.
    Name (coatlicue:tor): 
    331 Password required for tor.
    Password:
    230- OpenBSD 2.6 (GENERIC) #287: Thu Oct 21 23:31:48 MDT 1999
    230- 
    230- Welcome to OpenBSD: The proactively secure Unix-like operating system.
    230- 
    230 User tor logged in.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp> ls
    200 PORT command successful.
    150 Opening ASCII mode data connection for '/bin/ls'.
    total 7010
    -rw-------  1 tor  wheel     2267 Apr  4 13:25 .Xauthority
    -rw-r--r--  1 tor  wheel    17320 Aug 15  1999 .Xdefaults
    -rw-r--r--  1 tor  wheel     2701 Oct 24  1999 .alias
    -rw-r--r--  1 tor  wheel     2646 Aug 15  1999 .alias.old
    -rw-------  1 tor  wheel       70 Aug 15  1999 .bash_history
    -rw-r--r--  1 tor  wheel     1787 Oct 31  1999 .cshrc
    -rwxr-xr-x  1 tor  wheel     5111 Aug 15  1999 .dtprofile
    ...
    -rw-r--r--  1 tor  wheel      150 Nov 27 16:50 traffic
    226 Transfer complete.
    ftp> quit
    221 Goodbye.
    xibalba % 

1.7 Miscellaneous

Here is a quick look at the CS department FTP setup. We use the wu-ftpd mentioned above, running on a *SunOS 4.1.3* box (a SparcStation 5). Most of the setup is similar to what I did for the OpenBSD server. In fact, there are only two things worth noting.

First, the upload directory. In this case the directory is name submissions because it is most frequently used for the submission of research and technical papers:

    freestuff % ls -ldg pub/submissions
    d-wxrwx--t  2 ftp      faculty       512 Apr  4 04:45 pub/submissions/
Notice that the directory is owned and writable by the ftp user, but not readable. The directory is readable for the faculty group, however, to facilitate them being able to retrieve the documents from the submissions directory themselves (via NFS, not FTP).

Second, is the setup we have for mounting user public_ftp directories. To mount just the public_ftp directory we make use of a feature of traditional NFS. For example, my personal homedir is exported from a machine named fcsk and you can see that with the showmount command:

    freestuff % showmount -e fcsk
    export list for fcsk:
    /tmp_mnt/home/girl        cs-all
    /tmp_mnt/home/boy         cs-all
    /tmp_mnt/home/improvement cs-all
    /tmp_mnt/home/fcsk        cs-all
And, when I log into the machine where out ftp server runs, my homedir gets mounted normally, as you would expect:

    freestuff % cd ~tor
    freestuff % pwd
    /tmp_mnt/home/fcsk/tor
    freestuff % df .
    Filesystem            kbytes    used   avail capacity  Mounted on
    fcsk.cs.colorado.edu:/tmp_mnt/home/fcsk   xxx          /tmp_mnt/home/fcsk
The trick is that traditional NFS will allow you to mount a subdir of the exported filesystem instead of the filesystem itself! For example, the public_ftp subdirectory of a specific user's homedir. The mounts happen automatically because of a specialized AMD map. Watch what happens when I cd into the ftp users directory...

    freestuff % cd /local/ftp/users
    freestuff % ls
    baveja@  seidl@
    freestuff % cd tor
    freestuff % ls
    foo/      nlp/      saclass/  tqs-1.0/
    freestuff % pwd
    /.amd/fcsk/tor
    freestuff % cd /local/ftp/users
    freestuff % ls
    freestuff % ls -l
    total 2
    lrwxrwxrwx  1 root           19 May  3 23:49 baveja -> /.amd/hobbit/baveja/
    lrwxrwxrwx  1 root           18 May  4 00:11 mozer -> /.amd/neuron/mozer/
    lrwxrwxrwx  1 root           15 May  3 23:23 seidl -> /.amd/vex/seidl/
    lrwxrwxrwx  1 root           14 May  4 00:06 tor -> /.amd/fcsk/tor/
    freestuff % 

And you can look at the actual mounts like so:

    freestuff % mount | grep fcsk
    fcsk.cs.colorado.edu:/tmp_mnt/home/fcsk on /tmp_mnt/home/fcsk type nfs ..
    fcsk:/tmp_mnt/home/fcsk/tor/public_ftp on /.amd/fcsk/tor type nfs ..
Pretty cool! Here is a sample of the AMD map:

    # AMD map for users' public_ftp dirs
    #
    # This map is built automatically by ftp_registryd
    # *Never* edit it by hand, changes _will_ be *lost*
    # or you may hose the registry completely.
    # If you do, millert will flog you with a clammy noodle.
    #

/defaults type:=nfs;fs:=/.amd/${rhost}/${key};opts:=ro,${NFS_BOILERPLATE},\ timeo=${NFS_TIMEO},retrans=${NFS_RETRANS},rsize=${NFS_RSIZE},wsize=${NFS_WSIZE}

millert rhost:=fcsk;rfs:=/tmp_mnt/home/improvement/millert/public_ftp mcginley rhost:=fcsk;rfs:=/tmp_mnt/home/girl/mcginley/public_ftp tor rhost:=fcsk;rfs:=/tmp_mnt/home/fcsk/tor/public_ftp ...

If you are curious, despite the fact that the ftp session operates in a chrooted environment, AMD still controls the mountpoint ~ftp/users. There is one caveat however, the symlink that AMD creates must point somewhere within the chrooted environment. You can see that AMD makes a symlink pointing to something like /.amd/fcsk/tor and (ahead of time) we have made a symlink as follows (keep in mind that the chrooted environment is /local/ftp)

    freestuff % ls -lad /.amd
    lrwxrwxrwx  1 root           14 Mar 31  1999 /.amd -> local/ftp/.amd
Pretty clever! So the mountpoint really ends up being /local/ftp/.amd/fcsk/tor, for example. Fun with symlinks and chroot...

2 Rdist - Automating Updates for Large Installations

The maintenance of system files on only a handful of machines is trivial enough. However, when the number of machines gets into the hundreds, such manual methods simply don't scale. One program that can alleviate this problem is called rdist. Rdist is a client/server based program that uses the remote shell interface (i.e. rpc - Remote Procedure Call). The client is the machine initiating the rdist, the sender. The server is the receiver. The server side of the process must run a daemon program called rdistd which usually is invoked from inetd via shell - that is, the client uses 'rsh' to startup the rdistd daemon on the receiving host.

Using rdist in a networking environment requires that the host from whom files will be 'disted' to be trusted by all of the hosts who will receive the dists. The trusted host is often called the 'master' host, or the 'admin' host. The other machines are often just called 'clients'. Note that this exactly the opposite notion of master/client than the names of the rdist and rdistd commands imply.. just to be confusing, I guess.

You must ensure that the recipient hosts have the following:

Please NOTE WELL that using the .rhosts file like this as well as enabling the remote shell command in /etc/inetd.conf are VERY dangerous in terms of computer security. When you allow root access from a remote machine you are trusting that that remote machine will not itself be compromised and also that a rogue machine can not intercede (i.e. in a classic "man in the middle" attack.) When you allow remote shell access to your machine, you rely on the security of the 'shell' implementation (which is notoriously flawed, from a security point of view); also, each user can potentially create their own .rhosts file to allow password-less access to the machine (as that user). Be Careful!

Remember that one 'BSD and RedHat you can control how inetd responds based on IP address - read the manpages for details.

     
Let's first look at a simple example from the saclass-N machines. I set up a simple distfile to automate the distribution of the /etc/sudoers file. In this case, the machine saclass-1 is the master, trusted, machine, and the other three receive the dists.

     
The setup issues on saclass-2, an OpenBSD box.

First make sure shell is enabled in /etc/inetd.conf:

    saclass-2 % grep shell /etc/inetd.conf
    shell           stream  tcp     nowait  root    /usr/libexec/rshd       rshd -L
Yup, there it is, and UNcommented. (Note that it will be commented out by default!)

Next, make sure that 'saclass-1' appears in root's .rhosts file:

    saclass-2 % sudo cat ~root/.rhosts
    saclass-1.cs.colorado.edu
     
The setup issues on saclass-3 and -4 differ slightly, as they are RedHat Linux boxes. One difference may be that you are using xinetd instead. Another (important either way) difference is the arguments for the 'shell' entry in inetd.conf:

    saclass-4 % grep shell /etc/inetd.conf
    shell   stream  tcp     nowait  root    /usr/sbin/tcpd  in.rshd -h
Notice the -h argument. This is not present in the default entry (which is actually a Good Thing, as it disables root access...)

     
Now, on saclass-1 we probably want to make sure that root's .rhosts file is not present or empty and read-only. We also should turn off the remote shell service in /etc/inetd.conf. Two simple security precautions.

To fully automate the procedure, we need two things: a distfile with rules describing what files will be disted and to whom, and we need a crontab entry to periodically run rdist for us.

Here is the crontab entry:

    saclass-1 % sudo crontab -l | grep rdist
    1,16,31,46 *    *       *       *       /usr/local/sbin/rdist_sudoers
The above crontab entry invokes a script called rdist_sudoers every 15 minutes. The script is just a simple wrapper around rdist. It looks like this:

    saclass-1 % cat /usr/local/sbin/rdist_sudoers
    #!/bin/sh
    /usr/bin/rdist -f /usr/local/etc/sudoers
This wrapper is so simple it is hardly worth using. A better wrapper script should verify the invoking user, and send mail if there is a failure.

And lastly, here is the distfile itself:

    saclass-1 % cat /usr/local/etc/sudoers 

CLIENTS = ( saclass-2 saclass-3 saclass-4 )

FILES = ( /etc/sudoers )

( ${FILES} ) -> ( ${CLIENTS} ) install;

The above distfile is also very simple, but illustrates the basic functionality of the distfile concept. The first line is defining a list of machine names; the second line, a list of files. The final two lines are an actual 'dist' rule. These rules have a basic syntax like so:

    ( <file-list> ) -> ( <machine-list> )
        <install-option>;
        ...
The syntax in english says: "take this list of files and distribute them to this list of machines."

If you invoke the rdist by hand it looks like this:

    saclass-1 % sudo rdist -f /usr/local/etc/sudoers
    saclass-2: updating host saclass-2
    saclass-4: updating host saclass-4
    saclass-3: updating host saclass-3
    saclass-4: /etc/sudoers: updating
    saclass-4: updating of saclass-4 finished
    saclass-2: /etc/sudoers: updating
    saclass-2: updating of saclass-2 finished
    saclass-3: /etc/sudoers: updating
    saclass-3: updating of saclass-3 finished
You may use the install-options section to perform special commands if you need to. For example, if you were to distribute the sendmail /etc/mail/aliases file to all of your machines, you would want to rebuild the alias database file also. You could setup an dist rule to do this for you like so:

    ( /etc/mail/aliases ) -> ( ${CLIENTS} )
            install;
            special /etc/mail/aliases "/usr/sbin/sendmail -bi";
This would dist the aliases file to the machine and then run the 'newaliases' (actually, I'm using sendmail directly - newaliases is just "sendmail -bi") command on that machine for each machine in the CLIENTS list. The commands specified in the double-quotes can be any arbitrary bourne shell code. For example, if you were disting to both BSD and RedHat boxes, then the sendmail command lives in different places... here is one solution:

    ( /etc/mail/aliases ) -> ( ${CLIENTS} )
            install;
            special /etc/mail/aliases "if [ -f /usr/sbin/sendmail ]; then /usr/sbin/sendmail -bi; \
                                       else /usr/lib/sendmail -bi; fi";
Please note that the quoted shell commands must be ; (semi-colon) seperated and must be on one line! (in the example above, I split it over two lines for visual readability.)