restrict directories from which files may be accessed
authorThomas Ferrin <tef@ucbvax.Berkeley.EDU>
Tue, 11 Oct 1988 14:24:24 +0000 (06:24 -0800)
committerThomas Ferrin <tef@ucbvax.Berkeley.EDU>
Tue, 11 Oct 1988 14:24:24 +0000 (06:24 -0800)
SCCS-vsn: libexec/tftpd/tftpd.c 5.9
SCCS-vsn: libexec/tftpd/tftpd.8 6.4

usr/src/libexec/tftpd/tftpd.8
usr/src/libexec/tftpd/tftpd.c

index 7513ef8..23b06b3 100644 (file)
@@ -13,7 +13,7 @@
 .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 .\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
 .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 .\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.\"    @(#)tftpd.8     6.3 (Berkeley) %G%
+.\"    @(#)tftpd.8     6.4 (Berkeley) %G%
 .\"
 .TH TFTPD 8 ""
 .UC 5
 .\"
 .TH TFTPD 8 ""
 .UC 5
@@ -21,6 +21,7 @@
 tftpd \- DARPA Trivial File Transfer Protocol server
 .SH SYNOPSIS
 .B /etc/tftpd
 tftpd \- DARPA Trivial File Transfer Protocol server
 .SH SYNOPSIS
 .B /etc/tftpd
+[ directory ... ]
 .SH DESCRIPTION
 .I Tftpd
 is a server which supports the DARPA Trivial File Transfer
 .SH DESCRIPTION
 .I Tftpd
 is a server which supports the DARPA Trivial File Transfer
@@ -45,5 +46,13 @@ all users on all hosts that can be reached through the network;
 this may not be appropriate on all systems, and its implications
 should be considered before enabling tftp service.
 The server should have the user ID with the lowest possible privilege.
 this may not be appropriate on all systems, and its implications
 should be considered before enabling tftp service.
 The server should have the user ID with the lowest possible privilege.
+.PP
+Access to files may be restricted by invoking
+.I tftpd
+with a list of directories by including pathnames
+as server program arguments in
+.IR /etc/inetd.conf .
+In this case access is restricted to files whose
+names are prefixed by the one of the given directories.
 .SH "SEE ALSO"
 tftp(1), inetd(8)
 .SH "SEE ALSO"
 tftp(1), inetd(8)
index 2087b83..f4cd20f 100644 (file)
@@ -22,7 +22,7 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)tftpd.c    5.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)tftpd.c    5.9 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -63,12 +63,19 @@ char        ackbuf[PKTSIZE];
 struct sockaddr_in from;
 int    fromlen;
 
 struct sockaddr_in from;
 int    fromlen;
 
-main()
+#define MAXARG 4
+char   *dirs[MAXARG+1];
+
+main(ac, av)
+       char **av;
 {
        register struct tftphdr *tp;
 {
        register struct tftphdr *tp;
-       register int n;
+       register int n = 0;
        int on = 1;
 
        int on = 1;
 
+       ac--; av++;
+       while (ac-- > 0 && n < MAXARG)
+               dirs[n++] = *av++;
        openlog("tftpd", LOG_PID, LOG_DAEMON);
        if (ioctl(0, FIONBIO, &on) < 0) {
                syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
        openlog("tftpd", LOG_PID, LOG_DAEMON);
        if (ioctl(0, FIONBIO, &on) < 0) {
                syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
@@ -231,6 +238,9 @@ FILE *file;
  * have no uid or gid, for now require
  * file to exist and be publicly
  * readable/writable.
  * have no uid or gid, for now require
  * file to exist and be publicly
  * readable/writable.
+ * If we were invoked with arguments
+ * from inetd then the file must also be
+ * in one of the given directory prefixes.
  * Note also, full path name must be
  * given as we have no login directory.
  */
  * Note also, full path name must be
  * given as we have no login directory.
  */
@@ -240,9 +250,15 @@ validate_access(filename, mode)
 {
        struct stat stbuf;
        int     fd;
 {
        struct stat stbuf;
        int     fd;
+       char **dirp = dirs;
 
        if (*filename != '/')
                return (EACCESS);
 
        if (*filename != '/')
                return (EACCESS);
+       for (; *dirp; dirp++)
+               if (strncmp(filename, *dirp, strlen(*dirp)) == 0)
+                       break;
+       if (*dirp==0 && dirp!=dirs)
+               return (EACCESS);
        if (stat(filename, &stbuf) < 0)
                return (errno == ENOENT ? ENOTFOUND : EACCESS);
        if (mode == RRQ) {
        if (stat(filename, &stbuf) < 0)
                return (errno == ENOENT ? ENOTFOUND : EACCESS);
        if (mode == RRQ) {