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