aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2011-02-25 17:14:56 +0300
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2011-02-25 17:14:56 +0300
commit572462a0e27ae1880e1620b0f7427b3712e230df (patch)
tree072e4f1e31cdc9502dcec164921c0b0585cde269 /src
parent6f122c26db02d065b16521c7498e8ad8f776f56e (diff)
downloadrspamd-572462a0e27ae1880e1620b0f7427b3712e230df.tar.gz
rspamd-572462a0e27ae1880e1620b0f7427b3712e230df.zip
Fix parsing of DNS records :(
Fix parsing several mx addrs in spf parser [1] Reported by: Victor Ustugov
Diffstat (limited to 'src')
-rw-r--r--src/dns.c15
-rw-r--r--src/dns.h2
-rw-r--r--src/spf.c30
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)) {