220 lines
5.4 KiB
Text
220 lines
5.4 KiB
Text
$NetBSD: patch-ad,v 1.2 2003/09/21 09:15:31 jmc Exp $
|
|
|
|
--- tftpd.c.orig Mon Mar 20 21:14:39 1995
|
|
+++ tftpd.c
|
|
@@ -56,6 +56,8 @@
|
|
#include <syslog.h>
|
|
#include <string.h>
|
|
|
|
+#include <unistd.h>
|
|
+
|
|
#define TIMEOUT 5
|
|
|
|
extern int errno;
|
|
@@ -66,9 +68,9 @@
|
|
int rexmtval = TIMEOUT;
|
|
int maxtimeout = 5*TIMEOUT;
|
|
|
|
-#define PKTSIZE SEGSIZE+4
|
|
-char buf[PKTSIZE];
|
|
-char ackbuf[PKTSIZE];
|
|
+#define BUF_PKTSIZE SEGSIZE+4
|
|
+char buf[BUF_PKTSIZE];
|
|
+char ackbuf[BUF_PKTSIZE];
|
|
struct sockaddr_in from;
|
|
int fromlen;
|
|
|
|
@@ -105,6 +107,8 @@
|
|
|
|
if (argc > 1 && strcmp (argv[1], "-d") == 0) {
|
|
setUpForDebugging();
|
|
+ argc--;
|
|
+ argv++;
|
|
}
|
|
if (ioctl(0, FIONBIO, &on) < 0) {
|
|
syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");
|
|
@@ -202,7 +206,7 @@
|
|
awaitInput(chan)
|
|
int chan;
|
|
{
|
|
- int imask;
|
|
+ fd_set imask;
|
|
int nready;
|
|
struct timeval tv;
|
|
extern int maxInputWait;
|
|
@@ -212,8 +216,9 @@
|
|
else
|
|
tv.tv_sec = 5*60; /* default: wait for 5 minutes */
|
|
tv.tv_usec = 0;
|
|
- imask = 1<<chan;
|
|
- nready = select (sizeof(imask)*8, &imask, (int*)0, (int*)0, &tv);
|
|
+ FD_ZERO(&imask);
|
|
+ FD_SET(chan, &imask);
|
|
+ nready = select (chan+1 , &imask, NULL, NULL, &tv);
|
|
return nready;
|
|
}
|
|
|
|
@@ -294,7 +299,10 @@
|
|
}
|
|
|
|
int validate_access();
|
|
-int sendfile(), recvfile();
|
|
+
|
|
+struct formats;
|
|
+int tftpsendfile(struct formats *);
|
|
+int tftprecvfile(struct formats *);
|
|
|
|
struct formats {
|
|
char *f_mode;
|
|
@@ -303,8 +311,8 @@
|
|
int (*f_recv)();
|
|
int f_convert;
|
|
} formats[] = {
|
|
- { "netascii", validate_access, sendfile, recvfile, 1 },
|
|
- { "octet", validate_access, sendfile, recvfile, 0 },
|
|
+ { "netascii", validate_access, tftpsendfile, tftprecvfile, 1 },
|
|
+ { "octet", validate_access, tftpsendfile, tftprecvfile, 0 },
|
|
#ifdef notdef
|
|
{ "mail", validate_user, sendmail, recvmail, 1 },
|
|
#endif
|
|
@@ -355,13 +363,13 @@
|
|
exit(1);
|
|
}
|
|
if (tftpDebugLevel > 0) {
|
|
- char buf[1024];
|
|
- buf[0] = '\0';
|
|
- getwd(buf);
|
|
+ char* buf;
|
|
+ buf = getcwd(NULL, 0);
|
|
syslog(LOG_DEBUG, "request %s '%s' from %s; cwd='%s'",
|
|
(tp->th_opcode == RRQ ? "read" : "write"),
|
|
filename, inet_ntoa(from.sin_addr),
|
|
buf);
|
|
+ free(buf);
|
|
}
|
|
ecode = (*pf->f_validate)(filename, tp->th_opcode);
|
|
if (ecode) {
|
|
@@ -459,17 +467,25 @@
|
|
|
|
/* Rule 2:
|
|
*/
|
|
- if (tftpRootDirectory != 0 && IS_ROOTED(filename)) {
|
|
+ if ((tftpRootDirectory != 0 && IS_ROOTED(filename)) ||
|
|
+ (tftpDefaultDirectory != 0 && IS_ROOTED(filename))) {
|
|
char _tmp[1024];
|
|
+ char* realRootDir;
|
|
int maxPath;
|
|
int rootLen;
|
|
|
|
- rootLen = strlen (tftpRootDirectory);
|
|
+ if (tftpRootDirectory != 0 ) {
|
|
+ realRootDir = tftpRootDirectory;
|
|
+ }
|
|
+ else {
|
|
+ realRootDir = tftpDefaultDirectory;
|
|
+ }
|
|
+
|
|
+ rootLen = strlen (realRootDir);
|
|
|
|
/* make sure the pathname doesn't already contain
|
|
* the virtual root.
|
|
*/
|
|
- if (strncmp(filename,tftpRootDirectory,rootLen) != 0) {
|
|
|
|
/* Insure our temporary space is big enough */
|
|
maxPath = ((sizeof _tmp) - 1) - rootLen;
|
|
@@ -481,6 +497,8 @@
|
|
return EACCESS;
|
|
}
|
|
|
|
+ if (strncmp(filename,realRootDir,rootLen) != 0) {
|
|
+
|
|
/* Squeeze out any '.' or '..' components */
|
|
strcpy (tmpPath, filename);
|
|
if (realPath (tmpPath, _tmp) < 0) {
|
|
@@ -492,21 +510,54 @@
|
|
/* Create the full pathname, prefixed by the
|
|
* virtual root.
|
|
*/
|
|
- strcpy (tmpPath, tftpRootDirectory);
|
|
+ strcpy (tmpPath, realRootDir);
|
|
strcat (tmpPath, _tmp);
|
|
filename = tmpPath;
|
|
}
|
|
+ else {
|
|
+ /* Squeeze out any '.' or '..' components */
|
|
+ strcpy (tmpPath, filename);
|
|
+ if (realPath (tmpPath, _tmp) < 0) {
|
|
+ if (tftpDebugLevel > 1)
|
|
+ syslog (LOG_DEBUG, "realPath fails");
|
|
+ return EACCESS;
|
|
+ }
|
|
+ /* Create the full pathname */
|
|
+ strcpy (tmpPath,_tmp);
|
|
+ filename = tmpPath;
|
|
+ if (strncmp(filename,realRootDir,rootLen) != 0) {
|
|
+ if (tftpDebugLevel > 1) {
|
|
+ syslog(LOG_DEBUG, "file=%s; invalid access denied", filename);
|
|
+ return EACCESS;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
/* Rule 3:
|
|
*/
|
|
- if (!IS_ROOTED(filename) && tftpDefaultDirectory == 0) {
|
|
- strcpy (tmpPath, tftpRootDirectory);
|
|
- strcat (tmpPath, "/");
|
|
+ if ((!IS_ROOTED(filename) && tftpRootDirectory != 0) ||
|
|
+ (!IS_ROOTED(filename) && tftpDefaultDirectory != 0)) {
|
|
+ char _tmp[1024];
|
|
strcat (tmpPath, filename);
|
|
+ /* Squeeze out any '.' or '..' components */
|
|
+ strcpy (tmpPath, filename);
|
|
+ if (realPath (tmpPath, _tmp) < 0) {
|
|
+ if (tftpDebugLevel > 1)
|
|
+ syslog (LOG_DEBUG, "realPath fails");
|
|
+ return EACCESS;
|
|
+ }
|
|
+ if ( tftpDefaultDirectory == 0 ) {
|
|
+ strcpy (tmpPath, tftpRootDirectory);
|
|
+ }
|
|
+ else {
|
|
+ strcpy (tmpPath, tftpDefaultDirectory);
|
|
+ }
|
|
+ strcat (tmpPath, _tmp);
|
|
filename = tmpPath;
|
|
}
|
|
|
|
+
|
|
/* Check access lists */
|
|
/* Rules 4&5:
|
|
*/
|
|
@@ -593,7 +644,7 @@
|
|
/*
|
|
* Send the requested file.
|
|
*/
|
|
-sendfile(pf)
|
|
+tftpsendfile(pf)
|
|
struct formats *pf;
|
|
{
|
|
struct tftphdr *dp, *r_init();
|
|
@@ -664,7 +715,7 @@
|
|
/*
|
|
* Receive a file.
|
|
*/
|
|
-recvfile(pf)
|
|
+tftprecvfile(pf)
|
|
struct formats *pf;
|
|
{
|
|
struct tftphdr *dp, *w_init();
|
|
@@ -739,7 +739,7 @@
|
|
write_behind(file, pf->f_convert);
|
|
for ( ; ; ) {
|
|
alarm(rexmtval);
|
|
- n = recv(peer, dp, PKTSIZE, 0);
|
|
+ n = recv(peer, dp, BUF_PKTSIZE, 0);
|
|
alarm(0);
|
|
if (n < 0) { /* really? */
|
|
syslog(LOG_ERR, "tftpd: read: %m\n");
|