Home | History | Annotate | Download | only in x509
      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 	// countrys 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 }
    560