diff options
author | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2011-03-03 17:08:37 +0300 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rambler-co.ru> | 2011-03-03 17:08:37 +0300 |
commit | 2a2bc886c1b43a9c43a812959d7193cc03d7bc8d (patch) | |
tree | 99c0a23984497e9637a22e446d33b66c632788f1 /src/plugins/spf.c | |
parent | 0f2f88a6157250fecb9ce5d8d28b02b99739a2d2 (diff) | |
download | rspamd-2a2bc886c1b43a9c43a812959d7193cc03d7bc8d.tar.gz rspamd-2a2bc886c1b43a9c43a812959d7193cc03d7bc8d.zip |
* Fix parsing of include records in spf parser
Diffstat (limited to 'src/plugins/spf.c')
-rw-r--r-- | src/plugins/spf.c | 110 |
1 files changed, 65 insertions, 45 deletions
diff --git a/src/plugins/spf.c b/src/plugins/spf.c index 7b7dac605..f5cbbe7b3 100644 --- a/src/plugins/spf.c +++ b/src/plugins/spf.c @@ -128,55 +128,75 @@ spf_module_reconfig (struct config_file *cfg) return spf_module_config (cfg); } -static void -spf_plugin_callback (struct spf_record *record, struct worker_task *task) +static gboolean +spf_check_element (struct spf_addr *addr, struct worker_task *task) { - GList *cur; - struct spf_addr *addr; guint32 s, m; - if (record) { - cur = g_list_last (record->addrs); - s = ntohl (task->from_addr.s_addr); - while (cur) { - addr = cur->data; - if (addr != NULL) { - if (addr->mask == 0) { - m = 0; - } - 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: - insert_result (task, spf_module_ctx->symbol_fail, 1, g_list_prepend (NULL, addr->spf_string)); - task->messages = g_list_prepend (task->messages, "(SPF): spf fail"); - break; - case SPF_SOFT_FAIL: - case SPF_NEUTRAL: - insert_result (task, spf_module_ctx->symbol_softfail, 1, g_list_prepend (NULL, addr->spf_string)); - task->messages = g_list_prepend (task->messages, "(SPF): spf softfail"); - break; - default: - insert_result (task, spf_module_ctx->symbol_allow, 1, g_list_prepend (NULL, addr->spf_string)); - task->messages = g_list_prepend (task->messages, "(SPF): spf allow"); - break; - } - /* Stop parsing */ - break; - } - } - cur = g_list_previous (cur); + if (addr->data.normal.mask == 0) { + m = 0; + } + else { + m = G_MAXUINT32 << (32 - addr->data.normal.mask); + } + s = ntohl (task->from_addr.s_addr); + + if ((s & m) == (addr->data.normal.addr & m)) { + switch (addr->mech) { + case SPF_FAIL: + insert_result (task, spf_module_ctx->symbol_fail, 1, g_list_prepend (NULL, addr->spf_string)); + task->messages = g_list_prepend (task->messages, "(SPF): spf fail"); + break; + case SPF_SOFT_FAIL: + case SPF_NEUTRAL: + insert_result (task, spf_module_ctx->symbol_softfail, 1, g_list_prepend (NULL, addr->spf_string)); + task->messages = g_list_prepend (task->messages, "(SPF): spf softfail"); + break; + default: + insert_result (task, spf_module_ctx->symbol_allow, 1, g_list_prepend (NULL, addr->spf_string)); + task->messages = g_list_prepend (task->messages, "(SPF): spf allow"); + break; + } + return TRUE; + } + + return FALSE; +} + +static gboolean +spf_check_list (GList *list, struct worker_task *task) +{ + GList *cur; + struct spf_addr *addr; + + cur = list; + + while (cur) { + addr = cur->data; + if (addr->is_list) { + /* Recursive call */ + addr->data.list = g_list_reverse (addr->data.list); + if (spf_check_list (addr->data.list, task)) { + return TRUE; + } + } + else { + if (spf_check_element (addr, task)) { + return TRUE; + } } + cur = g_list_next (cur); + } + + return FALSE; +} + +static void +spf_plugin_callback (struct spf_record *record, struct worker_task *task) +{ + if (record) { + record->addrs = g_list_reverse (record->addrs); + spf_check_list (record->addrs, task); } if (task->save.saved == 0) { |