requestedEKUs []ExtKeyUsage
expectedError string
noOpenSSL bool
+ ignoreCN bool
}
type constraintsSpec struct {
cn: "foo.bar",
},
},
+
+ // #85: without SANs, a certificate with a valid CN is accepted in a
+ // constrained chain if x509ignoreCN is set.
+ nameConstraintsTest{
+ roots: []constraintsSpec{
+ constraintsSpec{
+ ok: []string{"dns:foo.com", "dns:.foo.com"},
+ },
+ },
+ intermediates: [][]constraintsSpec{
+ []constraintsSpec{
+ constraintsSpec{},
+ },
+ },
+ leaf: leafSpec{
+ sans: []string{},
+ cn: "foo.com",
+ },
+ ignoreCN: true,
+ },
}
func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
}
func TestConstraintCases(t *testing.T) {
+ defer func(savedIgnoreCN bool) {
+ ignoreCN = savedIgnoreCN
+ }(ignoreCN)
+
privateKeys := sync.Pool{
New: func() interface{} {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
}
}
+ ignoreCN = test.ignoreCN
verifyOpts := VerifyOptions{
Roots: rootPool,
Intermediates: intermediatePool,
"fmt"
"net"
"net/url"
+ "os"
"reflect"
"runtime"
"strings"
"unicode/utf8"
)
+// ignoreCN disables interpreting Common Name as a hostname. See issue 24151.
+var ignoreCN = strings.Contains(os.Getenv("GODEBUG"), "x509ignoreCN=1")
+
type InvalidReason int
const (
// contain a Subject Alternative Name extension, but a CA certificate
// contains name constraints, and the Common Name can be interpreted as
// a hostname.
+ //
+ // You can avoid this error by setting the experimental GODEBUG environment
+ // variable to "x509ignoreCN=1", disabling Common Name matching entirely.
+ // This behavior might become the default in the future.
NameConstraintsWithoutSANs
// UnconstrainedName results when a CA certificate contains permitted
// name constraints, but leaf certificate contains a name of an
// constraints if there is no risk the CN would be matched as a hostname.
// See NameConstraintsWithoutSANs and issue 24151.
func (c *Certificate) commonNameAsHostname() bool {
- return !c.hasSANExtension() && validHostname(c.Subject.CommonName)
+ return !ignoreCN && !c.hasSANExtension() && validHostname(c.Subject.CommonName)
}
func matchHostnames(pattern, host string) bool {
keyUsages []ExtKeyUsage
testSystemRootsError bool
sha2 bool
+ ignoreCN bool
errorCallback func(*testing.T, int, error) bool
expectedChains [][]string
{"foo.example.com", "Test root"},
},
},
+ // Replicate CN tests with ignoreCN = true
+ {
+ leaf: ignoreCNWithSANLeaf,
+ dnsName: "foo.example.com",
+ roots: []string{ignoreCNWithSANRoot},
+ currentTime: 1486684488,
+ systemSkip: true,
+ ignoreCN: true,
+
+ errorCallback: expectHostnameError("certificate is not valid for any names"),
+ },
+ {
+ leaf: invalidCNWithoutSAN,
+ dnsName: "foo,invalid",
+ roots: []string{invalidCNRoot},
+ currentTime: 1540000000,
+ systemSkip: true,
+ ignoreCN: true,
+
+ errorCallback: expectHostnameError("Common Name is not a valid hostname"),
+ },
+ {
+ leaf: validCNWithoutSAN,
+ dnsName: "foo.example.com",
+ roots: []string{invalidCNRoot},
+ currentTime: 1540000000,
+ systemSkip: true,
+ ignoreCN: true,
+
+ errorCallback: expectHostnameError("not valid for any names"),
+ },
}
func expectHostnameError(msg string) func(*testing.T, int, error) bool {
}
func testVerify(t *testing.T, useSystemRoots bool) {
+ defer func(savedIgnoreCN bool) {
+ ignoreCN = savedIgnoreCN
+ }(ignoreCN)
for i, test := range verifyTests {
if useSystemRoots && test.systemSkip {
continue
continue
}
+ ignoreCN = test.ignoreCN
opts := VerifyOptions{
Intermediates: NewCertPool(),
DNSName: test.dnsName,