summaryrefslogtreecommitdiffstats
path: root/src/spf.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2009-10-17 05:50:38 +0400
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2009-10-17 05:50:38 +0400
commit9564dbc14ddcc4a35d70cb7ee187a2f24752f6eb (patch)
tree4612565e04ac279edcfbb192c7f1167c3c521256 /src/spf.c
parent115313228194cacf60a3e09c9b8117078ab37350 (diff)
downloadrspamd-9564dbc14ddcc4a35d70cb7ee187a2f24752f6eb.tar.gz
rspamd-9564dbc14ddcc4a35d70cb7ee187a2f24752f6eb.zip
* Small improvement of lua style
* Add ibility to process A records in spf parser * Add recursion limit to spf parser
Diffstat (limited to 'src/spf.c')
-rw-r--r--src/spf.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/spf.c b/src/spf.c
index 695eaaea4..c72698bc1 100644
--- a/src/spf.c
+++ b/src/spf.c
@@ -69,8 +69,18 @@
struct spf_dns_cb {
struct spf_record *rec;
struct spf_addr *addr;
+ spf_action_t cur_action;
};
+#define CHECK_REC(rec) \
+do { \
+ if ((rec)->nested > SPF_MAX_NESTING || \
+ (rec)->dns_requests > SPF_MAX_DNS_REQUESTS) { \
+ return FALSE; \
+ } \
+} while (0) \
+
+
/* Determine spf mech */
static spf_mech_t
check_spf_mech (const char *elt, gboolean *need_shift)
@@ -174,10 +184,86 @@ parse_spf_ipmask (const char *begin, struct spf_addr *addr)
}
+static void
+spf_record_dns_callback (int result, char type, int count, int ttl, void *addresses, void *data)
+{
+ struct spf_dns_cb *cb = data;
+ char *begin;
+
+ if (result == DNS_ERR_NONE) {
+ if (addresses != NULL) {
+ /* Add all logic for all DNS states here */
+ switch (cb->cur_action) {
+ case SPF_RESOLVE_MX:
+ break;
+ case SPF_RESOLVE_A:
+ if (type == DNS_IPv4_A) {
+ /* XXX: process only one record */
+ cb->addr->addr = *((uint32_t *)addresses);
+ }
+ break;
+ case SPF_RESOLVE_PTR:
+ break;
+ case SPF_RESOLVE_REDIRECT:
+ break;
+ case SPF_RESOLVE_INCLUDE:
+ break;
+ case SPF_RESOLVE_EXP:
+ break;
+ }
+ }
+ }
+
+ cb->rec->task->save.saved--;
+ if (cb->rec->task->save.saved == 0 && cb->rec->callback) {
+ cb->rec->callback (cb->rec, cb->rec->task);
+ }
+ remove_forced_event (cb->rec->task->s, (event_finalizer_t) spf_record_dns_callback);
+
+}
+
static gboolean
parse_spf_a (struct worker_task *task, const char *begin, struct spf_record *rec, struct spf_addr *addr)
{
struct spf_dns_cb *cb;
+ char *host, *p, mask_buf[3];
+ int hostlen;
+
+ CHECK_REC (rec);
+
+ bzero (mask_buf, sizeof (mask_buf));
+ p = strchr (begin, '/');
+ if (p != NULL) {
+ /* Extract mask */
+ g_strlcpy (mask_buf, p + 1, sizeof (mask_buf));
+ addr->mask = mask_buf[0] * 10 + mask_buf[1];
+ if (addr->mask > 32) {
+ return FALSE;
+ }
+ hostlen = p - begin;
+ host = memory_pool_alloc (task->task_pool, hostlen);
+ g_strlcpy (host, begin, hostlen);
+ }
+ else {
+ addr->mask = 32;
+ g_strlcpy (host, begin, strlen (begin));
+ }
+
+ rec->dns_requests ++;
+ cb = memory_pool_alloc (task->task_pool, sizeof (struct spf_dns_cb));
+ cb->rec = rec;
+ cb->addr = addr;
+ cb->cur_action = SPF_RESOLVE_A;
+
+ if (evdns_resolve_ipv4 (host, DNS_QUERY_NO_SEARCH, spf_record_dns_callback, (void *)cb) == 0) {
+ task->save.saved++;
+ register_async_event (task->s, (event_finalizer_t) spf_record_dns_callback, NULL, TRUE);
+
+ return TRUE;
+ }
+
+ return FALSE;
+
}
static gboolean
@@ -185,6 +271,8 @@ parse_spf_ptr (struct worker_task *task, const char *begin, struct spf_record *r
{
struct spf_dns_cb *cb;
+ CHECK_REC (rec);
+
}
static gboolean
@@ -192,6 +280,8 @@ parse_spf_mx (struct worker_task *task, const char *begin, struct spf_record *re
{
struct spf_dns_cb *cb;
+ CHECK_REC (rec);
+
}
static gboolean
@@ -207,6 +297,7 @@ parse_spf_ip4 (struct worker_task *task, const char *begin, struct spf_record *r
{
/* ip4:addr[/mask] */
+ CHECK_REC (rec);
return parse_spf_ipmask (begin, addr);
}
@@ -215,6 +306,8 @@ parse_spf_include (struct worker_task *task, const char *begin, struct spf_recor
{
struct spf_dns_cb *cb;
+ CHECK_REC (rec);
+
}
static gboolean
@@ -222,6 +315,7 @@ parse_spf_exp (struct worker_task *task, const char *begin, struct spf_record *r
{
struct spf_dns_cb *cb;
+ CHECK_REC (rec);
}
static gboolean
@@ -229,6 +323,7 @@ parse_spf_redirect (struct worker_task *task, const char *begin, struct spf_reco
{
struct spf_dns_cb *cb;
+ CHECK_REC (rec);
}
static gboolean
@@ -236,6 +331,7 @@ parse_spf_exists (struct worker_task *task, const char *begin, struct spf_record
{
struct spf_dns_cb *cb;
+ CHECK_REC (rec);
}
/* Read current element and try to parse record */