refactored ca_info_t
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 3 Mar 2007 21:08:07 +0000 (21:08 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 3 Mar 2007 21:08:07 +0000 (21:08 -0000)
src/charon/config/credentials/credential_store.h
src/charon/config/credentials/local_credential_store.c

index 54c04c4..f20d9b9 100755 (executable)
@@ -126,14 +126,14 @@ struct credential_store_t {
        x509_t* (*get_ca_certificate_by_keyid) (credential_store_t *this, chunk_t keyid);
        
        /**
-        * @brief Returns the issuer certificate of a given certificate.
+        * @brief Returns the issuing ca of a given certificate.
         * 
         * @param this                                  calling object
-        * @param id                                    certificate for which issuer cert is required
-        * @return                                              certificate, or NULL if not found
+        * @param cert                                  certificate for which issuer ca info is required
+        * @return                                              ca info, or NULL if not found
         */
-       x509_t* (*get_issuer_certificate) (credential_store_t *this, const x509_t* cert);
-       
+       ca_info_t* (*get_issuer) (credential_store_t *this, const x509_t* cert);
+
        /**
         * @brief Verify an X.509 certificate up to trust anchor including revocation checks
         *
@@ -206,12 +206,13 @@ struct credential_store_t {
        iterator_t* (*create_cainfo_iterator) (credential_store_t *this);
 
        /**
-        * @brief Create an iterator over all CRLs.
+        * @brief Check if there are any CRLs.
         *
         * @param this          calling object
-        * @return                      iterator
+        * @param out           output stream
+        * @param utc           either utc or local time
         */
-       iterator_t* (*create_crl_iterator) (credential_store_t *this);
+       void (*list_crls) (credential_store_t *this, FILE *out, bool utc);
 
        /**
         * @brief Loads trusted CA certificates from a default directory.
index 427fef2..53957b7 100644 (file)
@@ -28,8 +28,8 @@
 #include <library.h>
 #include <utils/lexparser.h>
 #include <utils/linked_list.h>
-#include <crypto/certinfo.h>
 #include <crypto/rsa/rsa_public_key.h>
+#include <crypto/certinfo.h>
 #include <crypto/x509.h>
 #include <crypto/ca.h>
 #include <crypto/crl.h>
@@ -88,6 +88,47 @@ static shared_key_t *shared_key_create(chunk_t secret)
        return (this);
 }
 
+/* ---------------------------------------------------------------------- *
+ * the ca_info_t object as a central control element
+
++------------------------------------------------------+
+| local_credential_store_t                             |
++------------------------------------------------------+
+  |                            |
++-------------------------+  +-------------------------+
+| linked_list_t *ca_certs |  | linked_list_t *ca_infos |
++-------------------------+  +-------------------------+
+  |                            |
+  |                 +------------------------- +
+  |                 | ca_info_t                |
+  |                 +--------------------------+
++---------------+   | char *name               |
+| x509_t        |<--| x509_t *cacert           |   +----------------------+
++---------------+   | linked_list_t *certinfos |-->| certinfo_t           |
+| chunk_t keyid |   | linked_list_t *ocspuris  |   +----------------------+
++---------------+   | bool ocsp_fetch_pending  |   | chunk_t serialNumber |
+  |                 | crl_t *crl               |   | cert_status_t status |
+  |                 | linked_list_t *crluris   |   | time_t thisUpdate    |
+  |                 | bool crl_fetch_pending   |   | time_t nextUpdate    |
+  |                 | pthread_mutex_t mutex    |   | bool once            |
+  |                 +--------------------------+   +----------------------+
+  |                            |                     |
+  |                 +------------------------- +   +----------------------+
+  |                 | ca_info_t                |   | certinfo_t           |
+  |                 +--------------------------+   +----------------------+
++---------------+   | char *name               |   | chunk_t serialNumber |
+| x509_t        |<--| x509_t *cacert           |   | cert_status_t status |
++---------------+   | linked_list_t *certinfos |   | time_t thisUpdate    |
+| chunk_t keyid |   | linked_list_t *ocspuris  |   | time_t nextUpdate    |
++---------------+   | bool ocsp_fetch_pending  |   | bool once            |
+  |                 | crl_t *crl               |   +----------------------+
+  |                 | linked_list_t *crluris   |     |
+  |                 | bool crl_fetch_pending   |
+  |                 | pthread_mutex_t mutex;   |
+  |                 +--------------------------+
+  |                            |
+
+ * ---------------------------------------------------------------------- */
 
 typedef struct private_local_credential_store_t private_local_credential_store_t;
 
@@ -127,21 +168,6 @@ struct private_local_credential_store_t {
        linked_list_t *ca_infos;
 
        /**
-        * mutex controlling the access to the ca_infos linked list
-        */
-       pthread_mutex_t ca_infos_mutex;
-
-       /**
-        * list of X.509 CRLs
-        */
-       linked_list_t *crls;
-
-       /**
-        * mutex controlling the access to the crls linked list
-        */
-       pthread_mutex_t crls_mutex;
-
-       /**
         * enforce strict crl policy
         */
        bool strict;
@@ -382,21 +408,20 @@ static x509_t* get_ca_certificate_by_keyid(private_local_credential_store_t *thi
 }
 
 /**
- * Implementation of credential_store_t.get_issuer_certificate.
+ * Implementation of credential_store_t.get_issuer.
  */
-static x509_t* get_issuer_certificate(private_local_credential_store_t *this,
-                                                                         const x509_t *cert)
+static ca_info_t* get_issuer(private_local_credential_store_t *this, const x509_t *cert)
 {
-       x509_t *found = NULL;
-       x509_t *current_cert;
+       ca_info_t *found = NULL;
+       ca_info_t *ca_info;
 
-       iterator_t *iterator = this->ca_certs->create_iterator(this->ca_certs, TRUE);
+       iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
 
-       while (iterator->iterate(iterator, (void**)&current_cert))
+       while (iterator->iterate(iterator, (void**)&ca_info))
        {
-               if (cert->is_issuer(cert, current_cert))
+               if (ca_info->is_cert_issuer(ca_info, cert))
                {
-                       found = current_cert;
+                       found = ca_info;
                        break;
                }
        }
@@ -406,76 +431,6 @@ static x509_t* get_issuer_certificate(private_local_credential_store_t *this,
 }
 
 /**
- * Implementation of credential_store_t.get_crl.
- */
-static crl_t* get_crl(private_local_credential_store_t *this, const x509_t *issuer)
-{
-       crl_t *crl = NULL, *current_crl;
-
-       iterator_t *iterator = this->crls->create_iterator(this->crls, TRUE);
-
-       while (iterator->iterate(iterator, (void**)&current_crl))
-       {
-               if (current_crl->is_issuer(current_crl, issuer))
-               {
-                       crl = current_crl;
-                       break;
-               }
-       }
-       iterator->destroy(iterator);
-
-       return crl;
-}
-
-/**
- *  Verify the certificate status using CRLs
- */
-static cert_status_t verify_by_crl(private_local_credential_store_t* this, const x509_t *cert,
-       const x509_t *issuer_cert, certinfo_t *certinfo)
-{
-       crl_t *crl;
-       bool valid_signature;
-       rsa_public_key_t *issuer_public_key;
-
-
-       pthread_mutex_lock(&(this->crls_mutex));
-
-       crl = get_crl(this, issuer_cert);
-       if (crl == NULL)
-       {
-               DBG1(DBG_CFG, "crl not found");
-               goto err;
-       }
-       DBG2(DBG_CFG, "crl found");
-       
-       issuer_public_key = issuer_cert->get_public_key(issuer_cert);
-       valid_signature = crl->verify(crl, issuer_public_key);
-
-       if (!valid_signature)
-       {
-               DBG1(DBG_CFG, "crl signature is invalid");
-               goto err;
-       }
-       DBG2(DBG_CFG, "crl signature is valid");
-
-       crl->get_status(crl, certinfo);
-
-err:
-       pthread_mutex_unlock(&(this->crls_mutex));
-       return certinfo->get_status(certinfo);
-}
-
-/**
-  * Verify the certificate status using OCSP
-  */
-static cert_status_t verify_by_ocsp(private_local_credential_store_t* this,
-                       const x509_t *cert, certinfo_t *certinfo)
-{
-       /* TODO implement function */
-       return CERT_UNDEFINED;
-}
-
-/**
  * Find an exact copy of a certificate in a linked list
  */
 static x509_t* find_certificate(linked_list_t *certs, x509_t *cert)
@@ -518,6 +473,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
        for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
        {
                err_t ugh = NULL;
+               ca_info_t *issuer;
                x509_t *issuer_cert;
                rsa_public_key_t *issuer_public_key;
                bool valid_signature;
@@ -533,14 +489,15 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
                }
                DBG2(DBG_CFG, "certificate is valid");
 
-               issuer_cert = get_issuer_certificate(this, cert);
-               if (issuer_cert == NULL)
+               issuer = get_issuer(this, cert);
+               if (issuer == NULL)
                {
-                       DBG1(DBG_CFG, "issuer certificate not found");
+                       DBG1(DBG_CFG, "issuer info not found");
                        return FALSE;
                }
-               DBG2(DBG_CFG, "issuer certificate found");
+               DBG2(DBG_CFG, "issuer info found");
 
+               issuer_cert = issuer->get_certificate(issuer);
                issuer_public_key = issuer_cert->get_public_key(issuer_cert);
                valid_signature = cert->verify(cert, issuer_public_key);
 
@@ -574,12 +531,12 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
                        certinfo->set_nextUpdate(certinfo, until);
 
                        /* first check certificate revocation using ocsp */
-                       status = verify_by_ocsp(this, cert, certinfo);
+                       status = issuer->verify_by_ocsp(issuer, cert, certinfo);
 
                        /* if ocsp service is not available then fall back to crl */
                        if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict))
                        {
-                               status = verify_by_crl(this, cert, issuer_cert, certinfo);
+                               status = issuer->verify_by_crl(issuer, cert, certinfo);
                        }
                        
                        nextUpdate = certinfo->get_nextUpdate(certinfo);
@@ -683,7 +640,7 @@ static void add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_in
        ca_info_t *current_ca_info;
        ca_info_t *found_ca_info = NULL;
 
-       iterator_t *iterator = this->ca_infos->create_iterator_locked(this->ca_infos, &(this->ca_infos_mutex));
+       iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
 
        while (iterator->iterate(iterator, (void**)&current_ca_info))
        {
@@ -693,6 +650,8 @@ static void add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_in
                        break;
                }
        }
+       iterator->destroy(iterator);
+
        if (found_ca_info)
        {
                current_ca_info->add_info(current_ca_info, ca_info);
@@ -702,7 +661,6 @@ static void add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_in
        {
                this->ca_infos->insert_last(this->ca_infos, (void*)ca_info);
        }
-       iterator->destroy(iterator);
 }
 
 /**
@@ -713,13 +671,12 @@ static status_t release_ca_info(private_local_credential_store_t *this, const ch
        status_t status = NOT_FOUND;
        ca_info_t *ca_info;
 
-       iterator_t *iterator = this->ca_infos->create_iterator_locked(this->ca_infos, &(this->ca_infos_mutex));
+       iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
 
        while (iterator->iterate(iterator, (void**)&ca_info))
        {
-               if (ca_info->equals_name(ca_info, name))
+               if (ca_info->equals_name_release_info(ca_info, name))
                {
-                       ca_info->release_info(ca_info);
                        status = SUCCESS;
                        break;
                }
@@ -738,34 +695,32 @@ static x509_t* add_end_certificate(private_local_credential_store_t *this, x509_
 
        if (ret_cert == cert)
        {
-               x509_t *issuer_cert = get_issuer_certificate(this, cert);
+               ca_info_t *issuer = get_issuer(this, cert);
 
-               if (issuer_cert)
+               if (issuer)
                {
-                       ca_info_t *ca_info = ca_info_create(NULL, issuer_cert);
-
+                       /* add any crl distribution points to the issuer ca info record */
                        {
                                iterator_t *iterator = cert->create_crluri_iterator(cert);
                                identification_t *uri;
        
                                while (iterator->iterate(iterator, (void**)&uri))
                                {
-                                       ca_info->add_crluri(ca_info, uri->get_encoding(uri));
+                                       issuer->add_crluri(issuer, uri->get_encoding(uri));
                                }
                                iterator->destroy(iterator);
                        }
+                       /* add any ocsp access points to the issuer ca info record */
                        {
                                iterator_t *iterator = cert->create_ocspuri_iterator(cert);
                                identification_t *uri;
        
                                while (iterator->iterate(iterator, (void**)&uri))
                                {
-                                       ca_info->add_ocspuri(ca_info, uri->get_encoding(uri));
+                                       issuer->add_ocspuri(issuer, uri->get_encoding(uri));
                                }
                                iterator->destroy(iterator);
                        }
-
-                       add_ca_info(this, ca_info);
                }
        }
        return ret_cert;
