Alternative to mem_cred_t.add_cert added, which returns the certificate.
[strongswan.git] / src / libstrongswan / credentials / sets / mem_cred.c
index ca3ee36..08a1e71 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2010 Tobias Brunner
+ * Hochschule fuer Technik Rapperwsil
  * Copyright (C) 2010 Martin Willi
  * Copyright (C) 2010 revosec AG
  *
@@ -90,7 +92,7 @@ static bool certs_filter(cert_data_t *data, certificate_t **in, certificate_t **
                {
                        if (data->key == KEY_ANY || data->key == public->get_type(public))
                        {
-                               if (public->has_fingerprint(public,
+                               if (data->id && public->has_fingerprint(public,
                                                                                        data->id->get_encoding(data->id)))
                                {
                                        public->destroy(public);
@@ -139,16 +141,50 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
                                                                        (void*)cert_data_destroy);
 }
 
-METHOD(mem_cred_t, add_cert, void,
-       private_mem_cred_t *this, bool trusted, certificate_t *cert)
+static bool certificate_equals(certificate_t *item, certificate_t *cert)
+{
+       return item->equals(item, cert);
+}
+
+/**
+ * Add a certificate the the cache. Returns a reference to "cert" or a
+ * previously cached certificate that equals "cert".
+ */
+static certificate_t *add_cert_internal(private_mem_cred_t *this, bool trusted,
+                                                                               certificate_t *cert)
 {
+       certificate_t *cached;
        this->lock->write_lock(this->lock);
-       if (trusted)
+       if (this->untrusted->find_last(this->untrusted,
+                                                                  (linked_list_match_t)certificate_equals,
+                                                                  (void**)&cached, cert) == SUCCESS)
+       {
+               cert->destroy(cert);
+               cert = cached->get_ref(cached);
+       }
+       else
        {
-               this->trusted->insert_last(this->trusted, cert->get_ref(cert));
+               if (trusted)
+               {
+                       this->trusted->insert_last(this->trusted, cert->get_ref(cert));
+               }
+               this->untrusted->insert_last(this->untrusted, cert->get_ref(cert));
        }
-       this->untrusted->insert_last(this->untrusted, cert);
        this->lock->unlock(this->lock);
+       return cert;
+}
+
+METHOD(mem_cred_t, add_cert, void,
+       private_mem_cred_t *this, bool trusted, certificate_t *cert)
+{
+       certificate_t *cached = add_cert_internal(this, trusted, cert);
+       cached->destroy(cached);
+}
+
+METHOD(mem_cred_t, add_cert_ref, certificate_t*,
+       private_mem_cred_t *this, bool trusted, certificate_t *cert)
+{
+       return add_cert_internal(this, trusted, cert);
 }
 
 /**
@@ -332,44 +368,68 @@ METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
                                                (void*)shared_filter, data, (void*)shared_data_destroy);
 }
 
-METHOD(mem_cred_t, add_shared, void,
-       private_mem_cred_t *this, shared_key_t *shared, ...)
+METHOD(mem_cred_t, add_shared_list, void,
+       private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners)
 {
        shared_entry_t *entry;
-       identification_t *id;
-       va_list args;
 
        INIT(entry,
                .shared = shared,
-               .owners = linked_list_create(),
+               .owners = owners,
        );
 
+       this->lock->write_lock(this->lock);
+       this->shared->insert_last(this->shared, entry);
+       this->lock->unlock(this->lock);
+}
+
+METHOD(mem_cred_t, add_shared, void,
+       private_mem_cred_t *this, shared_key_t *shared, ...)
+{
+       identification_t *id;
+       linked_list_t *owners = linked_list_create();
+       va_list args;
+
        va_start(args, shared);
        do
        {
                id = va_arg(args, identification_t*);
                if (id)
                {
-                       entry->owners->insert_last(entry->owners, id);
+                       owners->insert_last(owners, id);
                }
        }
        while (id);
        va_end(args);
 
-       this->lock->write_lock(this->lock);
-       this->shared->insert_last(this->shared, entry);
-       this->lock->unlock(this->lock);
+       add_shared_list(this, shared, owners);
 }
 
-METHOD(mem_cred_t, destroy, void,
+METHOD(mem_cred_t, clear_, void,
        private_mem_cred_t *this)
 {
+       this->lock->write_lock(this->lock);
        this->trusted->destroy_offset(this->trusted,
-                                                               offsetof(certificate_t, destroy));
+                                                                 offsetof(certificate_t, destroy));
        this->untrusted->destroy_offset(this->untrusted,
-                                                               offsetof(certificate_t, destroy));
+                                                                       offsetof(certificate_t, destroy));
        this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy));
        this->shared->destroy_function(this->shared, (void*)shared_entry_destroy);
+       this->trusted = linked_list_create();
+       this->untrusted = linked_list_create();
+       this->keys = linked_list_create();
+       this->shared = linked_list_create();
+       this->lock->unlock(this->lock);
+}
+
+METHOD(mem_cred_t, destroy, void,
+       private_mem_cred_t *this)
+{
+       clear_(this);
+       this->trusted->destroy(this->trusted);
+       this->untrusted->destroy(this->untrusted);
+       this->keys->destroy(this->keys);
+       this->shared->destroy(this->shared);
        this->lock->destroy(this->lock);
        free(this);
 }
@@ -391,8 +451,11 @@ mem_cred_t *mem_cred_create()
                                .cache_cert = (void*)nop,
                        },
                        .add_cert = _add_cert,
+                       .add_cert_ref = _add_cert_ref,
                        .add_key = _add_key,
                        .add_shared = _add_shared,
+                       .add_shared_list = _add_shared_list,
+                       .clear = _clear_,
                        .destroy = _destroy,
                },
                .trusted = linked_list_create(),