[meta-lts-collab][kirkstone][PATCH V2 4/7] strongswan: Fix CVE-2026-35331
Nitin Wankhade <[email protected]> Tue, 23 Jun 2026 11:39:58 +0530
| 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]> --- .../strongswan/files/CVE-2026-35331.patch | 157 ++++++++++++++++++ .../strongswan/strongswan_5.9.13.bbappend | 1 + 2 files changed, 158 insertions(+) create mode 100644 meta-networking/recipes-support/strongswan/files/CVE-2026-35331.patch diff --git a/meta-networking/recipes-support/strongswan/files/CVE-2026-35331.patch b/meta-networking/recipes-support/strongswan/files/CVE-2026-35331.patch new file mode 100644 index 0000000..13a8954 --- /dev/null +++ b/meta-networking/recipes-support/strongswan/files/CVE-2026-35331.patch @@ -0,0 +1,157 @@ +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..9a25eb6 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,6 +205,8 @@ 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]", FALSE }, +@@ -232,11 +236,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 +270,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,6 +280,7 @@ 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]", TRUE }, +@@ -304,7 +311,7 @@ static struct { + char *subject; + bool good; + } permitted_dninh[] = { +- { "C=CH", "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", TRUE }, ++ { "C=CH", "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", FALSE }, + { "C=CH", "C=DE, O=strongSwan", "C=CH, O=strongSwan, CN=tester", FALSE }, + { "C=CH, O=strongSwan", "C=CH", "C=CH", FALSE }, + }; +@@ -334,7 +341,7 @@ static struct { + char *subject; + bool good; + } excluded_dninh[] = { +- { "C=CH, O=strongSwan", "C=CH", "C=DE", TRUE }, ++ { "C=CH, O=strongSwan", "C=CH", "C=DE", FALSE }, + { "C=CH, O=strongSwan", "C=DE", "C=CH", FALSE }, + { "C=CH", "C=CH, O=strongSwan", "C=CH, O=strongSwan, CN=tester", FALSE }, + }; 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 527e3b3..b5d1966 100644 --- a/meta-networking/recipes-support/strongswan/strongswan_5.9.13.bbappend +++ b/meta-networking/recipes-support/strongswan/strongswan_5.9.13.bbappend @@ -3,4 +3,5 @@ SRC_URI += "\ file://CVE-2026-35328.patch \ file://CVE-2026-35329.patch \ file://CVE-2026-35330.patch \ + file://CVE-2026-35331.patch \ " -- 2.34.1