[meta-lts-collab][kirkstone][PATCH 4/7] strongswan: Fix CVE-2026-35331

Nitin Wankhade <[email protected]>
Newsgroups org.yoctoproject.lists.yocto-patches
Message-ID <[email protected]>
From: Nitin Wankhade <[email protected]>

Upstream-Status: Backport [https://snapshot.debian.org/archive/debian-security-debug/20260422T125423Z/pool/updates/main/s/strongswan/strongswan_6.0.1-6%2Bdeb13u5.debian.tar.xz]

Signed-off-by: Nitin Wankhade <[email protected]>
---
 ...-insensitive-matching-and-reject-exc.patch | 145 ++++++++++++++++++
 .../strongswan/strongswan_5.9.13.bbappend     |   1 +
 2 files changed, 146 insertions(+)
 create mode 100644 meta-networking/recipes-support/strongswan/files/constraints-Case-insensitive-matching-and-reject-exc.patch

diff --git a/meta-networking/recipes-support/strongswan/files/constraints-Case-insensitive-matching-and-reject-exc.patch b/meta-networking/recipes-support/strongswan/files/constraints-Case-insensitive-matching-and-reject-exc.patch
new file mode 100644
index 0000000..40ca317
--- /dev/null
+++ b/meta-networking/recipes-support/strongswan/files/constraints-Case-insensitive-matching-and-reject-exc.patch
@@ -0,0 +1,145 @@
+From: Tobias Brunner <[email protected]>
+Date: Mon, 23 Mar 2026 17:45:11 +0100
+Subject: constraints: Case-insensitive matching and reject excluded DN name
+ constraints
+
+The case is generally ignored when matching identities.  So this is
+an issue with excluded name constraints where a malicious intermediate
+CA could evade the constraints by issuing certificates with names that
+just modify the case (e.g. strongSwan.org instead strongswan.org).
+
+Note that it's likely that permitted name constraints are preferred over
+excluded name constraints as it might be difficult to come up with a
+conclusive list of names to exclude.
+
+With directoryName (DN) name constraints the issue is a bit more comples.
+Some RDNs have to be matched in a case-insensitive manner, which we e.g.
+do in `identification.c::rdn_equals`.  By not doing it for name
+constraints, a malicious intermediate CA could evade an excluded name
+constraint just by modifying the case in such an RDN.
+
+While we could use the mentioned function in `dn_matches`, this doesn't
+properly fix the problem because the function is basically too strict.
+Especially in regards to RDNs of type UTF8String, which are only compared
+binary.  To match these properly, we'd have to implement the string
+preparation described in RFC 5280, section 7.1 and the referenced RFCs.
+Until that's the case, we reject excluded name constraints of type
+directoryName as we are unable to enforce them.
+
+Fixes: a2b340764fac ("Implemented NameConstraint matching in constraints plugin")
+Fixes: CVE-2026-35331
+
+CVE: CVE-2026-35331
+Upstream-Status: Backport [https://snapshot.debian.org/archive/debian-security-debug/20260422T125423Z/pool/updates/main/s/strongswan/strongswan_6.0.1-6%2Bdeb13u5.debian.tar.xz]
+Patch is refreshed as per the source code version 5.9.13
+Signed-off-by: Nitin Wankhade <[email protected]>
+===
+diff --git a/src/libstrongswan/plugins/constraints/constraints_validator.c b/src/libstrongswan/plugins/constraints/constraints_validator.c
+index b1f60fb..a04720a 100644
+--- a/src/libstrongswan/plugins/constraints/constraints_validator.c
++++ b/src/libstrongswan/plugins/constraints/constraints_validator.c
+@@ -52,6 +52,18 @@ static bool check_pathlen(x509_t *issuer, int pathlen)
+ 	return TRUE;
+ }
+ 
++/**
++ * Check if the constraint and ID strings match case-insensitively
++ */
++static bool string_matches(chunk_t constraint, chunk_t id)
++{
++       /* make sure the two strings have actually the same length */
++       return constraint.len == id.len &&
++                  memchr(constraint.ptr, 0, constraint.len) == NULL &&
++                  memchr(id.ptr, 0, id.len) == NULL &&
++                  strncasecmp(constraint.ptr, id.ptr, constraint.len) == 0;
++}
++
+ /**
+  * Check if a FQDN constraint matches
+  */
+@@ -67,7 +79,7 @@ static bool fqdn_matches(identification_t *constraint, identification_t *id)
+ 		return FALSE;
+ 	}
+ 	diff = chunk_create(i.ptr, i.len - c.len);
+-	if (!chunk_equals(c, chunk_skip(i, diff.len)))
++	if (!string_matches(c, chunk_skip(i, diff.len)))
+ 	{
+ 		return FALSE;
+ 	}
+@@ -98,10 +110,10 @@ static bool email_matches(identification_t *constraint, identification_t *id)
+ 	}
+ 	if (memchr(c.ptr, '@', c.len))
+ 	{	/* constraint is a full email address */
+-		return chunk_equals(c, i);
++		return string_matches(c, i);
+ 	}
+ 	diff = chunk_create(i.ptr, i.len - c.len);
+-	if (!diff.len || !chunk_equals(c, chunk_skip(i, diff.len)))
++	if (!diff.len || !string_matches(c, chunk_skip(i, diff.len)))
+ 	{
+ 		return FALSE;
+ 	}
+diff --git a/src/libstrongswan/tests/suites/test_certnames.c b/src/libstrongswan/tests/suites/test_certnames.c
+index 3672912..4441912 100644
+--- a/src/libstrongswan/tests/suites/test_certnames.c
++++ b/src/libstrongswan/tests/suites/test_certnames.c
+@@ -194,8 +194,10 @@ static struct {
+ 	bool good;
+ } permitted_san[] = {
+ 	{ ID_FQDN, ".strongswan.org", "test.strongswan.org", TRUE },
++	{ ID_FQDN, ".strongswan.org", "test.strongSwan.org", TRUE },
+ 	{ ID_FQDN, "strongswan.org", "test.strongswan.org", TRUE },
+ 	{ ID_FQDN, "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", TRUE },
++	{ ID_FQDN, "a.b.c.strongswan.org", "d.A.b.C.strongswan.org", TRUE },
+ 	{ ID_FQDN, "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", FALSE },
+ 	{ ID_FQDN, "strongswan.org", "strongswan.org.com", FALSE },
+ 	{ ID_FQDN, ".strongswan.org", "strongswan.org", FALSE },
+@@ -203,8 +205,11 @@ static struct {
+ 	{ ID_FQDN, "strongswan.org", "swan.org", FALSE },
+ 	{ ID_FQDN, "strongswan.org", "swan.org", FALSE },
+ 	{ ID_RFC822_ADDR, "[email protected]", "[email protected]", TRUE },
++	{ ID_RFC822_ADDR, "[email protected]", "[email protected]", TRUE },
++	{ ID_RFC822_ADDR, "[email protected]", "[email protected]", TRUE },
+ 	{ ID_RFC822_ADDR, "[email protected]", "[email protected]", FALSE },
+ 	{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", TRUE },
++	{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", TRUE },
+ 	{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", FALSE },
+ 	{ ID_RFC822_ADDR, ".strongswan.org", "[email protected]", TRUE },
+ 	{ ID_RFC822_ADDR, ".strongswan.org", "[email protected]", FALSE },
+@@ -232,11 +237,11 @@ static struct {
+ 	char *subject;
+ 	bool good;
+ } excluded_dn[] = {
+-	{ "C=CH, O=another", "C=CH, O=strongSwan, CN=tester", TRUE },
+-	{ "C=CH, O=another", "C=CH, O=anot", TRUE },
+-	{ "C=CH, O=another", "C=CH, O=anot, CN=tester", TRUE },
++	{ "C=CH, O=another", "C=CH, O=strongSwan, CN=tester", FALSE },
++	{ "C=CH, O=another", "C=CH, O=anot", FALSE },
++	{ "C=CH, O=another", "C=CH, O=anot, CN=tester", FALSE },
+ 	{ "C=CH, O=another", "C=CH, O=another, CN=tester", FALSE },
+-	{ "C=CH, O=another", "C=CH, CN=tester, O=another", TRUE },
++	{ "C=CH, O=another", "C=CH, CN=tester, O=another", FALSE },
+ };
+ 
+ START_TEST(test_excluded_dn)
+@@ -266,7 +271,9 @@ static struct {
+ } excluded_san[] = {
+ 	{ ID_FQDN, ".strongswan.org", "test.strongswan.org", FALSE },
+ 	{ ID_FQDN, "strongswan.org", "test.strongswan.org", FALSE },
++	{ ID_FQDN, "strongswan.org", "test.strongSwan.org", FALSE },
+ 	{ ID_FQDN, "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", FALSE },
++	{ ID_FQDN, "a.b.c.strongswan.org", "d.a.b.C.strongswan.org", FALSE },
+ 	{ ID_FQDN, "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", TRUE },
+ 	{ ID_FQDN, "strongswan.org", "strongswan.org.com", TRUE },
+ 	{ ID_FQDN, ".strongswan.org", "strongswan.org", TRUE },
+@@ -274,8 +281,10 @@ static struct {
+ 	{ ID_FQDN, "strongswan.org", "swan.org", TRUE },
+ 	{ ID_FQDN, "strongswan.org", "swan.org", TRUE },
+ 	{ ID_RFC822_ADDR, "[email protected]", "[email protected]", FALSE },
++	{ ID_RFC822_ADDR, "[email protected]", "[email protected]", FALSE },
+ 	{ ID_RFC822_ADDR, "[email protected]", "[email protected]", TRUE },
+ 	{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", FALSE },
++	{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", FALSE },
+ 	{ ID_RFC822_ADDR, "strongswan.org", "[email protected]", TRUE },
+ 	{ ID_RFC822_ADDR, ".strongswan.org", "[email protected]", FALSE },
+ 	{ ID_RFC822_ADDR, ".strongswan.org", "[email protected]", TRUE },
diff --git a/meta-networking/recipes-support/strongswan/strongswan_5.9.13.bbappend b/meta-networking/recipes-support/strongswan/strongswan_5.9.13.bbappend
index 0769de9..5b30348 100644
--- a/meta-networking/recipes-support/strongswan/strongswan_5.9.13.bbappend
+++ b/meta-networking/recipes-support/strongswan/strongswan_5.9.13.bbappend
@@ -2,4 +2,5 @@ SRC_URI += "\
     file://tls-server-Prevent-infinite-loop-if-supported-versio.patch \
     file://pkcs5-pkcs7-Avoid-NULL-pointer-dereference-when-veri.patch \
     file://libsimaka-Reject-zero-length-EAP-SIM-AKA-attributes.patch \
+    file://constraints-Case-insensitive-matching-and-reject-exc.patch \
 "
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.