diff options
Diffstat (limited to 'src')
23 files changed, 760 insertions, 160 deletions
diff --git a/src/charon/credentials/auth_info.c b/src/charon/credentials/auth_info.c index 8839925fc..5d4a0f24e 100644 --- a/src/charon/credentials/auth_info.c +++ b/src/charon/credentials/auth_info.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -29,6 +30,8 @@ ENUM(auth_item_names, AUTHN_CA_CERT, AUTHZ_AC_GROUP, "AUTHN_CA_CERT_NAME", "AUTHN_IM_CERT", "AUTHN_SUBJECT_CERT", + "AUTHN_IM_HASH_URL", + "AUTHN_SUBJECT_HASH_URL", "AUTHZ_PUBKEY", "AUTHZ_PSK", "AUTHZ_EAP", @@ -69,14 +72,38 @@ struct item_t { }; /** - * implements item_enumerator_t.enumerate + * enumerator for auth_info_wrapper_t.create_cert_enumerator() */ -static bool item_filter(void *data, item_t **item, auth_item_t *type, - void *unused, void **value) +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) { - *type = (*item)->type; - *value = (*item)->value; - return TRUE; + 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); } /** @@ -84,8 +111,26 @@ static bool item_filter(void *data, item_t **item, auth_item_t *type, */ static enumerator_t* create_item_enumerator(private_auth_info_t *this) { - return enumerator_create_filter(this->items->create_enumerator(this->items), - (void*)item_filter, NULL, NULL); + 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; } /** @@ -136,6 +181,12 @@ static void add_item(private_auth_info_t *this, auth_item_t type, void *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: @@ -200,6 +251,8 @@ static bool complies(private_auth_info_t *this, auth_info_t *constraints) 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; } @@ -362,6 +415,16 @@ static bool equals(private_auth_info_t *this, private_auth_info_t *other) } 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: @@ -419,6 +482,57 @@ static bool equals(private_auth_info_t *this, private_auth_info_t *other) } /** + * 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_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_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.destroy */ static void destroy(private_auth_info_t *this) @@ -427,48 +541,7 @@ static void destroy(private_auth_info_t *this) while (this->items->remove_last(this->items, (void**)&item) == SUCCESS) { - 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 AUTHZ_CRL_VALIDATION: - case AUTHZ_OCSP_VALIDATION: - case AUTHZ_EAP: - { - free(item->value); - break; - } - 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; - } - } + destroy_item_value(item); free(item); } this->items->destroy(this->items); @@ -484,6 +557,7 @@ auth_info_t *auth_info_create() 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; diff --git a/src/charon/credentials/auth_info.h b/src/charon/credentials/auth_info.h index 5a4ecf90e..5fe2919f8 100644 --- a/src/charon/credentials/auth_info.h +++ b/src/charon/credentials/auth_info.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -69,6 +70,10 @@ enum auth_item_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 @@ -127,6 +132,14 @@ struct auth_info_t { 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) diff --git a/src/charon/credentials/sets/auth_info_wrapper.c b/src/charon/credentials/sets/auth_info_wrapper.c index b7576a5a7..cdbe2bc57 100644 --- a/src/charon/credentials/sets/auth_info_wrapper.c +++ b/src/charon/credentials/sets/auth_info_wrapper.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -15,6 +16,8 @@ * $Id$ */ +#include <daemon.h> + #include "auth_info_wrapper.h" typedef struct private_auth_info_wrapper_t private_auth_info_wrapper_t; @@ -43,6 +46,8 @@ typedef struct { enumerator_t public; /** inner enumerator from auth_info */ enumerator_t *inner; + /** wrapped auth info */ + auth_info_t *auth; /** enumerated cert type */ certificate_type_t cert; /** enumerated key type */ @@ -52,6 +57,52 @@ 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). + */ +static bool fetch_cert(wrapper_enumerator_t *enumerator, auth_item_t *type, void **value) +{ + char *url = (char*)*value; + if (!url) + { + /* fetching the certificate previously failed */ + return FALSE; + } + + chunk_t data; + certificate_t *cert; + + DBG1(DBG_CFG, "fetching certificate from '%s' ...", url); + if (lib->fetcher->fetch(lib->fetcher, url, &data) != SUCCESS) + { + DBG1(DBG_CFG, "fetching certificate from '%s' failed", url); + /* we set the item to NULL, so we can skip it */ + enumerator->auth->replace_item(enumerator->inner, *type, NULL); + return FALSE; + } + + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, data, BUILD_END); + + 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); + 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; + *value = cert; + enumerator->auth->replace_item(enumerator->inner, *type, cert); + + return TRUE; +} + +/** * enumerate function for wrapper_enumerator_t */ static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) @@ -62,8 +113,16 @@ static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) while (this->inner->enumerate(this->inner, &type, ¤t)) { - if (type != AUTHN_SUBJECT_CERT && - type != AUTHN_IM_CERT) + if (type == AUTHN_IM_HASH_URL || + type == AUTHN_SUBJECT_HASH_URL) + { + if (!fetch_cert(this, &type, (void**)¤t)) + { + continue; + } + } + else if (type != AUTHN_SUBJECT_CERT && + type != AUTHN_IM_CERT) { continue; } @@ -117,6 +176,7 @@ static enumerator_t *create_enumerator(private_auth_info_wrapper_t *this, return NULL; } enumerator = malloc_thing(wrapper_enumerator_t); + enumerator->auth = this->auth; enumerator->cert = cert; enumerator->key = key; enumerator->id = id; diff --git a/src/charon/encoding/payloads/cert_payload.c b/src/charon/encoding/payloads/cert_payload.c index e641cfb0e..c482b7a40 100644 --- a/src/charon/encoding/payloads/cert_payload.c +++ b/src/charon/encoding/payloads/cert_payload.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -17,6 +18,7 @@ */ #include <stddef.h> +#include <ctype.h> #include <daemon.h> @@ -75,6 +77,11 @@ struct private_cert_payload_t { * The contained cert data value. */ chunk_t data; + + /** + * TRUE if the hash and URL data is invalid + */ + bool invalid_hash_and_url; }; /** @@ -123,6 +130,42 @@ encoding_rule_t cert_payload_encodings[] = { */ static status_t verify(private_cert_payload_t *this) { + if (this->encoding == ENC_X509_HASH_AND_URL || + this->encoding == ENC_X509_HASH_AND_URL_BUNDLE) + { + /* rough verification of hash and URL encoded certificates */ + if (this->data.len <= 20) + { + DBG1(DBG_ENC, "invalid payload length for hash and URL (%d), ignore", + this->data.len); + this->invalid_hash_and_url = TRUE; + return SUCCESS; + } + + int i = 20; /* skipping the hash */ + for (; i < this->data.len; ++i) + { + if (this->data.ptr[i] == '\0') + { + /* null terminated, fine */ + return SUCCESS; + } + else if (!isprint(this->data.ptr[i])) + { + DBG1(DBG_ENC, "non printable characters in URL of hash and URL" + " encoded certificate payload, ignore"); + this->invalid_hash_and_url = TRUE; + return SUCCESS; + } + } + + /* URL is not null terminated, correct that */ + chunk_t data = chunk_alloc(this->data.len + 1); + memcpy(data.ptr, this->data.ptr, this->data.len); + data.ptr[this->data.len] = '\0'; + chunk_free(&this->data); + this->data = data; + } return SUCCESS; } @@ -169,40 +212,59 @@ static size_t get_length(private_cert_payload_t *this) } /** + * Implementation of cert_payload_t.get_cert_encoding. + */ +static cert_encoding_t get_cert_encoding(private_cert_payload_t *this) +{ + return this->encoding; +} + +/** * Implementation of cert_payload_t.get_cert. */ -static certificate_t* get_cert(private_cert_payload_t *this) +static certificate_t *get_cert(private_cert_payload_t *this) { - certificate_type_t type; - - switch (this->encoding) + if (this->encoding != ENC_X509_SIGNATURE) { - case ENC_X509_SIGNATURE: - type = CERT_X509; - break; - case ENC_PKCS7_WRAPPED_X509: - case ENC_PGP: - case ENC_DNS_SIGNED_KEY: - case ENC_KERBEROS_TOKEN: - case ENC_CRL: - case ENC_ARL: - case ENC_SPKI: - case ENC_X509_ATTRIBUTE: - case ENC_RAW_RSA_KEY: - case ENC_X509_HASH_AND_URL: - case ENC_X509_HASH_AND_URL_BUNDLE: - case ENC_OCSP_CONTENT: - default: - DBG1(DBG_ENC, "certificate encoding %N not supported", - cert_encoding_names, this->encoding); - return NULL; + return NULL; } - return lib->creds->create(lib->creds, CRED_CERTIFICATE, type, + return lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_BLOB_ASN1_DER, chunk_clone(this->data), BUILD_END); } /** + * Implementation of cert_payload_t.get_hash. + */ +static chunk_t get_hash(private_cert_payload_t *this) +{ + chunk_t hash = chunk_empty; + if ((this->encoding != ENC_X509_HASH_AND_URL && + this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || + this->invalid_hash_and_url) + { + return hash; + } + hash.ptr = this->data.ptr; + hash.len = 20; + return hash; +} + +/** + * Implementation of cert_payload_t.get_url. + */ +static char *get_url(private_cert_payload_t *this) +{ + if ((this->encoding != ENC_X509_HASH_AND_URL && + this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || + this->invalid_hash_and_url) + { + return NULL; + } + return (char*)this->data.ptr + 20; +} + +/** * Implementation of payload_t.destroy and cert_payload_t.destroy. */ static void destroy(private_cert_payload_t *this) @@ -228,12 +290,16 @@ cert_payload_t *cert_payload_create() this->public.destroy = (void (*) (cert_payload_t*))destroy; this->public.get_cert = (certificate_t* (*) (cert_payload_t*))get_cert; + this->public.get_cert_encoding = (cert_encoding_t (*) (cert_payload_t*))get_cert_encoding; + this->public.get_hash = (chunk_t (*) (cert_payload_t*))get_hash; + this->public.get_url = (char* (*) (cert_payload_t*))get_url; this->critical = FALSE; this->next_payload = NO_PAYLOAD; this->payload_length = CERT_PAYLOAD_HEADER_LENGTH; this->data = chunk_empty; this->encoding = 0; + this->invalid_hash_and_url = FALSE; return &this->public; } @@ -261,3 +327,21 @@ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert) return &this->public; } +/* + * Described in header + */ +cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url) +{ + private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create(); + chunk_t url_chunk; + + this->encoding = ENC_X509_HASH_AND_URL; + + url_chunk.ptr = url; + url_chunk.len = strlen(url) + 1; + + this->data = chunk_cat("cc", hash, url_chunk); + this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len; + return &this->public; +} + diff --git a/src/charon/encoding/payloads/cert_payload.h b/src/charon/encoding/payloads/cert_payload.h index 6b8228bb6..5a084cdb0 100644 --- a/src/charon/encoding/payloads/cert_payload.h +++ b/src/charon/encoding/payloads/cert_payload.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -80,6 +81,32 @@ struct cert_payload_t { certificate_t *(*get_cert)(cert_payload_t *this); /** + * Get the encoding of the certificate. + * + * @return encoding + */ + cert_encoding_t (*get_cert_encoding)(cert_payload_t *this); + + /** + * Get the hash if this is a hash and URL encoded certificate. + * + * This function returns internal data, do not free. + * + * @return hash + */ + chunk_t (*get_hash)(cert_payload_t *this); + + /** + * Get the URL if this is a hash and URL encoded certificate. + * + * This function returns internal data, do not free. + * + * @return url + */ + char *(*get_url)(cert_payload_t *this); + + + /** * Destroys the cert_payload object. */ void (*destroy) (cert_payload_t *this); @@ -101,4 +128,13 @@ cert_payload_t *cert_payload_create(void); */ cert_payload_t *cert_payload_create_from_cert(certificate_t *cert); +/** + * Creates a certificate payload with hash and URL encoding of a certificate. + * + * @param hash hash of the DER encoded certificate (get's cloned) + * @param url the URL to locate the certificate (get's cloned) + * @return cert_payload_t object + */ +cert_payload_t *cert_payload_create_from_hash_and_url(chunk_t hash, char *url); + #endif /* CERT_PAYLOAD_H_ @} */ diff --git a/src/charon/plugins/stroke/stroke_ca.c b/src/charon/plugins/stroke/stroke_ca.c index 30a270ee1..ba969b962 100644 --- a/src/charon/plugins/stroke/stroke_ca.c +++ b/src/charon/plugins/stroke/stroke_ca.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -20,6 +21,7 @@ #include <utils/mutex.h> #include <utils/linked_list.h> +#include <crypto/hashers/hasher.h> #include <daemon.h> @@ -77,6 +79,16 @@ struct ca_section_t { * OCSP URIs */ linked_list_t *ocsp; + + /** + * Hashes of certificates issued by this CA + */ + linked_list_t *hashes; + + /** + * Base URI used for certificates from this CA + */ + char *certuribase; }; /** @@ -90,6 +102,8 @@ static ca_section_t *ca_section_create(char *name, certificate_t *cert) ca->crl = linked_list_create(); ca->ocsp = linked_list_create(); ca->cert = cert; + ca->hashes = linked_list_create(); + ca->certuribase = NULL; return ca; } @@ -100,6 +114,8 @@ static void ca_section_destroy(ca_section_t *this) { this->crl->destroy_function(this->crl, free); this->ocsp->destroy_function(this->ocsp, free); + this->hashes->destroy_offset(this->hashes, offsetof(identification_t, destroy)); + free(this->certuribase); free(this->name); free(this); } @@ -162,6 +178,39 @@ static enumerator_t *create_inner_cdp(ca_section_t *section, cdp_data_t *data) } /** + * inner enumerator constructor for hash and URL + */ +static enumerator_t *create_inner_cdp_hashandurl(ca_section_t *section, cdp_data_t *data) +{ + enumerator_t *enumerator = NULL, *hash_enum; + identification_t *current; + + if (!data->id || !section->certuribase) + { + return NULL; + } + + hash_enum = section->hashes->create_enumerator(section->hashes); + while (hash_enum->enumerate(hash_enum, ¤t)) + { + if (current->matches(current, data->id)) + { + chunk_t hash = current->get_encoding(current); + char *hash_str = chunk_to_hex(hash, FALSE); + char *url = malloc(strlen(section->certuribase) + 40 + 1); + strcpy(url, section->certuribase); + strncat(url, hash_str, 40); + free(hash_str); + + enumerator = enumerator_create_single(url, free); + break; + } + } + hash_enum->destroy(hash_enum); + return enumerator; +} + +/** * Implementation of credential_set_t.create_cdp_enumerator. */ static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this, @@ -170,7 +219,8 @@ static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this, cdp_data_t *data; switch (type) - { /* we serve CRLs and OCSP responders */ + { /* we serve CRLs, OCSP responders and URLs for hash and URL */ + case CERT_X509: case CERT_X509_CRL: case CERT_X509_OCSP_RESPONSE: case CERT_ANY: @@ -185,8 +235,8 @@ static enumerator_t *create_cdp_enumerator(private_stroke_ca_t *this, this->mutex->lock(this->mutex); return enumerator_create_nested(this->sections->create_enumerator(this->sections), - (void*)create_inner_cdp, data, - (void*)cdp_data_destroy); + (type == CERT_X509) ? (void*)create_inner_cdp_hashandurl : (void*)create_inner_cdp, + data, (void*)cdp_data_destroy); } /** * Implementation of stroke_ca_t.add. @@ -221,6 +271,10 @@ static void add(private_stroke_ca_t *this, stroke_msg_t *msg) { ca->ocsp->insert_last(ca->ocsp, strdup(msg->add_ca.ocspuri2)); } + if (msg->add_ca.certuribase) + { + ca->certuribase = strdup(msg->add_ca.certuribase); + } this->mutex->lock(this->mutex); this->sections->insert_last(this->sections, ca); this->mutex->unlock(this->mutex); @@ -285,6 +339,42 @@ static void list_uris(linked_list_t *list, char *label, FILE *out) } /** + * Implementation of stroke_ca_t.check_for_hash_and_url. + */ +static void check_for_hash_and_url(private_stroke_ca_t *this, certificate_t* cert) +{ + ca_section_t *section; + enumerator_t *enumerator; + + hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher == NULL) + { + DBG1(DBG_IKE, "unable to use hash and URL, SHA1 not supported"); + return; + } + + this->mutex->lock(this->mutex); + enumerator = this->sections->create_enumerator(this->sections); + while (enumerator->enumerate(enumerator, (void**)§ion)) + { + if (section->certuribase && cert->issued_by(cert, section->cert)) + { + chunk_t hash, encoded = cert->get_encoding(cert); + hasher->allocate_hash(hasher, encoded, &hash); + section->hashes->insert_last(section->hashes, + identification_create_from_encoding(ID_CERT_DER_SHA1, hash)); + chunk_free(&hash); + chunk_free(&encoded); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); + + hasher->destroy(hasher); +} + +/** * Implementation of stroke_ca_t.list. */ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out) @@ -307,19 +397,20 @@ static void list(private_stroke_ca_t *this, stroke_msg_t *msg, FILE *out) first = FALSE; } fprintf(out, "\n"); - fprintf(out, " authname: \"%D\"\n", cert->get_subject(cert)); + fprintf(out, " authname: \"%D\"\n", cert->get_subject(cert)); /* list authkey and keyid */ if (public) { - fprintf(out, " authkey: %D\n", + fprintf(out, " authkey: %D\n", public->get_id(public, ID_PUBKEY_SHA1)); - fprintf(out, " keyid: %D\n", + fprintf(out, " keyid: %D\n", public->get_id(public, ID_PUBKEY_INFO_SHA1)); public->destroy(public); } - list_uris(section->crl, " crluris: ", out); - list_uris(section->ocsp, " ocspuris: ", out); + list_uris(section->crl, " crluris: ", out); + list_uris(section->ocsp, " ocspuris: ", out); + fprintf(out, " certuribase: '%s'\n", section->certuribase); } enumerator->destroy(enumerator); this->mutex->unlock(this->mutex); @@ -350,6 +441,7 @@ stroke_ca_t *stroke_ca_create(stroke_cred_t *cred) this->public.add = (void(*)(stroke_ca_t*, stroke_msg_t *msg))add; this->public.del = (void(*)(stroke_ca_t*, stroke_msg_t *msg))del; this->public.list = (void(*)(stroke_ca_t*, stroke_msg_t *msg, FILE *out))list; + this->public.check_for_hash_and_url = (void(*)(stroke_ca_t*, certificate_t*))check_for_hash_and_url; this->public.destroy = (void(*)(stroke_ca_t*))destroy; this->sections = linked_list_create(); diff --git a/src/charon/plugins/stroke/stroke_ca.h b/src/charon/plugins/stroke/stroke_ca.h index 5633196cd..882446afe 100644 --- a/src/charon/plugins/stroke/stroke_ca.h +++ b/src/charon/plugins/stroke/stroke_ca.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -61,6 +62,13 @@ struct stroke_ca_t { void (*list)(stroke_ca_t *this, stroke_msg_t *msg, FILE *out); /** + * Check if a certificate can be made available through hash and URL. + * + * @param cert peer certificate + */ + void (*check_for_hash_and_url)(stroke_ca_t *this, certificate_t* cert); + + /** * Destroy a stroke_ca instance. */ void (*destroy)(stroke_ca_t *this); diff --git a/src/charon/plugins/stroke/stroke_config.c b/src/charon/plugins/stroke/stroke_config.c index 622fa33b1..931dc9c39 100644 --- a/src/charon/plugins/stroke/stroke_config.c +++ b/src/charon/plugins/stroke/stroke_config.c @@ -43,6 +43,11 @@ struct private_stroke_config_t { mutex_t *mutex; /** + * ca sections + */ + stroke_ca_t *ca; + + /** * credentials */ stroke_cred_t *cred; @@ -435,6 +440,7 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, cert = this->cred->load_peer(this->cred, msg->add_conn.me.cert); if (cert) { + this->ca->check_for_hash_and_url(this->ca, cert); me = update_peerid(cert, me); cert->destroy(cert); } @@ -805,7 +811,7 @@ static void destroy(private_stroke_config_t *this) /* * see header file */ -stroke_config_t *stroke_config_create(stroke_cred_t *cred) +stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred) { private_stroke_config_t *this = malloc_thing(private_stroke_config_t); @@ -818,6 +824,7 @@ stroke_config_t *stroke_config_create(stroke_cred_t *cred) this->list = linked_list_create(); this->mutex = mutex_create(MUTEX_RECURSIVE); + this->ca = ca; this->cred = cred; return &this->public; diff --git a/src/charon/plugins/stroke/stroke_config.h b/src/charon/plugins/stroke/stroke_config.h index 478fa3843..22b493cd2 100644 --- a/src/charon/plugins/stroke/stroke_config.h +++ b/src/charon/plugins/stroke/stroke_config.h @@ -25,6 +25,7 @@ #include <config/backend.h> #include <stroke_msg.h> +#include "stroke_ca.h" #include "stroke_cred.h" typedef struct stroke_config_t stroke_config_t; @@ -62,6 +63,6 @@ struct stroke_config_t { /** * Create a stroke_config instance. */ -stroke_config_t *stroke_config_create(stroke_cred_t *cred); +stroke_config_t *stroke_config_create(stroke_ca_t *ca, stroke_cred_t *cred); #endif /* STROKE_CONFIG_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c index 03bc470ea..53148b9c0 100644 --- a/src/charon/plugins/stroke/stroke_socket.c +++ b/src/charon/plugins/stroke/stroke_socket.c @@ -250,13 +250,15 @@ static void stroke_add_ca(private_stroke_socket_t *this, pop_string(msg, &msg->add_ca.crluri2); pop_string(msg, &msg->add_ca.ocspuri); pop_string(msg, &msg->add_ca.ocspuri2); + pop_string(msg, &msg->add_ca.certuribase); - DBG2(DBG_CFG, "ca %s", msg->add_ca.name); - DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert); - DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri); - DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2); - DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri); - DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2); + DBG2(DBG_CFG, "ca %s", msg->add_ca.name); + DBG2(DBG_CFG, " cacert=%s", msg->add_ca.cacert); + DBG2(DBG_CFG, " crluri=%s", msg->add_ca.crluri); + DBG2(DBG_CFG, " crluri2=%s", msg->add_ca.crluri2); + DBG2(DBG_CFG, " ocspuri=%s", msg->add_ca.ocspuri); + DBG2(DBG_CFG, " ocspuri2=%s", msg->add_ca.ocspuri2); + DBG2(DBG_CFG, " certuribase=%s", msg->add_ca.certuribase); DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name); @@ -588,7 +590,7 @@ stroke_socket_t *stroke_socket_create() this->cred = stroke_cred_create(); this->attribute = stroke_attribute_create(); this->ca = stroke_ca_create(this->cred); - this->config = stroke_config_create(this->cred); + this->config = stroke_config_create(this->ca, this->cred); this->control = stroke_control_create(); this->list = stroke_list_create(); diff --git a/src/charon/sa/ike_sa.h b/src/charon/sa/ike_sa.h index 60e499d2c..4f760b532 100644 --- a/src/charon/sa/ike_sa.h +++ b/src/charon/sa/ike_sa.h @@ -79,6 +79,11 @@ enum ike_extension_t { * peer supports MOBIKE (RFC4555) */ EXT_MOBIKE = (1<<1), + + /** + * peer supports HTTP cert lookups as specified in RFC4306 + */ + EXT_HASH_AND_URL = (1<<2), }; /** diff --git a/src/charon/sa/tasks/ike_cert_post.c b/src/charon/sa/tasks/ike_cert_post.c index 3ec4ceca7..2532f2db8 100644 --- a/src/charon/sa/tasks/ike_cert_post.c +++ b/src/charon/sa/tasks/ike_cert_post.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2006-2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -48,6 +49,55 @@ struct private_ike_cert_post_t { }; /** + * Generates the cert payload, if possible with hash and url + */ +static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, certificate_t *cert) +{ + cert_payload_t *payload = NULL; + + if (this->ike_sa->supports_extension(this->ike_sa, EXT_HASH_AND_URL)) + { + /* ok, our peer sent us a HTTP_CERT_LOOKUP_SUPPORTED Notify */ + hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher != NULL) + { + chunk_t hash, encoded = cert->get_encoding(cert); + enumerator_t *enumerator; + char *url; + + hasher->allocate_hash(hasher, encoded, &hash); + identification_t *id = identification_create_from_encoding(ID_CERT_DER_SHA1, hash); + + enumerator = charon->credentials->create_cdp_enumerator(charon->credentials, CERT_X509, id); + if (enumerator->enumerate(enumerator, &url)) + { + /* if we have an URL available we send that to our peer */ + payload = cert_payload_create_from_hash_and_url(hash, url); + } + enumerator->destroy(enumerator); + + id->destroy(id); + chunk_free(&hash); + chunk_free(&encoded); + hasher->destroy(hasher); + } + else + { + DBG1(DBG_IKE, "unable to use hash and URL, SHA1 not supported"); + } + } + + if (!payload) + { + /* our peer does not support hash and URL or we do not have an URL + * to send to our peer, just create a normal cert payload */ + payload = cert_payload_create_from_cert(cert); + } + + return payload; +} + +/** * add certificates to message */ static void build_certs(private_ike_cert_post_t *this, message_t *message) @@ -81,7 +131,7 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message) { break; } - payload = cert_payload_create_from_cert(cert); + payload = build_cert_payload(this, cert); if (!payload) { break; diff --git a/src/charon/sa/tasks/ike_cert_pre.c b/src/charon/sa/tasks/ike_cert_pre.c index 34a5792ae..26ddb6e43 100644 --- a/src/charon/sa/tasks/ike_cert_pre.c +++ b/src/charon/sa/tasks/ike_cert_pre.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2006-2007 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -45,6 +46,11 @@ struct private_ike_cert_pre_t { * Are we the initiator? */ bool initiator; + + /** + * Did we send a HTTP_CERT_LOOKUP_SUPPORTED Notify? + */ + bool http_cert_lookup_supported_sent; }; /** @@ -62,53 +68,109 @@ static void process_certreqs(private_ike_cert_pre_t *this, message_t *message) iterator = message->get_payload_iterator(message); while (iterator->iterate(iterator, (void**)&payload)) { - if (payload->get_type(payload) == CERTIFICATE_REQUEST) + switch(payload->get_type(payload)) { - certreq_payload_t *certreq = (certreq_payload_t*)payload; - chunk_t keyid; - enumerator_t *enumerator; - - this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE); - - if (certreq->get_cert_type(certreq) != CERT_X509) + case CERTIFICATE_REQUEST: { - DBG1(DBG_IKE, "cert payload %N not supported - ignored", - certificate_type_names, certreq->get_cert_type(certreq)); - continue; - } - enumerator = certreq->create_keyid_enumerator(certreq); - while (enumerator->enumerate(enumerator, &keyid)) - { - identification_t *id; - certificate_t *cert; + certreq_payload_t *certreq = (certreq_payload_t*)payload; + chunk_t keyid; + enumerator_t *enumerator; + + this->ike_sa->set_condition(this->ike_sa, COND_CERTREQ_SEEN, TRUE); - id = identification_create_from_encoding( - ID_PUBKEY_INFO_SHA1, keyid); - cert = charon->credentials->get_cert(charon->credentials, - CERT_X509, KEY_ANY, id, TRUE); - if (cert) + if (certreq->get_cert_type(certreq) != CERT_X509) { - DBG1(DBG_IKE, "received cert request for \"%D\"", - cert->get_subject(cert)); - auth->add_item(auth, AUTHN_CA_CERT, cert); - cert->destroy(cert); - ca_found = TRUE; + DBG1(DBG_IKE, "cert payload %N not supported - ignored", + certificate_type_names, certreq->get_cert_type(certreq)); + break; } - else + enumerator = certreq->create_keyid_enumerator(certreq); + while (enumerator->enumerate(enumerator, &keyid)) + { + identification_t *id; + certificate_t *cert; + + id = identification_create_from_encoding( + ID_PUBKEY_INFO_SHA1, keyid); + cert = charon->credentials->get_cert(charon->credentials, + CERT_X509, KEY_ANY, id, TRUE); + if (cert) + { + DBG1(DBG_IKE, "received cert request for \"%D\"", + cert->get_subject(cert)); + auth->add_item(auth, AUTHN_CA_CERT, cert); + cert->destroy(cert); + ca_found = TRUE; + } + else + { + DBG1(DBG_IKE, "received cert request for unknown ca " + "with keyid %D", id); + auth->add_item(auth, AUTHN_CA_CERT_KEYID, id); + } + id->destroy(id); + } + enumerator->destroy(enumerator); + break; + } + case NOTIFY: + { + notify_payload_t *notify = (notify_payload_t*)payload; + + /* we only handle one type of notify here */ + if (notify->get_notify_type(notify) == HTTP_CERT_LOOKUP_SUPPORTED) { - DBG1(DBG_IKE, "received cert request for unknown ca " - "with keyid %D", id); - auth->add_item(auth, AUTHN_CA_CERT_KEYID, id); + this->ike_sa->enable_extension(this->ike_sa, EXT_HASH_AND_URL); } - id->destroy(id); + break; } - enumerator->destroy(enumerator); + default: + /* ignore other payloads here, these are handled elsewhere */ + break; } } iterator->destroy(iterator); } /** + * tries to extract a certificate from the cert payload or the credential + * manager (based on the hash of a hash and URL encoded cert). + * Note: the returned certificate (if any) has to be destroyed + */ +static certificate_t *try_get_cert(cert_payload_t *cert_payload) +{ + certificate_t *cert = NULL; + switch (cert_payload->get_cert_encoding(cert_payload)) + { + case ENC_X509_SIGNATURE: + { + cert = cert_payload->get_cert(cert_payload); + break; + } + case ENC_X509_HASH_AND_URL: + { + identification_t *id; + chunk_t hash = cert_payload->get_hash(cert_payload); + if (!hash.ptr) + { + /* invalid hash and URL data (logged elsewhere) */ + break; + } + id = identification_create_from_encoding(ID_CERT_DER_SHA1, hash); + cert = charon->credentials->get_cert(charon->credentials, + CERT_X509, KEY_ANY, id, FALSE); + id->destroy(id); + break; + } + default: + { + break; + } + } + return cert; +} + +/** * import certificates */ static void process_certs(private_ike_cert_pre_t *this, message_t *message) @@ -125,28 +187,85 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message) { if (payload->get_type(payload) == CERTIFICATE) { - certificate_t *cert; cert_payload_t *cert_payload = (cert_payload_t*)payload; - - cert = cert_payload->get_cert(cert_payload); - if (cert) + cert_encoding_t type = cert_payload->get_cert_encoding(cert_payload); + switch (type) { - if (first) - { /* the first certificate MUST be an end entity one */ - - DBG1(DBG_IKE, "received end entity cert \"%D\"", - cert->get_subject(cert)); - auth->add_item(auth, AUTHN_SUBJECT_CERT, cert); - first = FALSE; - } - else + case ENC_X509_SIGNATURE: + case ENC_X509_HASH_AND_URL: { - DBG1(DBG_IKE, "received issuer cert \"%D\"", - cert->get_subject(cert)); - auth->add_item(auth, AUTHN_IM_CERT, cert); + if (type == ENC_X509_HASH_AND_URL && + !this->http_cert_lookup_supported_sent) + { + DBG1(DBG_IKE, "received hash and URL encoded cert, but" + " we don't accept them, ignore"); + break; + } + + certificate_t *cert = try_get_cert(cert_payload); + + if (cert) + { + /* we've got a certificate from the payload or the cache */ + if (first) + { /* the first certificate MUST be an end entity one */ + DBG1(DBG_IKE, "received end entity cert \"%D\"", + cert->get_subject(cert)); + auth->add_item(auth, AUTHN_SUBJECT_CERT, cert); + first = FALSE; + } + else + { + DBG1(DBG_IKE, "received issuer cert \"%D\"", + cert->get_subject(cert)); + auth->add_item(auth, AUTHN_IM_CERT, cert); + } + cert->destroy(cert); + } + else if (type == ENC_X509_HASH_AND_URL) + { + /* we received a hash and URL encoded certificate that + * we haven't fetched yet, we store the URL and fetch + * it later */ + char *url = cert_payload->get_url(cert_payload); + if (!url) + { + DBG1(DBG_IKE, "received invalid hash and URL encoded" + " cert, ignore"); + break; + } + + if (first) + { /* the first certificate MUST be an end entity one */ + DBG1(DBG_IKE, "received hash and URL for end" + " entity cert \"%s\"", url); + auth->add_item(auth, AUTHN_SUBJECT_HASH_URL, url); + first = FALSE; + } + else + { + DBG1(DBG_IKE, "received hash and URL for issuer" + " cert \"%s\"", url); + auth->add_item(auth, AUTHN_IM_HASH_URL, url); + } + } + break; } + case ENC_PKCS7_WRAPPED_X509: + case ENC_PGP: + case ENC_DNS_SIGNED_KEY: + case ENC_KERBEROS_TOKEN: + case ENC_CRL: + case ENC_ARL: + case ENC_SPKI: + case ENC_X509_ATTRIBUTE: + case ENC_RAW_RSA_KEY: + case ENC_X509_HASH_AND_URL_BUNDLE: + case ENC_OCSP_CONTENT: + default: + DBG1(DBG_ENC, "certificate encoding %N not supported", + cert_encoding_names, cert_payload->get_cert_encoding(cert_payload)); } - cert->destroy(cert); } } iterator->destroy(iterator); @@ -238,6 +357,15 @@ static void build_certreqs(private_ike_cert_pre_t *this, message_t *message) } enumerator->destroy(enumerator); } + + /* if we've added at least one certreq, we notify our peer that we support + * hash and URL for the requested certificates */ + if (lib->settings->get_bool(lib->settings, "charon.hash_and_url", FALSE) && + message->get_payload(message, CERTIFICATE_REQUEST)) + { + message->add_notify(message, FALSE, HTTP_CERT_LOOKUP_SUPPORTED, chunk_empty); + this->http_cert_lookup_supported_sent = TRUE; + } } /** @@ -342,6 +470,7 @@ ike_cert_pre_t *ike_cert_pre_create(ike_sa_t *ike_sa, bool initiator) this->ike_sa = ike_sa; this->initiator = initiator; + this->http_cert_lookup_supported_sent = FALSE; return &this->public; } diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index 9b6bdb630..0b3ea68f5 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -4,6 +4,7 @@ * Copyright (C) 2002 Mario Strasser * Copyright (C) 2000-2006 Andreas Steffen * Copyright (C) 2006-2008 Martin Willi + * Copyright (C) 2008 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -68,6 +69,11 @@ struct private_x509_cert_t { * X.509 certificate encoding in ASN.1 DER format */ chunk_t encoding; + + /** + * SHA1 hash of the DER encoding of this X.509 certificate + */ + chunk_t encoding_hash; /** * X.509 certificate body over which signature is computed @@ -904,6 +910,12 @@ static id_match_t has_subject(private_x509_cert_t *this, identification_t *subje identification_t *current; enumerator_t *enumerator; id_match_t match, best; + + if (this->encoding_hash.ptr && subject->get_type(subject) == ID_CERT_DER_SHA1 && + chunk_equals(this->encoding_hash, subject->get_encoding(subject))) + { + return ID_MATCH_PERFECT; + } best = this->subject->matches(this->subject, subject); enumerator = this->subjectAltNames->create_enumerator(this->subjectAltNames); @@ -1152,6 +1164,7 @@ static void destroy(private_x509_cert_t *this) DESTROY_IF(this->public_key); DESTROY_IF(this->authKeyIdentifier); chunk_free(&this->encoding); + chunk_free(&this->encoding_hash); free(this); } } @@ -1184,6 +1197,7 @@ static private_x509_cert_t* create_empty(void) this->public.interface.create_ocsp_uri_enumerator = (enumerator_t* (*)(x509_t*))create_ocsp_uri_enumerator; this->encoding = chunk_empty; + this->encoding_hash = chunk_empty; this->public_key = NULL; this->subject = NULL; this->issuer = NULL; @@ -1218,6 +1232,18 @@ static private_x509_cert_t *create_from_chunk(chunk_t chunk) { this->flags |= X509_SELF_SIGNED; } + + hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); + if (hasher != NULL) + { + hasher->allocate_hash(hasher, this->encoding, &this->encoding_hash); + hasher->destroy(hasher); + } + else + { + DBG1(" unable to create hash of certificate, SHA1 not supported"); + } + return this; } diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index 4eead4a9f..e44ba7d6f 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -50,11 +50,12 @@ ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID, "ID_DER_ASN1_DN", "ID_DER_ASN1_GN", "ID_KEY_ID"); -ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_PUBKEY_SHA1, ID_KEY_ID, +ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_CERT_DER_SHA1, ID_KEY_ID, "ID_DER_ASN1_GN_URI", "ID_PUBKEY_INFO_SHA1", - "ID_PUBKEY_SHA1"); -ENUM_END(id_type_names, ID_PUBKEY_SHA1); + "ID_PUBKEY_SHA1", + "ID_CERT_DER_SHA1"); +ENUM_END(id_type_names, ID_CERT_DER_SHA1); /** * X.501 acronyms for well known object identifiers (OIDs) @@ -941,6 +942,7 @@ static int print(FILE *stream, const struct printf_info *info, case ID_KEY_ID: case ID_PUBKEY_INFO_SHA1: case ID_PUBKEY_SHA1: + case ID_CERT_DER_SHA1: return fprintf(stream, "%#B", &this->encoded); case ID_DER_ASN1_GN_URI: { @@ -1175,6 +1177,7 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en case ID_DER_ASN1_GN_URI: case ID_PUBKEY_INFO_SHA1: case ID_PUBKEY_SHA1: + case ID_CERT_DER_SHA1: default: break; } diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index 31c49c269..29318ce47 100644 --- a/src/libstrongswan/utils/identification.h +++ b/src/libstrongswan/utils/identification.h @@ -137,6 +137,11 @@ enum id_type_t { * SHA1 hash over PKCS#1 subjectPublicKey */ ID_PUBKEY_SHA1, + + /** + * SHA1 hash of the binary DER encoding of a certificate + */ + ID_CERT_DER_SHA1, }; /** diff --git a/src/starter/args.c b/src/starter/args.c index f9e307ed7..84179b673 100644 --- a/src/starter/args.c +++ b/src/starter/args.c @@ -1,5 +1,4 @@ /* automatic handling of confread struct arguments - * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2006 Andreas Steffen * Hochschule fuer Technik Rapperswil, Switzerland * @@ -233,6 +232,7 @@ static const token_info_t token_info[] = { ARG_STR, offsetof(starter_ca_t, crluri2), NULL }, { ARG_STR, offsetof(starter_ca_t, ocspuri), NULL }, { ARG_STR, offsetof(starter_ca_t, ocspuri2), NULL }, + { ARG_STR, offsetof(starter_ca_t, certuribase), NULL }, /* end keywords */ { ARG_MISC, 0, NULL /* KW_HOST */ }, diff --git a/src/starter/confread.h b/src/starter/confread.h index ae25a0843..5c0b714d8 100644 --- a/src/starter/confread.h +++ b/src/starter/confread.h @@ -1,6 +1,4 @@ /* strongSwan IPsec config file parser - * Copyright (C) 2007 Tobias Brunner - * Hochschule fuer Technik Rapperswil * Copyright (C) 2001-2002 Mathieu Lafon * Arkoon Network Security * @@ -154,6 +152,7 @@ struct starter_ca { char *crluri2; char *ocspuri; char *ocspuri2; + char *certuribase; bool strict; diff --git a/src/starter/ipsec.conf.5 b/src/starter/ipsec.conf.5 index 335042fb5..eefd216fb 100644 --- a/src/starter/ipsec.conf.5 +++ b/src/starter/ipsec.conf.5 @@ -858,6 +858,11 @@ synonym for .TP .B ocspuri2 defines an alternative OCSP URI. Currently used by IKEv2 only. +.B certuribase +defines the base URI for the Hash and URL feature supported by IKEv2. +Instead of exchanging complete certificates, IKEv2 allows to send an URI +that resolves to the DER encoded certificate. The certificate URIs are built +by appending the SHA1 hash of the DER encoded certificates to this base URI. .SH "CONFIG SECTIONS" At present, the only .B config diff --git a/src/starter/keywords.h b/src/starter/keywords.h index 84c5ab79a..3ffe0a9dc 100644 --- a/src/starter/keywords.h +++ b/src/starter/keywords.h @@ -1,5 +1,4 @@ /* strongSwan keywords - * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005 Andreas Steffen * Hochschule fuer Technik Rapperswil, Switzerland * @@ -105,9 +104,10 @@ typedef enum { KW_CRLURI2, KW_OCSPURI, KW_OCSPURI2, + KW_CERTURIBASE, #define KW_CA_FIRST KW_CA_SETUP -#define KW_CA_LAST KW_OCSPURI2 +#define KW_CA_LAST KW_CERTURIBASE /* end keywords */ KW_HOST, diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt index 470397a9c..79914133d 100644 --- a/src/starter/keywords.txt +++ b/src/starter/keywords.txt @@ -1,6 +1,5 @@ %{ /* strongSwan keywords - * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005 Andreas Steffen * Hochschule fuer Technik Rapperswil, Switzerland * @@ -89,6 +88,7 @@ crluri2, KW_CRLURI2 ocspuri, KW_OCSPURI ocspuri1, KW_OCSPURI ocspuri2, KW_OCSPURI2 +certuribase, KW_CERTURIBASE left, KW_LEFT leftnexthop, KW_LEFTNEXTHOP leftsubnet, KW_LEFTSUBNET diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index 1ee7ddc60..d75d25a72 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -1,5 +1,4 @@ /* Stroke for charon is the counterpart to whack from pluto - * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2006 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -308,12 +307,13 @@ int starter_stroke_add_ca(starter_ca_t *ca) msg.type = STR_ADD_CA; msg.length = offsetof(stroke_msg_t, buffer); - msg.add_ca.name = push_string(&msg, ca->name); - msg.add_ca.cacert = push_string(&msg, ca->cacert); - msg.add_ca.crluri = push_string(&msg, ca->crluri); - msg.add_ca.crluri2 = push_string(&msg, ca->crluri2); - msg.add_ca.ocspuri = push_string(&msg, ca->ocspuri); - msg.add_ca.ocspuri2 = push_string(&msg, ca->ocspuri2); + msg.add_ca.name = push_string(&msg, ca->name); + msg.add_ca.cacert = push_string(&msg, ca->cacert); + msg.add_ca.crluri = push_string(&msg, ca->crluri); + msg.add_ca.crluri2 = push_string(&msg, ca->crluri2); + msg.add_ca.ocspuri = push_string(&msg, ca->ocspuri); + msg.add_ca.ocspuri2 = push_string(&msg, ca->ocspuri2); + msg.add_ca.certuribase = push_string(&msg, ca->certuribase); return send_stroke_msg(&msg); } diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index 12df24570..96d13ae84 100644 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -233,6 +233,7 @@ struct stroke_msg_t { char *crluri2; char *ocspuri; char *ocspuri2; + char *certuribase; } add_ca; /* data for STR_LOGLEVEL */ |