support for hash and URL encoded certificate payloads in charon

This commit is contained in:
Tobias Brunner
2008-04-18 11:24:45 +00:00
parent eed87e1d76
commit 6439267a8c
23 changed files with 760 additions and 160 deletions
+108 -24
View File
@@ -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;
}
@@ -168,40 +211,59 @@ static size_t get_length(private_cert_payload_t *this)
return this->payload_length;
}
/**
* 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.
*/
@@ -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;
}
@@ -1,4 +1,5 @@
/*
* Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -79,6 +80,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.
*/
@@ -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_ @} */