summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/openssl/openssl_x509.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/openssl/openssl_x509.c')
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_x509.c194
1 files changed, 159 insertions, 35 deletions
diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c
index 676b97f7a..24b12d50c 100644
--- a/src/libstrongswan/plugins/openssl/openssl_x509.c
+++ b/src/libstrongswan/plugins/openssl/openssl_x509.c
@@ -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;
@@ -150,6 +158,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
*/
refcount_t ref;
@@ -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,
);
@@ -656,6 +679,41 @@ static bool parse_keyUsage_ext(private_openssl_x509_t *this,
}
/**
+ * Parse ExtendedKeyUsage
+ */
+static bool parse_extKeyUsage_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ EXTENDED_KEY_USAGE *usage;
+ int i;
+
+ usage = X509V3_EXT_d2i(ext);
+ if (usage)
+ {
+ for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++)
+ {
+ switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i)))
+ {
+ case NID_server_auth:
+ this->flags |= X509_SERVER_AUTH;
+ break;
+ case NID_client_auth:
+ this->flags |= X509_CLIENT_AUTH;
+ break;
+ case NID_OCSP_sign:
+ this->flags |= X509_OCSP_SIGNER;
+ break;
+ default:
+ break;
+ }
+ }
+ sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
* Parse CRL distribution points
*/
static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
@@ -772,6 +830,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
*/
@@ -854,16 +998,29 @@ static bool parse_extensions(private_openssl_x509_t *this)
case NID_key_usage:
ok = parse_keyUsage_ext(this, ext);
break;
+ case NID_ext_key_usage:
+ ok = parse_extKeyUsage_ext(this, ext);
+ break;
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,
"libstrongswan.x509.enforce_critical", TRUE);
if (!ok)
{
- DBG1(DBG_LIB, "found unsupported critical X.509 extension");
+ char buf[80] = "";
+
+ OBJ_obj2txt(buf, sizeof(buf),
+ X509_EXTENSION_get_object(ext), 0);
+ DBG1(DBG_LIB, "found unsupported critical X.509 "
+ "extension: %s", buf);
}
break;
}
@@ -877,38 +1034,6 @@ static bool parse_extensions(private_openssl_x509_t *this)
}
/**
- * Parse ExtendedKeyUsage
- */
-static void parse_extKeyUsage(private_openssl_x509_t *this)
-{
- EXTENDED_KEY_USAGE *usage;
- int i;
-
- usage = X509_get_ext_d2i(this->x509, NID_ext_key_usage, NULL, NULL);
- if (usage)
- {
- for (i = 0; i < sk_ASN1_OBJECT_num(usage); i++)
- {
- switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(usage, i)))
- {
- case NID_server_auth:
- this->flags |= X509_SERVER_AUTH;
- break;
- case NID_client_auth:
- this->flags |= X509_CLIENT_AUTH;
- break;
- case NID_OCSP_sign:
- this->flags |= X509_OCSP_SIGNER;
- break;
- default:
- break;
- }
- }
- sk_ASN1_OBJECT_pop_free(usage, ASN1_OBJECT_free);
- }
-}
-
-/**
* Parse a DER encoded x509 certificate
*/
static bool parse_certificate(private_openssl_x509_t *this)
@@ -974,7 +1099,6 @@ static bool parse_certificate(private_openssl_x509_t *this)
{
return FALSE;
}
- parse_extKeyUsage(this);
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (!hasher || !hasher->allocate_hash(hasher, this->encoding, &this->hash))