From e95914be50f41b3e2d5fb5e5b7ef578db4ac5497 Mon Sep 17 00:00:00 2001
From: Christopher Patton <cpatton@cloudflare.com>
Date: Wed, 27 May 2026 13:59:54 -0700
Subject: [PATCH] Introduce X509_CHECK_FLAG_UNDERSCORE_WILDCARDS
---
crypto/x509/v3_utl.cc | 4 +++-
crypto/x509/x509_test.cc | 27 +++++++++++++++++++++++++++
include/openssl/x509.h | 4 ++++
3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/crypto/x509/v3_utl.cc b/crypto/x509/v3_utl.cc
index 765dfa634..ab45d3b13 100644
@@ -697,7 +697,9 @@ static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
// Check that the part matched by the wildcard contains only
// permitted characters and only matches a single label.
for (p = wildcard_start; p != wildcard_end; ++p) {
- if (!OPENSSL_isalnum(*p) && *p != '-') {
+ if (!OPENSSL_isalnum(*p) && *p != '-' &&
+ !(*p == '_' &&
+ (flags & X509_CHECK_FLAG_UNDERSCORE_WILDCARDS))) {
return 0;
}
}
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index f151a8dd8..278fc5481 100644
@@ -5871,6 +5871,33 @@ TEST(X509Test, Names) {
/*invalid_emails=*/{},
/*flags=*/0,
},
+
+ // Underscores in DNS names are forbidden by default.
+ {
+ /*cert_subject=*/{},
+ /*cert_dns_names=*/{"*.example.com"},
+ /*cert_emails=*/{},
+ /*cert_invalid_subject_alt_name=*/false,
+ /*valid_dns_names=*/{},
+ /*invalid_dns_names=*/{"not_allowed.example.com"},
+ /*valid_emails=*/{},
+ /*invalid_emails=*/{},
+ /*flags=*/0,
+ },
+
+ // Underscores in DNS names can be allowed with the right flag.
+ {
+ /*cert_subject=*/{},
+ /*cert_dns_names=*/{"*.example.com"},
+ /*cert_emails=*/{},
+ /*cert_invalid_subject_alt_name=*/false,
+ /*valid_dns_names=*/{"now_allowed.example.com"},
+ /*invalid_dns_names=*/{},
+ /*valid_emails=*/{},
+ /*invalid_emails=*/{},
+ /*flags=*/X509_CHECK_FLAG_UNDERSCORE_WILDCARDS,
+ },
+
};
size_t i = 0;
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index d08e888b2..d4dc47643 100644
@@ -3372,6 +3372,10 @@ OPENSSL_EXPORT int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
// enabled when subjectAltNames is missing.
#define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20
+// X509_CHECK_FLAG_UNDERSCORE_WILDCARDS allows underscores in DNS wildcard
+// matches.
+#define X509_CHECK_FLAG_UNDERSCORE_WILDCARDS 0x40
+
// X509_VERIFY_PARAM_set_hostflags sets the name-checking flags on `param` to
// `flags`. `flags` should be a combination of `X509_CHECK_FLAG_*` constants.
OPENSSL_EXPORT void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,