github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/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 "net/url" 13 "reflect" 14 "runtime" 15 "strings" 16 "time" 17 "unicode/utf8" 18 ) 19 20 type InvalidReason int 21 22 const ( 23 // NotAuthorizedToSign results when a certificate is signed by another 24 // which isn't marked as a CA certificate. 25 NotAuthorizedToSign InvalidReason = iota 26 // Expired results when a certificate has expired, based on the time 27 // given in the VerifyOptions. 28 Expired 29 // CANotAuthorizedForThisName results when an intermediate or root 30 // certificate has a name constraint which doesn't permit a DNS or 31 // other name (including IP address) in the leaf certificate. 32 CANotAuthorizedForThisName 33 // TooManyIntermediates results when a path length constraint is 34 // violated. 35 TooManyIntermediates 36 // IncompatibleUsage results when the certificate's key usage indicates 37 // that it may only be used for a different purpose. 38 IncompatibleUsage 39 // NameMismatch results when the subject name of a parent certificate 40 // does not match the issuer name in the child. 41 NameMismatch 42 // NameConstraintsWithoutSANs results when a leaf certificate doesn't 43 // contain a Subject Alternative Name extension, but a CA certificate 44 // contains name constraints. 45 NameConstraintsWithoutSANs 46 // UnconstrainedName results when a CA certificate contains permitted 47 // name constraints, but leaf certificate contains a name of an 48 // unsupported or unconstrained type. 49 UnconstrainedName 50 // TooManyConstraints results when the number of comparision operations 51 // needed to check a certificate exceeds the limit set by 52 // VerifyOptions.MaxConstraintComparisions. This limit exists to 53 // prevent pathological certificates can consuming excessive amounts of 54 // CPU time to verify. 55 TooManyConstraints 56 // CANotAuthorizedForExtKeyUsage results when an intermediate or root 57 // certificate does not permit an extended key usage that is claimed by 58 // the leaf certificate. 59 CANotAuthorizedForExtKeyUsage 60 ) 61 62 // CertificateInvalidError results when an odd error occurs. Users of this 63 // library probably want to handle all these errors uniformly. 64 type CertificateInvalidError struct { 65 Cert *Certificate 66 Reason InvalidReason 67 Detail string 68 } 69 70 func (e CertificateInvalidError) Error() string { 71 switch e.Reason { 72 case NotAuthorizedToSign: 73 return "x509: certificate is not authorized to sign other certificates" 74 case Expired: 75 return "x509: certificate has expired or is not yet valid" 76 case CANotAuthorizedForThisName: 77 return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e.Detail 78 case CANotAuthorizedForExtKeyUsage: 79 return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e.Detail 80 case TooManyIntermediates: 81 return "x509: too many intermediates for path length constraint" 82 case IncompatibleUsage: 83 return "x509: certificate specifies an incompatible key usage: " + e.Detail 84 case NameMismatch: 85 return "x509: issuer name does not match subject from issuing certificate" 86 case NameConstraintsWithoutSANs: 87 return "x509: issuer has name constraints but leaf doesn't have a SAN extension" 88 case UnconstrainedName: 89 return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e.Detail 90 } 91 return "x509: unknown error" 92 } 93 94 // HostnameError results when the set of authorized names doesn't match the 95 // requested name. 96 type HostnameError struct { 97 Certificate *Certificate 98 Host string 99 } 100 101 func (h HostnameError) Error() string { 102 c := h.Certificate 103 104 var valid string 105 if ip := net.ParseIP(h.Host); ip != nil { 106 // Trying to validate an IP 107 if len(c.IPAddresses) == 0 { 108 return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs" 109 } 110 for _, san := range c.IPAddresses { 111 if len(valid) > 0 { 112 valid += ", " 113 } 114 valid += san.String() 115 } 116 } else { 117 if c.hasSANExtension() { 118 valid = strings.Join(c.DNSNames, ", ") 119 } else { 120 valid = c.Subject.CommonName 121 } 122 } 123 124 if len(valid) == 0 { 125 return "x509: certificate is not valid for any names, but wanted to match " + h.Host 126 } 127 return "x509: certificate is valid for " + valid + ", not " + h.Host 128 } 129 130 // UnknownAuthorityError results when the certificate issuer is unknown 131 type UnknownAuthorityError struct { 132 Cert *Certificate 133 // hintErr contains an error that may be helpful in determining why an 134 // authority wasn't found. 135 hintErr error 136 // hintCert contains a possible authority certificate that was rejected 137 // because of the error in hintErr. 138 hintCert *Certificate 139 } 140 141 func (e UnknownAuthorityError) Error() string { 142 s := "x509: certificate signed by unknown authority" 143 if e.hintErr != nil { 144 certName := e.hintCert.Subject.CommonName 145 if len(certName) == 0 { 146 if len(e.hintCert.Subject.Organization) > 0 { 147 certName = e.hintCert.Subject.Organization[0] 148 } else { 149 certName = "serial:" + e.hintCert.SerialNumber.String() 150 } 151 } 152 s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName) 153 } 154 return s 155 } 156 157 // SystemRootsError results when we fail to load the system root certificates. 158 type SystemRootsError struct { 159 Err error 160 } 161 162 func (se SystemRootsError) Error() string { 163 msg := "x509: failed to load system roots and no roots provided" 164 if se.Err != nil { 165 return msg + "; " + se.Err.Error() 166 } 167 return msg 168 } 169 170 // errNotParsed is returned when a certificate without ASN.1 contents is 171 // verified. Platform-specific verification needs the ASN.1 contents. 172 var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate") 173 174 // VerifyOptions contains parameters for Certificate.Verify. It's a structure 175 // because other PKIX verification APIs have ended up needing many options. 176 type VerifyOptions struct { 177 DNSName string 178 Intermediates *CertPool 179 Roots *CertPool // if nil, the system roots are used 180 CurrentTime time.Time // if zero, the current time is used 181 // KeyUsage specifies which Extended Key Usage values are acceptable. 182 // An empty list means ExtKeyUsageServerAuth. Key usage is considered a 183 // constraint down the chain which mirrors Windows CryptoAPI behavior, 184 // but not the spec. To accept any key usage, include ExtKeyUsageAny. 185 KeyUsages []ExtKeyUsage 186 // MaxConstraintComparisions is the maximum number of comparisons to 187 // perform when checking a given certificate's name constraints. If 188 // zero, a sensible default is used. This limit prevents pathalogical 189 // certificates from consuming excessive amounts of CPU time when 190 // validating. 191 MaxConstraintComparisions int 192 } 193 194 const ( 195 leafCertificate = iota 196 intermediateCertificate 197 rootCertificate 198 ) 199 200 // rfc2821Mailbox represents a “mailbox” (which is an email address to most 201 // people) by breaking it into the “local” (i.e. before the '@') and “domain” 202 // parts. 203 type rfc2821Mailbox struct { 204 local, domain string 205 } 206 207 // parseRFC2821Mailbox parses an email address into local and domain parts, 208 // based on the ABNF for a “Mailbox” from RFC 2821. According to 209 // https://tools.ietf.org/html/rfc5280#section-4.2.1.6 that's correct for an 210 // rfc822Name from a certificate: “The format of an rfc822Name is a "Mailbox" 211 // as defined in https://tools.ietf.org/html/rfc2821#section-4.1.2”. 212 func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) { 213 if len(in) == 0 { 214 return mailbox, false 215 } 216 217 localPartBytes := make([]byte, 0, len(in)/2) 218 219 if in[0] == '"' { 220 // Quoted-string = DQUOTE *qcontent DQUOTE 221 // non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127 222 // qcontent = qtext / quoted-pair 223 // qtext = non-whitespace-control / 224 // %d33 / %d35-91 / %d93-126 225 // quoted-pair = ("\" text) / obs-qp 226 // text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text 227 // 228 // (Names beginning with “obs-” are the obsolete syntax from 229 // https://tools.ietf.org/html/rfc2822#section-4. Since it has 230 // been 16 years, we no longer accept that.) 231 in = in[1:] 232 QuotedString: 233 for { 234 if len(in) == 0 { 235 return mailbox, false 236 } 237 c := in[0] 238 in = in[1:] 239 240 switch { 241 case c == '"': 242 break QuotedString 243 244 case c == '\\': 245 // quoted-pair 246 if len(in) == 0 { 247 return mailbox, false 248 } 249 if in[0] == 11 || 250 in[0] == 12 || 251 (1 <= in[0] && in[0] <= 9) || 252 (14 <= in[0] && in[0] <= 127) { 253 localPartBytes = append(localPartBytes, in[0]) 254 in = in[1:] 255 } else { 256 return mailbox, false 257 } 258 259 case c == 11 || 260 c == 12 || 261 // Space (char 32) is not allowed based on the 262 // BNF, but RFC 3696 gives an example that 263 // assumes that it is. Several “verified” 264 // errata continue to argue about this point. 265 // We choose to accept it. 266 c == 32 || 267 c == 33 || 268 c == 127 || 269 (1 <= c && c <= 8) || 270 (14 <= c && c <= 31) || 271 (35 <= c && c <= 91) || 272 (93 <= c && c <= 126): 273 // qtext 274 localPartBytes = append(localPartBytes, c) 275 276 default: 277 return mailbox, false 278 } 279 } 280 } else { 281 // Atom ("." Atom)* 282 NextChar: 283 for len(in) > 0 { 284 // atext from https://tools.ietf.org/html/rfc2822#section-3.2.4 285 c := in[0] 286 287 switch { 288 case c == '\\': 289 // Examples given in RFC 3696 suggest that 290 // escaped characters can appear outside of a 291 // quoted string. Several “verified” errata 292 // continue to argue the point. We choose to 293 // accept it. 294 in = in[1:] 295 if len(in) == 0 { 296 return mailbox, false 297 } 298 fallthrough 299 300 case ('0' <= c && c <= '9') || 301 ('a' <= c && c <= 'z') || 302 ('A' <= c && c <= 'Z') || 303 c == '!' || c == '#' || c == '$' || c == '%' || 304 c == '&' || c == '\'' || c == '*' || c == '+' || 305 c == '-' || c == '/' || c == '=' || c == '?' || 306 c == '^' || c == '_' || c == '`' || c == '{' || 307 c == '|' || c == '}' || c == '~' || c == '.': 308 localPartBytes = append(localPartBytes, in[0]) 309 in = in[1:] 310 311 default: 312 break NextChar 313 } 314 } 315 316 if len(localPartBytes) == 0 { 317 return mailbox, false 318 } 319 320 // https://tools.ietf.org/html/rfc3696#section-3 321 // “period (".") may also appear, but may not be used to start 322 // or end the local part, nor may two or more consecutive 323 // periods appear.” 324 twoDots := []byte{'.', '.'} 325 if localPartBytes[0] == '.' || 326 localPartBytes[len(localPartBytes)-1] == '.' || 327 bytes.Contains(localPartBytes, twoDots) { 328 return mailbox, false 329 } 330 } 331 332 if len(in) == 0 || in[0] != '@' { 333 return mailbox, false 334 } 335 in = in[1:] 336 337 // The RFC species a format for domains, but that's known to be 338 // violated in practice so we accept that anything after an '@' is the 339 // domain part. 340 if _, ok := domainToReverseLabels(in); !ok { 341 return mailbox, false 342 } 343 344 mailbox.local = string(localPartBytes) 345 mailbox.domain = in 346 return mailbox, true 347 } 348 349 // domainToReverseLabels converts a textual domain name like foo.example.com to 350 // the list of labels in reverse order, e.g. ["com", "example", "foo"]. 351 func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) { 352 for len(domain) > 0 { 353 if i := strings.LastIndexByte(domain, '.'); i == -1 { 354 reverseLabels = append(reverseLabels, domain) 355 domain = "" 356 } else { 357 reverseLabels = append(reverseLabels, domain[i+1:len(domain)]) 358 domain = domain[:i] 359 } 360 } 361 362 if len(reverseLabels) > 0 && len(reverseLabels[0]) == 0 { 363 // An empty label at the end indicates an absolute value. 364 return nil, false 365 } 366 367 for _, label := range reverseLabels { 368 if len(label) == 0 { 369 // Empty labels are otherwise invalid. 370 return nil, false 371 } 372 373 for _, c := range label { 374 if c < 33 || c > 126 { 375 // Invalid character. 376 return nil, false 377 } 378 } 379 } 380 381 return reverseLabels, true 382 } 383 384 func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) { 385 // If the constraint contains an @, then it specifies an exact mailbox 386 // name. 387 if strings.Contains(constraint, "@") { 388 constraintMailbox, ok := parseRFC2821Mailbox(constraint) 389 if !ok { 390 return false, fmt.Errorf("x509: internal error: cannot parse constraint %q", constraint) 391 } 392 return mailbox.local == constraintMailbox.local && strings.EqualFold(mailbox.domain, constraintMailbox.domain), nil 393 } 394 395 // Otherwise the constraint is like a DNS constraint of the domain part 396 // of the mailbox. 397 return matchDomainConstraint(mailbox.domain, constraint) 398 } 399 400 func matchURIConstraint(uri *url.URL, constraint string) (bool, error) { 401 // https://tools.ietf.org/html/rfc5280#section-4.2.1.10 402 // “a uniformResourceIdentifier that does not include an authority 403 // component with a host name specified as a fully qualified domain 404 // name (e.g., if the URI either does not include an authority 405 // component or includes an authority component in which the host name 406 // is specified as an IP address), then the application MUST reject the 407 // certificate.” 408 409 host := uri.Host 410 if len(host) == 0 { 411 return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", uri.String()) 412 } 413 414 if strings.Contains(host, ":") && !strings.HasSuffix(host, "]") { 415 var err error 416 host, _, err = net.SplitHostPort(uri.Host) 417 if err != nil { 418 return false, err 419 } 420 } 421 422 if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") || 423 net.ParseIP(host) != nil { 424 return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String()) 425 } 426 427 return matchDomainConstraint(host, constraint) 428 } 429 430 func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) { 431 if len(ip) != len(constraint.IP) { 432 return false, nil 433 } 434 435 for i := range ip { 436 if mask := constraint.Mask[i]; ip[i]&mask != constraint.IP[i]&mask { 437 return false, nil 438 } 439 } 440 441 return true, nil 442 } 443 444 func matchDomainConstraint(domain, constraint string) (bool, error) { 445 // The meaning of zero length constraints is not specified, but this 446 // code follows NSS and accepts them as matching everything. 447 if len(constraint) == 0 { 448 return true, nil 449 } 450 451 domainLabels, ok := domainToReverseLabels(domain) 452 if !ok { 453 return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain) 454 } 455 456 // RFC 5280 says that a leading period in a domain name means that at 457 // least one label must be prepended, but only for URI and email 458 // constraints, not DNS constraints. The code also supports that 459 // behaviour for DNS constraints. 460 461 mustHaveSubdomains := false 462 if constraint[0] == '.' { 463 mustHaveSubdomains = true 464 constraint = constraint[1:] 465 } 466 467 constraintLabels, ok := domainToReverseLabels(constraint) 468 if !ok { 469 return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint) 470 } 471 472 if len(domainLabels) < len(constraintLabels) || 473 (mustHaveSubdomains && len(domainLabels) == len(constraintLabels)) { 474 return false, nil 475 } 476 477 for i, constraintLabel := range constraintLabels { 478 if !strings.EqualFold(constraintLabel, domainLabels[i]) { 479 return false, nil 480 } 481 } 482 483 return true, nil 484 } 485 486 // checkNameConstraints checks that c permits a child certificate to claim the 487 // given name, of type nameType. The argument parsedName contains the parsed 488 // form of name, suitable for passing to the match function. The total number 489 // of comparisons is tracked in the given count and should not exceed the given 490 // limit. 491 func (c *Certificate) checkNameConstraints(count *int, 492 maxConstraintComparisons int, 493 nameType string, 494 name string, 495 parsedName interface{}, 496 match func(parsedName, constraint interface{}) (match bool, err error), 497 permitted, excluded interface{}) error { 498 499 excludedValue := reflect.ValueOf(excluded) 500 501 *count += excludedValue.Len() 502 if *count > maxConstraintComparisons { 503 return CertificateInvalidError{c, TooManyConstraints, ""} 504 } 505 506 for i := 0; i < excludedValue.Len(); i++ { 507 constraint := excludedValue.Index(i).Interface() 508 match, err := match(parsedName, constraint) 509 if err != nil { 510 return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()} 511 } 512 513 if match { 514 return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", nameType, name, constraint)} 515 } 516 } 517 518 permittedValue := reflect.ValueOf(permitted) 519 520 *count += permittedValue.Len() 521 if *count > maxConstraintComparisons { 522 return CertificateInvalidError{c, TooManyConstraints, ""} 523 } 524 525 ok := true 526 for i := 0; i < permittedValue.Len(); i++ { 527 constraint := permittedValue.Index(i).Interface() 528 529 var err error 530 if ok, err = match(parsedName, constraint); err != nil { 531 return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()} 532 } 533 534 if ok { 535 break 536 } 537 } 538 539 if !ok { 540 return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", nameType, name)} 541 } 542 543 return nil 544 } 545 546 // ekuPermittedBy returns true iff the given extended key usage is permitted by 547 // the given EKU from a certificate. Normally, this would be a simple 548 // comparison plus a special case for the “any” EKU. But, in order to support 549 // COMODO chains, SGC EKUs permit generic server and client authentication 550 // EKUs. 551 func ekuPermittedBy(eku, certEKU ExtKeyUsage) bool { 552 if certEKU == ExtKeyUsageAny || eku == certEKU { 553 return true 554 } 555 556 if (eku == ExtKeyUsageServerAuth || eku == ExtKeyUsageClientAuth) && 557 (certEKU == ExtKeyUsageNetscapeServerGatedCrypto || certEKU == ExtKeyUsageMicrosoftServerGatedCrypto) { 558 return true 559 } 560 561 return false 562 } 563 564 // isValid performs validity checks on c given that it is a candidate to append 565 // to the chain in currentChain. 566 func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error { 567 if len(c.UnhandledCriticalExtensions) > 0 { 568 return UnhandledCriticalExtension{} 569 } 570 571 if len(currentChain) > 0 { 572 child := currentChain[len(currentChain)-1] 573 if !bytes.Equal(child.RawIssuer, c.RawSubject) { 574 return CertificateInvalidError{c, NameMismatch, ""} 575 } 576 } 577 578 now := opts.CurrentTime 579 if now.IsZero() { 580 now = time.Now() 581 } 582 if now.Before(c.NotBefore) || now.After(c.NotAfter) { 583 return CertificateInvalidError{c, Expired, ""} 584 } 585 586 maxConstraintComparisons := opts.MaxConstraintComparisions 587 if maxConstraintComparisons == 0 { 588 maxConstraintComparisons = 250000 589 } 590 comparisonCount := 0 591 592 var leaf *Certificate 593 if certType == intermediateCertificate || certType == rootCertificate { 594 if len(currentChain) == 0 { 595 return errors.New("x509: internal error: empty chain when appending CA cert") 596 } 597 leaf = currentChain[0] 598 } 599 600 if (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints() { 601 sanExtension, ok := leaf.getSANExtension() 602 if !ok { 603 // This is the deprecated, legacy case of depending on 604 // the CN as a hostname. Chains modern enough to be 605 // using name constraints should not be depending on 606 // CNs. 607 return CertificateInvalidError{c, NameConstraintsWithoutSANs, ""} 608 } 609 610 err := forEachSAN(sanExtension, func(tag int, data []byte) error { 611 switch tag { 612 case nameTypeEmail: 613 name := string(data) 614 mailbox, ok := parseRFC2821Mailbox(name) 615 if !ok { 616 // This certificate should not have parsed. 617 return errors.New("x509: internal error: rfc822Name SAN failed to parse") 618 } 619 620 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox, 621 func(parsedName, constraint interface{}) (bool, error) { 622 return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string)) 623 }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil { 624 return err 625 } 626 627 case nameTypeDNS: 628 name := string(data) 629 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name, 630 func(parsedName, constraint interface{}) (bool, error) { 631 return matchDomainConstraint(parsedName.(string), constraint.(string)) 632 }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil { 633 return err 634 } 635 636 case nameTypeURI: 637 name := string(data) 638 uri, err := url.Parse(name) 639 if err != nil { 640 return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name) 641 } 642 643 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri, 644 func(parsedName, constraint interface{}) (bool, error) { 645 return matchURIConstraint(parsedName.(*url.URL), constraint.(string)) 646 }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil { 647 return err 648 } 649 650 case nameTypeIP: 651 ip := net.IP(data) 652 if l := len(ip); l != net.IPv4len && l != net.IPv6len { 653 return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data) 654 } 655 656 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip, 657 func(parsedName, constraint interface{}) (bool, error) { 658 return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet)) 659 }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil { 660 return err 661 } 662 663 default: 664 // Unknown SAN types are ignored. 665 } 666 667 return nil 668 }) 669 670 if err != nil { 671 return err 672 } 673 } 674 675 checkEKUs := certType == intermediateCertificate || certType == rootCertificate 676 677 // If no extended key usages are specified, then all are acceptable. 678 if checkEKUs && (len(c.ExtKeyUsage) == 0 && len(c.UnknownExtKeyUsage) == 0) { 679 checkEKUs = false 680 } 681 682 // If the “any” key usage is permitted, then no more checks are needed. 683 if checkEKUs { 684 for _, caEKU := range c.ExtKeyUsage { 685 comparisonCount++ 686 if caEKU == ExtKeyUsageAny { 687 checkEKUs = false 688 break 689 } 690 } 691 } 692 693 if checkEKUs { 694 NextEKU: 695 for _, eku := range leaf.ExtKeyUsage { 696 if comparisonCount > maxConstraintComparisons { 697 return CertificateInvalidError{c, TooManyConstraints, ""} 698 } 699 700 for _, caEKU := range c.ExtKeyUsage { 701 comparisonCount++ 702 if ekuPermittedBy(eku, caEKU) { 703 continue NextEKU 704 } 705 } 706 707 oid, _ := oidFromExtKeyUsage(eku) 708 return CertificateInvalidError{c, CANotAuthorizedForExtKeyUsage, fmt.Sprintf("EKU not permitted: %#v", oid)} 709 } 710 711 NextUnknownEKU: 712 for _, eku := range leaf.UnknownExtKeyUsage { 713 if comparisonCount > maxConstraintComparisons { 714 return CertificateInvalidError{c, TooManyConstraints, ""} 715 } 716 717 for _, caEKU := range c.UnknownExtKeyUsage { 718 comparisonCount++ 719 if caEKU.Equal(eku) { 720 continue NextUnknownEKU 721 } 722 } 723 724 return CertificateInvalidError{c, CANotAuthorizedForExtKeyUsage, fmt.Sprintf("EKU not permitted: %#v", eku)} 725 } 726 } 727 728 // KeyUsage status flags are ignored. From Engineering Security, Peter 729 // Gutmann: A European government CA marked its signing certificates as 730 // being valid for encryption only, but no-one noticed. Another 731 // European CA marked its signature keys as not being valid for 732 // signatures. A different CA marked its own trusted root certificate 733 // as being invalid for certificate signing. Another national CA 734 // distributed a certificate to be used to encrypt data for the 735 // country’s tax authority that was marked as only being usable for 736 // digital signatures but not for encryption. Yet another CA reversed 737 // the order of the bit flags in the keyUsage due to confusion over 738 // encoding endianness, essentially setting a random keyUsage in 739 // certificates that it issued. Another CA created a self-invalidating 740 // certificate by adding a certificate policy statement stipulating 741 // that the certificate had to be used strictly as specified in the 742 // keyUsage, and a keyUsage containing a flag indicating that the RSA 743 // encryption key could only be used for Diffie-Hellman key agreement. 744 745 if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) { 746 return CertificateInvalidError{c, NotAuthorizedToSign, ""} 747 } 748 749 if c.BasicConstraintsValid && c.MaxPathLen >= 0 { 750 numIntermediates := len(currentChain) - 1 751 if numIntermediates > c.MaxPathLen { 752 return CertificateInvalidError{c, TooManyIntermediates, ""} 753 } 754 } 755 756 return nil 757 } 758 759 // Verify attempts to verify c by building one or more chains from c to a 760 // certificate in opts.Roots, using certificates in opts.Intermediates if 761 // needed. If successful, it returns one or more chains where the first 762 // element of the chain is c and the last element is from opts.Roots. 763 // 764 // If opts.Roots is nil and system roots are unavailable the returned error 765 // will be of type SystemRootsError. 766 // 767 // WARNING: this doesn't do any revocation checking. 768 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { 769 // Platform-specific verification needs the ASN.1 contents so 770 // this makes the behavior consistent across platforms. 771 if len(c.Raw) == 0 { 772 return nil, errNotParsed 773 } 774 if opts.Intermediates != nil { 775 for _, intermediate := range opts.Intermediates.certs { 776 if len(intermediate.Raw) == 0 { 777 return nil, errNotParsed 778 } 779 } 780 } 781 782 // Use Windows's own verification and chain building. 783 if opts.Roots == nil && runtime.GOOS == "windows" { 784 return c.systemVerify(&opts) 785 } 786 787 if opts.Roots == nil { 788 opts.Roots = systemRootsPool() 789 if opts.Roots == nil { 790 return nil, SystemRootsError{systemRootsErr} 791 } 792 } 793 794 err = c.isValid(leafCertificate, nil, &opts) 795 if err != nil { 796 return 797 } 798 799 if len(opts.DNSName) > 0 { 800 err = c.VerifyHostname(opts.DNSName) 801 if err != nil { 802 return 803 } 804 } 805 806 requestedKeyUsages := make([]ExtKeyUsage, len(opts.KeyUsages)) 807 copy(requestedKeyUsages, opts.KeyUsages) 808 if len(requestedKeyUsages) == 0 { 809 requestedKeyUsages = append(requestedKeyUsages, ExtKeyUsageServerAuth) 810 } 811 812 // If no key usages are specified, then any are acceptable. 813 checkEKU := len(c.ExtKeyUsage) > 0 814 815 for _, eku := range requestedKeyUsages { 816 if eku == ExtKeyUsageAny { 817 checkEKU = false 818 break 819 } 820 } 821 822 if checkEKU { 823 NextUsage: 824 for _, eku := range requestedKeyUsages { 825 for _, leafEKU := range c.ExtKeyUsage { 826 if ekuPermittedBy(eku, leafEKU) { 827 continue NextUsage 828 } 829 } 830 831 oid, _ := oidFromExtKeyUsage(eku) 832 return nil, CertificateInvalidError{c, IncompatibleUsage, fmt.Sprintf("%#v", oid)} 833 } 834 } 835 836 var candidateChains [][]*Certificate 837 if opts.Roots.contains(c) { 838 candidateChains = append(candidateChains, []*Certificate{c}) 839 } else { 840 if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil { 841 return nil, err 842 } 843 } 844 845 return candidateChains, nil 846 } 847 848 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { 849 n := make([]*Certificate, len(chain)+1) 850 copy(n, chain) 851 n[len(chain)] = cert 852 return n 853 } 854 855 func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) { 856 possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c) 857 nextRoot: 858 for _, rootNum := range possibleRoots { 859 root := opts.Roots.certs[rootNum] 860 861 for _, cert := range currentChain { 862 if cert.Equal(root) { 863 continue nextRoot 864 } 865 } 866 867 err = root.isValid(rootCertificate, currentChain, opts) 868 if err != nil { 869 continue 870 } 871 chains = append(chains, appendToFreshChain(currentChain, root)) 872 } 873 874 possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c) 875 nextIntermediate: 876 for _, intermediateNum := range possibleIntermediates { 877 intermediate := opts.Intermediates.certs[intermediateNum] 878 for _, cert := range currentChain { 879 if cert.Equal(intermediate) { 880 continue nextIntermediate 881 } 882 } 883 err = intermediate.isValid(intermediateCertificate, currentChain, opts) 884 if err != nil { 885 continue 886 } 887 var childChains [][]*Certificate 888 childChains, ok := cache[intermediateNum] 889 if !ok { 890 childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts) 891 cache[intermediateNum] = childChains 892 } 893 chains = append(chains, childChains...) 894 } 895 896 if len(chains) > 0 { 897 err = nil 898 } 899 900 if len(chains) == 0 && err == nil { 901 hintErr := rootErr 902 hintCert := failedRoot 903 if hintErr == nil { 904 hintErr = intermediateErr 905 hintCert = failedIntermediate 906 } 907 err = UnknownAuthorityError{c, hintErr, hintCert} 908 } 909 910 return 911 } 912 913 func matchHostnames(pattern, host string) bool { 914 host = strings.TrimSuffix(host, ".") 915 pattern = strings.TrimSuffix(pattern, ".") 916 917 if len(pattern) == 0 || len(host) == 0 { 918 return false 919 } 920 921 patternParts := strings.Split(pattern, ".") 922 hostParts := strings.Split(host, ".") 923 924 if len(patternParts) != len(hostParts) { 925 return false 926 } 927 928 for i, patternPart := range patternParts { 929 if i == 0 && patternPart == "*" { 930 continue 931 } 932 if patternPart != hostParts[i] { 933 return false 934 } 935 } 936 937 return true 938 } 939 940 // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use 941 // an explicitly ASCII function to avoid any sharp corners resulting from 942 // performing Unicode operations on DNS labels. 943 func toLowerCaseASCII(in string) string { 944 // If the string is already lower-case then there's nothing to do. 945 isAlreadyLowerCase := true 946 for _, c := range in { 947 if c == utf8.RuneError { 948 // If we get a UTF-8 error then there might be 949 // upper-case ASCII bytes in the invalid sequence. 950 isAlreadyLowerCase = false 951 break 952 } 953 if 'A' <= c && c <= 'Z' { 954 isAlreadyLowerCase = false 955 break 956 } 957 } 958 959 if isAlreadyLowerCase { 960 return in 961 } 962 963 out := []byte(in) 964 for i, c := range out { 965 if 'A' <= c && c <= 'Z' { 966 out[i] += 'a' - 'A' 967 } 968 } 969 return string(out) 970 } 971 972 // VerifyHostname returns nil if c is a valid certificate for the named host. 973 // Otherwise it returns an error describing the mismatch. 974 func (c *Certificate) VerifyHostname(h string) error { 975 // IP addresses may be written in [ ]. 976 candidateIP := h 977 if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' { 978 candidateIP = h[1 : len(h)-1] 979 } 980 if ip := net.ParseIP(candidateIP); ip != nil { 981 // We only match IP addresses against IP SANs. 982 // https://tools.ietf.org/html/rfc6125#appendix-B.2 983 for _, candidate := range c.IPAddresses { 984 if ip.Equal(candidate) { 985 return nil 986 } 987 } 988 return HostnameError{c, candidateIP} 989 } 990 991 lowered := toLowerCaseASCII(h) 992 993 if c.hasSANExtension() { 994 for _, match := range c.DNSNames { 995 if matchHostnames(toLowerCaseASCII(match), lowered) { 996 return nil 997 } 998 } 999 // If Subject Alt Name is given, we ignore the common name. 1000 } else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) { 1001 return nil 1002 } 1003 1004 return HostnameError{c, h} 1005 }