summaryrefslogtreecommitdiffstats
path: root/libexec/tftpd
diff options
context:
space:
mode:
authorbillf <billf@FreeBSD.org>2001-01-25 04:20:25 +0000
committerbillf <billf@FreeBSD.org>2001-01-25 04:20:25 +0000
commitea6d044997ade8643407bfe172d0f54702f346fa (patch)
tree00ef2ad8f7694e2ab4b955b8c5e2e3c4165bb58f /libexec/tftpd
parent73de9eb2af2aa657a555f80e5ff0117fea74c064 (diff)
downloadFreeBSD-src-ea6d044997ade8643407bfe172d0f54702f346fa.zip
FreeBSD-src-ea6d044997ade8643407bfe172d0f54702f346fa.tar.gz
Add -c/C which chroots by IP of tftp client, (i.e. /tftproot/127.0.0.1/).
Diffstat (limited to 'libexec/tftpd')
-rw-r--r--libexec/tftpd/tftpd.829
-rw-r--r--libexec/tftpd/tftpd.c25
2 files changed, 50 insertions, 4 deletions
diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8
index f53229d..41e0a92 100644
--- a/libexec/tftpd/tftpd.8
+++ b/libexec/tftpd/tftpd.8
@@ -41,7 +41,7 @@
Internet Trivial File Transfer Protocol server
.Sh SYNOPSIS
.Nm /usr/libexec/tftpd
-.Op Fl ln
+.Op Fl cCln
.Op Fl s Ar directory
.Op Fl u Ar user
.Op Ar directory ...
@@ -114,6 +114,25 @@ option is specified.
.Pp
The options are:
.Bl -tag -width Ds
+.It Fl c
+Changes the default root directory of a connecting host via chroot based on the
+connecting IP address.
+This prevents multiple clients from writing to the same file at the same time.
+If the directory does not exist, the client connection is refused.
+The
+.Fl s
+option is required for
+.Fl c
+and the specified
+.Ar directory
+is used as a base.
+.It Fl C
+Operates the same as
+.Fl c
+except it falls back to
+.Fl s Ns No 's
+.Ar directory
+if a directory does not exist for the client's IP.
.It Fl l
Log all requests using
.Xr syslog 3
@@ -165,7 +184,11 @@ the
.Fl s
option was introduced in
.Fx 2.2 ,
-and the
+the
.Fl u
option was introduced in
-.Fx 4.2 .
+.Fx 4.2 ,
+and the
+.Fl c
+option was introduced in
+.Fx 5.0 .
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index 56c6c02..f0f0ca4 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -106,6 +106,7 @@ static struct dirlist {
} dirs[MAXDIRS+1];
static int suppress_naks;
static int logging;
+static int ipchroot;
static char *errtomsg __P((int));
static void nak __P((int));
@@ -124,8 +125,14 @@ main(argc, argv)
char *chuser = "nobody";
openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
- while ((ch = getopt(argc, argv, "lns:u:")) != -1) {
+ while ((ch = getopt(argc, argv, "cClns:u:")) != -1) {
switch (ch) {
+ case 'c':
+ ipchroot = 1;
+ break;
+ case 'C':
+ ipchroot = 2;
+ break;
case 'l':
logging = 1;
break;
@@ -159,6 +166,10 @@ main(argc, argv)
dirs->name = "/";
dirs->len = 1;
}
+ if (ipchroot && chroot_dir == NULL) {
+ syslog(LOG_ERR, "-c requires -s");
+ exit(1);
+ }
on = 1;
if (ioctl(0, FIONBIO, &on) < 0) {
@@ -229,6 +240,18 @@ main(argc, argv)
* be a problem. See the above comment about system clogging.
*/
if (chroot_dir) {
+ if (ipchroot) {
+ char *tempchroot;
+ struct stat sb;
+ int statret;
+
+ tempchroot = inet_ntoa(from.sin_addr);
+ asprintf(&tempchroot, "%s/%s", chroot_dir, tempchroot);
+ statret = stat(tempchroot, &sb);
+ if ((sb.st_mode & S_IFDIR) &&
+ (statret == 0 || (statret == -1 && ipchroot == 1)))
+ chroot_dir = tempchroot;
+ }
/* Must get this before chroot because /etc might go away */
if ((nobody = getpwnam(chuser)) == NULL) {
syslog(LOG_ERR, "%s: no such user", chuser);
OpenPOWER on IntegriCloud