From 572462a0e27ae1880e1620b0f7427b3712e230df Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 25 Feb 2011 17:14:56 +0300 Subject: [PATCH] Fix parsing of DNS records :( Fix parsing several mx addrs in spf parser [1] Reported by: Victor Ustugov --- src/dns.c | 15 ++++++++------- src/dns.h | 2 +- src/spf.c | 30 ++++++++++++++++++++++++------ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/dns.c b/src/dns.c index e11d03582..d29ea5696 100644 --- a/src/dns.c +++ b/src/dns.c @@ -572,8 +572,8 @@ dns_fin_cb (gpointer arg) static guint8 * decompress_label (guint8 *begin, guint16 *len, guint16 max) { - guint16 offset; - offset = ntohs ((*len) ^ DNS_COMPRESSION_BITS); + guint16 offset = DNS_COMPRESSION_BITS; + offset = (*len) ^ (offset << 8); if (offset > max) { return NULL; @@ -610,7 +610,7 @@ dns_request_reply_cmp (struct rspamd_dns_request *req, guint8 *in, gint len) } /* This may be compressed, so we need to decompress it */ if (len1 & DNS_COMPRESSION_BITS) { - memcpy (&len1, p, sizeof (guint16)); + len1 = ((*p) << 8) + *(p + 1); l1 = decompress_label (in, &len1, len); if (l1 == NULL) { msg_info ("invalid DNS pointer"); @@ -625,7 +625,7 @@ dns_request_reply_cmp (struct rspamd_dns_request *req, guint8 *in, gint len) p += len1; } if (len2 & DNS_COMPRESSION_BITS) { - memcpy (&len2, p, sizeof (guint16)); + len2 = ((*p) << 8) + *(p + 1); l2 = decompress_label (req->packet, &len2, len); if (l2 == NULL) { msg_info ("invalid DNS pointer"); @@ -686,7 +686,7 @@ dns_parse_labels (guint8 *in, gchar **target, guint8 **pos, struct rspamd_dns_re } else if (llen & DNS_COMPRESSION_BITS) { ptrs ++; - memcpy (&llen, p, sizeof (guint16)); + llen = ((*p) << 8) + *(p + 1); l = decompress_label (in, &llen, end - in); if (l == NULL) { msg_info ("invalid DNS pointer"); @@ -728,7 +728,7 @@ dns_parse_labels (guint8 *in, gchar **target, guint8 **pos, struct rspamd_dns_re break; } else if (llen & DNS_COMPRESSION_BITS) { - memcpy (&llen, p, sizeof (guint16)); + llen = ((*p) << 8) + *(p + 1); l = decompress_label (in, &llen, end - in); begin = l; length = end - begin; @@ -747,7 +747,7 @@ dns_parse_labels (guint8 *in, gchar **target, guint8 **pos, struct rspamd_dns_re *(t - 1) = '\0'; end: if (offset < 0) { - offset = p - begin; + offset = p - begin + 1; } *remain -= offset; *pos += offset; @@ -815,6 +815,7 @@ dns_parse_rr (guint8 *in, union rspamd_reply_element *elt, guint8 **pos, struct } else { GET16 (elt->mx.priority); + datalen -= sizeof (guint16); if (! dns_parse_labels (in, &elt->mx.name, &p, rep, remain, TRUE)) { msg_info ("invalid labels in MX record"); return -1; diff --git a/src/dns.h b/src/dns.h index 57877748b..9896a6fa4 100644 --- a/src/dns.h +++ b/src/dns.h @@ -11,7 +11,7 @@ #define DNS_D_MAXLABEL 63 /* + 1 '\0' */ #define DNS_D_MAXNAME 255 /* + 1 '\0' */ -#define MAX_ADDRS 4 +#define MAX_ADDRS 1 struct rspamd_dns_reply; struct config_file; diff --git a/src/spf.c b/src/spf.c index 8e60604ac..212bd0074 100644 --- a/src/spf.c +++ b/src/spf.c @@ -265,11 +265,13 @@ parse_spf_hostmask (struct worker_task *task, const gchar *begin, struct spf_add static void spf_record_dns_callback (struct rspamd_dns_reply *reply, gpointer arg) { - struct spf_dns_cb *cb = arg; + struct spf_dns_cb *cb = arg; gchar *begin; - union rspamd_reply_element *elt_data; - GList *tmp = NULL, *tmp1, *elt, *last; - struct worker_task *task; + union rspamd_reply_element *elt_data; + GList *tmp = NULL, *tmp1, + *elt, *last; + struct worker_task *task; + struct spf_addr *new_addr; task = cb->rec->task; @@ -288,8 +290,23 @@ spf_record_dns_callback (struct rspamd_dns_reply *reply, gpointer arg) } } else if (reply->type == DNS_REQUEST_A) { - /* XXX: process only one record */ - cb->addr->addr = ntohl (elt_data->a.addr[0].s_addr); + if (cb->addr->addr == 0) { + cb->addr->addr = ntohl (elt_data->a.addr[0].s_addr); + } + else { + /* Insert one more address */ + tmp = g_list_find (cb->rec->addrs, cb->addr); + if (tmp) { + new_addr = memory_pool_alloc (task->task_pool, sizeof (struct spf_addr)); + memcpy (new_addr, cb->addr, sizeof (struct spf_addr)); + new_addr->addr = ntohl (elt_data->a.addr[0].s_addr); + cb->rec->addrs = g_list_insert_before (cb->rec->addrs, tmp, new_addr); + } + else { + msg_info ("wrong address list"); + } + } + } break; case SPF_RESOLVE_A: @@ -496,6 +513,7 @@ parse_spf_mx (struct worker_task *task, const gchar *begin, struct spf_record *r cb = memory_pool_alloc (task->task_pool, sizeof (struct spf_dns_cb)); cb->rec = rec; cb->addr = addr; + addr->addr = 0; cb->cur_action = SPF_RESOLVE_MX; cb->in_include = rec->in_include; if (make_dns_request (task->resolver, task->s, task->task_pool, spf_record_dns_callback, (void *)cb, DNS_REQUEST_MX, host)) { -- 2.39.5