revocation: Make sure issuer of fetched CRL matches that of the certificate

Unless there is a cRLIssuer listed in the CDP, the CRL should be issued
by the same issuer as the checked certificate.

Fixes #2608.
This commit is contained in:
Tobias Brunner
2018-04-12 15:45:24 +02:00
parent 85bfab621d
commit 21553276a3
@@ -578,6 +578,31 @@ static cert_validation_t find_crl(x509_t *subject, identification_t *issuer,
return valid; return valid;
} }
/**
* Check if the issuer of the given CRL matches
*/
static bool check_issuer(certificate_t *crl, x509_t *issuer, x509_cdp_t *cdp)
{
certificate_t *cissuer = (certificate_t*)issuer;
identification_t *id;
chunk_t chunk;
bool matches = FALSE;
if (cdp->issuer)
{
return crl->has_issuer(crl, cdp->issuer);
}
/* check SKI/AKI first, but fall back to DN matching */
chunk = issuer->get_subjectKeyIdentifier(issuer);
if (chunk.len)
{
id = identification_create_from_encoding(ID_KEY_ID, chunk);
matches = crl->has_issuer(crl, id);
id->destroy(id);
}
return matches || crl->has_issuer(crl, cissuer->get_subject(cissuer));
}
/** /**
* Look for a delta CRL for a given base CRL * Look for a delta CRL for a given base CRL
*/ */
@@ -585,7 +610,7 @@ static cert_validation_t check_delta_crl(x509_t *subject, x509_t *issuer,
crl_t *base, cert_validation_t base_valid) crl_t *base, cert_validation_t base_valid)
{ {
cert_validation_t valid = VALIDATION_SKIPPED; cert_validation_t valid = VALIDATION_SKIPPED;
certificate_t *best = NULL, *current; certificate_t *best = NULL, *current, *cissuer = (certificate_t*)issuer;
enumerator_t *enumerator; enumerator_t *enumerator;
identification_t *id; identification_t *id;
x509_cdp_t *cdp; x509_cdp_t *cdp;
@@ -621,11 +646,12 @@ static cert_validation_t check_delta_crl(x509_t *subject, x509_t *issuer,
current = fetch_crl(cdp->uri); current = fetch_crl(cdp->uri);
if (current) if (current)
{ {
if (cdp->issuer && !current->has_issuer(current, cdp->issuer)) if (!check_issuer(current, issuer, cdp))
{ {
DBG1(DBG_CFG, "issuer of fetched delta CRL '%Y' does not match " DBG1(DBG_CFG, "issuer of fetched delta CRL '%Y' does not match "
"certificates CRL issuer '%Y'", "certificate's %sissuer '%Y'",
current->get_issuer(current), cdp->issuer); current->get_issuer(current), cdp->issuer ? "CRL " : "",
cdp->issuer ?: cissuer->get_subject(cissuer));
current->destroy(current); current->destroy(current);
continue; continue;
} }
@@ -653,7 +679,7 @@ static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
auth_cfg_t *auth) auth_cfg_t *auth)
{ {
cert_validation_t valid = VALIDATION_SKIPPED; cert_validation_t valid = VALIDATION_SKIPPED;
certificate_t *best = NULL; certificate_t *best = NULL, *cissuer = (certificate_t*)issuer;
identification_t *id; identification_t *id;
x509_cdp_t *cdp; x509_cdp_t *cdp;
bool uri_found = FALSE; bool uri_found = FALSE;
@@ -692,11 +718,12 @@ static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
current = fetch_crl(cdp->uri); current = fetch_crl(cdp->uri);
if (current) if (current)
{ {
if (cdp->issuer && !current->has_issuer(current, cdp->issuer)) if (!check_issuer(current, issuer, cdp))
{ {
DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match " DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match "
"certificates CRL issuer '%Y'", "certificate's %sissuer '%Y'",
current->get_issuer(current), cdp->issuer); current->get_issuer(current), cdp->issuer ? "CRL " : "",
cdp->issuer ?: cissuer->get_subject(cissuer));
current->destroy(current); current->destroy(current);
continue; continue;
} }