Hello S-1-1-0, PowerShell CryptoGuy (aka @Crypt32) is here again. Today I want to discuss about X.509 Name Constraints certificate extension. It is not widely used, but sometimes it is necessary. As extension name depicts, it is used to provide constraints or restrictions to certificate subject and subject alternative names (SAN) extension.
Name Constraints extension is defined and described in RFC 5280 §4.2.1.10. Extension presence in an end-entity certificate does not have any effect and is applied only to CA certificates that issue certificates to end entities. Once defined, the extension applies restrictions on any certificates that appear below that CA in the tree. Name Constraints may appear further in the certification path to set more restrictive constraints. It is not possible to set less restrictive constraints at lower levels. This prevents low-level (in the certification path meaning) CAs to violate restrictions applied at higher levels.
Figure 1 - sample certificate chain
Here we see a 3-tier PKI hierarchy with applied Name Constraints extension at 2nd level (below root). This is indicated by a yellow triangle. Name Constraints restrictions are applied to all directly and indirectly issued certificates. CA-2 doesn’t define Name Constraints extension in its own certificate, but restrictions still apply to certificates issued by CA-2 indirectly.
Although Name Constraints extension is not widely used, it may be mandatory in certain PKI deployment scenarios. Generally, these scenarios include (but not limited to) CA deployment in a partially trusted environments. The following sections
This scenario assumes that two (or more) organizations run their own business and have tight communications between each other. For example, employees of two companies exchange secure emails, digitally signed documents, encrypted files and so on. Each company run its own PKI with separate CAs. By default, Company1 (say, Contoso) won’t trust certificates issued by Company2 (say, Adatum), because their PKIs are private and not generally trusted. Opposite is true: Adatum won’t trust certificates issued by Contoso.
To establish a trust, companies may issue cross-certificates to each other, so Contoso will trust certificates issued by Adatum and vice versa. However, each party must protect themselves from a possible certificate issuance violations. For example, Contoso don’t want Adatum to issue certificates for Contoso namespace, because it will lead to a serious security breach. And Adatum don’t want Contoso to issue certificates for Adatum namespace. Otherwise, Adatum will be able to impersonate users from Contoso. Thus, companies agree on terms at which certificates are trusted. One term is that Contoso will trust Adatum certificates issued only to Adatum namespace. No other namespaces are permitted. As always, opposite is true. This restriction is achieved by applying Name Constraints extension in cross-certificates.
CA bridge is a larger version of cross-certification. It is intended for the same purposes and just for larger scales. Individual cross-certification is effective when there are very few parties (no more than 4-5). Once the party count is increased, the number of totally issued cross-certificates (to provide a fully connected network of trust) grows in the following proportion: and quickly becomes enormous. For example, for 6 parties, it will require 15 certificates, for 7 parties it will require 21 cross-certificate. To solve this problem a special Bridge CA is implemented:
Figure 2 - sample Bridge CA
Bridge CA is a standard CA which issues cross-certificates to each party and each party issue certificates to Bridge CA. This will provide fully connected network of trust, so each party will trust other bridge party CAs and will require only cross-certificates.
This often occurs when the company runs multiple Active Directory forests (during another company acquisition, for example). In this case, head company deploys single root CA and each forest run subordinate CAs and are managed by respective forest administrators. Subordinate CA certificates will include Name Constraints extension to protect each forest from certificate misissuance by other forests.
In Internet PKI profile, Name Constraints extension is defined in . It consist of two optional (however, at least one component must present) components:
Permitted subtree contains definitions for allowed namespaces, while Excluded subtree contains definitions for explicitly disallowed namespaces. Each subtree’s entry is provided in an Alternative Name form (like Subject Alternative Names extension). The most common alternative name forms are:
and others. Below is an example syntax for INF file to use in Microsoft certreq.exe
utility:
[NameConstraintsExtension] Include = PermittedSubtree ; permitted subtree Exclude = ExcludedSubtree ; excluded subtree Critical = True [PermittedSubtree] DirectoryName = "DC=contoso,DC=com" ; allows any name blow this root DNS = contoso.com ; allows *.contoso.com, for example, www.contoso.com DNS = .contoso.com ; allows subdomains: www.sub.contoso.com Email = @contoso.com ; allows someone@contoso.com Email = .contoso.com ; allows someone@sub.contoso.com IPAddress = 192.168.0.0, 255.255.255.0 ; format: {IP network address},{Subnet Mask} [ExcludedSubtree] DirectoryName = "DC=Branch,DC=contoso,DC=com" ; explicitly disallows DC=Branch,DC=contoso,DC=com entire subtree DNS = branch.contoso.com ; disallows branch.contoso.com DNS = .branch.contoso.com ; disallows subdomains: www.sub.branch.contoso.com UPN = empty ; disallows any name of User Principal Name form Email = @branch.contoso.com ; disallows someone@branch.contoso.com Email = .branch.contoso.com ; disallows someone@sub.branch.contoso.com
The syntax should be self-explanatory. We define one or both subtrees (permitted and/or excluded) and provide name constraints in required name form.
Name constraints processing rules are not easy to understand, but they are similar to NTFS permissions in certain aspects. To make it easier to understand, I will provide examples to show how name is validated.
Certificate chaining engine (CCE) performs name validation after constructing certificate chain (or certification path) starting from root CA certificate down to certificate being processed. If we take a loot at Figure 1, CCE will take each name in the certificate (including Subject field and SAN extension) and process it in the following direction for the certificate issued by Subordinate Policy and Issuing CA-1:
1 - Root CA 2 - Subordinate Policy and Issuing CA-1 3 - Subordinate Policy and Issuing CA-2
If particular name in leaf certificate is excluded at some point, this name will be invalid for that leaf certificate. In short, CCE will compare each name with Name Constraints extension and passes down only valid name. If the name is excluded, CCE will take another name and starts over. Names reached leaf certificate (which weren’t excluded and eliminated) are the only valid names for the certificate being processed. I hope, this general behavior is clear for you.
The following sections will describe exact processing rules at each CA level depending on Name Constraints configuration. As said above, Name Constraints extension may have the following configurations:
Let’s start with general subtree processing rules. Configuration when no subtrees are defines is not valid.
All examples in this section, assume that CA certificate has Name Constraints with sections according to INF configuration provided above.
If only Permitted Subtree is presented, then only names that matches to name patterns defined in Permitted Subtree section. This means that particular name must match at least one pattern in the matching name form. For example, if certificate name is in the DnsName form, it must match to any DnsName form specified in the configuration. Otherwise the name is excluded. The following examples assume that there is no Excluded Subtree section in the CA certificate.
Example 1: validating DnsName = www.contoso.com
. This name has one matching entry in permitted subtree: DNS = contoso.com
. As the result, DnsName = www.contoso.com
name is allowed.
Example 2: validating Email = admin@sub.contoso.com
. This name has one matching entry in permitted subtree: Email = .contoso.com
. As the result, Email = admin@sub.contoso.com
name is allowed.
Example 3: validating DnsName = 192.168.0.5
. This name has one matching entry in permitted subtree: IPAddress = 192.168.0.0, 255.255.255.0
. Although, name pattern matches – IP address falls to allowed subnet, name forms are not matching. As the result, DnsName = 192.168.0.5
name is excluded and not allowed.
Example 4: validating UPN = admin@sub.contoso.com
. This name has no matching in permitted subtree. However, Name Constraints configuration doesn’t have UPN name form definitions.
As per RFC 5280 §4.2.1.10(g).(1):
Restrictions apply to the subject distinguished name and apply to subject alternative names. Restrictions apply only when the specified name form is present. If no name of the type is in the certificate, the certificate is acceptable.
and §6.1.4:
If permittedSubtrees does not include a particular name type, the permitted_subtrees state variable is unchanged for that name type.
This means that if particular name form is not defined, then all names of that undefined form are allowed! Remember this!
If Name Constraints extension contains only Excluded Subtree, it works in blacklisting mode. If certificate name matches at least one entry in excluded subtree, the name is excluded and is invalidated. In all other cases the name is valid.
Example 1: validating DnsName = www.sub.branch.contoso.com
. This name has one matching entry in excluded subtree: DNS = .branch.contoso.com
. As the result, DnsName = www.sub.branch.contoso.com
name is excluded and invalidated.
Example 2: validating Email = admin@sub.contoso.com
. This name has no matching entry in excluded subtree. As the result, Email = admin@sub.contoso.com
name is valid.
Example 3: validating IPAddress = 192.168.0.0, 255.255.255.0
. There are no name forms of IPAddress in excluded subtree. This means that IPAddress = 192.168.0.0, 255.255.255.0
is valid.
Example 4: validating UPN = admin@contoso.com
. There is an empty entry of UPN form. Empty sequence is a wildcard and literally disallows any namespace of that name form. In a given example, no UPNs are allowed in the certificate.
When both subtrees are defined, their processing rules are the same as described above with the following additional rule:
As I already mentioned, empty entries imply wildcard entries. However, you should understand the difference in presence of empty entry in permitted and excluded subtrees.
the following diagram illustrates processing rules at each CA level:
Figure 3 - processing rules diagram
The diagram is not that beautiful as it could be, but it is correct. If someone or you have better diagram skills and can spend time to rewrite it – you are welcome!
As of now, Windows CryptoAPI and OpenSSL fully support Name Constraints certificate extension. However, neither of Apple products: Mac OS X, nor iOS does support this extension. Since, Name Constraints is always marked critical, Apple products will reject any certificate that contains Name Constraints extension in any certificate in the certificate chain.
Critical extensions are extensions that are mandatory for processing. If client software (i.e. certificate chaining engine) does not recognize critical extension, or extension value is unclear, the certificate must be rejected. In a given case, when Name Constraints extension is presented and no subtree is defined, client MUST reject the certificate, because critical extension is malformed.
HTH.
Hello Vadims,
Thanks for this interesting post. I have a question regarding processing of name forms within the subject name. Is the common name tested against DNS/IP addresses entries of name constraint subtrees or are those name forms only tested against corresponding SAN entries?
Second question, with your pkix library, how would you create an empty name form (like "UPN = empty")? Simply passing a blank string as the second argument of X509AlternativeName?
Thanks,
Your question is very good. Indeed. The quick answer is No, IPAddress/DNS name forms are not tested against subject field. However, DirectoryName name form is tested against Subject field and against DirectoryName entries in SAN extension. There is one exception for RFC822 name. If Name Constraints define restrictions on RFC822 name form (Email), they apply to both, RFC822 name value in SAN extension (if presented) and to E(Email) RDN attribute in Subject field if SAN extension is absent in the certificate.
Another case includes IPAddress. As per RFC5280, empty entry of type of IPAddress in NameConstraints extension is not valid at all. It must be 8 (for IPv4) or 32 bytes (for IPv6) long value. However, Microsoft implementation does support empty sequence in IPAddress name form.
As of second question. PKIX.NET library -- it doesn't fully support empty entries for particular name forms yet. I made modifications to allow extended values for IPAddress name form (for example) to support IP address and netmask (which are required in Name Constraints, but not allowed in SAN extension) altogether. Your point is valid and I would ask you to open a bug/feature request on GitHub. I think, my general X509AlternativeName class should allow empty entries for particular name type and empty names should be accepted by an X509NameConstraintsExtension class, but not by X509AlternativeSubjectNamesExtension and X509AlternativeIssuerNamesExtension classes. They should provide additional logic to check for empty sequences and disallow/ignore them.
Hi and thank you for the reply.
Feature request posted on Github. I have no short term plan to use that feature myself so this would be for completeness I guess.
As for your first answer, this is too bad :/ This means that a classic TLS server authentication certificate putting a server's domain name in the common name but having no SAN extension at all (which is accepted by browsers of course) cannot be constrained by any name constraint extensions. And using a directory name constraint is of no use in that case since we do not care about the complete DN here but just the CN.
> This means that a classic TLS server authentication certificate putting a server's domain name in the common name but having no SAN extension at all (which is accepted by browsers of course) cannot be constrained by any name constraint extensions
I consider your scenario is an example of technology misuse these days.
Many years back (in 1988 when X.509 profile was standartized) there was a big hope that everything in the world could be expressed in a X.500 distinguished name form and will be a part of the huge world-size DAP directory. That directory would define everything in the world: people (real people) organizations and even job positions in each organization. For example, root node is "." (dot) and many namespaces uner root that would define countries, each country will define child namespaces for states/cities, organizations registered in particular country and so on. For that purposes X.509 profile decided to use X.500 distinguished name form in Subject and Issuer fields. However, that idea failed and digital world moved from complex DAP to more flexible DNS. In those days, there were no certificate extensions, so Internet consorciums decided to change X.509 subject field use from original to another: describe and define other name forms in X.500 terms. As the result, real LDAP path is ignored. Valid RDN attributes are used to embed non-X.500 name forms. That is, to identify an end entity, CN attribute is used, E attribute is used to identify mail recipient/sender and so on. It was an ad-hoc solution until X.509 Version 3 profile was released.
X.509 V3 profile addressed all these issues by adding Subject Alternative Name (SAN) and Issuer Alternative Name (IAN) left Subject and Issuer fields for compatibility purposes with previous profile versions (V1 and V2). X.509 V3 profile discourages Subject field usage unless it is a part of real DAP directory. If the entity is identified by a non-DAP path (i.e. DNS form), its identity MUST be defined in the SAN extension. These days, CAs still provide Subject field with fictional information for compatibility purposes. Another reason is that they used to do so many years ago. However, I can't imagine these days a crypto software that can't interpret X.509 V3 certificates.
To summarize all above, I want to say that embedding non-X.500 name forms in Subject field without putting them into SAN extension is technology misuse and against X.509 profile recommendations. This is why in X.509, DNS name constraints do not affect Subject field at all. That is, if you attempt to use the technology in a way it is not supposed to be used -- consequences might be unpredictable. I hope you understand the whole point.
Hello Vadims,
I find your discussion very interesting and now I have the following question.
I have understood that a certificate with a dns name (e.g.: "abcd.efgh.ijkl") only in the Subject Name field is accepted as TLS server certificates on principle even if this is a misuse as you have explained. Could you please tell me what must be specified as Name Constraints in the respective CA certificate so that TLS server certificates issued under this CA for the domain "efgh.ijkl" will be rejected?
Thanks in advance.
Just add "efgh.ijkl" as a DNS name in ExcludedSubtree section. Like I said, CN attribute in certificate's subject is equivalent to DNS name entry in SAN (in context of SSL, or course).
What exactly does "Since, Name Constraints is always marked critical, Apple products will reject any certificate that contains Name Constraints extension in any certificate in the certificate chain."
If I import a self-signed cert with a name constraint on my Mac, it appears that it will go to (open tls/https) sites hosted by signed cert if they are validated or not validated by the name constraints. I was hoping that it would reject all sites because as you stated it should reject "any certificate" with the Name Constraints.
Note: Firefox (which does support name constraints via a separate TLS stack) does allows / disallows the correct domains. So I believe I have the correct setup.
> If I import a self-signed cert with a name constraint on my Mac, it appears that it will go to (open tls/https) sites hosted by signed cert if they are validated or not validated by the name constraints
haven't checket latest MacOS versions, but there is confirmation that Name Constraints is not supported: https://security.stackexchange.com/questions/95600/are-x-509-nameconstraints-on-certificates-supported-on-os-x
Hello Vadims
Appologies if this a repeat of a previous question, but I just want to be 100% sure about something and there are two answers above that appear at first light to be contry to one another
I have a standalone root CA (test)
I want to stop the CA issuing a certficate where the CN element of the Subject Name contains MyDomain.net for example "CN=web01.mydomain.net,OU=IT,O=MyOrg,L=Poole,S=Dorset,C=GB" I should note the CSR has no SAN (I am not in control of the incomming CSRs)
From one of your replies above I do not believe this is possible, but on another reply above you seem to suggest this is possible, below is a copy of the CAPolicy.inf file I used when standing up the root CA and I can see the name contrains extension on the CA certificate OK (if I add a SAN with a DNS name which includes MyDomain.net the CA does indeed reject the request, but not if there is no SAN and only a Subject name)
[Version]
Signature= "$Windows NT$"
[Strings]
szOID_NAME_CONSTRAINTS = "2.5.29.30"
[Extensions]
Critical = %szOID_NAME_CONSTRAINTS%
%szOID_NAME_CONSTRAINTS% = "{text}"
_continue_ = "SubTree=Exclude&"
_continue_ = "DNS = CN=.MyDomain.net&"
_continue_ = "DNS = CN=*.MyDomain.net&"
_continue_ = "DNS = MyDomain.net&"
_continue_ = "DNS = .MyDomain.net&"
_continue_ = "UPN = .MyDomain.net&"
_continue_ = "UPN = MyDomain.net&"
_continue_ = "email = .MyDomain.net&"
_continue_ = "email = @MyDomain.net&"
_continue_ = "DIRECTORYNAME = DC=MyDomain, DC=com&"
_continue_ = "URL = .MyDomain.net&"
_continue_ = "URL = MyDomain.net"
From what I have seen so far (unless I am missing something) if someone sends my CA a CSR with a Subject only (on SAN) which includes CN=MyWeb01.MyDomain.net,...... I cannot reject it based in name contraints
Thanks very much in advance
Ernie
Type above, I meant to say
From what I have seen so far (unless I am missing something) if someone sends my CA a CSR with a Subject only (no SAN) which includes CN=MyWeb01.MyDomain.net,...... I cannot reject it based in name contraints
Thanks
Ernie
hi
as i understood, then nameConstrain extension use to restrict subCA sign certificate request?
this example valid only for windows.
if you want do it with openssl, then syntax is different.
....
nameConstraints=critical,permitted;dirName:nameConstraintsDirName, permitted;DNS:.example.com, permitted;email:@example.com
[nameConstraintsDirName]
0.C=FR
1.L=Paris
2.O=Renault Corporation
3.OU=Sales Department
Yes, all examples are provided for Windows platforms and Windows tooling. Of course, you can do this with OpenSSL with different syntax, but it is not in my focus.
and ca must contain eku (clientauth, serverauth ...etc), for what ca is allowed sign client certificates.
if permitted tree does not contain IP, then excluded tree must contain "excluded;IP:0.0.0.0/0.0.0.0, excluded;IP:::/::"
also ca must contain crl or/and oscp points.
there is sample from INTEL CA
################# FROM INTEL ######################
nameConstraints=permitted;DNS:01.org, permitted;dirName:nameConstraints_106_dirname, excluded;IP:0.0.0.0/0.0.0.0, excluded;IP:::/::
authorityInfoAccess=caIssuers;URI:http://crt.comodoca.com/COMODORSAAddTrustCA.crt, OCSP;URI:http://ocsp.comodoca.com
crlDistributionPoints=crlDistributionPoint0_sect
certificatePolicies=ia5org,1.2.840.113741.1.5.1.105.1, 2.23.140.1.2.2
extendedKeyUsage=serverAuth, clientAuth
basicConstraints=critical,CA:TRUE,pathlen:0
keyUsage=critical,digitalSignature, keyCertSign, cRLSign
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid, issuer
[crlDistributionPoint0_sect]
fullname=URI:http://crl.comodoca.com/COMODORSACertificationAuthority.crl
[nameConstraints_106_dirname]
0.C=US
1.ST=CA
2.L=Santa Clara
3.O=Intel Corporation
######################################################
> and ca must contain eku (clientauth, serverauth ...etc), for what ca is allowed sign client certificates.
name constraints has nothing to do with EKU, CDP and AIA extensions at all. These are different pieces of chain building and revocation checking.
@Igor Ukraine, I need to check the diagram again. This point is a bit weird.
https://cabforum.org/wp-content/uploads/CA-Browser-Forum-BR-1.5.6.pdf
page46
...
For a Subordinate CA Certificate to be considered Technically Constrained, the certificate MUST include an Extended Key Usage (EKU) extension specifying all extended key usages that the Subordinate CA Certificate is authorized to issue certificates for. The anyExtendedKeyUsage KeyPurposeId MUST NOT appear within this extension
...
@karlo, I still believe that you are talking about different use cases which are not subjects of this article. Article is about X509 Name Constraints extension and EKU, CAB forum has nothing to do with it.
i know that song strange.
but before using nameConstraints, user must have answear to question.
why you should use this extension??
nameConstraints main essence is "restriction". if you decide to use this, then you have resource to must restrict access.
We've found the format above does not seem to work on a standalone Microsoft Server 2016 (we have not tested with a domain joined CA or other versions of the Microsoft OS) when adding Name Constraints for signing a request for a subordinate CA. When using the above format, and running the command:
certreq -policy <input.csr> policy.inf <output.csr>
The command will appear to complete successfully, but the Name Constraints value in the certificate itself will not appear correctly populated. However, if you use the older/alternate format, it works perfectly:
[Strings]
szOID_NAME_CONSTRAINTS = "2.5.29.30"
[Extensions]
Critical = %szOID_NAME_CONSTRAINTS%
%szOID_NAME_CONSTRAINTS% = "{text}"
_continue_ = "SubTree=Include&"
_continue_ = "DNS = contoso.com&"
_continue_ = "DNS = .contoso.com&"
_continue_ = "SubTree=Exclude&"
_continue_ = "DNS = test.com&"
_continue_ = "IPAddress = "192.168.0.0", "255.255.255.0"&"
_continue_ = "IPAddress = "1234:5678:9abc:def0:3210:7654:ba98:fedc","1234:5678:9abc:def0:3210:7654:ba98:fedc"&"
I hope this helps somebody.
Hello Vadims,
you wrote "When empty entry appears in excluded subtree, the meaning is different. It explicitly disallows any namespaces of that type..."
Can you please remind us where exactly is that specified in RFC5280 (or any other RFC) ? I cannot find the relevant wording...
Thank you.
DNS = contoso.com ; allows *.contoso.com, for example, www.contoso.com
DNS = .contoso.com ; allows subdomains: www.sub.contoso.com
Using a . prefix is not defined in the specs for DNS... only for URI which is defined differently. '.' is used for URI but DNS doesn't have such feature defined. centoso.com for DNS means centoso.com and any number of names appended to the left of it.
The DNS definition is below for RFC5280.
"DNS name restrictions are expressed as host.example.com. Any DNS name that can be constructed by simply adding zero or more labels to the left-hand side of the name satisfies the name constraint. For example, www.host.example.com would satisfy the constraint but host1.example.com would not."
Do you include the '.' because of some bad implementations not following the RFC or was there a newer one that redefined it?
> Do you include the '.' because of some bad implementations not following the RFC or was there a newer one that redefined it?
In my opinion, this was overlooked in RFC: RFC explicitly permits wildcards for all name types, but not for dnsName? Although leading period syntax is not explicitly permitted by RFC, it is not prohibited, so this is up to implementer interpretation. And implementer reasoning was somewhat expected: if not explicitly prohibited, the standard could be extended. Reasoning is backed by this statement:
> Any DNS name that can be constructed by simply adding zero or more labels to the left-hand side of the name satisfies the name constraint.
And leading period syntax is required to satisfy this statement, because dot itself is not valid character for DNS label. This syntax was eventually adopted by all major X.509 profile implementations and actually is a de-facto standard. I don't see any issues with it.
Hello,
Is it possible to add name constraint in C#? I have not found any means to do so!
> Is it possible to add name constraint in C#? I have not found any means to do so!
Not with built-in SDK. With the use of 3rd party packages it is possible. For example, my SysadminsLV.PKI package has managed class for this extension: X509NameConstraintsExtension Class
Post your comment:
Comments: