From: Arkadiusz Miśkiewicz Date: Mon, 2 Oct 2023 13:28:58 +0000 (+0200) Subject: - rel 26; official fixes for CVE-2023-42114, CVE-2023-42115, CVE-2023-42116. Still... X-Git-Tag: auto/th/exim-4.96-26 X-Git-Url: http://git.pld-linux.org/gitweb.cgi?a=commitdiff_plain;h=0a6eb0abd190c788f18dae38aa4ad418f3dbd3e7;p=packages%2Fexim.git - rel 26; official fixes for CVE-2023-42114, CVE-2023-42115, CVE-2023-42116. Still 2 issues left (proxy protocol and untrusted resolver) --- diff --git a/CVE-2023-42114+42115+42116-fixes.patch b/CVE-2023-42114+42115+42116-fixes.patch new file mode 100644 index 0000000..15d7047 --- /dev/null +++ b/CVE-2023-42114+42115+42116-fixes.patch @@ -0,0 +1,306 @@ +;+JH/01 Bug 2999: Fix a possible OOB write in the external authenticator, which +; could be triggered by externally-supplied input. Found by Trend Micro. +; CVE-2023-42115 +; +;JH/02 Bug 3000: Fix a possible OOB write in the SPA authenticator, which could +; be triggered by externally-controlled input. Found by Trend Micro. +; CVE-2023-42116 +; +;JH/03 Bug 3001: Fix a possible OOB read in the SPA authenticator, which could +; be triggered by externally-controlled input. Found by Trend Micro. +; CVE-2023-42114 +; +diff --git a/src/src/auths/auth-spa.c b/src/src/auths/auth-spa.c +index 8d886b6b6..bb3d327d1 100644 +--- a/src/src/auths/auth-spa.c ++++ b/src/src/auths/auth-spa.c +@@ -155,6 +155,9 @@ int main (int argc, char ** argv) + up with a different answer to the one above) + */ + ++#ifndef MACRO_PREDEF ++ ++ + #define DEBUG_X(a,b) ; + + extern int DEBUGLEVEL; +@@ -1211,7 +1214,9 @@ char versionString[] = "libntlm version 0.21"; + + #define spa_bytes_add(ptr, header, buf, count) \ + { \ +-if (buf && (count) != 0) /* we hate -Wint-in-bool-contex */ \ ++if ( buf && (count) != 0 /* we hate -Wint-in-bool-contex */ \ ++ && ptr->bufIndex + count < sizeof(ptr->buffer) \ ++ ) \ + { \ + SSVAL(&ptr->header.len,0,count); \ + SSVAL(&ptr->header.maxlen,0,count); \ +@@ -1229,35 +1234,30 @@ else \ + + #define spa_string_add(ptr, header, string) \ + { \ +-char *p = string; \ ++uschar * p = string; \ + int len = 0; \ +-if (p) len = strlen(p); \ +-spa_bytes_add(ptr, header, (US p), len); \ ++if (p) len = Ustrlen(p); \ ++spa_bytes_add(ptr, header, p, len); \ + } + + #define spa_unicode_add_string(ptr, header, string) \ + { \ +-char *p = string; \ +-uschar *b = NULL; \ ++uschar * p = string; \ ++uschar * b = NULL; \ + int len = 0; \ + if (p) \ + { \ +- len = strlen(p); \ +- b = strToUnicode(p); \ ++ len = Ustrlen(p); \ ++ b = US strToUnicode(CS p); \ + } \ + spa_bytes_add(ptr, header, b, len*2); \ + } + + +-#define GetUnicodeString(structPtr, header) \ +-unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2) +-#define GetString(structPtr, header) \ +-toString(((CS structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0)) +- + #ifdef notdef + + #define DumpBuffer(fp, structPtr, header) \ +-dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0)) ++ dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0)) + + + static void +@@ -1321,8 +1321,33 @@ buf[len] = 0; + return buf; + } + ++static inline uschar * ++get_challenge_unistr(SPAAuthChallenge * challenge, SPAStrHeader * hdr) ++{ ++int off = IVAL(&hdr->offset, 0); ++int len = SVAL(&hdr->len, 0); ++return off + len < sizeof(SPAAuthChallenge) ++ ? US unicodeToString(CS challenge + off, len/2) : US""; ++} ++ ++static inline uschar * ++get_challenge_str(SPAAuthChallenge * challenge, SPAStrHeader * hdr) ++{ ++int off = IVAL(&hdr->offset, 0); ++int len = SVAL(&hdr->len, 0); ++return off + len < sizeof(SPAAuthChallenge) ++ ? US toString(CS challenge + off, len) : US""; ++} ++ + #ifdef notdef + ++#define GetUnicodeString(structPtr, header) \ ++ unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2) ++ ++#define GetString(structPtr, header) \ ++ toString(((CS structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0)) ++ ++ + void + dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request) + { +@@ -1366,15 +1391,15 @@ fprintf (fp, " Flags = %08x\n", IVAL (&response->flags, 0)); + #endif + + void +-spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain) ++spa_build_auth_request (SPAAuthRequest * request, uschar * user, uschar * domain) + { +-char *u = strdup (user); +-char *p = strchr (u, '@'); ++uschar * u = string_copy(user); ++uschar * p = Ustrchr(u, '@'); + + if (p) + { + if (!domain) +- domain = p + 1; ++ domain = p + 1; + *p = '\0'; + } + +@@ -1384,7 +1409,6 @@ SIVAL (&request->msgType, 0, 1); + SIVAL (&request->flags, 0, 0x0000b207); /* have to figure out what these mean */ + spa_string_add (request, user, u); + spa_string_add (request, domain, domain); +-free (u); + } + + +@@ -1475,16 +1499,16 @@ free (u); + + void + spa_build_auth_response (SPAAuthChallenge * challenge, +- SPAAuthResponse * response, char *user, +- char *password) ++ SPAAuthResponse * response, uschar * user, ++ uschar * password) + { + uint8x lmRespData[24]; + uint8x ntRespData[24]; + uint32x cf = IVAL(&challenge->flags, 0); +-char *u = strdup (user); +-char *p = strchr (u, '@'); +-char *d = NULL; +-char *domain; ++uschar * u = string_copy(user); ++uschar * p = Ustrchr(u, '@'); ++uschar * d = NULL; ++uschar * domain; + + if (p) + { +@@ -1492,33 +1516,33 @@ if (p) + *p = '\0'; + } + +-else domain = d = strdup((cf & 0x1)? +- CCS GetUnicodeString(challenge, uDomain) : +- CCS GetString(challenge, uDomain)); ++else domain = d = string_copy(cf & 0x1 ++ ? CUS get_challenge_unistr(challenge, &challenge->uDomain) ++ : CUS get_challenge_str(challenge, &challenge->uDomain)); + +-spa_smb_encrypt (US password, challenge->challengeData, lmRespData); +-spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData); ++spa_smb_encrypt(password, challenge->challengeData, lmRespData); ++spa_smb_nt_encrypt(password, challenge->challengeData, ntRespData); + + response->bufIndex = 0; + memcpy (response->ident, "NTLMSSP\0\0\0", 8); + SIVAL (&response->msgType, 0, 3); + +-spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0); +-spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0); ++spa_bytes_add(response, lmResponse, lmRespData, cf & 0x200 ? 24 : 0); ++spa_bytes_add(response, ntResponse, ntRespData, cf & 0x8000 ? 24 : 0); + + if (cf & 0x1) { /* Unicode Text */ +- spa_unicode_add_string (response, uDomain, domain); +- spa_unicode_add_string (response, uUser, u); +- spa_unicode_add_string (response, uWks, u); ++ spa_unicode_add_string(response, uDomain, domain); ++ spa_unicode_add_string(response, uUser, u); ++ spa_unicode_add_string(response, uWks, u); + } else { /* OEM Text */ +- spa_string_add (response, uDomain, domain); +- spa_string_add (response, uUser, u); +- spa_string_add (response, uWks, u); ++ spa_string_add(response, uDomain, domain); ++ spa_string_add(response, uUser, u); ++ spa_string_add(response, uWks, u); + } + +-spa_string_add (response, sessionKey, NULL); ++spa_string_add(response, sessionKey, NULL); + response->flags = challenge->flags; +- +-if (d != NULL) free (d); +-free (u); + } ++ ++ ++#endif /*!MACRO_PREDEF*/ +diff --git a/src/src/auths/auth-spa.h b/src/src/auths/auth-spa.h +index cfe1b086d..3b0b3a9e3 100644 +--- a/src/src/auths/auth-spa.h ++++ b/src/src/auths/auth-spa.h +@@ -79,10 +79,10 @@ typedef struct + + void spa_bits_to_base64 (unsigned char *, const unsigned char *, int); + int spa_base64_to_bits(char *, int, const char *); +-void spa_build_auth_response (SPAAuthChallenge *challenge, +- SPAAuthResponse *response, char *user, char *password); +-void spa_build_auth_request (SPAAuthRequest *request, char *user, +- char *domain); ++void spa_build_auth_response (SPAAuthChallenge * challenge, ++ SPAAuthResponse * response, uschar * user, uschar * password); ++void spa_build_auth_request (SPAAuthRequest * request, uschar * user, ++ uschar * domain); + extern void spa_smb_encrypt (unsigned char * passwd, unsigned char * c8, + unsigned char * p24); + extern void spa_smb_nt_encrypt (unsigned char * passwd, unsigned char * c8, +diff --git a/src/src/auths/external.c b/src/src/auths/external.c +index 7e7fca841..790b98159 100644 +--- a/src/src/auths/external.c ++++ b/src/src/auths/external.c +@@ -103,7 +103,7 @@ if (expand_nmax == 0) /* skip if rxd data */ + if (ob->server_param2) + { + uschar * s = expand_string(ob->server_param2); +- auth_vars[expand_nmax] = s; ++ auth_vars[expand_nmax = 1] = s; + expand_nstring[++expand_nmax] = s; + expand_nlength[expand_nmax] = Ustrlen(s); + if (ob->server_param3) +diff --git a/src/src/auths/spa.c b/src/src/auths/spa.c +index ff90d33a3..bfaccefda 100644 +--- a/src/src/auths/spa.c ++++ b/src/src/auths/spa.c +@@ -284,14 +284,13 @@ SPAAuthRequest request; + SPAAuthChallenge challenge; + SPAAuthResponse response; + char msgbuf[2048]; +-char *domain = NULL; +-char *username, *password; ++uschar * domain = NULL, * username, * password; + + /* Code added by PH to expand the options */ + + *buffer = 0; /* Default no message when cancelled */ + +-if (!(username = CS expand_string(ob->spa_username))) ++if (!(username = expand_string(ob->spa_username))) + { + if (f.expand_string_forcedfail) return CANCELLED; + string_format(buffer, buffsize, "expansion of \"%s\" failed in %s " +@@ -300,7 +299,7 @@ if (!(username = CS expand_string(ob->spa_username))) + return ERROR; + } + +-if (!(password = CS expand_string(ob->spa_password))) ++if (!(password = expand_string(ob->spa_password))) + { + if (f.expand_string_forcedfail) return CANCELLED; + string_format(buffer, buffsize, "expansion of \"%s\" failed in %s " +@@ -310,7 +309,7 @@ if (!(password = CS expand_string(ob->spa_password))) + } + + if (ob->spa_domain) +- if (!(domain = CS expand_string(ob->spa_domain))) ++ if (!(domain = expand_string(ob->spa_domain))) + { + if (f.expand_string_forcedfail) return CANCELLED; + string_format(buffer, buffsize, "expansion of \"%s\" failed in %s " +@@ -330,7 +329,7 @@ if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout)) + + DSPA("\n\n%s authenticator: using domain %s\n\n", ablock->name, domain); + +-spa_build_auth_request(&request, CS username, domain); ++spa_build_auth_request(&request, username, domain); + spa_bits_to_base64(US msgbuf, US &request, spa_request_length(&request)); + + DSPA("\n\n%s authenticator: sending request (%s)\n\n", ablock->name, msgbuf); +@@ -347,7 +346,7 @@ if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout)) + DSPA("\n\n%s authenticator: challenge (%s)\n\n", ablock->name, buffer + 4); + spa_base64_to_bits(CS (&challenge), sizeof(challenge), CCS (buffer + 4)); + +-spa_build_auth_response(&challenge, &response, CS username, CS password); ++spa_build_auth_response(&challenge, &response, username, password); + spa_bits_to_base64(US msgbuf, US &response, spa_request_length(&response)); + DSPA("\n\n%s authenticator: challenge response (%s)\n\n", ablock->name, msgbuf); + diff --git a/exim.spec b/exim.spec index 8a3e69d..89ac53b 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: 25 +Release: 26 Epoch: 2 License: GPL v2+ Group: Networking/Daemons/SMTP @@ -62,7 +62,8 @@ Patch6: 90_localscan_dlopen-fixes.dpatch Patch7: linelength-show.patch Patch8: %{name}-spam-timeout.patch Patch9: autoreply-return-path.patch -Patch10: unofficial-hotfix.patch +Patch10: CVE-2023-42114+42115+42116-fixes.patch +Patch11: unofficial-hotfix.patch URL: http://www.exim.org/ %{?with_sasl:BuildRequires: cyrus-sasl-devel >= 2.1.0} BuildRequires: db-devel @@ -188,6 +189,7 @@ Pliki nagłówkowe dla Exima. %patch8 -p1 %patch9 -p2 %patch10 -p2 +%patch11 -p2 install %{SOURCE4} exim4.conf install %{SOURCE14} doc/config.samples.tar.bz2 diff --git a/unofficial-hotfix.patch b/unofficial-hotfix.patch index c7cc282..b8eab75 100644 --- a/unofficial-hotfix.patch +++ b/unofficial-hotfix.patch @@ -41,42 +41,6 @@ index 078aad0..54966e6 100644 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