From fb4df3f36021d6020a09b0189e5715ac26eedbea Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 4 Aug 2016 16:39:16 +0100 Subject: [PATCH] [Fix] Restore multiple values headers in protocol --- src/libserver/protocol.c | 336 ++++++++++++++++++++------------------- 1 file changed, 169 insertions(+), 167 deletions(-) diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c index 3b511971e..ffefc125f 100644 --- a/src/libserver/protocol.c +++ b/src/libserver/protocol.c @@ -280,193 +280,195 @@ rspamd_protocol_handle_headers (struct rspamd_task *task, rspamd_fstring_t *hn, *hv; rspamd_ftok_t *hn_tok, *hv_tok, srch; gboolean fl, has_ip = FALSE; - struct rspamd_http_header *h, *htmp; + struct rspamd_http_header *header, *h, *htmp; struct rspamd_email_address *addr; - HASH_ITER (hh, msg->headers, h, htmp) { - hn = rspamd_fstring_new_init (h->name->begin, h->name->len); - hv = rspamd_fstring_new_init (h->value->begin, h->value->len); - hn_tok = rspamd_ftok_map (hn); - hv_tok = rspamd_ftok_map (hv); - - g_hash_table_replace (task->request_headers, hn_tok, hv_tok); - - switch (*hn_tok->begin) { - case 'd': - case 'D': - IF_HEADER (DELIVER_TO_HEADER) { - task->deliver_to = rspamd_protocol_escape_braces (task, hv); - debug_task ("read deliver-to header, value: %s", - task->deliver_to); - } - else { - debug_task ("wrong header: %V", hn); - } - break; - case 'h': - case 'H': - IF_HEADER (HELO_HEADER) { - task->helo = rspamd_mempool_ftokdup (task->task_pool, hv_tok); - debug_task ("read helo header, value: %s", task->helo); - } - IF_HEADER (HOSTNAME_HEADER) { - task->hostname = rspamd_mempool_ftokdup (task->task_pool, - hv_tok); - debug_task ("read hostname header, value: %s", task->hostname); - } - break; - case 'f': - case 'F': - IF_HEADER (FROM_HEADER) { - task->from_envelope = rspamd_email_address_from_smtp (hv->str, - hv->len); - if (!task->from_envelope) { - msg_err_task ("bad from header: '%V'", hv); - } - } - else { - debug_task ("wrong header: %V", hn); - } - break; - case 'j': - case 'J': - IF_HEADER (JSON_HEADER) { - fl = rspamd_config_parse_flag (hv->str, hv->len); - if (fl) { - task->flags |= RSPAMD_TASK_FLAG_JSON; + HASH_ITER (hh, msg->headers, header, htmp) { + DL_FOREACH (header, h) { + hn = rspamd_fstring_new_init (h->name->begin, h->name->len); + hv = rspamd_fstring_new_init (h->value->begin, h->value->len); + hn_tok = rspamd_ftok_map (hn); + hv_tok = rspamd_ftok_map (hv); + + g_hash_table_replace (task->request_headers, hn_tok, hv_tok); + + switch (*hn_tok->begin) { + case 'd': + case 'D': + IF_HEADER (DELIVER_TO_HEADER) { + task->deliver_to = rspamd_protocol_escape_braces (task, hv); + debug_task ("read deliver-to header, value: %s", + task->deliver_to); } else { - task->flags &= ~RSPAMD_TASK_FLAG_JSON; + debug_task ("wrong header: %V", hn); } - } - else { - debug_task ("wrong header: %V", hn); - } - break; - case 'q': - case 'Q': - IF_HEADER (QUEUE_ID_HEADER) { - task->queue_id = rspamd_mempool_ftokdup (task->task_pool, - hv_tok); - debug_task ("read queue_id header, value: %s", task->queue_id); - } - else { - debug_task ("wrong header: %V", hn); - } - break; - case 'r': - case 'R': - IF_HEADER (RCPT_HEADER) { - addr = rspamd_email_address_from_smtp (hv->str, hv->len); - - if (addr) { - if (task->rcpt_envelope == NULL) { - task->rcpt_envelope = g_ptr_array_new (); + break; + case 'h': + case 'H': + IF_HEADER (HELO_HEADER) { + task->helo = rspamd_mempool_ftokdup (task->task_pool, hv_tok); + debug_task ("read helo header, value: %s", task->helo); + } + IF_HEADER (HOSTNAME_HEADER) { + task->hostname = rspamd_mempool_ftokdup (task->task_pool, + hv_tok); + debug_task ("read hostname header, value: %s", task->hostname); + } + break; + case 'f': + case 'F': + IF_HEADER (FROM_HEADER) { + task->from_envelope = rspamd_email_address_from_smtp (hv->str, + hv->len); + if (!task->from_envelope) { + msg_err_task ("bad from header: '%V'", hv); } - - g_ptr_array_add (task->rcpt_envelope, addr); } else { - msg_err_task ("bad from header: '%T'", h->value); + debug_task ("wrong header: %V", hn); } - debug_task ("read rcpt header, value: %V", hv); - } - else { - debug_task ("wrong header: %V", hn); - } - break; - case 'i': - case 'I': - IF_HEADER (IP_ADDR_HEADER) { - if (!rspamd_parse_inet_address (&task->from_addr, hv->str, hv->len)) { - msg_err_task ("bad ip header: '%V'", hv); - return FALSE; + break; + case 'j': + case 'J': + IF_HEADER (JSON_HEADER) { + fl = rspamd_config_parse_flag (hv->str, hv->len); + if (fl) { + task->flags |= RSPAMD_TASK_FLAG_JSON; + } + else { + task->flags &= ~RSPAMD_TASK_FLAG_JSON; + } } - debug_task ("read IP header, value: %V", hv); - has_ip = TRUE; - } - else { - debug_task ("wrong header: %V", hn); - } - break; - case 'p': - case 'P': - IF_HEADER (PASS_HEADER) { - srch.begin = "all"; - srch.len = 3; - - if (rspamd_ftok_casecmp (hv_tok, &srch) == 0) { - task->flags |= RSPAMD_TASK_FLAG_PASS_ALL; - debug_task ("pass all filters"); + else { + debug_task ("wrong header: %V", hn); } - } - break; - case 's': - case 'S': - IF_HEADER (SUBJECT_HEADER) { - task->subject = rspamd_mempool_ftokdup (task->task_pool, hv_tok); - } - IF_HEADER (SETTINGS_ID_HEADER) { - guint64 h; - guint32 *hp; - - h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_XXHASH64, - hv_tok->begin, hv_tok->len, 0xdeadbabe); - hp = rspamd_mempool_alloc (task->task_pool, sizeof (*hp)); - memcpy (hp, &h, sizeof (*hp)); - rspamd_mempool_set_variable (task->task_pool, "settings_hash", - hp, NULL); - } - break; - case 'u': - case 'U': - IF_HEADER (USER_HEADER) { - /* - * We must ignore User header in case of spamc, as SA has - * different meaning of this header - */ - if (!RSPAMD_TASK_IS_SPAMC (task)) { - task->user = rspamd_mempool_ftokdup (task->task_pool, + break; + case 'q': + case 'Q': + IF_HEADER (QUEUE_ID_HEADER) { + task->queue_id = rspamd_mempool_ftokdup (task->task_pool, hv_tok); + debug_task ("read queue_id header, value: %s", task->queue_id); } - } - IF_HEADER (URLS_HEADER) { - srch.begin = "extended"; - srch.len = 8; + else { + debug_task ("wrong header: %V", hn); + } + break; + case 'r': + case 'R': + IF_HEADER (RCPT_HEADER) { + addr = rspamd_email_address_from_smtp (hv->str, hv->len); + + if (addr) { + if (task->rcpt_envelope == NULL) { + task->rcpt_envelope = g_ptr_array_new (); + } - if (rspamd_ftok_casecmp (hv_tok, &srch) == 0) { - task->flags |= RSPAMD_TASK_FLAG_EXT_URLS; - debug_task ("extended urls information"); + g_ptr_array_add (task->rcpt_envelope, addr); + } + else { + msg_err_task ("bad from header: '%T'", h->value); + } + debug_task ("read rcpt header, value: %V", hv); } - } - break; - case 'l': - case 'L': - IF_HEADER (NO_LOG_HEADER) { - srch.begin = "no"; - srch.len = 2; - - if (rspamd_ftok_casecmp (hv_tok, &srch) == 0) { - task->flags |= RSPAMD_TASK_FLAG_NO_LOG; + else { + debug_task ("wrong header: %V", hn); } - } - break; - case 'm': - case 'M': - IF_HEADER (MLEN_HEADER) { - if (!rspamd_strtoul (hv_tok->begin, - hv_tok->len, - &task->message_len)) { - msg_err_task ("Invalid message length header: %V", hv); + break; + case 'i': + case 'I': + IF_HEADER (IP_ADDR_HEADER) { + if (!rspamd_parse_inet_address (&task->from_addr, hv->str, hv->len)) { + msg_err_task ("bad ip header: '%V'", hv); + return FALSE; + } + debug_task ("read IP header, value: %V", hv); + has_ip = TRUE; } else { - task->flags |= RSPAMD_TASK_FLAG_HAS_CONTROL; + debug_task ("wrong header: %V", hn); + } + break; + case 'p': + case 'P': + IF_HEADER (PASS_HEADER) { + srch.begin = "all"; + srch.len = 3; + + if (rspamd_ftok_casecmp (hv_tok, &srch) == 0) { + task->flags |= RSPAMD_TASK_FLAG_PASS_ALL; + debug_task ("pass all filters"); + } + } + break; + case 's': + case 'S': + IF_HEADER (SUBJECT_HEADER) { + task->subject = rspamd_mempool_ftokdup (task->task_pool, hv_tok); + } + IF_HEADER (SETTINGS_ID_HEADER) { + guint64 h; + guint32 *hp; + + h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_XXHASH64, + hv_tok->begin, hv_tok->len, 0xdeadbabe); + hp = rspamd_mempool_alloc (task->task_pool, sizeof (*hp)); + memcpy (hp, &h, sizeof (*hp)); + rspamd_mempool_set_variable (task->task_pool, "settings_hash", + hp, NULL); + } + break; + case 'u': + case 'U': + IF_HEADER (USER_HEADER) { + /* + * We must ignore User header in case of spamc, as SA has + * different meaning of this header + */ + if (!RSPAMD_TASK_IS_SPAMC (task)) { + task->user = rspamd_mempool_ftokdup (task->task_pool, + hv_tok); + } + } + IF_HEADER (URLS_HEADER) { + srch.begin = "extended"; + srch.len = 8; + + if (rspamd_ftok_casecmp (hv_tok, &srch) == 0) { + task->flags |= RSPAMD_TASK_FLAG_EXT_URLS; + debug_task ("extended urls information"); + } + } + break; + case 'l': + case 'L': + IF_HEADER (NO_LOG_HEADER) { + srch.begin = "no"; + srch.len = 2; + + if (rspamd_ftok_casecmp (hv_tok, &srch) == 0) { + task->flags |= RSPAMD_TASK_FLAG_NO_LOG; + } } + break; + case 'm': + case 'M': + IF_HEADER (MLEN_HEADER) { + if (!rspamd_strtoul (hv_tok->begin, + hv_tok->len, + &task->message_len)) { + msg_err_task ("Invalid message length header: %V", hv); + } + else { + task->flags |= RSPAMD_TASK_FLAG_HAS_CONTROL; + } + } + break; + default: + debug_task ("unknown header: %V", hn); + break; } - break; - default: - debug_task ("unknown header: %V", hn); - break; } } -- 2.39.5