diff options
Diffstat (limited to 'src/libstrongswan/credentials/credential_manager.c')
-rw-r--r-- | src/libstrongswan/credentials/credential_manager.c | 531 |
1 files changed, 0 insertions, 531 deletions
diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c index 8df232b30..3b671c71f 100644 --- a/src/libstrongswan/credentials/credential_manager.c +++ b/src/libstrongswan/credentials/credential_manager.c @@ -20,15 +20,10 @@ #include <threading/thread_value.h> #include <threading/mutex.h> #include <threading/rwlock.h> -#include <selectors/traffic_selector.h> #include <utils/linked_list.h> #include <credentials/sets/cert_cache.h> #include <credentials/sets/auth_cfg_wrapper.h> -#include <credentials/sets/ocsp_response_wrapper.h> #include <credentials/certificates/x509.h> -#include <credentials/certificates/crl.h> -#include <credentials/certificates/ocsp_request.h> -#include <credentials/certificates/ocsp_response.h> /** * Maximum length of a certificate trust chain @@ -452,492 +447,6 @@ static void cache_queue(private_credential_manager_t *this) } /** - * forward declaration - */ -static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this, - key_type_t type, identification_t *id, bool online); - -/** - * Do an OCSP request - */ -static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url, - certificate_t *subject, certificate_t *issuer) -{ - certificate_t *request, *response; - chunk_t send, receive; - - /* TODO: requestor name, signature */ - request = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST, - BUILD_CA_CERT, issuer, - BUILD_CERT, subject, BUILD_END); - if (!request) - { - DBG1(DBG_CFG, "generating ocsp request failed"); - return NULL; - } - - send = request->get_encoding(request); - request->destroy(request); - - DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url); - if (lib->fetcher->fetch(lib->fetcher, url, &receive, - FETCH_REQUEST_DATA, send, - FETCH_REQUEST_TYPE, "application/ocsp-request", - FETCH_END) != SUCCESS) - { - DBG1(DBG_CFG, "ocsp request to %s failed", url); - chunk_free(&send); - return NULL; - } - chunk_free(&send); - - response = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE, - BUILD_BLOB_ASN1_DER, receive, BUILD_END); - chunk_free(&receive); - if (!response) - { - DBG1(DBG_CFG, "parsing ocsp response failed"); - return NULL; - } - return response; -} - -/** - * check the signature of an OCSP response - */ -static bool verify_ocsp(private_credential_manager_t *this, - ocsp_response_t *response) -{ - certificate_t *issuer, *subject; - identification_t *responder; - ocsp_response_wrapper_t *wrapper; - enumerator_t *enumerator; - bool verified = FALSE; - - wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); - add_local_set(this, &wrapper->set); - - subject = &response->certificate; - responder = subject->get_issuer(subject); - enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) - { - if (this->cache->issued_by(this->cache, subject, issuer)) - { - DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"", - issuer->get_subject(issuer)); - verified = TRUE; - break; - } - } - enumerator->destroy(enumerator); - - remove_local_set(this, &wrapper->set); - wrapper->destroy(wrapper); - return verified; -} - -/** - * Get the better of two OCSP responses, and check for usable OCSP info - */ -static certificate_t *get_better_ocsp(private_credential_manager_t *this, - certificate_t *cand, certificate_t *best, - x509_t *subject, x509_t *issuer, - cert_validation_t *valid, bool cache) -{ - ocsp_response_t *response; - time_t revocation, this_update, next_update, valid_until; - crl_reason_t reason; - bool revoked = FALSE; - - response = (ocsp_response_t*)cand; - - /* check ocsp signature */ - if (!verify_ocsp(this, response)) - { - DBG1(DBG_CFG, "ocsp response verification failed"); - cand->destroy(cand); - return best; - } - /* check if response contains our certificate */ - switch (response->get_status(response, subject, issuer, &revocation, &reason, - &this_update, &next_update)) - { - case VALIDATION_REVOKED: - /* subject has been revoked by a valid OCSP response */ - DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", - &revocation, TRUE, crl_reason_names, reason); - revoked = TRUE; - break; - case VALIDATION_GOOD: - /* results in either good or stale */ - break; - default: - case VALIDATION_FAILED: - /* candidate unusable, does not contain our cert */ - DBG1(DBG_CFG, " ocsp response contains no status on our certificate"); - cand->destroy(cand); - return best; - } - - /* select the better of the two responses */ - if (best == NULL || certificate_is_newer(cand, best)) - { - DESTROY_IF(best); - best = cand; - if (best->get_validity(best, NULL, NULL, &valid_until)) - { - DBG1(DBG_CFG, " ocsp response is valid: until %T", - &valid_until, FALSE); - *valid = VALIDATION_GOOD; - if (cache) - { /* cache non-stale only, stale certs get refetched */ - cache_cert(this, best); - } - } - else - { - DBG1(DBG_CFG, " ocsp response is stale: since %T", - &valid_until, FALSE); - *valid = VALIDATION_STALE; - } - } - else - { - *valid = VALIDATION_STALE; - cand->destroy(cand); - } - if (revoked) - { /* revoked always counts, even if stale */ - *valid = VALIDATION_REVOKED; - } - return best; -} - -/** - * validate a x509 certificate using OCSP - */ -static cert_validation_t check_ocsp(private_credential_manager_t *this, - x509_t *subject, x509_t *issuer, - auth_cfg_t *auth) -{ - enumerator_t *enumerator; - cert_validation_t valid = VALIDATION_SKIPPED; - certificate_t *best = NULL, *current; - identification_t *keyid = NULL; - public_key_t *public; - chunk_t chunk; - char *uri = NULL; - - /** lookup cache for valid OCSP responses */ - enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE, - KEY_ANY, NULL, FALSE); - while (enumerator->enumerate(enumerator, ¤t)) - { - current->get_ref(current); - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, FALSE); - if (best && valid != VALIDATION_STALE) - { - DBG1(DBG_CFG, " using cached ocsp response"); - break; - } - } - enumerator->destroy(enumerator); - - /* derive the authorityKeyIdentifier from the issuer's public key */ - current = &issuer->interface; - public = current->get_public_key(current); - if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) - { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); - } - /** fetch from configured OCSP responder URLs */ - if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid); - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_ocsp(this, uri, &subject->interface, - &issuer->interface); - if (current) - { - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - DESTROY_IF(public); - DESTROY_IF(keyid); - - /* fallback to URL fetching from subject certificate's URIs */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = subject->create_ocsp_uri_enumerator(subject); - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_ocsp(this, uri, &subject->interface, - &issuer->interface); - if (current) - { - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - /* an uri was found, but no result. switch validation state to failed */ - if (valid == VALIDATION_SKIPPED && uri) - { - valid = VALIDATION_FAILED; - } - if (auth) - { - auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid); - if (valid == VALIDATION_GOOD) - { /* successful OCSP check fulfills also CRL constraint */ - auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD); - } - } - DESTROY_IF(best); - return valid; -} - -/** - * fetch a CRL from an URL - */ -static certificate_t* fetch_crl(private_credential_manager_t *this, char *url) -{ - certificate_t *crl; - chunk_t chunk; - - DBG1(DBG_CFG, " fetching crl from '%s' ...", url); - if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS) - { - DBG1(DBG_CFG, "crl fetching failed"); - return NULL; - } - crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, - BUILD_BLOB_ASN1_DER, chunk, BUILD_END); - chunk_free(&chunk); - if (!crl) - { - DBG1(DBG_CFG, "crl fetched successfully but parsing failed"); - return NULL; - } - return crl; -} - -/** - * check the signature of an CRL - */ -static bool verify_crl(private_credential_manager_t *this, certificate_t *crl) -{ - certificate_t *issuer; - enumerator_t *enumerator; - bool verified = FALSE; - - enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl), - FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) - { - if (this->cache->issued_by(this->cache, crl, issuer)) - { - DBG1(DBG_CFG, " crl correctly signed by \"%Y\"", - issuer->get_subject(issuer)); - verified = TRUE; - break; - } - } - enumerator->destroy(enumerator); - - return verified; -} - -/** - * Get the better of two CRLs, and check for usable CRL info - */ -static certificate_t *get_better_crl(private_credential_manager_t *this, - certificate_t *cand, certificate_t *best, - x509_t *subject, x509_t *issuer, - cert_validation_t *valid, bool cache) -{ - enumerator_t *enumerator; - time_t revocation, valid_until; - crl_reason_t reason; - chunk_t serial; - crl_t *crl; - - /* check CRL signature */ - if (!verify_crl(this, cand)) - { - DBG1(DBG_CFG, "crl response verification failed"); - cand->destroy(cand); - return best; - } - - crl = (crl_t*)cand; - enumerator = crl->create_enumerator(crl); - while (enumerator->enumerate(enumerator, &serial, &revocation, &reason)) - { - if (chunk_equals(serial, subject->get_serial(subject))) - { - DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", - &revocation, TRUE, crl_reason_names, reason); - *valid = VALIDATION_REVOKED; - enumerator->destroy(enumerator); - DESTROY_IF(best); - return cand; - } - } - enumerator->destroy(enumerator); - - /* select the better of the two CRLs */ - if (best == NULL || crl_is_newer(crl, (crl_t*)best)) - { - DESTROY_IF(best); - best = cand; - if (best->get_validity(best, NULL, NULL, &valid_until)) - { - DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE); - *valid = VALIDATION_GOOD; - if (cache) - { /* we cache non-stale crls only, as a stale crls are refetched */ - cache_cert(this, best); - } - } - else - { - DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE); - *valid = VALIDATION_STALE; - } - } - else - { - *valid = VALIDATION_STALE; - cand->destroy(cand); - } - return best; -} - -/** - * validate a x509 certificate using CRL - */ -static cert_validation_t check_crl(private_credential_manager_t *this, - x509_t *subject, x509_t *issuer, - auth_cfg_t *auth) -{ - 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; - - /* derive the authorityKeyIdentifier from the issuer's public key */ - current = &issuer->interface; - public = current->get_public_key(current); - if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) - { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); - - /* find a cached crl by authorityKeyIdentifier */ - enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY, - keyid, FALSE); - while (enumerator->enumerate(enumerator, ¤t)) - { - current->get_ref(current); - best = get_better_crl(this, current, best, subject, issuer, - &valid, FALSE); - if (best && valid != VALIDATION_STALE) - { - DBG1(DBG_CFG, " using cached crl"); - break; - } - } - enumerator->destroy(enumerator); - - /* fallback to fetching crls from credential sets cdps */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid); - - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_crl(this, uri); - if (current) - { - best = get_better_crl(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - keyid->destroy(keyid); - } - DESTROY_IF(public); - - /* fallback to fetching crls from cdps from subject's certificate */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = subject->create_crl_uri_enumerator(subject); - - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_crl(this, uri); - if (current) - { - best = get_better_crl(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - - /* an uri was found, but no result. switch validation state to failed */ - if (valid == VALIDATION_SKIPPED && uri) - { - valid = VALIDATION_FAILED; - } - if (auth) - { - if (valid == VALIDATION_SKIPPED) - { /* if we skipped CRL validation, we use the result of OCSP for - * constraint checking */ - auth->add(auth, AUTH_RULE_CRL_VALIDATION, - auth->get(auth, AUTH_RULE_OCSP_VALIDATION)); - } - else - { - auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid); - } - } - DESTROY_IF(best); - return valid; -} - -/** * check a certificate for its lifetime */ static bool check_certificate(private_credential_manager_t *this, @@ -976,46 +485,6 @@ static bool check_certificate(private_credential_manager_t *this, pathlen, pathlen_constraint); return FALSE; } - - if (online) - { - DBG1(DBG_CFG, "checking certificate status of \"%Y\"", - subject->get_subject(subject)); - switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth)) - { - case VALIDATION_GOOD: - DBG1(DBG_CFG, "certificate status is good"); - return TRUE; - case VALIDATION_REVOKED: - /* has already been logged */ - return FALSE; - case VALIDATION_SKIPPED: - DBG2(DBG_CFG, "ocsp check skipped, no ocsp found"); - break; - case VALIDATION_STALE: - DBG1(DBG_CFG, "ocsp information stale, fallback to crl"); - break; - case VALIDATION_FAILED: - DBG1(DBG_CFG, "ocsp check failed, fallback to crl"); - break; - } - switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth)) - { - case VALIDATION_GOOD: - DBG1(DBG_CFG, "certificate status is good"); - return TRUE; - case VALIDATION_REVOKED: - /* has already been logged */ - return FALSE; - case VALIDATION_FAILED: - case VALIDATION_SKIPPED: - DBG1(DBG_CFG, "certificate status is not available"); - break; - case VALIDATION_STALE: - DBG1(DBG_CFG, "certificate status is unknown, crl is stale"); - break; - } - } } enumerator = this->validators->create_enumerator(this->validators); |