implemented dynamic http-based CRL fetching
authorAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 3 Apr 2007 21:09:11 +0000 (21:09 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 3 Apr 2007 21:09:11 +0000 (21:09 -0000)
src/libstrongswan/crypto/ca.c
src/libstrongswan/crypto/ca.h
src/libstrongswan/crypto/crl.c
src/libstrongswan/crypto/crl.h

index 36c8530..f437b6b 100644 (file)
@@ -36,6 +36,7 @@
 #include <debug.h>
 #include <utils/linked_list.h>
 #include <utils/identification.h>
+#include <utils/fetcher.h>
 
 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);
+       else
+       {
+               stale = !this->crl->is_valid(this->crl);
+               DBG1("crl is %s", stale? "stale":"valid");
+       }
 
-       if (!valid_signature)
+       if (stale)
        {
-               DBG1("crl signature is invalid");
-               goto err;
+               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);
        }
-       DBG2("crl signature is valid");
+       {
+               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;
 
index da51673..440ac4f 100644 (file)
@@ -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
index 685ccfc..0b9fdaf 100755 (executable)
@@ -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", &current_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;
index 216cafa..48953ba 100755 (executable)
@@ -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