Added a flag to register local credential sets exclusively, disabling all others
authorMartin Willi <martin@revosec.ch>
Mon, 19 Dec 2011 19:22:18 +0000 (20:22 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 20 Mar 2012 16:31:28 +0000 (17:31 +0100)
src/libcharon/plugins/stroke/stroke_cred.c
src/libstrongswan/credentials/credential_manager.c
src/libstrongswan/credentials/credential_manager.h
src/libstrongswan/plugins/revocation/revocation_validator.c
src/pluto/keys.c

index 47381b7..aff0e66 100644 (file)
@@ -576,7 +576,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
                pin_data.keyid = chunk;
                pin_data.try = 1;
                cb = callback_cred_create_shared((void*)pin_cb, &pin_data);
-               lib->credmgr->add_local_set(lib->credmgr, &cb->set);
+               lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE);
        }
        else
        {
@@ -585,7 +585,7 @@ static bool load_pin(private_stroke_cred_t *this, chunk_t line, int line_nr,
                id = identification_create_from_encoding(ID_KEY_ID, chunk);
                mem = mem_cred_create();
                mem->add_shared(mem, shared, id, NULL);
-               lib->credmgr->add_local_set(lib->credmgr, &mem->set);
+               lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
        }
 
        /* unlock: smartcard needs the pin and potentially calls public set */
@@ -693,7 +693,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
                pp_data.path = path;
                pp_data.try = 1;
                cb = callback_cred_create_shared((void*)passphrase_cb, &pp_data);
-               lib->credmgr->add_local_set(lib->credmgr, &cb->set);
+               lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE);
 
                key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
                                                                 BUILD_FROM_FILE, path, BUILD_END);
@@ -710,7 +710,7 @@ static bool load_private(private_stroke_cred_t *this, chunk_t line, int line_nr,
                shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, secret);
                mem = mem_cred_create();
                mem->add_shared(mem, shared, NULL);
-               lib->credmgr->add_local_set(lib->credmgr, &mem->set);
+               lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
 
                key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
                                                                 BUILD_FROM_FILE, path, BUILD_END);
