summaryrefslogtreecommitdiffstats
path: root/debian/patches/76-14-Lookups-Fix-dnsdb-lookup-of-multi-chunk-TXT.-Bug-305.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/76-14-Lookups-Fix-dnsdb-lookup-of-multi-chunk-TXT.-Bug-305.patch')
-rw-r--r--debian/patches/76-14-Lookups-Fix-dnsdb-lookup-of-multi-chunk-TXT.-Bug-305.patch118
1 files changed, 118 insertions, 0 deletions
diff --git a/debian/patches/76-14-Lookups-Fix-dnsdb-lookup-of-multi-chunk-TXT.-Bug-305.patch b/debian/patches/76-14-Lookups-Fix-dnsdb-lookup-of-multi-chunk-TXT.-Bug-305.patch
new file mode 100644
index 0000000..7b9eb6e
--- /dev/null
+++ b/debian/patches/76-14-Lookups-Fix-dnsdb-lookup-of-multi-chunk-TXT.-Bug-305.patch
@@ -0,0 +1,118 @@
+From 79670d3c32ccb37fe06f25d8192943b58606a32a Mon Sep 17 00:00:00 2001
+From: Jeremy Harris <jgh146exb@wizmail.org>
+Date: Fri, 17 Nov 2023 16:55:17 +0000
+Subject: [PATCH] Lookups: Fix dnsdb lookup of multi-chunk TXT. Bug 3054
+
+Broken=by: f6b1f8e7d642
+---
+ doc/ChangeLog | 6 ++++-
+ src/dns.c | 4 +++-
+ src/lookups/dnsdb.c | 45 +++++++++++++++---------------------
+ test/dnszones-src/db.test.ex | 1 +
+ test/scripts/2200-dnsdb/2200 | 1 +
+ test/src/fakens.c | 1 +
+ test/stdout/2200 | 1 +
+ 7 files changed, 31 insertions(+), 28 deletions(-)
+
+--- a/doc/ChangeLog
++++ b/doc/ChangeLog
+@@ -87,10 +87,13 @@ JH/34 Bug 3013: Fix use of $recipients w
+ JH/35 Bug 3014: GnuTLS: fix expiry date for an auto-generated server
+ certificate. Find and fix by Andreas Metzler.
+
+ JH/39 Bug 3023: Fix crash induced by some combinations of zero-length strings
+ and ${tr...}. Found and diagnosed by Heiko Schlichting.
++
++JH/06 Bug 3054: Fix dnsdb lookup for a TXT record with multiple chunks. This
++ was broken by hardening introduced for Bug 3033.
+
+ Exim version 4.96
+ -----------------
+
+ JH/01 Move the wait-for-next-tick (needed for unique message IDs) from
+--- a/src/dns.c
++++ b/src/dns.c
+@@ -428,11 +428,13 @@ TRACE trace = "R-namelen";
+ namelen = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen, dnss->aptr,
+ (DN_EXPAND_ARG4_TYPE) &dnss->srr.name, DNS_MAXNAME);
+ if (namelen < 0) goto null_return;
+
+ /* Move the pointer past the name and fill in the rest of the data structure
+-from the following bytes. */
++from the following bytes. We seem to be assuming here that the RR blob passed
++to us by the resolver library is the same as that defined for an RR by RFC 1035
++section 3.2.1 */
+
+ TRACE trace = "R-name";
+ if (dnss_inc_aptr(dnsa, dnss, namelen)) goto null_return;
+
+ /* Check space for type, class, TTL & data-size-word */
+--- a/src/lookups/dnsdb.c
++++ b/src/lookups/dnsdb.c
+@@ -390,46 +390,36 @@ while ((domain = string_nextinlist(&keys
+ }
+ continue;
+ }
+
+ /* Other kinds of record just have one piece of data each, but there may be
+- several of them, of course. */
++ several of them, of course. TXT & SPF can have data in multiple chunks. */
+
+ if (yield->ptr) yield = string_catn(yield, outsep, 1);
+
+ if (type == T_TXT || type == T_SPF)
+- {
+- if (!outsep2) /* output only the first item of data */
++ for (unsigned data_offset = 0; data_offset + 1 < rr->size; )
+ {
+- uschar n = (rr->data)[0];
+- /* size byte + data bytes must not excced the RRs length */
+- if (n + 1 <= rr->size)
+- yield = string_catn(yield, US (rr->data+1), n);
++ uschar chunk_len = (rr->data)[data_offset];
++ int remain;
++
++ if (outsep2 && *outsep2 && data_offset != 0)
++ yield = string_catn(yield, outsep2, 1);
++
++ /* Apparently there are resolvers that do not check RRs before passing
++ them on, and glibc fails to do so. So every application must...
++ Check for chunk len exceeding RR */
++
++ remain = rr->size - ++data_offset;
++ if (chunk_len > remain)
++ chunk_len = remain;
++ yield = string_catn(yield, US ((rr->data) + data_offset), chunk_len);
++ data_offset += chunk_len;
++
++ if (!outsep2) break; /* output only the first chunk of the RR */
++
+ }
+- else
+- {
+- /* output all items */
+- int data_offset = 0;
+- while (data_offset < rr->size)
+- {
+- uschar chunk_len = (rr->data)[data_offset];
+- int remain = rr->size - data_offset;
+-
+- /* Apparently there are resolvers that do not check RRs before passing
+- them on, and glibc fails to do so. So every application must...
+- Check for chunk len exceeding RR */
+-
+- if (chunk_len > remain)
+- chunk_len = remain;
+-
+- if (*outsep2 && data_offset != 0)
+- yield = string_catn(yield, outsep2, 1);
+- yield = string_catn(yield, US ((rr->data) + ++data_offset), --chunk_len);
+- data_offset += chunk_len;
+- }
+- }
+- }
+ else if (type == T_TLSA)
+ if (rr->size < 3)
+ continue;
+ else
+ {