Bläddra i källkod

[Fix] Make spf digest stable

tags/1.9.2
Vsevolod Stakhov 5 år sedan
förälder
incheckning
fe1c8f88b7
1 ändrade filer med 76 tillägg och 34 borttagningar
  1. 76
    34
      src/libserver/spf.c

+ 76
- 34
src/libserver/spf.c Visa fil

@@ -371,34 +371,6 @@ rspamd_spf_process_reference (struct spf_resolved *target,
DL_FOREACH (cur, cur_addr) {
memcpy (&taddr, cur_addr, sizeof (taddr));
taddr.spf_string = g_strdup (cur_addr->spf_string);

if (cur_addr->flags & RSPAMD_SPF_FLAG_IPV6) {
guint64 t[3];

memcpy (t, cur_addr->addr6, sizeof (guint64) * 2);
t[2] = ((guint64)(cur_addr->mech)) << 48;
t[2] |= cur_addr->m.dual.mask_v6;

for (guint j = 0; j < G_N_ELEMENTS (t); j ++) {
target->digest = mum_hash_step (target->digest, t[j]);
}
}
else if (cur_addr->flags & RSPAMD_SPF_FLAG_IPV4) {
guint64 t;

memcpy (&t, cur_addr->addr4, sizeof (guint32));
t |= ((guint64)(cur_addr->mech)) << 48;
t |= ((guint64)cur_addr->m.dual.mask_v4) << 32;

target->digest = mum_hash_step (target->digest, t);
}
else {
guint64 t = 0;

t |= ((guint64)(cur_addr->mech)) << 48;
target->digest = mum_hash_step (target->digest, t);
}

g_array_append_val (target->elts, taddr);
}
}
@@ -427,8 +399,6 @@ rspamd_spf_record_flatten (struct spf_record *rec)
if (rec->resolved->len > 0) {
rspamd_spf_process_reference (res, NULL, rec, TRUE);
}

res->digest = mum_hash_finish (res->digest);
}
else {
res = g_malloc0 (sizeof (*res));
@@ -442,6 +412,77 @@ rspamd_spf_record_flatten (struct spf_record *rec)
return res;
}

static gint
rspamd_spf_elts_cmp (gconstpointer a, gconstpointer b)
{
struct spf_addr *addr_a, *addr_b;

addr_a = (struct spf_addr *)a;
addr_b = (struct spf_addr *)b;

if (addr_a->flags == addr_b->flags) {
if (addr_a->flags & RSPAMD_SPF_FLAG_ANY) {
return 0;
}
else if (addr_a->flags & RSPAMD_SPF_FLAG_IPV4) {
return (addr_a->m.dual.mask_v4 - addr_b->m.dual.mask_v4) ||
memcmp (addr_a->addr4, addr_b->addr4, sizeof (addr_a->addr4));
}
else if (addr_a->flags & RSPAMD_SPF_FLAG_IPV6) {
return (addr_a->m.dual.mask_v6 - addr_b->m.dual.mask_v6) ||
memcmp (addr_a->addr6, addr_b->addr6, sizeof (addr_a->addr6));
}
else {
return 0;
}
}
else {
if (addr_a->flags & RSPAMD_SPF_FLAG_ANY) {
return 1;
}
else if (addr_b->flags & RSPAMD_SPF_FLAG_ANY) {
return -1;
}
else if (addr_a->flags & RSPAMD_SPF_FLAG_IPV4) {
return -1;
}

return 1;
}
}

static void
rspamd_spf_record_postprocess (struct spf_resolved *rec)
{
g_array_sort (rec->elts, rspamd_spf_elts_cmp);

for (guint i = 0; i < rec->elts->len; i ++) {
struct spf_addr *cur_addr = &g_array_index (rec->elts, struct spf_addr, i);

if (cur_addr->flags & RSPAMD_SPF_FLAG_IPV6) {
guint64 t[3];

memcpy (t, cur_addr->addr6, sizeof (guint64) * 2);
t[2] = 0;
t[2] = ((guint64) (cur_addr->mech)) << 48u;
t[2] |= cur_addr->m.dual.mask_v6;

for (guint j = 0; j < G_N_ELEMENTS (t); j++) {
rec->digest = mum_hash_step (rec->digest, t[j]);
}
}
else if (cur_addr->flags & RSPAMD_SPF_FLAG_IPV4) {
guint64 t = 0;

memcpy (&t, cur_addr->addr4, sizeof (guint32));
t |= ((guint64) (cur_addr->mech)) << 48u;
t |= ((guint64) cur_addr->m.dual.mask_v4) << 32u;

rec->digest = mum_hash_step (rec->digest, t);
}
}
}

static void
rspamd_spf_maybe_return (struct spf_record *rec)
{
@@ -449,6 +490,7 @@ rspamd_spf_maybe_return (struct spf_record *rec)

if (rec->requests_inflight == 0 && !rec->done) {
flat = rspamd_spf_record_flatten (rec);
rspamd_spf_record_postprocess (flat);
rec->callback (flat, rec->task, rec->cbdata);
REF_RELEASE (flat);
rec->done = TRUE;
@@ -688,6 +730,7 @@ spf_record_dns_callback (struct rdns_reply *reply, gpointer arg)
else {
cb->addr->flags |= RSPAMD_SPF_FLAG_RESOLVED;
cb->addr->flags &= ~RSPAMD_SPF_FLAG_PERMFAIL;
msg_debug_spf ("resolved MX addr");
spf_record_process_addr (rec, addr, elt_data);
}
break;
@@ -2107,7 +2150,6 @@ spf_dns_callback (struct rdns_reply *reply, gpointer arg)
&& rec->dns_requests == 0) {
resolved = rspamd_spf_new_addr_list (rec, rec->sender_domain);
addr = g_malloc0 (sizeof(*addr));
addr->flags = 0;
addr->flags |= RSPAMD_SPF_FLAG_NA;
g_ptr_array_insert (resolved->elts, 0, addr);
}
@@ -2115,7 +2157,6 @@ spf_dns_callback (struct rdns_reply *reply, gpointer arg)
&& rec->dns_requests == 0) {
resolved = rspamd_spf_new_addr_list (rec, rec->sender_domain);
addr = g_malloc0 (sizeof(*addr));
addr->flags = 0;
addr->flags |= RSPAMD_SPF_FLAG_TEMPFAIL;
g_ptr_array_insert (resolved->elts, 0, addr);
}
@@ -2135,7 +2176,7 @@ spf_dns_callback (struct rdns_reply *reply, gpointer arg)
}
else {
addr = g_malloc0 (sizeof(*addr));
addr->flags = 0;
if (reply->code == RDNS_RC_NOREC || reply->code == RDNS_RC_NXDOMAIN
|| reply->code == RDNS_RC_NOERROR) {
addr->flags |= RSPAMD_SPF_FLAG_NA;
@@ -2300,7 +2341,8 @@ spf_addr_mask_to_string (struct spf_addr *addr)
rspamd_printf_gstring (res, "%s/%d", ipstr, addr->m.dual.mask_v6);
}
else {
res = g_string_new ("unknown");
res = g_string_new (NULL);
rspamd_printf_gstring (res, "unknown, flags = %d", addr->flags);
}

s = res->str;

Laddar…
Avbryt
Spara