From: Alexander Sosedkin Date: Wed, 4 Feb 2026 12:30:08 +0000 (+0100) Subject: x509/name_constraints: implement name_constraints_node_list_union X-Git-Tag: 3.8.12^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=80db5e90fa18d3e34bb91dd027bdf76d31e93dcd;p=thirdparty%2Fgnutls.git x509/name_constraints: implement name_constraints_node_list_union Signed-off-by: Alexander Sosedkin --- diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c index 41f30d13b9..de20dd8ef4 100644 --- a/lib/x509/name_constraints.c +++ b/lib/x509/name_constraints.c @@ -41,6 +41,7 @@ #include "intprops.h" #include "minmax.h" +#include #include #define MAX_NC_CHECKS (1 << 20) @@ -870,22 +871,95 @@ cleanup: return ret; } -static int name_constraints_node_list_concat( - gnutls_x509_name_constraints_t nc, - struct name_constraints_node_list_st *nodes, - const struct name_constraints_node_list_st *nodes2) +static int +name_constraints_node_list_union(gnutls_x509_name_constraints_t nc, + struct name_constraints_node_list_st *nodes, + struct name_constraints_node_list_st *nodes2) { int ret; + size_t i = 0, j = 0; + struct name_constraints_node_st *nc1; + const struct name_constraints_node_st *nc2; + enum name_constraint_relation rel; + struct name_constraints_node_list_st result = { 0 }; + + if (nodes2->size == 0) /* nothing to do */ + return GNUTLS_E_SUCCESS; + + ret = ensure_sorted(nodes); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + ret = ensure_sorted(nodes2); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* traverse both lists in a single pass and merge them w/o duplicates */ + while (i < nodes->size || j < nodes2->size) { + nc1 = (i < nodes->size) ? nodes->sorted_view[i] : NULL; + nc2 = (j < nodes2->size) ? nodes2->sorted_view[j] : NULL; - for (size_t i = 0; i < nodes2->size; i++) { - ret = name_constraints_node_add_copy(nc, nodes, - nodes2->data[i]); + rel = compare_name_constraint_nodes(nc1, nc2); + switch (rel) { + case NC_SORTS_BEFORE: + assert(nc1 != NULL); /* comparator-guaranteed */ + ret = name_constraints_node_list_add(&result, nc1); + i++; + break; + case NC_SORTS_AFTER: + assert(nc2 != NULL); /* comparator-guaranteed */ + ret = name_constraints_node_add_copy(nc, &result, nc2); + j++; + break; + case NC_INCLUDES: /* nc1 is broader, shallow-copy it */ + assert(nc1 != NULL && nc2 != NULL); /* comparator */ + ret = name_constraints_node_list_add(&result, nc1); + i++; + j++; + break; + case NC_INCLUDED_BY: /* nc2 is broader, deep-copy it */ + assert(nc1 != NULL && nc2 != NULL); /* comparator */ + ret = name_constraints_node_add_copy(nc, &result, nc2); + i++; + j++; + break; + case NC_EQUAL: + assert(nc1 != NULL && nc2 != NULL); /* loop condition */ + ret = name_constraints_node_list_add(&result, nc1); + i++; + j++; + break; + } if (ret < 0) { - return gnutls_assert_val(ret); + gnutls_assert(); + goto cleanup; } } - return 0; + gnutls_free(nodes->data); + gnutls_free(nodes->sorted_view); + nodes->data = result.data; + nodes->sorted_view = NULL; + nodes->size = result.size; + nodes->capacity = result.capacity; + nodes->dirty = true; + /* since we know it's sorted, populate sorted_view almost for free */ + nodes->sorted_view = gnutls_calloc( + nodes->size, sizeof(struct name_constraints_node_st *)); + if (!nodes->sorted_view) + return GNUTLS_E_SUCCESS; /* we tried, no harm done */ + memcpy(nodes->sorted_view, nodes->data, + nodes->size * sizeof(struct name_constraints_node_st *)); + nodes->dirty = false; + + result.data = NULL; + return GNUTLS_E_SUCCESS; +cleanup: + name_constraints_node_list_clear(&result); + return gnutls_assert_val(ret); } /** @@ -1026,7 +1100,7 @@ static int name_constraints_add(gnutls_x509_name_constraints_t nc, * @nc2: The name constraints to be merged with * * This function will merge the provided name constraints structures - * as per RFC5280 p6.1.4. That is, the excluded constraints will be appended, + * as per RFC5280 p6.1.4. That is, the excluded constraints will be unioned, * and permitted will be intersected. The intersection assumes that @nc * is the root CA constraints. * @@ -1048,8 +1122,8 @@ int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc, return ret; } - ret = name_constraints_node_list_concat(nc, &nc->excluded, - &nc2->excluded); + ret = name_constraints_node_list_union(nc, &nc->excluded, + &nc2->excluded); if (ret < 0) { gnutls_assert(); return ret;