...

Source file src/crypto/x509/verify.go

     1	// Copyright 2011 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package x509
     6	
     7	import (
     8		"bytes"
     9		"errors"
    10		"fmt"
    11		"net"
    12		"net/url"
    13		"os"
    14		"reflect"
    15		"runtime"
    16		"strings"
    17		"time"
    18		"unicode/utf8"
    19	)
    20	
    21	// ignoreCN disables interpreting Common Name as a hostname. See issue 24151.
    22	var ignoreCN = strings.Contains(os.Getenv("GODEBUG"), "x509ignoreCN=1")
    23	
    24	type InvalidReason int
    25	
    26	const (
    27		// NotAuthorizedToSign results when a certificate is signed by another
    28		// which isn't marked as a CA certificate.
    29		NotAuthorizedToSign InvalidReason = iota
    30		// Expired results when a certificate has expired, based on the time
    31		// given in the VerifyOptions.
    32		Expired
    33		// CANotAuthorizedForThisName results when an intermediate or root
    34		// certificate has a name constraint which doesn't permit a DNS or
    35		// other name (including IP address) in the leaf certificate.
    36		CANotAuthorizedForThisName
    37		// TooManyIntermediates results when a path length constraint is
    38		// violated.
    39		TooManyIntermediates
    40		// IncompatibleUsage results when the certificate's key usage indicates
    41		// that it may only be used for a different purpose.
    42		IncompatibleUsage
    43		// NameMismatch results when the subject name of a parent certificate
    44		// does not match the issuer name in the child.
    45		NameMismatch
    46		// NameConstraintsWithoutSANs results when a leaf certificate doesn't
    47		// contain a Subject Alternative Name extension, but a CA certificate
    48		// contains name constraints, and the Common Name can be interpreted as
    49		// a hostname.
    50		//
    51		// You can avoid this error by setting the experimental GODEBUG environment
    52		// variable to "x509ignoreCN=1", disabling Common Name matching entirely.
    53		// This behavior might become the default in the future.
    54		NameConstraintsWithoutSANs
    55		// UnconstrainedName results when a CA certificate contains permitted
    56		// name constraints, but leaf certificate contains a name of an
    57		// unsupported or unconstrained type.
    58		UnconstrainedName
    59		// TooManyConstraints results when the number of comparison operations
    60		// needed to check a certificate exceeds the limit set by
    61		// VerifyOptions.MaxConstraintComparisions. This limit exists to
    62		// prevent pathological certificates can consuming excessive amounts of
    63		// CPU time to verify.
    64		TooManyConstraints
    65		// CANotAuthorizedForExtKeyUsage results when an intermediate or root
    66		// certificate does not permit a requested extended key usage.
    67		CANotAuthorizedForExtKeyUsage
    68	)
    69	
    70	// CertificateInvalidError results when an odd error occurs. Users of this
    71	// library probably want to handle all these errors uniformly.
    72	type CertificateInvalidError struct {
    73		Cert   *Certificate
    74		Reason InvalidReason
    75		Detail string
    76	}
    77	
    78	func (e CertificateInvalidError) Error() string {
    79		switch e.Reason {
    80		case NotAuthorizedToSign:
    81			return "x509: certificate is not authorized to sign other certificates"
    82		case Expired:
    83			return "x509: certificate has expired or is not yet valid"
    84		case CANotAuthorizedForThisName:
    85			return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e.Detail
    86		case CANotAuthorizedForExtKeyUsage:
    87			return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e.Detail
    88		case TooManyIntermediates:
    89			return "x509: too many intermediates for path length constraint"
    90		case IncompatibleUsage:
    91			return "x509: certificate specifies an incompatible key usage"
    92		case NameMismatch:
    93			return "x509: issuer name does not match subject from issuing certificate"
    94		case NameConstraintsWithoutSANs:
    95			return "x509: issuer has name constraints but leaf doesn't have a SAN extension"
    96		case UnconstrainedName:
    97			return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e.Detail
    98		}
    99		return "x509: unknown error"
   100	}
   101	
   102	// HostnameError results when the set of authorized names doesn't match the
   103	// requested name.
   104	type HostnameError struct {
   105		Certificate *Certificate
   106		Host        string
   107	}
   108	
   109	func (h HostnameError) Error() string {
   110		c := h.Certificate
   111	
   112		if !c.hasSANExtension() && !validHostname(c.Subject.CommonName) &&
   113			matchHostnames(toLowerCaseASCII(c.Subject.CommonName), toLowerCaseASCII(h.Host)) {
   114			// This would have validated, if it weren't for the validHostname check on Common Name.
   115			return "x509: Common Name is not a valid hostname: " + c.Subject.CommonName
   116		}
   117	
   118		var valid string
   119		if ip := net.ParseIP(h.Host); ip != nil {
   120			// Trying to validate an IP
   121			if len(c.IPAddresses) == 0 {
   122				return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
   123			}
   124			for _, san := range c.IPAddresses {
   125				if len(valid) > 0 {
   126					valid += ", "
   127				}
   128				valid += san.String()
   129			}
   130		} else {
   131			if c.commonNameAsHostname() {
   132				valid = c.Subject.CommonName
   133			} else {
   134				valid = strings.Join(c.DNSNames, ", ")
   135			}
   136		}
   137	
   138		if len(valid) == 0 {
   139			return "x509: certificate is not valid for any names, but wanted to match " + h.Host
   140		}
   141		return "x509: certificate is valid for " + valid + ", not " + h.Host
   142	}
   143	
   144	// UnknownAuthorityError results when the certificate issuer is unknown
   145	type UnknownAuthorityError struct {
   146		Cert *Certificate
   147		// hintErr contains an error that may be helpful in determining why an
   148		// authority wasn't found.
   149		hintErr error
   150		// hintCert contains a possible authority certificate that was rejected
   151		// because of the error in hintErr.
   152		hintCert *Certificate
   153	}
   154	
   155	func (e UnknownAuthorityError) Error() string {
   156		s := "x509: certificate signed by unknown authority"
   157		if e.hintErr != nil {
   158			certName := e.hintCert.Subject.CommonName
   159			if len(certName) == 0 {
   160				if len(e.hintCert.Subject.Organization) > 0 {
   161					certName = e.hintCert.Subject.Organization[0]
   162				} else {
   163					certName = "serial:" + e.hintCert.SerialNumber.String()
   164				}
   165			}
   166			s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
   167		}
   168		return s
   169	}
   170	
   171	// SystemRootsError results when we fail to load the system root certificates.
   172	type SystemRootsError struct {
   173		Err error
   174	}
   175	
   176	func (se SystemRootsError) Error() string {
   177		msg := "x509: failed to load system roots and no roots provided"
   178		if se.Err != nil {
   179			return msg + "; " + se.Err.Error()
   180		}
   181		return msg
   182	}
   183	
   184	// errNotParsed is returned when a certificate without ASN.1 contents is
   185	// verified. Platform-specific verification needs the ASN.1 contents.
   186	var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
   187	
   188	// VerifyOptions contains parameters for Certificate.Verify. It's a structure
   189	// because other PKIX verification APIs have ended up needing many options.
   190	type VerifyOptions struct {
   191		DNSName       string
   192		Intermediates *CertPool
   193		Roots         *CertPool // if nil, the system roots are used
   194		CurrentTime   time.Time // if zero, the current time is used
   195		// KeyUsage specifies which Extended Key Usage values are acceptable. A leaf
   196		// certificate is accepted if it contains any of the listed values. An empty
   197		// list means ExtKeyUsageServerAuth. To accept any key usage, include
   198		// ExtKeyUsageAny.
   199		//
   200		// Certificate chains are required to nest these extended key usage values.
   201		// (This matches the Windows CryptoAPI behavior, but not the spec.)
   202		KeyUsages []ExtKeyUsage
   203		// MaxConstraintComparisions is the maximum number of comparisons to
   204		// perform when checking a given certificate's name constraints. If
   205		// zero, a sensible default is used. This limit prevents pathological
   206		// certificates from consuming excessive amounts of CPU time when
   207		// validating.
   208		MaxConstraintComparisions int
   209	}
   210	
   211	const (
   212		leafCertificate = iota
   213		intermediateCertificate
   214		rootCertificate
   215	)
   216	
   217	// rfc2821Mailbox represents a “mailbox” (which is an email address to most
   218	// people) by breaking it into the “local” (i.e. before the '@') and “domain”
   219	// parts.
   220	type rfc2821Mailbox struct {
   221		local, domain string
   222	}
   223	
   224	// parseRFC2821Mailbox parses an email address into local and domain parts,
   225	// based on the ABNF for a “Mailbox” from RFC 2821. According to RFC 5280,
   226	// Section 4.2.1.6 that's correct for an rfc822Name from a certificate: “The
   227	// format of an rfc822Name is a "Mailbox" as defined in RFC 2821, Section 4.1.2”.
   228	func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) {
   229		if len(in) == 0 {
   230			return mailbox, false
   231		}
   232	
   233		localPartBytes := make([]byte, 0, len(in)/2)
   234	
   235		if in[0] == '"' {
   236			// Quoted-string = DQUOTE *qcontent DQUOTE
   237			// non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127
   238			// qcontent = qtext / quoted-pair
   239			// qtext = non-whitespace-control /
   240			//         %d33 / %d35-91 / %d93-126
   241			// quoted-pair = ("\" text) / obs-qp
   242			// text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text
   243			//
   244			// (Names beginning with “obs-” are the obsolete syntax from RFC 2822,
   245			// Section 4. Since it has been 16 years, we no longer accept that.)
   246			in = in[1:]
   247		QuotedString:
   248			for {
   249				if len(in) == 0 {
   250					return mailbox, false
   251				}
   252				c := in[0]
   253				in = in[1:]
   254	
   255				switch {
   256				case c == '"':
   257					break QuotedString
   258	
   259				case c == '\\':
   260					// quoted-pair
   261					if len(in) == 0 {
   262						return mailbox, false
   263					}
   264					if in[0] == 11 ||
   265						in[0] == 12 ||
   266						(1 <= in[0] && in[0] <= 9) ||
   267						(14 <= in[0] && in[0] <= 127) {
   268						localPartBytes = append(localPartBytes, in[0])
   269						in = in[1:]
   270					} else {
   271						return mailbox, false
   272					}
   273	
   274				case c == 11 ||
   275					c == 12 ||
   276					// Space (char 32) is not allowed based on the
   277					// BNF, but RFC 3696 gives an example that
   278					// assumes that it is. Several “verified”
   279					// errata continue to argue about this point.
   280					// We choose to accept it.
   281					c == 32 ||
   282					c == 33 ||
   283					c == 127 ||
   284					(1 <= c && c <= 8) ||
   285					(14 <= c && c <= 31) ||
   286					(35 <= c && c <= 91) ||
   287					(93 <= c && c <= 126):
   288					// qtext
   289					localPartBytes = append(localPartBytes, c)
   290	
   291				default:
   292					return mailbox, false
   293				}
   294			}
   295		} else {
   296			// Atom ("." Atom)*
   297		NextChar:
   298			for len(in) > 0 {
   299				// atext from RFC 2822, Section 3.2.4
   300				c := in[0]
   301	
   302				switch {
   303				case c == '\\':
   304					// Examples given in RFC 3696 suggest that
   305					// escaped characters can appear outside of a
   306					// quoted string. Several “verified” errata
   307					// continue to argue the point. We choose to
   308					// accept it.
   309					in = in[1:]
   310					if len(in) == 0 {
   311						return mailbox, false
   312					}
   313					fallthrough
   314	
   315				case ('0' <= c && c <= '9') ||
   316					('a' <= c && c <= 'z') ||
   317					('A' <= c && c <= 'Z') ||
   318					c == '!' || c == '#' || c == '$' || c == '%' ||
   319					c == '&' || c == '\'' || c == '*' || c == '+' ||
   320					c == '-' || c == '/' || c == '=' || c == '?' ||
   321					c == '^' || c == '_' || c == '`' || c == '{' ||
   322					c == '|' || c == '}' || c == '~' || c == '.':
   323					localPartBytes = append(localPartBytes, in[0])
   324					in = in[1:]
   325	
   326				default:
   327					break NextChar
   328				}
   329			}
   330	
   331			if len(localPartBytes) == 0 {
   332				return mailbox, false
   333			}
   334	
   335			// From RFC 3696, Section 3:
   336			// “period (".") may also appear, but may not be used to start
   337			// or end the local part, nor may two or more consecutive
   338			// periods appear.”
   339			twoDots := []byte{'.', '.'}
   340			if localPartBytes[0] == '.' ||
   341				localPartBytes[len(localPartBytes)-1] == '.' ||
   342				bytes.Contains(localPartBytes, twoDots) {
   343				return mailbox, false
   344			}
   345		}
   346	
   347		if len(in) == 0 || in[0] != '@' {
   348			return mailbox, false
   349		}
   350		in = in[1:]
   351	
   352		// The RFC species a format for domains, but that's known to be
   353		// violated in practice so we accept that anything after an '@' is the
   354		// domain part.
   355		if _, ok := domainToReverseLabels(in); !ok {
   356			return mailbox, false
   357		}
   358	
   359		mailbox.local = string(localPartBytes)
   360		mailbox.domain = in
   361		return mailbox, true
   362	}
   363	
   364	// domainToReverseLabels converts a textual domain name like foo.example.com to
   365	// the list of labels in reverse order, e.g. ["com", "example", "foo"].
   366	func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) {
   367		for len(domain) > 0 {
   368			if i := strings.LastIndexByte(domain, '.'); i == -1 {
   369				reverseLabels = append(reverseLabels, domain)
   370				domain = ""
   371			} else {
   372				reverseLabels = append(reverseLabels, domain[i+1:])
   373				domain = domain[:i]
   374			}
   375		}
   376	
   377		if len(reverseLabels) > 0 && len(reverseLabels[0]) == 0 {
   378			// An empty label at the end indicates an absolute value.
   379			return nil, false
   380		}
   381	
   382		for _, label := range reverseLabels {
   383			if len(label) == 0 {
   384				// Empty labels are otherwise invalid.
   385				return nil, false
   386			}
   387	
   388			for _, c := range label {
   389				if c < 33 || c > 126 {
   390					// Invalid character.
   391					return nil, false
   392				}
   393			}
   394		}
   395	
   396		return reverseLabels, true
   397	}
   398	
   399	func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) {
   400		// If the constraint contains an @, then it specifies an exact mailbox
   401		// name.
   402		if strings.Contains(constraint, "@") {
   403			constraintMailbox, ok := parseRFC2821Mailbox(constraint)
   404			if !ok {
   405				return false, fmt.Errorf("x509: internal error: cannot parse constraint %q", constraint)
   406			}
   407			return mailbox.local == constraintMailbox.local && strings.EqualFold(mailbox.domain, constraintMailbox.domain), nil
   408		}
   409	
   410		// Otherwise the constraint is like a DNS constraint of the domain part
   411		// of the mailbox.
   412		return matchDomainConstraint(mailbox.domain, constraint)
   413	}
   414	
   415	func matchURIConstraint(uri *url.URL, constraint string) (bool, error) {
   416		// From RFC 5280, Section 4.2.1.10:
   417		// “a uniformResourceIdentifier that does not include an authority
   418		// component with a host name specified as a fully qualified domain
   419		// name (e.g., if the URI either does not include an authority
   420		// component or includes an authority component in which the host name
   421		// is specified as an IP address), then the application MUST reject the
   422		// certificate.”
   423	
   424		host := uri.Host
   425		if len(host) == 0 {
   426			return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", uri.String())
   427		}
   428	
   429		if strings.Contains(host, ":") && !strings.HasSuffix(host, "]") {
   430			var err error
   431			host, _, err = net.SplitHostPort(uri.Host)
   432			if err != nil {
   433				return false, err
   434			}
   435		}
   436	
   437		if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") ||
   438			net.ParseIP(host) != nil {
   439			return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
   440		}
   441	
   442		return matchDomainConstraint(host, constraint)
   443	}
   444	
   445	func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
   446		if len(ip) != len(constraint.IP) {
   447			return false, nil
   448		}
   449	
   450		for i := range ip {
   451			if mask := constraint.Mask[i]; ip[i]&mask != constraint.IP[i]&mask {
   452				return false, nil
   453			}
   454		}
   455	
   456		return true, nil
   457	}
   458	
   459	func matchDomainConstraint(domain, constraint string) (bool, error) {
   460		// The meaning of zero length constraints is not specified, but this
   461		// code follows NSS and accepts them as matching everything.
   462		if len(constraint) == 0 {
   463			return true, nil
   464		}
   465	
   466		domainLabels, ok := domainToReverseLabels(domain)
   467		if !ok {
   468			return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain)
   469		}
   470	
   471		// RFC 5280 says that a leading period in a domain name means that at
   472		// least one label must be prepended, but only for URI and email
   473		// constraints, not DNS constraints. The code also supports that
   474		// behaviour for DNS constraints.
   475	
   476		mustHaveSubdomains := false
   477		if constraint[0] == '.' {
   478			mustHaveSubdomains = true
   479			constraint = constraint[1:]
   480		}
   481	
   482		constraintLabels, ok := domainToReverseLabels(constraint)
   483		if !ok {
   484			return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint)
   485		}
   486	
   487		if len(domainLabels) < len(constraintLabels) ||
   488			(mustHaveSubdomains && len(domainLabels) == len(constraintLabels)) {
   489			return false, nil
   490		}
   491	
   492		for i, constraintLabel := range constraintLabels {
   493			if !strings.EqualFold(constraintLabel, domainLabels[i]) {
   494				return false, nil
   495			}
   496		}
   497	
   498		return true, nil
   499	}
   500	
   501	// checkNameConstraints checks that c permits a child certificate to claim the
   502	// given name, of type nameType. The argument parsedName contains the parsed
   503	// form of name, suitable for passing to the match function. The total number
   504	// of comparisons is tracked in the given count and should not exceed the given
   505	// limit.
   506	func (c *Certificate) checkNameConstraints(count *int,
   507		maxConstraintComparisons int,
   508		nameType string,
   509		name string,
   510		parsedName interface{},
   511		match func(parsedName, constraint interface{}) (match bool, err error),
   512		permitted, excluded interface{}) error {
   513	
   514		excludedValue := reflect.ValueOf(excluded)
   515	
   516		*count += excludedValue.Len()
   517		if *count > maxConstraintComparisons {
   518			return CertificateInvalidError{c, TooManyConstraints, ""}
   519		}
   520	
   521		for i := 0; i < excludedValue.Len(); i++ {
   522			constraint := excludedValue.Index(i).Interface()
   523			match, err := match(parsedName, constraint)
   524			if err != nil {
   525				return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
   526			}
   527	
   528			if match {
   529				return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", nameType, name, constraint)}
   530			}
   531		}
   532	
   533		permittedValue := reflect.ValueOf(permitted)
   534	
   535		*count += permittedValue.Len()
   536		if *count > maxConstraintComparisons {
   537			return CertificateInvalidError{c, TooManyConstraints, ""}
   538		}
   539	
   540		ok := true
   541		for i := 0; i < permittedValue.Len(); i++ {
   542			constraint := permittedValue.Index(i).Interface()
   543	
   544			var err error
   545			if ok, err = match(parsedName, constraint); err != nil {
   546				return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
   547			}
   548	
   549			if ok {
   550				break
   551			}
   552		}
   553	
   554		if !ok {
   555			return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", nameType, name)}
   556		}
   557	
   558		return nil
   559	}
   560	
   561	// isValid performs validity checks on c given that it is a candidate to append
   562	// to the chain in currentChain.
   563	func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
   564		if len(c.UnhandledCriticalExtensions) > 0 {
   565			return UnhandledCriticalExtension{}
   566		}
   567	
   568		if len(currentChain) > 0 {
   569			child := currentChain[len(currentChain)-1]
   570			if !bytes.Equal(child.RawIssuer, c.RawSubject) {
   571				return CertificateInvalidError{c, NameMismatch, ""}
   572			}
   573		}
   574	
   575		now := opts.CurrentTime
   576		if now.IsZero() {
   577			now = time.Now()
   578		}
   579		if now.Before(c.NotBefore) || now.After(c.NotAfter) {
   580			return CertificateInvalidError{c, Expired, ""}
   581		}
   582	
   583		maxConstraintComparisons := opts.MaxConstraintComparisions
   584		if maxConstraintComparisons == 0 {
   585			maxConstraintComparisons = 250000
   586		}
   587		comparisonCount := 0
   588	
   589		var leaf *Certificate
   590		if certType == intermediateCertificate || certType == rootCertificate {
   591			if len(currentChain) == 0 {
   592				return errors.New("x509: internal error: empty chain when appending CA cert")
   593			}
   594			leaf = currentChain[0]
   595		}
   596	
   597		checkNameConstraints := (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints()
   598		if checkNameConstraints && leaf.commonNameAsHostname() {
   599			// This is the deprecated, legacy case of depending on the commonName as
   600			// a hostname. We don't enforce name constraints against the CN, but
   601			// VerifyHostname will look for hostnames in there if there are no SANs.
   602			// In order to ensure VerifyHostname will not accept an unchecked name,
   603			// return an error here.
   604			return CertificateInvalidError{c, NameConstraintsWithoutSANs, ""}
   605		} else if checkNameConstraints && leaf.hasSANExtension() {
   606			err := forEachSAN(leaf.getSANExtension(), func(tag int, data []byte) error {
   607				switch tag {
   608				case nameTypeEmail:
   609					name := string(data)
   610					mailbox, ok := parseRFC2821Mailbox(name)
   611					if !ok {
   612						return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox)
   613					}
   614	
   615					if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
   616						func(parsedName, constraint interface{}) (bool, error) {
   617							return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string))
   618						}, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil {
   619						return err
   620					}
   621	
   622				case nameTypeDNS:
   623					name := string(data)
   624					if _, ok := domainToReverseLabels(name); !ok {
   625						return fmt.Errorf("x509: cannot parse dnsName %q", name)
   626					}
   627	
   628					if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
   629						func(parsedName, constraint interface{}) (bool, error) {
   630							return matchDomainConstraint(parsedName.(string), constraint.(string))
   631						}, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil {
   632						return err
   633					}
   634	
   635				case nameTypeURI:
   636					name := string(data)
   637					uri, err := url.Parse(name)
   638					if err != nil {
   639						return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name)
   640					}
   641	
   642					if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri,
   643						func(parsedName, constraint interface{}) (bool, error) {
   644							return matchURIConstraint(parsedName.(*url.URL), constraint.(string))
   645						}, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil {
   646						return err
   647					}
   648	
   649				case nameTypeIP:
   650					ip := net.IP(data)
   651					if l := len(ip); l != net.IPv4len && l != net.IPv6len {
   652						return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data)
   653					}
   654	
   655					if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip,
   656						func(parsedName, constraint interface{}) (bool, error) {
   657							return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet))
   658						}, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil {
   659						return err
   660					}
   661	
   662				default:
   663					// Unknown SAN types are ignored.
   664				}
   665	
   666				return nil
   667			})
   668	
   669			if err != nil {
   670				return err
   671			}
   672		}
   673	
   674		// KeyUsage status flags are ignored. From Engineering Security, Peter
   675		// Gutmann: A European government CA marked its signing certificates as
   676		// being valid for encryption only, but no-one noticed. Another
   677		// European CA marked its signature keys as not being valid for
   678		// signatures. A different CA marked its own trusted root certificate
   679		// as being invalid for certificate signing. Another national CA
   680		// distributed a certificate to be used to encrypt data for the
   681		// country’s tax authority that was marked as only being usable for
   682		// digital signatures but not for encryption. Yet another CA reversed
   683		// the order of the bit flags in the keyUsage due to confusion over
   684		// encoding endianness, essentially setting a random keyUsage in
   685		// certificates that it issued. Another CA created a self-invalidating
   686		// certificate by adding a certificate policy statement stipulating
   687		// that the certificate had to be used strictly as specified in the
   688		// keyUsage, and a keyUsage containing a flag indicating that the RSA
   689		// encryption key could only be used for Diffie-Hellman key agreement.
   690	
   691		if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
   692			return CertificateInvalidError{c, NotAuthorizedToSign, ""}
   693		}
   694	
   695		if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
   696			numIntermediates := len(currentChain) - 1
   697			if numIntermediates > c.MaxPathLen {
   698				return CertificateInvalidError{c, TooManyIntermediates, ""}
   699			}
   700		}
   701	
   702		return nil
   703	}
   704	
   705	// Verify attempts to verify c by building one or more chains from c to a
   706	// certificate in opts.Roots, using certificates in opts.Intermediates if
   707	// needed. If successful, it returns one or more chains where the first
   708	// element of the chain is c and the last element is from opts.Roots.
   709	//
   710	// If opts.Roots is nil and system roots are unavailable the returned error
   711	// will be of type SystemRootsError.
   712	//
   713	// Name constraints in the intermediates will be applied to all names claimed
   714	// in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim
   715	// example.com if an intermediate doesn't permit it, even if example.com is not
   716	// the name being validated. Note that DirectoryName constraints are not
   717	// supported.
   718	//
   719	// Extended Key Usage values are enforced down a chain, so an intermediate or
   720	// root that enumerates EKUs prevents a leaf from asserting an EKU not in that
   721	// list.
   722	//
   723	// WARNING: this function doesn't do any revocation checking.
   724	func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
   725		// Platform-specific verification needs the ASN.1 contents so
   726		// this makes the behavior consistent across platforms.
   727		if len(c.Raw) == 0 {
   728			return nil, errNotParsed
   729		}
   730		if opts.Intermediates != nil {
   731			for _, intermediate := range opts.Intermediates.certs {
   732				if len(intermediate.Raw) == 0 {
   733					return nil, errNotParsed
   734				}
   735			}
   736		}
   737	
   738		// Use Windows's own verification and chain building.
   739		if opts.Roots == nil && runtime.GOOS == "windows" {
   740			return c.systemVerify(&opts)
   741		}
   742	
   743		if opts.Roots == nil {
   744			opts.Roots = systemRootsPool()
   745			if opts.Roots == nil {
   746				return nil, SystemRootsError{systemRootsErr}
   747			}
   748		}
   749	
   750		err = c.isValid(leafCertificate, nil, &opts)
   751		if err != nil {
   752			return
   753		}
   754	
   755		if len(opts.DNSName) > 0 {
   756			err = c.VerifyHostname(opts.DNSName)
   757			if err != nil {
   758				return
   759			}
   760		}
   761	
   762		var candidateChains [][]*Certificate
   763		if opts.Roots.contains(c) {
   764			candidateChains = append(candidateChains, []*Certificate{c})
   765		} else {
   766			if candidateChains, err = c.buildChains(nil, []*Certificate{c}, nil, &opts); err != nil {
   767				return nil, err
   768			}
   769		}
   770	
   771		keyUsages := opts.KeyUsages
   772		if len(keyUsages) == 0 {
   773			keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
   774		}
   775	
   776		// If any key usage is acceptable then we're done.
   777		for _, usage := range keyUsages {
   778			if usage == ExtKeyUsageAny {
   779				return candidateChains, nil
   780			}
   781		}
   782	
   783		for _, candidate := range candidateChains {
   784			if checkChainForKeyUsage(candidate, keyUsages) {
   785				chains = append(chains, candidate)
   786			}
   787		}
   788	
   789		if len(chains) == 0 {
   790			return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
   791		}
   792	
   793		return chains, nil
   794	}
   795	
   796	func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
   797		n := make([]*Certificate, len(chain)+1)
   798		copy(n, chain)
   799		n[len(chain)] = cert
   800		return n
   801	}
   802	
   803	// maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls
   804	// that an invocation of buildChains will (tranistively) make. Most chains are
   805	// less than 15 certificates long, so this leaves space for multiple chains and
   806	// for failed checks due to different intermediates having the same Subject.
   807	const maxChainSignatureChecks = 100
   808	
   809	func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) {
   810		var (
   811			hintErr  error
   812			hintCert *Certificate
   813		)
   814	
   815		considerCandidate := func(certType int, candidate *Certificate) {
   816			for _, cert := range currentChain {
   817				if cert.Equal(candidate) {
   818					return
   819				}
   820			}
   821	
   822			if sigChecks == nil {
   823				sigChecks = new(int)
   824			}
   825			*sigChecks++
   826			if *sigChecks > maxChainSignatureChecks {
   827				err = errors.New("x509: signature check attempts limit reached while verifying certificate chain")
   828				return
   829			}
   830	
   831			if err := c.CheckSignatureFrom(candidate); err != nil {
   832				if hintErr == nil {
   833					hintErr = err
   834					hintCert = candidate
   835				}
   836				return
   837			}
   838	
   839			err = candidate.isValid(certType, currentChain, opts)
   840			if err != nil {
   841				return
   842			}
   843	
   844			switch certType {
   845			case rootCertificate:
   846				chains = append(chains, appendToFreshChain(currentChain, candidate))
   847			case intermediateCertificate:
   848				if cache == nil {
   849					cache = make(map[*Certificate][][]*Certificate)
   850				}
   851				childChains, ok := cache[candidate]
   852				if !ok {
   853					childChains, err = candidate.buildChains(cache, appendToFreshChain(currentChain, candidate), sigChecks, opts)
   854					cache[candidate] = childChains
   855				}
   856				chains = append(chains, childChains...)
   857			}
   858		}
   859	
   860		for _, rootNum := range opts.Roots.findPotentialParents(c) {
   861			considerCandidate(rootCertificate, opts.Roots.certs[rootNum])
   862		}
   863		for _, intermediateNum := range opts.Intermediates.findPotentialParents(c) {
   864			considerCandidate(intermediateCertificate, opts.Intermediates.certs[intermediateNum])
   865		}
   866	
   867		if len(chains) > 0 {
   868			err = nil
   869		}
   870		if len(chains) == 0 && err == nil {
   871			err = UnknownAuthorityError{c, hintErr, hintCert}
   872		}
   873	
   874		return
   875	}
   876	
   877	// validHostname reports whether host is a valid hostname that can be matched or
   878	// matched against according to RFC 6125 2.2, with some leniency to accommodate
   879	// legacy values.
   880	func validHostname(host string) bool {
   881		host = strings.TrimSuffix(host, ".")
   882	
   883		if len(host) == 0 {
   884			return false
   885		}
   886	
   887		for i, part := range strings.Split(host, ".") {
   888			if part == "" {
   889				// Empty label.
   890				return false
   891			}
   892			if i == 0 && part == "*" {
   893				// Only allow full left-most wildcards, as those are the only ones
   894				// we match, and matching literal '*' characters is probably never
   895				// the expected behavior.
   896				continue
   897			}
   898			for j, c := range part {
   899				if 'a' <= c && c <= 'z' {
   900					continue
   901				}
   902				if '0' <= c && c <= '9' {
   903					continue
   904				}
   905				if 'A' <= c && c <= 'Z' {
   906					continue
   907				}
   908				if c == '-' && j != 0 {
   909					continue
   910				}
   911				if c == '_' || c == ':' {
   912					// Not valid characters in hostnames, but commonly
   913					// found in deployments outside the WebPKI.
   914					continue
   915				}
   916				return false
   917			}
   918		}
   919	
   920		return true
   921	}
   922	
   923	// commonNameAsHostname reports whether the Common Name field should be
   924	// considered the hostname that the certificate is valid for. This is a legacy
   925	// behavior, disabled if the Subject Alt Name extension is present.
   926	//
   927	// It applies the strict validHostname check to the Common Name field, so that
   928	// certificates without SANs can still be validated against CAs with name
   929	// constraints if there is no risk the CN would be matched as a hostname.
   930	// See NameConstraintsWithoutSANs and issue 24151.
   931	func (c *Certificate) commonNameAsHostname() bool {
   932		return !ignoreCN && !c.hasSANExtension() && validHostname(c.Subject.CommonName)
   933	}
   934	
   935	func matchHostnames(pattern, host string) bool {
   936		host = strings.TrimSuffix(host, ".")
   937		pattern = strings.TrimSuffix(pattern, ".")
   938	
   939		if len(pattern) == 0 || len(host) == 0 {
   940			return false
   941		}
   942	
   943		patternParts := strings.Split(pattern, ".")
   944		hostParts := strings.Split(host, ".")
   945	
   946		if len(patternParts) != len(hostParts) {
   947			return false
   948		}
   949	
   950		for i, patternPart := range patternParts {
   951			if i == 0 && patternPart == "*" {
   952				continue
   953			}
   954			if patternPart != hostParts[i] {
   955				return false
   956			}
   957		}
   958	
   959		return true
   960	}
   961	
   962	// toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
   963	// an explicitly ASCII function to avoid any sharp corners resulting from
   964	// performing Unicode operations on DNS labels.
   965	func toLowerCaseASCII(in string) string {
   966		// If the string is already lower-case then there's nothing to do.
   967		isAlreadyLowerCase := true
   968		for _, c := range in {
   969			if c == utf8.RuneError {
   970				// If we get a UTF-8 error then there might be
   971				// upper-case ASCII bytes in the invalid sequence.
   972				isAlreadyLowerCase = false
   973				break
   974			}
   975			if 'A' <= c && c <= 'Z' {
   976				isAlreadyLowerCase = false
   977				break
   978			}
   979		}
   980	
   981		if isAlreadyLowerCase {
   982			return in
   983		}
   984	
   985		out := []byte(in)
   986		for i, c := range out {
   987			if 'A' <= c && c <= 'Z' {
   988				out[i] += 'a' - 'A'
   989			}
   990		}
   991		return string(out)
   992	}
   993	
   994	// VerifyHostname returns nil if c is a valid certificate for the named host.
   995	// Otherwise it returns an error describing the mismatch.
   996	func (c *Certificate) VerifyHostname(h string) error {
   997		// IP addresses may be written in [ ].
   998		candidateIP := h
   999		if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
  1000			candidateIP = h[1 : len(h)-1]
  1001		}
  1002		if ip := net.ParseIP(candidateIP); ip != nil {
  1003			// We only match IP addresses against IP SANs.
  1004			// See RFC 6125, Appendix B.2.
  1005			for _, candidate := range c.IPAddresses {
  1006				if ip.Equal(candidate) {
  1007					return nil
  1008				}
  1009			}
  1010			return HostnameError{c, candidateIP}
  1011		}
  1012	
  1013		lowered := toLowerCaseASCII(h)
  1014	
  1015		if c.commonNameAsHostname() {
  1016			if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) {
  1017				return nil
  1018			}
  1019		} else {
  1020			for _, match := range c.DNSNames {
  1021				if matchHostnames(toLowerCaseASCII(match), lowered) {
  1022					return nil
  1023				}
  1024			}
  1025		}
  1026	
  1027		return HostnameError{c, h}
  1028	}
  1029	
  1030	func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
  1031		usages := make([]ExtKeyUsage, len(keyUsages))
  1032		copy(usages, keyUsages)
  1033	
  1034		if len(chain) == 0 {
  1035			return false
  1036		}
  1037	
  1038		usagesRemaining := len(usages)
  1039	
  1040		// We walk down the list and cross out any usages that aren't supported
  1041		// by each certificate. If we cross out all the usages, then the chain
  1042		// is unacceptable.
  1043	
  1044	NextCert:
  1045		for i := len(chain) - 1; i >= 0; i-- {
  1046			cert := chain[i]
  1047			if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
  1048				// The certificate doesn't have any extended key usage specified.
  1049				continue
  1050			}
  1051	
  1052			for _, usage := range cert.ExtKeyUsage {
  1053				if usage == ExtKeyUsageAny {
  1054					// The certificate is explicitly good for any usage.
  1055					continue NextCert
  1056				}
  1057			}
  1058	
  1059			const invalidUsage ExtKeyUsage = -1
  1060	
  1061		NextRequestedUsage:
  1062			for i, requestedUsage := range usages {
  1063				if requestedUsage == invalidUsage {
  1064					continue
  1065				}
  1066	
  1067				for _, usage := range cert.ExtKeyUsage {
  1068					if requestedUsage == usage {
  1069						continue NextRequestedUsage
  1070					} else if requestedUsage == ExtKeyUsageServerAuth &&
  1071						(usage == ExtKeyUsageNetscapeServerGatedCrypto ||
  1072							usage == ExtKeyUsageMicrosoftServerGatedCrypto) {
  1073						// In order to support COMODO
  1074						// certificate chains, we have to
  1075						// accept Netscape or Microsoft SGC
  1076						// usages as equal to ServerAuth.
  1077						continue NextRequestedUsage
  1078					}
  1079				}
  1080	
  1081				usages[i] = invalidUsage
  1082				usagesRemaining--
  1083				if usagesRemaining == 0 {
  1084					return false
  1085				}
  1086			}
  1087		}
  1088	
  1089		return true
  1090	}
  1091	

View as plain text