diff options
Diffstat (limited to 'src/libcharon/credentials')
-rw-r--r-- | src/libcharon/credentials/credential_manager.c | 1681 | ||||
-rw-r--r-- | src/libcharon/credentials/credential_manager.h | 203 | ||||
-rw-r--r-- | src/libcharon/credentials/credential_set.h | 108 | ||||
-rw-r--r-- | src/libcharon/credentials/sets/auth_cfg_wrapper.c | 223 | ||||
-rw-r--r-- | src/libcharon/credentials/sets/auth_cfg_wrapper.h | 53 | ||||
-rw-r--r-- | src/libcharon/credentials/sets/cert_cache.c | 390 | ||||
-rw-r--r-- | src/libcharon/credentials/sets/cert_cache.h | 71 | ||||
-rw-r--r-- | src/libcharon/credentials/sets/ocsp_response_wrapper.c | 147 | ||||
-rw-r--r-- | src/libcharon/credentials/sets/ocsp_response_wrapper.h | 53 |
9 files changed, 0 insertions, 2929 deletions
diff --git a/src/libcharon/credentials/credential_manager.c b/src/libcharon/credentials/credential_manager.c deleted file mode 100644 index adea0b4be..000000000 --- a/src/libcharon/credentials/credential_manager.c +++ /dev/null @@ -1,1681 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "credential_manager.h" - -#include <daemon.h> -#include <threading/thread_value.h> -#include <threading/mutex.h> -#include <threading/rwlock.h> -#include <utils/linked_list.h> -#include <credentials/sets/cert_cache.h> -#include <credentials/sets/auth_cfg_wrapper.h> -#include <credentials/sets/ocsp_response_wrapper.h> -#include <credentials/certificates/x509.h> -#include <credentials/certificates/crl.h> -#include <credentials/certificates/ocsp_request.h> -#include <credentials/certificates/ocsp_response.h> - -typedef struct private_credential_manager_t private_credential_manager_t; - -/** - * private data of credential_manager - */ -struct private_credential_manager_t { - - /** - * public functions - */ - credential_manager_t public; - - /** - * list of credential sets - */ - linked_list_t *sets; - - /** - * thread local set of credentials, linked_list_t with credential_set_t's - */ - thread_value_t *local_sets; - - /** - * trust relationship and certificate cache - */ - cert_cache_t *cache; - - /** - * certificates queued for persistent caching - */ - linked_list_t *cache_queue; - - /** - * read-write lock to sets list - */ - rwlock_t *lock; - - /** - * mutex for cache queue - */ - mutex_t *queue_mutex; -}; - -/** data to pass to create_private_enumerator */ -typedef struct { - private_credential_manager_t *this; - key_type_t type; - identification_t* keyid; -} private_data_t; - -/** data to pass to create_cert_enumerator */ -typedef struct { - private_credential_manager_t *this; - certificate_type_t cert; - key_type_t key; - identification_t *id; - bool trusted; -} cert_data_t; - -/** data to pass to create_cdp_enumerator */ -typedef struct { - private_credential_manager_t *this; - certificate_type_t type; - identification_t *id; -} cdp_data_t; - -/** data to pass to create_shared_enumerator */ -typedef struct { - private_credential_manager_t *this; - shared_key_type_t type; - identification_t *me; - identification_t *other; -} shared_data_t; - -/** enumerator over local and global sets */ -typedef struct { - /** implements enumerator_t */ - enumerator_t public; - /** enumerator over global sets */ - enumerator_t *global; - /** enumerator over local sets */ - enumerator_t *local; -} sets_enumerator_t; - -/** - * destroy a sets_enumerator_t - */ -static void sets_enumerator_destroy(sets_enumerator_t *this) -{ - DESTROY_IF(this->global); - DESTROY_IF(this->local); - free(this); -} - -/** - * sets_enumerator_t.enumerate - */ -static bool sets_enumerator_enumerate(sets_enumerator_t *this, - credential_set_t **set) -{ - if (this->global) - { - if (this->global->enumerate(this->global, set)) - { - return TRUE; - } - /* end of global sets, look for local */ - this->global->destroy(this->global); - this->global = NULL; - } - if (this->local) - { - return this->local->enumerate(this->local, set); - } - return FALSE; -} - -/** - * create an enumerator over both, global and local sets - */ -static enumerator_t *create_sets_enumerator(private_credential_manager_t *this) -{ - linked_list_t *local; - sets_enumerator_t *enumerator = malloc_thing(sets_enumerator_t); - - enumerator->public.enumerate = (void*)sets_enumerator_enumerate; - enumerator->public.destroy = (void*)sets_enumerator_destroy; - enumerator->global = this->sets->create_enumerator(this->sets); - enumerator->local = NULL; - local = this->local_sets->get(this->local_sets); - if (local) - { - enumerator->local = local->create_enumerator(local); - } - return &enumerator->public; -} - -/** - * cleanup function for cert data - */ -static void destroy_cert_data(cert_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * enumerator constructor for certificates - */ -static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data) -{ - return set->create_cert_enumerator(set, data->cert, data->key, - data->id, data->trusted); -} - -/** - * Implementation of credential_manager_t.create_cert_enumerator. - */ -static enumerator_t *create_cert_enumerator(private_credential_manager_t *this, - certificate_type_t certificate, key_type_t key, - identification_t *id, bool trusted) -{ - cert_data_t *data = malloc_thing(cert_data_t); - data->this = this; - data->cert = certificate; - data->key = key; - data->id = id; - data->trusted = trusted; - - this->lock->read_lock(this->lock); - return enumerator_create_nested(create_sets_enumerator(this), - (void*)create_cert, data, - (void*)destroy_cert_data); -} - -/** - * Implementation of credential_manager_t.get_cert. - */ -static certificate_t *get_cert(private_credential_manager_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - certificate_t *current, *found = NULL; - enumerator_t *enumerator; - - enumerator = create_cert_enumerator(this, cert, key, id, trusted); - if (enumerator->enumerate(enumerator, ¤t)) - { - /* TODO: best match? order by keyid, subject, sualtname */ - found = current->get_ref(current); - } - enumerator->destroy(enumerator); - return found; -} - - -/** - * cleanup function for cdp data - */ -static void destroy_cdp_data(cdp_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * enumerator constructor for CDPs - */ -static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data) -{ - return set->create_cdp_enumerator(set, data->type, data->id); -} -/** - * Implementation of credential_manager_t.create_cdp_enumerator. - */ -static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this, - certificate_type_t type, identification_t *id) -{ - cdp_data_t *data = malloc_thing(cdp_data_t); - data->this = this; - data->type = type; - data->id = id; - - this->lock->read_lock(this->lock); - return enumerator_create_nested(create_sets_enumerator(this), - (void*)create_cdp, data, - (void*)destroy_cdp_data); -} - -/** - * cleanup function for private data - */ -static void destroy_private_data(private_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * enumerator constructor for private keys - */ -static enumerator_t *create_private(credential_set_t *set, private_data_t *data) -{ - return set->create_private_enumerator(set, data->type, data->keyid); -} - -/** - * Implementation of credential_manager_t.create_private_enumerator. - */ -static enumerator_t* create_private_enumerator( - private_credential_manager_t *this, - key_type_t key, identification_t *keyid) -{ - private_data_t *data; - - data = malloc_thing(private_data_t); - data->this = this; - data->type = key; - data->keyid = keyid; - this->lock->read_lock(this->lock); - return enumerator_create_nested(create_sets_enumerator(this), - (void*)create_private, data, - (void*)destroy_private_data); -} - -/** - * Implementation of credential_manager_t.get_private_by_keyid. - */ -static private_key_t *get_private_by_keyid(private_credential_manager_t *this, - key_type_t key, identification_t *keyid) -{ - private_key_t *found = NULL; - enumerator_t *enumerator; - - enumerator = create_private_enumerator(this, key, keyid); - if (enumerator->enumerate(enumerator, &found)) - { - found->get_ref(found); - } - enumerator->destroy(enumerator); - return found; -} - -/** - * cleanup function for shared data - */ -static void destroy_shared_data(shared_data_t *data) -{ - data->this->lock->unlock(data->this->lock); - free(data); -} - -/** - * enumerator constructor for shared keys - */ -static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data) -{ - return set->create_shared_enumerator(set, data->type, data->me, data->other); -} - -/** - * Implementation of credential_manager_t.create_shared_enumerator. - */ -static enumerator_t *create_shared_enumerator(private_credential_manager_t *this, - shared_key_type_t type, - identification_t *me, identification_t *other) -{ - shared_data_t *data = malloc_thing(shared_data_t); - data->this = this; - data->type = type; - data->me = me; - data->other = other; - - this->lock->read_lock(this->lock); - return enumerator_create_nested(create_sets_enumerator(this), - (void*)create_shared, data, - (void*)destroy_shared_data); -} - -/** - * Implementation of credential_manager_t.get_shared. - */ -static shared_key_t *get_shared(private_credential_manager_t *this, - shared_key_type_t type, identification_t *me, - identification_t *other) -{ - shared_key_t *current, *found = NULL; - id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE; - id_match_t *match_me, *match_other; - enumerator_t *enumerator; - - enumerator = create_shared_enumerator(this, type, me, other); - while (enumerator->enumerate(enumerator, ¤t, &match_me, &match_other)) - { - if (match_other > best_other || - (match_other == best_other && match_me > best_me)) - { - DESTROY_IF(found); - found = current->get_ref(current); - best_me = match_me; - best_other = match_other; - } - } - enumerator->destroy(enumerator); - return found; -} - -/** - * add a credential set to the thread local list - */ -static void add_local_set(private_credential_manager_t *this, - credential_set_t *set) -{ - linked_list_t *sets; - - sets = this->local_sets->get(this->local_sets); - if (!sets) - { /* first invocation */ - sets = linked_list_create(); - this->local_sets->set(this->local_sets, sets); - } - sets->insert_last(sets, set); -} - -/** - * remove a credential set from the thread local list - */ -static void remove_local_set(private_credential_manager_t *this, - credential_set_t *set) -{ - linked_list_t *sets; - - sets = this->local_sets->get(this->local_sets); - sets->remove(sets, set, NULL); -} - -/** - * Implementation of credential_manager_t.cache_cert. - */ -static void cache_cert(private_credential_manager_t *this, certificate_t *cert) -{ - credential_set_t *set; - enumerator_t *enumerator; - - if (this->lock->try_write_lock(this->lock)) - { - enumerator = this->sets->create_enumerator(this->sets); - while (enumerator->enumerate(enumerator, &set)) - { - set->cache_cert(set, cert); - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - } - else - { /* we can't cache now as other threads are active, queue for later */ - this->queue_mutex->lock(this->queue_mutex); - this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert)); - this->queue_mutex->unlock(this->queue_mutex); - } -} - -/** - * Try to cache certificates queued for caching - */ -static void cache_queue(private_credential_manager_t *this) -{ - credential_set_t *set; - certificate_t *cert; - enumerator_t *enumerator; - - this->queue_mutex->lock(this->queue_mutex); - if (this->cache_queue->get_count(this->cache_queue) > 0 && - this->lock->try_write_lock(this->lock)) - { - while (this->cache_queue->remove_last(this->cache_queue, - (void**)&cert) == SUCCESS) - { - enumerator = this->sets->create_enumerator(this->sets); - while (enumerator->enumerate(enumerator, &set)) - { - set->cache_cert(set, cert); - } - enumerator->destroy(enumerator); - cert->destroy(cert); - } - this->lock->unlock(this->lock); - } - this->queue_mutex->unlock(this->queue_mutex); -} - -/** - * forward declaration - */ -static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this, - key_type_t type, identification_t *id, bool crl, bool ocsp); - -/** - * Do an OCSP request - */ -static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url, - certificate_t *subject, certificate_t *issuer) -{ - certificate_t *request, *response; - chunk_t send, receive; - - /* TODO: requestor name, signature */ - request = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST, - BUILD_CA_CERT, issuer, - BUILD_CERT, subject, BUILD_END); - if (!request) - { - DBG1(DBG_CFG, "generating ocsp request failed"); - return NULL; - } - - send = request->get_encoding(request); - request->destroy(request); - - DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url); - if (lib->fetcher->fetch(lib->fetcher, url, &receive, - FETCH_REQUEST_DATA, send, - FETCH_REQUEST_TYPE, "application/ocsp-request", - FETCH_END) != SUCCESS) - { - DBG1(DBG_CFG, "ocsp request to %s failed", url); - chunk_free(&send); - return NULL; - } - chunk_free(&send); - - response = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE, - BUILD_BLOB_ASN1_DER, receive, BUILD_END); - chunk_free(&receive); - if (!response) - { - DBG1(DBG_CFG, "parsing ocsp response failed"); - return NULL; - } - return response; -} - -/** - * check the signature of an OCSP response - */ -static bool verify_ocsp(private_credential_manager_t *this, - ocsp_response_t *response) -{ - certificate_t *issuer, *subject; - identification_t *responder; - ocsp_response_wrapper_t *wrapper; - enumerator_t *enumerator; - bool verified = FALSE; - - wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); - add_local_set(this, &wrapper->set); - - subject = &response->certificate; - responder = subject->get_issuer(subject); - enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE, FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) - { - if (this->cache->issued_by(this->cache, subject, issuer)) - { - DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"", - issuer->get_subject(issuer)); - verified = TRUE; - break; - } - } - enumerator->destroy(enumerator); - - remove_local_set(this, &wrapper->set); - wrapper->destroy(wrapper); - return verified; -} - -/** - * Get the better of two OCSP responses, and check for usable OCSP info - */ -static certificate_t *get_better_ocsp(private_credential_manager_t *this, - certificate_t *cand, certificate_t *best, - x509_t *subject, x509_t *issuer, - cert_validation_t *valid, bool cache) -{ - ocsp_response_t *response; - time_t revocation, this_update, next_update, valid_until; - crl_reason_t reason; - bool revoked = FALSE; - - response = (ocsp_response_t*)cand; - - /* check ocsp signature */ - if (!verify_ocsp(this, response)) - { - DBG1(DBG_CFG, "ocsp response verification failed"); - cand->destroy(cand); - return best; - } - /* check if response contains our certificate */ - switch (response->get_status(response, subject, issuer, &revocation, &reason, - &this_update, &next_update)) - { - case VALIDATION_REVOKED: - /* subject has been revoked by a valid OCSP response */ - DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", - &revocation, TRUE, crl_reason_names, reason); - revoked = TRUE; - break; - case VALIDATION_GOOD: - /* results in either good or stale */ - break; - default: - case VALIDATION_FAILED: - /* candidate unusable, does not contain our cert */ - DBG1(DBG_CFG, " ocsp response contains no status on our certificate"); - cand->destroy(cand); - return best; - } - - /* select the better of the two responses */ - if (best == NULL || cand->is_newer(cand, best)) - { - DESTROY_IF(best); - best = cand; - if (best->get_validity(best, NULL, NULL, &valid_until)) - { - DBG1(DBG_CFG, " ocsp response is valid: until %T", - &valid_until, FALSE); - *valid = VALIDATION_GOOD; - if (cache) - { /* cache non-stale only, stale certs get refetched */ - cache_cert(this, best); - } - } - else - { - DBG1(DBG_CFG, " ocsp response is stale: since %T", - &valid_until, FALSE); - *valid = VALIDATION_STALE; - } - } - else - { - *valid = VALIDATION_STALE; - cand->destroy(cand); - } - if (revoked) - { /* revoked always counts, even if stale */ - *valid = VALIDATION_REVOKED; - } - return best; -} - -/** - * validate a x509 certificate using OCSP - */ -static cert_validation_t check_ocsp(private_credential_manager_t *this, - x509_t *subject, x509_t *issuer, - auth_cfg_t *auth) -{ - enumerator_t *enumerator; - cert_validation_t valid = VALIDATION_SKIPPED; - certificate_t *best = NULL, *current; - identification_t *keyid = NULL; - public_key_t *public; - chunk_t chunk; - char *uri = NULL; - - /** lookup cache for valid OCSP responses */ - enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE, - KEY_ANY, NULL, FALSE); - while (enumerator->enumerate(enumerator, ¤t)) - { - current->get_ref(current); - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, FALSE); - if (best && valid != VALIDATION_STALE) - { - DBG1(DBG_CFG, " using cached ocsp response"); - break; - } - } - enumerator->destroy(enumerator); - - /* derive the authorityKeyIdentifier from the issuer's public key */ - current = &issuer->interface; - public = current->get_public_key(current); - if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) - { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); - } - /** fetch from configured OCSP responder URLs */ - if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid); - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_ocsp(this, uri, &subject->interface, - &issuer->interface); - if (current) - { - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - DESTROY_IF(public); - DESTROY_IF(keyid); - - /* fallback to URL fetching from subject certificate's URIs */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = subject->create_ocsp_uri_enumerator(subject); - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_ocsp(this, uri, &subject->interface, - &issuer->interface); - if (current) - { - best = get_better_ocsp(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - /* an uri was found, but no result. switch validation state to failed */ - if (valid == VALIDATION_SKIPPED && uri) - { - valid = VALIDATION_FAILED; - } - if (auth) - { - auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid); - if (valid == VALIDATION_GOOD) - { /* successful OCSP check fulfills also CRL constraint */ - auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD); - } - } - DESTROY_IF(best); - return valid; -} - -/** - * fetch a CRL from an URL - */ -static certificate_t* fetch_crl(private_credential_manager_t *this, char *url) -{ - certificate_t *crl; - chunk_t chunk; - - DBG1(DBG_CFG, " fetching crl from '%s' ...", url); - if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS) - { - DBG1(DBG_CFG, "crl fetching failed"); - return NULL; - } - crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, - BUILD_BLOB_ASN1_DER, chunk, BUILD_END); - chunk_free(&chunk); - if (!crl) - { - DBG1(DBG_CFG, "crl fetched successfully but parsing failed"); - return NULL; - } - return crl; -} - -/** - * check the signature of an CRL - */ -static bool verify_crl(private_credential_manager_t *this, certificate_t *crl) -{ - certificate_t *issuer; - enumerator_t *enumerator; - bool verified = FALSE; - - enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl), - FALSE, FALSE); - while (enumerator->enumerate(enumerator, &issuer, NULL)) - { - if (this->cache->issued_by(this->cache, crl, issuer)) - { - DBG1(DBG_CFG, " crl correctly signed by \"%Y\"", - issuer->get_subject(issuer)); - verified = TRUE; - break; - } - } - enumerator->destroy(enumerator); - - return verified; -} - -/** - * Get the better of two CRLs, and check for usable CRL info - */ -static certificate_t *get_better_crl(private_credential_manager_t *this, - certificate_t *cand, certificate_t *best, - x509_t *subject, x509_t *issuer, - cert_validation_t *valid, bool cache) -{ - enumerator_t *enumerator; - time_t revocation, valid_until; - crl_reason_t reason; - chunk_t serial; - crl_t *crl; - - /* check CRL signature */ - if (!verify_crl(this, cand)) - { - DBG1(DBG_CFG, "crl response verification failed"); - cand->destroy(cand); - return best; - } - - crl = (crl_t*)cand; - enumerator = crl->create_enumerator(crl); - while (enumerator->enumerate(enumerator, &serial, &revocation, &reason)) - { - if (chunk_equals(serial, subject->get_serial(subject))) - { - DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N", - &revocation, TRUE, crl_reason_names, reason); - *valid = VALIDATION_REVOKED; - enumerator->destroy(enumerator); - DESTROY_IF(best); - return cand; - } - } - enumerator->destroy(enumerator); - - /* select the better of the two CRLs */ - if (best == NULL || cand->is_newer(cand, best)) - { - DESTROY_IF(best); - best = cand; - if (best->get_validity(best, NULL, NULL, &valid_until)) - { - DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE); - *valid = VALIDATION_GOOD; - if (cache) - { /* we cache non-stale crls only, as a stale crls are refetched */ - cache_cert(this, best); - } - } - else - { - DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE); - *valid = VALIDATION_STALE; - } - } - else - { - *valid = VALIDATION_STALE; - cand->destroy(cand); - } - return best; -} - -/** - * validate a x509 certificate using CRL - */ -static cert_validation_t check_crl(private_credential_manager_t *this, - x509_t *subject, x509_t *issuer, - auth_cfg_t *auth) -{ - cert_validation_t valid = VALIDATION_SKIPPED; - identification_t *keyid = NULL; - certificate_t *best = NULL; - certificate_t *current; - public_key_t *public; - enumerator_t *enumerator; - chunk_t chunk; - char *uri = NULL; - - /* derive the authorityKeyIdentifier from the issuer's public key */ - current = &issuer->interface; - public = current->get_public_key(current); - if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) - { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); - - /* find a cached crl by authorityKeyIdentifier */ - enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY, - keyid, FALSE); - while (enumerator->enumerate(enumerator, ¤t)) - { - current->get_ref(current); - best = get_better_crl(this, current, best, subject, issuer, - &valid, FALSE); - if (best && valid != VALIDATION_STALE) - { - DBG1(DBG_CFG, " using cached crl"); - break; - } - } - enumerator->destroy(enumerator); - - /* fallback to fetching crls from credential sets cdps */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid); - - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_crl(this, uri); - if (current) - { - best = get_better_crl(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - keyid->destroy(keyid); - } - DESTROY_IF(public); - - /* fallback to fetching crls from cdps from subject's certificate */ - if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED) - { - enumerator = subject->create_crl_uri_enumerator(subject); - - while (enumerator->enumerate(enumerator, &uri)) - { - current = fetch_crl(this, uri); - if (current) - { - best = get_better_crl(this, current, best, subject, issuer, - &valid, TRUE); - if (best && valid != VALIDATION_STALE) - { - break; - } - } - } - enumerator->destroy(enumerator); - } - - /* an uri was found, but no result. switch validation state to failed */ - if (valid == VALIDATION_SKIPPED && uri) - { - valid = VALIDATION_FAILED; - } - if (auth) - { - if (valid == VALIDATION_SKIPPED) - { /* if we skipped CRL validation, we use the result of OCSP for - * constraint checking */ - auth->add(auth, AUTH_RULE_CRL_VALIDATION, - auth->get(auth, AUTH_RULE_OCSP_VALIDATION)); - } - else - { - auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid); - } - } - DESTROY_IF(best); - return valid; -} - -/** - * check a certificate for optional IP address block constraints - */ -static bool check_ip_addr_block_constraints(x509_t *subject, x509_t *issuer) -{ - bool subject_constraint = subject->get_flags(subject) & X509_IP_ADDR_BLOCKS; - bool issuer_constraint = issuer->get_flags(issuer) & X509_IP_ADDR_BLOCKS; - bool contained = TRUE; - - enumerator_t *subject_enumerator, *issuer_enumerator; - traffic_selector_t *subject_ts, *issuer_ts; - - if (!subject_constraint && !issuer_constraint) - { - return TRUE; - } - if (!subject_constraint) - { - DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension"); - return FALSE; - } - if (!issuer_constraint) - { - DBG1(DBG_CFG, "issuer certficate lacks ipAddrBlocks extension"); - return FALSE; - } - subject_enumerator = subject->create_ipAddrBlock_enumerator(subject); - while (subject_enumerator->enumerate(subject_enumerator, &subject_ts)) - { - contained = FALSE; - - issuer_enumerator = issuer->create_ipAddrBlock_enumerator(issuer); - while (issuer_enumerator->enumerate(issuer_enumerator, &issuer_ts)) - { - if (subject_ts->is_contained_in(subject_ts, issuer_ts)) - { - DBG2(DBG_CFG, " subject address block %R is contained in " - "issuer address block %R", subject_ts, issuer_ts); - contained = TRUE; - break; - } - } - issuer_enumerator->destroy(issuer_enumerator); - if (!contained) - { - DBG1(DBG_CFG, "subject address block %R is not contained in any " - "issuer address block", subject_ts); - break; - } - } - subject_enumerator->destroy(subject_enumerator); - return contained; -} - -/** - * check a certificate for its lifetime - */ -static bool check_certificate(private_credential_manager_t *this, - certificate_t *subject, certificate_t *issuer, - bool crl, bool ocsp, auth_cfg_t *auth) -{ - time_t not_before, not_after; - - if (!subject->get_validity(subject, NULL, ¬_before, ¬_after)) - { - DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_after, FALSE); - return FALSE; - } - if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after)) - { - DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_after, FALSE); - return FALSE; - } - if (issuer->get_type(issuer) == CERT_X509 && - subject->get_type(subject) == CERT_X509) - { - if (!check_ip_addr_block_constraints((x509_t*)subject, (x509_t*)issuer)) - { - return FALSE; - } - if (ocsp || crl) - { - DBG1(DBG_CFG, "checking certificate status of \"%Y\"", - subject->get_subject(subject)); - } - if (ocsp) - { - switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth)) - { - case VALIDATION_GOOD: - DBG1(DBG_CFG, "certificate status is good"); - return TRUE; - case VALIDATION_REVOKED: - /* has already been logged */ - return FALSE; - case VALIDATION_SKIPPED: - DBG2(DBG_CFG, "ocsp check skipped, no ocsp found"); - break; - case VALIDATION_STALE: - DBG1(DBG_CFG, "ocsp information stale, fallback to crl"); - break; - case VALIDATION_FAILED: - DBG1(DBG_CFG, "ocsp check failed, fallback to crl"); - break; - } - } - if (crl) - { - switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth)) - { - case VALIDATION_GOOD: - DBG1(DBG_CFG, "certificate status is good"); - return TRUE; - case VALIDATION_REVOKED: - /* has already been logged */ - return FALSE; - case VALIDATION_FAILED: - case VALIDATION_SKIPPED: - DBG1(DBG_CFG, "certificate status is not available"); - break; - case VALIDATION_STALE: - DBG1(DBG_CFG, "certificate status is unknown, crl is stale"); - break; - } - } - } - return TRUE; -} - -/** - * Get a trusted certificate from a credential set - */ -static certificate_t *get_pretrusted_cert(private_credential_manager_t *this, - key_type_t type, identification_t *id) -{ - certificate_t *subject; - public_key_t *public; - - subject = get_cert(this, CERT_ANY, type, id, TRUE); - if (!subject) - { - return NULL; - } - public = subject->get_public_key(subject); - if (!public) - { - subject->destroy(subject); - return NULL; - } - public->destroy(public); - return subject; -} - -/** - * Get the issuing certificate of a subject certificate - */ -static certificate_t *get_issuer_cert(private_credential_manager_t *this, - certificate_t *subject, bool trusted) -{ - enumerator_t *enumerator; - certificate_t *issuer = NULL, *candidate; - - enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY, - subject->get_issuer(subject), trusted); - while (enumerator->enumerate(enumerator, &candidate)) - { - if (this->cache->issued_by(this->cache, subject, candidate)) - { - issuer = candidate->get_ref(candidate); - break; - } - } - enumerator->destroy(enumerator); - return issuer; -} - -/** - * try to verify the trust chain of subject, return TRUE if trusted - */ -static bool verify_trust_chain(private_credential_manager_t *this, - certificate_t *subject, auth_cfg_t *result, - bool trusted, bool crl, bool ocsp) -{ - certificate_t *current, *issuer; - x509_t *x509; - auth_cfg_t *auth; - int pathlen, pathlen_constraint; - - auth = auth_cfg_create(); - current = subject->get_ref(subject); - - for (pathlen = 0; pathlen <= X509_MAX_PATH_LEN; pathlen++) - { - issuer = get_issuer_cert(this, current, TRUE); - if (issuer) - { - /* accept only self-signed CAs as trust anchor */ - if (this->cache->issued_by(this->cache, issuer, issuer)) - { - auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer)); - DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"", - issuer->get_subject(issuer)); - trusted = TRUE; - } - else - { - auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer)); - DBG1(DBG_CFG, " using trusted intermediate ca certificate " - "\"%Y\"", issuer->get_subject(issuer)); - } - } - else - { - issuer = get_issuer_cert(this, current, FALSE); - if (issuer) - { - if (current->equals(current, issuer)) - { - DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted", - current->get_subject(current)); - issuer->destroy(issuer); - break; - } - auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer)); - DBG1(DBG_CFG, " using untrusted intermediate certificate " - "\"%Y\"", issuer->get_subject(issuer)); - } - else - { - DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"", - current->get_subject(current)); - break; - } - } - if (!check_certificate(this, current, issuer, crl, ocsp, - current == subject ? auth : NULL)) - { - trusted = FALSE; - issuer->destroy(issuer); - break; - } - - /* check path length constraint */ - x509 = (x509_t*)issuer; - pathlen_constraint = x509->get_pathLenConstraint(x509); - if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT && - pathlen > pathlen_constraint) - { - DBG1(DBG_CFG, "path length of %d violates constraint of %d", - pathlen, pathlen_constraint); - trusted = FALSE; - issuer->destroy(issuer); - break; - } - current->destroy(current); - current = issuer; - if (trusted) - { - DBG1(DBG_CFG, " reached self-signed root ca with a path length of %d", - pathlen); - break; - } - } - current->destroy(current); - if (pathlen > X509_MAX_PATH_LEN) - { - DBG1(DBG_CFG, "maximum path length of %d exceeded", X509_MAX_PATH_LEN); - } - if (trusted) - { - result->merge(result, auth, FALSE); - } - auth->destroy(auth); - return trusted; -} - -/** - * enumerator for trusted certificates - */ -typedef struct { - /** implements enumerator_t interface */ - enumerator_t public; - /** enumerator over candidate peer certificates */ - enumerator_t *candidates; - /** reference to the credential_manager */ - private_credential_manager_t *this; - /** type of the requested key */ - key_type_t type; - /** identity the requested key belongs to */ - identification_t *id; - /** TRUE to do CRL checking */ - bool crl; - /** TRUE to do OCSP checking */ - bool ocsp; - /** pretrusted certificate we have served at first invocation */ - certificate_t *pretrusted; - /** currently enumerating auth config */ - auth_cfg_t *auth; -} trusted_enumerator_t; - -/** - * Implements trusted_enumerator_t.enumerate - */ -static bool trusted_enumerate(trusted_enumerator_t *this, - certificate_t **cert, auth_cfg_t **auth) -{ - certificate_t *current; - - DESTROY_IF(this->auth); - this->auth = auth_cfg_create(); - - if (!this->candidates) - { - /* first invocation, build enumerator for next one */ - this->candidates = create_cert_enumerator(this->this, CERT_ANY, - this->type, this->id, FALSE); - /* check if we have a trusted certificate for that peer */ - this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id); - if (this->pretrusted) - { - /* if we find a trusted self signed certificate, we just accept it. - * However, in order to fulfill authorization rules, we try to build - * the trust chain if it is not self signed */ - if (this->this->cache->issued_by(this->this->cache, - this->pretrusted, this->pretrusted) || - verify_trust_chain(this->this, this->pretrusted, this->auth, - TRUE, this->crl, this->ocsp)) - { - this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT, - this->pretrusted->get_ref(this->pretrusted)); - DBG1(DBG_CFG, " using trusted certificate \"%Y\"", - this->pretrusted->get_subject(this->pretrusted)); - *cert = this->pretrusted; - if (auth) - { - *auth = this->auth; - } - return TRUE; - } - } - } - /* try to verify the trust chain for each certificate found */ - while (this->candidates->enumerate(this->candidates, ¤t)) - { - if (this->pretrusted && - this->pretrusted->equals(this->pretrusted, current)) - { /* skip pretrusted certificate we already served */ - continue; - } - - DBG1(DBG_CFG, " using certificate \"%Y\"", - current->get_subject(current)); - if (verify_trust_chain(this->this, current, this->auth, FALSE, - this->crl, this->ocsp)) - { - *cert = current; - if (auth) - { - *auth = this->auth; - } - return TRUE; - } - } - return FALSE; -} - -/** - * Implements trusted_enumerator_t.destroy - */ -static void trusted_destroy(trusted_enumerator_t *this) -{ - DESTROY_IF(this->pretrusted); - DESTROY_IF(this->auth); - DESTROY_IF(this->candidates); - free(this); -} - -/** - * create an enumerator over trusted certificates and their trustchain - */ -static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this, - key_type_t type, identification_t *id, bool crl, bool ocsp) -{ - trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t); - - enumerator->public.enumerate = (void*)trusted_enumerate; - enumerator->public.destroy = (void*)trusted_destroy; - - enumerator->candidates = NULL; - enumerator->this = this; - enumerator->type = type; - enumerator->id = id; - enumerator->crl = crl; - enumerator->ocsp = ocsp; - enumerator->pretrusted = NULL; - enumerator->auth = NULL; - - return &enumerator->public; -} - -/** - * enumerator for public keys - */ -typedef struct { - /** implements enumerator_t interface */ - enumerator_t public; - /** enumerator over candidate peer certificates */ - enumerator_t *inner; - /** reference to the credential_manager */ - private_credential_manager_t *this; - /** currently enumerating key */ - public_key_t *current; - /** credset wrapper around auth config */ - auth_cfg_wrapper_t *wrapper; -} public_enumerator_t; - -/** - * Implements public_enumerator_t.enumerate - */ -static bool public_enumerate(public_enumerator_t *this, - public_key_t **key, auth_cfg_t **auth) -{ - certificate_t *cert; - - while (this->inner->enumerate(this->inner, &cert, auth)) - { - DESTROY_IF(this->current); - this->current = cert->get_public_key(cert); - if (this->current) - { - *key = this->current; - return TRUE; - } - } - return FALSE; -} - -/** - * Implements public_enumerator_t.destroy - */ -static void public_destroy(public_enumerator_t *this) -{ - DESTROY_IF(this->current); - this->inner->destroy(this->inner); - if (this->wrapper) - { - remove_local_set(this->this, &this->wrapper->set); - this->wrapper->destroy(this->wrapper); - } - this->this->lock->unlock(this->this->lock); - - /* check for delayed certificate cache queue */ - cache_queue(this->this); - free(this); -} - -/** - * Implementation of credential_manager_t.create_public_enumerator. - */ -static enumerator_t* create_public_enumerator(private_credential_manager_t *this, - key_type_t type, identification_t *id, auth_cfg_t *auth) -{ - public_enumerator_t *enumerator = malloc_thing(public_enumerator_t); - - enumerator->public.enumerate = (void*)public_enumerate; - enumerator->public.destroy = (void*)public_destroy; - enumerator->inner = create_trusted_enumerator(this, type, id, TRUE, TRUE); - enumerator->this = this; - enumerator->current = NULL; - enumerator->wrapper = NULL; - if (auth) - { - enumerator->wrapper = auth_cfg_wrapper_create(auth); - add_local_set(this, &enumerator->wrapper->set); - } - this->lock->read_lock(this->lock); - return &enumerator->public; -} - -/** - * Check if a certificate's keyid is contained in the auth helper - */ -static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert) -{ - enumerator_t *enumerator; - identification_t *value; - auth_rule_t type; - bool found = FALSE; - - enumerator = auth->create_enumerator(auth); - while (enumerator->enumerate(enumerator, &type, &value)) - { - if (type == AUTH_RULE_CA_CERT && - cert->equals(cert, (certificate_t*)value)) - { - found = TRUE; - break; - } - } - enumerator->destroy(enumerator); - return found; -} - -/** - * build a trustchain from subject up to a trust anchor in trusted - */ -static auth_cfg_t *build_trustchain(private_credential_manager_t *this, - certificate_t *subject, auth_cfg_t *auth) -{ - certificate_t *issuer, *current; - auth_cfg_t *trustchain; - int pathlen = 0; - - trustchain = auth_cfg_create(); - - current = auth->get(auth, AUTH_RULE_CA_CERT); - if (!current) - { - /* no trust anchor specified, return this cert only */ - trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, - subject->get_ref(subject)); - return trustchain; - } - current = subject->get_ref(subject); - while (TRUE) - { - if (auth_contains_cacert(auth, current)) - { - trustchain->add(trustchain, AUTH_RULE_CA_CERT, current); - return trustchain; - } - if (subject == current) - { - trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current); - } - else - { - trustchain->add(trustchain, AUTH_RULE_IM_CERT, current); - } - issuer = get_issuer_cert(this, current, FALSE); - if (!issuer || issuer->equals(issuer, current) || - pathlen > X509_MAX_PATH_LEN) - { - DESTROY_IF(issuer); - break; - } - current = issuer; - pathlen++; - } - trustchain->destroy(trustchain); - return NULL; -} - -/** - * find a private key of a give certificate - */ -static private_key_t *get_private_by_cert(private_credential_manager_t *this, - certificate_t *cert, key_type_t type) -{ - private_key_t *private = NULL; - identification_t *keyid; - chunk_t chunk; - public_key_t *public; - - public = cert->get_public_key(cert); - if (public) - { - if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk)) - { - keyid = identification_create_from_encoding(ID_KEY_ID, chunk); - private = get_private_by_keyid(this, type, keyid); - keyid->destroy(keyid); - } - public->destroy(public); - } - return private; -} - -/** - * Implementation of credential_manager_t.get_private. - */ -static private_key_t *get_private(private_credential_manager_t *this, - key_type_t type, identification_t *id, - auth_cfg_t *auth) -{ - enumerator_t *enumerator; - certificate_t *cert; - private_key_t *private = NULL; - auth_cfg_t *trustchain; - - /* check if this is a lookup by key ID, and do it if so */ - if (id && id->get_type(id) == ID_KEY_ID) - { - private = get_private_by_keyid(this, type, id); - if (private) - { - return private; - } - } - - /* if a specific certificate is preferred, check for a matching key */ - cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); - if (cert) - { - private = get_private_by_cert(this, cert, type); - if (private) - { - trustchain = build_trustchain(this, cert, auth); - if (trustchain) - { - auth->merge(auth, trustchain, FALSE); - trustchain->destroy(trustchain); - } - return private; - } - } - - /* try to build a trust chain for each certificate found */ - enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE); - while (enumerator->enumerate(enumerator, &cert)) - { - private = get_private_by_cert(this, cert, type); - if (private) - { - trustchain = build_trustchain(this, cert, auth); - if (trustchain) - { - auth->merge(auth, trustchain, FALSE); - trustchain->destroy(trustchain); - break; - } - private->destroy(private); - private = NULL; - } - } - enumerator->destroy(enumerator); - - /* if no valid trustchain was found, fall back to the first usable cert */ - if (!private) - { - enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE); - while (enumerator->enumerate(enumerator, &cert)) - { - private = get_private_by_cert(this, cert, type); - if (private) - { - auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert)); - break; - } - } - enumerator->destroy(enumerator); - } - return private; -} - -/** - * Implementation of credential_manager_t.flush_cache. - */ -static void flush_cache(private_credential_manager_t *this, - certificate_type_t type) -{ - this->cache->flush(this->cache, type); -} - -/** - * Implementation of credential_manager_t.add_set. - */ -static void add_set(private_credential_manager_t *this, - credential_set_t *set) -{ - this->lock->write_lock(this->lock); - this->sets->insert_last(this->sets, set); - this->lock->unlock(this->lock); -} - -/** - * Implementation of credential_manager_t.remove_set. - */ -static void remove_set(private_credential_manager_t *this, credential_set_t *set) -{ - this->lock->write_lock(this->lock); - this->sets->remove(this->sets, set, NULL); - this->lock->unlock(this->lock); -} - -/** - * Implementation of credential_manager_t.destroy - */ -static void destroy(private_credential_manager_t *this) -{ - cache_queue(this); - this->cache_queue->destroy(this->cache_queue); - this->sets->remove(this->sets, this->cache, NULL); - this->sets->destroy(this->sets); - this->local_sets->destroy(this->local_sets); - this->cache->destroy(this->cache); - this->lock->destroy(this->lock); - this->queue_mutex->destroy(this->queue_mutex); - free(this); -} - -/* - * see header file - */ -credential_manager_t *credential_manager_create() -{ - private_credential_manager_t *this = malloc_thing(private_credential_manager_t); - - this->public.create_cert_enumerator = (enumerator_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *id,bool))create_cert_enumerator; - this->public.create_shared_enumerator = (enumerator_t *(*)(credential_manager_t *this, shared_key_type_t type,identification_t *me, identification_t *other))create_shared_enumerator; - this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, certificate_type_t type, identification_t *id))create_cdp_enumerator; - this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert; - this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared; - this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_cfg_t*))get_private; - this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_cfg_t *aut))create_public_enumerator; - this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache; - this->public.cache_cert = (void(*)(credential_manager_t*, certificate_t *cert))cache_cert; - this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set; - this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set; - this->public.destroy = (void(*)(credential_manager_t*))destroy; - - this->sets = linked_list_create(); - this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy); - this->cache = cert_cache_create(); - this->cache_queue = linked_list_create(); - this->sets->insert_first(this->sets, this->cache); - this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - this->queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT); - - return &this->public; -} - diff --git a/src/libcharon/credentials/credential_manager.h b/src/libcharon/credentials/credential_manager.h deleted file mode 100644 index 0448da992..000000000 --- a/src/libcharon/credentials/credential_manager.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2007-2009 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup credential_manager credential_manager - * @{ @ingroup ccredentials - */ - -#ifndef CREDENTIAL_MANAGER_H_ -#define CREDENTIAL_MANAGER_H_ - -#include <utils/identification.h> -#include <utils/enumerator.h> -#include <config/auth_cfg.h> -#include <credentials/credential_set.h> -#include <credentials/keys/private_key.h> -#include <credentials/keys/shared_key.h> -#include <credentials/certificates/certificate.h> - -typedef struct credential_manager_t credential_manager_t; - -/** - * Manages credentials using credential_sets. - * - * The credential manager is the entry point of the credential framework. It - * uses so called "sets" to access credentials in a modular fashion, these - * are implemented through the credential_set_t interface. - * The manager additionally does trust chain verification and trust status - * chaching. A set may call the managers methods if it needs credentials itself, - * the manager uses recursive locking. - * - * @verbatim - - +-------+ +----------------+ - | A | | | +------------------+ - | u | -----> | | ------> | +------------------+ - | t | | credential- | | | +------------------+ - | h | -----> | manager | ------> +--| | credential- | => IPC - | e | | | +--| sets | - | n | +--> | | ------> +------------------+ - | t | | | | | - | i | | | | | - | c | | +----------------+ | - | a | | | - | t | +----------------------------------------------+ - | o | may be recursive - | r | - +-------+ - - @endverbatim - * - * The credential manager uses rwlocks for performance reasons, credential - * sets must be fully thread save. - */ -struct credential_manager_t { - - /** - * Create an enumerator over all certificates. - * - * @param cert kind of certificate - * @param key kind of key in certificate - * @param id subject this certificate belongs to - * @param trusted TRUE to list trusted certificates only - * @return enumerator over the certificates - */ - enumerator_t *(*create_cert_enumerator)(credential_manager_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted); - /** - * Create an enumerator over all shared keys. - * - * The enumerator enumerates over: - * shared_key_t*, id_match_t me, id_match_t other - * But must accepts values for the id_matches. - * - * @param type kind of requested shared key - * @param first first subject between key is shared - * @param second second subject between key is shared - * @return enumerator over shared keys - */ - enumerator_t *(*create_shared_enumerator)(credential_manager_t *this, - shared_key_type_t type, - identification_t *first, identification_t *second); - /** - * Create an enumerator over all Certificate Distribution Points. - * - * @param type kind of certificate the point distributes - * @param id identification of the distributed certificate - * @return enumerator of CDPs as char* - */ - enumerator_t *(*create_cdp_enumerator)(credential_manager_t *this, - certificate_type_t type, identification_t *id); - /** - * Get a trusted or untrusted certificate. - * - * @param cert kind of certificate - * @param key kind of key in certificate - * @param id subject this certificate belongs to - * @param trusted TRUE to get a trusted certificate only - * @return certificate, if found, NULL otherwise - */ - certificate_t *(*get_cert)(credential_manager_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted); - /** - * Get the best matching shared key for two IDs. - * - * @param type kind of requested shared key - * @param me own identity - * @param other peers identity - * @return shared_key_t, NULL if none found - */ - shared_key_t *(*get_shared)(credential_manager_t *this, shared_key_type_t type, - identification_t *me, identification_t *other); - /** - * Get a private key to create a signature. - * - * The get_private() method gets a secret private key identified by either - * the keyid itself or an id the key belongs to. - * The auth parameter contains additional information, such as receipients - * trusted CA certs. Auth gets filled with subject and CA certificates - * needed to validate a created signature. - * - * @param type type of the key to get - * @param id identification the key belongs to - * @param auth auth config, including trusted CA certificates - * @return private_key_t, NULL if none found - */ - private_key_t* (*get_private)(credential_manager_t *this, key_type_t type, - identification_t *id, auth_cfg_t *auth); - - /** - * Create an enumerator over trusted public keys. - * - * This method gets a an enumerator over trusted public keys to verify a - * signature created by id. The auth parameter contains additional - * authentication infos, e.g. peer and intermediate certificates. - * The resulting enumerator enumerates over public_key_t *, auth_cfg_t *, - * where the auth config helper contains rules for constraint checks. - * - * @param type type of the key to get - * @param id owner of the key, signer of the signature - * @param auth authentication infos - * @return enumerator - */ - enumerator_t* (*create_public_enumerator)(credential_manager_t *this, - key_type_t type, identification_t *id, auth_cfg_t *auth); - - /** - * Cache a certificate by invoking cache_cert() on all registerd sets. - * - * @param cert certificate to cache - */ - void (*cache_cert)(credential_manager_t *this, certificate_t *cert); - - /** - * Flush the certificate cache. - * - * Only the managers local cache is flushed, but not the sets cache filled - * by the cache_cert() method. - * - * @param type type of certificate to flush, or CERT_ANY - */ - void (*flush_cache)(credential_manager_t *this, certificate_type_t type); - - /** - * Register a credential set to the manager. - * - * @param set set to register - */ - void (*add_set)(credential_manager_t *this, credential_set_t *set); - - /** - * Unregister a credential set from the manager. - * - * @param set set to unregister - */ - void (*remove_set)(credential_manager_t *this, credential_set_t *set); - - /** - * Destroy a credential_manager instance. - */ - void (*destroy)(credential_manager_t *this); -}; - -/** - * Create a credential_manager instance. - */ -credential_manager_t *credential_manager_create(); - -#endif /** CREDENTIAL_MANAGER_H_ @}*/ diff --git a/src/libcharon/credentials/credential_set.h b/src/libcharon/credentials/credential_set.h deleted file mode 100644 index 274eb3feb..000000000 --- a/src/libcharon/credentials/credential_set.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup credential_set credential_set - * @{ @ingroup ccredentials - */ - -#ifndef CREDENTIAL_SET_H_ -#define CREDENTIAL_SET_H_ - -#include <credentials/keys/public_key.h> -#include <credentials/keys/shared_key.h> -#include <credentials/certificates/certificate.h> - -typedef struct credential_set_t credential_set_t; - -/** - * A set of credentials. - * - * Contains private keys, shared keys and different kinds of certificates. - * Enumerators are used because queries might return multiple matches. - * Filter parameters restrict enumeration over specific items only. - * See credential_manager_t for an overview of the credential framework. - * - * A credential set enumerator may not block the credential set, i.e. multiple - * threads must be able to hold multiple enumerators, as the credential manager - * is higly parallelized. The best way to achieve this is by using shared - * read locks for the enumerators only. Otherwiese deadlocks will occur. - * The writing cache_cert() routine is called by the manager only if no - * enumerator is alive, so it is save to use a write lock there. - */ -struct credential_set_t { - - /** - * Create an enumerator over private keys (private_key_t). - * - * The id is either a key identifier of the requested key, or an identity - * of the key owner. - * - * @param type type of requested private key - * @param id key identifier/owner - * @return enumerator over private_key_t's. - */ - enumerator_t *(*create_private_enumerator)(credential_set_t *this, - key_type_t type, identification_t *id); - /** - * Create an enumerator over certificates (certificate_t). - * - * @param cert kind of certificate - * @param key kind of key in certificate - * @param id identity (subject) this certificate belongs to - * @param trusted whether the certificate must be trustworthy - * @return enumerator as described above - */ - enumerator_t *(*create_cert_enumerator)(credential_set_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted); - /** - * Create an enumerator over shared keys (shared_key_t). - * - * The enumerator enumerates over: - * shared_key_t*, id_match_t me, id_match_t other - * But must accept NULL values for the id_matches. - * - * @param type kind of requested shared key - * @param me own identity - * @param other other identity who owns that secret - * @return enumerator as described above - */ - enumerator_t *(*create_shared_enumerator)(credential_set_t *this, - shared_key_type_t type, - identification_t *me, identification_t *other); - - /** - * Create an enumerator over certificate distribution points. - * - * @param type type of the certificate to get a CDP - * @param id identification of the distributed certificate - * @return an enumerator over CDPs as char* - */ - enumerator_t *(*create_cdp_enumerator)(credential_set_t *this, - certificate_type_t type, identification_t *id); - - /** - * Cache a certificate in the credential set. - * - * The caching policy is implementation dependent, the sets may cache the - * certificate in-memory, persistent on disk or not at all. - * - * @param cert certificate to cache - */ - void (*cache_cert)(credential_set_t *this, certificate_t *cert); -}; - -#endif /** CREDENTIAL_SET_H_ @}*/ diff --git a/src/libcharon/credentials/sets/auth_cfg_wrapper.c b/src/libcharon/credentials/sets/auth_cfg_wrapper.c deleted file mode 100644 index 82e33d283..000000000 --- a/src/libcharon/credentials/sets/auth_cfg_wrapper.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2008-2009 Martin Willi - * Copyright (C) 2008 Tobias Brunner - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <daemon.h> - -#include "auth_cfg_wrapper.h" - -typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t; - -/** - * private data of auth_cfg_wrapper - */ -struct private_auth_cfg_wrapper_t { - - /** - * public functions - */ - auth_cfg_wrapper_t public; - - /** - * wrapped auth info - */ - auth_cfg_t *auth; -}; - -/** - * enumerator for auth_cfg_wrapper_t.create_cert_enumerator() - */ -typedef struct { - /** implements enumerator_t */ - enumerator_t public; - /** inner enumerator from auth_cfg */ - enumerator_t *inner; - /** wrapped auth round */ - auth_cfg_t *auth; - /** enumerated cert type */ - certificate_type_t cert; - /** enumerated key type */ - key_type_t key; - /** enumerated id */ - identification_t *id; -} wrapper_enumerator_t; - -/** - * Tries to fetch a certificate that was supplied as "Hash and URL" - * (replaces rule type and value in place). - */ -static bool fetch_cert(wrapper_enumerator_t *enumerator, - auth_rule_t *rule, void **value) -{ - char *url = (char*)*value; - if (!url) - { - /* fetching the certificate previously failed */ - return FALSE; - } - - chunk_t data; - certificate_t *cert; - - DBG1(DBG_CFG, " fetching certificate from '%s' ...", url); - if (lib->fetcher->fetch(lib->fetcher, url, &data, FETCH_END) != SUCCESS) - { - DBG1(DBG_CFG, " fetching certificate failed"); - /* we set the item to NULL, so we can skip it */ - enumerator->auth->replace(enumerator->auth, enumerator->inner, - *rule, NULL); - return FALSE; - } - - cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_ASN1_DER, data, BUILD_END); - free(data.ptr); - - if (!cert) - { - DBG1(DBG_CFG, " parsing fetched certificate failed"); - /* we set the item to NULL, so we can skip it */ - enumerator->auth->replace(enumerator->auth, enumerator->inner, - *rule, NULL); - return FALSE; - } - - DBG1(DBG_CFG, " fetched certificate \"%Y\"", cert->get_subject(cert)); - charon->credentials->cache_cert(charon->credentials, cert); - - if (*rule == AUTH_HELPER_IM_HASH_URL) - { - *rule = AUTH_HELPER_IM_CERT; - } - else - { - *rule = AUTH_HELPER_SUBJECT_CERT; - } - *value = cert; - enumerator->auth->replace(enumerator->auth, enumerator->inner, - *rule, cert->get_ref(cert)); - return TRUE; -} - -/** - * enumerate function for wrapper_enumerator_t - */ -static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) -{ - auth_rule_t rule; - certificate_t *current; - public_key_t *public; - - while (this->inner->enumerate(this->inner, &rule, ¤t)) - { - if (rule == AUTH_HELPER_IM_HASH_URL || - rule == AUTH_HELPER_SUBJECT_HASH_URL) - { /* on-demand fetching of hash and url certificates */ - if (!fetch_cert(this, &rule, (void**)¤t)) - { - continue; - } - } - else if (rule != AUTH_HELPER_SUBJECT_CERT && - rule != AUTH_HELPER_IM_CERT) - { /* handle only HELPER certificates */ - continue; - } - if (this->cert != CERT_ANY && this->cert != current->get_type(current)) - { /* CERT type requested, but does not match */ - continue; - } - public = current->get_public_key(current); - if (this->key != KEY_ANY && !public) - { /* key type requested, but no public key */ - DESTROY_IF(public); - continue; - } - if (this->key != KEY_ANY && public && this->key != public->get_type(public)) - { /* key type requested, but public key has another type */ - DESTROY_IF(public); - continue; - } - DESTROY_IF(public); - if (this->id && !current->has_subject(current, this->id)) - { /* subject requested, but does not match */ - continue; - } - *cert = current; - return TRUE; - } - return FALSE; -} - -/** - * destroy function for wrapper_enumerator_t - */ -static void wrapper_enumerator_destroy(wrapper_enumerator_t *this) -{ - this->inner->destroy(this->inner); - free(this); -} - -/** - * implementation of auth_cfg_wrapper_t.set.create_cert_enumerator - */ -static enumerator_t *create_enumerator(private_auth_cfg_wrapper_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - wrapper_enumerator_t *enumerator; - - if (trusted) - { - return NULL; - } - enumerator = malloc_thing(wrapper_enumerator_t); - enumerator->auth = this->auth; - enumerator->cert = cert; - enumerator->key = key; - enumerator->id = id; - enumerator->inner = this->auth->create_enumerator(this->auth); - enumerator->public.enumerate = (void*)enumerate; - enumerator->public.destroy = (void*)wrapper_enumerator_destroy; - return &enumerator->public; -} - -/** - * Implementation of auth_cfg_wrapper_t.destroy - */ -static void destroy(private_auth_cfg_wrapper_t *this) -{ - free(this); -} - -/* - * see header file - */ -auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth) -{ - private_auth_cfg_wrapper_t *this = malloc_thing(private_auth_cfg_wrapper_t); - - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)create_enumerator; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - this->public.destroy = (void(*)(auth_cfg_wrapper_t*))destroy; - - this->auth = auth; - - return &this->public; -} - diff --git a/src/libcharon/credentials/sets/auth_cfg_wrapper.h b/src/libcharon/credentials/sets/auth_cfg_wrapper.h deleted file mode 100644 index 7653fcdbf..000000000 --- a/src/libcharon/credentials/sets/auth_cfg_wrapper.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008-2009 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup auth_cfg_wrapper auth_cfg_wrapper - * @{ @ingroup sets - */ - -#ifndef AUTH_CFG_WRAPPER_H_ -#define AUTH_CFG_WRAPPER_H_ - -#include <config/auth_cfg.h> -#include <credentials/credential_set.h> - -typedef struct auth_cfg_wrapper_t auth_cfg_wrapper_t; - -/** - * A wrapper around auth_cfg_t to handle it as a credential set. - */ -struct auth_cfg_wrapper_t { - - /** - * implements credential_set_t - */ - credential_set_t set; - - /** - * Destroy a auth_cfg_wrapper instance. - */ - void (*destroy)(auth_cfg_wrapper_t *this); -}; - -/** - * Create a auth_cfg_wrapper instance. - * - * @param auth the wrapped auth info - * @return wrapper around auth - */ -auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth); - -#endif /** AUTH_CFG_WRAPPER_H_ @}*/ diff --git a/src/libcharon/credentials/sets/cert_cache.c b/src/libcharon/credentials/sets/cert_cache.c deleted file mode 100644 index 176accce2..000000000 --- a/src/libcharon/credentials/sets/cert_cache.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "cert_cache.h" - -#include <time.h> -#include <sched.h> - -#include <daemon.h> -#include <threading/rwlock.h> -#include <utils/linked_list.h> - -/** cache size, a power of 2 for fast modulo */ -#define CACHE_SIZE 32 - -/** attempts to acquire a cache lock */ -#define REPLACE_TRIES 5 - -typedef struct private_cert_cache_t private_cert_cache_t; -typedef struct relation_t relation_t; - -/** - * A trusted relation between subject and issuer - */ -struct relation_t { - - /** - * subject of this relation - */ - certificate_t *subject; - - /** - * issuer of this relation - */ - certificate_t *issuer; - - /** - * Cache hits - */ - u_int hits; - - /** - * Lock for this relation - */ - rwlock_t *lock; -}; - -/** - * private data of cert_cache - */ -struct private_cert_cache_t { - - /** - * public functions - */ - cert_cache_t public; - - /** - * array of trusted subject-issuer relations - */ - relation_t relations[CACHE_SIZE]; -}; - -/** - * Cache relation in a free slot/replace an other - */ -static void cache(private_cert_cache_t *this, - certificate_t *subject, certificate_t *issuer) -{ - relation_t *rel; - int i, offset, try; - u_int total_hits = 0; - - /* check for a unused relation slot first */ - for (i = 0; i < CACHE_SIZE; i++) - { - rel = &this->relations[i]; - - if (!rel->subject && rel->lock->try_write_lock(rel->lock)) - { - /* double-check having lock */ - if (!rel->subject) - { - rel->subject = subject->get_ref(subject); - rel->issuer = issuer->get_ref(issuer); - return rel->lock->unlock(rel->lock); - } - rel->lock->unlock(rel->lock); - } - total_hits += rel->hits; - } - /* run several attempts to replace a random slot, never block. */ - for (try = 0; try < REPLACE_TRIES; try++) - { - /* replace a random relation */ - offset = random(); - for (i = 0; i < CACHE_SIZE; i++) - { - rel = &this->relations[(i + offset) % CACHE_SIZE]; - - if (rel->hits > total_hits / CACHE_SIZE) - { /* skip often used slots */ - continue; - } - if (rel->lock->try_write_lock(rel->lock)) - { - if (rel->subject) - { - rel->subject->destroy(rel->subject); - rel->issuer->destroy(rel->issuer); - } - rel->subject = subject->get_ref(subject); - rel->issuer = issuer->get_ref(issuer); - rel->hits = 0; - return rel->lock->unlock(rel->lock); - } - } - /* give other threads a chance to release locks */ - sched_yield(); - } -} - -/** - * Implementation of cert_cache_t.issued_by. - */ -static bool issued_by(private_cert_cache_t *this, - certificate_t *subject, certificate_t *issuer) -{ - relation_t *found = NULL, *current; - int i; - - for (i = 0; i < CACHE_SIZE; i++) - { - current = &this->relations[i]; - - current->lock->read_lock(current->lock); - if (current->subject) - { - /* check for equal issuer */ - if (issuer->equals(issuer, current->issuer)) - { - /* reuse issuer instance in cache() */ - issuer = current->issuer; - if (subject->equals(subject, current->subject)) - { - /* write hit counter is not locked, but not critical */ - current->hits++; - found = current; - } - } - } - current->lock->unlock(current->lock); - if (found) - { - return TRUE; - } - } - /* no cache hit, check and cache signature */ - if (subject->issued_by(subject, issuer)) - { - cache(this, subject, issuer); - return TRUE; - } - return FALSE; -} - -/** - * certificate enumerator implemenation - */ -typedef struct { - /** implements enumerator_t interface */ - enumerator_t public; - /** type of requested certificate */ - certificate_type_t cert; - /** type of requested key */ - key_type_t key; - /** ID to get a cert for */ - identification_t *id; - /** cache */ - relation_t *relations; - /** current position in array cache */ - int index; - /** currently locked relation */ - int locked; -} cert_enumerator_t; - -/** - * filter function for certs enumerator - */ -static bool cert_enumerate(cert_enumerator_t *this, certificate_t **out) -{ - public_key_t *public; - relation_t *rel; - - if (this->locked >= 0) - { - rel = &this->relations[this->locked]; - rel->lock->unlock(rel->lock); - this->locked = -1; - } - - while (++this->index < CACHE_SIZE) - { - rel = &this->relations[this->index]; - rel->lock->read_lock(rel->lock); - this->locked = this->index; - if (rel->subject) - { - /* CRL lookup is done using issuer/authkeyidentifier */ - if (this->key == KEY_ANY && this->id && - (this->cert == CERT_ANY || this->cert == CERT_X509_CRL) && - rel->subject->get_type(rel->subject) == CERT_X509_CRL && - rel->subject->has_issuer(rel->subject, this->id)) - { - *out = rel->subject; - return TRUE; - } - if ((this->cert == CERT_ANY || - rel->subject->get_type(rel->subject) == this->cert) && - (!this->id || rel->subject->has_subject(rel->subject, this->id))) - { - if (this->key == KEY_ANY) - { - *out = rel->subject; - return TRUE; - } - public = rel->subject->get_public_key(rel->subject); - if (public) - { - if (public->get_type(public) == this->key) - { - public->destroy(public); - *out = rel->subject; - return TRUE; - } - public->destroy(public); - } - } - } - this->locked = -1; - rel->lock->unlock(rel->lock); - } - return FALSE; -} - -/** - * clean up enumeration data - */ -static void cert_enumerator_destroy(cert_enumerator_t *this) -{ - relation_t *rel; - - if (this->locked >= 0) - { - rel = &this->relations[this->locked]; - rel->lock->unlock(rel->lock); - } - free(this); -} - -/** - * implementation of credential_set_t.create_cert_enumerator - */ -static enumerator_t *create_enumerator(private_cert_cache_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - cert_enumerator_t *enumerator; - - if (trusted) - { - return NULL; - } - enumerator = malloc_thing(cert_enumerator_t); - enumerator->public.enumerate = (void*)cert_enumerate; - enumerator->public.destroy = (void*)cert_enumerator_destroy; - enumerator->cert = cert; - enumerator->key = key; - enumerator->id = id; - enumerator->relations = this->relations; - enumerator->index = -1; - enumerator->locked = -1; - - return &enumerator->public; -} - -/** - * Implementation of cert_cache_t.flush. - */ -static void flush(private_cert_cache_t *this, certificate_type_t type) -{ - relation_t *rel; - int i; - - for (i = 0; i < CACHE_SIZE; i++) - { - rel = &this->relations[i]; - if (!rel->subject) - { - continue; - } - /* check with cheap read lock first */ - if (type != CERT_ANY) - { - rel->lock->read_lock(rel->lock); - if (!rel->subject || type != rel->subject->get_type(rel->subject)) - { - rel->lock->unlock(rel->lock); - continue; - } - rel->lock->unlock(rel->lock); - } - /* double check in write lock */ - rel->lock->write_lock(rel->lock); - if (rel->subject) - { - if (type == CERT_ANY || type == rel->subject->get_type(rel->subject)) - { - rel->subject->destroy(rel->subject); - rel->issuer->destroy(rel->issuer); - rel->subject = NULL; - rel->issuer = NULL; - rel->hits = 0; - } - } - rel->lock->unlock(rel->lock); - } -} - -/** - * Implementation of cert_cache_t.destroy - */ -static void destroy(private_cert_cache_t *this) -{ - relation_t *rel; - int i; - - for (i = 0; i < CACHE_SIZE; i++) - { - rel = &this->relations[i]; - if (rel->subject) - { - rel->subject->destroy(rel->subject); - rel->issuer->destroy(rel->issuer); - } - rel->lock->destroy(rel->lock); - } - free(this); -} - -/* - * see header file - */ -cert_cache_t *cert_cache_create() -{ - private_cert_cache_t *this; - int i; - - this = malloc_thing(private_cert_cache_t); - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)create_enumerator; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - this->public.issued_by = (bool(*)(cert_cache_t*, certificate_t *subject, certificate_t *issuer))issued_by; - this->public.flush = (void(*)(cert_cache_t*, certificate_type_t type))flush; - this->public.destroy = (void(*)(cert_cache_t*))destroy; - - for (i = 0; i < CACHE_SIZE; i++) - { - this->relations[i].subject = NULL; - this->relations[i].issuer = NULL; - this->relations[i].hits = 0; - this->relations[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - } - return &this->public; -} - diff --git a/src/libcharon/credentials/sets/cert_cache.h b/src/libcharon/credentials/sets/cert_cache.h deleted file mode 100644 index d2721866e..000000000 --- a/src/libcharon/credentials/sets/cert_cache.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup cert_cache cert_cache - * @{ @ingroup sets - */ - -#ifndef CERT_CACHE_H_ -#define CERT_CACHE_H_ - -#include <credentials/credential_set.h> - -typedef struct cert_cache_t cert_cache_t; - -/** - * Certificate signature verification and certificate cache. - * - * This cache serves all certificates seen in its issued_by method - * and serves them as untrusted through the credential set interface. Further, - * it caches valid subject-issuer relationships to speed up the issued_by - * method. - */ -struct cert_cache_t { - - /** - * Implements credential_set_t. - */ - credential_set_t set; - - /** - * Caching wrapper around certificate_t.issued_by. - * - * @param subject certificate to verify - * @param issuer issuing certificate to verify subject - * @return TRUE if subject issued by issuer - */ - bool (*issued_by)(cert_cache_t *this, - certificate_t *subject, certificate_t *issuer); - - /** - * Flush the certificate cache. - * - * @param type type of certificate to flush, or CERT_ANY - */ - void (*flush)(cert_cache_t *this, certificate_type_t type); - - /** - * Destroy a cert_cache instance. - */ - void (*destroy)(cert_cache_t *this); -}; - -/** - * Create a cert_cache instance. - */ -cert_cache_t *cert_cache_create(); - -#endif /** CERT_CACHE_H_ @}*/ diff --git a/src/libcharon/credentials/sets/ocsp_response_wrapper.c b/src/libcharon/credentials/sets/ocsp_response_wrapper.c deleted file mode 100644 index 82079209a..000000000 --- a/src/libcharon/credentials/sets/ocsp_response_wrapper.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include "ocsp_response_wrapper.h" - -typedef struct private_ocsp_response_wrapper_t private_ocsp_response_wrapper_t; - -/** - * private data of ocsp_response_wrapper - */ -struct private_ocsp_response_wrapper_t { - - /** - * public functions - */ - ocsp_response_wrapper_t public; - - /** - * wrapped OCSP response - */ - ocsp_response_t *response; -}; - -/** - * enumerator for ocsp_response_wrapper_t.create_cert_enumerator() - */ -typedef struct { - /** implements enumerator_t */ - enumerator_t public; - /** enumerator over ocsp response */ - enumerator_t *inner; - /** type of cert */ - certificate_type_t cert; - /** type of key */ - key_type_t key; - /** filtering identity */ - identification_t *id; -} wrapper_enumerator_t; - -/** - * enumerate function wrapper_enumerator_t - */ -static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) -{ - certificate_t *current; - public_key_t *public; - - while (this->inner->enumerate(this->inner, ¤t)) - { - if (this->cert != CERT_ANY && this->cert != current->get_type(current)) - { /* CERT type requested, but does not match */ - continue; - } - public = current->get_public_key(current); - if (this->key != KEY_ANY && !public) - { /* key type requested, but no public key */ - DESTROY_IF(public); - continue; - } - if (this->key != KEY_ANY && public && this->key != public->get_type(public)) - { /* key type requested, but public key has another type */ - DESTROY_IF(public); - continue; - } - DESTROY_IF(public); - if (this->id && !current->has_subject(current, this->id)) - { /* subject requested, but does not match */ - continue; - } - *cert = current; - return TRUE; - } - return FALSE; -} - -/** - * destroy function for wrapper_enumerator_t - */ -static void enumerator_destroy(wrapper_enumerator_t *this) -{ - this->inner->destroy(this->inner); - free(this); -} - -/** - * implementation of ocsp_response_wrapper_t.set.create_cert_enumerator - */ -static enumerator_t *create_enumerator(private_ocsp_response_wrapper_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - wrapper_enumerator_t *enumerator; - - if (trusted) - { - return NULL; - } - - enumerator = malloc_thing(wrapper_enumerator_t); - enumerator->cert = cert; - enumerator->key = key; - enumerator->id = id; - enumerator->inner = this->response->create_cert_enumerator(this->response); - enumerator->public.enumerate = (void*)enumerate; - enumerator->public.destroy = (void*)enumerator_destroy; - return &enumerator->public; -} - -/** - * Implementation of ocsp_response_wrapper_t.destroy - */ -static void destroy(private_ocsp_response_wrapper_t *this) -{ - free(this); -} - -/* - * see header file - */ -ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response) -{ - private_ocsp_response_wrapper_t *this = malloc_thing(private_ocsp_response_wrapper_t); - - this->public.set.create_private_enumerator = (void*)return_null; - this->public.set.create_cert_enumerator = (void*)create_enumerator; - this->public.set.create_shared_enumerator = (void*)return_null; - this->public.set.create_cdp_enumerator = (void*)return_null; - this->public.set.cache_cert = (void*)nop; - this->public.destroy = (void(*)(ocsp_response_wrapper_t*))destroy; - - this->response = response; - - return &this->public; -} - diff --git a/src/libcharon/credentials/sets/ocsp_response_wrapper.h b/src/libcharon/credentials/sets/ocsp_response_wrapper.h deleted file mode 100644 index dc4b451df..000000000 --- a/src/libcharon/credentials/sets/ocsp_response_wrapper.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -/** - * @defgroup ocsp_response_wrapper ocsp_response_wrapper - * @{ @ingroup sets - */ - -#ifndef OCSP_RESPONSE_WRAPPER_H_ -#define OCSP_RESPONSE_WRAPPER_H_ - -#include <credentials/credential_set.h> -#include <credentials/certificates/ocsp_response.h> - -typedef struct ocsp_response_wrapper_t ocsp_response_wrapper_t; - -/** - * A wrapper around ocsp_response_t to handle it like a credential set. - */ -struct ocsp_response_wrapper_t { - - /** - * implements credential_set_t - */ - credential_set_t set; - - /** - * Destroy a ocsp_response_wrapper instance. - */ - void (*destroy)(ocsp_response_wrapper_t *this); -}; - -/** - * Create a ocsp_response_wrapper instance. - * - * @param response the wrapped OCSP response - * @return wrapper around response - */ -ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response); - -#endif /** OCSP_RESPONSE_WRAPPER_H_ @}*/ |