!30 fix CVE-2020-14154
From: @starlet-dx Reviewed-by: @small_leek Signed-off-by: @small_leek
This commit is contained in:
commit
1ae70d79e3
188
CVE-2020-14154-1.patch
Normal file
188
CVE-2020-14154-1.patch
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
From bb0e6277a45a5d4c3a30d3b968eeb31d78124e95 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin McCarthy <kevin@8t8.us>
|
||||||
|
Date: Fri, 5 Jun 2020 15:21:03 -0700
|
||||||
|
Subject: [PATCH] Fix GnuTLS tls_verify_peers() checking.
|
||||||
|
|
||||||
|
* Change the function to pass the certstatus parameter by reference,
|
||||||
|
and indicate success/failure of the function via the return value. It
|
||||||
|
was previously returning the certstatus, but was also returning 0 or
|
||||||
|
the *unset* certstatus on error too. Since a 0 certstatus means
|
||||||
|
"success", this meant a gnutls_certificate_verify_peers2() failure
|
||||||
|
would be regarded as a valid cert.
|
||||||
|
|
||||||
|
* The gnutls_certificate_type_get() inside tls_verify_peers() checks
|
||||||
|
the *client* certificate type. Since it was only called if gnutls_certificate_verify_peers2() failed, I assume was either a
|
||||||
|
mistake, or perhaps an attempt to give a special error message if the
|
||||||
|
client cert was OpenPGP. In either case, the error message was not
|
||||||
|
very informative, so just remove the call and special error message.
|
||||||
|
|
||||||
|
* Fix GNUTLS_E_NO_CERTIFICATE_FOUND check to be against verify_ret
|
||||||
|
instead of certstat.
|
||||||
|
|
||||||
|
* Fix gnutls_strerror() call to use verify_ret instead of certstat.
|
||||||
|
|
||||||
|
* gnutls_certificate_verify_peers2() already calls and checks gnutls_auth_get_type(), so remove call at the beginning of tls_check_certificate().
|
||||||
|
|
||||||
|
* gnutls_certificate_verify_peers2() also verifies the certificate
|
||||||
|
type for the *server* is GNUTLS_CRT_X509. Add a comment about that.
|
||||||
|
---
|
||||||
|
mutt_ssl_gnutls.c | 100 +++++++++++++++++++++++++++-------------------
|
||||||
|
1 file changed, 60 insertions(+), 40 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mutt_ssl_gnutls.c b/mutt_ssl_gnutls.c
|
||||||
|
index 8fc6421..19d47b3 100644
|
||||||
|
--- a/mutt_ssl_gnutls.c
|
||||||
|
+++ b/mutt_ssl_gnutls.c
|
||||||
|
@@ -684,6 +684,9 @@ static int tls_check_stored_hostname (const gnutls_datum_t *cert,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Returns 0 on success
|
||||||
|
+ * -1 on failure
|
||||||
|
+ */
|
||||||
|
static int tls_check_preauth (const gnutls_datum_t *certdata,
|
||||||
|
gnutls_certificate_status_t certstat,
|
||||||
|
const char *hostname, int chainidx, int* certerr,
|
||||||
|
@@ -802,8 +805,8 @@ static int tls_check_preauth (const gnutls_datum_t *certdata,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * Returns 0 on failure, nonzero on success.
|
||||||
|
+/* Returns 1 on success.
|
||||||
|
+ * 0 on failure.
|
||||||
|
*/
|
||||||
|
static int tls_check_one_certificate (const gnutls_datum_t *certdata,
|
||||||
|
gnutls_certificate_status_t certstat,
|
||||||
|
@@ -1086,44 +1089,57 @@ static int tls_check_one_certificate (const gnutls_datum_t *certdata,
|
||||||
|
mutt_menuDestroy (&menu);
|
||||||
|
gnutls_x509_crt_deinit (cert);
|
||||||
|
|
||||||
|
- return (done == 2);
|
||||||
|
+ return (done == 2) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* sanity-checking wrapper for gnutls_certificate_verify_peers */
|
||||||
|
-static gnutls_certificate_status_t tls_verify_peers (gnutls_session_t tlsstate)
|
||||||
|
+/* sanity-checking wrapper for gnutls_certificate_verify_peers.
|
||||||
|
+ *
|
||||||
|
+ * certstat is technically a bitwise-or of gnutls_certificate_status_t
|
||||||
|
+ * values.
|
||||||
|
+ *
|
||||||
|
+ * Returns:
|
||||||
|
+ * - 0 if certstat was set. note: this does not mean success.
|
||||||
|
+ * - nonzero on failure.
|
||||||
|
+ */
|
||||||
|
+static int tls_verify_peers (gnutls_session_t tlsstate,
|
||||||
|
+ gnutls_certificate_status_t *certstat)
|
||||||
|
{
|
||||||
|
int verify_ret;
|
||||||
|
- unsigned int status;
|
||||||
|
|
||||||
|
- verify_ret = gnutls_certificate_verify_peers2 (tlsstate, &status);
|
||||||
|
+ /* gnutls_certificate_verify_peers2() chains to
|
||||||
|
+ * gnutls_x509_trust_list_verify_crt2(). That function's documentation says:
|
||||||
|
+ *
|
||||||
|
+ * When a certificate chain of cert_list_size with more than one
|
||||||
|
+ * certificates is provided, the verification status will apply to
|
||||||
|
+ * the first certificate in the chain that failed
|
||||||
|
+ * verification. The verification process starts from the end of
|
||||||
|
+ * the chain (from CA to end certificate). The first certificate
|
||||||
|
+ * in the chain must be the end-certificate while the rest of the
|
||||||
|
+ * members may be sorted or not.
|
||||||
|
+ *
|
||||||
|
+ * This is why tls_check_certificate() loops from CA to host in that order,
|
||||||
|
+ * calling the menu, and recalling tls_verify_peers() for each approved
|
||||||
|
+ * cert in the chain.
|
||||||
|
+ */
|
||||||
|
+ verify_ret = gnutls_certificate_verify_peers2 (tlsstate, certstat);
|
||||||
|
+
|
||||||
|
+ /* certstat was set */
|
||||||
|
if (!verify_ret)
|
||||||
|
- return status;
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
- if (status == GNUTLS_E_NO_CERTIFICATE_FOUND)
|
||||||
|
- {
|
||||||
|
+ if (verify_ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
|
||||||
|
mutt_error (_("Unable to get certificate from peer"));
|
||||||
|
- mutt_sleep (2);
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
- if (verify_ret < 0)
|
||||||
|
- {
|
||||||
|
+ else
|
||||||
|
mutt_error (_("Certificate verification error (%s)"),
|
||||||
|
- gnutls_strerror (status));
|
||||||
|
- mutt_sleep (2);
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* We only support X.509 certificates (not OpenPGP) at the moment */
|
||||||
|
- if (gnutls_certificate_type_get (tlsstate) != GNUTLS_CRT_X509)
|
||||||
|
- {
|
||||||
|
- mutt_error (_("Certificate is not X.509"));
|
||||||
|
- mutt_sleep (2);
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
+ gnutls_strerror (verify_ret));
|
||||||
|
|
||||||
|
- return status;
|
||||||
|
+ mutt_sleep (2);
|
||||||
|
+ return verify_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Returns 1 on success.
|
||||||
|
+ * 0 on failure.
|
||||||
|
+ */
|
||||||
|
static int tls_check_certificate (CONNECTION* conn)
|
||||||
|
{
|
||||||
|
tlssockdata *data = conn->sockdata;
|
||||||
|
@@ -1133,15 +1149,16 @@ static int tls_check_certificate (CONNECTION* conn)
|
||||||
|
gnutls_certificate_status_t certstat;
|
||||||
|
int certerr, i, preauthrc, savedcert, rc = 0;
|
||||||
|
int rcpeer = -1; /* the result of tls_check_preauth() on the peer's EE cert */
|
||||||
|
+ int rcsettrust;
|
||||||
|
|
||||||
|
- if (gnutls_auth_get_type (state) != GNUTLS_CRD_CERTIFICATE)
|
||||||
|
- {
|
||||||
|
- mutt_error (_("Unable to get certificate from peer"));
|
||||||
|
- mutt_sleep (2);
|
||||||
|
+ /* tls_verify_peers() calls gnutls_certificate_verify_peers2(),
|
||||||
|
+ * which verifies the auth_type is GNUTLS_CRD_CERTIFICATE
|
||||||
|
+ * and that get_certificate_type() for the server is GNUTLS_CRT_X509.
|
||||||
|
+ * If it returns 0, certstat will be set with failure codes for the first
|
||||||
|
+ * cert in the chain (from CA to host) with an error.
|
||||||
|
+ */
|
||||||
|
+ if (tls_verify_peers (state, &certstat) != 0)
|
||||||
|
return 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- certstat = tls_verify_peers (state);
|
||||||
|
|
||||||
|
cert_list = gnutls_certificate_get_peers (state, &cert_list_size);
|
||||||
|
if (!cert_list)
|
||||||
|
@@ -1184,12 +1201,15 @@ static int tls_check_certificate (CONNECTION* conn)
|
||||||
|
|
||||||
|
/* add signers to trust set, then reverify */
|
||||||
|
if (i && rc) {
|
||||||
|
- rc = gnutls_certificate_set_x509_trust_mem (data->xcred, &cert_list[i],
|
||||||
|
- GNUTLS_X509_FMT_DER);
|
||||||
|
- if (rc != 1)
|
||||||
|
- dprint (1, (debugfile, "error trusting certificate %d: %d\n", i, rc));
|
||||||
|
+ rcsettrust = gnutls_certificate_set_x509_trust_mem (data->xcred,
|
||||||
|
+ &cert_list[i],
|
||||||
|
+ GNUTLS_X509_FMT_DER);
|
||||||
|
+ if (rcsettrust != 1)
|
||||||
|
+ dprint (1, (debugfile, "error trusting certificate %d: %d\n", i, rcsettrust));
|
||||||
|
+
|
||||||
|
+ if (tls_verify_peers (state, &certstat) != 0)
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
- certstat = tls_verify_peers (state);
|
||||||
|
/* If the cert chain now verifies, and the peer's cert was otherwise
|
||||||
|
* valid (rcpeer==0), we are done.
|
||||||
|
*/
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
38
CVE-2020-14154-2.patch
Normal file
38
CVE-2020-14154-2.patch
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
From 5fccf603ebcf352ba783136d6b2d2600d811fb3b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin McCarthy <kevin@8t8.us>
|
||||||
|
Date: Fri, 5 Jun 2020 18:16:31 -0700
|
||||||
|
Subject: [PATCH] Abort GnuTLS certificate check if a cert in the chain is
|
||||||
|
rejected.
|
||||||
|
|
||||||
|
GnuTLS is not checking dates because we disabled that in
|
||||||
|
tls_negotiate().
|
||||||
|
|
||||||
|
So if we don't do this, rejecting an expired intermediate cert will
|
||||||
|
have no effect. Certstat won't contain an expiration error, and
|
||||||
|
tls_check_preauth() will only look at each subsequent cert in the
|
||||||
|
chain's dates.
|
||||||
|
---
|
||||||
|
mutt_ssl_gnutls.c | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/mutt_ssl_gnutls.c b/mutt_ssl_gnutls.c
|
||||||
|
index 19d47b3..6f98f50 100644
|
||||||
|
--- a/mutt_ssl_gnutls.c
|
||||||
|
+++ b/mutt_ssl_gnutls.c
|
||||||
|
@@ -1199,8 +1199,12 @@ static int tls_check_certificate (CONNECTION* conn)
|
||||||
|
rc = tls_check_one_certificate (&cert_list[i], certstat, conn->account.host,
|
||||||
|
i, cert_list_size);
|
||||||
|
|
||||||
|
+ /* Stop checking if the menu cert is aborted or rejected. */
|
||||||
|
+ if (!rc)
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
/* add signers to trust set, then reverify */
|
||||||
|
- if (i && rc) {
|
||||||
|
+ if (i) {
|
||||||
|
rcsettrust = gnutls_certificate_set_x509_trust_mem (data->xcred,
|
||||||
|
&cert_list[i],
|
||||||
|
GNUTLS_X509_FMT_DER);
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
67
CVE-2020-14154-3.patch
Normal file
67
CVE-2020-14154-3.patch
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
From f64ec1deefb67d471a642004e102cd1c501a1db3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kevin McCarthy <kevin@8t8.us>
|
||||||
|
Date: Sat, 6 Jun 2020 20:03:56 -0700
|
||||||
|
Subject: [PATCH] Fix GnuTLS interactive prompt short-circuiting.
|
||||||
|
|
||||||
|
tls_verify_peers() doesn't verify expiration dates. So aborting early
|
||||||
|
because of a 0 certstat and the leaf passing tls_check_preauth() does
|
||||||
|
not mean subsequent intermediate certs are okay: they could beexpired.
|
||||||
|
|
||||||
|
In the saved-cert preauth loop, instead of just noting the
|
||||||
|
tls_check_preauth() rc for the leaf, note the highest cert that passes
|
||||||
|
preauth.
|
||||||
|
|
||||||
|
Then, in the interactive loop (which goes in the opposite order, from
|
||||||
|
CA to leaf) check that value instead. Since we are trusting certs one
|
||||||
|
by one, anything that passed in the previous loop will certainly pass
|
||||||
|
the preauth check at the beginning of tls_check_one_certificate().
|
||||||
|
---
|
||||||
|
mutt_ssl_gnutls.c | 17 ++++++-----------
|
||||||
|
1 file changed, 6 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mutt_ssl_gnutls.c b/mutt_ssl_gnutls.c
|
||||||
|
index 6f98f50..09d628a 100644
|
||||||
|
--- a/mutt_ssl_gnutls.c
|
||||||
|
+++ b/mutt_ssl_gnutls.c
|
||||||
|
@@ -1148,7 +1148,7 @@ static int tls_check_certificate (CONNECTION* conn)
|
||||||
|
unsigned int cert_list_size = 0;
|
||||||
|
gnutls_certificate_status_t certstat;
|
||||||
|
int certerr, i, preauthrc, savedcert, rc = 0;
|
||||||
|
- int rcpeer = -1; /* the result of tls_check_preauth() on the peer's EE cert */
|
||||||
|
+ int max_preauth_pass = -1;
|
||||||
|
int rcsettrust;
|
||||||
|
|
||||||
|
/* tls_verify_peers() calls gnutls_certificate_verify_peers2(),
|
||||||
|
@@ -1176,13 +1176,8 @@ static int tls_check_certificate (CONNECTION* conn)
|
||||||
|
rc = tls_check_preauth(&cert_list[i], certstat, conn->account.host, i,
|
||||||
|
&certerr, &savedcert);
|
||||||
|
preauthrc += rc;
|
||||||
|
- if (i == 0)
|
||||||
|
- {
|
||||||
|
- /* This is the peer's end-entity X.509 certificate. Stash the result
|
||||||
|
- * to check later in this function.
|
||||||
|
- */
|
||||||
|
- rcpeer = rc;
|
||||||
|
- }
|
||||||
|
+ if (!preauthrc)
|
||||||
|
+ max_preauth_pass = i;
|
||||||
|
|
||||||
|
if (savedcert)
|
||||||
|
{
|
||||||
|
@@ -1214,10 +1209,10 @@ static int tls_check_certificate (CONNECTION* conn)
|
||||||
|
if (tls_verify_peers (state, &certstat) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
- /* If the cert chain now verifies, and the peer's cert was otherwise
|
||||||
|
- * valid (rcpeer==0), we are done.
|
||||||
|
+ /* If the cert chain now verifies, and all lower certs already
|
||||||
|
+ * passed preauth, we are done.
|
||||||
|
*/
|
||||||
|
- if (!certstat && !rcpeer)
|
||||||
|
+ if (!certstat && (max_preauth_pass >= i - 1))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
Name: mutt
|
Name: mutt
|
||||||
Version: 1.10.1
|
Version: 1.10.1
|
||||||
Release: 6
|
Release: 7
|
||||||
Epoch: 5
|
Epoch: 5
|
||||||
Summary: Text-based mail client
|
Summary: Text-based mail client
|
||||||
License: GPLv2+ and Public Domain
|
License: GPLv2+ and Public Domain
|
||||||
@ -19,6 +19,9 @@ Patch13: CVE-2020-28896.patch
|
|||||||
Patch14: CVE-2021-3181.patch
|
Patch14: CVE-2021-3181.patch
|
||||||
Patch15: backport-CVE-2020-14093-1.patch
|
Patch15: backport-CVE-2020-14093-1.patch
|
||||||
Patch16: backport-CVE-2020-14093-2.patch
|
Patch16: backport-CVE-2020-14093-2.patch
|
||||||
|
Patch17: CVE-2020-14154-1.patch
|
||||||
|
Patch18: CVE-2020-14154-2.patch
|
||||||
|
Patch19: CVE-2020-14154-3.patch
|
||||||
|
|
||||||
BuildRequires: gcc ncurses-devel gettext automake /usr/bin/xsltproc
|
BuildRequires: gcc ncurses-devel gettext automake /usr/bin/xsltproc
|
||||||
BuildRequires: lynx docbook-style-xsl perl-interpreter perl-generators
|
BuildRequires: lynx docbook-style-xsl perl-interpreter perl-generators
|
||||||
@ -123,6 +126,9 @@ ln -sf ./muttrc.5 %{buildroot}%{_mandir}/man5/muttrc.local.5
|
|||||||
%{_mandir}/man5/muttrc.*
|
%{_mandir}/man5/muttrc.*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
- Fri Oct 15 2021 yaoxin<yaoxin30@huawei.com> - 1.10.1-7
|
||||||
|
- fix CVE-2020-14154
|
||||||
|
|
||||||
- Tue Jul 27 2021 wangyue<wangyue92@huawei.com> - 1.10.1-6
|
- Tue Jul 27 2021 wangyue<wangyue92@huawei.com> - 1.10.1-6
|
||||||
- fix CVE-2020-14093
|
- fix CVE-2020-14093
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user