github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/src/crypto/x509/verify.go (about)

     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  	"runtime"
    13  	"strings"
    14  	"time"
    15  	"unicode/utf8"
    16  )
    17  
    18  type InvalidReason int
    19  
    20  const (
    21  	// NotAuthorizedToSign results when a certificate is signed by another
    22  	// which isn't marked as a CA certificate.
    23  	NotAuthorizedToSign InvalidReason = iota
    24  	// Expired results when a certificate has expired, based on the time
    25  	// given in the VerifyOptions.
    26  	Expired
    27  	// CANotAuthorizedForThisName results when an intermediate or root
    28  	// certificate has a name constraint which doesn't include the name
    29  	// being checked.
    30  	CANotAuthorizedForThisName
    31  	// TooManyIntermediates results when a path length constraint is
    32  	// violated.
    33  	TooManyIntermediates
    34  	// IncompatibleUsage results when the certificate's key usage indicates
    35  	// that it may only be used for a different purpose.
    36  	IncompatibleUsage
    37  	// NameMismatch results when the subject name of a parent certificate
    38  	// does not match the issuer name in the child.
    39  	NameMismatch
    40  )
    41  
    42  // CertificateInvalidError results when an odd error occurs. Users of this
    43  // library probably want to handle all these errors uniformly.
    44  type CertificateInvalidError struct {
    45  	Cert   *Certificate
    46  	Reason InvalidReason
    47  }
    48  
    49  func (e CertificateInvalidError) Error() string {
    50  	switch e.Reason {
    51  	case NotAuthorizedToSign:
    52  		return "x509: certificate is not authorized to sign other certificates"
    53  	case Expired:
    54  		return "x509: certificate has expired or is not yet valid"
    55  	case CANotAuthorizedForThisName:
    56  		return "x509: a root or intermediate certificate is not authorized to sign in this domain"
    57  	case TooManyIntermediates:
    58  		return "x509: too many intermediates for path length constraint"
    59  	case IncompatibleUsage:
    60  		return "x509: certificate specifies an incompatible key usage"
    61  	case NameMismatch:
    62  		return "x509: issuer name does not match subject from issuing certificate"
    63  	}
    64  	return "x509: unknown error"
    65  }
    66  
    67  // HostnameError results when the set of authorized names doesn't match the
    68  // requested name.
    69  type HostnameError struct {
    70  	Certificate *Certificate
    71  	Host        string
    72  }
    73  
    74  func (h HostnameError) Error() string {
    75  	c := h.Certificate
    76  
    77  	var valid string
    78  	if ip := net.ParseIP(h.Host); ip != nil {
    79  		// Trying to validate an IP
    80  		if len(c.IPAddresses) == 0 {
    81  			return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
    82  		}
    83  		for _, san := range c.IPAddresses {
    84  			if len(valid) > 0 {
    85  				valid += ", "
    86  			}
    87  			valid += san.String()
    88  		}
    89  	} else {
    90  		if len(c.DNSNames) > 0 {
    91  			valid = strings.Join(c.DNSNames, ", ")
    92  		} else {
    93  			valid = c.Subject.CommonName
    94  		}
    95  	}
    96  
    97  	if len(valid) == 0 {
    98  		return "x509: certificate is not valid for any names, but wanted to match " + h.Host
    99  	}
   100  	return "x509: certificate is valid for " + valid + ", not " + h.Host
   101  }
   102  
   103  // UnknownAuthorityError results when the certificate issuer is unknown
   104  type UnknownAuthorityError struct {
   105  	Cert *Certificate
   106  	// hintErr contains an error that may be helpful in determining why an
   107  	// authority wasn't found.
   108  	hintErr error
   109  	// hintCert contains a possible authority certificate that was rejected
   110  	// because of the error in hintErr.
   111  	hintCert *Certificate
   112  }
   113  
   114  func (e UnknownAuthorityError) Error() string {
   115  	s := "x509: certificate signed by unknown authority"
   116  	if e.hintErr != nil {
   117  		certName := e.hintCert.Subject.CommonName
   118  		if len(certName) == 0 {
   119  			if len(e.hintCert.Subject.Organization) > 0 {
   120  				certName = e.hintCert.Subject.Organization[0]
   121  			} else {
   122  				certName = "serial:" + e.hintCert.SerialNumber.String()
   123  			}
   124  		}
   125  		s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
   126  	}
   127  	return s
   128  }
   129  
   130  // SystemRootsError results when we fail to load the system root certificates.
   131  type SystemRootsError struct {
   132  	Err error
   133  }
   134  
   135  func (se SystemRootsError) Error() string {
   136  	msg := "x509: failed to load system roots and no roots provided"
   137  	if se.Err != nil {
   138  		return msg + "; " + se.Err.Error()
   139  	}
   140  	return msg
   141  }
   142  
   143  // errNotParsed is returned when a certificate without ASN.1 contents is
   144  // verified. Platform-specific verification needs the ASN.1 contents.
   145  var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
   146  
   147  // VerifyOptions contains parameters for Certificate.Verify. It's a structure
   148  // because other PKIX verification APIs have ended up needing many options.
   149  type VerifyOptions struct {
   150  	DNSName       string
   151  	Intermediates *CertPool
   152  	Roots         *CertPool // if nil, the system roots are used
   153  	CurrentTime   time.Time // if zero, the current time is used
   154  	// KeyUsage specifies which Extended Key Usage values are acceptable.
   155  	// An empty list means ExtKeyUsageServerAuth. Key usage is considered a
   156  	// constraint down the chain which mirrors Windows CryptoAPI behavior,
   157  	// but not the spec. To accept any key usage, include ExtKeyUsageAny.
   158  	KeyUsages []ExtKeyUsage
   159  }
   160  
   161  const (
   162  	leafCertificate = iota
   163  	intermediateCertificate
   164  	rootCertificate
   165  )
   166  
   167  func matchNameConstraint(domain, constraint string) bool {
   168  	// The meaning of zero length constraints is not specified, but this
   169  	// code follows NSS and accepts them as valid for everything.
   170  	if len(constraint) == 0 {
   171  		return true
   172  	}
   173  
   174  	if len(domain) < len(constraint) {
   175  		return false
   176  	}
   177  
   178  	prefixLen := len(domain) - len(constraint)
   179  	if !strings.EqualFold(domain[prefixLen:], constraint) {
   180  		return false
   181  	}
   182  
   183  	if prefixLen == 0 {
   184  		return true
   185  	}
   186  
   187  	isSubdomain := domain[prefixLen-1] == '.'
   188  	constraintHasLeadingDot := constraint[0] == '.'
   189  	return isSubdomain != constraintHasLeadingDot
   190  }
   191  
   192  // isValid performs validity checks on the c.
   193  func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
   194  	if len(currentChain) > 0 {
   195  		child := currentChain[len(currentChain)-1]
   196  		if !bytes.Equal(child.RawIssuer, c.RawSubject) {
   197  			return CertificateInvalidError{c, NameMismatch}
   198  		}
   199  	}
   200  
   201  	now := opts.CurrentTime
   202  	if now.IsZero() {
   203  		now = time.Now()
   204  	}
   205  	if now.Before(c.NotBefore) || now.After(c.NotAfter) {
   206  		return CertificateInvalidError{c, Expired}
   207  	}
   208  
   209  	if len(c.PermittedDNSDomains) > 0 {
   210  		ok := false
   211  		for _, constraint := range c.PermittedDNSDomains {
   212  			ok = matchNameConstraint(opts.DNSName, constraint)
   213  			if ok {
   214  				break
   215  			}
   216  		}
   217  
   218  		if !ok {
   219  			return CertificateInvalidError{c, CANotAuthorizedForThisName}
   220  		}
   221  	}
   222  
   223  	// KeyUsage status flags are ignored. From Engineering Security, Peter
   224  	// Gutmann: A European government CA marked its signing certificates as
   225  	// being valid for encryption only, but no-one noticed. Another
   226  	// European CA marked its signature keys as not being valid for
   227  	// signatures. A different CA marked its own trusted root certificate
   228  	// as being invalid for certificate signing. Another national CA
   229  	// distributed a certificate to be used to encrypt data for the
   230  	// country’s tax authority that was marked as only being usable for
   231  	// digital signatures but not for encryption. Yet another CA reversed
   232  	// the order of the bit flags in the keyUsage due to confusion over
   233  	// encoding endianness, essentially setting a random keyUsage in
   234  	// certificates that it issued. Another CA created a self-invalidating
   235  	// certificate by adding a certificate policy statement stipulating
   236  	// that the certificate had to be used strictly as specified in the
   237  	// keyUsage, and a keyUsage containing a flag indicating that the RSA
   238  	// encryption key could only be used for Diffie-Hellman key agreement.
   239  
   240  	if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
   241  		return CertificateInvalidError{c, NotAuthorizedToSign}
   242  	}
   243  
   244  	if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
   245  		numIntermediates := len(currentChain) - 1
   246  		if numIntermediates > c.MaxPathLen {
   247  			return CertificateInvalidError{c, TooManyIntermediates}
   248  		}
   249  	}
   250  
   251  	return nil
   252  }
   253  
   254  // Verify attempts to verify c by building one or more chains from c to a
   255  // certificate in opts.Roots, using certificates in opts.Intermediates if
   256  // needed. If successful, it returns one or more chains where the first
   257  // element of the chain is c and the last element is from opts.Roots.
   258  //
   259  // If opts.Roots is nil and system roots are unavailable the returned error
   260  // will be of type SystemRootsError.
   261  //
   262  // WARNING: this doesn't do any revocation checking.
   263  func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
   264  	// Platform-specific verification needs the ASN.1 contents so
   265  	// this makes the behavior consistent across platforms.
   266  	if len(c.Raw) == 0 {
   267  		return nil, errNotParsed
   268  	}
   269  	if opts.Intermediates != nil {
   270  		for _, intermediate := range opts.Intermediates.certs {
   271  			if len(intermediate.Raw) == 0 {
   272  				return nil, errNotParsed
   273  			}
   274  		}
   275  	}
   276  
   277  	// Use Windows's own verification and chain building.
   278  	if opts.Roots == nil && runtime.GOOS == "windows" {
   279  		return c.systemVerify(&opts)
   280  	}
   281  
   282  	if len(c.UnhandledCriticalExtensions) > 0 {
   283  		return nil, UnhandledCriticalExtension{}
   284  	}
   285  
   286  	if opts.Roots == nil {
   287  		opts.Roots = systemRootsPool()
   288  		if opts.Roots == nil {
   289  			return nil, SystemRootsError{systemRootsErr}
   290  		}
   291  	}
   292  
   293  	err = c.isValid(leafCertificate, nil, &opts)
   294  	if err != nil {
   295  		return
   296  	}
   297  
   298  	if len(opts.DNSName) > 0 {
   299  		err = c.VerifyHostname(opts.DNSName)
   300  		if err != nil {
   301  			return
   302  		}
   303  	}
   304  
   305  	var candidateChains [][]*Certificate
   306  	if opts.Roots.contains(c) {
   307  		candidateChains = append(candidateChains, []*Certificate{c})
   308  	} else {
   309  		if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil {
   310  			return nil, err
   311  		}
   312  	}
   313  
   314  	keyUsages := opts.KeyUsages
   315  	if len(keyUsages) == 0 {
   316  		keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
   317  	}
   318  
   319  	// If any key usage is acceptable then we're done.
   320  	for _, usage := range keyUsages {
   321  		if usage == ExtKeyUsageAny {
   322  			chains = candidateChains
   323  			return
   324  		}
   325  	}
   326  
   327  	for _, candidate := range candidateChains {
   328  		if checkChainForKeyUsage(candidate, keyUsages) {
   329  			chains = append(chains, candidate)
   330  		}
   331  	}
   332  
   333  	if len(chains) == 0 {
   334  		err = CertificateInvalidError{c, IncompatibleUsage}
   335  	}
   336  
   337  	return
   338  }
   339  
   340  func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
   341  	n := make([]*Certificate, len(chain)+1)
   342  	copy(n, chain)
   343  	n[len(chain)] = cert
   344  	return n
   345  }
   346  
   347  func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
   348  	possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
   349  nextRoot:
   350  	for _, rootNum := range possibleRoots {
   351  		root := opts.Roots.certs[rootNum]
   352  
   353  		for _, cert := range currentChain {
   354  			if cert.Equal(root) {
   355  				continue nextRoot
   356  			}
   357  		}
   358  
   359  		err = root.isValid(rootCertificate, currentChain, opts)
   360  		if err != nil {
   361  			continue
   362  		}
   363  		chains = append(chains, appendToFreshChain(currentChain, root))
   364  	}
   365  
   366  	possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c)
   367  nextIntermediate:
   368  	for _, intermediateNum := range possibleIntermediates {
   369  		intermediate := opts.Intermediates.certs[intermediateNum]
   370  		for _, cert := range currentChain {
   371  			if cert.Equal(intermediate) {
   372  				continue nextIntermediate
   373  			}
   374  		}
   375  		err = intermediate.isValid(intermediateCertificate, currentChain, opts)
   376  		if err != nil {
   377  			continue
   378  		}
   379  		var childChains [][]*Certificate
   380  		childChains, ok := cache[intermediateNum]
   381  		if !ok {
   382  			childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
   383  			cache[intermediateNum] = childChains
   384  		}
   385  		chains = append(chains, childChains...)
   386  	}
   387  
   388  	if len(chains) > 0 {
   389  		err = nil
   390  	}
   391  
   392  	if len(chains) == 0 && err == nil {
   393  		hintErr := rootErr
   394  		hintCert := failedRoot
   395  		if hintErr == nil {
   396  			hintErr = intermediateErr
   397  			hintCert = failedIntermediate
   398  		}
   399  		err = UnknownAuthorityError{c, hintErr, hintCert}
   400  	}
   401  
   402  	return
   403  }
   404  
   405  func matchHostnames(pattern, host string) bool {
   406  	host = strings.TrimSuffix(host, ".")
   407  	pattern = strings.TrimSuffix(pattern, ".")
   408  
   409  	if len(pattern) == 0 || len(host) == 0 {
   410  		return false
   411  	}
   412  
   413  	patternParts := strings.Split(pattern, ".")
   414  	hostParts := strings.Split(host, ".")
   415  
   416  	if len(patternParts) != len(hostParts) {
   417  		return false
   418  	}
   419  
   420  	for i, patternPart := range patternParts {
   421  		if i == 0 && patternPart == "*" {
   422  			continue
   423  		}
   424  		if patternPart != hostParts[i] {
   425  			return false
   426  		}
   427  	}
   428  
   429  	return true
   430  }
   431  
   432  // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
   433  // an explicitly ASCII function to avoid any sharp corners resulting from
   434  // performing Unicode operations on DNS labels.
   435  func toLowerCaseASCII(in string) string {
   436  	// If the string is already lower-case then there's nothing to do.
   437  	isAlreadyLowerCase := true
   438  	for _, c := range in {
   439  		if c == utf8.RuneError {
   440  			// If we get a UTF-8 error then there might be
   441  			// upper-case ASCII bytes in the invalid sequence.
   442  			isAlreadyLowerCase = false
   443  			break
   444  		}
   445  		if 'A' <= c && c <= 'Z' {
   446  			isAlreadyLowerCase = false
   447  			break
   448  		}
   449  	}
   450  
   451  	if isAlreadyLowerCase {
   452  		return in
   453  	}
   454  
   455  	out := []byte(in)
   456  	for i, c := range out {
   457  		if 'A' <= c && c <= 'Z' {
   458  			out[i] += 'a' - 'A'
   459  		}
   460  	}
   461  	return string(out)
   462  }
   463  
   464  // VerifyHostname returns nil if c is a valid certificate for the named host.
   465  // Otherwise it returns an error describing the mismatch.
   466  func (c *Certificate) VerifyHostname(h string) error {
   467  	// IP addresses may be written in [ ].
   468  	candidateIP := h
   469  	if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
   470  		candidateIP = h[1 : len(h)-1]
   471  	}
   472  	if ip := net.ParseIP(candidateIP); ip != nil {
   473  		// We only match IP addresses against IP SANs.
   474  		// https://tools.ietf.org/html/rfc6125#appendix-B.2
   475  		for _, candidate := range c.IPAddresses {
   476  			if ip.Equal(candidate) {
   477  				return nil
   478  			}
   479  		}
   480  		return HostnameError{c, candidateIP}
   481  	}
   482  
   483  	lowered := toLowerCaseASCII(h)
   484  
   485  	if len(c.DNSNames) > 0 {
   486  		for _, match := range c.DNSNames {
   487  			if matchHostnames(toLowerCaseASCII(match), lowered) {
   488  				return nil
   489  			}
   490  		}
   491  		// If Subject Alt Name is given, we ignore the common name.
   492  	} else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) {
   493  		return nil
   494  	}
   495  
   496  	return HostnameError{c, h}
   497  }
   498  
   499  func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
   500  	usages := make([]ExtKeyUsage, len(keyUsages))
   501  	copy(usages, keyUsages)
   502  
   503  	if len(chain) == 0 {
   504  		return false
   505  	}
   506  
   507  	usagesRemaining := len(usages)
   508  
   509  	// We walk down the list and cross out any usages that aren't supported
   510  	// by each certificate. If we cross out all the usages, then the chain
   511  	// is unacceptable.
   512  
   513  NextCert:
   514  	for i := len(chain) - 1; i >= 0; i-- {
   515  		cert := chain[i]
   516  		if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
   517  			// The certificate doesn't have any extended key usage specified.
   518  			continue
   519  		}
   520  
   521  		for _, usage := range cert.ExtKeyUsage {
   522  			if usage == ExtKeyUsageAny {
   523  				// The certificate is explicitly good for any usage.
   524  				continue NextCert
   525  			}
   526  		}
   527  
   528  		const invalidUsage ExtKeyUsage = -1
   529  
   530  	NextRequestedUsage:
   531  		for i, requestedUsage := range usages {
   532  			if requestedUsage == invalidUsage {
   533  				continue
   534  			}
   535  
   536  			for _, usage := range cert.ExtKeyUsage {
   537  				if requestedUsage == usage {
   538  					continue NextRequestedUsage
   539  				} else if requestedUsage == ExtKeyUsageServerAuth &&
   540  					(usage == ExtKeyUsageNetscapeServerGatedCrypto ||
   541  						usage == ExtKeyUsageMicrosoftServerGatedCrypto) {
   542  					// In order to support COMODO
   543  					// certificate chains, we have to
   544  					// accept Netscape or Microsoft SGC
   545  					// usages as equal to ServerAuth.
   546  					continue NextRequestedUsage
   547  				}
   548  			}
   549  
   550  			usages[i] = invalidUsage
   551  			usagesRemaining--
   552  			if usagesRemaining == 0 {
   553  				return false
   554  			}
   555  		}
   556  	}
   557  
   558  	return true
   559  }