소스 검색

[Fix] Make spf digest stable

tags/1.9.2
Vsevolod Stakhov 5 년 전
부모
커밋
fe1c8f88b7
1개의 변경된 파일76개의 추가작업 그리고 34개의 파일을 삭제
  1. 76
    34
      src/libserver/spf.c

+ 76
- 34
src/libserver/spf.c 파일 보기

DL_FOREACH (cur, cur_addr) { DL_FOREACH (cur, cur_addr) {
memcpy (&taddr, cur_addr, sizeof (taddr)); memcpy (&taddr, cur_addr, sizeof (taddr));
taddr.spf_string = g_strdup (cur_addr->spf_string); 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); g_array_append_val (target->elts, taddr);
} }
} }
if (rec->resolved->len > 0) { if (rec->resolved->len > 0) {
rspamd_spf_process_reference (res, NULL, rec, TRUE); rspamd_spf_process_reference (res, NULL, rec, TRUE);
} }

res->digest = mum_hash_finish (res->digest);
} }
else { else {
res = g_malloc0 (sizeof (*res)); res = g_malloc0 (sizeof (*res));
return res; 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 static void
rspamd_spf_maybe_return (struct spf_record *rec) rspamd_spf_maybe_return (struct spf_record *rec)
{ {


if (rec->requests_inflight == 0 && !rec->done) { if (rec->requests_inflight == 0 && !rec->done) {
flat = rspamd_spf_record_flatten (rec); flat = rspamd_spf_record_flatten (rec);
rspamd_spf_record_postprocess (flat);
rec->callback (flat, rec->task, rec->cbdata); rec->callback (flat, rec->task, rec->cbdata);
REF_RELEASE (flat); REF_RELEASE (flat);
rec->done = TRUE; rec->done = TRUE;
else { else {
cb->addr->flags |= RSPAMD_SPF_FLAG_RESOLVED; cb->addr->flags |= RSPAMD_SPF_FLAG_RESOLVED;
cb->addr->flags &= ~RSPAMD_SPF_FLAG_PERMFAIL; cb->addr->flags &= ~RSPAMD_SPF_FLAG_PERMFAIL;
msg_debug_spf ("resolved MX addr");
spf_record_process_addr (rec, addr, elt_data); spf_record_process_addr (rec, addr, elt_data);
} }
break; break;
&& rec->dns_requests == 0) { && rec->dns_requests == 0) {
resolved = rspamd_spf_new_addr_list (rec, rec->sender_domain); resolved = rspamd_spf_new_addr_list (rec, rec->sender_domain);
addr = g_malloc0 (sizeof(*addr)); addr = g_malloc0 (sizeof(*addr));
addr->flags = 0;
addr->flags |= RSPAMD_SPF_FLAG_NA; addr->flags |= RSPAMD_SPF_FLAG_NA;
g_ptr_array_insert (resolved->elts, 0, addr); g_ptr_array_insert (resolved->elts, 0, addr);
} }
&& rec->dns_requests == 0) { && rec->dns_requests == 0) {
resolved = rspamd_spf_new_addr_list (rec, rec->sender_domain); resolved = rspamd_spf_new_addr_list (rec, rec->sender_domain);
addr = g_malloc0 (sizeof(*addr)); addr = g_malloc0 (sizeof(*addr));
addr->flags = 0;
addr->flags |= RSPAMD_SPF_FLAG_TEMPFAIL; addr->flags |= RSPAMD_SPF_FLAG_TEMPFAIL;
g_ptr_array_insert (resolved->elts, 0, addr); g_ptr_array_insert (resolved->elts, 0, addr);
} }
} }
else { else {
addr = g_malloc0 (sizeof(*addr)); addr = g_malloc0 (sizeof(*addr));
addr->flags = 0;
if (reply->code == RDNS_RC_NOREC || reply->code == RDNS_RC_NXDOMAIN if (reply->code == RDNS_RC_NOREC || reply->code == RDNS_RC_NXDOMAIN
|| reply->code == RDNS_RC_NOERROR) { || reply->code == RDNS_RC_NOERROR) {
addr->flags |= RSPAMD_SPF_FLAG_NA; addr->flags |= RSPAMD_SPF_FLAG_NA;
rspamd_printf_gstring (res, "%s/%d", ipstr, addr->m.dual.mask_v6); rspamd_printf_gstring (res, "%s/%d", ipstr, addr->m.dual.mask_v6);
} }
else { else {
res = g_string_new ("unknown");
res = g_string_new (NULL);
rspamd_printf_gstring (res, "unknown, flags = %d", addr->flags);
} }


s = res->str; s = res->str;

Loading…
취소
저장