From: Vsevolod Stakhov Date: Thu, 11 Apr 2019 16:26:42 +0000 (+0100) Subject: [Minor] Add method to get matching SPF record X-Git-Tag: 1.9.2~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2219a8e09fba415759e06279ebe4f044c42ae4ba;p=thirdparty%2Frspamd.git [Minor] Add method to get matching SPF record --- diff --git a/src/libserver/spf.c b/src/libserver/spf.c index ee2c06923e..2451f73dbc 100644 --- a/src/libserver/spf.c +++ b/src/libserver/spf.c @@ -2308,4 +2308,74 @@ spf_addr_mask_to_string (struct spf_addr *addr) return s; +} + +struct spf_addr* +spf_addr_match_task (struct rspamd_task *task, struct spf_resolved *rec) +{ + const guint8 *s, *d; + guint af, mask, bmask, addrlen; + struct spf_addr *selected = NULL, *addr, *any_addr = NULL; + guint i; + + if (task->from_addr == NULL) { + return FALSE; + } + + for (i = 0; i < rec->elts->len; i ++) { + addr = &g_array_index (rec->elts, struct spf_addr, i); + if (addr->flags & RSPAMD_SPF_FLAG_TEMPFAIL) { + continue; + } + + af = rspamd_inet_address_get_af (task->from_addr); + /* Basic comparing algorithm */ + if (((addr->flags & RSPAMD_SPF_FLAG_IPV6) && af == AF_INET6) || + ((addr->flags & RSPAMD_SPF_FLAG_IPV4) && af == AF_INET)) { + d = rspamd_inet_address_get_hash_key (task->from_addr, &addrlen); + + if (af == AF_INET6) { + s = (const guint8 *) addr->addr6; + mask = addr->m.dual.mask_v6; + } + else { + s = (const guint8 *) addr->addr4; + mask = addr->m.dual.mask_v4; + } + + /* Compare the first bytes */ + bmask = mask / CHAR_BIT; + if (mask > addrlen * CHAR_BIT) { + msg_info_task ("bad mask length: %d", mask); + } + else if (memcmp (s, d, bmask) == 0) { + if (bmask * CHAR_BIT < mask) { + /* Compare the remaining bits */ + s += bmask; + d += bmask; + mask = (0xffu << (CHAR_BIT - (mask - bmask * 8u))) & 0xffu; + + if ((*s & mask) == (*d & mask)) { + selected = addr; + break; + } + } + else { + selected = addr; + break; + } + } + } + else { + if (addr->flags & RSPAMD_SPF_FLAG_ANY) { + any_addr = addr; + } + } + } + + if (selected) { + return selected; + } + + return any_addr; } \ No newline at end of file diff --git a/src/libserver/spf.h b/src/libserver/spf.h index 5df52d0e0a..722e98c032 100644 --- a/src/libserver/spf.h +++ b/src/libserver/spf.h @@ -98,4 +98,13 @@ void spf_record_unref (struct spf_resolved *rec); * @return */ gchar *spf_addr_mask_to_string (struct spf_addr *addr); + +/** + * Returns spf address that matches the specific task (or nil if not matched) + * @param task + * @param rec + * @return + */ +struct spf_addr * spf_addr_match_task (struct rspamd_task *task, + struct spf_resolved *rec); #endif