stroke: Serve ca section CA certificates directly, not over central CA set
authorMartin Willi <martin@revosec.ch>
Fri, 6 Feb 2015 11:43:33 +0000 (12:43 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 3 Mar 2015 12:50:26 +0000 (13:50 +0100)
This makes these CA certificates independent from the purge issued by reread
commands. Certificates loaded by CA sections can be removed through ipsec.conf
update/reread, while CA certificates loaded implicitly from ipsec.d/cacerts
can individually be reread using ipsec rereadcacerts.

src/libcharon/plugins/stroke/stroke_ca.c
src/libcharon/plugins/stroke/stroke_cred.c
src/libcharon/plugins/stroke/stroke_cred.h

index f802687..b470b81 100644 (file)
@@ -120,6 +120,84 @@ static void ca_section_destroy(ca_section_t *this)
 }
 
 /**
+ * Data for the certificate enumerator
+ */
+typedef struct {
+       private_stroke_ca_t *this;
+       certificate_type_t cert;
+       key_type_t key;
+       identification_t *id;
+} cert_data_t;
+
+/**
+ * destroy cert_data
+ */
+static void cert_data_destroy(cert_data_t *data)
+{
+       data->this->lock->unlock(data->this->lock);
+       free(data);
+}
+
+/**
+ * filter function for certs enumerator
+ */
+static bool certs_filter(cert_data_t *data, ca_section_t **in,
+                                                certificate_t **out)
+{
+       public_key_t *public;
+       certificate_t *cert = (*in)->cert;
+
+       if (data->cert == CERT_ANY || data->cert == cert->get_type(cert))
+       {
+               public = cert->get_public_key(cert);
+               if (public)
+               {
+                       if (data->key == KEY_ANY || data->key == public->get_type(public))
+                       {
+                               if (data->id && public->has_fingerprint(public,
+                                                                                       data->id->get_encoding(data->id)))
+                               {
+                                       public->destroy(public);
+                                       *out = cert;
+                                       return TRUE;
+                               }
+                       }
+                       public->destroy(public);
+               }
+               else if (data->key != KEY_ANY)
+               {
+                       return FALSE;
+               }
+               if (data->id == NULL || cert->has_subject(cert, data->id))
+               {
+                       *out = cert;
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
+       private_stroke_ca_t *this, certificate_type_t cert, key_type_t key,
+       identification_t *id, bool trusted)
+{
+       enumerator_t *enumerator;
+       cert_data_t *data;
+
+       INIT(data,
+               .this = this,
+               .cert = cert,
+               .key = key,
+               .id = id,
+       );
+
+       this->lock->read_lock(this->lock);
+       enumerator = this->sections->create_enumerator(this->sections);
+       return enumerator_create_filter(enumerator, (void*)certs_filter, data,
+                                                                       (void*)cert_data_destroy);
+}
+
+/**
  * data to pass to create_inner_cdp
  */
 typedef struct {
@@ -438,7 +516,7 @@ stroke_ca_t *stroke_ca_create(stroke_cred_t *cred)
                .public = {
                        .set = {
                                .create_private_enumerator = (void*)return_null,
-                               .create_cert_enumerator = (void*)return_null,
+                               .create_cert_enumerator = _create_cert_enumerator,
                                .create_shared_enumerator = (void*)return_null,
                                .create_cdp_enumerator = _create_cdp_enumerator,
                                .cache_cert = (void*)nop,
@@ -456,4 +534,3 @@ stroke_ca_t *stroke_ca_create(stroke_cred_t *cred)
 
        return &this->public;
 }
-
index 1f02102..5e423f1 100644 (file)
@@ -241,7 +241,7 @@ METHOD(stroke_cred_t, load_ca, certificate_t*,
                }
                DBG1(DBG_CFG, "  loaded ca certificate \"%Y\" from '%s'",
                         cert->get_subject(cert), filename);
-               return this->creds->add_cert_ref(this->creds, TRUE, cert);
+               return this->creds->get_cert_ref(this->creds, cert);
        }
        return NULL;
 }
index f6fbb96..9434629 100644 (file)
@@ -50,10 +50,13 @@ struct stroke_cred_t {
        void (*reread)(stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt);
 
        /**
-        * Load a CA certificate, and serve it through the credential_set.
+        * Load a CA certificate.
+        *
+        * This method does not add the loaded CA certificate to the internal
+        * credentail set, but returns it only.
         *
         * @param filename              file to load CA cert from
-        * @return                              reference to loaded certificate, or NULL
+        * @return                              loaded certificate, or NULL
         */
        certificate_t* (*load_ca)(stroke_cred_t *this, char *filename);