Module Name: src
Committed By: hubertf
Date: Wed Apr 28 22:21:51 UTC 2010
Modified Files:
src/doc: CHANGES
src/libexec/tftpd: tftpd.8 tftpd.c
Log Message:
tftpd(8): Add -w so files can be uploaded without requiring them
to be created before the upload. See the section on security
considerations before enabling. [hubertf 20100429]
Addresses PR bin/43164.
To generate a diff of this commit:
cvs rdiff -u -r1.1383 -r1.1384 src/doc/CHANGES
cvs rdiff -u -r1.24 -r1.25 src/libexec/tftpd/tftpd.8
cvs rdiff -u -r1.36 -r1.37 src/libexec/tftpd/tftpd.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/doc/CHANGES
diff -u src/doc/CHANGES:1.1383 src/doc/CHANGES:1.1384
--- src/doc/CHANGES:1.1383 Sun Apr 25 00:57:12 2010
+++ src/doc/CHANGES Wed Apr 28 22:21:51 2010
@@ -1,4 +1,4 @@
-# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1383 $>
+# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1384 $>
#
#
# [Note: This file does not mention every change made to the NetBSD source tree.
@@ -599,3 +599,6 @@
The database cache for services(5) has been updated to use
this. services_mkdb(8) can still be used to create the old
format. [joerg 20100425]
+ tftpd(8): Add -w so files can be uploaded without requiring them
+ to be created before the upload. See the section on security
+ considerations before enabling. [hubertf 20100429]
Index: src/libexec/tftpd/tftpd.8
diff -u src/libexec/tftpd/tftpd.8:1.24 src/libexec/tftpd/tftpd.8:1.25
--- src/libexec/tftpd/tftpd.8:1.24 Fri Jan 8 23:27:08 2010
+++ src/libexec/tftpd/tftpd.8 Wed Apr 28 22:21:51 2010
@@ -1,4 +1,4 @@
-.\" $NetBSD: tftpd.8,v 1.24 2010/01/08 23:27:08 wiz Exp $
+.\" $NetBSD: tftpd.8,v 1.25 2010/04/28 22:21:51 hubertf Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)tftpd.8 8.1 (Berkeley) 6/4/93
.\"
-.Dd January 8, 2010
+.Dd April 22, 2010
.Dt TFTPD 8
.Os
.Sh NAME
@@ -44,6 +44,7 @@
.Op Fl p Ar pathsep
.Op Fl s Ar directory
.Op Fl u Ar user
+.Op Fl w
.Op Ar directory ...
.Sh DESCRIPTION
.Nm
@@ -70,7 +71,10 @@
or containing
.Dq Pa /../
are not allowed.
-Files may be written to only if they already exist and are publicly writable.
+Unless option
+.Fl w
+is used,
+files may be written to only if they already exist and are publicly writable.
.Pp
Note that this extends the concept of
.Qq public
@@ -148,6 +152,9 @@
isn't also given, change the gid to that of
.Ar user
as well.
+.It Fl w
+Allow unrestricted writing of new files, with no need for
+a prior existance.
.El
.Sh SEE ALSO
.Xr tftp 1 ,
@@ -232,3 +239,9 @@
sort of file-access restrictions in place.
The exact methods are specific to each site and therefore
difficult to document here.
+.Pp
+If unrestricted file upload is enabled via the
+.Fl w
+option, care should be taken that this can be used
+to fill up disk space in an uncontrolled manner
+if this is used in an insecure environment.
Index: src/libexec/tftpd/tftpd.c
diff -u src/libexec/tftpd/tftpd.c:1.36 src/libexec/tftpd/tftpd.c:1.37
--- src/libexec/tftpd/tftpd.c:1.36 Sat Jan 9 10:46:31 2010
+++ src/libexec/tftpd/tftpd.c Wed Apr 28 22:21:51 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: tftpd.c,v 1.36 2010/01/09 10:46:31 mbalmer Exp $ */
+/* $NetBSD: tftpd.c,v 1.37 2010/04/28 22:21:51 hubertf Exp $ */
/*
* Copyright (c) 1983, 1993
@@ -36,7 +36,7 @@
#if 0
static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: tftpd.c,v 1.36 2010/01/09 10:46:31 mbalmer Exp $");
+__RCSID("$NetBSD: tftpd.c,v 1.37 2010/04/28 22:21:51 hubertf Exp $");
#endif
#endif /* not lint */
@@ -109,6 +109,7 @@
static int secure;
static char pathsep = '\0';
static char *securedir;
+static int unrestricted_writes; /* uploaded files don't have to exist */
struct formats;
@@ -171,7 +172,7 @@
curuid = getuid();
curgid = getgid();
- while ((ch = getopt(argc, argv, "dg:lnp:s:u:w:")) != -1)
+ while ((ch = getopt(argc, argv, "dg:lnp:s:u:w")) != -1)
switch (ch) {
case 'd':
debug++;
@@ -204,6 +205,10 @@
tgtuser = optarg;
break;
+ case 'w':
+ unrestricted_writes = 1;
+ break;
+
default:
usage();
break;
@@ -739,6 +744,8 @@
static char pathname[MAXPATHLEN];
char *filename;
int fd;
+ int create = 0;
+ int trunc = 0;
filename = *filep;
@@ -804,21 +811,45 @@
return (EACCESS);
*filep = filename = pathname;
} else {
+ int stat_rc;
+
/*
* If there's no directory list, take our cue from the
* absolute file request check above (*filename == '/'),
* and allow access to anything.
*/
- if (stat(filename, &stbuf) < 0)
- return (errno == ENOENT ? ENOTFOUND : EACCESS);
- if (!S_ISREG(stbuf.st_mode))
- return (ENOTFOUND);
+ stat_rc = stat(filename, &stbuf);
if (mode == RRQ) {
+ /* Read request */
+ if (stat_rc < 0)
+ return (errno == ENOENT ? ENOTFOUND : EACCESS);
+ if (!S_ISREG(stbuf.st_mode))
+ return (ENOTFOUND);
if ((stbuf.st_mode & S_IROTH) == 0)
return (EACCESS);
} else {
- if ((stbuf.st_mode & S_IWOTH) == 0)
- return (EACCESS);
+ if (stat_rc < 0) {
+ /* Can't stat */
+ if (errno == EACCES) {
+ /* Permission denied */
+ return EACCESS;
+ } else {
+ /* Not there */
+ if (unrestricted_writes) {
+ /* need to creat new file! */
+ create = O_CREAT;
+ } else {
+ /* Permission denied */
+ return EACCESS;
+ }
+ }
+ } else {
+ /* Can stat */
+ if ((stbuf.st_mode & S_IWOTH) == 0) {
+ return (EACCESS);
+ }
+ trunc = O_TRUNC;
+ }
}
*filep = filename;
}
@@ -827,7 +858,8 @@
if (tftp_opt_tsize && mode == RRQ)
tftp_tsize = (unsigned long) stbuf.st_size;
- fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY | O_TRUNC);
+ fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY | trunc | create,
+ 0644); /* debatable */
if (fd < 0)
return (errno + 100);
file = fdopen(fd, (mode == RRQ)? "r":"w");