avoid changing deliver_homw appendfile_safe_path
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 29 Aug 2020 23:12:49 +0000 (00:12 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 29 Aug 2020 23:12:49 +0000 (00:12 +0100)
src/src/transports/appendfile.c

index 95857a53e01fb705687e60f7b5c2982eb1fbfa7f..a3bc3fe3d3b33fc27120288bc75aa77db574a7b5 100644 (file)
@@ -888,22 +888,23 @@ we can't do any tests.
 Arguments:
   filename     the file name
   create_file  the ob->create_file option
+  deliver_dir  the delivery directory
 
 Returns:       TRUE if creation is permitted
 */
 
 static BOOL
-check_creation(uschar *filename, int create_file)
+check_creation(uschar *filename, int create_file, const uschar * deliver_dir)
 {
 BOOL yield = TRUE;
 
-if (deliver_home  &&  create_file != create_anywhere)
+if (deliver_dir  &&  create_file != create_anywhere)
   {
-  int len = Ustrlen(deliver_home);
+  int len = Ustrlen(deliver_dir);
   uschar *file = filename;
 
   while (file[0] == '/' && file[1] == '/') file++;
-  if (  Ustrncmp(file, deliver_home, len) != 0
+  if (  Ustrncmp(file, deliver_dir, len) != 0
      || file[len] != '/'
      ||    Ustrchr(file+len+2, '/') != NULL
        && (  create_file != create_belowhome
@@ -946,10 +947,10 @@ if (deliver_home  &&  create_file != create_anywhere)
     if (rp)
       {
       uschar hdbuffer[PATH_MAX+1];
-      uschar *rph = deliver_home;
+      const uschar * rph = deliver_dir;
       int rlen = Ustrlen(big_buffer);
 
-      if ((rp = US realpath(CS deliver_home, CS hdbuffer)))
+      if ((rp = US realpath(CS deliver_dir, CS hdbuffer)))
         {
         rph = hdbuffer;
         len = Ustrlen(rph);
@@ -960,7 +961,7 @@ if (deliver_home  &&  create_file != create_anywhere)
         {
         yield = FALSE;
         DEBUG(D_transport) debug_printf("Real path \"%s\" does not match \"%s\"\n",
-          big_buffer, deliver_home);
+          big_buffer, deliver_dir);
         }
       }
     }
@@ -1130,6 +1131,7 @@ appendfile_transport_entry(
 appendfile_transport_options_block *ob =
   (appendfile_transport_options_block *)(tblock->options_block);
 struct stat statbuf;
+const uschar * deliver_dir;
 uschar *fdname = NULL;
 uschar *filename = NULL;
 uschar *hitchname = NULL;
@@ -1312,8 +1314,8 @@ if (f.dont_deliver)
 /* If an absolute path was given for create_file the it overrides deliver_home
 (here) and de-taints the filename (below, after check_creation() */
 
-if (*ob->create_file_string == '/')
-  deliver_home = ob->create_file_string;
+deliver_dir = *ob->create_file_string == '/'
+  ? ob->create_file_string : deliver_home;
 
 /* Handle the case of a file name. If the file name is /dev/null, we can save
 ourselves some effort and just give a success return right away. */
@@ -1334,9 +1336,8 @@ if (!isdirectory)
   is written, and find out if we are permitted to create a non-existent file.
   If the create_file option is an absolute path and the file was within it,
   de-taint.  Chaeck for a tainted path. */
-/*XXX could we just de-taint on belowhome? */
 
-  if (  (allow_creation_here = check_creation(path, ob->create_file))
+  if (  (allow_creation_here = check_creation(path, ob->create_file, deliver_dir))
      && ob->create_file == create_belowhome)
     if (is_tainted(path))
       {
@@ -2165,7 +2166,8 @@ else
   uschar *check_path;          /* Default quota check path */
   const pcre *regex = NULL;     /* Regex for file size from file name */
 
-  if (!check_creation(string_sprintf("%s/any", path), ob->create_file))
+  if (!check_creation(string_sprintf("%s/any", path),
+                     ob->create_file, deliver_dir))
     {
     addr->basic_errno = ERRNO_BADCREATE;
     addr->message = string_sprintf("tried to create file in %s, but "