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