From 6db7da7fcfe230f445b1edbb56e2a8346120c891 Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Thu, 5 Feb 2026 13:22:10 +0100
Subject: [PATCH] x509/name_constraints: name_constraints_node_add_{new,copy}

Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>

Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/6db7da7fcfe230f445b1edbb56e2a8346120c891]
CVE: CVE-2025-14831
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
---
 lib/x509/name_constraints.c | 112 ++++++++++++++++--------------------
 1 file changed, 51 insertions(+), 61 deletions(-)

diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
index 9783d92851..81035eef8f 100644
--- a/lib/x509/name_constraints.c
+++ b/lib/x509/name_constraints.c
@@ -86,6 +86,38 @@ name_constraints_node_list_add(struct name_constraints_node_list_st *list,
 	return 0;
 }
 
+static int
+name_constraints_node_add_new(gnutls_x509_name_constraints_t nc,
+			      struct name_constraints_node_list_st *list,
+			      unsigned type, const unsigned char *data,
+			      unsigned int size)
+{
+	struct name_constraints_node_st *node;
+	int ret;
+	node = name_constraints_node_new(nc, type, data, size);
+	if (node == NULL) {
+		gnutls_assert();
+		return GNUTLS_E_MEMORY_ERROR;
+	}
+	ret = name_constraints_node_list_add(list, node);
+	if (ret < 0) {
+		gnutls_assert();
+		return ret;
+	}
+	return GNUTLS_E_SUCCESS;
+}
+
+static int
+name_constraints_node_add_copy(gnutls_x509_name_constraints_t nc,
+			       struct name_constraints_node_list_st *dest,
+			       const struct name_constraints_node_st *src)
+{
+	if (!src)
+		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+	return name_constraints_node_add_new(nc, dest, src->type,
+					     src->name.data, src->name.size);
+}
+
 // for documentation see the implementation
 static int name_constraints_intersect_nodes(
 	gnutls_x509_name_constraints_t nc,
@@ -188,7 +220,6 @@ static int extract_name_constraints(gnutls_x509_name_constraints_t nc,
 	unsigned indx;
 	gnutls_datum_t tmp = { NULL, 0 };
 	unsigned int type;
-	struct name_constraints_node_st *node;
 
 	for (indx = 1;; indx++) {
 		snprintf(tmpstr, sizeof(tmpstr), "%s.?%u.base", vstr, indx);
@@ -231,15 +262,9 @@ static int extract_name_constraints(gnutls_x509_name_constraints_t nc,
 			goto cleanup;
 		}
 
-		node = name_constraints_node_new(nc, type, tmp.data, tmp.size);
+		ret = name_constraints_node_add_new(nc, nodes, type, tmp.data,
+						    tmp.size);
 		_gnutls_free_datum(&tmp);
-		if (node == NULL) {
-			gnutls_assert();
-			ret = GNUTLS_E_MEMORY_ERROR;
-			goto cleanup;
-		}
-
-		ret = name_constraints_node_list_add(nodes, node);
 		if (ret < 0) {
 			gnutls_assert();
 			goto cleanup;
@@ -462,14 +487,7 @@ static int name_constraints_node_list_intersect(
 		// 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(
-				nc, t2->type, t2->name.data, t2->name.size);
-			if (tmp == NULL) {
-				gnutls_assert();
-				ret = GNUTLS_E_MEMORY_ERROR;
-				goto cleanup;
-			}
-			ret = name_constraints_node_list_add(permitted, tmp);
+			ret = name_constraints_node_add_copy(nc, permitted, t2);
 			if (ret < 0) {
 				gnutls_assert();
 				goto cleanup;
@@ -491,27 +509,17 @@ static int name_constraints_node_list_intersect(
 		switch (type) {
 		case GNUTLS_SAN_IPADDRESS:
 			// add universal restricted range for IPv4
-			tmp = name_constraints_node_new(
-				nc, GNUTLS_SAN_IPADDRESS, universal_ip, 8);
-			if (tmp == NULL) {
-				gnutls_assert();
-				ret = GNUTLS_E_MEMORY_ERROR;
-				goto cleanup;
-			}
-			ret = name_constraints_node_list_add(excluded, tmp);
+			ret = name_constraints_node_add_new(
+				nc, excluded, GNUTLS_SAN_IPADDRESS,
+				universal_ip, 8);
 			if (ret < 0) {
 				gnutls_assert();
 				goto cleanup;
 			}
 			// add universal restricted range for IPv6
-			tmp = name_constraints_node_new(
-				nc, GNUTLS_SAN_IPADDRESS, universal_ip, 32);
-			if (tmp == NULL) {
-				gnutls_assert();
-				ret = GNUTLS_E_MEMORY_ERROR;
-				goto cleanup;
-			}
-			ret = name_constraints_node_list_add(excluded, tmp);
+			ret = name_constraints_node_add_new(
+				nc, excluded, GNUTLS_SAN_IPADDRESS,
+				universal_ip, 32);
 			if (ret < 0) {
 				gnutls_assert();
 				goto cleanup;
@@ -519,13 +527,8 @@ static int name_constraints_node_list_intersect(
 			break;
 		case GNUTLS_SAN_DNSNAME:
 		case GNUTLS_SAN_RFC822NAME:
-			tmp = name_constraints_node_new(nc, type, NULL, 0);
-			if (tmp == NULL) {
-				gnutls_assert();
-				ret = GNUTLS_E_MEMORY_ERROR;
-				goto cleanup;
-			}
-			ret = name_constraints_node_list_add(excluded, tmp);
+			ret = name_constraints_node_add_new(nc, excluded, type,
+							    NULL, 0);
 			if (ret < 0) {
 				gnutls_assert();
 				goto cleanup;
@@ -547,20 +550,13 @@ static int name_constraints_node_list_concat(
 	struct name_constraints_node_list_st *nodes,
 	const struct name_constraints_node_list_st *nodes2)
 {
-	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;
+	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);
-		}
-		ret = name_constraints_node_list_add(nodes, tmp);
+	for (size_t i = 0; i < nodes2->size; i++) {
+		ret = name_constraints_node_add_copy(nc, nodes,
+						     nodes2->data[i]);
 		if (ret < 0) {
-			name_constraints_node_free(tmp);
-			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+			return gnutls_assert_val(ret);
 		}
 	}
 
@@ -690,7 +686,6 @@ 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;
 	struct name_constraints_node_list_st *nodes;
 	int ret;
 
@@ -700,15 +695,10 @@ static int name_constraints_add(gnutls_x509_name_constraints_t nc,
 
 	nodes = permitted ? &nc->permitted : &nc->excluded;
 
-	tmp = name_constraints_node_new(nc, type, name->data, name->size);
-	if (tmp == NULL)
-		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-
-	ret = name_constraints_node_list_add(nodes, tmp);
-	if (ret < 0) {
-		name_constraints_node_free(tmp);
+	ret = name_constraints_node_add_new(nc, nodes, type, name->data,
+					    name->size);
+	if (ret < 0)
 		return gnutls_assert_val(ret);
-	}
 
 	return 0;
 }
-- 
GitLab

