refactored ca_info_t
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 3 Mar 2007 21:07:23 +0000 (21:07 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 3 Mar 2007 21:07:23 +0000 (21:07 -0000)
src/libstrongswan/crypto/ca.c
src/libstrongswan/crypto/ca.h

index f7ffa38..1a53021 100644 (file)
 #include <unistd.h>
 #include <string.h>
 #include <stdio.h>
+#include <pthread.h>
 
+#include "x509.h"
+#include "crl.h"
 #include "ca.h"
 #include "certinfo.h"
 
@@ -57,7 +60,7 @@ struct private_ca_info_t {
        /**
         * Distinguished Name of the CA
         */
-       const x509_t *cacert;
+       x509_t *cacert;
        
        /**
         * List of crl URIs
@@ -70,9 +73,20 @@ struct private_ca_info_t {
        linked_list_t *ocspuris;
 
        /**
+        * CRL issued by this ca
+        */
+       crl_t *crl;
+
+       /**
         * List of certificate info records
         */
        linked_list_t *certinfos;
+
+       /**
+        * mutex controls access to the elements:
+        * name, crluris, ocspuris, crl, and certinfos
+        */
+       pthread_mutex_t mutex;
 };
 
 /**
@@ -85,11 +99,103 @@ static bool equals(const private_ca_info_t *this, const private_ca_info_t *that)
 }
 
 /**
- * Implements ca_info_t.equals_name
+ * Implements ca_info_t.equals_name_release_info
+ */
+static bool equals_name_release_info(private_ca_info_t *this, const char *name)
+{
+       bool found;
+
+       pthread_mutex_lock(&(this->mutex));
+       found = this->name != NULL && streq(this->name, name);
+
+       if (found)
+       {
+               this->crluris->destroy_offset(this->crluris,
+                                                                         offsetof(identification_t, destroy));
+               this->crluris = linked_list_create();
+
+               this->ocspuris->destroy_offset(this->ocspuris,
+                                                                          offsetof(identification_t, destroy));
+               this->ocspuris = linked_list_create();
+
+               free(this->name);
+               this->name = NULL;
+       }
+
+       pthread_mutex_unlock(&(this->mutex));
+       return found;
+}
+
+/**
+ * Implements ca_info_t.is_crl_issuer
  */
-static bool equals_name(const private_ca_info_t *this, const char *name)
+static bool is_cert_issuer(private_ca_info_t *this, const x509_t *cert)
 {
-       return this->name != NULL && streq(this->name, name);
+       return cert->is_issuer(cert, this->cacert);
+}
+
+/**
+ * Implements ca_info_t.is_crl_issuer
+ */
+static bool is_crl_issuer(private_ca_info_t *this, const crl_t *crl)
+{
+       return crl->is_issuer(crl, this->cacert);
+}
+
+/**
+ * Implements ca_info_t.has_crl
+ */
+static bool has_crl(private_ca_info_t *this)
+{
+       bool found;
+
+       pthread_mutex_lock(&(this->mutex));
+       found = this->crl != NULL;
+       pthread_mutex_unlock(&(this->mutex));
+
+       return found;
+}
+
+/**
+ * Implements ca_info_t.add_crl
+ */
+static void add_crl(private_ca_info_t *this, crl_t *crl)
+{
+       pthread_mutex_lock(&(this->mutex));
+
+       if (this->crl)
+       {
+               if (crl->is_newer(crl, this->crl))
+               {
+                       this->crl->destroy(this->crl);
+                       this->crl = crl;
+                       DBG1("  thisUpdate is newer - existing crl replaced");
+               }
+               else
+               {
+                       crl->destroy(crl);
+                       DBG1("  thisUpdate is not newer - existing crl retained");
+               }
+       }
+       else
+       {
+               this->crl = crl;
+               DBG2("  crl added");
+       }
+
+       pthread_mutex_unlock(&(this->mutex));
+}
+
+/**
+ * Implements ca_info_t.list_crl
+ */
+static void list_crl(private_ca_info_t *this, FILE *out, bool utc)
+{
+       pthread_mutex_lock(&(this->mutex));
+
+       fprintf(out, "%#U\n", this->crl, utc);
+
+       pthread_mutex_unlock(&(this->mutex));
 }
 
 /**
@@ -151,7 +257,9 @@ static void add_crluri(private_ca_info_t *this, chunk_t uri)
        {
                identification_t *crluri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
 
+               pthread_mutex_lock(&(this->mutex));
                add_identification(this->crluris, crluri);
+               pthread_mutex_unlock(&(this->mutex));
        }
 }
 
@@ -169,19 +277,26 @@ static void add_ocspuri(private_ca_info_t *this, chunk_t uri)
        {
                identification_t *ocspuri = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
 
+               pthread_mutex_lock(&(this->mutex));
                add_identification(this->ocspuris, ocspuri);
+               pthread_mutex_unlock(&(this->mutex));
        }
 }
 
 /**
- * Implements ca_info_t.add_info
+ * Implements ca_info_t.add_info.
  */
 void add_info (private_ca_info_t *this, const private_ca_info_t *that)
 {
+       pthread_mutex_lock(&(this->mutex));
+
        if (this->name == NULL && that->name != NULL)
        {
                this->name = strdup(that->name);
        }
+
+       pthread_mutex_unlock(&(this->mutex));
+
        {
                identification_t *uri;
 
@@ -193,6 +308,7 @@ void add_info (private_ca_info_t *this, const private_ca_info_t *that)
                }
                iterator->destroy(iterator);
        }
+
        {
                identification_t *uri;
 
@@ -207,20 +323,57 @@ void add_info (private_ca_info_t *this, const private_ca_info_t *that)
 }
 
 /**
- * Implements ca_info_t.release_info
+ *  Implements ca_info_t.get_certificate.
  */
-static void release_info(private_ca_info_t *this)
+static x509_t* get_certificate(private_ca_info_t* this)
 {
-       this->crluris->destroy_offset(this->crluris,
-                                                                 offsetof(identification_t, destroy));
-       this->crluris = linked_list_create();
+       return this->cacert;
+}
 
-       this->ocspuris->destroy_offset(this->ocspuris,
-                                                                  offsetof(identification_t, destroy));
-       this->ocspuris = linked_list_create();
+/**
+ *  Implements ca_info_t.verify_by_crl.
+ */
+static cert_status_t verify_by_crl(private_ca_info_t* this, const x509_t *cert,
+                                                                  certinfo_t *certinfo)
+{
+       bool valid_signature;
+       rsa_public_key_t *issuer_public_key;
 
-       free(this->name);
-       this->name = NULL;
+
+       pthread_mutex_lock(&(this->mutex));
+
+       if (this->crl == NULL)
+       {
+               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)
+       {
+               DBG1("crl signature is invalid");
+               goto err;
+       }
+       DBG2("crl signature is valid");
+
+       this->crl->get_status(this->crl, certinfo);
+
+err:
+       pthread_mutex_unlock(&(this->mutex));
+       return certinfo->get_status(certinfo);
+}
+
+/**
+  * 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)
+{
+       /* TODO implement function */
+       return CERT_UNDEFINED;
 }
 
 /**
@@ -234,6 +387,7 @@ static void destroy(private_ca_info_t *this)
                                                                   offsetof(identification_t, destroy));
        this->certinfos->destroy_offset(this->certinfos,
                                                                   offsetof(certinfo_t, destroy));
+       DESTROY_IF(this->crl);
        free(this->name);
        free(this);
 }
@@ -258,6 +412,8 @@ static int print(FILE *stream, const struct printf_info *info,
        {
                return fprintf(stream, "(null)");
        }
+
+       pthread_mutex_lock(&(this->mutex));
        written += fprintf(stream, "%#T", &this->installed, utc);
 
        if (this->name)
@@ -303,6 +459,7 @@ static int print(FILE *stream, const struct printf_info *info,
                }
                iterator->destroy(iterator);
        }
+       pthread_mutex_unlock(&(this->mutex));
        return written;
 }
 
@@ -317,7 +474,7 @@ static void __attribute__ ((constructor))print_register()
 /*
  * Described in header.
  */
