full support of ca info records
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 24 Feb 2007 23:21:57 +0000 (23:21 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 24 Feb 2007 23:21:57 +0000 (23:21 -0000)
src/libstrongswan/crypto/ca.c
src/libstrongswan/crypto/ca.h

index d7e46f0..c3f707f 100644 (file)
@@ -56,55 +56,168 @@ struct private_ca_info_t {
        /**
         * Distinguished Name of the CA
         */
-       x509_t *cacert;
+       const x509_t *cacert;
        
        /**
-        * List of crlDistributionPoints
+        * List of crl URIs
         */
        linked_list_t *crlURIs;
 
        /**
-        * List of ocspAccessPoints
+        * List of ocsp URIs
         */
        linked_list_t *ocspURIs;
 };
 
 /**
+ * Implements ca_info_t.equals
+ */
+static bool equals(const private_ca_info_t *this, const private_ca_info_t *that)
+{
+       return chunk_equals(this->cacert->get_keyid(this->cacert),
+                                               that->cacert->get_keyid(that->cacert));
+}
+
+/**
+ * Implements ca_info_t.equals_name
+ */
+static bool equals_name(const private_ca_info_t *this, const char *name)
+{
+       return this->name != NULL && streq(this->name, name);
+}
+
+/**
+ * Find an exact copy of an identification in a linked list
+ */
+static identification_t* find_identification(linked_list_t *list, identification_t *id)
+{
+       identification_t *found_id = NULL, *current_id;
+
+       iterator_t *iterator = list->create_iterator(list, TRUE);
+
+       while (iterator->iterate(iterator, (void**)&current_id))
+       {
+               if (id->equals(id, current_id))
+               {
+                       found_id = current_id;
+                       break;
+               }
+       }
+       iterator->destroy(iterator);
+
+       return found_id;
+}
+
+/**
+ * Add a unique identification to a linked list
+ */
+static identification_t *add_identification(linked_list_t *list, identification_t *id)
+{
+       identification_t *found_id = find_identification(list, id);
+
+       if (found_id)
+       {
+               id->destroy(id);
+               return found_id;
+       }
+       else
+       {
+               list->insert_last(list, (void*)id);
+               return id;
+       }
+}
+
+/**
  * Implements ca_info_t.add_crluri
  */
-static void add_crluri(private_ca_info_t *this, const char* uri)
+static void add_crluri(private_ca_info_t *this, chunk_t uri)
 {
-       if (uri == NULL)
+       if (uri.len < 6 ||
+          (strncasecmp(uri.ptr, "http", 4) != 0  &&
+               strncasecmp(uri.ptr, "ldap", 4) != 0  &&
+               strncasecmp(uri.ptr, "file", 4) != 0  &&
+               strncasecmp(uri.ptr, "ftp",  3) != 0))
        {
+               DBG1("  invalid crl uri '%#B'", uri);
                return;
        }
-       if (strncasecmp(uri, "http", 4) != 0
-    &&  strncasecmp(uri, "ldap", 4) != 0
-    &&  strncasecmp(uri, "file", 4) != 0 
-       &&  strncasecmp(uri, "ftp",  3) != 0)
+       else
        {
-               DBG1("  invalid crl uri '%s'", uri);
-               return;
+               identification_t *crlURI = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
+
+               add_identification(this->crlURIs, crlURI);
        }
 }
 
 /**
  * Implements ca_info_t.add_ocspuri
  */
-static void add_ocspuri(private_ca_info_t *this, const char* uri)
+static void add_ocspuri(private_ca_info_t *this, chunk_t uri)
 {
-       if (uri == NULL)
+       if (uri.len < 7 || strncasecmp(uri.ptr, "http", 4) != 0)
        {
+               DBG1("  invalid ocsp uri '%.*s'", uri.len, uri.ptr);
                return;
        }
-       if (strncasecmp(uri, "http", 4) != 0)
+       else
        {
-               DBG1("  invalid ocsp uri '%s'", uri);
-               return;
+               identification_t *ocspURI = identification_create_from_encoding(ID_DER_ASN1_GN_URI, uri);
+
+               add_identification(this->ocspURIs, ocspURI);
+       }
+}
+
+/**
+ * Implements ca_info_t.add_info
+ */
+void add_info (private_ca_info_t *this, const private_ca_info_t *that)
+{
+       if (this->name == NULL && that->name != NULL)
+       {
+               this->name = strdup(that->name);
+       }
+       {
+               identification_t *uri;
+
+               iterator_t *iterator = that->crlURIs->create_iterator(that->crlURIs, TRUE);
+
+               while (iterator->iterate(iterator, (void**)&uri))
+               {
+                       add_crluri(this, uri->get_encoding(uri));
+               }
+               iterator->destroy(iterator);
+       }
+       {
+               identification_t *uri;
+
+               iterator_t *iterator = that->ocspURIs->create_iterator(that->ocspURIs, TRUE);
+
+               while (iterator->iterate(iterator, (void**)&uri))
+               {
+                       add_ocspuri(this, uri->get_encoding(uri));
+               }
+               iterator->destroy(iterator);
        }
 }
 
 /**
+ * Implements ca_info_t.release_info
+ */
+static void release_info(private_ca_info_t *this)
+{
+       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;
+}
+
+/**
  * Implements ca_info_t.destroy
  */
 static void destroy(private_ca_info_t *this)
@@ -126,27 +239,62 @@ static int print(FILE *stream, const struct printf_info *info,
        private_ca_info_t *this = *((private_ca_info_t**)(args[0]));
        bool utc = TRUE;
        int written = 0;
-       x509_t *cacert;
+       const x509_t *cacert;
        chunk_t keyid;
        
        if (info->alt)
        {
                utc = *((bool*)args[1]);
        }
-       
        if (this == NULL)
        {
                return fprintf(stream, "(null)");
        }
-       
-       written += fprintf(stream, "%#T, \"%s\"\n", &this->installed, utc, this->name);
+       written += fprintf(stream, "%#T", &this->installed, utc);
+
+       if (this->name)
+       {
+               written += fprintf(stream, ", \"%s\"\n", this->name);
+       }
+       else
+       {
+               written += fprintf(stream, "\n");
+       }
 
        cacert = this->cacert;
        written += fprintf(stream, "    authname:  '%D'\n", cacert->get_subject(cacert));
 
-       keyid = cacert->get_keyid(cacert);
-       written += fprintf(stream, "    keyid:      %#B\n", &keyid);
+       {
+               chunk_t keyid = cacert->get_keyid(cacert);
+
+               written += fprintf(stream, "    keyid:      %#B\n", &keyid);
+       }
+       {
+               identification_t *crlURI;
+               iterator_t *iterator = this->crlURIs->create_iterator(this->crlURIs, TRUE);
+               bool first = TRUE;
 
+               while (iterator->iterate(iterator, (void**)&crlURI))
+               {
+                       written += fprintf(stream, "    %s   '%D'\n",
+                                                          first? "crluris:":"        ", crlURI);
+                       first = FALSE;
+               }
+               iterator->destroy(iterator);
+       }
+       {
+               identification_t *ocspURI;
+               iterator_t *iterator = this->ocspURIs->create_iterator(this->ocspURIs, TRUE);
+               bool first = TRUE;
+
+               while (iterator->iterate(iterator, (void**)&ocspURI))
+               {
+                       written += fprintf(stream, "    %s  '%D'\n",
+                                                          first? "ocspuris:":"         ", ocspURI);
+                       first = FALSE;
+               }
+               iterator->destroy(iterator);
+       }
        return written;
 }
 
@@ -167,14 +315,18 @@ ca_info_t *ca_info_create(const char *name, const x509_t *cacert)
        
        /* initialize */
        this->installed = time(NULL);
-       this->name = strdup(name);
+       this->name = (name == NULL)? NULL:strdup(name);
        this->cacert = cacert;
        this->crlURIs = linked_list_create();
        this->ocspURIs = linked_list_create();
        
        /* public functions */
-       this->public.add_crluri = (void (*) (ca_info_t*,const char*))add_crluri;
-       this->public.add_ocspuri = (void (*) (ca_info_t*,const char*))add_ocspuri;
+       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.add_info = (void (*) (ca_info_t*,ca_info_t*))add_info;
+       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.destroy = (void (*) (ca_info_t*))destroy;
 
        return &this->public;
index deff830..8b1bd3d 100644 (file)
@@ -26,6 +26,7 @@
 typedef struct ca_info_t ca_info_t;
 
 #include <library.h>
+#include <chunk.h>
 
 #include "x509.h"
 
@@ -40,20 +41,54 @@ typedef struct ca_info_t ca_info_t;
 struct ca_info_t {
 
        /**
+        * @brief Compare two ca info records
+        *
+        * Comparison is doen via the keyid of the ca certificate
+     *
+        * @param this                  first ca info object
+        * @param that                  second ca info objct
+        * @return                              TRUE if a match is found
+        */
+       bool (*equals) (const ca_info_t *this, const ca_info_t* that);
+
+       /**
+        * @brief Checks if the ca info record has the same name
+        * 
+        * @param this                  ca info object
+        * @return                              TRUE if a match is found
+        */
+       bool (*equals_name) (const ca_info_t *this, const char *name);
+
+       /**
+        * @brief Merges info from a secondary ca info object
+        * 
+        * @param this                  primary ca info object
+        * @param that                  secondary ca info object
+        */
+       void (*add_info) (ca_info_t *this, const ca_info_t *that);
+
+       /**
         * @brief Adds a CRL URI to a list
         * 
         * @param this                  ca info object
-        * @param uri                   crl uri string to be added
+        * @param uri                   crl uri to be added
         */
-       void (*add_crluri) (ca_info_t *this, const char* uri);
+       void (*add_crluri) (ca_info_t *this, chunk_t uri);
 
        /**
         * @brief Adds a CRL URI to a list
         * 
         * @param this                  ca info object
-        * @param uri                   ocsp uri string to be added
+        * @param uri                   ocsp uri to be added
+        */
+       void (*add_ocspuri) (ca_info_t *this, chunk_t uri);
+
+       /**
+        * @brief Releases the name and URIs of ca info record
+        * 
+        * @param this                  ca info to release
         */
-       void (*add_ocspuri) (ca_info_t *this, const char* uri);
+       void (*release_info) (ca_info_t *this);
 
        /**
         * @brief Destroys a ca info record