diff options
Diffstat (limited to 'src/charon/encoding/payloads/cert_payload.c')
-rw-r--r-- | src/charon/encoding/payloads/cert_payload.c | 221 |
1 files changed, 139 insertions, 82 deletions
diff --git a/src/charon/encoding/payloads/cert_payload.c b/src/charon/encoding/payloads/cert_payload.c index c456f4936..99f504c5e 100644 --- a/src/charon/encoding/payloads/cert_payload.c +++ b/src/charon/encoding/payloads/cert_payload.c @@ -1,12 +1,6 @@ -/** - * @file cert_payload.c - * - * @brief Implementation of cert_payload_t. - * - */ - /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -19,29 +13,32 @@ * 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: cert_payload.c 3852 2008-04-18 21:27:08Z andreas $ */ #include <stddef.h> +#include <ctype.h> -#include "cert_payload.h" +#include <daemon.h> +#include "cert_payload.h" -ENUM(cert_encoding_names, CERT_NONE, CERT_OCSP_CONTENT, - "CERT_NONE", - "CERT_PKCS7_WRAPPED_X509", - "CERT_PGP", - "CERT_DNS_SIGNED_KEY", - "CERT_X509_SIGNATURE", - "CERT_X509_KEY_EXCHANGE", - "CERT_KERBEROS_TOKENS", - "CERT_CRL", - "CERT_ARL", - "CERT_SPKI", - "CERT_X509_ATTRIBUTE", - "CERT_RAW_RSA_KEY", - "CERT_X509_HASH_AND_URL", - "CERT_X509_HASH_AND_URL_BUNDLE", - "CERT_OCSP_CONTENT", +ENUM(cert_encoding_names, ENC_PKCS7_WRAPPED_X509, ENC_OCSP_CONTENT, + "ENC_PKCS7_WRAPPED_X509", + "ENC_PGP", + "ENC_DNS_SIGNED_KEY", + "ENC_X509_SIGNATURE", + "ENC_X509_KEY_EXCHANGE", + "ENC_KERBEROS_TOKENS", + "ENC_CRL", + "ENC_ARL", + "ENC_SPKI", + "ENC_X509_ATTRIBUTE", + "ENC_RAW_RSA_KEY", + "ENC_X509_HASH_AND_URL", + "ENC_X509_HASH_AND_URL_BUNDLE", + "ENC_OCSP_CONTENT", ); typedef struct private_cert_payload_t private_cert_payload_t; @@ -74,12 +71,17 @@ struct private_cert_payload_t { /** * Encoding of the CERT Data. */ - u_int8_t cert_encoding; + u_int8_t encoding; /** * The contained cert data value. */ - chunk_t cert_data; + chunk_t data; + + /** + * TRUE if the "Hash and URL" data is invalid + */ + bool invalid_hash_and_url; }; /** @@ -105,9 +107,9 @@ encoding_rule_t cert_payload_encodings[] = { /* Length of the whole payload*/ { PAYLOAD_LENGTH, offsetof(private_cert_payload_t, payload_length)}, /* 1 Byte CERT type*/ - { U_INT_8, offsetof(private_cert_payload_t, cert_encoding) }, + { U_INT_8, offsetof(private_cert_payload_t, encoding) }, /* some cert data bytes, length is defined in PAYLOAD_LENGTH */ - { CERT_DATA, offsetof(private_cert_payload_t, cert_data) } + { CERT_DATA, offsetof(private_cert_payload_t, data) } }; /* @@ -128,11 +130,41 @@ encoding_rule_t cert_payload_encodings[] = { */ static status_t verify(private_cert_payload_t *this) { - if ((this->cert_encoding == 0) || - ((this->cert_encoding >= CERT_ROOF) && (this->cert_encoding <= 200))) + if (this->encoding == ENC_X509_HASH_AND_URL || + this->encoding == ENC_X509_HASH_AND_URL_BUNDLE) { - /* reserved IDs */ - return FAILED; + /* coarse 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; } @@ -140,7 +172,8 @@ static status_t verify(private_cert_payload_t *this) /** * Implementation of cert_payload_t.get_encoding_rules. */ -static void get_encoding_rules(private_cert_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +static void get_encoding_rules(private_cert_payload_t *this, + encoding_rule_t **rules, size_t *rule_count) { *rules = cert_payload_encodings; *rule_count = sizeof(cert_payload_encodings) / sizeof(encoding_rule_t); @@ -159,7 +192,7 @@ static payload_type_t get_payload_type(private_cert_payload_t *this) */ static payload_type_t get_next_type(private_cert_payload_t *this) { - return (this->next_payload); + return this->next_payload; } /** @@ -179,56 +212,56 @@ static size_t get_length(private_cert_payload_t *this) } /** - * Implementation of cert_payload_t.set_cert_encoding. - */ -static void set_cert_encoding (private_cert_payload_t *this, cert_encoding_t encoding) -{ - this->cert_encoding = encoding; -} - -/** * Implementation of cert_payload_t.get_cert_encoding. */ -static cert_encoding_t get_cert_encoding (private_cert_payload_t *this) +static cert_encoding_t get_cert_encoding(private_cert_payload_t *this) { - return (this->cert_encoding); + return this->encoding; } /** - * Implementation of cert_payload_t.set_data. + * Implementation of cert_payload_t.get_cert. */ -static void set_data (private_cert_payload_t *this, chunk_t data) +static certificate_t *get_cert(private_cert_payload_t *this) { - if (this->cert_data.ptr != NULL) + if (this->encoding != ENC_X509_SIGNATURE) { - chunk_free(&(this->cert_data)); + return NULL; } - this->cert_data.ptr = clalloc(data.ptr,data.len); - this->cert_data.len = data.len; - this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->cert_data.len; + 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_data. + * Implementation of cert_payload_t.get_hash. */ -static chunk_t get_data (private_cert_payload_t *this) +static chunk_t get_hash(private_cert_payload_t *this) { - return (this->cert_data); + 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_data_clone. + * Implementation of cert_payload_t.get_url. */ -static chunk_t get_data_clone (private_cert_payload_t *this) +static char *get_url(private_cert_payload_t *this) { - chunk_t cloned_data; - if (this->cert_data.ptr == NULL) + if ((this->encoding != ENC_X509_HASH_AND_URL && + this->encoding != ENC_X509_HASH_AND_URL_BUNDLE) || + this->invalid_hash_and_url) { - return (this->cert_data); + return NULL; } - cloned_data.ptr = clalloc(this->cert_data.ptr,this->cert_data.len); - cloned_data.len = this->cert_data.len; - return cloned_data; + return (char*)this->data.ptr + 20; } /** @@ -236,11 +269,7 @@ static chunk_t get_data_clone (private_cert_payload_t *this) */ static void destroy(private_cert_payload_t *this) { - if (this->cert_data.ptr != NULL) - { - chunk_free(&(this->cert_data)); - } - + chunk_free(&this->data); free(this); } @@ -251,7 +280,6 @@ cert_payload_t *cert_payload_create() { private_cert_payload_t *this = malloc_thing(private_cert_payload_t); - /* interface functions */ this->public.payload_interface.verify = (status_t (*) (payload_t*))verify; this->public.payload_interface.get_encoding_rules = (void (*) (payload_t*,encoding_rule_t**, size_t*))get_encoding_rules; this->public.payload_interface.get_length = (size_t (*) (payload_t*))get_length; @@ -260,31 +288,60 @@ cert_payload_t *cert_payload_create() this->public.payload_interface.get_type = (payload_type_t (*) (payload_t*))get_payload_type; this->public.payload_interface.destroy = (void (*) (payload_t*))destroy; - /* public functions */ this->public.destroy = (void (*) (cert_payload_t*))destroy; - this->public.set_cert_encoding = (void (*) (cert_payload_t*,cert_encoding_t))set_cert_encoding; + 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.set_data = (void (*) (cert_payload_t*,chunk_t))set_data; - this->public.get_data_clone = (chunk_t (*) (cert_payload_t*))get_data_clone; - this->public.get_data = (chunk_t (*) (cert_payload_t*))get_data; + this->public.get_hash = (chunk_t (*) (cert_payload_t*))get_hash; + this->public.get_url = (char* (*) (cert_payload_t*))get_url; - /* private variables */ this->critical = FALSE; this->next_payload = NO_PAYLOAD; this->payload_length = CERT_PAYLOAD_HEADER_LENGTH; - this->cert_data = chunk_empty; + this->data = chunk_empty; + this->encoding = 0; + this->invalid_hash_and_url = FALSE; - return (&(this->public)); + return &this->public; } /* * Described in header */ -cert_payload_t *cert_payload_create_from_x509(x509_t *cert) +cert_payload_t *cert_payload_create_from_cert(certificate_t *cert) { - cert_payload_t *this = cert_payload_create(); + private_cert_payload_t *this = (private_cert_payload_t*)cert_payload_create(); + + switch (cert->get_type(cert)) + { + case CERT_X509: + this->encoding = ENC_X509_SIGNATURE; + break; + default: + DBG1(DBG_ENC, "embedding %N certificate in payload failed", + certificate_type_names, cert->get_type(cert)); + free(this); + return NULL; + } + this->data = cert->get_encoding(cert); + this->payload_length = CERT_PAYLOAD_HEADER_LENGTH + this->data.len; + return &this->public; +} - this->set_cert_encoding(this, CERT_X509_SIGNATURE); - this->set_data(this, cert->get_certificate(cert)); - return this; +/* + * 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; } + |