--- tftpd.c.orig Mon Mar 20 14:14:39 1995 +++ tftpd.c Fri Aug 27 12:46:59 1999 @@ -294,7 +294,10 @@ } int validate_access(); -int sendfile(), recvfile(); + +struct formats; +int tftpsendfile(struct formats *); +int tftprecvfile(struct formats *); struct formats { char *f_mode; @@ -303,8 +306,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 @@ -459,17 +462,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 +492,8 @@ return EACCESS; } + if (strncmp(filename,realRootDir,rootLen) != 0) { + /* Squeeze out any '.' or '..' components */ strcpy (tmpPath, filename); if (realPath (tmpPath, _tmp) < 0) { @@ -492,21 +505,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 +639,7 @@ /* * Send the requested file. */ -sendfile(pf) +tftpsendfile(pf) struct formats *pf; { struct tftphdr *dp, *r_init(); @@ -664,7 +710,7 @@ /* * Receive a file. */ -recvfile(pf) +tftprecvfile(pf) struct formats *pf; { struct tftphdr *dp, *w_init();