1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
From 654056e44fc93a0ee7c09d1228933e8af6862206 Mon Sep 17 00:00:00 2001
From: Jeremy Harris <jgh146exb@wizmail.org>
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
|