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