From 9564dbc14ddcc4a35d70cb7ee187a2f24752f6eb Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 17 Oct 2009 05:50:38 +0400 Subject: [PATCH] * Small improvement of lua style * Add ibility to process A records in spf parser * Add recursion limit to spf parser --- src/plugins/lua/forged_recipients.lua | 2 +- src/spf.c | 96 +++++++++++++++++++++++++++ src/spf.h | 3 +- 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/src/plugins/lua/forged_recipients.lua b/src/plugins/lua/forged_recipients.lua index 82f53dd73..d5fda34bb 100644 --- a/src/plugins/lua/forged_recipients.lua +++ b/src/plugins/lua/forged_recipients.lua @@ -26,7 +26,7 @@ function check_forged_headers(task) else -- Find pair for each smtp recipient recipient in To or Cc headers for _,sr in ipairs(smtp_rcpt) do - if string.byte(sr, 1) == string.byte('<') then + if sr:byte(1) == utf8.ltsym then -- Trim brackets sr = string.sub(sr, 2, -2) end 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 */ diff --git a/src/spf.h b/src/spf.h index 6c98f85ef..b31980958 100644 --- a/src/spf.h +++ b/src/spf.h @@ -34,7 +34,8 @@ struct spf_record { char **elts; char **cur_elt; - spf_action_t cur_action; + int nested; + int dns_requests; GList *addrs; char *cur_domain; -- 2.39.5