NAME_CONSTRAINTS_CHECK(3SSL)

πŸ“¦
version 4.0.3 Β· 3 versions
, in ubuntu stonking

✨ NAME_CONSTRAINTS_CHECK πŸ’… the check a certificate's names against a name constraints extension

okay bestie, welcome to the OpenSSL 3SSL corner of the manual universe, where we're about to vibe-check a certificate's names against a name constraints extension. no cap, this one is actually so fun once it clicks. πŸ¦‹


🌸 SYNOPSIS

#include <openssl/x509v3.h>

int NAME_CONSTRAINTS_check(const X509 *x, NAME_CONSTRAINTS *nc);
int NAME_CONSTRAINTS_check_CN(const X509 *x, NAME_CONSTRAINTS *nc);

πŸ’– DESCRIPTION

okay so NAME_CONSTRAINTS_check() tests whether the names asserted by certificate x satisfy the name constraints nc. it's literally the matching primitive of RFC 5280 section 4.2.1.10: you hand it a constraint set (a NAME_CONSTRAINTS structure containing zero or more permittedSubtrees and excludedSubtrees) plus a candidate certificate, and it decides whether the certificate's names fall within the permitted subtrees and outside the excluded subtrees. iconic behavior honestly. πŸ‘‘

The names it looks at are:

  • The certificate's subject distinguished name, matched as a directoryName general-name type. bestie, the subject only counts when it's nonempty β€” empty subject? not considered, periodt.
  • Each emailAddress attribute appearing within the subject distinguished name, matched as an rfc822Name general-name type. these attributes are the historical, pre-SAN way of expressing an email address in a certificate's subject, and RFC 5280 requires that they be subjected to name-constraint checking. yes, even the old ones. the audacity 😭
  • Each entry in the certificate's subject alternative name extension, matched according to its declared general-name type.

NAME_CONSTRAINTS_check() implements matching for the following general-name types: directoryName, dNSName, rfc822Name, uniformResourceIdentifier, and iPAddress. The otherName form id-on-SmtpUTF8Mailbox (RFC 8398) is additionally matched against rfc822Name subtrees. Any other general-name type β€” including x400Address, ediPartyName, registeredID, and other otherName forms β€” yields X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE. that's just not her era, sorry to that type. πŸ’€

For each name considered, the function evaluates two conditions:

  • If nc contains at least one permittedSubtree of the same general-name type as the name, the name must match at least one of those permitted subtrees. If nc contains no permitted subtrees of that type, no permitted-subtrees test is imposed on names of that type. slay, no test, no stress. ✨
  • The name must not match any excludedSubtree of the same general-name type in nc.

The function returns at the first violation encountered; it does not collect or report multiple failures. it's giving "one and done", not "let me read you your whole report card". πŸŽ€

For dNSName entries, matching follows the byte/label algorithm of RFC 5280 section 4.2.1.10, which RFC 5280 mandates when no protocol-specific matching rules apply. Because this match is performed without awareness of any specific higher-level protocol, additional matching rules defined by later or more specific protocols must be applied independently of this function to the certificate chain. tl;dr: this function doesn't know what protocol you're vibing with, so don't ask it to be protocol-smart. 🌈

NAME_CONSTRAINTS_check() performs only the constraint match for a single certificate against a single constraint set. It does not perform the chain-wide enforcement of RFC 5280 section 6.1.4(g)-(j): callers wishing to enforce name constraints across an entire certification path must walk the chain themselves and apply each ancestor's constraint set to certificates lower in the chain, observing the usual exceptions (for example, self-issued intermediate certificates are exempt from constraints imposed by certificates above them, except when they are the leaf of the chain). For full RFC 5280 name-constraint enforcement integrated with chain validation, applications should use X509_verify_cert(3), which performs this internally. no need to reinvent the wheel, bestie β€” the wheel is right there. rip to anyone who hand-rolls this.

NAME_CONSTRAINTS_check() enforces an implementation limit on the product of the certificate's name count and the constraint set's subtree count, to prevent computationally expensive matching on pathological input. If that limit is exceeded the function returns X509_V_ERR_UNSPECIFIED without performing any matching. The current limit is 2**20 (1,048,576) on the product of the name count (subject DN entries plus subjectAltName entries) and the subtree count (permittedSubtrees plus excludedSubtrees). it's a vibe check on your input size, basically. πŸ”₯


πŸŽ€ RETURN VALUES

