d7fdbd
From 548375b2122f83771dc0b8571f16e5b5adabba98 Mon Sep 17 00:00:00 2001
d7fdbd
From: Martin Sehnoutka <msehnout@redhat.com>
d7fdbd
Date: Wed, 7 Sep 2016 10:04:31 +0200
d7fdbd
Subject: [PATCH 07/59] Make filename filters smarter.
d7fdbd
d7fdbd
In the original version vsftpd was not able to prevent
d7fdbd
users from downloading for instance /etc/passwd by
d7fdbd
defining filters such as deny_file=/etc/passwd or /etc*
d7fdbd
or passwd. Example of erroneous behavior:
d7fdbd
230 Login successful.
d7fdbd
Remote system type is UNIX.
d7fdbd
Using binary mode to transfer files.
d7fdbd
ftp> cd /
d7fdbd
250 Directory successfully changed.
d7fdbd
ftp> cd /etc
d7fdbd
550 Permission denied.
d7fdbd
ftp> cd etc
d7fdbd
250 Directory successfully changed.
d7fdbd
ftp> get passwd
d7fdbd
local: passwd remote: passwd
d7fdbd
227 Entering Passive Mode (127,0,0,1,99,251)
d7fdbd
150 Opening BINARY mode data connection for passwd (2813 bytes).
d7fdbd
226 File send OK.
d7fdbd
2813 bytes received in 0.00016 seconds (1.7e+04 Kbytes/s)
d7fdbd
ftp> quit
d7fdbd
221 Goodbye.
d7fdbd
---
d7fdbd
 ls.c  | 24 +++++++++++++++++++++++-
d7fdbd
 str.c | 11 +++++++++++
d7fdbd
 str.h |  1 +
d7fdbd
 3 files changed, 35 insertions(+), 1 deletion(-)
d7fdbd
d7fdbd
diff --git a/ls.c b/ls.c
d7fdbd
index 7e1376d..f489478 100644
d7fdbd
--- a/ls.c
d7fdbd
+++ b/ls.c
d7fdbd
@@ -246,8 +246,30 @@ vsf_filename_passes_filter(const struct mystr* p_filename_str,
d7fdbd
   int ret = 0;
d7fdbd
   char last_token = 0;
d7fdbd
   int must_match_at_current_pos = 1;
d7fdbd
+
d7fdbd
+
d7fdbd
   str_copy(&filter_remain_str, p_filter_str);
d7fdbd
-  str_copy(&name_remain_str, p_filename_str);
d7fdbd
+
d7fdbd
+  if (!str_isempty (&filter_remain_str) && !str_isempty(p_filename_str)) {
d7fdbd
+    if (str_get_char_at(p_filter_str, 0) == '/') {
d7fdbd
+      if (str_get_char_at(p_filename_str, 0) != '/') {
d7fdbd
+        str_getcwd (&name_remain_str);
d7fdbd
+
d7fdbd
+        if (str_getlen(&name_remain_str) > 1) /* cwd != root dir */
d7fdbd
+          str_append_char (&name_remain_str, '/');
d7fdbd
+
d7fdbd
+        str_append_str (&name_remain_str, p_filename_str);
d7fdbd
+      }
d7fdbd
+      else
d7fdbd
+       str_copy (&name_remain_str, p_filename_str);
d7fdbd
+    } else {
d7fdbd
+      if (str_get_char_at(p_filter_str, 0) != '{')
d7fdbd
+        str_basename (&name_remain_str, p_filename_str);
d7fdbd
+      else
d7fdbd
+        str_copy (&name_remain_str, p_filename_str);
d7fdbd
+    }
d7fdbd
+  } else
d7fdbd
+    str_copy(&name_remain_str, p_filename_str);
d7fdbd
 
d7fdbd
   while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX)
d7fdbd
   {
d7fdbd
diff --git a/str.c b/str.c
d7fdbd
index 6596204..ba4b92a 100644
d7fdbd
--- a/str.c
d7fdbd
+++ b/str.c
d7fdbd
@@ -711,3 +711,14 @@ str_replace_unprintable(struct mystr* p_str, char new_char)
d7fdbd
   }
d7fdbd
 }
d7fdbd
 
d7fdbd
+void
d7fdbd
+str_basename (struct mystr* d_str, const struct mystr* path)
d7fdbd
+{
d7fdbd
+  static struct mystr tmp;
d7fdbd
+
d7fdbd
+  str_copy (&tmp, path);
d7fdbd
+  str_split_char_reverse(&tmp, d_str, '/');
d7fdbd
+
d7fdbd
+  if (str_isempty(d_str))
d7fdbd
+   str_copy (d_str, path);
d7fdbd
+}
d7fdbd
diff --git a/str.h b/str.h
d7fdbd
index ab0a9a4..3a21b50 100644
d7fdbd
--- a/str.h
d7fdbd
+++ b/str.h
d7fdbd
@@ -100,6 +100,7 @@ void str_replace_unprintable(struct mystr* p_str, char new_char);
d7fdbd
 int str_atoi(const struct mystr* p_str);
d7fdbd
 filesize_t str_a_to_filesize_t(const struct mystr* p_str);
d7fdbd
 unsigned int str_octal_to_uint(const struct mystr* p_str);
d7fdbd
+void str_basename (struct mystr* d_str, const struct mystr* path);
d7fdbd
 
d7fdbd
 /* PURPOSE: Extract a line of text (delimited by \n or EOF) from a string
d7fdbd
  * buffer, starting at character position 'p_pos'. The extracted line will
d7fdbd
-- 
d7fdbd
2.14.4
d7fdbd