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); } }