* Get the better of two CRLs, and check for usable CRL info
*/
static certificate_t *get_better_crl(certificate_t *cand, certificate_t *best,
- x509_t *subject, x509_t *issuer, cert_validation_t *valid, bool cache)
+ x509_t *subject, cert_validation_t *valid, bool cache)
{
enumerator_t *enumerator;
time_t revocation, valid_until;
}
/**
- * validate a x509 certificate using CRL
+ * Find or fetch a certificate for a given crlIssuer
*/
-static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
- auth_cfg_t *auth)
+static cert_validation_t find_crl(x509_t *subject, identification_t *issuer,
+ certificate_t **best, bool *uri_found)
{
cert_validation_t valid = VALIDATION_SKIPPED;
- identification_t *keyid = NULL;
- certificate_t *best = NULL;
- certificate_t *current;
- public_key_t *public;
enumerator_t *enumerator;
- chunk_t chunk;
- char *uri = NULL;
+ certificate_t *current;
+ char *uri;
- /* derive the authorityKeyIdentifier from the issuer's public key */
- current = &issuer->interface;
- public = current->get_public_key(current);
- if (public && public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
+ /* find a cached crl */
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_X509_CRL, KEY_ANY, issuer, FALSE);
+ while (enumerator->enumerate(enumerator, ¤t))
{
- keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
-
- /* find a cached crl by authorityKeyIdentifier */
- enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
- CERT_X509_CRL, KEY_ANY, keyid, FALSE);
- while (enumerator->enumerate(enumerator, ¤t))
+ current->get_ref(current);
+ *best = get_better_crl(current, *best, subject, &valid, FALSE);
+ if (*best && valid != VALIDATION_STALE)
{
- current->get_ref(current);
- best = get_better_crl(current, best, subject, issuer,
- &valid, FALSE);
- if (best && valid != VALIDATION_STALE)
- {
- DBG1(DBG_CFG, " using cached crl");
- break;
- }
+ DBG1(DBG_CFG, " using cached crl");
+ break;
}
- enumerator->destroy(enumerator);
+ }
+ enumerator->destroy(enumerator);
- /* fallback to fetching crls from credential sets cdps */
- if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ /* fallback to fetching crls from credential sets cdps */
+ if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
+ CERT_X509_CRL, issuer);
+ while (enumerator->enumerate(enumerator, &uri))
{
- enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
- CERT_X509_CRL, keyid);
- while (enumerator->enumerate(enumerator, &uri))
+ *uri_found = TRUE;
+ current = fetch_crl(uri);
+ if (!current->has_issuer(current, issuer))
{
- current = fetch_crl(uri);
- if (current)
+ DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match CRL "
+ "issuer '%Y'", current->get_issuer(current), issuer);
+ current->destroy(current);
+ continue;
+ }
+ if (current)
+ {
+ *best = get_better_crl(current, *best, subject, &valid, TRUE);
+ if (*best && valid != VALIDATION_STALE)
{
- best = get_better_crl(current, best, subject, issuer,
- &valid, TRUE);
- if (best && valid != VALIDATION_STALE)
- {
- break;
- }
+ break;
}
}
- enumerator->destroy(enumerator);
}
- keyid->destroy(keyid);
+ enumerator->destroy(enumerator);
}
- DESTROY_IF(public);
+ return valid;
+}
+
+/**
+ * validate a x509 certificate using CRL
+ */
+static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
+ auth_cfg_t *auth)
+{
+ cert_validation_t valid = VALIDATION_SKIPPED;
+ identification_t *id;
+ certificate_t *best = NULL;
+ bool uri_found = FALSE;
+ certificate_t *current;
+ enumerator_t *enumerator;
+ chunk_t chunk;
+ char *uri;
+
+ /* use issuers subjectKeyIdentifier to find a cached CRL / fetch from CDP */
+ chunk = issuer->get_subjectKeyIdentifier(issuer);
+ if (chunk.len)
+ {
+ id = identification_create_from_encoding(ID_KEY_ID, chunk);
+ valid = find_crl(subject, id, &best, &uri_found);
+ id->destroy(id);
+ }
+
+ /* find a cached CRL or fetch via configured CDP via CRLIssuer */
+ enumerator = subject->create_crl_uri_enumerator(subject);
+ while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
+ enumerator->enumerate(enumerator, &uri, &id))
+ {
+ if (id)
+ {
+ valid = find_crl(subject, id, &best, &uri_found);
+ }
+ }
+ enumerator->destroy(enumerator);
- /* fallback to fetching crls from cdps from subject's certificate */
+ /* fallback to fetching CRLs from CDPs found in subjects certificate */
if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
{
enumerator = subject->create_crl_uri_enumerator(subject);
- while (enumerator->enumerate(enumerator, &uri, NULL))
+ while (enumerator->enumerate(enumerator, &uri, &id))
{
+ uri_found = TRUE;
current = fetch_crl(uri);
if (current)
{
- best = get_better_crl(current, best, subject, issuer,
- &valid, TRUE);
+ if (id && !current->has_issuer(current, id))
+ {
+ DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match "
+ "certificates CRL issuer '%Y'",
+ current->get_issuer(current), id);
+ current->destroy(current);
+ continue;
+ }
+ best = get_better_crl(current, best, subject, &valid, TRUE);
if (best && valid != VALIDATION_STALE)
{
break;
}
/* an uri was found, but no result. switch validation state to failed */
- if (valid == VALIDATION_SKIPPED && uri)
+ if (valid == VALIDATION_SKIPPED && uri_found)
{
valid = VALIDATION_FAILED;
}