Fix mime ACL filename decode
[exim.git] / src / src / mime.c
index 7b1fa387d7cde8be790e8c2c7d5b498fcdfb0142..17643eda366f5ef1ea621aa8761932082f09e04c 100644 (file)
@@ -2,8 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004, 2015 */
-/* License: GPL */
+/* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004, 2015
+ * License: GPL
+ * Copyright (c) The Exim Maintainers 2016
+ */
 
 #include "exim.h"
 #ifdef WITH_CONTENT_SCAN       /* entire file */
 
 FILE *mime_stream = NULL;
 uschar *mime_current_boundary = NULL;
-static int mime_header_list_size = sizeof(mime_header_list)/sizeof(mime_header);
+
+static mime_header mime_header_list[] = {
+  { US"content-type:",              13, &mime_content_type },
+  { US"content-disposition:",       20, &mime_content_disposition },
+  { US"content-transfer-encoding:", 26, &mime_content_transfer_encoding },
+  { US"content-id:",                11, &mime_content_id },
+  { US"content-description:",       20, &mime_content_description }
+};
+
+static int mime_header_list_size = nelem(mime_header_list);
 
 static mime_parameter mime_parameter_list[] = {
   { US"name=",     5, &mime_filename },
@@ -177,21 +188,17 @@ return size;
 }
 
 
+/*
+ * Return open filehandle for combo of path and file.
+ * Side-effect: set mime_decoded_filename, to copy in allocated mem
+ */
 static FILE *
 mime_get_decode_file(uschar *pname, uschar *fname)
 {
-FILE *f = NULL;
-uschar *filename;
-
-filename = (uschar *)malloc(2048);
-
 if (pname && fname)
-  {
-  (void)string_format(filename, 2048, "%s/%s", pname, fname);
-  f = modefopen(filename,"wb+",SPOOL_MODE);
-  }
+  mime_decoded_filename = string_sprintf("%s/%s", pname, fname);
 else if (!pname)
-  f = modefopen(fname,"wb+",SPOOL_MODE);
+  mime_decoded_filename = string_copy(fname);
 else if (!fname)
   {
   int file_nr = 0;
@@ -201,21 +208,15 @@ else if (!fname)
   do
     {
     struct stat mystat;
-    (void)string_format(filename, 2048,
-      "%s/%s-%05u", pname, message_id, file_nr++);
+    mime_decoded_filename = string_sprintf("%s/%s-%05u", pname, message_id, file_nr++);
     /* security break */
     if (file_nr >= 1024)
       break;
-    result = stat(CS filename, &mystat);
+    result = stat(CS mime_decoded_filename, &mystat);
     } while(result != -1);
-
-  f = modefopen(filename, "wb+", SPOOL_MODE);
   }
 
-/* set expansion variable */
-mime_decoded_filename = filename;
-
-return f;
+return modefopen(mime_decoded_filename, "wb+", SPOOL_MODE);
 }
 
 
@@ -295,7 +296,8 @@ decode_function =
 size_counter = decode_function(mime_stream, decode_file, mime_current_boundary);
 
 clearerr(mime_stream);
-fseek(mime_stream, f_pos, SEEK_SET);
+if (fseek(mime_stream, f_pos, SEEK_SET))
+  return DEFER;
 
 if (fclose(decode_file) != 0 || size_counter < 0)
   return DEFER;
@@ -453,11 +455,11 @@ while (*s && *s != ';')           /* ; terminates */
     {
     s++;                       /* skip opening " */
     while (*s && *s != '"')    /* " protects ; */
-      val = string_cat(val, &size, &ptr, s++, 1);
+      val = string_catn(val, &size, &ptr, s++, 1);
     if (*s) s++;               /* skip closing " */
     }
   else
-    val = string_cat(val, &size, &ptr, s++, 1);
+    val = string_catn(val, &size, &ptr, s++, 1);
 if (val) val[ptr] = '\0';
 *sp = s;
 return val;
@@ -484,24 +486,24 @@ static uschar *
 rfc2231_to_2047(const uschar * fname, const uschar * charset, int * len)
 {
 int size = 0, ptr = 0;
-uschar * val = string_cat(NULL, &size, &ptr, US"=?", 2);
+uschar * val = string_catn(NULL, &size, &ptr, US"=?", 2);
 uschar c;
 
 if (charset)
-  val = string_cat(val, &size, &ptr, charset, Ustrlen(charset));
-val = string_cat(val, &size, &ptr, US"?Q?", 3);
+  val = string_cat(val, &size, &ptr, charset);
+val = string_catn(val, &size, &ptr, US"?Q?", 3);
 
 while ((c = *fname))
   if (c == '%' && isxdigit(fname[1]) && isxdigit(fname[2]))
     {
-    val = string_cat(val, &size, &ptr, US"=", 1);
-    val = string_cat(val, &size, &ptr, ++fname, 2);
+    val = string_catn(val, &size, &ptr, US"=", 1);
+    val = string_catn(val, &size, &ptr, ++fname, 2);
     fname += 2;
     }
   else
-    val = string_cat(val, &size, &ptr, fname++, 1);
+    val = string_catn(val, &size, &ptr, fname++, 1);
 
-val = string_cat(val, &size, &ptr, US"?=", 2);
+val = string_catn(val, &size, &ptr, US"?=", 2);
 val[*len = ptr] = '\0';
 return val;
 }
@@ -799,7 +801,7 @@ while(1)
     if (!mime_decoded_filename)                /* decoding failed */
       {
       log_write(0, LOG_MAIN,
-          "mime_regex acl condition warning - could not decode RFC822 MIME part to file.");
+          "MIME acl condition warning - could not decode RFC822 MIME part to file.");
       rc = DEFER;
       goto out;
       }