github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/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 c.hasSANExtension() { 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 matching 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(c.UnhandledCriticalExtensions) > 0 { 195 return UnhandledCriticalExtension{} 196 } 197 198 if len(currentChain) > 0 { 199 child := currentChain[len(currentChain)-1] 200 if !bytes.Equal(child.RawIssuer, c.RawSubject) { 201 return CertificateInvalidError{c, NameMismatch} 202 } 203 } 204 205 now := opts.CurrentTime 206 if now.IsZero() { 207 now = time.Now() 208 } 209 if now.Before(c.NotBefore) || now.After(c.NotAfter) { 210 return CertificateInvalidError{c, Expired} 211 } 212 213 if len(c.PermittedDNSDomains) > 0 { 214 ok := false 215 for _, constraint := range c.PermittedDNSDomains { 216 ok = matchNameConstraint(opts.DNSName, constraint) 217 if ok { 218 break 219 } 220 } 221 222 if !ok { 223 return CertificateInvalidError{c, CANotAuthorizedForThisName} 224 } 225 } 226 227 for _, constraint := range c.ExcludedDNSDomains { 228 if matchNameConstraint(opts.DNSName, constraint) { 229 return CertificateInvalidError{c, CANotAuthorizedForThisName} 230 } 231 } 232 233 // KeyUsage status flags are ignored. From Engineering Security, Peter 234 // Gutmann: A European government CA marked its signing certificates as 235 // being valid for encryption only, but no-one noticed. Another 236 // European CA marked its signature keys as not being valid for 237 // signatures. A different CA marked its own trusted root certificate 238 // as being invalid for certificate signing. Another national CA 239 // distributed a certificate to be used to encrypt data for the 240 // country’s tax authority that was marked as only being usable for 241 // digital signatures but not for encryption. Yet another CA reversed 242 // the order of the bit flags in the keyUsage due to confusion over 243 // encoding endianness, essentially setting a random keyUsage in 244 // certificates that it issued. Another CA created a self-invalidating 245 // certificate by adding a certificate policy statement stipulating 246 // that the certificate had to be used strictly as specified in the 247 // keyUsage, and a keyUsage containing a flag indicating that the RSA 248 // encryption key could only be used for Diffie-Hellman key agreement. 249 250 if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) { 251 return CertificateInvalidError{c, NotAuthorizedToSign} 252 } 253 254 if c.BasicConstraintsValid && c.MaxPathLen >= 0 { 255 numIntermediates := len(currentChain) - 1 256 if numIntermediates > c.MaxPathLen { 257 return CertificateInvalidError{c, TooManyIntermediates} 258 } 259 } 260 261 return nil 262 } 263 264 // Verify attempts to verify c by building one or more chains from c to a 265 // certificate in opts.Roots, using certificates in opts.Intermediates if 266 // needed. If successful, it returns one or more chains where the first 267 // element of the chain is c and the last element is from opts.Roots. 268 // 269 // If opts.Roots is nil and system roots are unavailable the returned error 270 // will be of type SystemRootsError. 271 // 272 // WARNING: this doesn't do any revocation checking. 273 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { 274 // Platform-specific verification needs the ASN.1 contents so 275 // this makes the behavior consistent across platforms. 276 if len(c.Raw) == 0 { 277 return nil, errNotParsed 278 } 279 if opts.Intermediates != nil { 280 for _, intermediate := range opts.Intermediates.certs { 281 if len(intermediate.Raw) == 0 { 282 return nil, errNotParsed 283 } 284 } 285 } 286 287 // Use Windows's own verification and chain building. 288 if opts.Roots == nil && runtime.GOOS == "windows" { 289 return c.systemVerify(&opts) 290 } 291 292 if opts.Roots == nil { 293 opts.Roots = systemRootsPool() 294 if opts.Roots == nil { 295 return nil, SystemRootsError{systemRootsErr} 296 } 297 } 298 299 err = c.isValid(leafCertificate, nil, &opts) 300 if err != nil { 301 return 302 } 303 304 if len(opts.DNSName) > 0 { 305 err = c.VerifyHostname(opts.DNSName) 306 if err != nil { 307 return 308 } 309 } 310 311 var candidateChains [][]*Certificate 312 if opts.Roots.contains(c) { 313 candidateChains = append(candidateChains, []*Certificate{c}) 314 } else { 315 if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil { 316 return nil, err 317 } 318 } 319 320 keyUsages := opts.KeyUsages 321 if len(keyUsages) == 0 { 322 keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} 323 } 324 325 // If any key usage is acceptable then we're done. 326 for _, usage := range keyUsages { 327 if usage == ExtKeyUsageAny { 328 chains = candidateChains 329 return 330 } 331 } 332 333 for _, candidate := range candidateChains { 334 if checkChainForKeyUsage(candidate, keyUsages) { 335 chains = append(chains, candidate) 336 } 337 } 338 339 if len(chains) == 0 { 340 err = CertificateInvalidError{c, IncompatibleUsage} 341 } 342 343 return 344 } 345 346 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { 347 n := make([]*Certificate, len(chain)+1) 348 copy(n, chain) 349 n[len(chain)] = cert 350 return n 351 } 352 353 func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) { 354 possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c) 355 nextRoot: 356 for _, rootNum := range possibleRoots { 357 root := opts.Roots.certs[rootNum] 358 359 for _, cert := range currentChain { 360 if cert.Equal(root) { 361 continue nextRoot 362 } 363 } 364 365 err = root.isValid(rootCertificate, currentChain, opts) 366 if err != nil { 367 continue 368 } 369 chains = append(chains, appendToFreshChain(currentChain, root)) 370 } 371 372 possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c) 373 nextIntermediate: 374 for _, intermediateNum := range possibleIntermediates { 375 intermediate := opts.Intermediates.certs[intermediateNum] 376 for _, cert := range currentChain { 377 if cert.Equal(intermediate) { 378 continue nextIntermediate 379 } 380 } 381 err = intermediate.isValid(intermediateCertificate, currentChain, opts) 382 if err != nil { 383 continue 384 } 385 var childChains [][]*Certificate 386 childChains, ok := cache[intermediateNum] 387 if !ok { 388 childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts) 389 cache[intermediateNum] = childChains 390 } 391 chains = append(chains, childChains...) 392 } 393 394 if len(chains) > 0 { 395 err = nil 396 } 397 398 if len(chains) == 0 && err == nil { 399 hintErr := rootErr 400 hintCert := failedRoot 401 if hintErr == nil { 402 hintErr = intermediateErr 403 hintCert = failedIntermediate 404 } 405 err = UnknownAuthorityError{c, hintErr, hintCert} 406 } 407 408 return 409 } 410 411 func matchHostnames(pattern, host string) bool { 412 host = strings.TrimSuffix(host, ".") 413 pattern = strings.TrimSuffix(pattern, ".") 414 415 if len(pattern) == 0 || len(host) == 0 { 416 return false 417 } 418 419 patternParts := strings.Split(pattern, ".") 420 hostParts := strings.Split(host, ".") 421 422 if len(patternParts) != len(hostParts) { 423 return false 424 } 425 426 for i, patternPart := range patternParts { 427 if i == 0 && patternPart == "*" { 428 continue 429 } 430 if patternPart != hostParts[i] { 431 return false 432 } 433 } 434 435 return true 436 } 437 438 // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use 439 // an explicitly ASCII function to avoid any sharp corners resulting from 440 // performing Unicode operations on DNS labels. 441 func toLowerCaseASCII(in string) string { 442 // If the string is already lower-case then there's nothing to do. 443 isAlreadyLowerCase := true 444 for _, c := range in { 445 if c == utf8.RuneError { 446 // If we get a UTF-8 error then there might be 447 // upper-case ASCII bytes in the invalid sequence. 448 isAlreadyLowerCase = false 449 break 450 } 451 if 'A' <= c && c <= 'Z' { 452 isAlreadyLowerCase = false 453 break 454 } 455 } 456 457 if isAlreadyLowerCase { 458 return in 459 } 460 461 out := []byte(in) 462 for i, c := range out { 463 if 'A' <= c && c <= 'Z' { 464 out[i] += 'a' - 'A' 465 } 466 } 467 return string(out) 468 } 469 470 // VerifyHostname returns nil if c is a valid certificate for the named host. 471 // Otherwise it returns an error describing the mismatch. 472 func (c *Certificate) VerifyHostname(h string) error { 473 // IP addresses may be written in [ ]. 474 candidateIP := h 475 if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' { 476 candidateIP = h[1 : len(h)-1] 477 } 478 if ip := net.ParseIP(candidateIP); ip != nil { 479 // We only match IP addresses against IP SANs. 480 // https://tools.ietf.org/html/rfc6125#appendix-B.2 481 for _, candidate := range c.IPAddresses { 482 if ip.Equal(candidate) { 483 return nil 484 } 485 } 486 return HostnameError{c, candidateIP} 487 } 488 489 lowered := toLowerCaseASCII(h) 490 491 if c.hasSANExtension() { 492 for _, match := range c.DNSNames { 493 if matchHostnames(toLowerCaseASCII(match), lowered) { 494 return nil 495 } 496 } 497 // If Subject Alt Name is given, we ignore the common name. 498 } else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) { 499 return nil 500 } 501 502 return HostnameError{c, h} 503 } 504 505 func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { 506 usages := make([]ExtKeyUsage, len(keyUsages)) 507 copy(usages, keyUsages) 508 509 if len(chain) == 0 { 510 return false 511 } 512 513 usagesRemaining := len(usages) 514 515 // We walk down the list and cross out any usages that aren't supported 516 // by each certificate. If we cross out all the usages, then the chain 517 // is unacceptable. 518 519 NextCert: 520 for i := len(chain) - 1; i >= 0; i-- { 521 cert := chain[i] 522 if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 { 523 // The certificate doesn't have any extended key usage specified. 524 continue 525 } 526 527 for _, usage := range cert.ExtKeyUsage { 528 if usage == ExtKeyUsageAny { 529 // The certificate is explicitly good for any usage. 530 continue NextCert 531 } 532 } 533 534 const invalidUsage ExtKeyUsage = -1 535 536 NextRequestedUsage: 537 for i, requestedUsage := range usages { 538 if requestedUsage == invalidUsage { 539 continue 540 } 541 542 for _, usage := range cert.ExtKeyUsage { 543 if requestedUsage == usage { 544 continue NextRequestedUsage 545 } else if requestedUsage == ExtKeyUsageServerAuth && 546 (usage == ExtKeyUsageNetscapeServerGatedCrypto || 547 usage == ExtKeyUsageMicrosoftServerGatedCrypto) { 548 // In order to support COMODO 549 // certificate chains, we have to 550 // accept Netscape or Microsoft SGC 551 // usages as equal to ServerAuth. 552 continue NextRequestedUsage 553 } 554 } 555 556 usages[i] = invalidUsage 557 usagesRemaining-- 558 if usagesRemaining == 0 { 559 return false 560 } 561 } 562 } 563 564 return true 565 }