summaryrefslogtreecommitdiffstats
path: root/dirmngr/certcache.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2021-10-06 09:28:26 +0200
committerWerner Koch <wk@gnupg.org>2021-10-06 10:35:51 +0200
commit68799378859739887549108bf765568ccbc328bc (patch)
tree4ce96294848c1d180fac5ed813816cb9f5f4dd02 /dirmngr/certcache.c
parentagent,dirmngr,kbx,scd,tpm2d: Use gnupg_sleep. (diff)
downloadgnupg2-68799378859739887549108bf765568ccbc328bc.tar.xz
gnupg2-68799378859739887549108bf765568ccbc328bc.zip
dirmngr: Fix Let's Encrypt certificate chain validation.
* dirmngr/certcache.c (find_cert_bysubject): Return the first trusted certififcate if any. -- This is basically the same as using OpenSSL with ist X509_V_FLAG_TRUSTED_FIRST flag. See https://www.openssl.org/blog/blog/2021/09/13/LetsEncryptRootCertExpire/ GnuPG-bug-id: 5639
Diffstat (limited to 'dirmngr/certcache.c')
-rw-r--r--dirmngr/certcache.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/dirmngr/certcache.c b/dirmngr/certcache.c
index 4c2bf121f..a52801b38 100644
--- a/dirmngr/certcache.c
+++ b/dirmngr/certcache.c
@@ -1449,6 +1449,7 @@ find_cert_bysubject (ctrl_t ctrl, const char *subject_dn, ksba_sexp_t keyid)
gpg_error_t err;
int seq;
ksba_cert_t cert = NULL;
+ ksba_cert_t first; /* The first certificate found. */
cert_fetch_context_t context = NULL;
ksba_sexp_t subj;
@@ -1486,24 +1487,46 @@ find_cert_bysubject (ctrl_t ctrl, const char *subject_dn, ksba_sexp_t keyid)
}
/* Now check whether the certificate is cached. */
+ first = NULL;
+ subj = NULL;
for (seq=0; (cert = get_cert_bysubject (subject_dn, seq)); seq++)
{
- if (!keyid)
- break; /* No keyid requested, so return the first one found. */
- if (!ksba_cert_get_subj_key_id (cert, NULL, &subj)
- && !cmp_simple_canon_sexp (keyid, subj))
+ if (!keyid
+ || (!ksba_cert_get_subj_key_id (cert, NULL, &subj)
+ && !cmp_simple_canon_sexp (keyid, subj)))
{
xfree (subj);
+ subj = NULL;
if (DBG_LOOKUP)
log_debug ("%s: certificate found in the cache"
- " via subject DN\n", __func__);
- break; /* Found matching cert. */
+ " %sby subject DN\n", __func__, !keyid?"only ":"");
+
+ /* If this a trusted cert - then prefer it. */
+ if (!is_trusted_cert (cert, (CERTTRUST_CLASS_SYSTEM
+ | CERTTRUST_CLASS_CONFIG)))
+ {
+ ksba_cert_release (first);
+ first = cert;
+ cert = NULL;
+ /* We stop at the first trusted certificate and ignore
+ * any yet found non-trusted certificates. */
+ break;
+ }
+ else if (!first)
+ {
+ /* Not trusted. Save only the first one but continue
+ * the loop in case there is also a trusted one. */
+ ksba_cert_release (first);
+ first = cert;
+ cert = NULL;
+ }
}
xfree (subj);
+ subj = NULL;
ksba_cert_release (cert);
}
- if (cert)
- return cert; /* Done. */
+ if (first)
+ return first; /* Return the first found certificate. */
/* If we do not have a subject DN but have a keyid, try to locate it
* by keyid. */