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