]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Minor] Add method to get matching SPF record
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 11 Apr 2019 16:26:42 +0000 (17:26 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 11 Apr 2019 16:26:42 +0000 (17:26 +0100)
src/libserver/spf.c
src/libserver/spf.h

index ee2c06923ef8c39640e66983c5fb7ba8b7ce5a6e..2451f73dbc22420ee2ff549f40f99ab8716edbb7 100644 (file)
@@ -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
index 5df52d0e0adca9bf60c0e60e21c3e178a62d3bc2..722e98c032a12ec71fea8c1689771e8b951a2f60 100644 (file)
@@ -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