summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2011-02-14 17:56:13 +0300
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2011-02-14 17:56:13 +0300
commit4be4cd5d9da12c449a2154d7e70b5244e7bb1a48 (patch)
treea79ccbbaa8e9521b7d02e8e46de5b76c53b25582
parent3c2638e27f6a693318ec9d787885d20c28c41d36 (diff)
downloadrspamd-4be4cd5d9da12c449a2154d7e70b5244e7bb1a48.tar.gz
rspamd-4be4cd5d9da12c449a2154d7e70b5244e7bb1a48.zip
Fix spf parser for some cases.
-rw-r--r--src/plugins/spf.c12
-rw-r--r--src/spf.c61
2 files changed, 63 insertions, 10 deletions
diff --git a/src/plugins/spf.c b/src/plugins/spf.c
index f6077d2c2..f7b0caab3 100644
--- a/src/plugins/spf.c
+++ b/src/plugins/spf.c
@@ -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 */
diff --git a/src/spf.c b/src/spf.c
index 0f89e7513..63a3fed99 100644
--- 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 {