From: Martin Willi Date: Wed, 19 Mar 2008 17:54:54 +0000 (-0000) Subject: refactored trustchain verification, this should fix #33 X-Git-Tag: 4.2.0~116 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=48acfe98ae504894d02767e475cfba67e6295827;p=thirdparty%2Fstrongswan.git refactored trustchain verification, this should fix #33 moved auth_info/ocsp_response credset wrapper to separate files --- diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 0ee61cd087..bbfe221688 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -86,6 +86,8 @@ sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \ sa/tasks/task.c sa/tasks/task.h \ credentials/credential_manager.c credentials/credential_manager.h \ credentials/auth_info.c credentials/auth_info.h \ +credentials/sets/auth_info_wrapper.c credentials/sets/auth_info_wrapper.h \ +credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \ credentials/credential_set.h # Use RAW socket if pluto gets built diff --git a/src/charon/credentials/credential_manager.c b/src/charon/credentials/credential_manager.c index be098c087d..e4db59b6bb 100644 --- a/src/charon/credentials/credential_manager.c +++ b/src/charon/credentials/credential_manager.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -299,111 +301,6 @@ static certificate_t *get_trusted_cert(private_credential_manager_t *this, key_type_t type, identification_t *id, auth_info_t *auth, bool crl, bool ocsp); -/** - * credential_set_t implementation around an OCSP response - */ -typedef struct ocsp_wrapper_t { - credential_set_t set; - ocsp_response_t *response; -} ocsp_wrapper_t; - -/** - * enumerator for ocsp_wrapper_t.create_cert_enumerator() - */ -typedef struct { - enumerator_t public; - enumerator_t *inner; - certificate_type_t cert; - key_type_t key; - identification_t *id; -} ocsp_wrapper_enumerator_t; - -/** - * enumerate function for ocsp_wrapper_enumerator_t - */ -static bool ocsp_wrapper_enum_enumerate(ocsp_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 ocsp_wrapper_enumerator_t - */ -static void ocsp_wrapper_enum_destroy(ocsp_wrapper_enumerator_t *this) -{ - this->inner->destroy(this->inner); - free(this); -} - -/** - * implementation of ocsp_wrapper_t.set.create_cert_enumerator - */ -static enumerator_t *ocsp_wrapper_create_enumerator(ocsp_wrapper_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - ocsp_wrapper_enumerator_t *enumerator; - - if (trusted) - { - return NULL; - } - - enumerator = malloc_thing(ocsp_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*)ocsp_wrapper_enum_enumerate; - enumerator->public.destroy = (void*)ocsp_wrapper_enum_destroy; - return &enumerator->public; -} - -/** - * create credential_set wrapper around an OCSP response - */ -static ocsp_wrapper_t *ocsp_wrapper_create(ocsp_response_t *response) -{ - ocsp_wrapper_t *this = malloc_thing(ocsp_wrapper_t); - - this->response = response; - this->set.create_private_enumerator = (void*)return_null; - this->set.create_cert_enumerator = (void*)ocsp_wrapper_create_enumerator; - this->set.create_shared_enumerator = (void*)return_null; - this->set.create_cdp_enumerator = (void*)return_null; - - return this; -} - /** * Do an OCSP request */ @@ -454,16 +351,16 @@ static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url, certificate_t *issuer_cert; identification_t *responder; auth_info_t *auth; - ocsp_wrapper_t *wrapper; + ocsp_response_wrapper_t *wrapper; auth = auth_info_create(); - wrapper = ocsp_wrapper_create((ocsp_response_t*)response); + wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); this->sets->insert_first(this->sets, wrapper); responder = response->get_issuer(response); DBG1(DBG_CFG, "ocsp signer is \"%D\"", responder); issuer_cert = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE); this->sets->remove(this->sets, wrapper, NULL); - free(wrapper); + wrapper->destroy(wrapper); auth->destroy(auth); if (!issuer_cert) @@ -897,29 +794,20 @@ static bool check_certificate(private_credential_manager_t *this, bool crl, bool ocsp, auth_info_t *auth) { time_t not_before, not_after; - + if (!subject->get_validity(subject, NULL, ¬_before, ¬_after)) { - DBG1(DBG_CFG, "certificate is invalid: validity from %T to %T)", - ¬_before, ¬_after); + DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)", + ¬_before, ¬_after); return FALSE; } - if (issuer) + if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after)) { - /* check the issuer's signature */ - if (subject->issued_by(subject, issuer, TRUE)) - { - DBG1(DBG_CFG, "certificate correctly signed by \"%D\"", - issuer->get_subject(issuer)); - } - else - { - DBG1(DBG_CFG, "certificate not issued by \"%D\"", - issuer->get_subject(issuer)); - return FALSE; - } + DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)", + ¬_before, ¬_after); + return FALSE; } - if (issuer && issuer->get_type(issuer) == CERT_X509 && + if (issuer->get_type(issuer) == CERT_X509 && subject->get_type(subject) == CERT_X509) { if (ocsp) @@ -967,251 +855,140 @@ static bool check_certificate(private_credential_manager_t *this, } /** - * credential_set_t implementation around a auth_info_t - */ -typedef struct auth_wrapper_t { - credential_set_t set; - auth_info_t *auth; -} auth_wrapper_t; - -/** - * enumerator for auth_wrapper_t.create_cert_enumerator() - */ -typedef struct { - enumerator_t public; - enumerator_t *inner; - certificate_type_t cert; - key_type_t key; - identification_t *id; -} auth_wrapper_enumerator_t; - -/** - * enumerate function for auth_wrapper_enumerator_t + * Get a trusted certificate from a credential set */ -static bool auth_wrapper_enum_enumerate(auth_wrapper_enumerator_t *this, - certificate_t **cert) +static certificate_t *get_pretrusted_cert(private_credential_manager_t *this, + key_type_t type, identification_t *id) { - auth_item_t type; - certificate_t *current; + certificate_t *subject; public_key_t *public; - - while (this->inner->enumerate(this->inner, &type, ¤t)) + + subject = get_cert(this, CERT_ANY, type, id, TRUE); + if (!subject) { - if (type != AUTHN_SUBJECT_CERT && - type != AUTHN_IM_CERT) - { - 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 NULL; } - return FALSE; -} - -/** - * destroy function for auth_wrapper_enumerator_t - */ -static void auth_wrapper_enum_destroy(auth_wrapper_enumerator_t *this) -{ - this->inner->destroy(this->inner); - free(this); -} - -/** - * implementation of auth_wrapper_t.set.create_cert_enumerator - */ -static enumerator_t *auth_wrapper_create_enumerator(auth_wrapper_t *this, - certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - auth_wrapper_enumerator_t *enumerator; - - if (trusted) + public = subject->get_public_key(subject); + if (!public) { + subject->destroy(subject); return NULL; } - - enumerator = malloc_thing(auth_wrapper_enumerator_t); - enumerator->cert = cert; - enumerator->key = key; - enumerator->id = id; - enumerator->inner = this->auth->create_item_enumerator(this->auth); - enumerator->public.enumerate = (void*)auth_wrapper_enum_enumerate; - enumerator->public.destroy = (void*)auth_wrapper_enum_destroy; - return &enumerator->public; + public->destroy(public); + return subject; } /** - * create credential_set wrapper around auth_info_t + * try to build the next link in the trustchain, either to a root CA (trusted) + * or to an intermediate CA. */ -static auth_wrapper_t *auth_wrapper_create(auth_info_t *auth) +static auth_info_t *verify_trustchain(private_credential_manager_t *this, + certificate_t **issuerp, bool crl, + bool ocsp, bool peer, bool trusted) { - auth_wrapper_t *this = malloc_thing(auth_wrapper_t); + enumerator_t *enumerator; + certificate_t *candidate, *issuer; + auth_info_t *auth = NULL; - this->auth = auth; - this->set.create_private_enumerator = (void*)return_null; - this->set.create_cert_enumerator = (void*)auth_wrapper_create_enumerator; - this->set.create_shared_enumerator = (void*)return_null; - this->set.create_cdp_enumerator = (void*)return_null; - - return this; + issuer = *issuerp; + enumerator = create_cert_enumerator(this, issuer->get_type(issuer), KEY_ANY, + issuer->get_issuer(issuer), trusted); + while (enumerator->enumerate(enumerator, &candidate)) + { + if (!issuer->issued_by(issuer, candidate, TRUE)) + { + continue; + } + auth = auth_info_create(); + if (check_certificate(this, issuer, candidate, crl, ocsp, + peer ? auth : NULL)) + { + issuer->destroy(issuer); + *issuerp = candidate->get_ref(candidate); + break; + } + auth->destroy(auth); + auth = NULL; + break; + } + enumerator->destroy(enumerator); + return auth; } /** - * Get a trusted certificate + * Get a trusted certificate by verifying the trustchain */ static certificate_t *get_trusted_cert(private_credential_manager_t *this, key_type_t type, identification_t *id, auth_info_t *auth, bool crl, bool ocsp) { - enumerator_t *enumerator; - auth_wrapper_t *wrapper; - certificate_t *subject, *issuer, *candidate; - public_key_t *public; - bool trusted = FALSE; + certificate_t *subject, *issuer; + bool peer = TRUE, trusted = FALSE; auth_info_t *auth1, *auth2; u_int level = 0; - this->mutex->lock(this->mutex); - wrapper = auth_wrapper_create(auth); - this->sets->insert_first(this->sets, wrapper); - /* check if we have a trusted certificate for that peer */ - auth1 = auth_info_create(); - subject = get_cert(this, CERT_ANY, type, id, TRUE); + subject = get_pretrusted_cert(this, type, id); if (subject) - { - if (check_certificate(this, subject, NULL, crl, ocsp, auth1)) - { - public = subject->get_public_key(subject); - if (public) - { - DBG1(DBG_CFG, "found trusted certificate \"%D\"", - subject->get_subject(subject)); - this->sets->remove(this->sets, wrapper, NULL); - free(wrapper); - this->mutex->unlock(this->mutex); - auth->add_item(auth1, AUTHZ_SUBJECT_CERT, subject); - public->destroy(public); - auth->merge(auth, auth1); - auth1->destroy(auth1); - return subject; - } - } - subject->destroy(subject); + { /* if we find a trusted certificate, we accept it. However, to + * fullfill authorization rules, we try build the trustchain anyway. */ + trusted = TRUE; + } + else + { /* check for an untrusted peer certificate */ + subject = get_cert(this, CERT_ANY, type, id, FALSE); } - auth1->destroy(auth1); - - /* check for an untrusted certificate */ - auth1 = auth_info_create(); - subject = get_cert(this, CERT_ANY, type, id, FALSE); if (!subject) { DBG1(DBG_CFG, "no certificate found for '%D'", id); + return NULL; } - else + DBG1(DBG_CFG, " using end entity certificate \"%D\"", + subject->get_subject(subject)); + auth1 = auth_info_create(); + auth->add_item(auth, AUTHZ_SUBJECT_CERT, subject); + issuer = subject->get_ref(subject); + while (level++ < MAX_CA_LEVELS) { - DBG1(DBG_CFG, "found untrusted certificate for '%D'", id); - issuer = subject; - do + /* look for a trusted CA certificate */ + auth2 = verify_trustchain(this, &issuer, crl, ocsp, peer, TRUE); + if (auth2) { - /* look for a trusted certificate */ - auth2 = auth_info_create(); - enumerator = create_cert_enumerator(this, issuer->get_type(issuer), - KEY_ANY, issuer->get_issuer(issuer), TRUE); - while (enumerator->enumerate(enumerator, &candidate)) - { - if (check_certificate(this, issuer, candidate, crl, ocsp, - issuer == subject ? auth2 : NULL) && - check_certificate(this, candidate, NULL, crl, ocsp, NULL)) - { - DBG1(DBG_CFG, "reached trusted root ca certificate \"%D\"", - candidate->get_subject(candidate)); - issuer = candidate; - trusted = TRUE; - auth1->merge(auth1, auth2); - auth1->add_item(auth1, AUTHZ_CA_CERT, candidate); - break; - } - } - enumerator->destroy(enumerator); + DBG1(DBG_CFG, " using trusted root CA certificate \"%D\"", + issuer->get_subject(issuer)); + auth1->merge(auth1, auth2); auth2->destroy(auth2); - if (trusted) - { - break; - } - - /* no trusted certificate found, look for an untrusted */ - enumerator = create_cert_enumerator(this, issuer->get_type(issuer), - KEY_ANY, issuer->get_issuer(issuer), FALSE); - while (enumerator->enumerate(enumerator, &candidate)) - { - auth2 = auth_info_create(); - if (check_certificate(this, issuer, candidate, crl, ocsp, - issuer == subject ? auth2 : NULL)) - { - if (issuer != subject) - { - DBG1(DBG_CFG, "found intermediate ca certificate \"%D\"", - candidate->get_subject(candidate)); - auth1->add_item(auth1, AUTHZ_IM_CERT, candidate); - } - else - { - DBG1(DBG_CFG, "found end entity certificate \"%D\"", - candidate->get_subject(candidate)); - } - issuer = candidate; - auth1->merge(auth1, auth2); - auth2->destroy(auth2); - /* check next level */ - break; - } - auth2->destroy(auth2); - } - enumerator->destroy(enumerator); + auth1->add_item(auth1, AUTHZ_CA_CERT, issuer); + trusted = TRUE; + break; } - while (++level < MAX_CA_LEVELS); - - if (!trusted) + /* check for a untrusted intermediate CA */ + auth2 = verify_trustchain(this, &issuer, crl, ocsp, peer, FALSE); + if (auth2) { - subject->destroy(subject); - subject = NULL; + DBG1(DBG_CFG, " using intermediate CA certificate \"%D\"", + issuer->get_subject(issuer)); + auth1->merge(auth1, auth2); + auth2->destroy(auth2); + auth1->add_item(auth1, AUTHZ_IM_CERT, issuer); + peer = FALSE; + continue; } + break; } - this->sets->remove(this->sets, wrapper, NULL); - free(wrapper); - this->mutex->unlock(this->mutex); - if (subject) + issuer->destroy(issuer); + if (trusted) { auth->add_item(auth, AUTHZ_SUBJECT_CERT, subject); auth->merge(auth, auth1); - auth1->destroy(auth1); - return subject; + } + else + { + subject->destroy(subject); + subject = NULL; } auth1->destroy(auth1); - return NULL; + return subject; } /** @@ -1221,17 +998,25 @@ static public_key_t *get_public(private_credential_manager_t *this, key_type_t type, identification_t *id, auth_info_t *auth) { - public_key_t *public; + public_key_t *public = NULL; certificate_t *cert; + auth_info_wrapper_t *wrapper; + + wrapper = auth_info_wrapper_create(auth); + this->mutex->lock(this->mutex); + this->sets->insert_first(this->sets, wrapper); cert = get_trusted_cert(this, type, id, auth, TRUE, TRUE); if (cert) { public = cert->get_public_key(cert); cert->destroy(cert); - return public; } - return NULL; + + this->sets->remove(this->sets, wrapper, NULL); + wrapper->destroy(wrapper); + this->mutex->unlock(this->mutex); + return public; } /** diff --git a/src/charon/credentials/sets/auth_info_wrapper.c b/src/charon/credentials/sets/auth_info_wrapper.c new file mode 100644 index 0000000000..12349b5fec --- /dev/null +++ b/src/charon/credentials/sets/auth_info_wrapper.c @@ -0,0 +1,154 @@ +/* + * 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 . + * + * 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. + * + * $Id$ + */ + +#include "auth_info_wrapper.h" + +typedef struct private_auth_info_wrapper_t private_auth_info_wrapper_t; + +/** + * private data of auth_info_wrapper + */ +struct private_auth_info_wrapper_t { + + /** + * public functions + */ + auth_info_wrapper_t public; + + /** + * wrapped auth info + */ + auth_info_t *auth; +}; + +/** + * enumerator for auth_info_wrapper_t.create_cert_enumerator() + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** inner enumerator from auth_info */ + enumerator_t *inner; + /** enumerated cert type */ + certificate_type_t cert; + /** enumerated key type */ + key_type_t key; + /** enumerated id */ + identification_t *id; +} wrapper_enumerator_t; + +/** + * enumerate function for wrapper_enumerator_t + */ +static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) +{ + auth_item_t type; + certificate_t *current; + public_key_t *public; + + while (this->inner->enumerate(this->inner, &type, ¤t)) + { + if (type != AUTHN_SUBJECT_CERT && + type != AUTHN_IM_CERT) + { + 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_info_wrapper_t.set.create_cert_enumerator + */ +static enumerator_t *create_enumerator(private_auth_info_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->auth->create_item_enumerator(this->auth); + enumerator->public.enumerate = (void*)enumerate; + enumerator->public.destroy = (void*)wrapper_enumerator_destroy; + return &enumerator->public; +} + +/** + * Implementation of auth_info_wrapper_t.destroy + */ +static void destroy(private_auth_info_wrapper_t *this) +{ + free(this); +} + +/* + * see header file + */ +auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth) +{ + private_auth_info_wrapper_t *this = malloc_thing(private_auth_info_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.destroy = (void(*)(auth_info_wrapper_t*))destroy; + + this->auth = auth; + + return &this->public; +} + diff --git a/src/charon/credentials/sets/auth_info_wrapper.h b/src/charon/credentials/sets/auth_info_wrapper.h new file mode 100644 index 0000000000..c382e98708 --- /dev/null +++ b/src/charon/credentials/sets/auth_info_wrapper.h @@ -0,0 +1,55 @@ +/* + * 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 . + * + * 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. + * + * $Id$ + */ + +/** + * @defgroup auth_info_wrapper auth_info_wrapper + * @{ @ingroup sets + */ + +#ifndef AUTH_INFO_WRAPPER_H_ +#define AUTH_INFO_WRAPPER_H_ + +#include +#include + +typedef struct auth_info_wrapper_t auth_info_wrapper_t; + +/** + * A wrapper around auth_info_t to handle it like a credential set. + */ +struct auth_info_wrapper_t { + + /** + * implements credential_set_t + */ + credential_set_t set; + + /** + * Destroy a auth_info_wrapper instance. + */ + void (*destroy)(auth_info_wrapper_t *this); +}; + +/** + * Create a auth_info_wrapper instance. + * + * @param auth the wrapped auth info + * @return wrapper around auth + */ +auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth); + +#endif /* AUTH_INFO_WRAPPER_H_ @}*/ diff --git a/src/charon/credentials/sets/ocsp_response_wrapper.c b/src/charon/credentials/sets/ocsp_response_wrapper.c new file mode 100644 index 0000000000..6241a5ada7 --- /dev/null +++ b/src/charon/credentials/sets/ocsp_response_wrapper.c @@ -0,0 +1,148 @@ +/* + * 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 . + * + * 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. + * + * $Id$ + */ + +#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.destroy = (void(*)(ocsp_response_wrapper_t*))destroy; + + this->response = response; + + return &this->public; +} + diff --git a/src/charon/credentials/sets/ocsp_response_wrapper.h b/src/charon/credentials/sets/ocsp_response_wrapper.h new file mode 100644 index 0000000000..6d32c2ca87 --- /dev/null +++ b/src/charon/credentials/sets/ocsp_response_wrapper.h @@ -0,0 +1,55 @@ +/* + * 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 . + * + * 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. + * + * $Id$ + */ + +/** + * @defgroup ocsp_response_wrapper ocsp_response_wrapper + * @{ @ingroup sets + */ + +#ifndef OCSP_RESPONSE_WRAPPER_H_ +#define OCSP_RESPONSE_WRAPPER_H_ + +#include +#include + +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_ @}*/ diff --git a/src/charon/daemon.h b/src/charon/daemon.h index d989c0bba8..b9c84b2dbc 100644 --- a/src/charon/daemon.h +++ b/src/charon/daemon.h @@ -36,6 +36,9 @@ * @defgroup ccredentials credentials * @ingroup charon * + * @defgroup sets sets + * @ingroup ccredentials + * * @defgroup encoding encoding * @ingroup charon *