mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-07-15 16:07:26 +00:00
strongswan: Fix CVE-2026-35331
Upstream-Status: Backport [https://github.com/strongswan/strongswan/commit/64130ede5cd8f61edd35a1b488c874fa328a42b0] [https://github.com/strongswan/strongswan/commit/c66143db48bab9eb82cc86190687938b809611eb] Signed-off-by: Nitin Wankhade <nitin.wankhade333@gmail.com> Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
committed by
Anuj Mittal
parent
0d3124974e
commit
fca99be2d5
+176
@@ -0,0 +1,176 @@
|
|||||||
|
From: Tobias Brunner <tobias@strongswan.org>
|
||||||
|
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://github.com/strongswan/strongswan/commit/64130ede5cd8f61edd35a1b488c874fa328a42b0]
|
||||||
|
[https://github.com/strongswan/strongswan/commit/c66143db48bab9eb82cc86190687938b809611eb]
|
||||||
|
Signed-off-by: Nitin Wankhade <nitin.wankhade333@gmail.com>
|
||||||
|
===
|
||||||
|
diff --git a/src/libstrongswan/plugins/constraints/constraints_validator.c b/src/libstrongswan/plugins/constraints/constraints_validator.c
|
||||||
|
index 27bdb89..daa7bfa 100644
|
||||||
|
--- a/src/libstrongswan/plugins/constraints/constraints_validator.c
|
||||||
|
+++ b/src/libstrongswan/plugins/constraints/constraints_validator.c
|
||||||
|
@@ -55,6 +55,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
|
||||||
|
*/
|
||||||
|
@@ -70,7 +82,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;
|
||||||
|
}
|
||||||
|
@@ -101,10 +113,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 (!chunk_equals(c, chunk_skip(i, diff.len)))
|
||||||
|
+ if (!string_matches(c, chunk_skip(i, diff.len)))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
@@ -389,9 +401,17 @@ static bool collect_constraints(x509_t *x509, bool permitted, hashtable_t **out)
|
||||||
|
type = constraint->get_type(constraint);
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
+ case ID_DER_ASN1_DN:
|
||||||
|
+ if (!permitted)
|
||||||
|
+ {
|
||||||
|
+ DBG1(DBG_CFG, "excluded %N NameConstraint not supported",
|
||||||
|
+ id_type_names, type);
|
||||||
|
+ success = FALSE;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* fall-through */
|
||||||
|
case ID_FQDN:
|
||||||
|
case ID_RFC822_ADDR:
|
||||||
|
- case ID_DER_ASN1_DN:
|
||||||
|
case ID_IPV4_ADDR_SUBNET:
|
||||||
|
case ID_IPV6_ADDR_SUBNET:
|
||||||
|
break;
|
||||||
|
diff --git a/src/libstrongswan/tests/suites/test_certnames.c b/src/libstrongswan/tests/suites/test_certnames.c
|
||||||
|
index 2549fb6..14570ee 100644
|
||||||
|
--- a/src/libstrongswan/tests/suites/test_certnames.c
|
||||||
|
+++ b/src/libstrongswan/tests/suites/test_certnames.c
|
||||||
|
@@ -207,8 +207,10 @@ static struct {
|
||||||
|
bool good;
|
||||||
|
} permitted_san[] = {
|
||||||
|
{ ".strongswan.org", "test.strongswan.org", TRUE },
|
||||||
|
+ { ".strongswan.org", "test.strongSwan.org", TRUE },
|
||||||
|
{ "strongswan.org", "test.strongswan.org", TRUE },
|
||||||
|
{ "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", TRUE },
|
||||||
|
+ { "a.b.c.strongswan.org", "d.A.b.C.strongswan.org", TRUE },
|
||||||
|
{ "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", FALSE },
|
||||||
|
{ "strongswan.org", "strongswan.org.com", FALSE },
|
||||||
|
{ ".strongswan.org", "strongswan.org", FALSE },
|
||||||
|
@@ -216,8 +218,11 @@ static struct {
|
||||||
|
{ "strongswan.org", "swan.org", FALSE },
|
||||||
|
{ "strongswan.org", "swan.org", FALSE },
|
||||||
|
{ "tester@strongswan.org", "tester@strongswan.org", TRUE },
|
||||||
|
+ { "tester@strongswan.org", "tester@strongSwan.org", TRUE },
|
||||||
|
+ { "tester@strongswan.org", "TESTER@strongswan.org", TRUE },
|
||||||
|
{ "tester@strongswan.org", "atester@strongswan.org", FALSE },
|
||||||
|
{ "email:strongswan.org", "tester@strongswan.org", TRUE },
|
||||||
|
+ { "email:strongswan.org", "tester@strongSwan.org", TRUE },
|
||||||
|
{ "email:strongswan.org", "tester@test.strongswan.org", FALSE },
|
||||||
|
{ "email:.strongswan.org", "tester@test.strongswan.org", TRUE },
|
||||||
|
{ "email:.strongswan.org", "tester@strongswan.org", FALSE },
|
||||||
|
@@ -248,11 +253,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)
|
||||||
|
@@ -281,7 +286,9 @@ static struct {
|
||||||
|
} excluded_san[] = {
|
||||||
|
{ ".strongswan.org", "test.strongswan.org", FALSE },
|
||||||
|
{ "strongswan.org", "test.strongswan.org", FALSE },
|
||||||
|
+ { "strongswan.org", "test.strongSwan.org", FALSE },
|
||||||
|
{ "a.b.c.strongswan.org", "d.a.b.c.strongswan.org", FALSE },
|
||||||
|
+ { "a.b.c.strongswan.org", "d.a.b.C.strongswan.org", FALSE },
|
||||||
|
{ "a.b.c.strongswan.org", "a.b.c.d.strongswan.org", TRUE },
|
||||||
|
{ "strongswan.org", "strongswan.org.com", TRUE },
|
||||||
|
{ ".strongswan.org", "strongswan.org", TRUE },
|
||||||
|
@@ -289,8 +296,10 @@ static struct {
|
||||||
|
{ "strongswan.org", "swan.org", TRUE },
|
||||||
|
{ "strongswan.org", "swan.org", TRUE },
|
||||||
|
{ "tester@strongswan.org", "tester@strongswan.org", FALSE },
|
||||||
|
+ { "tester@strongswan.org", "TESTER@strongswan.org", FALSE },
|
||||||
|
{ "tester@strongswan.org", "atester@strongswan.org", TRUE },
|
||||||
|
{ "email:strongswan.org", "tester@strongswan.org", FALSE },
|
||||||
|
+ { "email:strongswan.org", "tester@strongSwan.org", FALSE },
|
||||||
|
{ "email:strongswan.org", "tester@test.strongswan.org", TRUE },
|
||||||
|
{ "email:.strongswan.org", "tester@test.strongswan.org", FALSE },
|
||||||
|
{ "email:.strongswan.org", "tester@strongswan.org", TRUE },
|
||||||
|
@@ -418,9 +427,9 @@ static struct {
|
||||||
|
char *subject;
|
||||||
|
bool good;
|
||||||
|
} excluded_dn_levels[] = {
|
||||||
|
- { "C=CH, O=strongSwan", "C=CH", "C=DE", TRUE },
|
||||||
|
+ { "C=CH, O=strongSwan", "C=CH", "C=DE", FALSE },
|
||||||
|
{ "C=CH, O=strongSwan", "C=CH", "C=CH", FALSE },
|
||||||
|
- { "C=CH, O=strongSwan", "C=DE", "C=CH", TRUE },
|
||||||
|
+ { "C=CH, O=strongSwan", "C=DE", "C=CH", FALSE },
|
||||||
|
{ "C=CH, O=strongSwan", "C=DE", "C=DE", FALSE },
|
||||||
|
{ "C=CH, O=strongSwan", "C=DE", "C=CH, O=strongSwan", FALSE },
|
||||||
|
{ NULL, "C=CH", "C=CH, O=strongSwan", FALSE },
|
||||||
@@ -15,6 +15,7 @@ SRC_URI = "https://download.strongswan.org/strongswan-${PV}.tar.bz2 \
|
|||||||
file://tls-server-Prevent-infinite-loop-if-supported-versio.patch \
|
file://tls-server-Prevent-infinite-loop-if-supported-versio.patch \
|
||||||
file://pkcs5-pkcs7-Avoid-NULL-pointer-dereference-when-veri.patch \
|
file://pkcs5-pkcs7-Avoid-NULL-pointer-dereference-when-veri.patch \
|
||||||
file://libsimaka-Reject-zero-length-EAP-SIM-AKA-attributes.patch \
|
file://libsimaka-Reject-zero-length-EAP-SIM-AKA-attributes.patch \
|
||||||
|
file://constraints-Case-insensitive-matching-and-reject-exc.patch \
|
||||||
"
|
"
|
||||||
|
|
||||||
SRC_URI[sha256sum] = "728027ddda4cb34c67c4cec97d3ddb8c274edfbabdaeecf7e74693b54fc33678"
|
SRC_URI[sha256sum] = "728027ddda4cb34c67c4cec97d3ddb8c274edfbabdaeecf7e74693b54fc33678"
|
||||||
|
|||||||
Reference in New Issue
Block a user