aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-12-22 14:30:08 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-12-22 14:30:08 +0000
commit0fb2347cce41a52c93405cf35257eafb3efb2565 (patch)
treeba7e83c917cdce10f3b04c44dbc86962766b99e9 /src
parentd3bc4025a1c62ce4f11ceb3a3d175da4d7493c85 (diff)
downloadrspamd-0fb2347cce41a52c93405cf35257eafb3efb2565.tar.gz
rspamd-0fb2347cce41a52c93405cf35257eafb3efb2565.zip
Fix issues with multiple addresses in SPF records
Issue: #455 Reported by: @moisseev
Diffstat (limited to 'src')
-rw-r--r--src/libserver/spf.c73
-rw-r--r--src/libserver/spf.h12
2 files changed, 62 insertions, 23 deletions
diff --git a/src/libserver/spf.c b/src/libserver/spf.c
index a421d7a07..e8394ec74 100644
--- a/src/libserver/spf.c
+++ b/src/libserver/spf.c
@@ -177,6 +177,8 @@ rspamd_spf_new_addr (struct spf_record *rec,
}
g_ptr_array_add (resolved->elts, naddr);
+ naddr->prev = naddr;
+ naddr->next = NULL;
return naddr;
}
@@ -184,11 +186,13 @@ rspamd_spf_new_addr (struct spf_record *rec,
static void
rspamd_spf_free_addr (gpointer a)
{
- struct spf_addr *addr = a;
+ struct spf_addr *addr = a, *tmp, *cur;
if (addr) {
g_free (addr->spf_string);
- g_slice_free1 (sizeof (*addr), addr);
+ DL_FOREACH_SAFE (addr, cur, tmp) {
+ g_slice_free1 (sizeof (*cur), cur);
+ }
}
}
@@ -250,7 +254,7 @@ rspamd_spf_process_reference (struct spf_resolved *target,
struct spf_addr *addr, struct spf_record *rec, gboolean top)
{
struct spf_resolved_element *elt, *relt;
- struct spf_addr *cur = NULL, taddr;
+ struct spf_addr *cur = NULL, taddr, *cur_addr;
guint i;
if (addr) {
@@ -314,10 +318,11 @@ rspamd_spf_process_reference (struct spf_resolved *target,
continue;
}
- memcpy (&taddr, cur, sizeof (taddr));
- /* Steal element */
- cur->spf_string = NULL;
- g_array_append_val (target->elts, taddr);
+ DL_FOREACH (cur, cur_addr) {
+ memcpy (&taddr, cur_addr, sizeof (taddr));
+ taddr.spf_string = g_strdup (cur_addr->spf_string);
+ g_array_append_val (target->elts, taddr);
+ }
}
}
}
@@ -420,20 +425,52 @@ spf_check_ptr_host (struct spf_dns_cb *cb, const char *name)
static void
spf_record_process_addr (struct spf_record *rec, struct spf_addr *addr, struct
- rdns_reply_entry
- *reply)
+ rdns_reply_entry *reply)
{
- if (reply->type == RDNS_REQUEST_AAAA) {
- memcpy (addr->addr6, &reply->content.aaa.addr, sizeof (addr->addr6));
- addr->flags |= RSPAMD_SPF_FLAG_IPV6;
- }
- else if (reply->type == RDNS_REQUEST_A) {
- memcpy (addr->addr4, &reply->content.a.addr, sizeof (addr->addr4));
- addr->flags |= RSPAMD_SPF_FLAG_IPV4;
+ struct spf_addr *naddr;
+
+ if (!addr->flags & RSPAMD_SPF_FLAG_PROCESSED) {
+ /* That's the first address */
+ if (reply->type == RDNS_REQUEST_AAAA) {
+ memcpy (addr->addr6,
+ &reply->content.aaa.addr,
+ sizeof (addr->addr6));
+ addr->flags |= RSPAMD_SPF_FLAG_IPV6;
+ }
+ else if (reply->type == RDNS_REQUEST_A) {
+ memcpy (addr->addr4, &reply->content.a.addr, sizeof (addr->addr4));
+ addr->flags |= RSPAMD_SPF_FLAG_IPV4;
+ }
+ else {
+ msg_err_spf (
+ "internal error, bad DNS reply is treated as address: %s",
+ rdns_strtype (reply->type));
+ }
}
else {
- msg_err_spf ("internal error, bad DNS reply is treated as address: %s",
- rdns_strtype (reply->type));
+ /* We need to create a new address */
+ naddr = g_slice_alloc0 (sizeof (*naddr));
+ memcpy (naddr, addr, sizeof (*naddr));
+ naddr->next = NULL;
+ naddr->prev = NULL;
+
+ if (reply->type == RDNS_REQUEST_AAAA) {
+ memcpy (naddr->addr6,
+ &reply->content.aaa.addr,
+ sizeof (addr->addr6));
+ naddr->flags |= RSPAMD_SPF_FLAG_IPV6;
+ }
+ else if (reply->type == RDNS_REQUEST_A) {
+ memcpy (naddr->addr4, &reply->content.a.addr, sizeof (addr->addr4));
+ naddr->flags |= RSPAMD_SPF_FLAG_IPV4;
+ }
+ else {
+ msg_err_spf (
+ "internal error, bad DNS reply is treated as address: %s",
+ rdns_strtype (reply->type));
+ }
+
+ DL_APPEND (addr, naddr);
}
}
diff --git a/src/libserver/spf.h b/src/libserver/spf.h
index 9aa439905..9e875b515 100644
--- a/src/libserver/spf.h
+++ b/src/libserver/spf.h
@@ -30,11 +30,12 @@ typedef enum spf_action_e {
#define RSPAMD_SPF_FLAG_IPV6 (1 << 0)
#define RSPAMD_SPF_FLAG_IPV4 (1 << 1)
-#define RSPAMD_SPF_FLAG_ANY (1 << 2)
-#define RSPAMD_SPF_FLAG_PARSED (1 << 3)
-#define RSPAMD_SPF_FLAG_VALID (1 << 4)
-#define RSPAMD_SPF_FLAG_REFRENCE (1 << 5)
-#define RSPAMD_SPF_FLAG_REDIRECT (1 << 6)
+#define RSPAMD_SPF_FLAG_PROCESSED (1 << 2)
+#define RSPAMD_SPF_FLAG_ANY (1 << 3)
+#define RSPAMD_SPF_FLAG_PARSED (1 << 4)
+#define RSPAMD_SPF_FLAG_VALID (1 << 5)
+#define RSPAMD_SPF_FLAG_REFRENCE (1 << 6)
+#define RSPAMD_SPF_FLAG_REDIRECT (1 << 7)
struct spf_addr {
guchar addr6[sizeof (struct in6_addr)];
@@ -49,6 +50,7 @@ struct spf_addr {
guint flags;
spf_mech_t mech;
gchar *spf_string;
+ struct spf_addr *prev, *next;
};
struct spf_resolved {