aboutsummaryrefslogtreecommitdiffstats
path: root/src/libserver/spf.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2019-04-11 17:26:42 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2019-04-11 17:26:42 +0100
commit2219a8e09fba415759e06279ebe4f044c42ae4ba (patch)
tree28840edb8511364ba26705619b57b03e623f56bd /src/libserver/spf.c
parent09704cf02c243c4a2b90899222f033d91d4df88f (diff)
downloadrspamd-2219a8e09fba415759e06279ebe4f044c42ae4ba.tar.gz
rspamd-2219a8e09fba415759e06279ebe4f044c42ae4ba.zip
[Minor] Add method to get matching SPF record
Diffstat (limited to 'src/libserver/spf.c')
-rw-r--r--src/libserver/spf.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/libserver/spf.c b/src/libserver/spf.c
index ee2c06923..2451f73db 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