1149 lines
34 KiB
Diff
1149 lines
34 KiB
Diff
From 4760bc63531e3f5039e70ede91a20e1194410892 Mon Sep 17 00:00:00 2001
|
|
From: Daiki Ueno <ueno@gnu.org>
|
|
Date: Mon, 18 Nov 2024 17:23:46 +0900
|
|
Subject: [PATCH] x509: optimize name constraints processing
|
|
|
|
This switches the representation name constraints from linked lists to
|
|
array lists to optimize the lookup performance from O(n) to O(1), also
|
|
enforces a limit of name constraint checks against subject alternative
|
|
names.
|
|
|
|
Signed-off-by: Daiki Ueno <ueno@gnu.org>
|
|
---
|
|
lib/datum.c | 7 +-
|
|
lib/x509/name_constraints.c | 595 +++++++++++++++++++++---------------
|
|
lib/x509/x509_ext.c | 80 +++--
|
|
lib/x509/x509_ext_int.h | 5 +
|
|
lib/x509/x509_int.h | 21 +-
|
|
5 files changed, 399 insertions(+), 309 deletions(-)
|
|
|
|
diff --git a/lib/datum.c b/lib/datum.c
|
|
index 66e016965d..5577c2b4ab 100644
|
|
--- a/lib/datum.c
|
|
+++ b/lib/datum.c
|
|
@@ -29,6 +29,7 @@
|
|
#include "num.h"
|
|
#include "datum.h"
|
|
#include "errors.h"
|
|
+#include "intprops.h"
|
|
|
|
/* On error, @dat is not changed. */
|
|
int _gnutls_set_datum(gnutls_datum_t *dat, const void *data, size_t data_size)
|
|
@@ -60,7 +61,11 @@ int _gnutls_set_strdatum(gnutls_datum_t *dat, const void *data,
|
|
if (data == NULL)
|
|
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
|
|
|
|
- unsigned char *m = gnutls_malloc(data_size + 1);
|
|
+ size_t capacity;
|
|
+ if (!INT_ADD_OK(data_size, 1, &capacity))
|
|
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
+
|
|
+ unsigned char *m = gnutls_malloc(capacity);
|
|
if (!m)
|
|
return GNUTLS_E_MEMORY_ERROR;
|
|
|
|
diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
|
|
index 8327a9d94e..3c6e306303 100644
|
|
--- a/lib/x509/name_constraints.c
|
|
+++ b/lib/x509/name_constraints.c
|
|
@@ -33,51 +33,98 @@
|
|
#include <gnutls/x509-ext.h>
|
|
#include "x509_b64.h"
|
|
#include "x509_int.h"
|
|
+#include "x509_ext_int.h"
|
|
#include <libtasn1.h>
|
|
|
|
#include "ip.h"
|
|
#include "ip-in-cidr.h"
|
|
+#include "intprops.h"
|
|
+
|
|
+#define MAX_NC_CHECKS (1 << 20)
|
|
+
|
|
+struct name_constraints_node_st {
|
|
+ unsigned type;
|
|
+ gnutls_datum_t name;
|
|
+};
|
|
+
|
|
+struct name_constraints_node_list_st {
|
|
+ struct name_constraints_node_st **data;
|
|
+ size_t size;
|
|
+ size_t capacity;
|
|
+};
|
|
+
|
|
+struct gnutls_name_constraints_st {
|
|
+ struct name_constraints_node_list_st nodes; /* owns elements */
|
|
+ struct name_constraints_node_list_st permitted; /* borrows elements */
|
|
+ struct name_constraints_node_list_st excluded; /* borrows elements */
|
|
+};
|
|
+
|
|
+static struct name_constraints_node_st *
|
|
+name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type,
|
|
+ unsigned char *data, unsigned int size);
|
|
|
|
-// for documentation see the implementation
|
|
static int
|
|
-name_constraints_intersect_nodes(name_constraints_node_st *nc1,
|
|
- name_constraints_node_st *nc2,
|
|
- name_constraints_node_st **intersection);
|
|
+name_constraints_node_list_add(struct name_constraints_node_list_st *list,
|
|
+ struct name_constraints_node_st *node)
|
|
+{
|
|
+ if (!list->capacity || list->size == list->capacity) {
|
|
+ size_t new_capacity = list->capacity;
|
|
+ struct name_constraints_node_st **new_data;
|
|
+
|
|
+ if (!INT_MULTIPLY_OK(new_capacity, 2, &new_capacity) ||
|
|
+ !INT_ADD_OK(new_capacity, 1, &new_capacity))
|
|
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
+ new_data = _gnutls_reallocarray(
|
|
+ list->data, new_capacity,
|
|
+ sizeof(struct name_constraints_node_st *));
|
|
+ if (!new_data)
|
|
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
+ list->capacity = new_capacity;
|
|
+ list->data = new_data;
|
|
+ }
|
|
+ list->data[list->size++] = node;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+// for documentation see the implementation
|
|
+static int name_constraints_intersect_nodes(
|
|
+ gnutls_x509_name_constraints_t nc,
|
|
+ const struct name_constraints_node_st *node1,
|
|
+ const struct name_constraints_node_st *node2,
|
|
+ struct name_constraints_node_st **intersection);
|
|
|
|
/*-
|
|
- * is_nc_empty:
|
|
+ * _gnutls_x509_name_constraints_is_empty:
|
|
* @nc: name constraints structure
|
|
- * @type: type (gnutls_x509_subject_alt_name_t)
|
|
+ * @type: type (gnutls_x509_subject_alt_name_t or 0)
|
|
*
|
|
* Test whether given name constraints structure has any constraints (permitted
|
|
* or excluded) of a given type. @nc must be allocated (not NULL) before the call.
|
|
+ * If @type is 0, type checking will be skipped.
|
|
*
|
|
- * Returns: 0 if @nc contains constraints of type @type, 1 otherwise
|
|
+ * Returns: false if @nc contains constraints of type @type, true otherwise
|
|
-*/
|
|
-static unsigned is_nc_empty(struct gnutls_name_constraints_st *nc,
|
|
- unsigned type)
|
|
+bool _gnutls_x509_name_constraints_is_empty(gnutls_x509_name_constraints_t nc,
|
|
+ unsigned type)
|
|
{
|
|
- name_constraints_node_st *t;
|
|
+ if (nc->permitted.size == 0 && nc->excluded.size == 0)
|
|
+ return true;
|
|
|
|
- if (nc->permitted == NULL && nc->excluded == NULL)
|
|
- return 1;
|
|
+ if (type == 0)
|
|
+ return false;
|
|
|
|
- t = nc->permitted;
|
|
- while (t != NULL) {
|
|
- if (t->type == type)
|
|
- return 0;
|
|
- t = t->next;
|
|
+ for (size_t i = 0; i < nc->permitted.size; i++) {
|
|
+ if (nc->permitted.data[i]->type == type)
|
|
+ return false;
|
|
}
|
|
|
|
- t = nc->excluded;
|
|
- while (t != NULL) {
|
|
- if (t->type == type)
|
|
- return 0;
|
|
- t = t->next;
|
|
+ for (size_t i = 0; i < nc->excluded.size; i++) {
|
|
+ if (nc->excluded.data[i]->type == type)
|
|
+ return false;
|
|
}
|
|
|
|
/* no constraint for that type exists */
|
|
- return 1;
|
|
+ return true;
|
|
}
|
|
|
|
/*-
|
|
@@ -115,21 +162,16 @@ static int validate_name_constraints_node(gnutls_x509_subject_alt_name_t type,
|
|
return GNUTLS_E_SUCCESS;
|
|
}
|
|
|
|
-int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr,
|
|
- name_constraints_node_st **_nc)
|
|
+static int extract_name_constraints(gnutls_x509_name_constraints_t nc,
|
|
+ asn1_node c2, const char *vstr,
|
|
+ struct name_constraints_node_list_st *nodes)
|
|
{
|
|
int ret;
|
|
char tmpstr[128];
|
|
unsigned indx;
|
|
gnutls_datum_t tmp = { NULL, 0 };
|
|
unsigned int type;
|
|
- struct name_constraints_node_st *nc, *prev;
|
|
-
|
|
- prev = *_nc;
|
|
- if (prev != NULL) {
|
|
- while (prev->next != NULL)
|
|
- prev = prev->next;
|
|
- }
|
|
+ struct name_constraints_node_st *node;
|
|
|
|
for (indx = 1;; indx++) {
|
|
snprintf(tmpstr, sizeof(tmpstr), "%s.?%u.base", vstr, indx);
|
|
@@ -172,25 +214,19 @@ int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr,
|
|
goto cleanup;
|
|
}
|
|
|
|
- nc = gnutls_malloc(sizeof(struct name_constraints_node_st));
|
|
- if (nc == NULL) {
|
|
+ node = name_constraints_node_new(nc, type, tmp.data, tmp.size);
|
|
+ _gnutls_free_datum(&tmp);
|
|
+ if (node == NULL) {
|
|
gnutls_assert();
|
|
ret = GNUTLS_E_MEMORY_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
- memcpy(&nc->name, &tmp, sizeof(gnutls_datum_t));
|
|
- nc->type = type;
|
|
- nc->next = NULL;
|
|
-
|
|
- if (prev == NULL) {
|
|
- *_nc = prev = nc;
|
|
- } else {
|
|
- prev->next = nc;
|
|
- prev = nc;
|
|
+ ret = name_constraints_node_list_add(nodes, node);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
}
|
|
-
|
|
- tmp.data = NULL;
|
|
}
|
|
|
|
assert(ret < 0);
|
|
@@ -205,84 +241,104 @@ cleanup:
|
|
return ret;
|
|
}
|
|
|
|
+int _gnutls_x509_name_constraints_extract(asn1_node c2,
|
|
+ const char *permitted_name,
|
|
+ const char *excluded_name,
|
|
+ gnutls_x509_name_constraints_t nc)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = extract_name_constraints(nc, c2, permitted_name, &nc->permitted);
|
|
+ if (ret < 0)
|
|
+ return gnutls_assert_val(ret);
|
|
+ ret = extract_name_constraints(nc, c2, excluded_name, &nc->excluded);
|
|
+ if (ret < 0)
|
|
+ return gnutls_assert_val(ret);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/*-
|
|
- * _gnutls_name_constraints_node_free:
|
|
+ * name_constraints_node_free:
|
|
* @node: name constraints node
|
|
*
|
|
- * Deallocate a list of name constraints nodes starting at the given node.
|
|
+ * Deallocate a name constraints node.
|
|
-*/
|
|
-void _gnutls_name_constraints_node_free(name_constraints_node_st *node)
|
|
+static void name_constraints_node_free(struct name_constraints_node_st *node)
|
|
{
|
|
- name_constraints_node_st *next, *t;
|
|
-
|
|
- t = node;
|
|
- while (t != NULL) {
|
|
- next = t->next;
|
|
- gnutls_free(t->name.data);
|
|
- gnutls_free(t);
|
|
- t = next;
|
|
+ if (node) {
|
|
+ gnutls_free(node->name.data);
|
|
+ gnutls_free(node);
|
|
}
|
|
}
|
|
|
|
/*-
|
|
* name_constraints_node_new:
|
|
* @type: name constraints type to set (gnutls_x509_subject_alt_name_t)
|
|
+ * @nc: a %gnutls_x509_name_constraints_t
|
|
* @data: name.data to set or NULL
|
|
* @size: name.size to set
|
|
*
|
|
* Allocate a new name constraints node and set its type, name size and name data.
|
|
- * If @data is set to NULL, name data will be an array of \x00 (the length of @size).
|
|
- * The .next pointer is set to NULL.
|
|
*
|
|
* Returns: Pointer to newly allocated node or NULL in case of memory error.
|
|
-*/
|
|
-static name_constraints_node_st *
|
|
-name_constraints_node_new(unsigned type, unsigned char *data, unsigned int size)
|
|
+static struct name_constraints_node_st *
|
|
+name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type,
|
|
+ unsigned char *data, unsigned int size)
|
|
{
|
|
- name_constraints_node_st *tmp =
|
|
- gnutls_malloc(sizeof(struct name_constraints_node_st));
|
|
+ struct name_constraints_node_st *tmp;
|
|
+ int ret;
|
|
+
|
|
+ tmp = gnutls_calloc(1, sizeof(struct name_constraints_node_st));
|
|
if (tmp == NULL)
|
|
return NULL;
|
|
tmp->type = type;
|
|
- tmp->next = NULL;
|
|
- tmp->name.size = size;
|
|
- tmp->name.data = NULL;
|
|
- if (tmp->name.size > 0) {
|
|
- tmp->name.data = gnutls_malloc(tmp->name.size);
|
|
- if (tmp->name.data == NULL) {
|
|
+
|
|
+ if (data) {
|
|
+ ret = _gnutls_set_strdatum(&tmp->name, data, size);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
gnutls_free(tmp);
|
|
return NULL;
|
|
}
|
|
- if (data != NULL) {
|
|
- memcpy(tmp->name.data, data, size);
|
|
- } else {
|
|
- memset(tmp->name.data, 0, size);
|
|
- }
|
|
}
|
|
+
|
|
+ ret = name_constraints_node_list_add(&nc->nodes, tmp);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ name_constraints_node_free(tmp);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
return tmp;
|
|
}
|
|
|
|
/*-
|
|
- * @brief _gnutls_name_constraints_intersect:
|
|
- * @_nc: first name constraints list (permitted)
|
|
- * @_nc2: name constraints list to merge with (permitted)
|
|
- * @_nc_excluded: Corresponding excluded name constraints list
|
|
+ * @brief name_constraints_node_list_intersect:
|
|
+ * @nc: %gnutls_x509_name_constraints_t
|
|
+ * @permitted: first name constraints list (permitted)
|
|
+ * @permitted2: name constraints list to merge with (permitted)
|
|
+ * @excluded: Corresponding excluded name constraints list
|
|
*
|
|
- * This function finds the intersection of @_nc and @_nc2. The result is placed in @_nc,
|
|
- * the original @_nc is deallocated. @_nc2 is not changed. If necessary, a universal
|
|
+ * This function finds the intersection of @permitted and @permitted2. The result is placed in @permitted,
|
|
+ * the original @permitted is modified. @permitted2 is not changed. If necessary, a universal
|
|
* excluded name constraint node of the right type is added to the list provided
|
|
- * in @_nc_excluded.
|
|
+ * in @excluded.
|
|
*
|
|
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
|
|
-*/
|
|
-static int
|
|
-_gnutls_name_constraints_intersect(name_constraints_node_st **_nc,
|
|
- name_constraints_node_st *_nc2,
|
|
- name_constraints_node_st **_nc_excluded)
|
|
+static int name_constraints_node_list_intersect(
|
|
+ gnutls_x509_name_constraints_t nc,
|
|
+ struct name_constraints_node_list_st *permitted,
|
|
+ const struct name_constraints_node_list_st *permitted2,
|
|
+ struct name_constraints_node_list_st *excluded)
|
|
{
|
|
- name_constraints_node_st *nc, *nc2, *t, *tmp, *dest = NULL,
|
|
- *prev = NULL;
|
|
+ struct name_constraints_node_st *tmp;
|
|
int ret, type, used;
|
|
+ struct name_constraints_node_list_st removed = { .data = NULL,
|
|
+ .size = 0,
|
|
+ .capacity = 0 };
|
|
|
|
/* temporary array to see, if we need to add universal excluded constraints
|
|
* (see phase 3 for details)
|
|
@@ -291,61 +347,73 @@ _gnutls_name_constraints_intersect(name_constraints_node_st **_nc,
|
|
memset(types_with_empty_intersection, 0,
|
|
sizeof(types_with_empty_intersection));
|
|
|
|
- if (*_nc == NULL || _nc2 == NULL)
|
|
+ if (permitted->size == 0 || permitted2->size == 0)
|
|
return 0;
|
|
|
|
/* Phase 1
|
|
- * For each name in _NC, if a _NC2 does not contain a name
|
|
- * with the same type, preserve the original name.
|
|
- * Do this also for node of unknown type (not DNS, email, IP */
|
|
- t = nc = *_nc;
|
|
- while (t != NULL) {
|
|
- name_constraints_node_st *next = t->next;
|
|
- nc2 = _nc2;
|
|
- while (nc2 != NULL) {
|
|
- if (t->type == nc2->type) {
|
|
+ * For each name in PERMITTED, if a PERMITTED2 does not contain a name
|
|
+ * with the same type, move the original name to REMOVED.
|
|
+ * Do this also for node of unknown type (not DNS, email, IP) */
|
|
+ for (size_t i = 0; i < permitted->size;) {
|
|
+ struct name_constraints_node_st *t = permitted->data[i];
|
|
+ const struct name_constraints_node_st *found = NULL;
|
|
+
|
|
+ for (size_t j = 0; j < permitted2->size; j++) {
|
|
+ const struct name_constraints_node_st *t2 =
|
|
+ permitted2->data[j];
|
|
+ if (t->type == t2->type) {
|
|
// check bounds (we will use 't->type' as index)
|
|
- if (t->type > GNUTLS_SAN_MAX || t->type == 0)
|
|
- return gnutls_assert_val(
|
|
- GNUTLS_E_INTERNAL_ERROR);
|
|
+ if (t->type > GNUTLS_SAN_MAX || t->type == 0) {
|
|
+ gnutls_assert();
|
|
+ ret = GNUTLS_E_INTERNAL_ERROR;
|
|
+ goto cleanup;
|
|
+ }
|
|
// note the possibility of empty intersection for this type
|
|
// if we add something to the intersection in phase 2,
|
|
// we will reset this flag back to 0 then
|
|
types_with_empty_intersection[t->type - 1] = 1;
|
|
+ found = t2;
|
|
break;
|
|
}
|
|
- nc2 = nc2->next;
|
|
}
|
|
- if (nc2 == NULL || (t->type != GNUTLS_SAN_DNSNAME &&
|
|
- t->type != GNUTLS_SAN_RFC822NAME &&
|
|
- t->type != GNUTLS_SAN_IPADDRESS)) {
|
|
- /* move node from NC to DEST */
|
|
- if (prev != NULL)
|
|
- prev->next = next;
|
|
- else
|
|
- prev = nc = next;
|
|
- t->next = dest;
|
|
- dest = t;
|
|
- } else {
|
|
- prev = t;
|
|
+
|
|
+ if (found != NULL && (t->type == GNUTLS_SAN_DNSNAME ||
|
|
+ t->type == GNUTLS_SAN_RFC822NAME ||
|
|
+ t->type == GNUTLS_SAN_IPADDRESS)) {
|
|
+ /* move node from PERMITTED to REMOVED */
|
|
+ ret = name_constraints_node_list_add(&removed, t);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
+ }
|
|
+ /* remove node by swapping */
|
|
+ if (i < permitted->size - 1)
|
|
+ permitted->data[i] =
|
|
+ permitted->data[permitted->size - 1];
|
|
+ permitted->size--;
|
|
+ continue;
|
|
}
|
|
- t = next;
|
|
+ i++;
|
|
}
|
|
|
|
/* Phase 2
|
|
- * iterate through all combinations from nc2 and nc1
|
|
+ * iterate through all combinations from PERMITTED2 and PERMITTED
|
|
* and create intersections of nodes with same type */
|
|
- nc2 = _nc2;
|
|
- while (nc2 != NULL) {
|
|
- // current nc2 node has not yet been used for any intersection
|
|
- // (and is not in DEST either)
|
|
+ for (size_t i = 0; i < permitted2->size; i++) {
|
|
+ const struct name_constraints_node_st *t2 = permitted2->data[i];
|
|
+
|
|
+ // current PERMITTED2 node has not yet been used for any intersection
|
|
+ // (and is not in REMOVED either)
|
|
used = 0;
|
|
- t = nc;
|
|
- while (t != NULL) {
|
|
+ for (size_t j = 0; j < removed.size; j++) {
|
|
+ const struct name_constraints_node_st *t =
|
|
+ removed.data[j];
|
|
// save intersection of name constraints into tmp
|
|
- ret = name_constraints_intersect_nodes(t, nc2, &tmp);
|
|
- if (ret < 0)
|
|
- return gnutls_assert_val(ret);
|
|
+ ret = name_constraints_intersect_nodes(nc, t, t2, &tmp);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
+ }
|
|
used = 1;
|
|
// if intersection is not empty
|
|
if (tmp !=
|
|
@@ -360,32 +428,34 @@ _gnutls_name_constraints_intersect(name_constraints_node_st **_nc,
|
|
// we will not add universal excluded constraint for this type
|
|
types_with_empty_intersection[tmp->type - 1] =
|
|
0;
|
|
- // add intersection node to DEST
|
|
- tmp->next = dest;
|
|
- dest = tmp;
|
|
+ // add intersection node to PERMITTED
|
|
+ ret = name_constraints_node_list_add(permitted,
|
|
+ tmp);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
+ }
|
|
}
|
|
- t = t->next;
|
|
}
|
|
- // if the node from nc2 was not used for intersection, copy it to DEST
|
|
+ // if the node from PERMITTED2 was not used for intersection, copy it to DEST
|
|
// Beware: also copies nodes other than DNS, email, IP,
|
|
// since their counterpart may have been moved in phase 1.
|
|
if (!used) {
|
|
tmp = name_constraints_node_new(
|
|
- nc2->type, nc2->name.data, nc2->name.size);
|
|
+ nc, t2->type, t2->name.data, t2->name.size);
|
|
if (tmp == NULL) {
|
|
- _gnutls_name_constraints_node_free(dest);
|
|
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
+ gnutls_assert();
|
|
+ ret = GNUTLS_E_MEMORY_ERROR;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = name_constraints_node_list_add(permitted, tmp);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
}
|
|
- tmp->next = dest;
|
|
- dest = tmp;
|
|
}
|
|
- nc2 = nc2->next;
|
|
}
|
|
|
|
- /* replace the original with the new */
|
|
- _gnutls_name_constraints_node_free(nc);
|
|
- *_nc = dest;
|
|
-
|
|
/* Phase 3
|
|
* For each type: If we have empty permitted name constraints now
|
|
* and we didn't have at the beginning, we have to add a new
|
|
@@ -400,63 +470,77 @@ _gnutls_name_constraints_intersect(name_constraints_node_st **_nc,
|
|
switch (type) {
|
|
case GNUTLS_SAN_IPADDRESS:
|
|
// add universal restricted range for IPv4
|
|
- tmp = name_constraints_node_new(GNUTLS_SAN_IPADDRESS,
|
|
- NULL, 8);
|
|
+ tmp = name_constraints_node_new(
|
|
+ nc, GNUTLS_SAN_IPADDRESS, NULL, 8);
|
|
if (tmp == NULL) {
|
|
- _gnutls_name_constraints_node_free(dest);
|
|
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
+ gnutls_assert();
|
|
+ ret = GNUTLS_E_MEMORY_ERROR;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = name_constraints_node_list_add(excluded, tmp);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
}
|
|
- tmp->next = *_nc_excluded;
|
|
- *_nc_excluded = tmp;
|
|
// add universal restricted range for IPv6
|
|
- tmp = name_constraints_node_new(GNUTLS_SAN_IPADDRESS,
|
|
- NULL, 32);
|
|
+ tmp = name_constraints_node_new(
|
|
+ nc, GNUTLS_SAN_IPADDRESS, NULL, 32);
|
|
if (tmp == NULL) {
|
|
- _gnutls_name_constraints_node_free(dest);
|
|
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
+ gnutls_assert();
|
|
+ ret = GNUTLS_E_MEMORY_ERROR;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = name_constraints_node_list_add(excluded, tmp);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
}
|
|
- tmp->next = *_nc_excluded;
|
|
- *_nc_excluded = tmp;
|
|
break;
|
|
case GNUTLS_SAN_DNSNAME:
|
|
case GNUTLS_SAN_RFC822NAME:
|
|
- tmp = name_constraints_node_new(type, NULL, 0);
|
|
+ tmp = name_constraints_node_new(nc, type, NULL, 0);
|
|
if (tmp == NULL) {
|
|
- _gnutls_name_constraints_node_free(dest);
|
|
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
+ gnutls_assert();
|
|
+ ret = GNUTLS_E_MEMORY_ERROR;
|
|
+ goto cleanup;
|
|
+ }
|
|
+ ret = name_constraints_node_list_add(excluded, tmp);
|
|
+ if (ret < 0) {
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
}
|
|
- tmp->next = *_nc_excluded;
|
|
- *_nc_excluded = tmp;
|
|
break;
|
|
default: // do nothing, at least one node was already moved in phase 1
|
|
break;
|
|
}
|
|
}
|
|
- return GNUTLS_E_SUCCESS;
|
|
+ ret = GNUTLS_E_SUCCESS;
|
|
+
|
|
+cleanup:
|
|
+ gnutls_free(removed.data);
|
|
+ return ret;
|
|
}
|
|
|
|
-static int _gnutls_name_constraints_append(name_constraints_node_st **_nc,
|
|
- name_constraints_node_st *_nc2)
|
|
+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)
|
|
{
|
|
- name_constraints_node_st *nc, *nc2;
|
|
- struct name_constraints_node_st *tmp;
|
|
-
|
|
- if (_nc2 == NULL)
|
|
- return 0;
|
|
-
|
|
- nc2 = _nc2;
|
|
- while (nc2) {
|
|
- nc = *_nc;
|
|
-
|
|
- tmp = name_constraints_node_new(nc2->type, nc2->name.data,
|
|
- nc2->name.size);
|
|
- if (tmp == NULL)
|
|
+ for (size_t i = 0; i < nodes2->size; i++) {
|
|
+ const struct name_constraints_node_st *node = nodes2->data[i];
|
|
+ struct name_constraints_node_st *tmp;
|
|
+ int ret;
|
|
+
|
|
+ tmp = name_constraints_node_new(nc, node->type, node->name.data,
|
|
+ node->name.size);
|
|
+ if (tmp == NULL) {
|
|
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
-
|
|
- tmp->next = nc;
|
|
- *_nc = tmp;
|
|
-
|
|
- nc2 = nc2->next;
|
|
+ }
|
|
+ ret = name_constraints_node_list_add(nodes, tmp);
|
|
+ if (ret < 0) {
|
|
+ name_constraints_node_free(tmp);
|
|
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
+ }
|
|
}
|
|
|
|
return 0;
|
|
@@ -524,6 +608,25 @@ cleanup:
|
|
return ret;
|
|
}
|
|
|
|
+void _gnutls_x509_name_constraints_clear(gnutls_x509_name_constraints_t nc)
|
|
+{
|
|
+ for (size_t i = 0; i < nc->nodes.size; i++) {
|
|
+ struct name_constraints_node_st *node = nc->nodes.data[i];
|
|
+ name_constraints_node_free(node);
|
|
+ }
|
|
+ gnutls_free(nc->nodes.data);
|
|
+ nc->nodes.capacity = 0;
|
|
+ nc->nodes.size = 0;
|
|
+
|
|
+ gnutls_free(nc->permitted.data);
|
|
+ nc->permitted.capacity = 0;
|
|
+ nc->permitted.size = 0;
|
|
+
|
|
+ gnutls_free(nc->excluded.data);
|
|
+ nc->excluded.capacity = 0;
|
|
+ nc->excluded.size = 0;
|
|
+}
|
|
+
|
|
/**
|
|
* gnutls_x509_name_constraints_deinit:
|
|
* @nc: The nameconstraints
|
|
@@ -534,9 +637,7 @@ cleanup:
|
|
**/
|
|
void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc)
|
|
{
|
|
- _gnutls_name_constraints_node_free(nc->permitted);
|
|
- _gnutls_name_constraints_node_free(nc->excluded);
|
|
-
|
|
+ _gnutls_x509_name_constraints_clear(nc);
|
|
gnutls_free(nc);
|
|
}
|
|
|
|
@@ -552,12 +653,15 @@ void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc)
|
|
**/
|
|
int gnutls_x509_name_constraints_init(gnutls_x509_name_constraints_t *nc)
|
|
{
|
|
- *nc = gnutls_calloc(1, sizeof(struct gnutls_name_constraints_st));
|
|
- if (*nc == NULL) {
|
|
+ struct gnutls_name_constraints_st *tmp;
|
|
+
|
|
+ tmp = gnutls_calloc(1, sizeof(struct gnutls_name_constraints_st));
|
|
+ if (tmp == NULL) {
|
|
gnutls_assert();
|
|
return GNUTLS_E_MEMORY_ERROR;
|
|
}
|
|
|
|
+ *nc = tmp;
|
|
return 0;
|
|
}
|
|
|
|
@@ -565,36 +669,25 @@ static int name_constraints_add(gnutls_x509_name_constraints_t nc,
|
|
gnutls_x509_subject_alt_name_t type,
|
|
const gnutls_datum_t *name, unsigned permitted)
|
|
{
|
|
- struct name_constraints_node_st *tmp, *prev = NULL;
|
|
+ struct name_constraints_node_st *tmp;
|
|
+ struct name_constraints_node_list_st *nodes;
|
|
int ret;
|
|
|
|
ret = validate_name_constraints_node(type, name);
|
|
if (ret < 0)
|
|
return gnutls_assert_val(ret);
|
|
|
|
- if (permitted != 0)
|
|
- prev = tmp = nc->permitted;
|
|
- else
|
|
- prev = tmp = nc->excluded;
|
|
-
|
|
- while (tmp != NULL) {
|
|
- tmp = tmp->next;
|
|
- if (tmp != NULL)
|
|
- prev = tmp;
|
|
- }
|
|
+ nodes = permitted ? &nc->permitted : &nc->excluded;
|
|
|
|
- tmp = name_constraints_node_new(type, name->data, name->size);
|
|
+ tmp = name_constraints_node_new(nc, type, name->data, name->size);
|
|
if (tmp == NULL)
|
|
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
- tmp->next = NULL;
|
|
|
|
- if (prev == NULL) {
|
|
- if (permitted != 0)
|
|
- nc->permitted = tmp;
|
|
- else
|
|
- nc->excluded = tmp;
|
|
- } else
|
|
- prev->next = tmp;
|
|
+ ret = name_constraints_node_list_add(nodes, tmp);
|
|
+ if (ret < 0) {
|
|
+ name_constraints_node_free(tmp);
|
|
+ return gnutls_assert_val(ret);
|
|
+ }
|
|
|
|
return 0;
|
|
}
|
|
@@ -620,14 +713,15 @@ int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc,
|
|
{
|
|
int ret;
|
|
|
|
- ret = _gnutls_name_constraints_intersect(&nc->permitted, nc2->permitted,
|
|
- &nc->excluded);
|
|
+ ret = name_constraints_node_list_intersect(
|
|
+ nc, &nc->permitted, &nc2->permitted, &nc->excluded);
|
|
if (ret < 0) {
|
|
gnutls_assert();
|
|
return ret;
|
|
}
|
|
|
|
- ret = _gnutls_name_constraints_append(&nc->excluded, nc2->excluded);
|
|
+ ret = name_constraints_node_list_concat(nc, &nc->excluded,
|
|
+ &nc2->excluded);
|
|
if (ret < 0) {
|
|
gnutls_assert();
|
|
return ret;
|
|
@@ -804,50 +898,51 @@ static unsigned email_matches(const gnutls_datum_t *name,
|
|
*
|
|
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
|
|
-*/
|
|
-static int
|
|
-name_constraints_intersect_nodes(name_constraints_node_st *nc1,
|
|
- name_constraints_node_st *nc2,
|
|
- name_constraints_node_st **_intersection)
|
|
+static int name_constraints_intersect_nodes(
|
|
+ gnutls_x509_name_constraints_t nc,
|
|
+ const struct name_constraints_node_st *node1,
|
|
+ const struct name_constraints_node_st *node2,
|
|
+ struct name_constraints_node_st **_intersection)
|
|
{
|
|
// presume empty intersection
|
|
- name_constraints_node_st *intersection = NULL;
|
|
- name_constraints_node_st *to_copy = NULL;
|
|
+ struct name_constraints_node_st *intersection = NULL;
|
|
+ const struct name_constraints_node_st *to_copy = NULL;
|
|
unsigned iplength = 0;
|
|
unsigned byte;
|
|
|
|
*_intersection = NULL;
|
|
|
|
- if (nc1->type != nc2->type) {
|
|
+ if (node1->type != node2->type) {
|
|
return GNUTLS_E_SUCCESS;
|
|
}
|
|
- switch (nc1->type) {
|
|
+ switch (node1->type) {
|
|
case GNUTLS_SAN_DNSNAME:
|
|
- if (!dnsname_matches(&nc2->name, &nc1->name))
|
|
+ if (!dnsname_matches(&node2->name, &node1->name))
|
|
return GNUTLS_E_SUCCESS;
|
|
- to_copy = nc2;
|
|
+ to_copy = node2;
|
|
break;
|
|
case GNUTLS_SAN_RFC822NAME:
|
|
- if (!email_matches(&nc2->name, &nc1->name))
|
|
+ if (!email_matches(&node2->name, &node1->name))
|
|
return GNUTLS_E_SUCCESS;
|
|
- to_copy = nc2;
|
|
+ to_copy = node2;
|
|
break;
|
|
case GNUTLS_SAN_IPADDRESS:
|
|
- if (nc1->name.size != nc2->name.size)
|
|
+ if (node1->name.size != node2->name.size)
|
|
return GNUTLS_E_SUCCESS;
|
|
- iplength = nc1->name.size / 2;
|
|
+ iplength = node1->name.size / 2;
|
|
for (byte = 0; byte < iplength; byte++) {
|
|
- if (((nc1->name.data[byte] ^
|
|
- nc2->name.data[byte]) // XOR of addresses
|
|
- &
|
|
- nc1->name.data[byte + iplength] // AND mask from nc1
|
|
- &
|
|
- nc2->name.data[byte + iplength]) // AND mask from nc2
|
|
+ if (((node1->name.data[byte] ^
|
|
+ node2->name.data[byte]) // XOR of addresses
|
|
+ & node1->name.data[byte +
|
|
+ iplength] // AND mask from nc1
|
|
+ & node2->name.data[byte +
|
|
+ iplength]) // AND mask from nc2
|
|
!= 0) {
|
|
// CIDRS do not intersect
|
|
return GNUTLS_E_SUCCESS;
|
|
}
|
|
}
|
|
- to_copy = nc2;
|
|
+ to_copy = node2;
|
|
break;
|
|
default:
|
|
// for other types, we don't know how to do the intersection, assume empty
|
|
@@ -856,8 +951,9 @@ name_constraints_intersect_nodes(name_constraints_node_st *nc1,
|
|
|
|
// copy existing node if applicable
|
|
if (to_copy != NULL) {
|
|
- *_intersection = name_constraints_node_new(
|
|
- to_copy->type, to_copy->name.data, to_copy->name.size);
|
|
+ *_intersection = name_constraints_node_new(nc, to_copy->type,
|
|
+ to_copy->name.data,
|
|
+ to_copy->name.size);
|
|
if (*_intersection == NULL)
|
|
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
intersection = *_intersection;
|
|
@@ -869,12 +965,12 @@ name_constraints_intersect_nodes(name_constraints_node_st *nc1,
|
|
_gnutls_mask_ip(intersection->name.data,
|
|
intersection->name.data + iplength,
|
|
iplength);
|
|
- _gnutls_mask_ip(nc1->name.data,
|
|
- nc1->name.data + iplength, iplength);
|
|
+ _gnutls_mask_ip(node1->name.data,
|
|
+ node1->name.data + iplength, iplength);
|
|
// update intersection, if necessary (we already know one is subset of other)
|
|
for (byte = 0; byte < 2 * iplength; byte++) {
|
|
intersection->name.data[byte] |=
|
|
- nc1->name.data[byte];
|
|
+ node1->name.data[byte];
|
|
}
|
|
}
|
|
}
|
|
@@ -1177,10 +1273,17 @@ gnutls_x509_name_constraints_check_crt(gnutls_x509_name_constraints_t nc,
|
|
unsigned idx, t, san_type;
|
|
gnutls_datum_t n;
|
|
unsigned found_one;
|
|
+ size_t checks;
|
|
|
|
- if (is_nc_empty(nc, type) != 0)
|
|
+ if (_gnutls_x509_name_constraints_is_empty(nc, type) != 0)
|
|
return 1; /* shortcut; no constraints to check */
|
|
|
|
+ if (!INT_ADD_OK(nc->permitted.size, nc->excluded.size, &checks) ||
|
|
+ !INT_MULTIPLY_OK(checks, cert->san->size, &checks) ||
|
|
+ checks > MAX_NC_CHECKS) {
|
|
+ return gnutls_assert_val(0);
|
|
+ }
|
|
+
|
|
if (type == GNUTLS_SAN_RFC822NAME) {
|
|
found_one = 0;
|
|
for (idx = 0;; idx++) {
|
|
@@ -1378,20 +1481,13 @@ int gnutls_x509_name_constraints_get_permitted(gnutls_x509_name_constraints_t nc
|
|
unsigned idx, unsigned *type,
|
|
gnutls_datum_t *name)
|
|
{
|
|
- unsigned int i;
|
|
- struct name_constraints_node_st *tmp = nc->permitted;
|
|
+ const struct name_constraints_node_st *tmp;
|
|
|
|
- for (i = 0; i < idx; i++) {
|
|
- if (tmp == NULL)
|
|
- return gnutls_assert_val(
|
|
- GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
-
|
|
- tmp = tmp->next;
|
|
- }
|
|
-
|
|
- if (tmp == NULL)
|
|
+ if (idx >= nc->permitted.size)
|
|
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
|
|
+ tmp = nc->permitted.data[idx];
|
|
+
|
|
*type = tmp->type;
|
|
*name = tmp->name;
|
|
|
|
@@ -1421,20 +1517,13 @@ int gnutls_x509_name_constraints_get_excluded(gnutls_x509_name_constraints_t nc,
|
|
unsigned idx, unsigned *type,
|
|
gnutls_datum_t *name)
|
|
{
|
|
- unsigned int i;
|
|
- struct name_constraints_node_st *tmp = nc->excluded;
|
|
-
|
|
- for (i = 0; i < idx; i++) {
|
|
- if (tmp == NULL)
|
|
- return gnutls_assert_val(
|
|
- GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
+ const struct name_constraints_node_st *tmp;
|
|
|
|
- tmp = tmp->next;
|
|
- }
|
|
-
|
|
- if (tmp == NULL)
|
|
+ if (idx >= nc->excluded.size)
|
|
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
|
|
+ tmp = nc->excluded.data[idx];
|
|
+
|
|
*type = tmp->type;
|
|
*name = tmp->name;
|
|
|
|
diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c
|
|
index ae7216f23f..1714578de6 100644
|
|
--- a/lib/x509/x509_ext.c
|
|
+++ b/lib/x509/x509_ext.c
|
|
@@ -34,10 +34,6 @@
|
|
#include "intprops.h"
|
|
|
|
#define MAX_ENTRIES 64
|
|
-struct gnutls_subject_alt_names_st {
|
|
- struct name_st *names;
|
|
- unsigned int size;
|
|
-};
|
|
|
|
/**
|
|
* gnutls_subject_alt_names_init:
|
|
@@ -389,22 +385,15 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t *ext,
|
|
}
|
|
|
|
if (flags & GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND &&
|
|
- (nc->permitted != NULL || nc->excluded != NULL)) {
|
|
+ !_gnutls_x509_name_constraints_is_empty(nc, 0)) {
|
|
ret = gnutls_x509_name_constraints_init(&nc2);
|
|
if (ret < 0) {
|
|
gnutls_assert();
|
|
goto cleanup;
|
|
}
|
|
|
|
- ret = _gnutls_extract_name_constraints(c2, "permittedSubtrees",
|
|
- &nc2->permitted);
|
|
- if (ret < 0) {
|
|
- gnutls_assert();
|
|
- goto cleanup;
|
|
- }
|
|
-
|
|
- ret = _gnutls_extract_name_constraints(c2, "excludedSubtrees",
|
|
- &nc2->excluded);
|
|
+ ret = _gnutls_x509_name_constraints_extract(
|
|
+ c2, "permittedSubtrees", "excludedSubtrees", nc2);
|
|
if (ret < 0) {
|
|
gnutls_assert();
|
|
goto cleanup;
|
|
@@ -416,18 +405,10 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t *ext,
|
|
goto cleanup;
|
|
}
|
|
} else {
|
|
- _gnutls_name_constraints_node_free(nc->permitted);
|
|
- _gnutls_name_constraints_node_free(nc->excluded);
|
|
-
|
|
- ret = _gnutls_extract_name_constraints(c2, "permittedSubtrees",
|
|
- &nc->permitted);
|
|
- if (ret < 0) {
|
|
- gnutls_assert();
|
|
- goto cleanup;
|
|
- }
|
|
+ _gnutls_x509_name_constraints_clear(nc);
|
|
|
|
- ret = _gnutls_extract_name_constraints(c2, "excludedSubtrees",
|
|
- &nc->excluded);
|
|
+ ret = _gnutls_x509_name_constraints_extract(
|
|
+ c2, "permittedSubtrees", "excludedSubtrees", nc);
|
|
if (ret < 0) {
|
|
gnutls_assert();
|
|
goto cleanup;
|
|
@@ -463,9 +444,10 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc,
|
|
int ret, result;
|
|
uint8_t null = 0;
|
|
asn1_node c2 = NULL;
|
|
- struct name_constraints_node_st *tmp;
|
|
+ unsigned rtype;
|
|
+ gnutls_datum_t rname;
|
|
|
|
- if (nc->permitted == NULL && nc->excluded == NULL)
|
|
+ if (_gnutls_x509_name_constraints_is_empty(nc, 0))
|
|
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
|
|
result = asn1_create_element(_gnutls_get_pkix(),
|
|
@@ -475,11 +457,20 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc,
|
|
return _gnutls_asn2err(result);
|
|
}
|
|
|
|
- if (nc->permitted == NULL) {
|
|
+ ret = gnutls_x509_name_constraints_get_permitted(nc, 0, &rtype, &rname);
|
|
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
|
(void)asn1_write_value(c2, "permittedSubtrees", NULL, 0);
|
|
} else {
|
|
- tmp = nc->permitted;
|
|
- do {
|
|
+ for (unsigned i = 0;; i++) {
|
|
+ ret = gnutls_x509_name_constraints_get_permitted(
|
|
+ nc, i, &rtype, &rname);
|
|
+ if (ret < 0) {
|
|
+ if (ret ==
|
|
+ GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
|
|
+ break;
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
+ }
|
|
result = asn1_write_value(c2, "permittedSubtrees",
|
|
"NEW", 1);
|
|
if (result != ASN1_SUCCESS) {
|
|
@@ -506,21 +497,29 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc,
|
|
}
|
|
|
|
ret = _gnutls_write_general_name(
|
|
- c2, "permittedSubtrees.?LAST.base", tmp->type,
|
|
- tmp->name.data, tmp->name.size);
|
|
+ c2, "permittedSubtrees.?LAST.base", rtype,
|
|
+ rname.data, rname.size);
|
|
if (ret < 0) {
|
|
gnutls_assert();
|
|
goto cleanup;
|
|
}
|
|
- tmp = tmp->next;
|
|
- } while (tmp != NULL);
|
|
+ }
|
|
}
|
|
|
|
- if (nc->excluded == NULL) {
|
|
+ ret = gnutls_x509_name_constraints_get_excluded(nc, 0, &rtype, &rname);
|
|
+ if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
|
|
(void)asn1_write_value(c2, "excludedSubtrees", NULL, 0);
|
|
} else {
|
|
- tmp = nc->excluded;
|
|
- do {
|
|
+ for (unsigned i = 0;; i++) {
|
|
+ ret = gnutls_x509_name_constraints_get_excluded(
|
|
+ nc, i, &rtype, &rname);
|
|
+ if (ret < 0) {
|
|
+ if (ret ==
|
|
+ GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
|
|
+ break;
|
|
+ gnutls_assert();
|
|
+ goto cleanup;
|
|
+ }
|
|
result = asn1_write_value(c2, "excludedSubtrees", "NEW",
|
|
1);
|
|
if (result != ASN1_SUCCESS) {
|
|
@@ -546,14 +545,13 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc,
|
|
}
|
|
|
|
ret = _gnutls_write_general_name(
|
|
- c2, "excludedSubtrees.?LAST.base", tmp->type,
|
|
- tmp->name.data, tmp->name.size);
|
|
+ c2, "excludedSubtrees.?LAST.base", rtype,
|
|
+ rname.data, rname.size);
|
|
if (ret < 0) {
|
|
gnutls_assert();
|
|
goto cleanup;
|
|
}
|
|
- tmp = tmp->next;
|
|
- } while (tmp != NULL);
|
|
+ }
|
|
}
|
|
|
|
ret = _gnutls_x509_der_encode(c2, "", ext, 0);
|
|
diff --git a/lib/x509/x509_ext_int.h b/lib/x509/x509_ext_int.h
|
|
index 558d619565..b37d749976 100644
|
|
--- a/lib/x509/x509_ext_int.h
|
|
+++ b/lib/x509/x509_ext_int.h
|
|
@@ -29,6 +29,11 @@ struct name_st {
|
|
gnutls_datum_t othername_oid;
|
|
};
|
|
|
|
+struct gnutls_subject_alt_names_st {
|
|
+ struct name_st *names;
|
|
+ unsigned int size;
|
|
+};
|
|
+
|
|
int _gnutls_alt_name_process(gnutls_datum_t *out, unsigned type,
|
|
const gnutls_datum_t *san, unsigned raw);
|
|
|
|
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
|
|
index 693a4dd924..30f8051a70 100644
|
|
--- a/lib/x509/x509_int.h
|
|
+++ b/lib/x509/x509_int.h
|
|
@@ -503,20 +503,13 @@ int _gnutls_x509_crt_check_revocation(gnutls_x509_crt_t cert,
|
|
int crl_list_length,
|
|
gnutls_verify_output_function func);
|
|
|
|
-typedef struct gnutls_name_constraints_st {
|
|
- struct name_constraints_node_st *permitted;
|
|
- struct name_constraints_node_st *excluded;
|
|
-} gnutls_name_constraints_st;
|
|
-
|
|
-typedef struct name_constraints_node_st {
|
|
- unsigned type;
|
|
- gnutls_datum_t name;
|
|
- struct name_constraints_node_st *next;
|
|
-} name_constraints_node_st;
|
|
-
|
|
-int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr,
|
|
- name_constraints_node_st **_nc);
|
|
-void _gnutls_name_constraints_node_free(name_constraints_node_st *node);
|
|
+bool _gnutls_x509_name_constraints_is_empty(gnutls_x509_name_constraints_t nc,
|
|
+ unsigned type);
|
|
+int _gnutls_x509_name_constraints_extract(asn1_node c2,
|
|
+ const char *permitted_name,
|
|
+ const char *excluded_name,
|
|
+ gnutls_x509_name_constraints_t nc);
|
|
+void _gnutls_x509_name_constraints_clear(gnutls_x509_name_constraints_t nc);
|
|
int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc,
|
|
gnutls_x509_name_constraints_t nc2);
|
|
|
|
--
|
|
GitLab
|
|
|