Fixed out-of-bounds read in the SPA authenticator
Resolves: CVE-2020-12783
This commit is contained in:
parent
780569af31
commit
8b2730e97c
200
exim-4.93-CVE-2020-12783.patch
Normal file
200
exim-4.93-CVE-2020-12783.patch
Normal file
@ -0,0 +1,200 @@
|
||||
diff --git a/src/auths/auth-spa.c b/src/auths/auth-spa.c
|
||||
index fc363df..44c99e9 100644
|
||||
--- a/src/auths/auth-spa.c
|
||||
+++ b/src/auths/auth-spa.c
|
||||
@@ -374,27 +374,27 @@ void
|
||||
spa_bits_to_base64 (uschar *out, const uschar *in, int inlen)
|
||||
/* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
|
||||
{
|
||||
- for (; inlen >= 3; inlen -= 3)
|
||||
- {
|
||||
- *out++ = base64digits[in[0] >> 2];
|
||||
- *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
|
||||
- *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
|
||||
- *out++ = base64digits[in[2] & 0x3f];
|
||||
- in += 3;
|
||||
- }
|
||||
- if (inlen > 0)
|
||||
- {
|
||||
- uschar fragment;
|
||||
-
|
||||
- *out++ = base64digits[in[0] >> 2];
|
||||
- fragment = (in[0] << 4) & 0x30;
|
||||
- if (inlen > 1)
|
||||
- fragment |= in[1] >> 4;
|
||||
- *out++ = base64digits[fragment];
|
||||
- *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
|
||||
- *out++ = '=';
|
||||
- }
|
||||
- *out = '\0';
|
||||
+for (; inlen >= 3; inlen -= 3)
|
||||
+ {
|
||||
+ *out++ = base64digits[in[0] >> 2];
|
||||
+ *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
|
||||
+ *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
|
||||
+ *out++ = base64digits[in[2] & 0x3f];
|
||||
+ in += 3;
|
||||
+ }
|
||||
+if (inlen > 0)
|
||||
+ {
|
||||
+ uschar fragment;
|
||||
+
|
||||
+ *out++ = base64digits[in[0] >> 2];
|
||||
+ fragment = (in[0] << 4) & 0x30;
|
||||
+ if (inlen > 1)
|
||||
+ fragment |= in[1] >> 4;
|
||||
+ *out++ = base64digits[fragment];
|
||||
+ *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
|
||||
+ *out++ = '=';
|
||||
+ }
|
||||
+*out = '\0';
|
||||
}
|
||||
|
||||
|
||||
@@ -404,52 +404,52 @@ int
|
||||
spa_base64_to_bits (char *out, int outlength, const char *in)
|
||||
/* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
|
||||
{
|
||||
- int len = 0;
|
||||
- register uschar digit1, digit2, digit3, digit4;
|
||||
+int len = 0;
|
||||
+uschar digit1, digit2, digit3, digit4;
|
||||
|
||||
- if (in[0] == '+' && in[1] == ' ')
|
||||
- in += 2;
|
||||
- if (*in == '\r')
|
||||
- return (0);
|
||||
+if (in[0] == '+' && in[1] == ' ')
|
||||
+ in += 2;
|
||||
+if (*in == '\r')
|
||||
+ return (0);
|
||||
|
||||
- do
|
||||
+do
|
||||
+ {
|
||||
+ if (len >= outlength) /* Added by PH */
|
||||
+ return -1; /* Added by PH */
|
||||
+ digit1 = in[0];
|
||||
+ if (DECODE64 (digit1) == BAD)
|
||||
+ return -1;
|
||||
+ digit2 = in[1];
|
||||
+ if (DECODE64 (digit2) == BAD)
|
||||
+ return -1;
|
||||
+ digit3 = in[2];
|
||||
+ if (digit3 != '=' && DECODE64 (digit3) == BAD)
|
||||
+ return -1;
|
||||
+ digit4 = in[3];
|
||||
+ if (digit4 != '=' && DECODE64 (digit4) == BAD)
|
||||
+ return -1;
|
||||
+ in += 4;
|
||||
+ *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
|
||||
+ ++len;
|
||||
+ if (digit3 != '=')
|
||||
{
|
||||
+ if (len >= outlength) /* Added by PH */
|
||||
+ return -1; /* Added by PH */
|
||||
+ *out++ =
|
||||
+ ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
|
||||
+ ++len;
|
||||
+ if (digit4 != '=')
|
||||
+ {
|
||||
if (len >= outlength) /* Added by PH */
|
||||
- return (-1); /* Added by PH */
|
||||
- digit1 = in[0];
|
||||
- if (DECODE64 (digit1) == BAD)
|
||||
- return (-1);
|
||||
- digit2 = in[1];
|
||||
- if (DECODE64 (digit2) == BAD)
|
||||
- return (-1);
|
||||
- digit3 = in[2];
|
||||
- if (digit3 != '=' && DECODE64 (digit3) == BAD)
|
||||
- return (-1);
|
||||
- digit4 = in[3];
|
||||
- if (digit4 != '=' && DECODE64 (digit4) == BAD)
|
||||
- return (-1);
|
||||
- in += 4;
|
||||
- *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
|
||||
+ return -1; /* Added by PH */
|
||||
+ *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
|
||||
++len;
|
||||
- if (digit3 != '=')
|
||||
- {
|
||||
- if (len >= outlength) /* Added by PH */
|
||||
- return (-1); /* Added by PH */
|
||||
- *out++ =
|
||||
- ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
|
||||
- ++len;
|
||||
- if (digit4 != '=')
|
||||
- {
|
||||
- if (len >= outlength) /* Added by PH */
|
||||
- return (-1); /* Added by PH */
|
||||
- *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
|
||||
- ++len;
|
||||
- }
|
||||
- }
|
||||
+ }
|
||||
}
|
||||
- while (*in && *in != '\r' && digit4 != '=');
|
||||
+ }
|
||||
+while (*in && *in != '\r' && digit4 != '=');
|
||||
|
||||
- return (len);
|
||||
+return len;
|
||||
}
|
||||
|
||||
|
||||
diff --git a/src/auths/spa.c b/src/auths/spa.c
|
||||
index 97e3b10..5bffdfb 100644
|
||||
--- a/src/auths/spa.c
|
||||
+++ b/src/auths/spa.c
|
||||
@@ -139,7 +139,8 @@ SPAAuthChallenge challenge;
|
||||
SPAAuthResponse response;
|
||||
SPAAuthResponse *responseptr = &response;
|
||||
uschar msgbuf[2048];
|
||||
-uschar *clearpass;
|
||||
+uschar *clearpass, *s;
|
||||
+unsigned off;
|
||||
|
||||
/* send a 334, MS Exchange style, and grab the client's request,
|
||||
unless we already have it via an initial response. */
|
||||
@@ -194,9 +195,19 @@ that causes failure if the size of msgbuf is exceeded. ****/
|
||||
|
||||
{
|
||||
int i;
|
||||
- char *p = ((char*)responseptr) + IVAL(&responseptr->uUser.offset,0);
|
||||
+ char * p;
|
||||
int len = SVAL(&responseptr->uUser.len,0)/2;
|
||||
|
||||
+ if ( (off = IVAL(&responseptr->uUser.offset,0)) >= sizeof(SPAAuthResponse)
|
||||
+ || len >= sizeof(responseptr->buffer)/2
|
||||
+ || (p = (CS responseptr) + off) + len*2 >= CS (responseptr+1)
|
||||
+ )
|
||||
+ {
|
||||
+ DEBUG(D_auth)
|
||||
+ debug_printf("auth_spa_server(): bad uUser spec in response\n");
|
||||
+ return FAIL;
|
||||
+ }
|
||||
+
|
||||
if (len + 1 >= sizeof(msgbuf)) return FAIL;
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
@@ -245,9 +256,16 @@ spa_smb_nt_encrypt (clearpass, challenge.challengeData, ntRespData);
|
||||
|
||||
/* compare NT hash (LM may not be available) */
|
||||
|
||||
-if (memcmp(ntRespData,
|
||||
- ((unsigned char*)responseptr)+IVAL(&responseptr->ntResponse.offset,0),
|
||||
- 24) == 0)
|
||||
+off = IVAL(&responseptr->ntResponse.offset,0);
|
||||
+if (off >= sizeof(SPAAuthResponse) - 24)
|
||||
+ {
|
||||
+ DEBUG(D_auth)
|
||||
+ debug_printf("auth_spa_server(): bad ntRespData spec in response\n");
|
||||
+ return FAIL;
|
||||
+ }
|
||||
+s = (US responseptr) + off;
|
||||
+
|
||||
+if (memcmp(ntRespData, s, 24) == 0)
|
||||
/* success. we have a winner. */
|
||||
{
|
||||
return auth_check_serv_cond(ablock);
|
@ -15,7 +15,7 @@
|
||||
Summary: The exim mail transfer agent
|
||||
Name: exim
|
||||
Version: 4.93
|
||||
Release: 2%{?dist}
|
||||
Release: 3%{?dist}
|
||||
License: GPLv2+
|
||||
Url: https://www.exim.org/
|
||||
Group: System Environment/Daemons
|
||||
@ -56,6 +56,7 @@ Patch0: exim-4.93-config.patch
|
||||
Patch1: exim-4.93-libdir.patch
|
||||
Patch2: exim-4.93-dlopen-localscan.patch
|
||||
Patch3: exim-4.85-pic.patch
|
||||
Patch4: exim-4.93-CVE-2020-12783.patch
|
||||
|
||||
Requires: /etc/pki/tls/certs /etc/pki/tls/private
|
||||
Requires: /etc/aliases
|
||||
@ -204,6 +205,7 @@ greylisting unconditional.
|
||||
%patch1 -p1 -b .libdir
|
||||
%patch2 -p1 -b .dl
|
||||
%patch3 -p1 -b .fpic
|
||||
%patch4 -p1 -b .CVE-2020-12783
|
||||
|
||||
cp src/EDITME Local/Makefile
|
||||
sed -i 's@^# LOOKUP_MODULE_DIR=.*@LOOKUP_MODULE_DIR=%{_libdir}/exim/%{version}-%{release}/lookups@' Local/Makefile
|
||||
@ -608,6 +610,10 @@ test "$1" = 0 || %{_initrddir}/clamd.exim condrestart >/dev/null 2>&1 || :
|
||||
%{_sysconfdir}/cron.daily/greylist-tidy.sh
|
||||
|
||||
%changelog
|
||||
* Fri May 15 2020 Jaroslav Škarvada <jskarvad@redhat.com> - 4.93-3
|
||||
- Fixed out-of-bounds read in the SPA authenticator
|
||||
Resolves: CVE-2020-12783
|
||||
|
||||
* Wed Apr 29 2020 Jaroslav Škarvada <jskarvad@redhat.com> - 4.93-2
|
||||
- Enabled spf2 and opendmarc support
|
||||
Resolves: rhbz#1829076
|
||||
|
Loading…
Reference in New Issue
Block a user