diff options
author | Werner Koch <wk@gnupg.org> | 2021-10-06 09:28:26 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2021-10-06 10:35:51 +0200 |
commit | 68799378859739887549108bf765568ccbc328bc (patch) | |
tree | 4ce96294848c1d180fac5ed813816cb9f5f4dd02 /dirmngr/certcache.c | |
parent | agent,dirmngr,kbx,scd,tpm2d: Use gnupg_sleep. (diff) | |
download | gnupg2-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.c | 39 |
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. */ |