From 6e118a4dfe820ce62fc77130b89188bcd8fbcaad Mon Sep 17 00:00:00 2001
From: chenjianhu <chenjianhu@kylinos.cn>
Date: Fri, 1 Aug 2025 17:18:23 +0800
Subject: [PATCH] x509: fix incorrect handling in name constraints merging

As mentioned in commit ca573d65 ("x509: Fix asymmetry in name
constraints intersection", 2016-07-29), the
_gnutls_name_constraints_intersect function exhibited an
asymmetry in name constraints intersection behavior, specifically
manifested as:
1. Nodes of unique types in PERMITTED (absent in PERMITTED2) were
   preserved
2. Nodes of unique types in PERMITTED2 (absent in PERMITTED) were
   discarded

A 'used' flag was introduced, where if a node from PERMITTED2 was
   not used for the intersection, it would be copied to PERMITTED.

However,an unresolved edge case persisted:
- When 'removed.size > 0', the 'used' flag was unconditionally set
to 1
- This prevented copying of PERMITTED2 nodes with unique types

Signed-off-by: chenjianhu <chenjianhu@kylinos.cn>
Modified-by: Daiki Ueno <ueno@gnu.org>

Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/6e118a4dfe820ce62fc77130b89188bcd8fbcaad]
CVE: CVE-2025-14831 #Backport to apply CVE patches cleanly
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
---
 lib/x509/name_constraints.c    |  5 +++-
 tests/name-constraints-merge.c | 55 ++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
index 3c6e306303..2be6a2aaa6 100644
--- a/lib/x509/name_constraints.c
+++ b/lib/x509/name_constraints.c
@@ -414,7 +414,10 @@ static int name_constraints_node_list_intersect(
 				gnutls_assert();
 				goto cleanup;
 			}
-			used = 1;
+
+			if (t->type == t2->type)
+				used = 1;
+
 			// if intersection is not empty
 			if (tmp !=
 			    NULL) { // intersection for this type is not empty
diff --git a/tests/name-constraints-merge.c b/tests/name-constraints-merge.c
index 03b3243cc7..70376aaa74 100644
--- a/tests/name-constraints-merge.c
+++ b/tests/name-constraints-merge.c
@@ -418,6 +418,61 @@ void doit(void)
 	gnutls_x509_name_constraints_deinit(nc1);
 	gnutls_x509_name_constraints_deinit(nc2);
 
+	/* 5: variant of suite 0: after moving rfc822Name (ccc.com)
+	 * from NC1 to NC2, dNSName (xxx.ccc.com) should still be
+	 * rejected.
+	 *
+	 * NC1: permitted DNS org
+	 *      permitted DNS ccc.com
+	 * NC2: permitted DNS org
+	 *      permitted email ccc.com
+	 *      permitted DNS aaa.bbb.ccc.com
+	 */
+	suite = 5;
+
+	ret = gnutls_x509_name_constraints_init(&nc1);
+	check_for_error(ret);
+
+	ret = gnutls_x509_name_constraints_init(&nc2);
+	check_for_error(ret);
+
+	set_name("org", &name);
+	ret = gnutls_x509_name_constraints_add_permitted(
+		nc1, GNUTLS_SAN_DNSNAME, &name);
+	check_for_error(ret);
+
+	set_name("ccc.com", &name);
+	ret = gnutls_x509_name_constraints_add_permitted(
+		nc1, GNUTLS_SAN_DNSNAME, &name);
+	check_for_error(ret);
+
+	set_name("org", &name);
+	ret = gnutls_x509_name_constraints_add_permitted(
+		nc2, GNUTLS_SAN_DNSNAME, &name);
+	check_for_error(ret);
+
+	set_name("ccc.com", &name);
+	ret = gnutls_x509_name_constraints_add_permitted(
+		nc2, GNUTLS_SAN_RFC822NAME, &name);
+	check_for_error(ret);
+
+	set_name("aaa.bbb.ccc.com", &name);
+	ret = gnutls_x509_name_constraints_add_permitted(
+		nc2, GNUTLS_SAN_DNSNAME, &name);
+	check_for_error(ret);
+
+	ret = _gnutls_x509_name_constraints_merge(nc1, nc2);
+	check_for_error(ret);
+
+	/* check intersection of permitted */
+	set_name("xxx.ccc.com", &name);
+	ret = gnutls_x509_name_constraints_check(nc1, GNUTLS_SAN_DNSNAME,
+						 &name);
+	check_test_result(suite, ret, NAME_REJECTED, &name);
+
+	gnutls_x509_name_constraints_deinit(nc1);
+	gnutls_x509_name_constraints_deinit(nc2);
+
 	/* Test footer */
 
 	if (debug)
-- 
GitLab