@@ -800,15 +755,34 @@ static iterator_t* create_cacert_iterator(private_local_credential_store_t *this
  */
 static iterator_t* create_cainfo_iterator(private_local_credential_store_t *this)
 {
-       return this->ca_infos->create_iterator_locked(this->ca_infos, &(this->ca_infos_mutex));
+       return this->ca_infos->create_iterator(this->ca_infos, TRUE);
 }
 
 /**
- * Implements local_credential_store_t.create_crl_iterator
+ * Implements local_credential_store_t.list_crls
  */
-static iterator_t* create_crl_iterator(private_local_credential_store_t *this)
+static void list_crls(private_local_credential_store_t *this, FILE *out, bool utc)
 {
-       return this->crls->create_iterator_locked(this->crls, &(this->crls_mutex));
+       iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
+       ca_info_t *ca_info;
+       bool first = TRUE;
+
+       while (iterator->iterate(iterator, (void **)&ca_info))
+       {
+               if (ca_info->has_crl(ca_info))
+               {
+                       if (first)
+                       {
+                               fprintf(out, "\n");
+                               fprintf(out, "List of X.509 CRLs:\n");
+                               fprintf(out, "\n");
+                               first = FALSE;
+                       }
+                       ca_info->list_crl(ca_info, out, utc);
+                       break;
+               }
+       }
+       iterator->destroy(iterator);
 }
 
 /**
@@ -875,48 +849,30 @@ static void load_ca_certificates(private_local_credential_store_t *this)
 }
 
 /**
- * Add the latest crl to a linked list
+ * Add the latest crl to the issuing ca
  */
-static crl_t* add_crl(linked_list_t *crls, crl_t *crl)
+static void add_crl(private_local_credential_store_t *this, crl_t *crl)
 {
+       iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
+       ca_info_t *ca_info;
        bool found = FALSE;
-       crl_t *current_crl;
 
-       iterator_t *iterator = crls->create_iterator(crls, TRUE);
-
-       while (iterator->iterate(iterator, (void**)&current_crl))
+       while (iterator->iterate(iterator, (void**)&ca_info))
        {
-               if (crl->equals_issuer(crl, current_crl))
+               if (ca_info->is_crl_issuer(ca_info, crl))
                {
                        found = TRUE;
-                       if (crl->is_newer(crl, current_crl))
-                       {
-                               crl_t *old_crl = NULL;
-                               
-                               iterator->replace(iterator, (void**)&old_crl, (void*)crl);
-                               if (old_crl != NULL)
-                               {
-                                       old_crl->destroy(old_crl);
-                               }
-                               DBG2(DBG_CFG, "  thisUpdate is newer - existing crl replaced");
-                       }
-                       else
-                       {
-                               crl->destroy(crl);
-                               crl = current_crl;
-                               DBG2(DBG_CFG, "  thisUpdate is not newer - existing crl retained");
-                       }
+                       ca_info->add_crl(ca_info, crl);
                        break;
                }
        }
        iterator->destroy(iterator);
-
+       
        if (!found)
        {
-               crls->insert_last(crls, (void*)crl);
-               DBG2(DBG_CFG, "  crl added");
+               crl->destroy(crl);
+               DBG2(DBG_CFG, "  no issuing ca found for this crl - discarded");
        }
-       return crl;
 }
 
 /**
@@ -958,11 +914,9 @@ static void load_crls(private_local_credential_store_t *this)
 
                                if (ugh != NULL)        
                                {
-                                       DBG1(DBG_CFG, "warning: crl %s", ugh);
+                                       DBG1(DBG_CFG, "  warning: crl %s", ugh);
                                }
-                               pthread_mutex_lock(&(this->crls_mutex));
-                               crl = add_crl(this->crls, crl);
-                               pthread_mutex_unlock(&(this->crls_mutex));
+                               add_crl(this, crl);
                        }
                }
        }
@@ -1217,7 +1171,6 @@ static void destroy(private_local_credential_store_t *this)
        this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy));
        this->ca_certs->destroy_offset(this->ca_certs, offsetof(x509_t, destroy));
        this->ca_infos->destroy_offset(this->ca_infos, offsetof(ca_info_t, destroy));
-       this->crls->destroy_offset(this->crls, offsetof(crl_t, destroy));
        this->private_keys->destroy_offset(this->private_keys, offsetof(rsa_private_key_t, destroy));
        this->shared_keys->destroy_function(this->shared_keys, (void*)shared_key_destroy);
        free(this);
@@ -1238,7 +1191,7 @@ local_credential_store_t * local_credential_store_create(bool strict)
        this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate;
        this->public.credential_store.get_ca_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_ca_certificate;
        this->public.credential_store.get_ca_certificate_by_keyid = (x509_t* (*) (credential_store_t*,chunk_t))get_ca_certificate_by_keyid;
-       this->public.credential_store.get_issuer_certificate = (x509_t* (*) (credential_store_t*,const x509_t*))get_issuer_certificate;
+       this->public.credential_store.get_issuer = (ca_info_t* (*) (credential_store_t*,const x509_t*))get_issuer;
        this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify;
        this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate;
        this->public.credential_store.add_ca_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_ca_certificate;
@@ -1247,23 +1200,18 @@ local_credential_store_t * local_credential_store_create(bool strict)
        this->public.credential_store.create_cert_iterator = (iterator_t* (*) (credential_store_t*))create_cert_iterator;
        this->public.credential_store.create_cacert_iterator = (iterator_t* (*) (credential_store_t*))create_cacert_iterator;
        this->public.credential_store.create_cainfo_iterator = (iterator_t* (*) (credential_store_t*))create_cainfo_iterator;
-       this->public.credential_store.create_crl_iterator = (iterator_t* (*) (credential_store_t*))create_crl_iterator;
+       this->public.credential_store.list_crls = (void (*) (credential_store_t*,FILE*,bool))list_crls;
        this->public.credential_store.load_ca_certificates = (void (*) (credential_store_t*))load_ca_certificates;
        this->public.credential_store.load_crls = (void (*) (credential_store_t*))load_crls;
        this->public.credential_store.load_secrets = (void (*) (credential_store_t*))load_secrets;
        this->public.credential_store.destroy = (void (*) (credential_store_t*))destroy;
        
-       /* initialize mutexes */
-       pthread_mutex_init(&(this->crls_mutex), NULL);
-       pthread_mutex_init(&(this->ca_infos_mutex), NULL);
-
        /* private variables */
        this->shared_keys = linked_list_create();
        this->private_keys = linked_list_create();
        this->certs = linked_list_create();
        this->ca_certs = linked_list_create();
        this->ca_infos = linked_list_create();
-       this->crls = linked_list_create();
        this->strict = strict;
 
        return (&this->public);