diff options
Diffstat (limited to 'src/libstrongswan/plugins/openssl/openssl_x509.c')
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_x509.c | 194 |
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)) |