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 }