aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2024-07-05 22:05:49 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2024-07-05 22:05:49 +0000
commitc15290fb9d8fdf4b11b9c6e7406b67c73a98402d (patch)
tree26ee12c42599315d7e2eec6d98149066b9a3cbd7
parentb81424adf7181d816c10b1345aaa3305ab0ec304 (diff)
downloadsrc-c15290fb9d8fdf4b11b9c6e7406b67c73a98402d.tar.gz
src-c15290fb9d8fdf4b11b9c6e7406b67c73a98402d.zip
tftpd: Code cleanup.
MFC after: 3 days Sponsored by: Klara, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D45871
-rw-r--r--libexec/tftpd/tftpd.c91
1 files changed, 41 insertions, 50 deletions
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c
index 3f67ad2920cf..a51fb4742985 100644
--- a/libexec/tftpd/tftpd.c
+++ b/libexec/tftpd/tftpd.c
@@ -680,28 +680,27 @@ find_next_name(char *filename, int *fd)
int
validate_access(int peer, char **filep, int mode)
{
- struct stat stbuf;
- int fd;
- int error;
- struct dirlist *dirp;
static char pathname[MAXPATHLEN];
+ struct stat sb;
+ struct dirlist *dirp;
char *filename = *filep;
+ int err, fd;
/*
* Prevent tricksters from getting around the directory restrictions
*/
- if (strstr(filename, "/../"))
+ if (strncmp(filename, "../", 3) == 0 ||
+ strstr(filename, "/../") != NULL)
return (EACCESS);
if (*filename == '/') {
/*
- * Allow the request if it's in one of the approved locations.
- * Special case: check the null prefix ("/") by looking
- * for length = 1 and relying on the arg. processing that
- * it's a /.
+ * Absolute file name: allow the request if it's in one of the
+ * approved locations.
*/
for (dirp = dirs; dirp->name != NULL; dirp++) {
if (dirp->len == 1)
+ /* Only "/" can have len 1 */
break;
if (strncmp(filename, dirp->name, dirp->len) == 0 &&
filename[dirp->len] == '/')
@@ -710,30 +709,20 @@ validate_access(int peer, char **filep, int mode)
/* If directory list is empty, allow access to any file */
if (dirp->name == NULL && dirp != dirs)
return (EACCESS);
- if (stat(filename, &stbuf) < 0)
+ if (stat(filename, &sb) != 0)
return (errno == ENOENT ? ENOTFOUND : EACCESS);
- if ((stbuf.st_mode & S_IFMT) != S_IFREG)
+ if (!S_ISREG(sb.st_mode))
return (ENOTFOUND);
if (mode == RRQ) {
- if ((stbuf.st_mode & S_IROTH) == 0)
+ if ((sb.st_mode & S_IROTH) == 0)
return (EACCESS);
} else {
- if (check_woth && ((stbuf.st_mode & S_IWOTH) == 0))
+ if (check_woth && (sb.st_mode & S_IWOTH) == 0)
return (EACCESS);
}
} else {
- int err;
-
/*
* Relative file name: search the approved locations for it.
- * Don't allow write requests that avoid directory
- * restrictions.
- */
-
- if (!strncmp(filename, "../", 3))
- return (EACCESS);
-
- /*
* If the file exists in one of the directories and isn't
* readable, continue looking. However, change the error code
* to give an indication that the file exists.
@@ -741,18 +730,20 @@ validate_access(int peer, char **filep, int mode)
err = ENOTFOUND;
for (dirp = dirs; dirp->name != NULL; dirp++) {
snprintf(pathname, sizeof(pathname), "%s/%s",
- dirp->name, filename);
- if (stat(pathname, &stbuf) == 0 &&
- (stbuf.st_mode & S_IFMT) == S_IFREG) {
- if (mode == RRQ) {
- if ((stbuf.st_mode & S_IROTH) != 0)
- break;
- } else {
- if (!check_woth || ((stbuf.st_mode & S_IWOTH) != 0))
- break;
- }
- err = EACCESS;
+ dirp->name, filename);
+ if (stat(pathname, &sb) != 0)
+ continue;
+ if (!S_ISREG(sb.st_mode))
+ continue;
+ err = EACCESS;
+ if (mode == RRQ) {
+ if ((sb.st_mode & S_IROTH) == 0)
+ continue;
+ } else {
+ if (check_woth && (sb.st_mode & S_IWOTH) == 0)
+ continue;
}
+ break;
}
if (dirp->name != NULL)
*filep = filename = pathname;
@@ -766,27 +757,27 @@ validate_access(int peer, char **filep, int mode)
* This option is handled here because it (might) require(s) the
* size of the file.
*/
- option_tsize(peer, NULL, mode, &stbuf);
+ option_tsize(peer, NULL, mode, &sb);
- if (mode == RRQ)
+ if (mode == RRQ) {
fd = open(filename, O_RDONLY);
- else {
- if (create_new) {
- if (increase_name) {
- error = find_next_name(filename, &fd);
- if (error > 0)
- return (error + 100);
- } else
- fd = open(filename,
- O_WRONLY | O_TRUNC | O_CREAT,
- S_IRUSR | S_IWUSR | S_IRGRP |
- S_IWGRP | S_IROTH | S_IWOTH );
- } else
- fd = open(filename, O_WRONLY | O_TRUNC);
+ } else if (create_new) {
+ if (increase_name) {
+ err = find_next_name(filename, &fd);
+ if (err > 0)
+ return (err + 100);
+ } else {
+ fd = open(filename,
+ O_WRONLY | O_TRUNC | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP |
+ S_IWGRP | S_IROTH | S_IWOTH );
+ }
+ } else {
+ fd = open(filename, O_WRONLY | O_TRUNC);
}
if (fd < 0)
return (errno + 100);
- file = fdopen(fd, (mode == RRQ)? "r":"w");
+ file = fdopen(fd, mode == RRQ ? "r" : "w");
if (file == NULL) {
close(fd);
return (errno + 100);