]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
openssl: Add support for nameConstraints X.509 extension
authorTobias Brunner <tobias@strongswan.org>
Tue, 17 Oct 2023 08:21:28 +0000 (10:21 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 13 Nov 2023 11:23:02 +0000 (12:23 +0100)
Closes strongswan/strongswan#1990

src/libstrongswan/plugins/openssl/openssl_x509.c

index 832cec4b472ce4c851aca56c36b1089351481e42..f7bef0d0317fec199db037c0c276f2ab1650afe5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2017 Tobias Brunner
+ * Copyright (C) 2011-2023 Tobias Brunner
  * Copyright (C) 2010 Martin Willi
  *
  * Copyright (C) secunet Security Networks AG
@@ -181,6 +181,15 @@ struct private_openssl_x509_t {
         */
        linked_list_t *ipAddrBlocks;
 
+       /**
+        * List of permitted name constraints
+        */
+       linked_list_t *permitted_names;
+
+       /**
+        * List of excluded name constraints
+        */
+       linked_list_t *excluded_names;
 
        /**
         * References to this cert
@@ -312,6 +321,16 @@ METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
        return this->ipAddrBlocks->create_enumerator(this->ipAddrBlocks);
 }
 
+METHOD(x509_t, create_name_constraint_enumerator, enumerator_t*,
+       private_openssl_x509_t *this, bool perm)
+{
+       if (perm)
+       {
+               return this->permitted_names->create_enumerator(this->permitted_names);
+       }
+       return this->excluded_names->create_enumerator(this->excluded_names);
+}
+
 METHOD(certificate_t, get_type, certificate_type_t,
        private_openssl_x509_t *this)
 {
@@ -564,6 +583,10 @@ METHOD(certificate_t, destroy, void,
                this->ocsp_uris->destroy_function(this->ocsp_uris, free);
                this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks,
                                                                                offsetof(traffic_selector_t, destroy));
+               this->permitted_names->destroy_offset(this->permitted_names,
+                                                                               offsetof(identification_t, destroy));
+               this->excluded_names->destroy_offset(this->excluded_names,
+                                                                               offsetof(identification_t, destroy));
                free(this);
        }
 }
@@ -601,7 +624,7 @@ static private_openssl_x509_t *create_empty()
                                .create_crl_uri_enumerator = _create_crl_uri_enumerator,
                                .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
                                .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
-                               .create_name_constraint_enumerator = (void*)enumerator_create_empty,
+                               .create_name_constraint_enumerator = _create_name_constraint_enumerator,
                                .create_cert_policy_enumerator = (void*)enumerator_create_empty,
                                .create_policy_mapping_enumerator = (void*)enumerator_create_empty,
                        },
@@ -611,6 +634,8 @@ static private_openssl_x509_t *create_empty()
                .crl_uris = linked_list_create(),
                .ocsp_uris = linked_list_create(),
                .ipAddrBlocks = linked_list_create(),
+               .permitted_names = linked_list_create(),
+               .excluded_names = linked_list_create(),
                .pathlen = X509_NO_CONSTRAINT,
                .ref = 1,
        );
@@ -964,6 +989,51 @@ static bool parse_ipAddrBlock_ext(private_openssl_x509_t *this,
 }
 #endif /* !OPENSSL_NO_RFC3779 */
 
+/**
+ * Parse a "generalSubtree" structure (sequence of generalNames)
+ */
+static bool parse_generalSubtrees(linked_list_t *list,
+                                                                 STACK_OF(GENERAL_SUBTREE) *subtrees)
+{
+       GENERAL_SUBTREE *subtree;
+       identification_t *id;
+       int i;
+
+       for     (i = 0; i < sk_GENERAL_SUBTREE_num(subtrees); i++)
+       {
+               subtree = sk_GENERAL_SUBTREE_value(subtrees, i);
+               id = general_name2id(subtree->base);
+               if (id)
+               {
+                       list->insert_last(list, id);
+               }
+               else
+               {
+                       return FALSE;
+               }
+       }
+       return TRUE;
+}
+
+/**
+ * Parse permitted/excluded nameConstraints
+ */
+static bool parse_nameConstraints_ext(private_openssl_x509_t *this,
+                                                                         X509_EXTENSION *ext)
+{
+       NAME_CONSTRAINTS *nc;
+       bool ok = FALSE;
+
+       nc = (NAME_CONSTRAINTS*)X509V3_EXT_d2i(ext);
+       if (nc)
+       {
+               ok = parse_generalSubtrees(this->permitted_names, nc->permittedSubtrees) &&
+                        parse_generalSubtrees(this->excluded_names, nc->excludedSubtrees);
+               NAME_CONSTRAINTS_free(nc);
+       }
+       return ok;
+}
+
 /**
  * Parse authorityKeyIdentifier extension
  */
@@ -1059,6 +1129,9 @@ static bool parse_extensions(private_openssl_x509_t *this)
                                        ok = parse_ipAddrBlock_ext(this, ext);
                                        break;
 #endif /* !OPENSSL_NO_RFC3779 */
+                               case NID_name_constraints:
+                                       ok = parse_nameConstraints_ext(this, ext);
+                                       break;
                                default:
                                        ok = X509_EXTENSION_get_critical(ext) == 0 ||
                                                 !lib->settings->get_bool(lib->settings,