OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/x509_certificate.h" | 5 #include "net/cert/x509_certificate.h" |
6 | 6 |
7 #include <limits.h> | 7 #include <limits.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 bool X509Certificate::Equals(const X509Certificate* other) const { | 486 bool X509Certificate::Equals(const X509Certificate* other) const { |
487 return IsSameOSCert(cert_handle_, other->cert_handle_); | 487 return IsSameOSCert(cert_handle_, other->cert_handle_); |
488 } | 488 } |
489 | 489 |
490 // static | 490 // static |
491 bool X509Certificate::VerifyHostname( | 491 bool X509Certificate::VerifyHostname( |
492 const std::string& hostname, | 492 const std::string& hostname, |
493 const std::string& cert_common_name, | 493 const std::string& cert_common_name, |
494 const std::vector<std::string>& cert_san_dns_names, | 494 const std::vector<std::string>& cert_san_dns_names, |
495 const std::vector<std::string>& cert_san_ip_addrs, | 495 const std::vector<std::string>& cert_san_ip_addrs, |
496 bool* common_name_fallback_used) { | 496 bool allow_common_name_fallback) { |
497 DCHECK(!hostname.empty()); | 497 DCHECK(!hostname.empty()); |
498 // Perform name verification following http://tools.ietf.org/html/rfc6125. | 498 // Perform name verification following http://tools.ietf.org/html/rfc6125. |
499 // The terminology used in this method is as per that RFC:- | 499 // The terminology used in this method is as per that RFC:- |
500 // Reference identifier == the host the local user/agent is intending to | 500 // Reference identifier == the host the local user/agent is intending to |
501 // access, i.e. the thing displayed in the URL bar. | 501 // access, i.e. the thing displayed in the URL bar. |
502 // Presented identifier(s) == name(s) the server knows itself as, in its cert. | 502 // Presented identifier(s) == name(s) the server knows itself as, in its cert. |
503 | 503 |
504 // CanonicalizeHost requires surrounding brackets to parse an IPv6 address. | 504 // CanonicalizeHost requires surrounding brackets to parse an IPv6 address. |
505 const std::string host_or_ip = hostname.find(':') != std::string::npos ? | 505 const std::string host_or_ip = hostname.find(':') != std::string::npos ? |
506 "[" + hostname + "]" : hostname; | 506 "[" + hostname + "]" : hostname; |
507 url::CanonHostInfo host_info; | 507 url::CanonHostInfo host_info; |
508 std::string reference_name = CanonicalizeHost(host_or_ip, &host_info); | 508 std::string reference_name = CanonicalizeHost(host_or_ip, &host_info); |
509 // CanonicalizeHost does not normalize absolute vs relative DNS names. If | 509 // CanonicalizeHost does not normalize absolute vs relative DNS names. If |
510 // the input name was absolute (included trailing .), normalize it as if it | 510 // the input name was absolute (included trailing .), normalize it as if it |
511 // was relative. | 511 // was relative. |
512 if (!reference_name.empty() && *reference_name.rbegin() == '.') | 512 if (!reference_name.empty() && *reference_name.rbegin() == '.') |
513 reference_name.resize(reference_name.size() - 1); | 513 reference_name.resize(reference_name.size() - 1); |
514 if (reference_name.empty()) | 514 if (reference_name.empty()) |
515 return false; | 515 return false; |
516 | 516 |
517 // Allow fallback to Common name matching? | 517 if (!allow_common_name_fallback && cert_san_dns_names.empty() && |
518 const bool common_name_fallback = cert_san_dns_names.empty() && | 518 cert_san_ip_addrs.empty()) { |
519 cert_san_ip_addrs.empty(); | 519 // Common Name matching is not allowed, so fail fast. |
520 *common_name_fallback_used = common_name_fallback; | 520 return false; |
| 521 } |
521 | 522 |
522 // Fully handle all cases where |hostname| contains an IP address. | 523 // Fully handle all cases where |hostname| contains an IP address. |
523 if (host_info.IsIPAddress()) { | 524 if (host_info.IsIPAddress()) { |
524 if (common_name_fallback && host_info.family == url::CanonHostInfo::IPV4) { | 525 if (allow_common_name_fallback && cert_san_dns_names.empty() && |
| 526 cert_san_ip_addrs.empty() && |
| 527 host_info.family == url::CanonHostInfo::IPV4) { |
525 // Fallback to Common name matching. As this is deprecated and only | 528 // Fallback to Common name matching. As this is deprecated and only |
526 // supported for compatibility refuse it for IPv6 addresses. | 529 // supported for compatibility refuse it for IPv6 addresses. |
527 return reference_name == cert_common_name; | 530 return reference_name == cert_common_name; |
528 } | 531 } |
529 base::StringPiece ip_addr_string( | 532 base::StringPiece ip_addr_string( |
530 reinterpret_cast<const char*>(host_info.address), | 533 reinterpret_cast<const char*>(host_info.address), |
531 host_info.AddressLength()); | 534 host_info.AddressLength()); |
532 return std::find(cert_san_ip_addrs.begin(), cert_san_ip_addrs.end(), | 535 return std::find(cert_san_ip_addrs.begin(), cert_san_ip_addrs.end(), |
533 ip_addr_string) != cert_san_ip_addrs.end(); | 536 ip_addr_string) != cert_san_ip_addrs.end(); |
534 } | 537 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 allow_wildcards = | 576 allow_wildcards = |
574 !is_registry_controlled && | 577 !is_registry_controlled && |
575 reference_name.find_first_not_of("0123456789.") != std::string::npos; | 578 reference_name.find_first_not_of("0123456789.") != std::string::npos; |
576 } | 579 } |
577 | 580 |
578 // Now step through the DNS names doing wild card comparison (if necessary) | 581 // Now step through the DNS names doing wild card comparison (if necessary) |
579 // on each against the reference name. If subjectAltName is empty, then | 582 // on each against the reference name. If subjectAltName is empty, then |
580 // fallback to use the common name instead. | 583 // fallback to use the common name instead. |
581 std::vector<std::string> common_name_as_vector; | 584 std::vector<std::string> common_name_as_vector; |
582 const std::vector<std::string>* presented_names = &cert_san_dns_names; | 585 const std::vector<std::string>* presented_names = &cert_san_dns_names; |
583 if (common_name_fallback) { | 586 if (allow_common_name_fallback && cert_san_dns_names.empty() && |
| 587 cert_san_ip_addrs.empty()) { |
584 // Note: there's a small possibility cert_common_name is an international | 588 // Note: there's a small possibility cert_common_name is an international |
585 // domain name in non-standard encoding (e.g. UTF8String or BMPString | 589 // domain name in non-standard encoding (e.g. UTF8String or BMPString |
586 // instead of A-label). As common name fallback is deprecated we're not | 590 // instead of A-label). As common name fallback is deprecated we're not |
587 // doing anything specific to deal with this. | 591 // doing anything specific to deal with this. |
588 common_name_as_vector.push_back(cert_common_name); | 592 common_name_as_vector.push_back(cert_common_name); |
589 presented_names = &common_name_as_vector; | 593 presented_names = &common_name_as_vector; |
590 } | 594 } |
591 for (std::vector<std::string>::const_iterator it = | 595 for (std::vector<std::string>::const_iterator it = |
592 presented_names->begin(); | 596 presented_names->begin(); |
593 it != presented_names->end(); ++it) { | 597 it != presented_names->end(); ++it) { |
(...skipping 27 matching lines...) Expand all Loading... |
621 | 625 |
622 if (!allow_wildcards) | 626 if (!allow_wildcards) |
623 continue; | 627 continue; |
624 | 628 |
625 return true; | 629 return true; |
626 } | 630 } |
627 return false; | 631 return false; |
628 } | 632 } |
629 | 633 |
630 bool X509Certificate::VerifyNameMatch(const std::string& hostname, | 634 bool X509Certificate::VerifyNameMatch(const std::string& hostname, |
631 bool* common_name_fallback_used) const { | 635 bool allow_common_name_fallback) const { |
632 std::vector<std::string> dns_names, ip_addrs; | 636 std::vector<std::string> dns_names, ip_addrs; |
633 GetSubjectAltName(&dns_names, &ip_addrs); | 637 GetSubjectAltName(&dns_names, &ip_addrs); |
634 return VerifyHostname(hostname, subject_.common_name, dns_names, ip_addrs, | 638 return VerifyHostname(hostname, subject_.common_name, dns_names, ip_addrs, |
635 common_name_fallback_used); | 639 allow_common_name_fallback); |
636 } | 640 } |
637 | 641 |
638 // static | 642 // static |
639 bool X509Certificate::GetPEMEncodedFromDER(const std::string& der_encoded, | 643 bool X509Certificate::GetPEMEncodedFromDER(const std::string& der_encoded, |
640 std::string* pem_encoded) { | 644 std::string* pem_encoded) { |
641 if (der_encoded.empty()) | 645 if (der_encoded.empty()) |
642 return false; | 646 return false; |
643 std::string b64_encoded; | 647 std::string b64_encoded; |
644 base::Base64Encode(der_encoded, &b64_encoded); | 648 base::Base64Encode(der_encoded, &b64_encoded); |
645 *pem_encoded = "-----BEGIN CERTIFICATE-----\n"; | 649 *pem_encoded = "-----BEGIN CERTIFICATE-----\n"; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 RemoveFromCache(cert_handle_); | 719 RemoveFromCache(cert_handle_); |
716 FreeOSCertHandle(cert_handle_); | 720 FreeOSCertHandle(cert_handle_); |
717 } | 721 } |
718 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { | 722 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { |
719 RemoveFromCache(intermediate_ca_certs_[i]); | 723 RemoveFromCache(intermediate_ca_certs_[i]); |
720 FreeOSCertHandle(intermediate_ca_certs_[i]); | 724 FreeOSCertHandle(intermediate_ca_certs_[i]); |
721 } | 725 } |
722 } | 726 } |
723 | 727 |
724 } // namespace net | 728 } // namespace net |
OLD | NEW |