Wildcard certificates with short hostnames?
Solution 1:
Personal Experience
A while back I had a similar issue.
I had set up a local DNS for Windows and Linux servers with .staging as the
TLD. To save on creating and signing certificates for each virtual host and
avoid having to configure new IP addresses (non-SNI web servers), I created a
key and cert for *.staging
but all the clients I tried (including curl) only
reported that certificate subject name *.staging
does not match target host
name whenever I tried loading virtual hosts on our Staging server using TLS.
Relevant RFCs
I spent ages trying to figure out why the wildcard certificate I had generated
for *.staging
wouldn’t work. I had read all the relevant RFCs but none of them
specifically stated that such a wildcard certificate was invalid or illegal.
- Using TLS with IMAP, POP3 and ACAP
- HTTP Over TLS
- Representation and Verification of Domain-Based Application Service Identity within Internet Public Key Infrastructure Using X.509 (PKIX) Certificates in the Context of Transport Layer Security (TLS)
Security Stack Exchange Answers
I was eventually enlightened after reading this excellent Security Stack Exchange answer.
What matters is what SSL clients will accept as a "valid certificate", i.e. a certificate including a name which "matches" the intended server name (the one included in the URL). This is nominally specified in RFC 2818, section 3.1, and it allows many kinds of wildcard names, including things like "
www.*.*c*
", matching (theoretically) any server name containing three components, the first being "www
" and the third containing at least one "c
".
...
So browser vendors made their own schemes and restrictions. Much later, a new RFC (6125, from March 2011) was published, with section 6.4.3 dedicated to the processing of wildcard names in certificates. What RFC 6125 describes is more in tune with the reality, and is a "proposed standard", so there is at least some will, at some level, to make it happen. However, nothing in RFC 6125 mandates rejection of
*.com
; yet browsers do reject it.
The accepted answer to Can a wildcard SSL certificate be issued for a second level domain? also deserved an up-vote.
Edit
I figured that aside from recounting personal frustration, my answer doesn’t really add a lot other than linking to the RFCs and the relevant answers on Security Stack Exchange; I thought I’d put more effort in and search for the current relevant source code used by Chromium and Firefox.
Note that the comments in the Chromium source code explicitly mention that
unknown top-level domains (such as *.intranet
) are disallowed.
Also: there’s no reference to a user-configurable option that can override this behaviour.
Mozilla source code
From mozilla-central Mercurial Repository
Like NSS, require at least two labels to follow the wildcard label.
if (isWildcard) {
// If the DNS ID ends with a dot, the last dot signifies an absolute ID.
size_t labelCount = (labelLength == 0) ? dotCount : (dotCount + 1);
// Like NSS, require at least two labels to follow the wildcard label.
//
// TODO(bug XXXXXXX): Allow the TrustDomain to control this on a
// per-eTLD+1 basis, similar to Chromium. Even then, it might be better to
// still enforce that there are at least two labels after the wildcard.
if (labelCount < 3) {
return false;
}
// XXX: RFC6125 says that we shouldn't accept wildcards within an IDN
// A-Label. The consequence of this is that we effectively discriminate
// against users of languages that cannot be encoded with ASCII.
if (StartsWithIDNALabel(hostname)) {
return false;
}
// TODO(bug XXXXXXX): Wildcards are not allowed for EV certificates.
// Provide an option to indicate whether wildcards should be matched, for
// the purpose of helping the application enforce this.
}
Chromium source code
From Chromium Git Repository
Do not allow wildcards for public/ICANN registry controlled domains - that is, prevent *.com or *.co.uk as valid presented names
In addition, unknown top-level domains (such as 'intranet' domains or new TLDs/gTLDs not yet added to the registry controlled domain dataset) are also implicitly prevented.
if (!reference_domain.empty()) {
DCHECK(reference_domain.starts_with("."));
// Do not allow wildcards for public/ICANN registry controlled domains -
// that is, prevent *.com or *.co.uk as valid presented names, but do not
// prevent *.appspot.com (a private registry controlled domain).
// In addition, unknown top-level domains (such as 'intranet' domains or
// new TLDs/gTLDs not yet added to the registry controlled domain dataset)
// are also implicitly prevented.
// Because |reference_domain| must contain at least one name component that
// is not registry controlled, this ensures that all reference domains
// contain at least three domain components when using wildcards.
size_t registry_length =
registry_controlled_domains::GetRegistryLength(
reference_name,
registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
// Because |reference_name| was already canonicalized, the following
// should never happen.
CHECK_NE(std::string::npos, registry_length);
// Account for the leading dot in |reference_domain|.
bool is_registry_controlled =
registry_length != 0 &&
registry_length == (reference_domain.size() - 1);
// Additionally, do not attempt wildcard matching for purely numeric
// hostnames.
allow_wildcards =
!is_registry_controlled &&
reference_name.find_first_not_of("0123456789.") != std::string::npos;
}
The comments in registry_controlled_domain.h are also relevant:
The RegistryControlledDomainService examines the hostname of a GURL passed to it and determines the longest portion that is controlled by a registrar. Although technically the top-level domain (TLD) for a hostname is the last dot-portion of the name (such as .com or .org), many domains (such as co.uk) function as though they were TLDs, allocating any number of more specific, essentially unrelated names beneath them. For example, .uk is a TLD, but nobody is allowed to register a domain directly under .uk; the "effective" TLDs are ac.uk, co.uk, and so on. We wouldn't want to allow any site in *.co.uk to set a cookie for the entire co.uk domain, so it's important to be able to identify which higher-level domains function as effective TLDs and which can be registered.
Both the Chromium and Mozilla projects base their definition of an effective TLD on the Public Suffix List as published by Mozilla.
Solution 2:
HTTPS clients should refuse to match TLD wildcards like *.com
or *.net
(or even *
) for security reasons: No single certificate should claim authority over a whole TLD.
Now how is the client supposed to find out whether .example is a TLD (matching *.example
forbidden) or a short form (matching allowed)? Particularly considering that new TLDs pop up every other day and any static TLD list would soon be outdated.
So clients simply refuse to match any wildcard *.XYZ
and expect to see at least two dots in a wildcard.
Note that they should still maintain wildcard blacklists like *.co.uk *.co.jp
etc.