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.
This commit is contained in:
parent
6bf3beb134
commit
8ea3178507
@ -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 ,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user