Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!brl-adm!adm!guyton%condor@rand-unix.arpa From: guyton%condor@rand-unix.arpa Newsgroups: comp.unix.wizards Subject: Re: tftp in 4.3BSD Message-ID: <5306@brl-adm.ARPA> Date: Sun, 22-Mar-87 13:18:37 EST Article-I.D.: brl-adm.5306 Posted: Sun Mar 22 13:18:37 1987 Date-Received: Mon, 23-Mar-87 01:50:13 EST Sender: news@brl-adm.ARPA Lines: 83 Before you install tftpd, read and understand the routine tftpd.c: validate_access() in /usr/src/etc/tftpd/tftpd.c. The default is to allow anonymous reading of all publically readable files (not too bad), and anonymous writing of any publically writable file (ugh!). It also won't create a file for you. Here's my replacement for that code. Read it and agree with it before installing. Basically it chroot's to a directory of your choice and so restricts file i/o to that directory. Due to the chroot call, the tftpd will have to be run as root. It also won't create the TROOT directory, do that by hand. -- Jim Guyton, guyton@rand-unix.arpa p.s. this code is still far from ideal, but then so is tftp. #define TROOT "/tmp/tftp" /* Home for all tftp files */ FILE *file; /* opened by validate_access */ extern int errno; /* * Validate file access. * * This version changes root to TROOT and lets the client munge files * only within that directory. It should be fairly safe, though somewhat * inconvenient to use. Before changing, remember that this code is * run as root and there is *no* user validatation at all! Within * the /tmp/tftp directory, the rules are: * * FOR READING: File must exist and be publicly readable * FOR WRITING: If the file exists, it must be publicly writeable. * If it does not exist, it is created and made publicly * writeable by default. * * * ToDo: add logging of transfers * ToDo: act less paranoid if connection from known friendly host * */ validate_access(filename, client, mode) char *filename; struct sockaddr_in *client; int mode; { struct stat stbuf; if (restrict()) /* chdir and chroot */ return EACCESS; /* err out if not there */ if (mode == RRQ) { /* Check access if reading */ if (stat(filename, &stbuf) < 0) return (errno == ENOENT ? ENOTFOUND : EACCESS); if ((stbuf.st_mode&(S_IREAD >> 6)) == 0) return (EACCESS); file = fopen(filename, "r"); } else { /* write request */ if (restrict()) return EACCESS; if (stat(filename, &stbuf) == 0) { if ((stbuf.st_mode&(S_IWRITE >> 6)) == 0) return (EACCESS); } file = fopen(filename, "w"); } if (file == NULL) return (errno + 100); return (0); } restrict() { if (chdir(TROOT) != 0 || /* must go there and */ chroot(TROOT) != 0) /* also set root ... */ return -1; return 0; /* return zero if worked */ }