refactored trustchain verification, this should fix #33
moved auth_info/ocsp_response credset wrapper to separate files
This commit is contained in:
@@ -86,6 +86,8 @@ sa/tasks/ike_auth_lifetime.c sa/tasks/ike_auth_lifetime.h \
|
|||||||
sa/tasks/task.c sa/tasks/task.h \
|
sa/tasks/task.c sa/tasks/task.h \
|
||||||
credentials/credential_manager.c credentials/credential_manager.h \
|
credentials/credential_manager.c credentials/credential_manager.h \
|
||||||
credentials/auth_info.c credentials/auth_info.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
|
credentials/credential_set.h
|
||||||
|
|
||||||
# Use RAW socket if pluto gets built
|
# Use RAW socket if pluto gets built
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <utils/linked_list.h>
|
#include <utils/linked_list.h>
|
||||||
#include <utils/mutex.h>
|
#include <utils/mutex.h>
|
||||||
|
#include <credentials/sets/auth_info_wrapper.h>
|
||||||
|
#include <credentials/sets/ocsp_response_wrapper.h>
|
||||||
#include <credentials/certificates/x509.h>
|
#include <credentials/certificates/x509.h>
|
||||||
#include <credentials/certificates/crl.h>
|
#include <credentials/certificates/crl.h>
|
||||||
#include <credentials/certificates/ocsp_request.h>
|
#include <credentials/certificates/ocsp_request.h>
|
||||||
@@ -299,111 +301,6 @@ static certificate_t *get_trusted_cert(private_credential_manager_t *this,
|
|||||||
key_type_t type, identification_t *id,
|
key_type_t type, identification_t *id,
|
||||||
auth_info_t *auth, bool crl, bool ocsp);
|
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
|
* Do an OCSP request
|
||||||
*/
|
*/
|
||||||
@@ -454,16 +351,16 @@ static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
|
|||||||
certificate_t *issuer_cert;
|
certificate_t *issuer_cert;
|
||||||
identification_t *responder;
|
identification_t *responder;
|
||||||
auth_info_t *auth;
|
auth_info_t *auth;
|
||||||
ocsp_wrapper_t *wrapper;
|
ocsp_response_wrapper_t *wrapper;
|
||||||
|
|
||||||
auth = auth_info_create();
|
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);
|
this->sets->insert_first(this->sets, wrapper);
|
||||||
responder = response->get_issuer(response);
|
responder = response->get_issuer(response);
|
||||||
DBG1(DBG_CFG, "ocsp signer is \"%D\"", responder);
|
DBG1(DBG_CFG, "ocsp signer is \"%D\"", responder);
|
||||||
issuer_cert = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE);
|
issuer_cert = get_trusted_cert(this, KEY_ANY, responder, auth, FALSE, FALSE);
|
||||||
this->sets->remove(this->sets, wrapper, NULL);
|
this->sets->remove(this->sets, wrapper, NULL);
|
||||||
free(wrapper);
|
wrapper->destroy(wrapper);
|
||||||
auth->destroy(auth);
|
auth->destroy(auth);
|
||||||
|
|
||||||
if (!issuer_cert)
|
if (!issuer_cert)
|
||||||
@@ -897,29 +794,20 @@ static bool check_certificate(private_credential_manager_t *this,
|
|||||||
bool crl, bool ocsp, auth_info_t *auth)
|
bool crl, bool ocsp, auth_info_t *auth)
|
||||||
{
|
{
|
||||||
time_t not_before, not_after;
|
time_t not_before, not_after;
|
||||||
|
|
||||||
if (!subject->get_validity(subject, NULL, ¬_before, ¬_after))
|
if (!subject->get_validity(subject, NULL, ¬_before, ¬_after))
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "certificate is invalid: validity from %T to %T)",
|
DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
|
||||||
¬_before, ¬_after);
|
¬_before, ¬_after);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (issuer)
|
if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after))
|
||||||
{
|
{
|
||||||
/* check the issuer's signature */
|
DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
|
||||||
if (subject->issued_by(subject, issuer, TRUE))
|
¬_before, ¬_after);
|
||||||
{
|
return FALSE;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (issuer && issuer->get_type(issuer) == CERT_X509 &&
|
if (issuer->get_type(issuer) == CERT_X509 &&
|
||||||
subject->get_type(subject) == CERT_X509)
|
subject->get_type(subject) == CERT_X509)
|
||||||
{
|
{
|
||||||
if (ocsp)
|
if (ocsp)
|
||||||
@@ -967,251 +855,140 @@ static bool check_certificate(private_credential_manager_t *this,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* credential_set_t implementation around a auth_info_t
|
* Get a trusted certificate from a credential set
|
||||||
*/
|
*/
|
||||||
typedef struct auth_wrapper_t {
|
static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
|
||||||
credential_set_t set;
|
key_type_t type, identification_t *id)
|
||||||
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
|
|
||||||
*/
|
|
||||||
static bool auth_wrapper_enum_enumerate(auth_wrapper_enumerator_t *this,
|
|
||||||
certificate_t **cert)
|
|
||||||
{
|
{
|
||||||
auth_item_t type;
|
certificate_t *subject;
|
||||||
certificate_t *current;
|
|
||||||
public_key_t *public;
|
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 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)
|
subject = get_cert(this, CERT_ANY, type, id, TRUE);
|
||||||
|
if (!subject)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
public = subject->get_public_key(subject);
|
||||||
enumerator = malloc_thing(auth_wrapper_enumerator_t);
|
if (!public)
|
||||||
enumerator->cert = cert;
|
{
|
||||||
enumerator->key = key;
|
subject->destroy(subject);
|
||||||
enumerator->id = id;
|
return NULL;
|
||||||
enumerator->inner = this->auth->create_item_enumerator(this->auth);
|
}
|
||||||
enumerator->public.enumerate = (void*)auth_wrapper_enum_enumerate;
|
public->destroy(public);
|
||||||
enumerator->public.destroy = (void*)auth_wrapper_enum_destroy;
|
return subject;
|
||||||
return &enumerator->public;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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;
|
issuer = *issuerp;
|
||||||
this->set.create_private_enumerator = (void*)return_null;
|
enumerator = create_cert_enumerator(this, issuer->get_type(issuer), KEY_ANY,
|
||||||
this->set.create_cert_enumerator = (void*)auth_wrapper_create_enumerator;
|
issuer->get_issuer(issuer), trusted);
|
||||||
this->set.create_shared_enumerator = (void*)return_null;
|
while (enumerator->enumerate(enumerator, &candidate))
|
||||||
this->set.create_cdp_enumerator = (void*)return_null;
|
{
|
||||||
|
if (!issuer->issued_by(issuer, candidate, TRUE))
|
||||||
return this;
|
{
|
||||||
|
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,
|
static certificate_t *get_trusted_cert(private_credential_manager_t *this,
|
||||||
key_type_t type, identification_t *id,
|
key_type_t type, identification_t *id,
|
||||||
auth_info_t *auth, bool crl, bool ocsp)
|
auth_info_t *auth, bool crl, bool ocsp)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
certificate_t *subject, *issuer;
|
||||||
auth_wrapper_t *wrapper;
|
bool peer = TRUE, trusted = FALSE;
|
||||||
certificate_t *subject, *issuer, *candidate;
|
|
||||||
public_key_t *public;
|
|
||||||
bool trusted = FALSE;
|
|
||||||
auth_info_t *auth1, *auth2;
|
auth_info_t *auth1, *auth2;
|
||||||
u_int level = 0;
|
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 */
|
/* check if we have a trusted certificate for that peer */
|
||||||
auth1 = auth_info_create();
|
subject = get_pretrusted_cert(this, type, id);
|
||||||
subject = get_cert(this, CERT_ANY, type, id, TRUE);
|
|
||||||
if (subject)
|
if (subject)
|
||||||
{
|
{ /* if we find a trusted certificate, we accept it. However, to
|
||||||
if (check_certificate(this, subject, NULL, crl, ocsp, auth1))
|
* fullfill authorization rules, we try build the trustchain anyway. */
|
||||||
{
|
trusted = TRUE;
|
||||||
public = subject->get_public_key(subject);
|
}
|
||||||
if (public)
|
else
|
||||||
{
|
{ /* check for an untrusted peer certificate */
|
||||||
DBG1(DBG_CFG, "found trusted certificate \"%D\"",
|
subject = get_cert(this, CERT_ANY, type, id, FALSE);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
auth1->destroy(auth1);
|
|
||||||
|
|
||||||
/* check for an untrusted certificate */
|
|
||||||
auth1 = auth_info_create();
|
|
||||||
subject = get_cert(this, CERT_ANY, type, id, FALSE);
|
|
||||||
if (!subject)
|
if (!subject)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "no certificate found for '%D'", id);
|
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);
|
/* look for a trusted CA certificate */
|
||||||
issuer = subject;
|
auth2 = verify_trustchain(this, &issuer, crl, ocsp, peer, TRUE);
|
||||||
do
|
if (auth2)
|
||||||
{
|
{
|
||||||
/* look for a trusted certificate */
|
DBG1(DBG_CFG, " using trusted root CA certificate \"%D\"",
|
||||||
auth2 = auth_info_create();
|
issuer->get_subject(issuer));
|
||||||
enumerator = create_cert_enumerator(this, issuer->get_type(issuer),
|
auth1->merge(auth1, auth2);
|
||||||
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);
|
|
||||||
auth2->destroy(auth2);
|
auth2->destroy(auth2);
|
||||||
if (trusted)
|
auth1->add_item(auth1, AUTHZ_CA_CERT, issuer);
|
||||||
{
|
trusted = TRUE;
|
||||||
break;
|
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);
|
|
||||||
}
|
}
|
||||||
while (++level < MAX_CA_LEVELS);
|
/* check for a untrusted intermediate CA */
|
||||||
|
auth2 = verify_trustchain(this, &issuer, crl, ocsp, peer, FALSE);
|
||||||
if (!trusted)
|
if (auth2)
|
||||||
{
|
{
|
||||||
subject->destroy(subject);
|
DBG1(DBG_CFG, " using intermediate CA certificate \"%D\"",
|
||||||
subject = NULL;
|
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);
|
issuer->destroy(issuer);
|
||||||
free(wrapper);
|
if (trusted)
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
if (subject)
|
|
||||||
{
|
{
|
||||||
auth->add_item(auth, AUTHZ_SUBJECT_CERT, subject);
|
auth->add_item(auth, AUTHZ_SUBJECT_CERT, subject);
|
||||||
auth->merge(auth, auth1);
|
auth->merge(auth, auth1);
|
||||||
auth1->destroy(auth1);
|
}
|
||||||
return subject;
|
else
|
||||||
|
{
|
||||||
|
subject->destroy(subject);
|
||||||
|
subject = NULL;
|
||||||
}
|
}
|
||||||
auth1->destroy(auth1);
|
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,
|
key_type_t type, identification_t *id,
|
||||||
auth_info_t *auth)
|
auth_info_t *auth)
|
||||||
{
|
{
|
||||||
public_key_t *public;
|
public_key_t *public = NULL;
|
||||||
certificate_t *cert;
|
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);
|
cert = get_trusted_cert(this, type, id, auth, TRUE, TRUE);
|
||||||
if (cert)
|
if (cert)
|
||||||
{
|
{
|
||||||
public = cert->get_public_key(cert);
|
public = cert->get_public_key(cert);
|
||||||
cert->destroy(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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 <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.
|
||||||
|
*
|
||||||
|
* $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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 <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.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup auth_info_wrapper auth_info_wrapper
|
||||||
|
* @{ @ingroup sets
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AUTH_INFO_WRAPPER_H_
|
||||||
|
#define AUTH_INFO_WRAPPER_H_
|
||||||
|
|
||||||
|
#include <credentials/credential_set.h>
|
||||||
|
#include <credentials/auth_info.h>
|
||||||
|
|
||||||
|
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_ @}*/
|
||||||
@@ -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 <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.
|
||||||
|
*
|
||||||
|
* $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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 <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.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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_ @}*/
|
||||||
@@ -36,6 +36,9 @@
|
|||||||
* @defgroup ccredentials credentials
|
* @defgroup ccredentials credentials
|
||||||
* @ingroup charon
|
* @ingroup charon
|
||||||
*
|
*
|
||||||
|
* @defgroup sets sets
|
||||||
|
* @ingroup ccredentials
|
||||||
|
*
|
||||||
* @defgroup encoding encoding
|
* @defgroup encoding encoding
|
||||||
* @ingroup charon
|
* @ingroup charon
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user