* Case insensitive lookup patch for atftpd * * Copyright (c) 2006-2007 Gianluigi Tiesi * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this software; if not, write to the * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA diff -Nur atftp-0.7.dfsg.orig/tftpd.c atftp-0.7.dfsg/tftpd.c --- atftp-0.7.dfsg.orig/tftpd.c 2007-12-09 06:06:20.000000000 +0100 +++ atftp-0.7.dfsg/tftpd.c 2007-12-09 06:08:51.229707272 +0100 @@ -667,6 +667,15 @@ switch (retval) { case GET_RRQ: + if (data->tftp_options[OPT_FILENAME].value[0] == '\\') + if (!tftpd_lookup_file(directory, data->tftp_options[OPT_FILENAME].value)) + { + /* Short circuit */ + tftp_send_error(data->sockfd, &data->client_info->client, + ENOTFOUND, data->data_buffer, data->data_buffer_size); + stats_err_locked(); + break; + } logger(LOG_NOTICE, "Serving %s to %s:%d", data->tftp_options[OPT_FILENAME].value, inet_ntoa(data->client_info->client.sin_addr), diff -Nur atftp-0.7.dfsg.orig/tftpd.h atftp-0.7.dfsg/tftpd.h --- atftp-0.7.dfsg.orig/tftpd.h 2004-02-27 03:05:26.000000000 +0100 +++ atftp-0.7.dfsg/tftpd.h 2007-12-09 06:06:35.319368784 +0100 @@ -77,6 +77,7 @@ /* * Functions defined in tftpd_file.c */ +int tftpd_lookup_file(const char *directory, char *filename); int tftpd_rules_check(char *filename); int tftpd_receive_file(struct thread_data *data); int tftpd_send_file(struct thread_data *data); diff -Nur atftp-0.7.dfsg.orig/tftpd_file.c atftp-0.7.dfsg/tftpd_file.c --- atftp-0.7.dfsg.orig/tftpd_file.c 2004-02-18 03:21:47.000000000 +0100 +++ atftp-0.7.dfsg/tftpd_file.c 2007-12-09 06:09:23.683773504 +0100 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "tftpd.h" #include "tftp_io.h" @@ -60,6 +61,81 @@ extern tftpd_pcre_self_t *pcre_top; #endif +/* + * Case insensitive file lookup, for windows clients + */ + +int tftpd_lookup_entry(const char *comp, char *dest) +{ + DIR *dirp; + struct dirent *dptr; + dirp = opendir(dest); + if (!dirp) return 0; + while ((dptr = readdir(dirp))) + { + if (!strcasecmp(dptr->d_name, comp)) + { + strcat(dest, "/"); + strcat(dest, dptr->d_name); + closedir(dirp); + return 1; + } + } + closedir(dirp); + return 0; +} + +int tftpd_lookup_file(const char *directory, char *filename) +{ + int found = 0; + int len = 0; + char dest[MAXLEN]; + char comp[MAXLEN]; + char *check = filename; + char *seek = NULL; + + dest[0] = 0; + strcat(dest, directory); + len = strlen(dest); + if (dest[len-1] == '/') + dest[len-1] = 0; + check++; + while (*check) + { + seek = strchr(check, '\\'); + if (!seek) + { + if ((*check) && (tftpd_lookup_entry(check, dest))) + found = 1; + break; + } + len = seek - check; + memcpy(comp, check, len); + comp[len]=0; + if (!tftpd_lookup_entry(comp, dest)) + break; + check += len + 1; + } + + if (found) + { + filename[0] = 0; + strcat(filename, dest + strlen(directory)); + } + else + { + seek = filename; + while (*seek) + { + if (*seek == '\\') *seek = '/'; + seek++; + } + filename++; + } + + logger(LOG_DEBUG, "Filecase lookup file: %s (found %s)", filename, (found ? "yes" : "no")); + return found; +} /* * Rules for filenames. This is common to both tftpd_recieve_file