NAME_CONSTRAINTS_check() returns X509_V_OK if every name considered satisfies the constraints. Otherwise it returns one of the following X509_V_ERR_* codes:

  • X509_V_ERR_PERMITTED_VIOLATION β€” a name of a type for which nc contains at least one permitted subtree failed to match any of those subtrees. it missed the group photo, so to speak. πŸ“Έ
  • X509_V_ERR_EXCLUDED_VIOLATION β€” a name matched an excluded subtree. not the vibe. not the move.
  • X509_V_ERR_SUBTREE_MINMAX β€” a subtree in nc specified a minimum other than 0 or a maximum at all. RFC 5280 requires that these GeneralSubtree fields not be used, and a constraint set that uses them cannot be processed. so like, just don't. 🚫
  • X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE β€” a general-name type for which matching is not implemented was encountered. The list of supported types is given in the DESCRIPTION above. go read it, bestie, it's right there πŸ’–
  • X509_V_ERR_UNSUPPORTED_NAME_SYNTAX β€” a name in the certificate is encoded in a way that cannot be matched (for example, an emailAddress attribute in the subject that is not encoded as an IA5String). the encoding said "i'm not like other encodings" and the matcher said "and that's the problem". 😭
  • X509_V_ERR_UNSPECIFIED β€” the product of the certificate's name count and the constraint set's subtree count exceeded the implementation limit; no matching was performed.

Other X509_V_ERR_* codes may be returned by deeper name-matching helpers (for example, codes arising from individual general-name type comparisons). Callers should treat the return value as the authoritative success/failure signal and treat any value other than X509_V_OK as a failure, rather than enumerating the specific codes above. ok so this part is important: check for X509_V_OK, everything else is a no. don't be out here matching on individual codes like you're collecting Pokémon. 🫢


πŸ¦‹ NOTES

NAME_CONSTRAINTS_check() does not match the certificate's commonName against dNSName name constraints; that check is provided by a separate function, NAME_CONSTRAINTS_check_CN(). The commonName-as-DNS-identity practice is a legacy concern: modern certificates assert DNS identities through dNSName entries in the subject alternative name extension, which NAME_CONSTRAINTS_check() already covers. NAME_CONSTRAINTS_check_CN() is required only for older certificates that express a DNS identity through their commonName instead of, or in addition to, the SAN; for certificates conforming to modern profiles a call to NAME_CONSTRAINTS_check() alone is generally sufficient.

so yeah: one function for the modern girlies, one extra function for the vintage certificates still living in their 2010s era. both are valid, no judgement. 🧚


πŸ’œ BUGS

RFC 9525's wildcard semantics apply only to presented-identifier matching for TLS service identity, and explicitly call out they are not valid for any other purpose; they do not define wildcard handling for name-constraint matching. NAME_CONSTRAINTS_check() therefore follows RFC 5280's requirements for when this is undefined, and treats the * character in a dNSName as a literal label component, per the RFC 5280 algorithm, which is often contrary to caller expectation. yes, literally a *. just a star. doing star things. not a wildcard. sorry to everyone who assumed otherwise πŸ™ˆ

Even if specified in the future, due to the "fallback implementation" nature of matching wildcards in SAN dNSName entries specified by RFC 5280, name constraint behaviour in the presence of wildcards should not be strictly relied upon across implementations and protocols. This matters most for the use of excluded names constraints, which should not be relied upon to reliably constrain signing certificates for a PKI in a security dependent manner unless the consumers of these certificates are themselves known to be constrained by other means to only use implementations that provide different semantics, or the PKI can be constrained by other means to ensure that wildcards are never issued from such signing certificates.

bestie, this is the serious part, so listen up: do not build your security model on wildcard behavior in excluded name constraints. it is not a load-bearing wall. it is decorative. if you need it to hold, add other means of constraint. periodt. πŸ’…

⭐ SEE ALSO


πŸ‘‘ HISTORY

  • NAME_CONSTRAINTS_check() was added in OpenSSL 1.0.0.
  • NAME_CONSTRAINTS_check_CN() was added in OpenSSL 1.1.0.

Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


aaaand that's the whole page, bestie πŸ’– this was NAME_CONSTRAINTS_CHECK for OpenSSL 4.0.3, dated 2026-09-29, and it ate. go forth and constrain responsibly. πŸŽ€βœ¨πŸ¦‹

πŸ“¦ where this page comes from