Account properly for quoted or 2047-encoded MIME parameters while walking headers...
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 14 Dec 2014 15:15:34 +0000 (15:15 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 14 Dec 2014 15:15:34 +0000 (15:15 +0000)
src/src/mime.c
test/log/4000
test/mail/4000.userx
test/scripts/4000-scanning/4000
test/stdout/4000

index ab701f2a682e59f0adeeefb24e4e9344b9c792fd..a61e9f22f15844623fd5d81ab199feab987c4ed2 100644 (file)
@@ -528,26 +528,24 @@ while(1)
    */
   if (context != NULL)
     {
-    while(fgets(CS header, MIME_MAX_HEADER_SIZE, f) != NULL)
+    while(fgets(CS header, MIME_MAX_HEADER_SIZE, f))
       {
       /* boundary line must start with 2 dashes */
-      if (Ustrncmp(header,"--",2) == 0)
-        {
-       if (Ustrncmp((header+2),context->boundary,Ustrlen(context->boundary)) == 0)
+      if (  Ustrncmp(header, "--", 2) == 0
+        && Ustrncmp(header+2, context->boundary, Ustrlen(context->boundary)) == 0)
+       {
+       /* found boundary */
+       if (Ustrncmp((header+2+Ustrlen(context->boundary)), "--", 2) == 0)
          {
-         /* found boundary */
-         if (Ustrncmp((header+2+Ustrlen(context->boundary)),"--",2) == 0)
-           {
-           /* END boundary found */
-           debug_printf("End boundary found %s\n", context->boundary);
-           return rc;
-           }
-         else
-           debug_printf("Next part with boundary %s\n", context->boundary);
-
-         /* can't use break here */
-         goto DECODE_HEADERS;
+         /* END boundary found */
+         debug_printf("End boundary found %s\n", context->boundary);
+         return rc;
          }
+       else
+         debug_printf("Next part with boundary %s\n", context->boundary);
+
+       /* can't use break here */
+       goto DECODE_HEADERS;
        }
       }
     /* Hit EOF or read error. Ugh. */
@@ -557,92 +555,103 @@ while(1)
 
 DECODE_HEADERS:
   /* parse headers, set up expansion variables */
-  while (mime_get_header(f,header))
+  while (mime_get_header(f, header))
     {
     int i;
     /* loop through header list */
     for (i = 0; i < mime_header_list_size; i++)
-      {
-      uschar *header_value = NULL;
-      int header_value_len = 0;
-
-      /* found an interesting header? */
-      if (strncmpic(mime_header_list[i].name,header,mime_header_list[i].namelen) == 0)
-       {
-       uschar *p = header + mime_header_list[i].namelen;
-       /* yes, grab the value (normalize to lower case)
-          and copy to its corresponding expansion variable */
+      if (strncmpic(mime_header_list[i].name,
+           header, mime_header_list[i].namelen) == 0)
+       {                               /* found an interesting header */
+       uschar * header_value;
+       int header_value_len;
+       uschar * p = header + mime_header_list[i].namelen;
+
+       /* grab the value (normalize to lower case)
+       and copy to its corresponding expansion variable */
        while(*p != ';')
          {
          *p = tolower(*p);
          p++;
          }
-       header_value_len = (p - (header + mime_header_list[i].namelen));
-       header_value = (uschar *)malloc(header_value_len+1);
-       memset(header_value,0,header_value_len+1);
+       header_value_len = p - (header + mime_header_list[i].namelen);
        p = header + mime_header_list[i].namelen;
-       Ustrncpy(header_value, p, header_value_len);
-       debug_printf("Found %s MIME header, value is '%s'\n", mime_header_list[i].name, header_value);
+       header_value = string_copyn(p, header_value_len);
+       debug_printf("Found %s MIME header, value is '%s'\n",
+                       mime_header_list[i].name, header_value);
        *((uschar **)(mime_header_list[i].value)) = header_value;
 
        /* make p point to the next character after the closing ';' */
-       p += (header_value_len+1);
+       p += header_value_len+1;
 
-       /* grab all param=value tags on the remaining line, check if they are interesting */
+       /* grab all param=value tags on the remaining line,
+       check if they are interesting */
 NEXT_PARAM_SEARCH:
-       while (*p != 0)
+       while (*p)
          {
          mime_parameter * mp;
          for (mp = mime_parameter_list;
               mp < &mime_parameter_list[mime_parameter_list_size];
               mp++)
            {
-           uschar *param_value = NULL;
-           int param_value_len = 0;
+           uschar * param_value = NULL;
 
            /* found an interesting parameter? */
            if (strncmpic(mp->name, p, mp->namelen) == 0)
              {
-             uschar *q = p + mp->namelen;
+             uschar * q = p + mp->namelen;
+             int plen = 0;
              int size = 0;
              int ptr = 0;
 
              /* yes, grab the value and copy to its corresponding expansion variable */
              while(*q && *q != ';')            /* ; terminates */
-               {
                if (*q == '"')
                  {
                  q++;                          /* skip leading " */
-                 while(*q && *q != '"')        /* which protects ; */
+                 plen++;                       /* and account for the skip */
+                 while(*q && *q != '"')        /* " protects ; */
+                   {
                    param_value = string_cat(param_value, &size, &ptr, q++, 1);
-                 if (*q) q++;                  /* skip trailing " */
+                   plen++;
+                   }
+                 if (*q)
+                   {
+                   q++;                        /* skip trailing " */
+                   plen++;
+                   }
                  }
                else
+                 {
                  param_value = string_cat(param_value, &size, &ptr, q++, 1);
-               }
+                 plen++;
+                 }
+
              if (param_value)
                {
                param_value[ptr++] = '\0';
-               param_value_len = ptr;
 
                param_value = rfc2047_decode(param_value,
-                     check_rfc2047_length, NULL, 32, &param_value_len, &q);
+                     check_rfc2047_length, NULL, 32, NULL, &q);
                debug_printf("Found %s MIME parameter in %s header, "
                      "value is '%s'\n", mp->name, mime_header_list[i].name,
                      param_value);
                }
              *mp->value = param_value;
-             p += (mp->namelen + param_value_len + 1);
+             p += mp->namelen + plen + 1;      /* name=, content, ; */
              goto NEXT_PARAM_SEARCH;
            }
          }
          /* There is something, but not one of our interesting parameters.
             Advance to the next semicolon */
-         while(*p != ';') p++;
+         while(*p != ';')
+           {
+           if (*p == '"') while(*++p && *p != '"') ;
+           p++;
+           }
          p++;
        }
       }
-    }
   }
 
   /* set additional flag variables (easier access) */
index c5d503a0329e10108af387011fd373700ff7ce57..a6f5d2f7089090f5b8a6e5ececdf40a34873b531 100644 (file)
@@ -4,3 +4,6 @@
 1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss id=20041217133501.GA3058@test.ex
 1999-03-02 09:44:33 10HmaY-0005vi-00 => userx <userx@test.ex> R=r1 T=t1
 1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss id=20041217133501.GA3059@test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => userx <userx@test.ex> R=r1 T=t1
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
index ec9b2cba5015a5d9b6113976514110ea8e372d30..725770d6393a654032bc23c66f0cc0aaeff77d6b 100644 (file)
@@ -180,3 +180,41 @@ foobar
 
 --T4sUOijqQbZv57TR--
 
+From CALLER@myhost.test.ex Tue Mar 02 09:44:33 1999
+Received: from CALLER (helo=test.ex)
+       by myhost.test.ex with local-esmtp (Exim x.yz)
+       (envelope-from <CALLER@myhost.test.ex>)
+       id 10HmaZ-0005vi-00
+       for userx@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+From: J Caesar <jcaesar@test.ex>
+To: a-list00@exim.org
+Message-ID: <20041217133501.GA3059@test.ex>
+Mime-Version: 1.0
+Content-Type: text/html;
+        charset=UTF-8;
+        name=""
+Content-Disposition: inline
+Subject: Nasty
+Sender: CALLER_NAME <CALLER@myhost.test.ex>
+X-0-content-type: text/html
+X-0-filename: 
+X-0-charset: UTF-8
+X-0-boundary: 
+X-0-content-disposition: inline
+X-0-content-transfer-encoding: 
+X-0-content-id: 
+X-0-content-description: 
+X-0-is-multipart: 0
+X-0-is-coverletter: 1
+X-0-is-rfc822: 0
+X-0-decode-filename: TESTSUITE/spool/scan/10HmaZ-0005vi-00/10HmaZ-0005vi-00-00000
+X-0-content-size: 1
+
+--T4sUOijqQbZv57TR
+Content-Type: text/plain;
+
+foobar
+
+--T4sUOijqQbZv57TR--
+
index 649f9825a7aa509021d011ba560daa279594057f..2f760bca0b9d27a0e6253dd218eb4def4887c401 100644 (file)
@@ -97,3 +97,32 @@ foobar
 .
 quit
 ****
+#
+#
+# This one has a different rotten parameter, but should not induce a crash
+#
+exim -odi -bs
+ehlo test.ex
+mail from:<>
+rcpt to:<userx@test.ex>
+data
+Date: Fri, 17 Dec 2004 14:35:01 +0100
+From: J Caesar <jcaesar@test.ex>
+To: a-list00@exim.org
+Message-ID: <20041217133501.GA3059@test.ex>
+Mime-Version: 1.0
+Content-Type: text/html;
+        charset=UTF-8;
+        name=""
+Content-Disposition: inline
+Subject: Nasty
+
+--T4sUOijqQbZv57TR
+Content-Type: text/plain;
+
+foobar
+
+--T4sUOijqQbZv57TR--
+.
+quit
+****
index 789a8fe1a6b2e961af4cbccb26aeac12eafd65d4..42d2eefc7acaf504ef697ae0e9e38b59a3c9e108 100644 (file)
 354 Enter message, ending with "." on a line by itself\r
 250 OK id=10HmaY-0005vi-00\r
 221 myhost.test.ex closing connection\r
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-myhost.test.ex Hello CALLER at test.ex\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250 HELP\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmaZ-0005vi-00\r
+221 myhost.test.ex closing connection\r