]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Fix various issues with parsing of the received headers
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 16 Oct 2018 11:29:01 +0000 (12:29 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 16 Oct 2018 11:29:01 +0000 (12:29 +0100)
src/libmime/email_addr.c
src/libmime/email_addr.h
src/libmime/message.h
src/ragel/smtp_received.rl
src/ragel/smtp_received_parser.rl

index 8376e8f78909666f89cc300e868fa4734dc1387a..3b9f31de95651fc53110b0573faf6c840c3d8b49 100644 (file)
@@ -485,3 +485,29 @@ rspamd_email_address_list_destroy (gpointer ptr)
 
        g_ptr_array_free (ar, TRUE);
 }
+
+void rspamd_smtp_maybe_process_smtp_comment (struct rspamd_task *task,
+                                                                                        const char *data, size_t len,
+                                                                                        struct received_header *rh)
+{
+       if (!rh->by_hostname) {
+               /* Heuristic to detect IP addresses like in Exim received:
+                * [xxx]:port or [xxx]
+                */
+
+               if (*data == '[' && len > 2) {
+                       const gchar *p = data + 1;
+                       gsize iplen = rspamd_memcspn (p, "]", len - 1);
+
+                       if (iplen > 0) {
+                               guchar tbuf[sizeof(struct in6_addr) + sizeof(guint32)];
+
+                               if (rspamd_parse_inet_address_ip4 (p, iplen, tbuf) ||
+                                               rspamd_parse_inet_address_ip6 (p, iplen, tbuf)) {
+                                       rh->comment_ip = rspamd_mempool_alloc (task->task_pool, iplen + 1);
+                                       rspamd_strlcpy (rh->comment_ip, p, iplen + 1);
+                               }
+                       }
+               }
+       }
+}
\ No newline at end of file
index 8c9b54713127f8ad4968a0432691719d7fb4a925..129d2ba44874e8c0bf40476e2e10e5f646b8256a 100644 (file)
@@ -51,6 +51,19 @@ struct rspamd_email_address {
        guchar flags;
 };
 
+struct received_header;
+struct rspamd_task;
+/**
+ * Try to parse SMTP comment to process stupid Exim received headers
+ * @param task
+ * @param data
+ * @param len
+ * @param rh
+ */
+void rspamd_smtp_maybe_process_smtp_comment (struct rspamd_task *task,
+                                                                                        const char *data, size_t len,
+                                                                                        struct received_header *rh);
+
 /**
  * Create email address from a single rfc822 address (e.g. from mail from:)
  * @param str string to use
index 205bf5bb2e5c2631fe425d145a51e6157c77a747..17077860d628710a3b34075e1e96167178036926 100644 (file)
@@ -144,6 +144,7 @@ struct received_header {
        gchar *real_ip;
        gchar *by_hostname;
        gchar *for_mbox;
+       gchar *comment_ip;
        rspamd_inet_addr_t *addr;
        struct rspamd_mime_header *hdr;
        time_t timestamp;
index b13259fed8c88b818f45cd646f9b89df312d7022..f43ad167c109c3bf9eb38067c2ab1038099c4fef 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|exim_content)* FWS? ")";
+  comment        =   "(" ((FWS? ccontent)* FWS?) >Comment_Start %Comment_End ")";
   CFWS           =   ((FWS? comment)+ FWS?) | FWS;
 
   From_domain    = "FROM"i FWS Extended_Domain >From_Start %From_End;
index 565a20b7fbd6390e4989084f36007c7d737e7982..836a02384f0502cff02f1df3c289d9c2040565d8 100644 (file)
   }
 
   action Real_IP_Start {
-    if (real_ip_end == NULL) {
+    if (real_ip_end == NULL && real_ip_start == NULL) {
       real_ip_start = p;
     }
   }
   action Real_IP_End {
-    if (ip_start && ip_end && ip_end > ip_start) {
-      real_ip_start = ip_start;
-      real_ip_end = ip_end;
-    }
-    else {
-      real_ip_end = p;
-    }
-
-    ip_start = NULL;
-    ip_end = NULL;
-  }
-  action Reported_IP_Start {
-    reported_ip_start = p;
-  }
-  action Reported_IP_End {
-
-    if (ip_start && ip_end && ip_end > ip_start) {
-      reported_ip_start = ip_start;
-      reported_ip_end = ip_end;
-    }
-    else {
-      reported_ip_end = p;
+    if (real_ip_end == NULL && real_ip_start != NULL) {
+      if (ip_start && ip_end && ip_end > ip_start) {
+        real_ip_start = ip_start;
+        real_ip_end = ip_end;
+      }
+      else {
+        real_ip_end = p;
+      }
     }
 
     ip_start = NULL;
     }
   }
 
+  action Comment_Start {
+    cstart = p;
+  }
+
+  action Comment_End {
+    cend = p;
+
+    if (cend && cstart && cend > cstart) {
+      rspamd_smtp_maybe_process_smtp_comment (task, cstart, cend - cstart, rh);
+    }
+
+    cend = NULL;
+    cstart = NULL;
+  }
+
   include smtp_whitespace "smtp_whitespace.rl";
   include smtp_ip "smtp_ip.rl";
   include smtp_date "smtp_date.rl";
@@ -246,9 +247,8 @@ rspamd_smtp_received_parse (struct rspamd_task *task, const char *data, size_t l
   const char *real_domain_start, *real_domain_end,
               *real_ip_start, *real_ip_end,
               *reported_domain_start, *reported_domain_end,
-              *reported_ip_start, *reported_ip_end,
               *ip_start, *ip_end, *date_start,
-              *for_start, *for_end, *tmp;
+              *for_start, *for_end, *tmp, *cstart, *cend;
   struct tm tm;
   const char *p = data, *pe = data + len, *eof;
   int cs, in_v6 = 0, *stack = NULL;
@@ -269,13 +269,13 @@ rspamd_smtp_received_parse (struct rspamd_task *task, const char *data, size_t l
   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;
   date_start = NULL;
   for_start = NULL;
   for_end = NULL;
+  cstart = NULL;
+  cend = NULL;
   rh->type = RSPAMD_RECEIVED_UNKNOWN;
 
   memset (&for_addr, 0, sizeof (for_addr));
@@ -290,10 +290,9 @@ rspamd_smtp_received_parse (struct rspamd_task *task, const char *data, size_t l
     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->comment_ip) {
+    rh->real_ip = rh->comment_ip;
   }
 
   if (rh->real_ip && !rh->from_ip) {