]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Fix parsing of non-RFC compatible Exim received
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 2 Apr 2017 10:59:38 +0000 (11:59 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sun, 2 Apr 2017 11:00:23 +0000 (12:00 +0100)
Issue: #1575

src/ragel/smtp_ip.rl
src/ragel/smtp_received.rl
src/ragel/smtp_received_parser.rl

index dae90a09651cdb1d7216d48c62e35e98ed4dc7c2..cd9bec64f721ea949120a67caec45afa6de09ef6 100644 (file)
@@ -5,7 +5,8 @@
   # Source: https://tools.ietf.org/html/rfc5321#section-4.1.3
 
   Snum           = digit{1,3};
-  IPv4_address_literal  = (Snum ("."  Snum){3}) >IP4_start %IP4_end;
+  IPv4_addr = (Snum ("."  Snum){3});
+  IPv4_address_literal  = IPv4_addr >IP4_start %IP4_end;
   IPv6_hex       = xdigit{1,4};
   IPv6_full      = IPv6_hex (":" IPv6_hex){7};
   IPv6_comp      = (IPv6_hex (":" IPv6_hex){0,5})? "::"
@@ -14,6 +15,7 @@
   IPv6v4_comp    = (IPv6_hex (":" IPv6_hex){0,3})? "::"
                   (IPv6_hex (":" IPv6_hex){0,3} ":")?
                   IPv4_address_literal;
-  IPv6_addr      = IPv6_full | IPv6_comp | IPv6v4_full | IPv6v4_comp;
+  IPv6_simple    = IPv6_full | IPv6_comp;
+  IPv6_addr      = IPv6_simple | IPv6v4_full | IPv6v4_comp;
   IPv6_address_literal  = "IPv6:" %IP6_start IPv6_addr %IP6_end;
 }%%
\ No newline at end of file
index 8b88d4ffe372cb10d5a307fd9d3e0b0fa5864f21..ff3f10d19ae1c647403e64e8d9d790ec34d29161 100644 (file)
                   ( address_literal >Real_Domain_Start %Real_Domain_End FWS "(" TCP_info ")" ) |
                   address_literal >Real_IP_Start %Real_IP_End; # Not RFC conforming, but many MTA try this
 
+  exim_real_ip = "[" (IPv4_addr|IPv6_simple) >IP4_start %IP4_end "]"
+                  >Real_IP_Start %Real_IP_End (":" digit{1,4})?;
+  exim_content = exim_real_ip;
   ccontent = ctext | FWS | '(' @{ fcall balanced_ccontent; };
   balanced_ccontent := ccontent* ')' @{ fret; };
-  comment        =   "(" (FWS? ccontent)* FWS? ")";
+  comment        =   "(" (FWS? ccontent|exim_content)* FWS? ")";
   CFWS           =   ((FWS? comment)+ FWS?) | FWS;
 
   From_domain    = "FROM"i FWS Extended_Domain >From_Start %From_End;
