1Fix CVE-2015-1419 - config option deny_file is not handled correctly. 2From SUSE: https://bugzilla.suse.com/show_bug.cgi?id=915522 3 4Signed-off-by: Gustavo Zacarias <gustavo@zacarias.com.ar> 5 6Index: vsftpd-3.0.2/ls.c 7=================================================================== 8--- vsftpd-3.0.2.orig/ls.c 9+++ vsftpd-3.0.2/ls.c 10@@ -7,6 +7,7 @@ 11 * Would you believe, code to handle directory listing. 12 */ 13 14+#include <stdlib.h> 15 #include "ls.h" 16 #include "access.h" 17 #include "defs.h" 18@@ -243,11 +244,42 @@ vsf_filename_passes_filter(const struct 19 struct mystr temp_str = INIT_MYSTR; 20 struct mystr brace_list_str = INIT_MYSTR; 21 struct mystr new_filter_str = INIT_MYSTR; 22+ struct mystr normalize_filename_str = INIT_MYSTR; 23+ const char *normname; 24+ const char *path; 25 int ret = 0; 26 char last_token = 0; 27 int must_match_at_current_pos = 1; 28+ 29 str_copy(&filter_remain_str, p_filter_str); 30- str_copy(&name_remain_str, p_filename_str); 31+ 32+ /* normalize filepath */ 33+ path = str_strdup(p_filename_str); 34+ normname = realpath(path, NULL); 35+ if (normname == NULL) 36+ goto out; 37+ str_alloc_text(&normalize_filename_str, normname); 38+ 39+ if (!str_isempty (&filter_remain_str) && !str_isempty(&normalize_filename_str)) { 40+ if (str_get_char_at(p_filter_str, 0) == '/') { 41+ if (str_get_char_at(&normalize_filename_str, 0) != '/') { 42+ str_getcwd (&name_remain_str); 43+ 44+ if (str_getlen(&name_remain_str) > 1) /* cwd != root dir */ 45+ str_append_char (&name_remain_str, '/'); 46+ 47+ str_append_str (&name_remain_str, &normalize_filename_str); 48+ } 49+ else 50+ str_copy (&name_remain_str, &normalize_filename_str); 51+ } else { 52+ if (str_get_char_at(p_filter_str, 0) != '{') 53+ str_basename (&name_remain_str, &normalize_filename_str); 54+ else 55+ str_copy (&name_remain_str, &normalize_filename_str); 56+ } 57+ } else 58+ str_copy(&name_remain_str, &normalize_filename_str); 59 60 while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX) 61 { 62@@ -360,6 +392,9 @@ vsf_filename_passes_filter(const struct 63 ret = 0; 64 } 65 out: 66+ free(normname); 67+ free(path); 68+ str_free(&normalize_filename_str); 69 str_free(&filter_remain_str); 70 str_free(&name_remain_str); 71 str_free(&temp_str); 72Index: vsftpd-3.0.2/str.c 73=================================================================== 74--- vsftpd-3.0.2.orig/str.c 75+++ vsftpd-3.0.2/str.c 76@@ -711,3 +711,14 @@ str_replace_unprintable(struct mystr* p_ 77 } 78 } 79 80+void 81+str_basename (struct mystr* d_str, const struct mystr* path) 82+{ 83+ static struct mystr tmp; 84+ 85+ str_copy (&tmp, path); 86+ str_split_char_reverse(&tmp, d_str, '/'); 87+ 88+ if (str_isempty(d_str)) 89+ str_copy (d_str, path); 90+} 91Index: vsftpd-3.0.2/str.h 92=================================================================== 93--- vsftpd-3.0.2.orig/str.h 94+++ vsftpd-3.0.2/str.h 95@@ -100,6 +100,7 @@ void str_replace_unprintable(struct myst 96 int str_atoi(const struct mystr* p_str); 97 filesize_t str_a_to_filesize_t(const struct mystr* p_str); 98 unsigned int str_octal_to_uint(const struct mystr* p_str); 99+void str_basename (struct mystr* d_str, const struct mystr* path); 100 101 /* PURPOSE: Extract a line of text (delimited by \n or EOF) from a string 102 * buffer, starting at character position 'p_pos'. The extracted line will 103