summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/revocation/revocation_validator.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/revocation/revocation_validator.c')
-rw-r--r--src/libstrongswan/plugins/revocation/revocation_validator.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.c b/src/libstrongswan/plugins/revocation/revocation_validator.c
index 29d2bc128..dc8b849c7 100644
--- a/src/libstrongswan/plugins/revocation/revocation_validator.c
+++ b/src/libstrongswan/plugins/revocation/revocation_validator.c
@@ -93,12 +93,20 @@ static certificate_t *fetch_ocsp(char *url, certificate_t *subject,
/**
* check the signature of an OCSP response
*/
+<<<<<<< HEAD
static bool verify_ocsp(ocsp_response_t *response)
+=======
+static bool verify_ocsp(ocsp_response_t *response, auth_cfg_t *auth)
+>>>>>>> upstream/4.5.1
{
certificate_t *issuer, *subject;
identification_t *responder;
ocsp_response_wrapper_t *wrapper;
enumerator_t *enumerator;
+<<<<<<< HEAD
+=======
+ auth_cfg_t *current;
+>>>>>>> upstream/4.5.1
bool verified = FALSE;
wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
@@ -108,12 +116,23 @@ static bool verify_ocsp(ocsp_response_t *response)
responder = subject->get_issuer(subject);
enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
KEY_ANY, responder, FALSE);
+<<<<<<< HEAD
while (enumerator->enumerate(enumerator, &issuer, NULL))
+=======
+ while (enumerator->enumerate(enumerator, &issuer, &current))
+>>>>>>> upstream/4.5.1
{
if (lib->credmgr->issued_by(lib->credmgr, subject, issuer))
{
DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
issuer->get_subject(issuer));
+<<<<<<< HEAD
+=======
+ if (auth)
+ {
+ auth->merge(auth, current, FALSE);
+ }
+>>>>>>> upstream/4.5.1
verified = TRUE;
break;
}
@@ -129,7 +148,12 @@ static bool verify_ocsp(ocsp_response_t *response)
* Get the better of two OCSP responses, and check for usable OCSP info
*/
static certificate_t *get_better_ocsp(certificate_t *cand, certificate_t *best,
+<<<<<<< HEAD
x509_t *subject, x509_t *issuer, cert_validation_t *valid, bool cache)
+=======
+ x509_t *subject, x509_t *issuer, cert_validation_t *valid,
+ auth_cfg_t *auth, bool cache)
+>>>>>>> upstream/4.5.1
{
ocsp_response_t *response;
time_t revocation, this_update, next_update, valid_until;
@@ -139,7 +163,11 @@ static certificate_t *get_better_ocsp(certificate_t *cand, certificate_t *best,
response = (ocsp_response_t*)cand;
/* check ocsp signature */
+<<<<<<< HEAD
if (!verify_ocsp(response))
+=======
+ if (!verify_ocsp(response, auth))
+>>>>>>> upstream/4.5.1
{
DBG1(DBG_CFG, "ocsp response verification failed");
cand->destroy(cand);
@@ -220,7 +248,12 @@ static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer,
while (enumerator->enumerate(enumerator, &current))
{
current->get_ref(current);
+<<<<<<< HEAD
best = get_better_ocsp(current, best, subject, issuer, &valid, FALSE);
+=======
+ best = get_better_ocsp(current, best, subject, issuer,
+ &valid, auth, FALSE);
+>>>>>>> upstream/4.5.1
if (best && valid != VALIDATION_STALE)
{
DBG1(DBG_CFG, " using cached ocsp response");
@@ -247,7 +280,11 @@ static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer,
if (current)
{
best = get_better_ocsp(current, best, subject, issuer,
+<<<<<<< HEAD
&valid, TRUE);
+=======
+ &valid, auth, TRUE);
+>>>>>>> upstream/4.5.1
if (best && valid != VALIDATION_STALE)
{
break;
@@ -269,7 +306,11 @@ static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer,
if (current)
{
best = get_better_ocsp(current, best, subject, issuer,
+<<<<<<< HEAD
&valid, TRUE);
+=======
+ &valid, auth, TRUE);
+>>>>>>> upstream/4.5.1
if (best && valid != VALIDATION_STALE)
{
break;
@@ -323,20 +364,39 @@ static certificate_t* fetch_crl(char *url)
/**
* check the signature of an CRL
*/
+<<<<<<< HEAD
static bool verify_crl(certificate_t *crl)
+=======
+static bool verify_crl(certificate_t *crl, auth_cfg_t *auth)
+>>>>>>> upstream/4.5.1
{
certificate_t *issuer;
enumerator_t *enumerator;
bool verified = FALSE;
+<<<<<<< HEAD
enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
KEY_ANY, crl->get_issuer(crl), FALSE);
while (enumerator->enumerate(enumerator, &issuer, NULL))
+=======
+ auth_cfg_t *current;
+
+ enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
+ KEY_ANY, crl->get_issuer(crl), FALSE);
+ while (enumerator->enumerate(enumerator, &issuer, &current))
+>>>>>>> upstream/4.5.1
{
if (lib->credmgr->issued_by(lib->credmgr, crl, issuer))
{
DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
issuer->get_subject(issuer));
+<<<<<<< HEAD
+=======
+ if (auth)
+ {
+ auth->merge(auth, current, FALSE);
+ }
+>>>>>>> upstream/4.5.1
verified = TRUE;
break;
}
@@ -350,23 +410,56 @@ static bool verify_crl(certificate_t *crl)
* Get the better of two CRLs, and check for usable CRL info
*/
static certificate_t *get_better_crl(certificate_t *cand, certificate_t *best,
+<<<<<<< HEAD
x509_t *subject, x509_t *issuer, cert_validation_t *valid, bool cache)
+=======
+ x509_t *subject, cert_validation_t *valid, auth_cfg_t *auth,
+ bool cache, crl_t *base)
+>>>>>>> upstream/4.5.1
{
enumerator_t *enumerator;
time_t revocation, valid_until;
crl_reason_t reason;
chunk_t serial;
+<<<<<<< HEAD
crl_t *crl;
/* check CRL signature */
if (!verify_crl(cand))
+=======
+ crl_t *crl = (crl_t*)cand;
+
+ if (base)
+ {
+ if (!crl->is_delta_crl(crl, &serial) ||
+ !chunk_equals(serial, base->get_serial(base)))
+ {
+ cand->destroy(cand);
+ return best;
+ }
+ }
+ else
+ {
+ if (crl->is_delta_crl(crl, NULL))
+ {
+ cand->destroy(cand);
+ return best;
+ }
+ }
+
+ /* check CRL signature */
+ if (!verify_crl(cand, auth))
+>>>>>>> upstream/4.5.1
{
DBG1(DBG_CFG, "crl response verification failed");
cand->destroy(cand);
return best;
}
+<<<<<<< HEAD
crl = (crl_t*)cand;
+=======
+>>>>>>> upstream/4.5.1
enumerator = crl->create_enumerator(crl);
while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
{
@@ -411,6 +504,7 @@ static certificate_t *get_better_crl(certificate_t *cand, certificate_t *best,
}
/**
+<<<<<<< HEAD
* validate a x509 certificate using CRL
*/
static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
@@ -484,6 +578,193 @@ static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
{
best = get_better_crl(current, best, subject, issuer,
&valid, TRUE);
+=======
+ * Find or fetch a certificate for a given crlIssuer
+ */
+static cert_validation_t find_crl(x509_t *subject, identification_t *issuer,
+ auth_cfg_t *auth, crl_t *base,
+ certificate_t **best, bool *uri_found)
+{
+ cert_validation_t valid = VALIDATION_SKIPPED;
+ enumerator_t *enumerator;
+ certificate_t *current;
+ char *uri;
+
+ /* find a cached (delta) crl */
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_X509_CRL, KEY_ANY, issuer, FALSE);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ current->get_ref(current);
+ *best = get_better_crl(current, *best, subject, &valid,
+ auth, FALSE, base);
+ if (*best && valid != VALIDATION_STALE)
+ {
+ DBG1(DBG_CFG, " using cached crl");
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* fallback to fetching crls from credential sets cdps */
+ if (!base && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
+ CERT_X509_CRL, issuer);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ *uri_found = TRUE;
+ current = fetch_crl(uri);
+ if (current)
+ {
+ if (!current->has_issuer(current, issuer))
+ {
+ DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match CRL "
+ "issuer '%Y'", current->get_issuer(current), issuer);
+ current->destroy(current);
+ continue;
+ }
+ *best = get_better_crl(current, *best, subject,
+ &valid, auth, TRUE, base);
+ if (*best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return valid;
+}
+
+/**
+ * Look for a delta CRL for a given base CRL
+ */
+static cert_validation_t check_delta_crl(x509_t *subject, x509_t *issuer,
+ crl_t *base, cert_validation_t base_valid, auth_cfg_t *auth)
+{
+ cert_validation_t valid = VALIDATION_SKIPPED;
+ certificate_t *best = NULL, *current;
+ enumerator_t *enumerator;
+ identification_t *id;
+ x509_cdp_t *cdp;
+ chunk_t chunk;
+ bool uri;
+
+ /* find cached delta CRL via subjectKeyIdentifier */
+ chunk = issuer->get_subjectKeyIdentifier(issuer);
+ if (chunk.len)
+ {
+ id = identification_create_from_encoding(ID_KEY_ID, chunk);
+ valid = find_crl(subject, id, auth, base, &best, &uri);
+ id->destroy(id);
+ }
+
+ /* find delta CRL by CRLIssuer */
+ enumerator = subject->create_crl_uri_enumerator(subject);
+ while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
+ enumerator->enumerate(enumerator, &cdp))
+ {
+ if (cdp->issuer)
+ {
+ valid = find_crl(subject, cdp->issuer, auth, base, &best, &uri);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* fetch from URIs found in Freshest CRL extension */
+ enumerator = base->create_delta_crl_uri_enumerator(base);
+ while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
+ enumerator->enumerate(enumerator, &cdp))
+ {
+ current = fetch_crl(cdp->uri);
+ if (current)
+ {
+ if (cdp->issuer && !current->has_issuer(current, cdp->issuer))
+ {
+ DBG1(DBG_CFG, "issuer of fetched delta CRL '%Y' does not match "
+ "certificates CRL issuer '%Y'",
+ current->get_issuer(current), cdp->issuer);
+ current->destroy(current);
+ continue;
+ }
+ best = get_better_crl(current, best, subject, &valid,
+ auth, TRUE, base);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (best)
+ {
+ best->destroy(best);
+ return valid;
+ }
+ return base_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;
+ certificate_t *best = NULL;
+ identification_t *id;
+ x509_cdp_t *cdp;
+ bool uri_found = FALSE;
+ certificate_t *current;
+ enumerator_t *enumerator;
+ chunk_t chunk;
+
+ /* 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, auth, NULL, &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, &cdp))
+ {
+ if (cdp->issuer)
+ {
+ valid = find_crl(subject, cdp->issuer, auth, NULL,
+ &best, &uri_found);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* 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, &cdp))
+ {
+ uri_found = TRUE;
+ current = fetch_crl(cdp->uri);
+ if (current)
+ {
+ if (cdp->issuer && !current->has_issuer(current, cdp->issuer))
+ {
+ DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match "
+ "certificates CRL issuer '%Y'",
+ current->get_issuer(current), cdp->issuer);
+ current->destroy(current);
+ continue;
+ }
+ best = get_better_crl(current, best, subject, &valid,
+ auth, TRUE, NULL);
+>>>>>>> upstream/4.5.1
if (best && valid != VALIDATION_STALE)
{
break;
@@ -493,8 +774,19 @@ static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
enumerator->destroy(enumerator);
}
+<<<<<<< HEAD
/* an uri was found, but no result. switch validation state to failed */
if (valid == VALIDATION_SKIPPED && uri)
+=======
+ /* look for delta CRLs */
+ if (best && (valid == VALIDATION_GOOD || valid == VALIDATION_STALE))
+ {
+ valid = check_delta_crl(subject, issuer, (crl_t*)best, valid, auth);
+ }
+
+ /* an uri was found, but no result. switch validation state to failed */
+ if (valid == VALIDATION_SKIPPED && uri_found)
+>>>>>>> upstream/4.5.1
{
valid = VALIDATION_FAILED;
}
@@ -517,7 +809,12 @@ static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
METHOD(cert_validator_t, validate, bool,
private_revocation_validator_t *this, certificate_t *subject,
+<<<<<<< HEAD
certificate_t *issuer, bool online, int pathlen, auth_cfg_t *auth)
+=======
+ certificate_t *issuer, bool online, u_int pathlen, bool anchor,
+ auth_cfg_t *auth)
+>>>>>>> upstream/4.5.1
{
if (subject->get_type(subject) == CERT_X509 &&
issuer->get_type(issuer) == CERT_X509 &&
@@ -525,7 +822,12 @@ METHOD(cert_validator_t, validate, bool,
{
DBG1(DBG_CFG, "checking certificate status of \"%Y\"",
subject->get_subject(subject));
+<<<<<<< HEAD
switch (check_ocsp((x509_t*)subject, (x509_t*)issuer, auth))
+=======
+ switch (check_ocsp((x509_t*)subject, (x509_t*)issuer,
+ pathlen ? NULL : auth))
+>>>>>>> upstream/4.5.1
{
case VALIDATION_GOOD:
DBG1(DBG_CFG, "certificate status is good");
@@ -543,7 +845,12 @@ METHOD(cert_validator_t, validate, bool,
DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
break;
}
+<<<<<<< HEAD
switch (check_crl((x509_t*)subject, (x509_t*)issuer, auth))
+=======
+ switch (check_crl((x509_t*)subject, (x509_t*)issuer,
+ pathlen ? NULL : auth))
+>>>>>>> upstream/4.5.1
{
case VALIDATION_GOOD:
DBG1(DBG_CFG, "certificate status is good");