index 12b1c1b5cc5b5e39cbf876bc5b01474ed0cd4e2e..b22f34f03528b85503dab70e9c5df2f45575ce87 100644 (file)
   action From_Start {
     real_domain_start = NULL;
     real_domain_end = NULL;
-    real_ip_start = NULL;
-    real_ip_end = NULL;
     reported_domain_start = NULL;
     reported_domain_end = NULL;
-    reported_ip_start = NULL;
-    reported_ip_end = NULL;
     ip_start = NULL;
     ip_end = NULL;
     for_start = NULL;
   action By_Start {
     real_domain_start = NULL;
     real_domain_end = NULL;
-    real_ip_start = NULL;
-    real_ip_end = NULL;
     reported_domain_start = NULL;
     reported_domain_end = NULL;
-    reported_ip_start = NULL;
-    reported_ip_end = NULL;
     ip_start = NULL;
     ip_end = NULL;
     for_start = NULL;
   }
 
   action By_End {
-    guint len;
-
     if (real_domain_end && real_domain_start && real_domain_end > real_domain_start) {
-      len = real_domain_end - real_domain_start;
-      rh->by_hostname = rspamd_mempool_alloc (task->task_pool, len + 1);
-      rspamd_strlcpy (rh->by_hostname, real_domain_start, len + 1);
+      tmplen = real_domain_end - real_domain_start;
+      rh->by_hostname = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
+      rspamd_strlcpy (rh->by_hostname, real_domain_start, tmplen + 1);
     }
     else if (reported_domain_end && reported_domain_start && reported_domain_end > reported_domain_start) {
       len = reported_domain_end - reported_domain_start;
-      rh->by_hostname = rspamd_mempool_alloc (task->task_pool, len + 1);
-      rspamd_strlcpy (rh->by_hostname, reported_domain_start, len + 1);
+      rh->by_hostname = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
+      rspamd_strlcpy (rh->by_hostname, reported_domain_start, tmplen + 1);
     }
   }
 
   action From_End {
-    guint len;
-
     if (real_domain_end && real_domain_start && real_domain_end > real_domain_start) {
-      len = real_domain_end - real_domain_start;
-      rh->real_hostname = rspamd_mempool_alloc (task->task_pool, len + 1);
-      rspamd_strlcpy (rh->real_hostname, real_domain_start, len + 1);
+      tmplen = real_domain_end - real_domain_start;
+      rh->real_hostname = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
+      rspamd_strlcpy (rh->real_hostname, real_domain_start, tmplen + 1);
     }
     if (reported_domain_end && reported_domain_start && reported_domain_end > reported_domain_start) {
-      len = reported_domain_end - reported_domain_start;
-      rh->from_hostname = rspamd_mempool_alloc (task->task_pool, len + 1);
-      rspamd_strlcpy (rh->from_hostname, reported_domain_start, len + 1);
-    }
-    if (real_ip_end && real_ip_start && real_ip_end > real_ip_start) {
-      len = real_ip_end - real_ip_start;
-      rh->real_ip = rspamd_mempool_alloc (task->task_pool, len + 1);
-      rspamd_strlcpy (rh->real_ip, real_ip_start, len + 1);
-    }
-    if (reported_ip_end && reported_ip_start && reported_ip_end > reported_ip_start) {
-      len = reported_ip_end - reported_ip_start;
-      rh->from_ip = rspamd_mempool_alloc (task->task_pool, len + 1);
-      rspamd_strlcpy (rh->from_ip, reported_ip_start, len + 1);
-    }
-
-    if (rh->real_ip && !rh->from_ip) {
-      rh->from_ip = rh->real_ip;
-    }
-    if (rh->real_hostname && !rh->from_hostname) {
-      rh->from_hostname = rh->real_hostname;
-    }
-
-    if (rh->real_ip) {
-      if (rspamd_parse_inet_address (&rh->addr, rh->real_ip, strlen (rh->real_ip))) {
-        rspamd_mempool_add_destructor (task->task_pool, (rspamd_mempool_destruct_t)rspamd_inet_address_destroy, rh->addr);
-      }
+      tmplen = reported_domain_end - reported_domain_start;
+      rh->from_hostname = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
+      rspamd_strlcpy (rh->from_hostname, reported_domain_start, tmplen + 1);
     }
   }
 
   action For_End {
     if (for_start && p > for_start) {
       for_end = p;
-      len = for_end - for_start;
-      rh->for_mbox = rspamd_mempool_alloc (task->task_pool, len + 1);
-      rspamd_strlcpy (rh->for_mbox, for_start, len + 1);
+      tmplen = for_end - for_start;
+      rh->for_mbox = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
+      rspamd_strlcpy (rh->for_mbox, for_start, tmplen + 1);
     }
   }
 
@@ -287,6 +252,7 @@ rspamd_smtp_recieved_parse (struct rspamd_task *task, const char *data, size_t l
     int *data;
     gsize size;
   } st_storage;
+  guint tmplen;
 
   memset (&st_storage, 0, sizeof (st_storage));
   memset (rh, 0, sizeof (*rh));
@@ -313,6 +279,31 @@ rspamd_smtp_recieved_parse (struct rspamd_task *task, const char *data, size_t l
   %% write init;
   %% write exec;
 
+  if (real_ip_end && real_ip_start && real_ip_end > real_ip_start) {
+    tmplen = real_ip_end - real_ip_start;
+    rh->real_ip = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
+    rspamd_strlcpy (rh->real_ip, real_ip_start, tmplen + 1);
+  }
+  if (reported_ip_end && reported_ip_start && reported_ip_end > reported_ip_start) {
+    tmplen = reported_ip_end - reported_ip_start;
+    rh->from_ip = rspamd_mempool_alloc (task->task_pool, tmplen + 1);
+    rspamd_strlcpy (rh->from_ip, reported_ip_start, tmplen + 1);
+  }
+
+  if (rh->real_ip && !rh->from_ip) {
+    rh->from_ip = rh->real_ip;
+  }
+  if (rh->real_hostname && !rh->from_hostname) {
+    rh->from_hostname = rh->real_hostname;
+  }
+
+  if (rh->real_ip) {
+    if (rspamd_parse_inet_address (&rh->addr, rh->real_ip, strlen (rh->real_ip))) {
+      rspamd_mempool_add_destructor (task->task_pool,
+              (rspamd_mempool_destruct_t)rspamd_inet_address_destroy, rh->addr);
+    }
+  }
+
   if (st_storage.data) {
     free (st_storage.data);
   }