openssl: add support for IP addr blocks in X.509 certificates

This commit is contained in:
Michael Rossberg
2013-05-24 15:09:47 +02:00
committed by Martin Willi
parent 71d740cac6
commit 5e4b1ad20a
@@ -17,6 +17,9 @@
*/
/*
* Copyright (C) 2013 Michael Rossberg
* Copyright (C) 2013 Technische Universität Ilmenau
*
* Copyright (C) 2010 secunet Security Networks AG
* Copyright (C) 2010 Thomas Egerer
*
@@ -50,7 +53,12 @@
#include <utils/debug.h>
#include <asn1/oid.h>
#include <collections/linked_list.h>
#include <selectors/traffic_selector.h>
/* IP Addr block extension support was introduced with 0.9.8e */
#if OPENSSL_VERSION_NUMBER < 0x0090805fL
#define OPENSSL_NO_RFC3779
#endif
typedef struct private_openssl_x509_t private_openssl_x509_t;
@@ -149,6 +157,12 @@ struct private_openssl_x509_t {
*/
linked_list_t *ocsp_uris;
/**
* List of ipAddrBlocks as traffic_selector_t
*/
linked_list_t *ipAddrBlocks;
/**
* References to this cert
*/
@@ -283,6 +297,12 @@ METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
return this->ocsp_uris->create_enumerator(this->ocsp_uris);
}
METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
private_openssl_x509_t *this)
{
return this->ipAddrBlocks->create_enumerator(this->ipAddrBlocks);
}
METHOD(certificate_t, get_type, certificate_type_t,
private_openssl_x509_t *this)
{
@@ -506,6 +526,8 @@ METHOD(certificate_t, destroy, void,
offsetof(identification_t, destroy));
this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy);
this->ocsp_uris->destroy_function(this->ocsp_uris, free);
this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks,
offsetof(traffic_selector_t, destroy));
free(this);
}
}
@@ -542,7 +564,7 @@ static private_openssl_x509_t *create_empty()
.create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
.create_crl_uri_enumerator = _create_crl_uri_enumerator,
.create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
.create_ipAddrBlock_enumerator = (void*)enumerator_create_empty,
.create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
.create_name_constraint_enumerator = (void*)enumerator_create_empty,
.create_cert_policy_enumerator = (void*)enumerator_create_empty,
.create_policy_mapping_enumerator = (void*)enumerator_create_empty,
@@ -552,6 +574,7 @@ static private_openssl_x509_t *create_empty()
.issuerAltNames = linked_list_create(),
.crl_uris = linked_list_create(),
.ocsp_uris = linked_list_create(),
.ipAddrBlocks = linked_list_create(),
.pathlen = X509_NO_CONSTRAINT,
.ref = 1,
);
@@ -772,6 +795,92 @@ static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
return TRUE;
}
#ifndef OPENSSL_NO_RFC3779
/**
* Parse a single block of ipAddrBlock extension
*/
static void parse_ipAddrBlock_ext_fam(private_openssl_x509_t *this,
IPAddressFamily *fam)
{
const IPAddressOrRanges *list;
IPAddressOrRange *aor;
traffic_selector_t *ts;
ts_type_t type;
chunk_t from, to;
int i, afi;
if (fam->ipAddressChoice->type != IPAddressChoice_addressesOrRanges)
{
return;
}
afi = v3_addr_get_afi(fam);
switch (afi)
{
case IANA_AFI_IPV4:
from = chunk_alloca(4);
to = chunk_alloca(4);
type = TS_IPV4_ADDR_RANGE;
break;
case IANA_AFI_IPV6:
from = chunk_alloca(16);
to = chunk_alloca(16);
type = TS_IPV6_ADDR_RANGE;
break;
default:
return;
}
list = fam->ipAddressChoice->u.addressesOrRanges;
for (i = 0; i < sk_IPAddressOrRange_num(list); i++)
{
aor = sk_IPAddressOrRange_value(list, i);
if (v3_addr_get_range(aor, afi, from.ptr, to.ptr, from.len) > 0)
{
ts = traffic_selector_create_from_bytes(0, type, from, 0, to, 65535);
if (ts)
{
this->ipAddrBlocks->insert_last(this->ipAddrBlocks, ts);
}
}
}
}
/**
* Parse ipAddrBlock extension
*/
static bool parse_ipAddrBlock_ext(private_openssl_x509_t *this,
X509_EXTENSION *ext)
{
STACK_OF(IPAddressFamily) *blocks;
IPAddressFamily *fam;
blocks = (STACK_OF(IPAddressFamily)*)X509V3_EXT_d2i(ext);
if (!blocks)
{
return FALSE;
}
if (!v3_addr_is_canonical(blocks))
{
sk_IPAddressFamily_free(blocks);
return FALSE;
}
while (sk_IPAddressFamily_num(blocks) > 0)
{
fam = sk_IPAddressFamily_pop(blocks);
parse_ipAddrBlock_ext_fam(this, fam);
IPAddressFamily_free(fam);
}
sk_IPAddressFamily_free(blocks);
this->flags |= X509_IP_ADDR_BLOCKS;
return TRUE;
}
#endif /* !OPENSSL_NO_RFC3779 */
/**
* Parse authorityKeyIdentifier extension
*/
@@ -857,6 +966,11 @@ static bool parse_extensions(private_openssl_x509_t *this)
case NID_crl_distribution_points:
ok = parse_crlDistributionPoints_ext(this, ext);
break;
#ifndef OPENSSL_NO_RFC3779
case NID_sbgp_ipAddrBlock:
ok = parse_ipAddrBlock_ext(this, ext);
break;
#endif /* !OPENSSL_NO_RFC3779 */
default:
ok = X509_EXTENSION_get_critical(ext) == 0 ||
!lib->settings->get_bool(lib->settings,