From: Heiko Schlittermann (HS12-RIPE) Date: Sun, 15 Oct 2023 17:53:25 +0000 (+0200) Subject: Merge branch 'exim-4.96+security' into master+security X-Git-Tag: exim-4.97-RC3~6 X-Git-Url: https://git.exim.org/exim.git/commitdiff_plain/3857519629ca8fbcf3466c3fc761a5bb6ed32d53 Merge branch 'exim-4.96+security' into master+security * exim-4.96+security: docs: Changelog Harden dnsdb against crafted DNS responses. Bug 3033 SPF: harden against crafted DNS responses fix: string_is_ip_address (CVE-2023-42117) Bug 3031 Testsuite: Add testcases for string_is_ip_address (CVE-2023-42117) --- 3857519629ca8fbcf3466c3fc761a5bb6ed32d53 diff --cc doc/doc-txt/ChangeLog index a78ec386f,fb70203ed..4306cabc0 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@@ -205,6 -28,10 +205,14 @@@ JH/42 Bug 3001: Fix a possible OOB rea be triggered by externally-controlled input. Found by Trend Micro. CVE-2023-42114 -JH/04 Bug 2903: avoid exit on an attempt to rewrite a malformed address. ++JH/43 Bug 2903: avoid exit on an attempt to rewrite a malformed address. + Make the rewrite never match and keep the logging. Trust the + admin to be using verify=header-syntax (to actually reject the message). + ++JH/44 Bug 3033: Harden dnsdb lookups against crafted DNS responses. ++ CVE-2023-42219 ++ ++HS/02 Fix string_is_ip_address() CVE-2023-42117 (Bug 3031) Exim version 4.96 ----------------- diff --cc src/src/lookups/dnsdb.c index 1563eda56,020dc9a52..35a946447 --- a/src/src/lookups/dnsdb.c +++ b/src/src/lookups/dnsdb.c @@@ -394,38 -399,59 +394,55 @@@ while ((domain = string_nextinlist(&key if (type == T_TXT || type == T_SPF) { if (!outsep2) /* output only the first item of data */ - yield = string_catn(yield, US (rr->data+1), (rr->data)[0]); + { + 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); + } else - { - /* output all items */ - int data_offset = 0; - while (data_offset < rr->size) + for (unsigned data_offset = 0; 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); + yield = string_catn(yield, US ((rr->data) + ++data_offset), --chunk_len); data_offset += chunk_len; } - } } else if (type == T_TLSA) - { - uint8_t usage, selector, matching_type; - uint16_t payload_length; - uschar s[MAX_TLSA_EXPANDED_SIZE]; - uschar * sp = s; - uschar * p = US rr->data; + if (rr->size < 3) + continue; + else + { + uint8_t usage, selector, matching_type; + uint16_t payload_length; + uschar s[MAX_TLSA_EXPANDED_SIZE]; + uschar * sp = s; + uschar * p = US rr->data; + + usage = *p++; + selector = *p++; + matching_type = *p++; + /* What's left after removing the first 3 bytes above */ + payload_length = rr->size - 3; + sp += sprintf(CS s, "%d%c%d%c%d%c", usage, *outsep2, + selector, *outsep2, matching_type, *outsep2); + /* Now append the cert/identifier, one hex char at a time */ + while (payload_length-- > 0 && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4)) + sp += sprintf(CS sp, "%02x", *p++); - usage = *p++; - selector = *p++; - matching_type = *p++; - /* What's left after removing the first 3 bytes above */ - payload_length = rr->size - 3; - sp += sprintf(CS s, "%d%c%d%c%d%c", usage, *outsep2, - selector, *outsep2, matching_type, *outsep2); - /* Now append the cert/identifier, one hex char at a time */ - while (payload_length-- > 0 && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4)) - sp += sprintf(CS sp, "%02x", *p++); - - yield = string_cat(yield, s); - } + yield = string_cat(yield, s); + } else /* T_CNAME, T_CSA, T_MX, T_MXH, T_NS, T_PTR, T_SOA, T_SRV */ { int priority, weight, port;