]> source.dussan.org Git - rspamd.git/commitdiff
Fix spf parser for some cases.
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Mon, 14 Feb 2011 14:56:13 +0000 (17:56 +0300)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Mon, 14 Feb 2011 14:56:13 +0000 (17:56 +0300)
src/plugins/spf.c
src/spf.c

index f6077d2c253b091f944028e02b338b2ed1a034c0..f7b0caab36b50b89f5b879bc160d26df83b86f88 100644 (file)
@@ -136,7 +136,7 @@ spf_plugin_callback (struct spf_record *record, struct worker_task *task)
        guint32                         s, m;
 
        if (record) {
-               cur = g_list_first (record->addrs);
+               cur = g_list_last (record->addrs);
                s = ntohl (task->from_addr.s_addr);
                while (cur) {
                        addr = cur->data;
@@ -147,6 +147,14 @@ spf_plugin_callback (struct spf_record *record, struct worker_task *task)
                 else {
                     m = G_MAXUINT32 << (32 - addr->mask);
                 }
+                if (addr->addr == 0 && cur->prev != NULL) {
+                       /*
+                        * In fact default record should be the last element in a record
+                        * so ignore such other records
+                        */
+                       cur = g_list_previous (cur);
+                       continue;
+                }
                 if ((s & m) == (addr->addr & m)) {
                     switch (addr->mech) {
                         case SPF_FAIL:
@@ -167,7 +175,7 @@ spf_plugin_callback (struct spf_record *record, struct worker_task *task)
                     break;
                 }
             }
-                       cur = g_list_next (cur);
+                       cur = g_list_previous (cur);
                }
                if (record->addrs != NULL) {
                        /* Free addresses that we already proceed */
index 0f89e75134162605c922159e98c937dbc7795a17..63a3fed99b801738a5eca03e02ade0579c78b677 100644 (file)
--- a/src/spf.c
+++ b/src/spf.c
@@ -69,6 +69,8 @@
  *
  */
 
+#undef SPF_DEBUG
+
 struct spf_dns_cb {
        struct spf_record *rec;
        struct spf_addr *addr;
@@ -110,13 +112,46 @@ check_spf_mech (const gchar *elt, gboolean *need_shift)
        }
 }
 
+/* Debugging function that dumps spf record in log */
+static void
+dump_spf_record (GList *addrs)
+{
+       struct spf_addr                *addr;
+       GList                          *cur;
+       gint                            r = 0;
+       gchar                           logbuf[BUFSIZ], c;
+       struct in_addr                  ina;
+
+       cur = addrs;
+
+       while (cur) {
+               addr = cur->data;
+               switch (addr->mech) {
+               case SPF_FAIL:
+                       c = '-';
+                       break;
+               case SPF_SOFT_FAIL:
+               case SPF_NEUTRAL:
+                       c = '~';
+                       break;
+               case SPF_PASS:
+                       c = '+';
+                       break;
+               }
+               ina.s_addr = htonl (addr->addr);
+               r += snprintf (logbuf + r, sizeof (logbuf) - r, "%c%s/%d; ", c, inet_ntoa (ina), addr->mask);
+               cur = g_list_next (cur);
+       }
+       msg_info ("spf record: %s", logbuf);
+}
+
 static gboolean
 parse_spf_ipmask (const gchar *begin, struct spf_addr *addr)
 {
-       const gchar *pos;
+       const gchar                    *pos;
        gchar                           ip_buf[sizeof ("255.255.255.255")], mask_buf[3], *p;
        gint                            state = 0, dots = 0;
-       struct in_addr in;
+       struct in_addr                  in;
        
        bzero (ip_buf, sizeof (ip_buf));
        bzero (mask_buf, sizeof (mask_buf));
@@ -280,6 +315,10 @@ spf_record_dns_callback (struct rspamd_dns_reply *reply, gpointer arg)
                                case SPF_RESOLVE_INCLUDE:
                                        if (reply->type == DNS_REQUEST_TXT) {
                                                begin = elt_data->txt.data;
+#ifdef SPF_DEBUG
+                                               msg_info ("before include");
+                                               dump_spf_record (cb->rec->addrs);
+#endif
                                                if (cb->rec->addrs) {
                                                        tmp = cb->rec->addrs;
                                                        cb->rec->addrs = NULL;
@@ -325,6 +364,10 @@ spf_record_dns_callback (struct rspamd_dns_reply *reply, gpointer arg)
 
                                                                        cb->rec->addrs = tmp;
                                                                        g_list_free1 (tmp1);
+#ifdef SPF_DEBUG
+                                                                       msg_info ("after include");
+                                                                       dump_spf_record (cb->rec->addrs);
+#endif
                                                                }
                                                        }
                                                }
@@ -961,6 +1004,14 @@ parse_spf_record (struct worker_task *task, struct spf_record *rec)
                                        msg_info ("bad spf command: %s", begin);
                                }
                                break;
+                       case 'v':
+                               if (g_ascii_strncasecmp (begin, "v=spf", sizeof ("v=spf") - 1) == 0) {
+                                       /* Skip this element till the end of record */
+                                       while (*begin && !g_ascii_isspace (*begin)) {
+                                               begin ++;
+                                       }
+                               }
+                               break;
                        default:
                                msg_info ("bad spf command: %s", begin);
                                break;
@@ -1018,9 +1069,6 @@ start_spf_parse (struct spf_record *rec, gchar *begin)
                        memory_pool_add_destructor (rec->task->task_pool, (pool_destruct_func)g_strfreev, rec->elts);
                        rec->cur_elt = rec->elts[0];
                        while (parse_spf_record (rec->task, rec));
-                       if (rec->addrs) {
-                               rec->addrs = g_list_reverse (rec->addrs);
-                       }
                }
        }
        else if (g_ascii_strncasecmp (begin, SPF_VER2_STR, sizeof (SPF_VER2_STR) - 1) == 0) {
@@ -1043,9 +1091,6 @@ start_spf_parse (struct spf_record *rec, gchar *begin)
                        memory_pool_add_destructor (rec->task->task_pool, (pool_destruct_func)g_strfreev, rec->elts);
                        rec->cur_elt = rec->elts[0];
                        while (parse_spf_record (rec->task, rec));
-                       if (rec->addrs) {
-                               rec->addrs = g_list_reverse (rec->addrs);
-                       }
                }
        }
        else {