github.com/kdevb0x/go@v0.0.0-20180115030120-39687051e9e7/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 // existing certificates, some exceptions are made. 550 func ekuPermittedBy(eku, certEKU ExtKeyUsage) bool { 551 if certEKU == ExtKeyUsageAny || eku == certEKU { 552 return true 553 } 554 555 // Some exceptions are made to support existing certificates. Firstly, 556 // the ServerAuth and SGC EKUs are treated as a group. 557 mapServerAuthEKUs := func(eku ExtKeyUsage) ExtKeyUsage { 558 if eku == ExtKeyUsageNetscapeServerGatedCrypto || eku == ExtKeyUsageMicrosoftServerGatedCrypto { 559 return ExtKeyUsageServerAuth 560 } 561 return eku 562 } 563 564 eku = mapServerAuthEKUs(eku) 565 certEKU = mapServerAuthEKUs(certEKU) 566 567 if eku == certEKU || 568 // ServerAuth in a CA permits ClientAuth in the leaf. 569 (eku == ExtKeyUsageClientAuth && certEKU == ExtKeyUsageServerAuth) || 570 // Any CA may issue an OCSP responder certificate. 571 eku == ExtKeyUsageOCSPSigning || 572 // Code-signing CAs can use Microsoft's commercial and 573 // kernel-mode EKUs. 574 ((eku == ExtKeyUsageMicrosoftCommercialCodeSigning || eku == ExtKeyUsageMicrosoftKernelCodeSigning) && certEKU == ExtKeyUsageCodeSigning) { 575 return true 576 } 577 578 return false 579 } 580 581 // isValid performs validity checks on c given that it is a candidate to append 582 // to the chain in currentChain. 583 func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error { 584 if len(c.UnhandledCriticalExtensions) > 0 { 585 return UnhandledCriticalExtension{} 586 } 587 588 if len(currentChain) > 0 { 589 child := currentChain[len(currentChain)-1] 590 if !bytes.Equal(child.RawIssuer, c.RawSubject) { 591 return CertificateInvalidError{c, NameMismatch, ""} 592 } 593 } 594 595 now := opts.CurrentTime 596 if now.IsZero() { 597 now = time.Now() 598 } 599 if now.Before(c.NotBefore) || now.After(c.NotAfter) { 600 return CertificateInvalidError{c, Expired, ""} 601 } 602 603 maxConstraintComparisons := opts.MaxConstraintComparisions 604 if maxConstraintComparisons == 0 { 605 maxConstraintComparisons = 250000 606 } 607 comparisonCount := 0 608 609 var leaf *Certificate 610 if certType == intermediateCertificate || certType == rootCertificate { 611 if len(currentChain) == 0 { 612 return errors.New("x509: internal error: empty chain when appending CA cert") 613 } 614 leaf = currentChain[0] 615 } 616 617 if (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints() { 618 sanExtension, ok := leaf.getSANExtension() 619 if !ok { 620 // This is the deprecated, legacy case of depending on 621 // the CN as a hostname. Chains modern enough to be 622 // using name constraints should not be depending on 623 // CNs. 624 return CertificateInvalidError{c, NameConstraintsWithoutSANs, ""} 625 } 626 627 err := forEachSAN(sanExtension, func(tag int, data []byte) error { 628 switch tag { 629 case nameTypeEmail: 630 name := string(data) 631 mailbox, ok := parseRFC2821Mailbox(name) 632 if !ok { 633 // This certificate should not have parsed. 634 return errors.New("x509: internal error: rfc822Name SAN failed to parse") 635 } 636 637 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox, 638 func(parsedName, constraint interface{}) (bool, error) { 639 return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string)) 640 }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil { 641 return err 642 } 643 644 case nameTypeDNS: 645 name := string(data) 646 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name, 647 func(parsedName, constraint interface{}) (bool, error) { 648 return matchDomainConstraint(parsedName.(string), constraint.(string)) 649 }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil { 650 return err 651 } 652 653 case nameTypeURI: 654 name := string(data) 655 uri, err := url.Parse(name) 656 if err != nil { 657 return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name) 658 } 659 660 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri, 661 func(parsedName, constraint interface{}) (bool, error) { 662 return matchURIConstraint(parsedName.(*url.URL), constraint.(string)) 663 }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil { 664 return err 665 } 666 667 case nameTypeIP: 668 ip := net.IP(data) 669 if l := len(ip); l != net.IPv4len && l != net.IPv6len { 670 return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data) 671 } 672 673 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip, 674 func(parsedName, constraint interface{}) (bool, error) { 675 return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet)) 676 }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil { 677 return err 678 } 679 680 default: 681 // Unknown SAN types are ignored. 682 } 683 684 return nil 685 }) 686 687 if err != nil { 688 return err 689 } 690 } 691 692 checkEKUs := certType == intermediateCertificate 693 694 // If no extended key usages are specified, then all are acceptable. 695 if checkEKUs && (len(c.ExtKeyUsage) == 0 && len(c.UnknownExtKeyUsage) == 0) { 696 checkEKUs = false 697 } 698 699 // If the “any” key usage is permitted, then no more checks are needed. 700 if checkEKUs { 701 for _, caEKU := range c.ExtKeyUsage { 702 comparisonCount++ 703 if caEKU == ExtKeyUsageAny { 704 checkEKUs = false 705 break 706 } 707 } 708 } 709 710 if checkEKUs { 711 NextEKU: 712 for _, eku := range leaf.ExtKeyUsage { 713 if comparisonCount > maxConstraintComparisons { 714 return CertificateInvalidError{c, TooManyConstraints, ""} 715 } 716 717 for _, caEKU := range c.ExtKeyUsage { 718 comparisonCount++ 719 if ekuPermittedBy(eku, caEKU) { 720 continue NextEKU 721 } 722 } 723 724 oid, _ := oidFromExtKeyUsage(eku) 725 return CertificateInvalidError{c, CANotAuthorizedForExtKeyUsage, fmt.Sprintf("EKU not permitted: %#v", oid)} 726 } 727 728 NextUnknownEKU: 729 for _, eku := range leaf.UnknownExtKeyUsage { 730 if comparisonCount > maxConstraintComparisons { 731 return CertificateInvalidError{c, TooManyConstraints, ""} 732 } 733 734 for _, caEKU := range c.UnknownExtKeyUsage { 735 comparisonCount++ 736 if caEKU.Equal(eku) { 737 continue NextUnknownEKU 738 } 739 } 740 741 return CertificateInvalidError{c, CANotAuthorizedForExtKeyUsage, fmt.Sprintf("EKU not permitted: %#v", eku)} 742 } 743 } 744 745 // KeyUsage status flags are ignored. From Engineering Security, Peter 746 // Gutmann: A European government CA marked its signing certificates as 747 // being valid for encryption only, but no-one noticed. Another 748 // European CA marked its signature keys as not being valid for 749 // signatures. A different CA marked its own trusted root certificate 750 // as being invalid for certificate signing. Another national CA 751 // distributed a certificate to be used to encrypt data for the 752 // country’s tax authority that was marked as only being usable for 753 // digital signatures but not for encryption. Yet another CA reversed 754 // the order of the bit flags in the keyUsage due to confusion over 755 // encoding endianness, essentially setting a random keyUsage in 756 // certificates that it issued. Another CA created a self-invalidating 757 // certificate by adding a certificate policy statement stipulating 758 // that the certificate had to be used strictly as specified in the 759 // keyUsage, and a keyUsage containing a flag indicating that the RSA 760 // encryption key could only be used for Diffie-Hellman key agreement. 761 762 if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) { 763 return CertificateInvalidError{c, NotAuthorizedToSign, ""} 764 } 765 766 if c.BasicConstraintsValid && c.MaxPathLen >= 0 { 767 numIntermediates := len(currentChain) - 1 768 if numIntermediates > c.MaxPathLen { 769 return CertificateInvalidError{c, TooManyIntermediates, ""} 770 } 771 } 772 773 return nil 774 } 775 776 // Verify attempts to verify c by building one or more chains from c to a 777 // certificate in opts.Roots, using certificates in opts.Intermediates if 778 // needed. If successful, it returns one or more chains where the first 779 // element of the chain is c and the last element is from opts.Roots. 780 // 781 // If opts.Roots is nil and system roots are unavailable the returned error 782 // will be of type SystemRootsError. 783 // 784 // WARNING: this doesn't do any revocation checking. 785 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { 786 // Platform-specific verification needs the ASN.1 contents so 787 // this makes the behavior consistent across platforms. 788 if len(c.Raw) == 0 { 789 return nil, errNotParsed 790 } 791 if opts.Intermediates != nil { 792 for _, intermediate := range opts.Intermediates.certs { 793 if len(intermediate.Raw) == 0 { 794 return nil, errNotParsed 795 } 796 } 797 } 798 799 // Use Windows's own verification and chain building. 800 if opts.Roots == nil && runtime.GOOS == "windows" { 801 return c.systemVerify(&opts) 802 } 803 804 if opts.Roots == nil { 805 opts.Roots = systemRootsPool() 806 if opts.Roots == nil { 807 return nil, SystemRootsError{systemRootsErr} 808 } 809 } 810 811 err = c.isValid(leafCertificate, nil, &opts) 812 if err != nil { 813 return 814 } 815 816 if len(opts.DNSName) > 0 { 817 err = c.VerifyHostname(opts.DNSName) 818 if err != nil { 819 return 820 } 821 } 822 823 requestedKeyUsages := make([]ExtKeyUsage, len(opts.KeyUsages)) 824 copy(requestedKeyUsages, opts.KeyUsages) 825 if len(requestedKeyUsages) == 0 { 826 requestedKeyUsages = append(requestedKeyUsages, ExtKeyUsageServerAuth) 827 } 828 829 // If no key usages are specified, then any are acceptable. 830 checkEKU := len(c.ExtKeyUsage) > 0 831 832 for _, eku := range requestedKeyUsages { 833 if eku == ExtKeyUsageAny { 834 checkEKU = false 835 break 836 } 837 } 838 839 if checkEKU { 840 NextUsage: 841 for _, eku := range requestedKeyUsages { 842 for _, leafEKU := range c.ExtKeyUsage { 843 if ekuPermittedBy(eku, leafEKU) { 844 continue NextUsage 845 } 846 } 847 848 oid, _ := oidFromExtKeyUsage(eku) 849 return nil, CertificateInvalidError{c, IncompatibleUsage, fmt.Sprintf("%#v", oid)} 850 } 851 } 852 853 var candidateChains [][]*Certificate 854 if opts.Roots.contains(c) { 855 candidateChains = append(candidateChains, []*Certificate{c}) 856 } else { 857 if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil { 858 return nil, err 859 } 860 } 861 862 return candidateChains, nil 863 } 864 865 func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { 866 n := make([]*Certificate, len(chain)+1) 867 copy(n, chain) 868 n[len(chain)] = cert 869 return n 870 } 871 872 func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) { 873 possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c) 874 nextRoot: 875 for _, rootNum := range possibleRoots { 876 root := opts.Roots.certs[rootNum] 877 878 for _, cert := range currentChain { 879 if cert.Equal(root) { 880 continue nextRoot 881 } 882 } 883 884 err = root.isValid(rootCertificate, currentChain, opts) 885 if err != nil { 886 continue 887 } 888 chains = append(chains, appendToFreshChain(currentChain, root)) 889 } 890 891 possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c) 892 nextIntermediate: 893 for _, intermediateNum := range possibleIntermediates { 894 intermediate := opts.Intermediates.certs[intermediateNum] 895 for _, cert := range currentChain { 896 if cert.Equal(intermediate) { 897 continue nextIntermediate 898 } 899 } 900 err = intermediate.isValid(intermediateCertificate, currentChain, opts) 901 if err != nil { 902 continue 903 } 904 var childChains [][]*Certificate 905 childChains, ok := cache[intermediateNum] 906 if !ok { 907 childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts) 908 cache[intermediateNum] = childChains 909 } 910 chains = append(chains, childChains...) 911 } 912 913 if len(chains) > 0 { 914 err = nil 915 } 916 917 if len(chains) == 0 && err == nil { 918 hintErr := rootErr 919 hintCert := failedRoot 920 if hintErr == nil { 921 hintErr = intermediateErr 922 hintCert = failedIntermediate 923 } 924 err = UnknownAuthorityError{c, hintErr, hintCert} 925 } 926 927 return 928 } 929 930 func matchHostnames(pattern, host string) bool { 931 host = strings.TrimSuffix(host, ".") 932 pattern = strings.TrimSuffix(pattern, ".") 933 934 if len(pattern) == 0 || len(host) == 0 { 935 return false 936 } 937 938 patternParts := strings.Split(pattern, ".") 939 hostParts := strings.Split(host, ".") 940 941 if len(patternParts) != len(hostParts) { 942 return false 943 } 944 945 for i, patternPart := range patternParts { 946 if i == 0 && patternPart == "*" { 947 continue 948 } 949 if patternPart != hostParts[i] { 950 return false 951 } 952 } 953 954 return true 955 } 956 957 // toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use 958 // an explicitly ASCII function to avoid any sharp corners resulting from 959 // performing Unicode operations on DNS labels. 960 func toLowerCaseASCII(in string) string { 961 // If the string is already lower-case then there's nothing to do. 962 isAlreadyLowerCase := true 963 for _, c := range in { 964 if c == utf8.RuneError { 965 // If we get a UTF-8 error then there might be 966 // upper-case ASCII bytes in the invalid sequence. 967 isAlreadyLowerCase = false 968 break 969 } 970 if 'A' <= c && c <= 'Z' { 971 isAlreadyLowerCase = false 972 break 973 } 974 } 975 976 if isAlreadyLowerCase { 977 return in 978 } 979 980 out := []byte(in) 981 for i, c := range out { 982 if 'A' <= c && c <= 'Z' { 983 out[i] += 'a' - 'A' 984 } 985 } 986 return string(out) 987 } 988 989 // VerifyHostname returns nil if c is a valid certificate for the named host. 990 // Otherwise it returns an error describing the mismatch. 991 func (c *Certificate) VerifyHostname(h string) error { 992 // IP addresses may be written in [ ]. 993 candidateIP := h 994 if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' { 995 candidateIP = h[1 : len(h)-1] 996 } 997 if ip := net.ParseIP(candidateIP); ip != nil { 998 // We only match IP addresses against IP SANs. 999 // https://tools.ietf.org/html/rfc6125#appendix-B.2 1000 for _, candidate := range c.IPAddresses { 1001 if ip.Equal(candidate) { 1002 return nil 1003 } 1004 } 1005 return HostnameError{c, candidateIP} 1006 } 1007 1008 lowered := toLowerCaseASCII(h) 1009 1010 if c.hasSANExtension() { 1011 for _, match := range c.DNSNames { 1012 if matchHostnames(toLowerCaseASCII(match), lowered) { 1013 return nil 1014 } 1015 } 1016 // If Subject Alt Name is given, we ignore the common name. 1017 } else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) { 1018 return nil 1019 } 1020 1021 return HostnameError{c, h} 1022 }