From 654056e44fc93a0ee7c09d1228933e8af6862206 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 10 Oct 2023 12:45:27 +0100 Subject: [PATCH 2/3] SPF: harden against crafted DNS responses (cherry picked from commit 4f07f38374f8662c318699fb30432273ffcfe0d3) --- src/spf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/spf.c b/src/spf.c index db6eea3a8..1981d81b6 100644 --- a/src/spf.c +++ b/src/spf.c @@ -116,14 +116,15 @@ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; { const uschar * s = rr->data; srr.ttl = rr->ttl; switch(rr_type) { case T_MX: + if (rr->size < 2) continue; s += 2; /* skip the MX precedence field */ case T_PTR: { uschar * buf = store_malloc(256); (void)dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen, s, (DN_EXPAND_ARG4_TYPE)buf, 256); s = buf; @@ -131,24 +132,28 @@ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; } case T_TXT: { gstring * g = NULL; uschar chunk_len; + if (rr->size < 1+6) continue; /* min for version str */ if (strncmpic(rr->data+1, US SPF_VER_STR, 6) != 0) { HDEBUG(D_host_lookup) debug_printf("not an spf record: %.*s\n", (int) s[0], s+1); continue; } - for (int off = 0; off < rr->size; off += chunk_len) + /* require 1 byte for the chunk_len */ + for (int off = 0; off < rr->size - 1; off += chunk_len) { - if (!(chunk_len = s[off++])) break; + if ( !(chunk_len = s[off++]) + || rr->size < off + chunk_len /* ignore bogus size chunks */ + ) break; g = string_catn(g, s+off, chunk_len); } if (!g) continue; gstring_release_unused(g); s = string_copy_malloc(string_from_gstring(g)); DEBUG(D_receive) debug_printf("SPF_dns_exim_lookup '%s'\n", s); -- 2.42.0