On Sun, Jan 24, 2016 at 03:05:28AM -0600, Matthew Martin wrote:
> Add a -R flag to tftpd for a read only mode. This allows for a tighter
> pledge than currently possible because by default existing files can be
> overwritten (but no new files created). Perhaps read only should be the
> default since it is surprising that tftp can overwrite by default.
> 
> - Matthew Martin

This time not forgetting usage(). (Thanks Jason.)


Index: tftpd.8
===================================================================
RCS file: /cvs/src/usr.sbin/tftpd/tftpd.8,v
retrieving revision 1.5
diff -u -p -r1.5 tftpd.8
--- tftpd.8     18 Jul 2015 05:32:56 -0000      1.5
+++ tftpd.8     24 Jan 2016 18:09:07 -0000
@@ -37,7 +37,7 @@
 .Nd DARPA Trivial File Transfer Protocol daemon
 .Sh SYNOPSIS
 .Nm tftpd
-.Op Fl 46cdv
+.Op Fl 46cdRv
 .Op Fl l Ar address
 .Op Fl p Ar port
 .Op Fl r Ar socket
@@ -113,6 +113,8 @@ listens on the port indicated in the
 .Ql tftp
 service description; see
 .Xr services 5 .
+.It Fl R
+Only allow read requests.
 .It Fl r Ar socket
 Issue filename rewrite requests to the specified UNIX domain socket.
 .Nm
Index: tftpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/tftpd/tftpd.c,v
retrieving revision 1.34
diff -u -p -r1.34 tftpd.c
--- tftpd.c     14 Dec 2015 16:34:55 -0000      1.34
+++ tftpd.c     24 Jan 2016 18:09:07 -0000
@@ -262,12 +262,13 @@ __dead void
 usage(void)
 {
        extern char *__progname;
-       fprintf(stderr, "usage: %s [-46cdv] [-l address] [-p port] [-r socket]"
+       fprintf(stderr, "usage: %s [-46cdRv] [-l address] [-p port] [-r socket]"
            " directory\n", __progname);
        exit(1);
 }
 
 int              cancreate = 0;
+int              readonly = 0;
 int              verbose = 0;
 
 int
@@ -286,7 +287,7 @@ main(int argc, char *argv[])
        char *port = "tftp";
        int family = AF_UNSPEC;
 
-       while ((c = getopt(argc, argv, "46cdl:p:r:v")) != -1) {
+       while ((c = getopt(argc, argv, "46cdl:p:Rr:v")) != -1) {
                switch (c) {
                case '4':
                        family = AF_INET;
@@ -296,6 +297,7 @@ main(int argc, char *argv[])
                        break;
                case 'c':
                        cancreate = 1;
+                       readonly = 0;
                        break;
                case 'd':
                        verbose = debug = 1;
@@ -306,6 +308,10 @@ main(int argc, char *argv[])
                case 'p':
                        port = optarg;
                        break;
+               case 'R':
+                       readonly = 1;
+                       cancreate = 0;
+                       break;
                case 'r':
                        rewrite = optarg;
                        break;
@@ -358,8 +364,13 @@ main(int argc, char *argv[])
            setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
                errx(1, "can't drop privileges");
 
-       if (pledge("stdio rpath wpath cpath fattr dns inet", NULL) == -1)
-               err(1, "pledge");
+       if (readonly) {
+               if (pledge("stdio rpath dns inet", NULL) == -1)
+                       err(1, "pledge");
+       } else {
+               if (pledge("stdio rpath wpath cpath fattr dns inet", NULL) == 
-1)
+                       err(1, "pledge");
+       }
 
        event_init();
 
@@ -966,7 +977,7 @@ validate_access(struct tftp_client *clie
                        if ((stbuf.st_mode & (S_IRUSR >> 6)) == 0)
                                return (EACCESS);
                } else {
-                       if ((stbuf.st_mode & (S_IWUSR >> 6)) == 0)
+                       if (readonly || (stbuf.st_mode & (S_IWUSR >> 6)) == 0)
                                return (EACCESS);
                }
        }

Reply via email to