From 05c80ef30111128a0c6d1568b9691559161c255f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Arkadiusz=20Mi=C5=9Bkiewicz?= Date: Sun, 1 Oct 2023 17:16:31 +0200 Subject: [PATCH] Rel 25; unofficial hotfix for some of recent SECURITY issues (timelime for official (they exist but are not public) fixes is unknown) --- exim.spec | 6 +- unofficial-hotfix.patch | 151 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 unofficial-hotfix.patch diff --git a/exim.spec b/exim.spec index c07cf98..8a3e69d 100644 --- a/exim.spec +++ b/exim.spec @@ -23,7 +23,7 @@ Summary(pl.UTF-8): Agent Transferu Poczty Uniwersytetu w Cambridge Summary(pt_BR.UTF-8): Servidor de correio eletrônico exim Name: exim Version: 4.96 -Release: 24 +Release: 25 Epoch: 2 License: GPL v2+ Group: Networking/Daemons/SMTP @@ -49,7 +49,7 @@ Source15: %{name}4-smtp.pamd Source16: %{name}on.png # sh branch.sh Patch100: %{name}-git.patch -# Patch100-md5: 0ea3e11e6f8a3371f1ffe042a9f7a83c +# Patch100-md5: a08ce639b3a3652899a84ff606e66517 Patch0: %{name}4-EDITME.patch Patch1: %{name}4-monitor-EDITME.patch Patch2: %{name}4-cflags.patch @@ -62,6 +62,7 @@ Patch6: 90_localscan_dlopen-fixes.dpatch Patch7: linelength-show.patch Patch8: %{name}-spam-timeout.patch Patch9: autoreply-return-path.patch +Patch10: unofficial-hotfix.patch URL: http://www.exim.org/ %{?with_sasl:BuildRequires: cyrus-sasl-devel >= 2.1.0} BuildRequires: db-devel @@ -186,6 +187,7 @@ Pliki nagłówkowe dla Exima. %patch7 -p1 %patch8 -p1 %patch9 -p2 +%patch10 -p2 install %{SOURCE4} exim4.conf install %{SOURCE14} doc/config.samples.tar.bz2 diff --git a/unofficial-hotfix.patch b/unofficial-hotfix.patch new file mode 100644 index 0000000..c7cc282 --- /dev/null +++ b/unofficial-hotfix.patch @@ -0,0 +1,151 @@ +Date: Sun, 1 Oct 2023 11:33:26 +0200 +To: exim-dev@lists.exim.org +From: Florian Zumbiehl via Exim-dev + +Hi, + +below you find a patch that fixes some (probably three?) of what I guess are +the vulnerabilities reported by ZDI. + +Please note that the patch is only mildly tested, it is developed based on +the git master branch, but can be applied to older versions with minor +massaging. If you go back far enough, proxy.c was part of smtp_in.c, but if +you adjust for that, the patch can be made to apply there, too. + +Obviously, I have no idea whether this actually addresses what ZDI has +reported, but if not, these probably should be fixed, too, and if so, given +the fact that I managed to rather easily find these vulnerabilities based +on the information that's publicly available, I don't think there is much +point to trying to keep this secret any longer--if anything, it's +counterproductive. + +Also mind you that this is a hot fix, it's neither elegant, nor does it do +any useful error reporting, the goal was simply to prevent out of bounds +accesses. + +Florian + +--- + +diff --git a/src/src/auths/external.c b/src/src/auths/external.c +index 078aad0..54966e6 100644 +--- a/src/src/auths/external.c ++++ b/src/src/auths/external.c +@@ -101,6 +101,9 @@ if (expand_nmax == 0) /* skip if rxd data */ + if ((rc = auth_prompt(CUS"")) != OK) + return rc; + ++if (expand_nmax != 1) ++ return FAIL; ++ + if (ob->server_param2) + { + uschar * s = expand_string(ob->server_param2); +diff --git a/src/src/auths/spa.c b/src/src/auths/spa.c +index 222ccea..66967d6 100644 +--- a/src/src/auths/spa.c ++++ b/src/src/auths/spa.c +@@ -166,12 +166,18 @@ if (auth_get_no64_data(&data, msgbuf) != OK) + return FAIL; + + /* dump client response */ +-if (spa_base64_to_bits(CS &response, sizeof(response), CCS data) < 0) ++int l = spa_base64_to_bits(CS &response, sizeof(response), CCS data); ++if (l < 0) + { + DEBUG(D_auth) debug_printf("auth_spa_server(): bad base64 data in " + "response: %s\n", data); + return FAIL; + } ++if(l < (char *)&response.buffer - (char *)&response)return FAIL; ++unsigned long o = IVAL(&response.uUser.offset, 0); ++if((l < o) || (l - o < SVAL(&response.uUser.len, 0)))return FAIL; ++o = IVAL(&response.ntResponse.offset, 0); ++if((l < o) || (l - o < 24))return FAIL; + + /*************************************************************** + PH 07-Aug-2003: The original code here was this: +@@ -346,7 +352,10 @@ if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout)) + + /* convert the challenge into the challenge struct */ + DSPA("\n\n%s authenticator: challenge (%s)\n\n", ablock->name, buffer + 4); +-spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4)); ++int l = spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4)); ++if((l < 0) || (l < (char *)&challenge.buffer - (char *)&challenge))return FAIL; ++unsigned long o = IVAL(&challenge.uDomain.offset, 0); ++if((l < o) || (l - o < SVAL(&challenge.uDomain.len, 0)))return FAIL; + + spa_build_auth_response(&challenge, &response, CS username, CS password); + spa_bits_to_base64(US msgbuf, US &response, spa_request_length(&response)); +diff --git a/src/src/proxy.c b/src/src/proxy.c +index fbce111..8dd7034 100644 +--- a/src/src/proxy.c ++++ b/src/src/proxy.c +@@ -93,6 +93,8 @@ while (capacity > 0) + do { ret = read(fd, to, 1); } while (ret == -1 && errno == EINTR && !had_command_timeout); + if (ret == -1) + return -1; ++ if (!ret) ++ break; + have++; + if (last) + return have; +@@ -254,6 +256,8 @@ if ((ret == PROXY_INITIAL_READ) && (memcmp(&hdr.v2, v2sig, sizeof(v2sig)) == 0)) + goto proxyfail; + } + ++ if (ret < 16) ++ goto proxyfail; + /* The v2 header will always be 16 bytes per the spec. */ + size = 16 + ntohs(hdr.v2.len); + DEBUG(D_receive) debug_printf("Detected PROXYv2 header, size %d (limit %d)\n", +@@ -274,7 +278,7 @@ if ((ret == PROXY_INITIAL_READ) && (memcmp(&hdr.v2, v2sig, sizeof(v2sig)) == 0)) + { + retmore = read(fd, (uschar*)&hdr + ret, size-ret); + } while (retmore == -1 && errno == EINTR && !had_command_timeout); +- if (retmore == -1) ++ if (retmore < 1) + goto proxyfail; + DEBUG(D_receive) proxy_debug(US &hdr, ret, ret + retmore); + ret += retmore; +@@ -297,6 +301,8 @@ if (ret >= 16 && memcmp(&hdr.v2, v2sig, 12) == 0) + switch (hdr.v2.fam) + { + case 0x11: /* TCPv4 address type */ ++ if (ret < 28) ++ goto proxyfail; + iptype = US"IPv4"; + tmpaddr.sin_addr.s_addr = hdr.v2.addr.ip4.src_addr; + inet_ntop(AF_INET, &tmpaddr.sin_addr, CS &tmpip, sizeof(tmpip)); +@@ -323,6 +329,8 @@ if (ret >= 16 && memcmp(&hdr.v2, v2sig, 12) == 0) + proxy_external_port = tmpport; + goto done; + case 0x21: /* TCPv6 address type */ ++ if (ret < 52) ++ goto proxyfail; + iptype = US"IPv6"; + memmove(tmpaddr6.sin6_addr.s6_addr, hdr.v2.addr.ip6.src_addr, 16); + inet_ntop(AF_INET6, &tmpaddr6.sin6_addr, CS &tmpip6, sizeof(tmpip6)); +@@ -381,10 +389,13 @@ else if (ret >= 8 && memcmp(hdr.v1.line, "PROXY", 5) == 0) + goto proxyfail; + ret += r2; + ++ if(ret > 107) ++ goto proxyfail; ++ hdr.v1.line[ret] = 0; + p = string_copy(hdr.v1.line); + end = memchr(p, '\r', ret - 1); + +- if (!end || (end == (uschar*)&hdr + ret) || end[1] != '\n') ++ if (!end || end[1] != '\n') + { + DEBUG(D_receive) debug_printf("Partial or invalid PROXY header\n"); + goto proxyfail; + +-- +## subscription configuration (requires account): +## https://lists.exim.org/mailman3/postorius/lists/exim-dev.lists.exim.org/ +## unsubscribe (doesn't require an account): +## exim-dev-unsubscribe@lists.exim.org +## Exim details at http://www.exim.org/ +## Please use the Wiki with this list - http://wiki.exim.org/ -- 2.44.0