merged multi-auth branch back into trunk

This commit is contained in:
Martin Willi
2009-04-14 10:34:24 +00:00
parent 6e5c8d9413
commit a44bb9345f
230 changed files with 6163 additions and 4193 deletions
-607
View File
@@ -1,607 +0,0 @@
/*
* Copyright (C) 2008 Tobias Brunner
* 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.
*
* $Id$
*/
#include "auth_info.h"
#include <daemon.h>
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <credentials/certificates/certificate.h>
ENUM(auth_item_names, AUTHN_CA_CERT, AUTHZ_AC_GROUP,
"AUTHN_AUTH_CLASS",
"AUTHN_EAP_TYPE",
"AUTHN_EAP_VENDOR",
"AUTHN_EAP_IDENTITY",
"AUTHN_CA_CERT",
"AUTHN_CA_CERT_KEYID",
"AUTHN_CA_CERT_NAME",
"AUTHN_IM_CERT",
"AUTHN_SUBJECT_CERT",
"AUTHN_IM_HASH_URL",
"AUTHN_SUBJECT_HASH_URL",
"AUTHZ_PUBKEY",
"AUTHZ_PSK",
"AUTHZ_EAP",
"AUTHZ_CA_CERT",
"AUTHZ_CA_CERT_NAME",
"AUTHZ_IM_CERT",
"AUTHZ_SUBJECT_CERT",
"AUTHZ_CRL_VALIDATION",
"AUTHZ_OCSP_VALIDATION",
"AUTHZ_AC_GROUP",
);
typedef struct private_auth_info_t private_auth_info_t;
/**
* private data of item_set
*/
struct private_auth_info_t {
/**
* public functions
*/
auth_info_t public;
/**
* list of item_t's
*/
linked_list_t *items;
};
typedef struct item_t item_t;
struct item_t {
/** type of this item */
auth_item_t type;
/** associated privlege value, if any */
void *value;
};
/**
* enumerator for auth_info_wrapper_t.create_cert_enumerator()
*/
typedef struct {
/** implements enumerator_t */
enumerator_t public;
/** inner enumerator from linked_list_t */
enumerator_t *inner;
/** the current item */
item_t *item;
} item_enumerator_t;
/**
* enumerate function for item_enumerator_t
*/
static bool enumerate(item_enumerator_t *this, auth_item_t *type, void **value)
{
if (this->inner->enumerate(this->inner, &this->item))
{
*type = this->item->type;
*value = this->item->value;
return TRUE;
}
return FALSE;
}
/**
* destroy function for item_enumerator_t
*/
static void item_enumerator_destroy(item_enumerator_t *this)
{
this->inner->destroy(this->inner);
free(this);
}
/**
* Implementation of auth_info_t.create_item_enumerator.
*/
static enumerator_t* create_item_enumerator(private_auth_info_t *this)
{
item_enumerator_t *enumerator;
enumerator = malloc_thing(item_enumerator_t);
enumerator->item = NULL;
enumerator->inner = this->items->create_enumerator(this->items);
enumerator->public.enumerate = (void*)enumerate;
enumerator->public.destroy = (void*)item_enumerator_destroy;
return &enumerator->public;
}
static void destroy_item_value(item_t *item);
/**
* Implementation of auth_info_t.replace_item.
*/
static void replace_item(item_enumerator_t *enumerator, auth_item_t type, void *value)
{
destroy_item_value(enumerator->item);
enumerator->item->type = type;
enumerator->item->value = value;
}
/**
* Implementation of auth_info_t.get_item.
*/
static bool get_item(private_auth_info_t *this, auth_item_t type, void** value)
{
enumerator_t *enumerator;
void *current_value;
auth_item_t current_type;
bool found = FALSE;
enumerator = create_item_enumerator(this);
while (enumerator->enumerate(enumerator, &current_type, &current_value))
{
if (type == current_type)
{
*value = current_value;
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
return found;
}
/**
* Implementation of auth_info_t.add_item.
*/
static void add_item(private_auth_info_t *this, auth_item_t type, void *value)
{
item_t *item = malloc_thing(item_t);
item->type = type;
switch (type)
{
case AUTHZ_PUBKEY:
{
public_key_t *key = (public_key_t*)value;
item->value = key->get_ref(key);
break;
}
case AUTHZ_PSK:
{
shared_key_t *key = (shared_key_t*)value;
item->value = key->get_ref(key);
break;
}
case AUTHN_IM_HASH_URL:
case AUTHN_SUBJECT_HASH_URL:
{
item->value = strdup(value);
break;
}
case AUTHN_CA_CERT:
case AUTHN_IM_CERT:
case AUTHN_SUBJECT_CERT:
case AUTHZ_CA_CERT:
case AUTHZ_IM_CERT:
case AUTHZ_SUBJECT_CERT:
{
certificate_t *cert = (certificate_t*)value;
item->value = cert->get_ref(cert);
break;
}
case AUTHZ_CRL_VALIDATION:
case AUTHZ_OCSP_VALIDATION:
{
cert_validation_t *validation = malloc_thing(cert_validation_t);
*validation = *(cert_validation_t*)value;
item->value = validation;
break;
}
case AUTHN_AUTH_CLASS:
case AUTHN_EAP_TYPE:
case AUTHN_EAP_VENDOR:
case AUTHZ_EAP:
{
u_int *intval = malloc_thing(u_int);
*intval = *(u_int*)value;
item->value = intval;
break;
}
case AUTHN_EAP_IDENTITY:
case AUTHN_CA_CERT_KEYID:
case AUTHN_CA_CERT_NAME:
case AUTHZ_CA_CERT_NAME:
case AUTHZ_AC_GROUP:
{
identification_t *id = (identification_t*)value;
item->value = id->clone(id);
break;
}
}
this->items->insert_last(this->items, item);
}
/**
* Implementation of auth_info_t.complies.
*/
static bool complies(private_auth_info_t *this, auth_info_t *constraints)
{
enumerator_t *enumerator;
bool success = TRUE;
auth_item_t t1, t2;
void *value;
enumerator = constraints->create_item_enumerator(constraints);
while (enumerator->enumerate(enumerator, &t1, &value))
{
switch (t1)
{
case AUTHN_AUTH_CLASS:
case AUTHN_EAP_TYPE:
case AUTHN_EAP_VENDOR:
case AUTHN_EAP_IDENTITY:
case AUTHN_CA_CERT_KEYID:
case AUTHN_CA_CERT:
case AUTHN_CA_CERT_NAME:
case AUTHN_IM_CERT:
case AUTHN_SUBJECT_CERT:
case AUTHN_IM_HASH_URL:
case AUTHN_SUBJECT_HASH_URL:
{ /* skip non-authorization tokens */
continue;
}
case AUTHZ_CRL_VALIDATION:
case AUTHZ_OCSP_VALIDATION:
{
cert_validation_t *valid;
/* OCSP validation is also sufficient for CRL constraint, but
* not vice-versa */
if (!get_item(this, t1, (void**)&valid) &&
t1 == AUTHZ_CRL_VALIDATION &&
!get_item(this, AUTHZ_OCSP_VALIDATION, (void**)&valid))
{
DBG1(DBG_CFG, "constraint check failed: %N requires at "
"least %N, but no check done", auth_item_names, t1,
cert_validation_names, *(cert_validation_t*)value);
success = FALSE;
break;
}
switch (*(cert_validation_t*)value)
{
case VALIDATION_SKIPPED:
if (*valid == VALIDATION_SKIPPED)
{
break;
} /* FALL */
case VALIDATION_GOOD:
if (*valid == VALIDATION_GOOD)
{
break;
} /* FALL */
default:
DBG1(DBG_CFG, "constraint check failed: %N is %N, but "
"requires at least %N", auth_item_names, t1,
cert_validation_names, *valid,
cert_validation_names, *(cert_validation_t*)value);
success = FALSE;
break;
}
break;
}
case AUTHZ_CA_CERT:
{
enumerator_t *enumerator;
certificate_t *c1, *c2;
c1 = (certificate_t*)value;
success = FALSE;
enumerator = create_item_enumerator(this);
while (enumerator->enumerate(enumerator, &t2, &c2))
{
if ((t2 == AUTHZ_CA_CERT || t2 == AUTHZ_IM_CERT) &&
c1->equals(c1, c2))
{
success = TRUE;
}
}
enumerator->destroy(enumerator);
if (!success)
{
DBG1(DBG_CFG, "constraint check failed: peer not "
"authenticated by CA '%D'.", c1->get_subject(c1));
}
break;
}
case AUTHZ_CA_CERT_NAME:
{
enumerator_t *enumerator;
certificate_t *cert;
identification_t *id;
id = (identification_t*)value;
success = FALSE;
enumerator = create_item_enumerator(this);
while (enumerator->enumerate(enumerator, &t2, &cert))
{
if ((t2 == AUTHZ_CA_CERT || t2 == AUTHZ_IM_CERT) &&
cert->has_subject(cert, id))
{
success = TRUE;
}
}
enumerator->destroy(enumerator);
if (!success)
{
DBG1(DBG_CFG, "constraint check failed: peer not "
"authenticated by CA '%D'.", id);
}
break;
}
case AUTHZ_PUBKEY:
case AUTHZ_PSK:
case AUTHZ_IM_CERT:
case AUTHZ_SUBJECT_CERT:
case AUTHZ_EAP:
case AUTHZ_AC_GROUP:
{
DBG1(DBG_CFG, "constraint check %N not implemented!",
auth_item_names, t1);
success = FALSE;
break;
}
}
if (!success)
{
break;
}
}
enumerator->destroy(enumerator);
return success;
}
/**
* Implementation of auth_info_t.merge.
*/
static void merge(private_auth_info_t *this, private_auth_info_t *other)
{
item_t *item;
while (other->items->remove_first(other->items, (void**)&item) == SUCCESS)
{
this->items->insert_last(this->items, item);
}
}
/**
* Implementation of auth_info_t.equals.
*/
static bool equals(private_auth_info_t *this, private_auth_info_t *other)
{
enumerator_t *e1, *e2;
item_t *i1, *i2;
bool equal = TRUE, found;
e1 = this->items->create_enumerator(this->items);
while (e1->enumerate(e1, &i1))
{
found = FALSE;
e2 = other->items->create_enumerator(other->items);
while (e2->enumerate(e2, &i2))
{
if (i1->type == i2->type)
{
switch (i1->type)
{
case AUTHZ_CRL_VALIDATION:
case AUTHZ_OCSP_VALIDATION:
{
cert_validation_t c1, c2;
c1 = *(cert_validation_t*)i1->value;
c2 = *(cert_validation_t*)i2->value;
if (c1 == c2)
{
found = TRUE;
break;
}
continue;
}
case AUTHN_IM_HASH_URL:
case AUTHN_SUBJECT_HASH_URL:
{
if (streq(i1->value, i2->value))
{
found = TRUE;
break;
}
continue;
}
case AUTHN_CA_CERT:
case AUTHN_IM_CERT:
case AUTHN_SUBJECT_CERT:
case AUTHZ_CA_CERT:
case AUTHZ_IM_CERT:
case AUTHZ_SUBJECT_CERT:
{
certificate_t *c1, *c2;
c1 = (certificate_t*)i1->value;
c2 = (certificate_t*)i2->value;
if (c1->equals(c1, c2))
{
found = TRUE;
break;
}
continue;
}
case AUTHN_EAP_IDENTITY:
case AUTHN_CA_CERT_KEYID:
case AUTHN_CA_CERT_NAME:
case AUTHZ_CA_CERT_NAME:
{
identification_t *c1, *c2;
c1 = (identification_t*)i1->value;
c2 = (identification_t*)i2->value;
if (c1->equals(c1, c2))
{
found = TRUE;
break;
}
continue;
}
case AUTHN_AUTH_CLASS:
case AUTHN_EAP_TYPE:
case AUTHN_EAP_VENDOR:
{
if (*(u_int*)i1->value == *(u_int*)i2->value)
{
found = TRUE;
break;
}
}
case AUTHZ_PUBKEY:
case AUTHZ_PSK:
case AUTHZ_EAP:
case AUTHZ_AC_GROUP:
/* TODO: implement value comparison */
break;
}
break;
}
}
e2->destroy(e2);
if (!found)
{
equal = FALSE;
break;
}
}
e1->destroy(e1);
return equal;
}
/**
* Destroy the value associated with an item
*/
static void destroy_item_value(item_t *item)
{
switch (item->type)
{
case AUTHZ_PUBKEY:
{
public_key_t *key = (public_key_t*)item->value;
key->destroy(key);
break;
}
case AUTHZ_PSK:
{
shared_key_t *key = (shared_key_t*)item->value;
key->destroy(key);
break;
}
case AUTHN_CA_CERT:
case AUTHN_IM_CERT:
case AUTHN_SUBJECT_CERT:
case AUTHZ_CA_CERT:
case AUTHZ_IM_CERT:
case AUTHZ_SUBJECT_CERT:
{
certificate_t *cert = (certificate_t*)item->value;
cert->destroy(cert);
break;
}
case AUTHN_AUTH_CLASS:
case AUTHN_EAP_TYPE:
case AUTHN_EAP_VENDOR:
case AUTHN_IM_HASH_URL:
case AUTHN_SUBJECT_HASH_URL:
case AUTHZ_CRL_VALIDATION:
case AUTHZ_OCSP_VALIDATION:
case AUTHZ_EAP:
{
free(item->value);
break;
}
case AUTHN_EAP_IDENTITY:
case AUTHN_CA_CERT_KEYID:
case AUTHN_CA_CERT_NAME:
case AUTHZ_CA_CERT_NAME:
case AUTHZ_AC_GROUP:
{
identification_t *id = (identification_t*)item->value;
id->destroy(id);
break;
}
}
}
/**
* Implementation of auth_info_t.purge
*/
static void purge(private_auth_info_t *this)
{
item_t *item;
while (this->items->remove_last(this->items, (void**)&item) == SUCCESS)
{
destroy_item_value(item);
free(item);
}
}
/**
* Implementation of auth_info_t.destroy
*/
static void destroy(private_auth_info_t *this)
{
purge(this);
this->items->destroy(this->items);
free(this);
}
/*
* see header file
*/
auth_info_t *auth_info_create()
{
private_auth_info_t *this = malloc_thing(private_auth_info_t);
this->public.add_item = (void(*)(auth_info_t*, auth_item_t type, void *value))add_item;
this->public.get_item = (bool(*)(auth_info_t*, auth_item_t type, void **value))get_item;
this->public.replace_item = (void(*)(enumerator_t*,auth_item_t,void*))replace_item;
this->public.create_item_enumerator = (enumerator_t*(*)(auth_info_t*))create_item_enumerator;
this->public.complies = (bool(*)(auth_info_t*, auth_info_t *))complies;
this->public.merge = (void(*)(auth_info_t*, auth_info_t *other))merge;
this->public.purge = (void(*)(auth_info_t*))purge;
this->public.equals = (bool(*)(auth_info_t*, auth_info_t *other))equals;
this->public.destroy = (void(*)(auth_info_t*))destroy;
this->items = linked_list_create();
return &this->public;
}
-198
View File
@@ -1,198 +0,0 @@
/*
* Copyright (C) 2008 Tobias Brunner
* 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 auth_info auth_info
* @{ @ingroup ccredentials
*/
#ifndef AUTH_INFO_H_
#define AUTH_INFO_H_
#include <utils/enumerator.h>
typedef struct auth_info_t auth_info_t;
typedef enum auth_item_t auth_item_t;
/**
* Authentication/Authorization process helper item.
*
* For the authentication process, further information may be needed. These
* items are defined as auth_item_t and have a AUTHN prefix.
* The authentication process returns important data for the authorization
* process, these items are defined with a AUTHZ prefix.
* Authentication uses AUTHN items and creates AUTHZ items during authentication,
* authorization reads AUTHZ values to give out privileges.
*
* +---+ +---------------------+
* | A | | A |
* | u | | u +-----------+ |
* | t | | t | Required | |
* | h | | h | auth_info | |
* | e | | o +-----------+ |
* | n | | r | |
* +-----------+ | t | | i | |
* | Provided | | i | | z V |
* | auth_info |--| c |-------------| a ----> match? ----|------->
* +-----------+ | a | | t |
* | t | | i |
* | i | | o |
* | o | | n |
* | n | | |
* +---+ +---------------------+
*/
enum auth_item_t {
/*
* items provided to authentication process
*/
/** authentication class to use, value is auth_class_t* */
AUTHN_AUTH_CLASS,
/** EAP method to request from peer, value is eap_type_t* */
AUTHN_EAP_TYPE,
/** EAP vendor to used in conjunction with EAP method, value is u_int32_t* */
AUTHN_EAP_VENDOR,
/** EAP identity to use within EAP-Identity exchange */
AUTHN_EAP_IDENTITY,
/** CA certificate to use for authentication, value is certificate_t* */
AUTHN_CA_CERT,
/** Keyid of a CA certificate to use, value is identification_t* */
AUTHN_CA_CERT_KEYID,
/** subject DN of a CA certificate to use, value is identification_t* */
AUTHN_CA_CERT_NAME,
/** intermediate certificate, value is certificate_t* */
AUTHN_IM_CERT,
/** certificate for trustchain verification, value is certificate_t* */
AUTHN_SUBJECT_CERT,
/** intermediate certificate supplied as hash and url */
AUTHN_IM_HASH_URL,
/** end-entity certificate supplied as hash and url */
AUTHN_SUBJECT_HASH_URL,
/*
* item provided to authorization process
*/
/** subject has been authenticated by public key, value is public_key_t* */
AUTHZ_PUBKEY,
/** subject has ben authenticated using preshared secrets, value is shared_key_t* */
AUTHZ_PSK,
/** subject has been authenticated using EAP, value is eap_type_t* */
AUTHZ_EAP,
/** certificate authority, value is certificate_t* */
AUTHZ_CA_CERT,
/** subject DN of a certificate authority, value is identification_t* */
AUTHZ_CA_CERT_NAME,
/** intermediate certificate in trustchain, value is certificate_t* */
AUTHZ_IM_CERT,
/** subject certificate, value is certificate_t* */
AUTHZ_SUBJECT_CERT,
/** result of a CRL validation, value is cert_validation_t */
AUTHZ_CRL_VALIDATION,
/** result of a OCSP validation, value is cert_validation_t */
AUTHZ_OCSP_VALIDATION,
/** subject is in attribute certificate group, value is identification_t* */
AUTHZ_AC_GROUP,
};
/**
* enum name for auth_item_t.
*/
extern enum_name_t *auth_item_names;
/**
* The auth_info class contains auth_item_t's used for AA.
*
* A auth_info allows the separation of authentication and authorization.
*/
struct auth_info_t {
/**
* Add an item to the set.
*
* @param type auth_info type
* @param value associated value to auth_info type, if any
*/
void (*add_item)(auth_info_t *this, auth_item_t type, void *value);
/**
* Get an item.
*
* @param type auth_info type to get
* @param value pointer to a pointer receiving item
* @return bool if item has been found
*/
bool (*get_item)(auth_info_t *this, auth_item_t type, void **value);
/**
* Replace an item.
*
* @param type new auth_info type
* @param value pointer to the new value
*/
void (*replace_item)(enumerator_t *this, auth_item_t type, void *value);
/**
* Create an enumerator over all items.
*
* @return enumerator over (auth_item_t type, void *value)
*/
enumerator_t* (*create_item_enumerator)(auth_info_t *this);
/**
* Check if this fulfills a set of required constraints.
*
* @param constraints required authorization infos
* @return TRUE if this complies with constraints
*/
bool (*complies)(auth_info_t *this, auth_info_t *constraints);
/**
* Merge items from other into this.
*
* Items do not get cloned, but moved from other to this.
*
* @param other items to read for merge
*/
void (*merge)(auth_info_t *this, auth_info_t *other);
/**
* Purge all items in auth_info.
*/
void (*purge)(auth_info_t *this);
/**
* Check two auth_infos for equality.
*
* @param other other item to compaire against this
* @return TRUE if auth infos identical
*/
bool (*equals)(auth_info_t *this, auth_info_t *other);
/**
* Destroy a auth_info instance with all associated values.
*/
void (*destroy)(auth_info_t *this);
};
/**
* Create a auth_info instance.
*/
auth_info_t *auth_info_create();
#endif /** AUTH_INFO_H_ @}*/
+84 -70
View File
@@ -23,7 +23,7 @@
#include <utils/mutex.h>
#include <utils/linked_list.h>
#include <credentials/sets/cert_cache.h>
#include <credentials/sets/auth_info_wrapper.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>
@@ -625,7 +625,7 @@ static certificate_t *get_better_ocsp(private_credential_manager_t *this,
*/
static cert_validation_t check_ocsp(private_credential_manager_t *this,
x509_t *subject, x509_t *issuer,
auth_info_t *auth)
auth_cfg_t *auth)
{
enumerator_t *enumerator;
cert_validation_t valid = VALIDATION_SKIPPED;
@@ -706,7 +706,11 @@ static cert_validation_t check_ocsp(private_credential_manager_t *this,
}
if (auth)
{
auth->add_item(auth, AUTHZ_OCSP_VALIDATION, &valid);
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;
@@ -728,6 +732,7 @@ static certificate_t* fetch_crl(private_credential_manager_t *this, char *url)
}
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");
@@ -833,7 +838,7 @@ static certificate_t *get_better_crl(private_credential_manager_t *this,
*/
static cert_validation_t check_crl(private_credential_manager_t *this,
x509_t *subject, x509_t *issuer,
auth_info_t *auth)
auth_cfg_t *auth)
{
cert_validation_t valid = VALIDATION_SKIPPED;
identification_t *keyid = NULL;
@@ -841,7 +846,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
certificate_t *current;
public_key_t *public;
enumerator_t *enumerator;
char *uri;
char *uri = NULL;
/* derive the authorityKeyIdentifier from the issuer's public key */
current = &issuer->interface;
@@ -920,7 +925,16 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
}
if (auth)
{
auth->add_item(auth, AUTHZ_CRL_VALIDATION, &valid);
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;
@@ -931,7 +945,7 @@ static cert_validation_t check_crl(private_credential_manager_t *this,
*/
static bool check_certificate(private_credential_manager_t *this,
certificate_t *subject, certificate_t *issuer,
bool crl, bool ocsp, auth_info_t *auth)
bool crl, bool ocsp, auth_cfg_t *auth)
{
time_t not_before, not_after;
@@ -963,7 +977,7 @@ static bool check_certificate(private_credential_manager_t *this,
DBG1(DBG_CFG, "certificate status is good");
return TRUE;
case VALIDATION_REVOKED:
/* has already been logged */
/* has already been logged */
return FALSE;
case VALIDATION_SKIPPED:
DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
@@ -983,8 +997,8 @@ static bool check_certificate(private_credential_manager_t *this,
case VALIDATION_GOOD:
DBG1(DBG_CFG, "certificate status is good");
return TRUE;
case VALIDATION_REVOKED:
/* has already been logged */
case VALIDATION_REVOKED:
/* has already been logged */
return FALSE;
case VALIDATION_FAILED:
case VALIDATION_SKIPPED:
@@ -1050,14 +1064,14 @@ static certificate_t *get_issuer_cert(private_credential_manager_t *this,
* 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_info_t *result,
certificate_t *subject, auth_cfg_t *result,
bool trusted, bool crl, bool ocsp)
{
certificate_t *current, *issuer;
auth_info_t *auth;
auth_cfg_t *auth;
u_int level = 0;
auth = auth_info_create();
auth = auth_cfg_create();
current = subject->get_ref(subject);
while (level++ < MAX_CA_LEVELS)
{
@@ -1067,14 +1081,14 @@ static bool verify_trust_chain(private_credential_manager_t *this,
/* accept only self-signed CAs as trust anchor */
if (this->cache->issued_by(this->cache, issuer, issuer))
{
auth->add_item(auth, AUTHZ_CA_CERT, issuer);
auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
DBG1(DBG_CFG, " using trusted ca certificate \"%D\"",
issuer->get_subject(issuer));
trusted = TRUE;
}
else
{
auth->add_item(auth, AUTHZ_IM_CERT, issuer);
auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
DBG1(DBG_CFG, " using trusted intermediate ca certificate "
"\"%D\"", issuer->get_subject(issuer));
}
@@ -1091,7 +1105,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
issuer->destroy(issuer);
break;
}
auth->add_item(auth, AUTHZ_IM_CERT, issuer);
auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
DBG1(DBG_CFG, " using untrusted intermediate certificate "
"\"%D\"", issuer->get_subject(issuer));
}
@@ -1123,7 +1137,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
}
if (trusted)
{
result->merge(result, auth);
result->merge(result, auth, FALSE);
}
auth->destroy(auth);
return trusted;
@@ -1149,20 +1163,20 @@ typedef struct {
bool ocsp;
/** pretrusted certificate we have served at first invocation */
certificate_t *pretrusted;
/** currently enumerating auth info */
auth_info_t *auth;
/** 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_info_t **auth)
certificate_t **cert, auth_cfg_t **auth)
{
certificate_t *current;
DESTROY_IF(this->auth);
this->auth = auth_info_create();
this->auth = auth_cfg_create();
if (!this->candidates)
{
@@ -1181,7 +1195,8 @@ static bool trusted_enumerate(trusted_enumerator_t *this,
verify_trust_chain(this->this, this->pretrusted, this->auth,
TRUE, this->crl, this->ocsp))
{
this->auth->add_item(this->auth, AUTHZ_CA_CERT, this->pretrusted);
this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
this->pretrusted->get_ref(this->pretrusted));
DBG1(DBG_CFG, " using trusted certificate \"%D\"",
this->pretrusted->get_subject(this->pretrusted));
*cert = this->pretrusted;
@@ -1264,15 +1279,15 @@ typedef struct {
private_credential_manager_t *this;
/** currently enumerating key */
public_key_t *current;
/** credset wrapper around auth */
auth_info_wrapper_t *wrapper;
/** 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_info_t **auth)
public_key_t **key, auth_cfg_t **auth)
{
certificate_t *cert;
@@ -1312,7 +1327,7 @@ static void public_destroy(public_enumerator_t *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_info_t *auth)
key_type_t type, identification_t *id, auth_cfg_t *auth)
{
public_enumerator_t *enumerator = malloc_thing(public_enumerator_t);
@@ -1324,7 +1339,7 @@ static enumerator_t* create_public_enumerator(private_credential_manager_t *this
enumerator->wrapper = NULL;
if (auth)
{
enumerator->wrapper = auth_info_wrapper_create(auth);
enumerator->wrapper = auth_cfg_wrapper_create(auth);
add_local_set(this, &enumerator->wrapper->set);
}
this->lock->read_lock(this->lock);
@@ -1334,40 +1349,22 @@ static enumerator_t* create_public_enumerator(private_credential_manager_t *this
/**
* Check if a certificate's keyid is contained in the auth helper
*/
static bool auth_contains_cacert(auth_info_t *auth, certificate_t *cert)
static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
{
enumerator_t *enumerator;
identification_t *value;
auth_item_t type;
auth_rule_t type;
bool found = FALSE;
enumerator = auth->create_item_enumerator(auth);
enumerator = auth->create_enumerator(auth);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (type == AUTHN_CA_CERT && cert->equals(cert, (certificate_t*)value))
if (type == AUTH_RULE_CA_CERT &&
cert->equals(cert, (certificate_t*)value))
{
found = TRUE;
break;
}
if (type == AUTHN_CA_CERT_KEYID)
{
public_key_t *public;
identification_t *certid, *keyid;
public = cert->get_public_key(cert);
if (public)
{
keyid = (identification_t*)value;
certid = public->get_id(public, keyid->get_type(keyid));
if (certid && certid->equals(certid, keyid))
{
public->destroy(public);
found = TRUE;
break;
}
public->destroy(public);
}
}
}
enumerator->destroy(enumerator);
return found;
@@ -1376,19 +1373,21 @@ static bool auth_contains_cacert(auth_info_t *auth, certificate_t *cert)
/**
* build a trustchain from subject up to a trust anchor in trusted
*/
static auth_info_t *build_trustchain(private_credential_manager_t *this,
certificate_t *subject, auth_info_t *auth)
static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
certificate_t *subject, auth_cfg_t *auth)
{
certificate_t *issuer, *current;
auth_info_t *trustchain;
auth_cfg_t *trustchain;
u_int level = 0;
trustchain = auth_info_create();
trustchain = auth_cfg_create();
if (!auth->get_item(auth, AUTHN_CA_CERT, (void**)&current))
current = auth->get(auth, AUTH_RULE_CA_CERT);
if (!current)
{
/* no trust anchor specified, return this cert only */
trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, subject);
trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT,
subject->get_ref(subject));
return trustchain;
}
current = subject->get_ref(subject);
@@ -1396,26 +1395,23 @@ static auth_info_t *build_trustchain(private_credential_manager_t *this,
{
if (auth_contains_cacert(auth, current))
{
trustchain->add_item(trustchain, AUTHZ_CA_CERT, current);
current->destroy(current);
trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
return trustchain;
}
if (subject == current)
{
trustchain->add_item(trustchain, AUTHZ_SUBJECT_CERT, current);
trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
}
else
{
trustchain->add_item(trustchain, AUTHZ_IM_CERT, current);
trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
}
issuer = get_issuer_cert(this, current, FALSE);
if (!issuer || issuer->equals(issuer, current) || level > MAX_CA_LEVELS)
{
DESTROY_IF(issuer);
current->destroy(current);
break;
}
current->destroy(current);
current = issuer;
level++;
}
@@ -1451,12 +1447,12 @@ static private_key_t *get_private_by_cert(private_credential_manager_t *this,
*/
static private_key_t *get_private(private_credential_manager_t *this,
key_type_t type, identification_t *id,
auth_info_t *auth)
auth_cfg_t *auth)
{
enumerator_t *enumerator;
certificate_t *cert;
private_key_t *private = NULL;
auth_info_t *trustchain;
auth_cfg_t *trustchain;
/* check if this is a lookup by key ID, and do it if so */
if (id)
@@ -1471,8 +1467,25 @@ static private_key_t *get_private(private_credential_manager_t *this,
break;
}
}
/* try to build a trustchain for each certificate found */
/* 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))
{
@@ -1482,7 +1495,7 @@ static private_key_t *get_private(private_credential_manager_t *this,
trustchain = build_trustchain(this, cert, auth);
if (trustchain)
{
auth->merge(auth, trustchain);
auth->merge(auth, trustchain, FALSE);
trustchain->destroy(trustchain);
break;
}
@@ -1491,6 +1504,7 @@ static private_key_t *get_private(private_credential_manager_t *this,
}
}
enumerator->destroy(enumerator);
/* if no valid trustchain was found, fall back to the first usable cert */
if (!private)
{
@@ -1500,7 +1514,7 @@ static private_key_t *get_private(private_credential_manager_t *this,
private = get_private_by_cert(this, cert, type);
if (private)
{
auth->add_item(auth, AUTHZ_SUBJECT_CERT, cert);
auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
break;
}
}
@@ -1566,8 +1580,8 @@ credential_manager_t *credential_manager_create()
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_info_t*))get_private;
this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_info_t *aut))create_public_enumerator;
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;
+7 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2008 Martin Willi
* Copyright (C) 2007-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
#include <utils/identification.h>
#include <utils/enumerator.h>
#include <credentials/auth_info.h>
#include <config/auth_cfg.h>
#include <credentials/credential_set.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/shared_key.h>
@@ -122,7 +122,6 @@ struct credential_manager_t {
* @param type kind of requested shared key
* @param me own identity
* @param other peers identity
* @param auth auth_info helper
* @return shared_key_t, NULL if none found
*/
shared_key_t *(*get_shared)(credential_manager_t *this, shared_key_type_t type,
@@ -138,11 +137,11 @@ struct credential_manager_t {
*
* @param type type of the key to get
* @param id identification the key belongs to
* @param auth auth_info helper, including trusted CA certificates
* @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_info_t *auth);
identification_t *id, auth_cfg_t *auth);
/**
* Create an enumerator over trusted public keys.
@@ -150,9 +149,8 @@ struct credential_manager_t {
* 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_info_t *,
* where the auth info contains gained privileges for the authorization
* process.
* 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
@@ -160,7 +158,7 @@ struct credential_manager_t {
* @return enumerator
*/
enumerator_t* (*create_public_enumerator)(credential_manager_t *this,
key_type_t type, identification_t *id, auth_info_t *auth);
key_type_t type, identification_t *id, auth_cfg_t *auth);
/**
* Cache a certificate by invoking cache_cert() on all registerd sets.
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008-2009 Martin Willi
* Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,36 +18,36 @@
#include <daemon.h>
#include "auth_info_wrapper.h"
#include "auth_cfg_wrapper.h"
typedef struct private_auth_info_wrapper_t private_auth_info_wrapper_t;
typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t;
/**
* private data of auth_info_wrapper
* private data of auth_cfg_wrapper
*/
struct private_auth_info_wrapper_t {
struct private_auth_cfg_wrapper_t {
/**
* public functions
*/
auth_info_wrapper_t public;
auth_cfg_wrapper_t public;
/**
* wrapped auth info
*/
auth_info_t *auth;
auth_cfg_t *auth;
};
/**
* enumerator for auth_info_wrapper_t.create_cert_enumerator()
* enumerator for auth_cfg_wrapper_t.create_cert_enumerator()
*/
typedef struct {
/** implements enumerator_t */
enumerator_t public;
/** inner enumerator from auth_info */
/** inner enumerator from auth_cfg */
enumerator_t *inner;
/** wrapped auth info */
auth_info_t *auth;
/** wrapped auth round */
auth_cfg_t *auth;
/** enumerated cert type */
certificate_type_t cert;
/** enumerated key type */
@@ -57,10 +57,11 @@ typedef struct {
} wrapper_enumerator_t;
/**
* Tries to fetch a certificate that was supplied as "Hash and URL" (replaces the
* item's type and value in place).
* 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_item_t *type, void **value)
static bool fetch_cert(wrapper_enumerator_t *enumerator,
auth_rule_t *rule, void **value)
{
char *url = (char*)*value;
if (!url)
@@ -77,29 +78,38 @@ static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, void
{
DBG1(DBG_CFG, " fetching certificate failed");
/* we set the item to NULL, so we can skip it */
enumerator->auth->replace_item(enumerator->inner, *type, NULL);
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);
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_item(enumerator->inner, *type, NULL);
enumerator->auth->replace(enumerator->auth, enumerator->inner,
*rule, NULL);
return FALSE;
}
DBG1(DBG_CFG, " fetched certificate \"%D\"", cert->get_subject(cert));
charon->credentials->cache_cert(charon->credentials, cert);
*type = (*type == AUTHN_IM_HASH_URL) ? AUTHN_IM_CERT : AUTHN_SUBJECT_CERT;
if (*rule == AUTH_HELPER_IM_HASH_URL)
{
*rule = AUTH_HELPER_IM_CERT;
}
else
{
*rule = AUTH_HELPER_SUBJECT_CERT;
}
*value = cert;
enumerator->auth->replace_item(enumerator->inner, *type, cert);
enumerator->auth->replace(enumerator->auth, enumerator->inner,
*rule, cert->get_ref(cert));
return TRUE;
}
@@ -108,26 +118,25 @@ static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, void
*/
static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
{
auth_item_t type;
auth_rule_t rule;
certificate_t *current;
public_key_t *public;
while (this->inner->enumerate(this->inner, &type, &current))
while (this->inner->enumerate(this->inner, &rule, &current))
{
if (type == AUTHN_IM_HASH_URL ||
type == AUTHN_SUBJECT_HASH_URL)
{
if (!fetch_cert(this, &type, (void**)&current))
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**)&current))
{
continue;
}
}
else if (type != AUTHN_SUBJECT_CERT &&
type != AUTHN_IM_CERT)
{
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;
@@ -164,9 +173,9 @@ static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
}
/**
* implementation of auth_info_wrapper_t.set.create_cert_enumerator
* implementation of auth_cfg_wrapper_t.set.create_cert_enumerator
*/
static enumerator_t *create_enumerator(private_auth_info_wrapper_t *this,
static enumerator_t *create_enumerator(private_auth_cfg_wrapper_t *this,
certificate_type_t cert, key_type_t key,
identification_t *id, bool trusted)
{
@@ -181,16 +190,16 @@ static enumerator_t *create_enumerator(private_auth_info_wrapper_t *this,
enumerator->cert = cert;
enumerator->key = key;
enumerator->id = id;
enumerator->inner = this->auth->create_item_enumerator(this->auth);
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_info_wrapper_t.destroy
* Implementation of auth_cfg_wrapper_t.destroy
*/
static void destroy(private_auth_info_wrapper_t *this)
static void destroy(private_auth_cfg_wrapper_t *this)
{
free(this);
}
@@ -198,16 +207,16 @@ static void destroy(private_auth_info_wrapper_t *this)
/*
* see header file
*/
auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth)
auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth)
{
private_auth_info_wrapper_t *this = malloc_thing(private_auth_info_wrapper_t);
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_info_wrapper_t*))destroy;
this->public.destroy = (void(*)(auth_cfg_wrapper_t*))destroy;
this->auth = auth;
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008 Martin Willi
* Copyright (C) 2008-2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,22 +16,22 @@
*/
/**
* @defgroup auth_info_wrapper auth_info_wrapper
* @defgroup auth_cfg_wrapper auth_cfg_wrapper
* @{ @ingroup sets
*/
#ifndef AUTH_INFO_WRAPPER_H_
#define AUTH_INFO_WRAPPER_H_
#ifndef AUTH_CFG_WRAPPER_H_
#define AUTH_CFG_WRAPPER_H_
#include <config/auth_cfg.h>
#include <credentials/credential_set.h>
#include <credentials/auth_info.h>
typedef struct auth_info_wrapper_t auth_info_wrapper_t;
typedef struct auth_cfg_wrapper_t auth_cfg_wrapper_t;
/**
* A wrapper around auth_info_t to handle it like a credential set.
* A wrapper around auth_cfg_t to handle it as a credential set.
*/
struct auth_info_wrapper_t {
struct auth_cfg_wrapper_t {
/**
* implements credential_set_t
@@ -39,17 +39,17 @@ struct auth_info_wrapper_t {
credential_set_t set;
/**
* Destroy a auth_info_wrapper instance.
* Destroy a auth_cfg_wrapper instance.
*/
void (*destroy)(auth_info_wrapper_t *this);
void (*destroy)(auth_cfg_wrapper_t *this);
};
/**
* Create a auth_info_wrapper instance.
* Create a auth_cfg_wrapper instance.
*
* @param auth the wrapped auth info
* @return wrapper around auth
*/
auth_info_wrapper_t *auth_info_wrapper_create(auth_info_t *auth);
auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth);
#endif /** AUTH_INFO_WRAPPER_H_ @}*/
#endif /** AUTH_CFG_WRAPPER_H_ @}*/