summaryrefslogtreecommitdiff
path: root/libexec/tftpd
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2018-03-10 01:35:26 +0000
committerAlan Somers <asomers@FreeBSD.org>2018-03-10 01:35:26 +0000
commitd89aca7618ee5e1e27828b5581b565f358f199e7 (patch)
tree432c5786a90162816d84e3a76c7b1771b1102b8b /libexec/tftpd
parent2e1fccf2cf9ea48d28bce65e80ff99fd16a4a1e7 (diff)
downloadsrc-test-d89aca7618ee5e1e27828b5581b565f358f199e7.tar.gz
src-test-d89aca7618ee5e1e27828b5581b565f358f199e7.zip
tftpd: Verify world-writability for WRQ when using relative paths
tftpd(8) says that files may only be written if they already exist and are publicly writable. tftpd.c verifies that a file is publicly writable if it uses an absolute pathname. However, if the pathname is relative, that check is skipped. Fix it. Note that this is not a security vulnerability, because the transfer ultimately doesn't work unless the file already exists and is owned by user nobody. Also, this bug does not affect the default configuration, because the default uses the "-s" option which makes all pathnames absolute. PR: 226004 MFC after: 3 weeks
Notes
Notes: svn path=/head/; revision=330718
Diffstat (limited to 'libexec/tftpd')
-rw-r--r--libexec/tftpd/tests/functional.c13
-rw-r--r--libexec/tftpd/tftpd.c10
2 files changed, 17 insertions, 6 deletions
diff --git a/libexec/tftpd/tests/functional.c b/libexec/tftpd/tests/functional.c
index d7f5ac77f81b4..4d0992e29e0e6 100644
--- a/libexec/tftpd/tests/functional.c
+++ b/libexec/tftpd/tests/functional.c
@@ -350,6 +350,10 @@ setup(struct sockaddr_storage *to, uint16_t idx)
ATF_REQUIRE((client_s = socket(protocol, SOCK_DGRAM, 0)) > 0);
break;
}
+
+ /* Clear the client's umask. Test cases will specify exact modes */
+ umask(0000);
+
return (client_s);
}
@@ -714,7 +718,7 @@ TFTPD_TC_DEFINE(wrq_dropped_ack,)
for (i = 0; i < nitems(contents); i++)
contents[i] = i;
- fd = open("medium.txt", O_RDWR | O_CREAT, 0644);
+ fd = open("medium.txt", O_RDWR | O_CREAT, 0666);
ATF_REQUIRE(fd >= 0);
close(fd);
@@ -747,7 +751,7 @@ TFTPD_TC_DEFINE(wrq_dropped_data,)
size_t contents_len;
char buffer[1024];
- fd = open("small.txt", O_RDWR | O_CREAT, 0644);
+ fd = open("small.txt", O_RDWR | O_CREAT, 0666);
ATF_REQUIRE(fd >= 0);
close(fd);
contents_len = strlen(contents) + 1;
@@ -782,7 +786,7 @@ TFTPD_TC_DEFINE(wrq_duped_data,)
for (i = 0; i < nitems(contents); i++)
contents[i] = i;
- fd = open("medium.txt", O_RDWR | O_CREAT, 0644);
+ fd = open("medium.txt", O_RDWR | O_CREAT, 0666);
ATF_REQUIRE(fd >= 0);
close(fd);
@@ -831,7 +835,8 @@ TFTPD_TC_DEFINE(wrq_eaccess_world_readable,)
close(fd);
SEND_WRQ("empty.txt", "octet");
- atf_tc_expect_fail("PR 226004 with relative pathnames, tftpd doesn't validate world writability");
+ atf_tc_expect_fail("PR 225996 tftpd doesn't abort on a WRQ access "
+ "violation");
RECV_ERROR(2, "Access violation");
}
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index a167395d58321..94f2f52be808b 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -743,8 +743,12 @@ validate_access(int peer, char **filep, int mode)
dirp->name, filename);
if (stat(pathname, &stbuf) == 0 &&
(stbuf.st_mode & S_IFMT) == S_IFREG) {
- if ((stbuf.st_mode & S_IROTH) != 0) {
- break;
+ if (mode == RRQ) {
+ if ((stbuf.st_mode & S_IROTH) != 0)
+ break;
+ } else {
+ if ((stbuf.st_mode & S_IWOTH) != 0)
+ break;
}
err = EACCESS;
}
@@ -753,6 +757,8 @@ validate_access(int peer, char **filep, int mode)
*filep = filename = pathname;
else if (mode == RRQ)
return (err);
+ else if (err != ENOTFOUND || !create_new)
+ return (err);
}
/*