-ca_info_t *ca_info_create(const char *name, const x509_t *cacert)
+ca_info_t *ca_info_create(const char *name, x509_t *cacert)
 {
        private_ca_info_t *this = malloc_thing(private_ca_info_t);
        
@@ -328,14 +485,25 @@ ca_info_t *ca_info_create(const char *name, const x509_t *cacert)
        this->crluris = linked_list_create();
        this->ocspuris = linked_list_create();
        this->certinfos = linked_list_create();
+       this->crl = NULL;
        
+       /* initialize the mutex */
+       pthread_mutex_init(&(this->mutex), NULL);
+
        /* public functions */
        this->public.equals = (bool (*) (const ca_info_t*,const ca_info_t*))equals;
-       this->public.equals_name = (bool (*) (const ca_info_t*,const char*))equals_name;
+       this->public.equals_name_release_info = (bool (*) (ca_info_t*,const char*))equals_name_release_info;
+       this->public.is_cert_issuer = (bool (*) (ca_info_t*,const x509_t*))is_cert_issuer;
+       this->public.is_crl_issuer = (bool (*) (ca_info_t*,const crl_t*))is_crl_issuer;
        this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info;
+       this->public.add_crl = (void (*) (ca_info_t*,crl_t*))add_crl;
+       this->public.has_crl = (bool (*) (ca_info_t*))has_crl;
+       this->public.list_crl = (void (*) (ca_info_t*,FILE*,bool))list_crl;
        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.release_info = (void (*) (ca_info_t*))release_info;
+       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*))verify_by_ocsp;
        this->public.destroy = (void (*) (ca_info_t*))destroy;
 
        return &this->public;
