From 8afaa80ad5eb23d2b9feb575f9ef4d7bef7b1e85 Mon Sep 17 00:00:00 2001 From: Andrew Lewis Date: Tue, 27 Sep 2016 14:19:21 +0200 Subject: [PATCH] [Minor] Really fix SPF PERMFAIL/DNSFAIL behaviour on failed redirect --- src/libserver/spf.c | 49 +++++++++++++++++++++++++++++++++++---------- src/libserver/spf.h | 2 +- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/libserver/spf.c b/src/libserver/spf.c index 41f31bfb0..362c96255 100644 --- a/src/libserver/spf.c +++ b/src/libserver/spf.c @@ -314,10 +314,9 @@ rspamd_spf_process_reference (struct spf_resolved *target, if (!(cur->flags & RSPAMD_SPF_FLAG_PARSED)) { /* Unresolved redirect */ msg_info_spf ("redirect to %s cannot be resolved", cur->spf_string); - cur->flags |= RSPAMD_SPF_FLAG_TEMPFAIL; } else { - g_assert (cur->flags & RSPAMD_SPF_FLAG_REFRENCE); + g_assert (cur->flags & RSPAMD_SPF_FLAG_REFERENCE); g_assert (cur->m.idx < rec->resolved->len); relt = g_ptr_array_index (rec->resolved, cur->m.idx); msg_debug_spf ("domain %s is redirected to %s", elt->cur_domain, @@ -344,7 +343,7 @@ rspamd_spf_process_reference (struct spf_resolved *target, /* Ignore unparsed addrs */ continue; } - if (cur->flags & RSPAMD_SPF_FLAG_REFRENCE) { + if (cur->flags & RSPAMD_SPF_FLAG_REFERENCE) { /* Process reference */ if (cur->flags & RSPAMD_SPF_FLAG_REDIRECT) { /* Stop on redirected domain */ @@ -665,11 +664,18 @@ spf_record_dns_callback (struct rdns_reply *reply, gpointer arg) break; case SPF_RESOLVE_REDIRECT: if (elt_data->type == RDNS_REQUEST_TXT) { - if (spf_process_txt_record (rec, cb->resolved, reply)) { - cb->addr->flags |= RSPAMD_SPF_FLAG_PARSED; + if (reply->code == RDNS_RC_NOERROR || reply->code == RDNS_RC_NXDOMAIN || reply->code == RDNS_RC_NOREC) { + if (spf_process_txt_record (rec, cb->resolved, reply)) { + cb->addr->flags |= RSPAMD_SPF_FLAG_PARSED; + } + else { + cb->addr->flags &= ~RSPAMD_SPF_FLAG_PARSED; + cb->addr->flags |= RSPAMD_SPF_FLAG_PERMFAIL; + } } else { cb->addr->flags &= ~RSPAMD_SPF_FLAG_PARSED; + cb->addr->flags |= RSPAMD_SPF_FLAG_TEMPFAIL; } } @@ -759,7 +765,13 @@ spf_record_dns_callback (struct rdns_reply *reply, gpointer arg) else if ((cb->cur_action == SPF_RESOLVE_INCLUDE || cb->cur_action == SPF_RESOLVE_REDIRECT) || reply->code == RDNS_RC_TIMEOUT) { - cb->addr->flags |= RSPAMD_SPF_FLAG_TEMPFAIL; + if ((cb->cur_action == SPF_RESOLVE_INCLUDE || cb->cur_action == SPF_RESOLVE_REDIRECT) && + (reply->code == RDNS_RC_NOREC && reply->code == RDNS_RC_NXDOMAIN)) { + cb->addr->flags |= RSPAMD_SPF_FLAG_PERMFAIL; + } + else { + cb->addr->flags |= RSPAMD_SPF_FLAG_TEMPFAIL; + } msg_info_spf ( "<%s>: spf error for domain %s: cannot resolve %s DNS record for" " %s: %s", @@ -1166,7 +1178,7 @@ parse_spf_include (struct spf_record *rec, struct spf_addr *addr) cb->resolved = rspamd_spf_new_addr_list (rec, domain); cb->ptr_host = domain; /* Set reference */ - addr->flags |= RSPAMD_SPF_FLAG_REFRENCE; + addr->flags |= RSPAMD_SPF_FLAG_REFERENCE; msg_debug_spf ("resolve include %s", domain); if (make_dns_request_task_forced (task, @@ -1210,7 +1222,7 @@ parse_spf_redirect (struct spf_record *rec, cb = rspamd_mempool_alloc (task->task_pool, sizeof (struct spf_dns_cb)); /* Set reference */ - addr->flags |= RSPAMD_SPF_FLAG_REFRENCE | RSPAMD_SPF_FLAG_REDIRECT; + addr->flags |= RSPAMD_SPF_FLAG_REFERENCE | RSPAMD_SPF_FLAG_REDIRECT; addr->m.idx = rec->resolved->len; cb->rec = rec; @@ -1818,11 +1830,26 @@ spf_dns_callback (struct rdns_reply *reply, gpointer arg) if (resolved) { if (!spf_process_txt_record (rec, resolved, reply)) { - if (rec->dns_requests == 0) { - resolved = g_ptr_array_index(rec->resolved, 0); + resolved = g_ptr_array_index(rec->resolved, 0); + if (rec->resolved->len > 1) { + addr = g_ptr_array_index(resolved->elts, 0); + if ((reply->code == RDNS_RC_NOREC || reply->code == RDNS_RC_NXDOMAIN) + && addr->flags & RSPAMD_SPF_FLAG_REDIRECT) { + addr->flags |= RSPAMD_SPF_FLAG_PERMFAIL; + } else { + addr->flags |= RSPAMD_SPF_FLAG_TEMPFAIL; + } + } + else { addr = g_slice_alloc0 (sizeof(*addr)); addr->flags = 0; - addr->flags |= RSPAMD_SPF_FLAG_NA; + if (reply->code == RDNS_RC_NOREC || reply->code == RDNS_RC_NXDOMAIN + || reply->code == RDNS_RC_NOERROR) { + addr->flags |= RSPAMD_SPF_FLAG_NA; + } + else { + addr->flags |= RSPAMD_SPF_FLAG_TEMPFAIL; + } g_ptr_array_insert (resolved->elts, 0, addr); } } diff --git a/src/libserver/spf.h b/src/libserver/spf.h index ab2d0bc53..271056d87 100644 --- a/src/libserver/spf.h +++ b/src/libserver/spf.h @@ -35,7 +35,7 @@ typedef enum spf_action_e { #define RSPAMD_SPF_FLAG_ANY (1 << 3) #define RSPAMD_SPF_FLAG_PARSED (1 << 4) #define RSPAMD_SPF_FLAG_VALID (1 << 5) -#define RSPAMD_SPF_FLAG_REFRENCE (1 << 6) +#define RSPAMD_SPF_FLAG_REFERENCE (1 << 6) #define RSPAMD_SPF_FLAG_REDIRECT (1 << 7) #define RSPAMD_SPF_FLAG_TEMPFAIL (1 << 8) #define RSPAMD_SPF_FLAG_NA (1 << 9) -- 2.39.5