From a8f02ad5f5f9a15c22cc2371818022a3c1b5e41c Mon Sep 17 00:00:00 2001 From: Andreas Steffen Date: Tue, 3 Apr 2007 21:09:11 +0000 Subject: [PATCH] implemented dynamic http-based CRL fetching --- src/libstrongswan/crypto/ca.c | 96 +++++++++++++++++++++++++++------- src/libstrongswan/crypto/ca.h | 6 +-- src/libstrongswan/crypto/crl.c | 16 ++---- src/libstrongswan/crypto/crl.h | 6 +-- 4 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/libstrongswan/crypto/ca.c b/src/libstrongswan/crypto/ca.c index 36c8530ca..f437b6ba5 100644 --- a/src/libstrongswan/crypto/ca.c +++ b/src/libstrongswan/crypto/ca.c @@ -36,6 +36,7 @@ #include #include #include +#include typedef struct private_ca_info_t private_ca_info_t; @@ -375,35 +376,95 @@ static x509_t* get_certificate(private_ca_info_t* this) /** * Implements ca_info_t.verify_by_crl. */ -static cert_status_t verify_by_crl(private_ca_info_t* this, const x509_t *cert, +static cert_status_t verify_by_crl(private_ca_info_t* this, certinfo_t *certinfo) { - bool valid_signature; - rsa_public_key_t *issuer_public_key; - + bool stale; pthread_mutex_lock(&(this->mutex)); if (this->crl == NULL) { + stale = TRUE; DBG1("crl not found"); - goto err; } - DBG2("crl found"); - - issuer_public_key = this->cacert->get_public_key(this->cacert); - valid_signature = this->crl->verify(this->crl, issuer_public_key); - - if (!valid_signature) + else { - DBG1("crl signature is invalid"); - goto err; + stale = !this->crl->is_valid(this->crl); + DBG1("crl is %s", stale? "stale":"valid"); } - DBG2("crl signature is valid"); + if (stale) + { + iterator_t *iterator = this->crluris->create_iterator(this->crluris, TRUE); + identification_t *uri; + + while (iterator->iterate(iterator, (void**)&uri)) + { + fetcher_t *fetcher; + char uri_string[BUF_LEN]; + chunk_t uri_chunk = uri->get_encoding(uri); + chunk_t response_chunk; + + snprintf(uri_string, BUF_LEN, "%.*s", uri_chunk.len, uri_chunk.ptr); + fetcher = fetcher_create(uri_string); + + response_chunk = fetcher->get(fetcher); + fetcher->destroy(fetcher); + if (response_chunk.ptr != NULL) + { + crl_t *crl = crl_create_from_chunk(response_chunk); + + if (crl) + { + if (this->crl == NULL) + { + this->crl = crl; + } + else if (crl->is_newer(crl, this->crl)) + { + this->crl->destroy(this->crl); + this->crl = crl; + DBG1(" thisUpdate is newer - existing crl replaced"); + if (this->crl->is_valid(this->crl)) + { + break; + } + else + { + DBG1("fetched crl is stale"); + } + } + else + { + crl->destroy(crl); + DBG1(" thisUpdate is not newer - existing crl retained"); + } + } + else + { + free(response_chunk.ptr); + }; + } + } + iterator->destroy(iterator); + } + { + rsa_public_key_t *issuer_public_key; + bool valid_signature; + + issuer_public_key = this->cacert->get_public_key(this->cacert); + valid_signature = this->crl->verify(this->crl, issuer_public_key); + if (!valid_signature) + { + DBG1("crl signature is invalid"); + goto ret; + } + DBG2("crl signature is valid"); + } this->crl->get_status(this->crl, certinfo); -err: +ret: pthread_mutex_unlock(&(this->mutex)); return certinfo->get_status(certinfo); } @@ -412,7 +473,6 @@ err: * Implements ca_info_t.verify_by_ocsp. */ static cert_status_t verify_by_ocsp(private_ca_info_t* this, - const x509_t *cert, certinfo_t *certinfo, credential_store_t *credentials) { @@ -636,8 +696,8 @@ ca_info_t *ca_info_create(const char *name, x509_t *cacert) this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri; this->public.add_ocspuri = (void (*) (ca_info_t*,chunk_t))add_ocspuri; this->public.get_certificate = (x509_t* (*) (ca_info_t*))get_certificate; - this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,const x509_t*,certinfo_t*))verify_by_crl; - this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,const x509_t*,certinfo_t*,credential_store_t*))verify_by_ocsp; + this->public.verify_by_crl = (cert_status_t (*) (ca_info_t*,certinfo_t*))verify_by_crl; + this->public.verify_by_ocsp = (cert_status_t (*) (ca_info_t*,certinfo_t*,credential_store_t*))verify_by_ocsp; this->public.purge_ocsp = (void (*) (ca_info_t*))purge_ocsp; this->public.destroy = (void (*) (ca_info_t*))destroy; diff --git a/src/libstrongswan/crypto/ca.h b/src/libstrongswan/crypto/ca.h index da51673f7..440ac4f0b 100644 --- a/src/libstrongswan/crypto/ca.h +++ b/src/libstrongswan/crypto/ca.h @@ -160,22 +160,20 @@ struct ca_info_t { * @brief Verify the status of a certificate by CRL * * @param this ca info object - * @param cert certificate to be verified * @param certinfo detailed certificate status information * @return certificate status */ - cert_status_t (*verify_by_crl) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo); + cert_status_t (*verify_by_crl) (ca_info_t* this, certinfo_t* certinfo); /** * @brief Verify the status of a certificate by OCSP * * @param this ca info object - * @param cert certificate to be verified * @param certinfo detailed certificate status information * @param credentials credential store needed for trust path verification * @return certificate status */ - cert_status_t (*verify_by_ocsp) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo, credential_store_t* credentials); + cert_status_t (*verify_by_ocsp) (ca_info_t* this, certinfo_t* certinfo, credential_store_t* credentials); /** * @brief Purge the OCSP certinfos of a ca info record diff --git a/src/libstrongswan/crypto/crl.c b/src/libstrongswan/crypto/crl.c index 685ccfc8a..0b9fdaf4f 100755 --- a/src/libstrongswan/crypto/crl.c +++ b/src/libstrongswan/crypto/crl.c @@ -311,7 +311,7 @@ bool parse_x509crl(chunk_t blob, u_int level0, private_crl_t *crl) /** * Implements crl_t.is_valid */ -static err_t is_valid(const private_crl_t *this, time_t *until, bool strict) +static bool is_valid(const private_crl_t *this) { time_t current_time = time(NULL); @@ -319,17 +319,7 @@ static err_t is_valid(const private_crl_t *this, time_t *until, bool strict) DBG2(" current time: %T", ¤t_time); DBG2(" next update: %T", &this->nextUpdate); - if (strict && until != NULL && - (*until == UNDEFINED_TIME || this->nextUpdate < *until)) - { - *until = this->nextUpdate; - } - if (current_time > this->nextUpdate) - { - return "has expired"; - } - DBG2(" crl is valid"); - return NULL; + return current_time < this->nextUpdate; } /** @@ -499,7 +489,7 @@ crl_t *crl_create_from_chunk(chunk_t chunk) this->public.get_issuer = (identification_t* (*) (const crl_t*))get_issuer; this->public.equals_issuer = (bool (*) (const crl_t*,const crl_t*))equals_issuer; this->public.is_issuer = (bool (*) (const crl_t*,const x509_t*))is_issuer; - this->public.is_valid = (err_t (*) (const crl_t*,time_t*,bool))is_valid; + this->public.is_valid = (bool (*) (const crl_t*))is_valid; this->public.is_newer = (bool (*) (const crl_t*,const crl_t*))is_newer; this->public.verify = (bool (*) (const crl_t*,const rsa_public_key_t*))verify; this->public.get_status = (void (*) (const crl_t*,certinfo_t*))get_status; diff --git a/src/libstrongswan/crypto/crl.h b/src/libstrongswan/crypto/crl.h index 216cafad0..48953ba78 100755 --- a/src/libstrongswan/crypto/crl.h +++ b/src/libstrongswan/crypto/crl.h @@ -75,11 +75,9 @@ struct crl_t { * @brief Checks the validity interval of the crl * * @param this calling object - * @param until until = min(until, nextUpdate) if strict == TRUE - * @param strict nextUpdate restricts the validity - * @return NULL if the crl is valid + * @return TRUE if the crl is valid */ - err_t (*is_valid) (const crl_t *this, time_t *until, bool strict); + bool (*is_valid) (const crl_t *this); /** * @brief Checks if this crl is newer (thisUpdate) than the other crl