68 lines
2.4 KiB
Diff
68 lines
2.4 KiB
Diff
|
|
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
|
||
|
|
|