From 3a8236c9344d6c757760a785510315d851bcbe62 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 2 Apr 2017 11:59:38 +0100 Subject: [PATCH] [Fix] Fix parsing of non-RFC compatible Exim received Issue: #1575 --- src/ragel/smtp_ip.rl | 6 ++- src/ragel/smtp_received.rl | 5 +- src/ragel/smtp_received_parser.rl | 89 ++++++++++++++----------------- 3 files changed, 48 insertions(+), 52 deletions(-) diff --git a/src/ragel/smtp_ip.rl b/src/ragel/smtp_ip.rl index dae90a096..cd9bec64f 100644 --- a/src/ragel/smtp_ip.rl +++ b/src/ragel/smtp_ip.rl @@ -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 diff --git a/src/ragel/smtp_received.rl b/src/ragel/smtp_received.rl index 8b88d4ffe..ff3f10d19 100644 --- a/src/ragel/smtp_received.rl +++ b/src/ragel/smtp_received.rl @@ -27,9 +27,12 @@ ( 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; diff --git a/src/ragel/smtp_received_parser.rl b/src/ragel/smtp_received_parser.rl index 12b1c1b5c..b22f34f03 100644 --- a/src/ragel/smtp_received_parser.rl +++ b/src/ragel/smtp_received_parser.rl @@ -134,12 +134,8 @@ 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; @@ -149,12 +145,8 @@ 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; @@ -162,55 +154,28 @@ } 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); } } @@ -221,9 +186,9 @@ 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); } -- 2.39.5