--- 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();
