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