|
|
@@ -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; |
|
|
|
} |
|
|
|
} |
|
|
|
|