index 8b1bd3d..1b2e33e 100644 (file)
@@ -29,6 +29,7 @@ typedef struct ca_info_t ca_info_t;
 #include <chunk.h>
 
 #include "x509.h"
+#include "crl.h"
 
 /**
  * @brief X.509 certification authority information record
@@ -43,7 +44,7 @@ struct ca_info_t {
        /**
         * @brief Compare two ca info records
         *
-        * Comparison is doen via the keyid of the ca certificate
+        * Comparison is done via the keyid of the ca certificate
      *
         * @param this                  first ca info object
         * @param that                  second ca info objct
@@ -52,12 +53,30 @@ struct ca_info_t {
        bool (*equals) (const ca_info_t *this, const ca_info_t* that);
 
        /**
-        * @brief Checks if the ca info record has the same name
+        * @brief If the ca info record has the same name then release the name and URIs
         * 
         * @param this                  ca info object
         * @return                              TRUE if a match is found
         */
-       bool (*equals_name) (const ca_info_t *this, const char *name);
+       bool (*equals_name_release_info) (ca_info_t *this, const char *name);
+
+       /**
+        * @brief Checks if a certificate was issued by this ca
+        * 
+        * @param this                  ca info object
+        * @param cert                  certificate to be checked
+        * @return                              TRUE if the issuing ca has been found
+        */
+       bool (*is_cert_issuer) (ca_info_t *this, const x509_t *cert);
+
+       /**
+        * @brief Checks if a crl was issued by this ca
+        * 
+        * @param this                  ca info object
+        * @param crl                   crl to be checked
+        * @return                              TRUE if the issuing ca has been found
+        */
+       bool (*is_crl_issuer) (ca_info_t *this, const crl_t *crl);
 
        /**
         * @brief Merges info from a secondary ca info object
@@ -68,6 +87,31 @@ struct ca_info_t {
        void (*add_info) (ca_info_t *this, const ca_info_t *that);
 
        /**
+        * @brief Adds a new or replaces an obsoleted CRL
+        * 
+        * @param this                  ca info object
+        * @param crl                   crl to be added
+        */
+       void (*add_crl) (ca_info_t *this, crl_t *crl);
+
+       /**
+        * @brief Does the CA have a CRL?
+        * 
+        * @param this                  ca info object
+        * @return                              TRUE if crl is available
+        */
+       bool (*has_crl) (ca_info_t *this);
+
+       /**
+        * @brief List the CRL onto the console
+        * 
+        * @param this                  ca info object
+        * @param utc                   TRUE -  utc
+                                                       FALSE - local time
+        */
+       void (*list_crl) (ca_info_t *this, FILE *out, bool utc);
+
+       /**
         * @brief Adds a CRL URI to a list
         * 
         * @param this                  ca info object
@@ -76,7 +120,7 @@ struct ca_info_t {
        void (*add_crluri) (ca_info_t *this, chunk_t uri);
 
        /**
-        * @brief Adds a CRL URI to a list
+        * @brief Adds a OCSP URI to a list
         * 
         * @param this                  ca info object
         * @param uri                   ocsp uri to be added
@@ -84,11 +128,32 @@ struct ca_info_t {
        void (*add_ocspuri) (ca_info_t *this, chunk_t uri);
 
        /**
-        * @brief Releases the name and URIs of ca info record
+        * @brief Get the ca certificate
+        * 
+        * @param this                  ca info object
+        * @return                              ca certificate
+        */
+       x509_t* (*get_certificate) (ca_info_t *this);
+
+       /**
+        * @brief Verify the status of a certificate by CRL
         * 
-        * @param this                  ca info to release
+        * @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);
+
+       /**
+        * @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
+        * @return                              certificate status
         */
-       void (*release_info) (ca_info_t *this);
+       cert_status_t (*verify_by_ocsp) (ca_info_t* this, const x509_t* cert, certinfo_t* certinfo);
 
        /**
         * @brief Destroys a ca info record
@@ -107,6 +172,6 @@ struct ca_info_t {
  * 
  * @ingroup transforms
  */
-ca_info_t *ca_info_create(const char *name, const x509_t *cacert);
+ca_info_t *ca_info_create(const char *name, x509_t *cacert);
 
 #endif /* CA_H_ */