summaryrefslogtreecommitdiffstats
path: root/libexec/tftpd
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>1996-09-22 04:19:27 +0000
committerimp <imp@FreeBSD.org>1996-09-22 04:19:27 +0000
commitc04f619292e13248b5eac368266aee4d54699b51 (patch)
tree9c12365a107622c02dbcb4ffc7b4a1952873ff11 /libexec/tftpd
parenta43b707795a51c0af5320d933cbf0d274a3661b4 (diff)
downloadFreeBSD-src-c04f619292e13248b5eac368266aee4d54699b51.zip
FreeBSD-src-c04f619292e13248b5eac368266aee4d54699b51.tar.gz
Reviewed by: Bill Fenner <fennder@parc.xerox.com>
Reviewed by: Garrett Wollman <wollman@freebsd.org> Submitted by: Warner Losh <imp@village.org> Close PR bin/1145: Add -s flag to tftpd. This enables the so-called secure mode of tftpd where it chroots to a given directory before allowing access to the files. In addition, it runs as nobody when in this mode. Reviewed a long time ago by Bill and Garrett. Apply my patch from the pr, and close the PR.
Diffstat (limited to 'libexec/tftpd')
-rw-r--r--libexec/tftpd/tftpd.815
-rw-r--r--libexec/tftpd/tftpd.c33
2 files changed, 47 insertions, 1 deletions
diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8
index 430c1c4..4a9004d 100644
--- a/libexec/tftpd/tftpd.8
+++ b/libexec/tftpd/tftpd.8
@@ -42,6 +42,7 @@ Internet Trivial File Transfer Protocol server
.Nm tftpd
.Op Fl l
.Op Fl n
+.Op Fl s Ar directory
.Op Ar directory ...
.Sh DESCRIPTION
.Nm Tftpd
@@ -87,6 +88,15 @@ names are prefixed by the one of the given directories.
The given directories are also treated as a search path for
relative filename requests.
.Pp
+The chroot option provides additional security by restricting access
+of tftpd to only a chroot'd file system. This is useful when moving
+from an OS that supported
+.Nm -s
+as a boot server. Because chroot is restricted to root, you must run
+tftpd as root. However, if you chroot, then
+.Nm tftpd
+will set its user id to nobody.
+.Pp
The options are:
.Bl -tag -width Ds
.It Fl l
@@ -95,6 +105,11 @@ Logs all requests using
.It Fl n
Suppresses negative acknowledgement of requests for nonexistent
relative filenames.
+.It Fl s Ar directory
+Causes tftpd to chroot to
+.Pa directory
+before accepting commands. In addition, the user id is set to
+nobody.
.El
.Sh SEE ALSO
.Xr tftp 1 ,
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index 7500abf..9ab7778 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -52,6 +52,7 @@ static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93";
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/tftp.h>
@@ -68,6 +69,7 @@ static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93";
#include <string.h>
#include <syslog.h>
#include <unistd.h>
+#include <pwd.h>
#include "tftpsubs.h"
@@ -113,9 +115,11 @@ main(argc, argv)
register int n;
int ch, on;
struct sockaddr_in sin;
+ char *chroot_dir = NULL;
+ struct passwd *nobody;
openlog("tftpd", LOG_PID, LOG_FTP);
- while ((ch = getopt(argc, argv, "ln")) != EOF) {
+ while ((ch = getopt(argc, argv, "lns:")) != EOF) {
switch (ch) {
case 'l':
logging = 1;
@@ -123,6 +127,9 @@ main(argc, argv)
case 'n':
suppress_naks = 1;
break;
+ case 's':
+ chroot_dir = optarg;
+ break;
default:
syslog(LOG_WARNING, "ignoring unknown option -%c", ch);
}
@@ -140,6 +147,10 @@ main(argc, argv)
}
}
}
+ else if (chroot_dir) {
+ dirs->name = "/";
+ dirs->len = 1;
+ }
on = 1;
if (ioctl(0, FIONBIO, &on) < 0) {
@@ -203,6 +214,26 @@ main(argc, argv)
exit(0);
}
}
+
+ /*
+ * Since we exit here, we should do that only after the above
+ * recvfrom to keep inetd from constantly forking should there
+ * be a problem. See the above comment about system clogging.
+ */
+ if (chroot_dir) {
+ /* Must get this before chroot because /etc might go away */
+ if ((nobody = getpwnam("nobody")) == NULL) {
+ syslog(LOG_ERR, "nobody: no such user");
+ exit(1);
+ }
+ if (chroot(chroot_dir)) {
+ syslog(LOG_ERR, "chroot: %s: %m", chroot_dir);
+ exit(1);
+ }
+ chdir( "/" );
+ setuid(nobody->pw_uid);
+ }
+
from.sin_family = AF_INET;
alarm(0);
close(0);
OpenPOWER on IntegriCloud