diff options
author | Martin Willi <martin@strongswan.org> | 2008-03-26 15:21:50 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2008-03-26 15:21:50 +0000 |
commit | 7b88a983d8dfb6fa8137bcc53d0e97054cfb18fe (patch) | |
tree | c2a7356d574958d2dc9839ab421f47a6bdabe64c | |
parent | 391abda0828ea4d7bd1b9e9f81ff7b3108e65c4d (diff) | |
download | strongswan-7b88a983d8dfb6fa8137bcc53d0e97054cfb18fe.tar.bz2 strongswan-7b88a983d8dfb6fa8137bcc53d0e97054cfb18fe.tar.xz |
caching of ocsp responses (experimental), no crl caching yet
-rw-r--r-- | src/charon/credentials/credential_manager.c | 317 | ||||
-rw-r--r-- | src/charon/credentials/sets/cert_cache.c | 5 | ||||
-rw-r--r-- | src/libstrongswan/Makefile.am | 2 | ||||
-rw-r--r-- | src/libstrongswan/credentials/certificates/ac.h | 2 | ||||
-rw-r--r-- | src/libstrongswan/credentials/certificates/certificate.c | 10 | ||||
-rw-r--r-- | src/libstrongswan/credentials/certificates/certificate.h | 19 | ||||
-rw-r--r-- | src/libstrongswan/credentials/certificates/ocsp_request.c | 19 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ac.c | 10 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_cert.c | 11 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_crl.c | 34 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ocsp_request.c | 5 | ||||
-rw-r--r-- | src/libstrongswan/plugins/x509/x509_ocsp_response.c | 58 |
12 files changed, 205 insertions, 287 deletions
diff --git a/src/charon/credentials/credential_manager.c b/src/charon/credentials/credential_manager.c index 34a801e85..35816a820 100644 --- a/src/charon/credentials/credential_manager.c +++ b/src/charon/credentials/credential_manager.c @@ -331,6 +331,7 @@ static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url, request->destroy(request); DBG1(DBG_CFG, "requesting ocsp status from '%s' ...", url); + /* TODO: unlock manager while fetching? */ if (lib->fetcher->fetch(lib->fetcher, url, &receive, FETCH_REQUEST_DATA, send, FETCH_REQUEST_TYPE, "application/ocsp-request", @@ -350,50 +351,111 @@ static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url, DBG1(DBG_CFG, "parsing ocsp response failed"); return NULL; } + return response; +} + +/** + * check the signature of an OCSP response + */ +static bool check_ocsp_response(private_credential_manager_t *this, + ocsp_response_t *response) +{ + certificate_t *issuer, *subject; + identification_t *responder; + auth_info_t *auth; + ocsp_response_wrapper_t *wrapper; + + auth = auth_info_create(); + wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); + this->sets->remove(this->sets, this->cache, NULL); + this->sets->insert_first(this->sets, wrapper); + this->sets->insert_first(this->sets, this->cache); + + subject = &response->certificate; + responder = subject->get_issuer(subject); + issuer = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE); + this->sets->remove(this->sets, wrapper, NULL); + wrapper->destroy(wrapper); + auth->destroy(auth); - /* verify the signature of the ocsp response */ + if (!issuer) { - certificate_t *issuer_cert; - identification_t *responder; - auth_info_t *auth; - ocsp_response_wrapper_t *wrapper; - - auth = auth_info_create(); - wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); - this->sets->remove(this->sets, this->cache, NULL); - this->sets->insert_first(this->sets, wrapper); - this->sets->insert_first(this->sets, this->cache); - responder = response->get_issuer(response); - DBG1(DBG_CFG, " ocsp signer is \"%D\"", responder); - issuer_cert = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE); - this->sets->remove(this->sets, wrapper, NULL); - wrapper->destroy(wrapper); - auth->destroy(auth); + DBG1(DBG_CFG, "OCSP response verification failed, responder cert missing"); + return FALSE; + } + if (!this->cache->issued_by(this->cache, subject, issuer)) + { + DBG1(DBG_CFG, "OCSP response verification failed"); + issuer->destroy(issuer); + return FALSE; + } + issuer->destroy(issuer); + return TRUE; +} - if (!issuer_cert) +/** + * 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) +{ + ocsp_response_t *response; + time_t revocation, this_update, next_update, valid_until; + crl_reason_t reason; + + response = (ocsp_response_t*)cand; + + /* check ocsp signature */ + if (!check_ocsp_response(this, response)) + { + 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, crl_reason_names, reason); + DESTROY_IF(best); + return cand; + case VALIDATION_GOOD: + /* results in either good or stale */ + break; + default: + case VALIDATION_FAILED: + /* candidate unusable, does not contain our cert */ + cand->destroy(cand); + return best; + } + + /* select the better of the two responses */ + if (best == NULL || cand->is_newer(cand, best)) + { + DESTROY_IF(best); + best = cand; + if (best->get_validity(best, NULL, NULL, &valid_until)) { - DBG1(DBG_CFG, "ocsp response untrusted: no signer certificate found"); - response->destroy(response); - return NULL; - } - if (this->cache->issued_by(this->cache, response, issuer_cert)) - { - DBG1(DBG_CFG, " ocsp response correctly signed by \"%D\"", - issuer_cert->get_subject(issuer_cert)); - issuer_cert->destroy(issuer_cert); + DBG1(DBG_CFG, " ocsp response is valid: until %#T", &valid_until); + *valid = VALIDATION_GOOD; } else { - DBG1(DBG_CFG, "ocsp response not accepted from \"%D\"", - issuer_cert->get_subject(issuer_cert)); - issuer_cert->destroy(issuer_cert); - response->destroy(response); - return NULL; + DBG1(DBG_CFG, " ocsp response is stale: since %#T", &valid_until); + *valid = VALIDATION_STALE; } } - /* TODO: cache response? */ - return response; + else + { + *valid = VALIDATION_STALE; + cand->destroy(cand); + } + return best; } /** @@ -403,92 +465,49 @@ static cert_validation_t check_ocsp(private_credential_manager_t *this, x509_t *subject, x509_t *issuer, auth_info_t *auth) { - certificate_t *sub = (certificate_t*)subject; - certificate_t *best_cert = NULL; - certificate_t *cert; - public_key_t *public; + enumerator_t *enumerator; cert_validation_t valid = VALIDATION_SKIPPED; + certificate_t *best = NULL, *current; identification_t *keyid = NULL; - bool stale = TRUE; - - /* derive the authorityKeyIdentifier from the issuer's public key */ - cert = &issuer->interface; - public = cert->get_public_key(cert); - if (public) - { - keyid = public->get_id(public, ID_PUBKEY_SHA1); - } - - /* find a cached ocsp response by authorityKeyIdentifier */ - if (keyid) - { - enumerator_t *enumerator = create_cert_enumerator(this, - CERT_X509_OCSP_RESPONSE, - KEY_ANY, keyid, TRUE); - certificate_t *cert; + public_key_t *public; + char *uri = NULL; - while (enumerator->enumerate(enumerator, &cert)) + /** 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); + if (best && valid != VALIDATION_STALE) { - if (cert->has_subject(cert, sub->get_subject(sub))) - { - /* select most recent ocsp response */ - if (best_cert == NULL || cert->is_newer(cert, best_cert)) - { - DESTROY_IF(best_cert); - best_cert = cert->get_ref(cert); - } - } + DBG1(DBG_CFG, " used cached ocsp response"); + break; } - enumerator->destroy(enumerator); } - - /* check the validity of the cached ocsp response if one was found */ - if (best_cert) + enumerator->destroy(enumerator); + + /* derive the authorityKeyIdentifier from the issuer's public key */ + current = &issuer->interface; + public = current->get_public_key(current); + if (public) { - time_t nextUpdate; - - stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate); - DBG1(DBG_CFG, "cached ocsp response is %s %#T", - stale? "stale: since":"valid: until", - &nextUpdate, FALSE ); + keyid = public->get_id(public, ID_PUBKEY_SHA1); } - - /* fallback to URL fetching from CDPs */ - if (stale && keyid) + /** fetch from configured OCSP responder URLs */ + if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) { - enumerator_t *enumerator = create_cdp_enumerator(this, - CERT_X509_OCSP_RESPONSE, keyid); - char *uri; - + enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid); while (enumerator->enumerate(enumerator, &uri)) { - certificate_t* cert = fetch_ocsp(this, uri, &subject->interface, - &issuer->interface); - - /* redefine default since we have at least one uri */ - valid = VALIDATION_FAILED; - - if (cert) + current = fetch_ocsp(this, uri, &subject->interface, + &issuer->interface); + if (current) { - /* select most recent ocsp response until valid one is found */ - if (best_cert == NULL || cert->is_newer(cert, best_cert)) + best = get_better_ocsp(this, current, best, subject, issuer, &valid); + if (best && valid != VALIDATION_STALE) { - time_t nextUpdate; - - DESTROY_IF(best_cert); - best_cert = cert; - stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate); - DBG1(DBG_CFG, "ocsp response is %s %#T", - stale? "stale: since":"valid: until", - &nextUpdate, FALSE ); - if (!stale) - { - break; - } - } - else - { - cert->destroy(cert); + break; } } } @@ -497,76 +516,34 @@ static cert_validation_t check_ocsp(private_credential_manager_t *this, DESTROY_IF(public); /* fallback to URL fetching from subject certificate's URIs */ - if (stale) + if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) { - enumerator_t *enumerator = subject->create_ocsp_uri_enumerator(subject); - char *uri; - + enumerator = subject->create_ocsp_uri_enumerator(subject); while (enumerator->enumerate(enumerator, &uri)) { - certificate_t* cert = fetch_ocsp(this, uri, &subject->interface, - &issuer->interface); - - /* redefine default since we have at least one uri */ - valid = VALIDATION_FAILED; - - if (cert) + current = fetch_ocsp(this, uri, &subject->interface, + &issuer->interface); + if (current) { - /* select most recent ocsp response until valid one is found */ - if (best_cert == NULL || cert->is_newer(cert, best_cert)) - { - time_t nextUpdate; - - DESTROY_IF(best_cert); - best_cert = cert; - stale = !best_cert->get_validity(best_cert, NULL, NULL, &nextUpdate); - DBG1(DBG_CFG, "ocsp response is %s %#T", - stale? "stale: since":"valid: until", - &nextUpdate, FALSE ); - if (!stale) - { - break; - } - } - else + best = get_better_ocsp(this, current, best, subject, issuer, &valid); + if (best && valid != VALIDATION_STALE) { - cert->destroy(cert); + break; } } } enumerator->destroy(enumerator); } - - /* if we have an ocsp response, check the revocation status */ - if (best_cert) + /* an uri was found, but no result. switch validation state to failed */ + if (valid == VALIDATION_SKIPPED && uri) { - time_t revocation, this_update, next_update; - crl_reason_t reason; - ocsp_response_t *response = (ocsp_response_t*)best_cert; - - valid = response->get_status(response, subject, issuer, &revocation, - &reason, &this_update, &next_update); - switch (valid) - { - case VALIDATION_FAILED: - DBG1(DBG_CFG, "subject not found in ocsp response"); - break; - case VALIDATION_REVOKED: - DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", - &revocation, crl_reason_names, reason); - break; - case VALIDATION_GOOD: - case VALIDATION_UNKNOWN: - default: - break; - } - best_cert->destroy(best_cert); + valid = VALIDATION_FAILED; } - if (auth) { auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid); } + DESTROY_IF(best); return valid; } @@ -771,7 +748,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this, enumerator_t *enumerator = crl->create_enumerator(crl); /* redefine default */ - valid = stale ? VALIDATION_UNKNOWN : VALIDATION_GOOD; + valid = stale ? VALIDATION_STALE : VALIDATION_GOOD; while (enumerator->enumerate(enumerator, &serial, &revocation, &reason)) { @@ -831,8 +808,10 @@ static bool check_certificate(private_credential_manager_t *this, 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: - case VALIDATION_UNKNOWN: DBG1(DBG_CFG, "ocsp check failed, fallback to crl"); break; } @@ -847,14 +826,12 @@ static bool check_certificate(private_credential_manager_t *this, case VALIDATION_REVOKED: /* has already been logged */ return FALSE; - case VALIDATION_UNKNOWN: - DBG1(DBG_CFG, "certificate status is unknown"); - break; case VALIDATION_FAILED: case VALIDATION_SKIPPED: DBG1(DBG_CFG, "certificate status is not available"); - break; - default: + break; + case VALIDATION_STALE: + DBG1(DBG_CFG, "certificate status is unknown, crl is stale"); break; } } @@ -993,8 +970,8 @@ static certificate_t *get_trusted_cert(private_credential_manager_t *this, subject = get_pretrusted_cert(this, type, id); if (subject) { - - if (subject->issued_by(subject, subject, TRUE)) + /* if we find a trusted self signed certificate, we just accept it */ + if (this->cache->issued_by(this->cache, subject, subject)) { DBG1(DBG_CFG, " using trusted self-signed certificate \"%D\"", subject->get_subject(subject)); diff --git a/src/charon/credentials/sets/cert_cache.c b/src/charon/credentials/sets/cert_cache.c index 17e6d357c..5d4964314 100644 --- a/src/charon/credentials/sets/cert_cache.c +++ b/src/charon/credentials/sets/cert_cache.c @@ -93,7 +93,7 @@ static bool issued_by(private_cert_cache_t *this, return TRUE; } /* no cache hit, check signature */ - if (!subject->issued_by(subject, issuer, TRUE)) + if (!subject->issued_by(subject, issuer)) { return FALSE; } @@ -131,10 +131,9 @@ static bool certs_filter(cert_data_t *data, relation_t **in, certificate_t **out public_key_t *public; certificate_t *cert; - /* serve all subjects, but only if an ID is requestd (no listing) */ cert = (*in)->subject; if ((data->cert == CERT_ANY || cert->get_type(cert) == data->cert) && - data->id && cert->has_subject(cert, data->id)) + (!data->id || cert->has_subject(cert, data->id))) { if (data->key == KEY_ANY) { diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 5f2169cc4..9b0417f05 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -36,7 +36,7 @@ credentials/certificates/certificate.c credentials/certificates/certificate.h \ credentials/certificates/x509.h credentials/certificates/x509.c \ credentials/certificates/ac.h \ credentials/certificates/crl.h credentials/certificates/crl.c \ -credentials/certificates/ocsp_request.h credentials/certificates/ocsp_request.c \ +credentials/certificates/ocsp_request.h \ credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \ fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \ database/database.h database/database_factory.h database/database_factory.c \ diff --git a/src/libstrongswan/credentials/certificates/ac.h b/src/libstrongswan/credentials/certificates/ac.h index 7a3b747e0..c9645d68b 100644 --- a/src/libstrongswan/credentials/certificates/ac.h +++ b/src/libstrongswan/credentials/certificates/ac.h @@ -51,7 +51,7 @@ struct ac_t { * @param that other attribute certificate * @return TRUE if same holder */ - bool (*equals_holder) (const ac_t *this, const ac_t *other); + bool (*equals_holder) (ac_t *this, ac_t *other); }; #endif /* AC_H_ @}*/ diff --git a/src/libstrongswan/credentials/certificates/certificate.c b/src/libstrongswan/credentials/certificates/certificate.c index 8d159472d..1a83bdf4c 100644 --- a/src/libstrongswan/credentials/certificates/certificate.c +++ b/src/libstrongswan/credentials/certificates/certificate.c @@ -32,10 +32,10 @@ ENUM(certificate_type_names, CERT_ANY, CERT_PGP, ); ENUM(cert_validation_names, VALIDATION_GOOD, VALIDATION_SKIPPED, - "GOOD", - "REVOKED", - "UNKNOWN", - "FAILED", - "SKIPPED", + "VALIDATION_GOOD", + "VALIDATION_STALE", + "VALIDATION_REVOKED", + "VALIDATION_FAILED", + "VALIDATION_SKIPPED", ); diff --git a/src/libstrongswan/credentials/certificates/certificate.h b/src/libstrongswan/credentials/certificates/certificate.h index cc3f73a0d..14f4de389 100644 --- a/src/libstrongswan/credentials/certificates/certificate.h +++ b/src/libstrongswan/credentials/certificates/certificate.h @@ -62,13 +62,13 @@ extern enum_name_t *certificate_type_names; enum cert_validation_t { /** certificate has been validated successfully */ VALIDATION_GOOD, - /** validation failed, certificate is revoked */ + /** certificate has been validated, but check based on stale information */ + VALIDATION_STALE, + /** certificate has been revoked */ VALIDATION_REVOKED, - /* ocsp status is unknown or crl is stale */ - VALIDATION_UNKNOWN, - /** validation process failed due to an error */ + /** validation failed due to a processing error */ VALIDATION_FAILED, - /** validation has been skipped (no cdps available) */ + /** validation has been skipped due to missing validation information */ VALIDATION_SKIPPED, }; @@ -129,17 +129,12 @@ struct certificate_t { id_match_t (*has_issuer)(certificate_t *this, identification_t *issuer); /** - * Check if this certificate is issued by a specific issuer. + * Check if this certificate is issued and signed by a specific issuer. * - * As signature verification is computional expensive, it is optional - * and may be skipped. While this is not sufficient for verification - * purposes, it is to e.g. find matching certificates. - * * @param issuer issuer's certificate - * @param checksig TRUE to verify signature, FALSE to compare issuer only * @return TRUE if certificate issued by issuer and trusted */ - bool (*issued_by)(certificate_t *this, certificate_t *issuer, bool checksig); + bool (*issued_by)(certificate_t *this, certificate_t *issuer); /** * Get the public key associated to this certificate. diff --git a/src/libstrongswan/credentials/certificates/ocsp_request.c b/src/libstrongswan/credentials/certificates/ocsp_request.c deleted file mode 100644 index 0958be4a0..000000000 --- a/src/libstrongswan/credentials/certificates/ocsp_request.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * $Id$ - */ - -#include "ocsp_request.h" - diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c index 42dbc94c2..f90197bad 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.c +++ b/src/libstrongswan/plugins/x509/x509_ac.c @@ -714,8 +714,7 @@ static id_match_t has_issuer(private_x509_ac_t *this, identification_t *issuer) /** * Implementation of certificate_t.issued_by */ -static bool issued_by(private_x509_ac_t *this, certificate_t *issuer, - bool sigcheck) +static bool issued_by(private_x509_ac_t *this, certificate_t *issuer) { public_key_t *key; signature_scheme_t scheme; @@ -753,11 +752,6 @@ static bool issued_by(private_x509_ac_t *this, certificate_t *issuer, return FALSE; } } - - if (!sigcheck) - { - return TRUE; - } /* TODO: generic OID to scheme mapper? */ switch (this->algorithm) { @@ -912,7 +906,7 @@ static private_x509_ac_t *create_empty(void) this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer; this->public.interface.certificate.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_subject; this->public.interface.certificate.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer; - this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by; + this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by; this->public.interface.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key; this->public.interface.certificate.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity; this->public.interface.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer; diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index dcd393c23..ab32e13c3 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -932,8 +932,7 @@ static id_match_t has_issuer(private_x509_cert_t *this, identification_t *issuer /** * Implementation of certificate_t.issued_by */ -static bool issued_by(private_x509_cert_t *this, certificate_t *issuer, - bool sigcheck) +static bool issued_by(private_x509_cert_t *this, certificate_t *issuer) { public_key_t *key; signature_scheme_t scheme; @@ -962,10 +961,6 @@ static bool issued_by(private_x509_cert_t *this, certificate_t *issuer, { return FALSE; } - if (!sigcheck) - { - return TRUE; - } /* TODO: generic OID to scheme mapper? */ switch (this->algorithm) { @@ -1174,7 +1169,7 @@ static private_x509_cert_t* create_empty(void) this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer; this->public.interface.interface.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject; this->public.interface.interface.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer; - this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by; + this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by; this->public.interface.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key; this->public.interface.interface.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity; this->public.interface.interface.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer; @@ -1220,7 +1215,7 @@ static private_x509_cert_t *create_from_chunk(chunk_t chunk) } /* check if the certificate is self-signed */ - if (issued_by(this, &this->public.interface.interface, TRUE)) + if (issued_by(this, &this->public.interface.interface)) { this->flags |= X509_SELF_SIGNED; } diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c index d59b15303..a2871977e 100644 --- a/src/libstrongswan/plugins/x509/x509_crl.c +++ b/src/libstrongswan/plugins/x509/x509_crl.c @@ -362,15 +362,7 @@ static certificate_type_t get_type(private_x509_crl_t *this) } /** - * Implementation of certificate_t.get_subject - */ -static identification_t* get_subject(private_x509_crl_t *this) -{ - return this->issuer; -} - -/** - * Implementation of certificate_t.get_issuer + * Implementation of certificate_t.get_issuer and get_subject */ static identification_t* get_issuer(private_x509_crl_t *this) { @@ -378,15 +370,7 @@ static identification_t* get_issuer(private_x509_crl_t *this) } /** - * Implementation of certificate_t.has_subject. - */ -static id_match_t has_subject(private_x509_crl_t *this, identification_t *subject) -{ - return ID_MATCH_NONE; -} - -/** - * Implementation of certificate_t.has_issuer. + * Implementation of certificate_t.has_subject and has_issuer. */ static id_match_t has_issuer(private_x509_crl_t *this, identification_t *issuer) { @@ -413,8 +397,7 @@ static id_match_t has_issuer(private_x509_crl_t *this, identification_t *issuer) /** * Implementation of certificate_t.issued_by */ -static bool issued_by(private_x509_crl_t *this, certificate_t *issuer, - bool sigcheck) +static bool issued_by(private_x509_crl_t *this, certificate_t *issuer) { public_key_t *key; signature_scheme_t scheme; @@ -452,11 +435,6 @@ static bool issued_by(private_x509_crl_t *this, certificate_t *issuer, return FALSE; } } - - if (!sigcheck) - { - return TRUE; - } /* TODO: generic OID to scheme mapper? */ switch (this->algorithm) { @@ -616,11 +594,11 @@ static private_x509_crl_t* create_empty(void) this->public.crl.get_authKeyIdentifier = (identification_t* (*)(crl_t*))get_authKeyIdentifier; this->public.crl.create_enumerator = (enumerator_t* (*)(crl_t*))create_enumerator; this->public.crl.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type; - this->public.crl.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_subject; + this->public.crl.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_issuer; this->public.crl.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer; - this->public.crl.certificate.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject; + this->public.crl.certificate.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_issuer; this->public.crl.certificate.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer; - this->public.crl.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by; + this->public.crl.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by; this->public.crl.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key; this->public.crl.certificate.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity; this->public.crl.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer; diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c index 7e3230412..957df2414 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c @@ -378,8 +378,7 @@ static id_match_t has_issuer(private_x509_ocsp_request_t *this, /** * Implementation of certificate_t.issued_by */ -static bool issued_by(private_x509_ocsp_request_t *this, certificate_t *issuer, - bool sigcheck) +static bool issued_by(private_x509_ocsp_request_t *this, certificate_t *issuer) { DBG1("OCSP request validation not implemented!"); return FALSE; @@ -482,7 +481,7 @@ static private_x509_ocsp_request_t *create_empty() this->public.interface.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer; this->public.interface.interface.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_subject; this->public.interface.interface.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer; - this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by; + this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by; this->public.interface.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key; this->public.interface.interface.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity; this->public.interface.interface.get_encoding = (chunk_t(*)(certificate_t*))get_encoding; diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c index cf1de6b4e..0c1eb8539 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c @@ -31,6 +31,11 @@ #include <credentials/certificates/x509.h> #include <credentials/certificates/crl.h> +/** + * how long do we use an OCSP response without a nextUpdate + */ +#define OCSP_DEFAULT_LIFETIME 30 + typedef struct private_x509_ocsp_response_t private_x509_ocsp_response_t; /** @@ -58,10 +63,7 @@ struct private_x509_ocsp_response_t { int signatureAlgorithm; /** - * signature enumerator = this->responses->create_enumerator(this->responses); - while (enumerator->enumerate(enumerator, &response)) - { - value + * signature */ chunk_t signature; @@ -76,6 +78,11 @@ struct private_x509_ocsp_response_t { time_t producedAt; /** + * latest nextUpdate in this OCSP response + */ + time_t usableUntil; + + /** * list of included certificates */ linked_list_t *certs; @@ -382,8 +389,9 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this, response->status = VALIDATION_FAILED; response->revocationTime = 0; response->revocationReason = CRL_UNSPECIFIED; - response->thisUpdate = 0; - response->nextUpdate = 0; + response->thisUpdate = UNDEFINED_TIME; + /* if nextUpdate is missing, we give it a short lifetime */ + response->nextUpdate = this->producedAt + OCSP_DEFAULT_LIFETIME; asn1_init(&ctx, blob, level0, FALSE, FALSE); while (objectID < SINGLE_RESPONSE_ROOF) @@ -423,17 +431,25 @@ static bool parse_singleResponse(private_x509_ocsp_response_t *this, } break; case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN: - response->status = VALIDATION_UNKNOWN; + response->status = VALIDATION_FAILED; break; case SINGLE_RESPONSE_THIS_UPDATE: response->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); break; case SINGLE_RESPONSE_NEXT_UPDATE: response->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME); + if (response->nextUpdate > this->usableUntil) + { + this->usableUntil = response->nextUpdate; + } break; } objectID++; } + if (this->usableUntil == UNDEFINED_TIME) + { + this->usableUntil = this->producedAt + OCSP_DEFAULT_LIFETIME; + } this->responses->insert_last(this->responses, response); return TRUE; } @@ -643,8 +659,7 @@ static id_match_t has_issuer(private_x509_ocsp_response_t *this, /** * Implementation of certificate_t.issued_by */ -static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer, - bool sigcheck) +static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer) { public_key_t *key; signature_scheme_t scheme; @@ -685,10 +700,6 @@ static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer, { return FALSE; } - if (!sigcheck) - { - return TRUE; - } /* TODO: generic OID to scheme mapper? */ switch (this->signatureAlgorithm) { @@ -734,19 +745,7 @@ static public_key_t* get_public_key(private_x509_ocsp_response_t *this) static bool get_validity(private_x509_ocsp_response_t *this, time_t *when, time_t *not_before, time_t *not_after) { - enumerator_t *enumerator; - single_response_t *response; - time_t thisUpdate = this->producedAt; - time_t nextUpdate = 0; time_t t; - - enumerator = this->responses->create_enumerator(this->responses); - if (enumerator->enumerate(enumerator, &response)) - { - thisUpdate = response->thisUpdate; - nextUpdate = response->nextUpdate; - } - enumerator->destroy(enumerator); if (when == NULL) { @@ -758,13 +757,13 @@ static bool get_validity(private_x509_ocsp_response_t *this, time_t *when, } if (not_before) { - *not_before = thisUpdate; + *not_before = this->producedAt; } if (not_after) { - *not_after = nextUpdate; + *not_after = this->usableUntil; } - return (t < nextUpdate); + return (t < this->usableUntil); } /** @@ -853,7 +852,7 @@ static x509_ocsp_response_t *load(chunk_t data) this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer; this->public.interface.certificate.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_issuer; this->public.interface.certificate.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer; - this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by; + this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by; this->public.interface.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key; this->public.interface.certificate.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity; this->public.interface.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer; @@ -869,6 +868,7 @@ static x509_ocsp_response_t *load(chunk_t data) this->tbsResponseData = chunk_empty; this->responderId = NULL; this->producedAt = UNDEFINED_TIME; + this->usableUntil = UNDEFINED_TIME; this->responses = linked_list_create(); this->nonce = chunk_empty; this->signatureAlgorithm = OID_UNKNOWN; |