--- tftp-hpa-5.0/tftpd/tftpd.c.orig 2009-12-26 13:17:35.000000000 +0300 +++ tftp-hpa-5.0/tftpd/tftpd.c 2009-12-26 13:19:01.000000000 +0300 @@ -46,6 +46,7 @@ #include #include #include +#include #include "common/tftpsubs.h" #include "recvfrom.h" @@ -975,6 +976,8 @@ static int validate_access(char *, int, struct formats *, const char **); static void tftp_sendfile(struct formats *, struct tftphdr *, int); static void tftp_recvfile(struct formats *, struct tftphdr *, int); +int lookup_entry(const char *comp, char *dest); +void lookup_file(char *filename); struct formats { const char *f_mode; @@ -1353,6 +1356,62 @@ } #endif +int lookup_entry(const char *comp, char *dest) +{ + DIR *dirp; + struct dirent *dptr; + dirp = opendir(dest[0] ? dest : "."); + if (!dirp) return 0; + while ((dptr = readdir(dirp))) + { + if (!strcasecmp(dptr->d_name, comp)) + { + if (dest[0]) strcat(dest, "/"); + strcat(dest, dptr->d_name); + closedir(dirp); + return 1; + } + } + closedir(dirp); + return 0; +} + + +void lookup_file(char *filename) +{ + int found = 0; + int len = 0; + char dest[1024]; + char comp[1024]; + char *check = filename; + char *seek = NULL; + + dest[0] = 0; + check++; + while (*check) + { + seek = strchr(check, '\\'); + if (!seek) + { + if ((*check) && (lookup_entry(check, dest))) + found = 1; + break; + } + len = seek - check; + memcpy(comp, check, len); + comp[len]=0; + if (!lookup_entry(comp, dest)) + break; + check += len + 1; + } + + if (found) + { + filename[0] = 0; + strcat(filename, dest); + } +} + static FILE *file; /* * Validate file access. Since we @@ -1378,6 +1437,8 @@ tsize_ok = 0; *errmsg = NULL; + if (*filename == '\\') lookup_file(filename); + if (!secure) { if (*filename != '/') { *errmsg = "Only absolute filenames allowed";