index 4c31040..944c269 100644 (file)
@@ -53,6 +53,11 @@ struct private_credential_manager_t {
        thread_value_t *local_sets;
 
        /**
+        * Exclusive local sets, linked_list_t with credential_set_t
+        */
+       thread_value_t *exclusive_local_sets;
+
+       /**
         * trust relationship and certificate cache
         */
        cert_cache_t *cache;
@@ -117,12 +122,23 @@ typedef struct {
        enumerator_t *global;
        /** enumerator over local sets */
        enumerator_t *local;
+       /** enumerator over exclusive local sets */
+       enumerator_t *exclusive;
 } sets_enumerator_t;
 
 
 METHOD(enumerator_t, sets_enumerate, bool,
        sets_enumerator_t *this, credential_set_t **set)
 {
+       if (this->exclusive)
+       {
+               if (this->exclusive->enumerate(this->exclusive, set))
+               {       /* only enumerate last added */
+                       this->exclusive->destroy(this->exclusive);
+                       this->exclusive = NULL;
+                       return TRUE;
+               }
+       }
        if (this->global)
        {
                if (this->global->enumerate(this->global, set))
@@ -145,6 +161,7 @@ METHOD(enumerator_t, sets_destroy, void,
 {
        DESTROY_IF(this->global);
        DESTROY_IF(this->local);
+       DESTROY_IF(this->exclusive);
        free(this);
 }
 
@@ -154,19 +171,28 @@ METHOD(enumerator_t, sets_destroy, void,
 static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
 {
        sets_enumerator_t *enumerator;
-       linked_list_t *local;
+       linked_list_t *list;
 
        INIT(enumerator,
                .public = {
                        .enumerate = (void*)_sets_enumerate,
                        .destroy = _sets_destroy,
                },
-               .global = this->sets->create_enumerator(this->sets),
        );
-       local = this->local_sets->get(this->local_sets);
-       if (local)
+
+       list = this->exclusive_local_sets->get(this->exclusive_local_sets);
+       if (list && list->get_count(list))
        {
-               enumerator->local = local->create_enumerator(local);
+               enumerator->exclusive = list->create_enumerator(list);
+       }
+       else
+       {
+               enumerator->global = this->sets->create_enumerator(this->sets);
+               list = this->local_sets->get(this->local_sets);
+               if (list)
+               {
+                       enumerator->local = list->create_enumerator(list);
+               }
        }
        return &enumerator->public;
 }
@@ -373,29 +399,53 @@ METHOD(credential_manager_t, get_shared, shared_key_t*,
 }
 
 METHOD(credential_manager_t, add_local_set, void,
-       private_credential_manager_t *this, credential_set_t *set)
+       private_credential_manager_t *this, credential_set_t *set, bool exclusive)
 {
        linked_list_t *sets;
+       thread_value_t *tv;
 
-       sets = this->local_sets->get(this->local_sets);
+       if (exclusive)
+       {
+               tv = this->exclusive_local_sets;
+       }
+       else
+       {
+               tv = this->local_sets;
+       }
+       sets = tv->get(tv);
        if (!sets)
-       {       /* first invocation */
+       {
                sets = linked_list_create();
-               this->local_sets->set(this->local_sets, sets);
+               tv->set(tv, sets);
+       }
+       if (exclusive)
+       {
+               sets->insert_first(sets, set);
+       }
+       else
+       {
+               sets->insert_last(sets, set);
        }
-       sets->insert_last(sets, set);
 }
 
 METHOD(credential_manager_t, remove_local_set, void,
        private_credential_manager_t *this, credential_set_t *set)
 {
        linked_list_t *sets;
+       thread_value_t *tv;
 
-       sets = this->local_sets->get(this->local_sets);
-       sets->remove(sets, set, NULL);
-       if (sets->get_count(sets) == 0)
+       tv = this->local_sets;
+       sets = tv->get(tv);
+       if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
+       {
+               tv->set(tv, NULL);
+               sets->destroy(sets);
+       }
+       tv = this->exclusive_local_sets;
+       sets = tv->get(tv);
+       if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
        {
-               this->local_sets->set(this->local_sets, NULL);
+               tv->set(tv, NULL);
                sets->destroy(sets);
        }
 }
@@ -864,7 +914,7 @@ METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
        if (auth)
        {
                enumerator->wrapper = auth_cfg_wrapper_create(auth);
-               add_local_set(this, &enumerator->wrapper->set);
+               add_local_set(this, &enumerator->wrapper->set, FALSE);
        }
        this->lock->read_lock(this->lock);
        return &enumerator->public;
@@ -1105,6 +1155,7 @@ METHOD(credential_manager_t, destroy, void,
        this->sets->remove(this->sets, this->cache, NULL);
        this->sets->destroy(this->sets);
        this->local_sets->destroy(this->local_sets);
+       this->exclusive_local_sets->destroy(this->exclusive_local_sets);
        this->cache->destroy(this->cache);
        this->validators->destroy(this->validators);
        this->lock->destroy(this->lock);
@@ -1149,6 +1200,7 @@ credential_manager_t *credential_manager_create()
        );
 
        this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
+       this->exclusive_local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
        this->sets->insert_first(this->sets, this->cache);
 
        return &this->public;
index 4c662d1..8a774f6 100644 (file)
@@ -230,10 +230,14 @@ struct credential_manager_t {
         * operation, sets may be added for the calling thread only. This
         * does not require a write lock and is therefore a much less expensive
         * operation.
+        * The exclusive option allows to disable all other credential sets
+        * until the set is deregistered.
         *
         * @param set           set to register
+        * @param exclusive     TRUE to disable all other sets for this thread
         */
-       void (*add_local_set)(credential_manager_t *this, credential_set_t *set);
+       void (*add_local_set)(credential_manager_t *this, credential_set_t *set,
+                                                 bool exclusive);
 
        /**
         * Unregister a thread local credential set from the manager.
index 34f347d..ff3ef14 100644 (file)
@@ -103,7 +103,7 @@ static bool verify_ocsp(ocsp_response_t *response, auth_cfg_t *auth)
        bool verified = FALSE;
 
        wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
-       lib->credmgr->add_local_set(lib->credmgr, &wrapper->set);
+       lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE);
 
        subject = &response->certificate;
        responder = subject->get_issuer(subject);
index a204d86..9031fcd 100644 (file)
@@ -621,7 +621,7 @@ static private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
                callback_cred_t *cb;
 
                cb = callback_cred_create_shared((void*)whack_pass_cb, pass);
-               lib->credmgr->add_local_set(lib->credmgr, &cb->set);
+               lib->credmgr->add_local_set(lib->credmgr, &cb->set, FALSE);
 
                key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
                                                                 BUILD_FROM_FILE, path, BUILD_END);
@@ -638,7 +638,7 @@ static private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
                shared_key_t *shared;
 
                mem = mem_cred_create();
-               lib->credmgr->add_local_set(lib->credmgr, &mem->set);
+               lib->credmgr->add_local_set(lib->credmgr, &mem->set, FALSE);
                shared = shared_key_create(SHARED_PRIVATE_KEY_PASS,
                                chunk_clone(chunk_create(pass->secret, strlen(pass->secret))));
                mem->add_shared(mem, shared, NULL);