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/http/transport_security_state.h" | 5 #include "net/http/transport_security_state.h" |
6 | 6 |
7 #if defined(USE_OPENSSL) | 7 #if defined(USE_OPENSSL) |
8 #include <openssl/ecdsa.h> | 8 #include <openssl/ecdsa.h> |
9 #include <openssl/ssl.h> | 9 #include <openssl/ssl.h> |
10 #else // !defined(USE_OPENSSL) | 10 #else // !defined(USE_OPENSSL) |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 return true; | 512 return true; |
513 } | 513 } |
514 | 514 |
515 return false; | 515 return false; |
516 } | 516 } |
517 | 517 |
518 bool TransportSecurityState::CheckPublicKeyPins( | 518 bool TransportSecurityState::CheckPublicKeyPins( |
519 const std::string& host, | 519 const std::string& host, |
520 bool is_issued_by_known_root, | 520 bool is_issued_by_known_root, |
521 const HashValueVector& public_key_hashes, | 521 const HashValueVector& public_key_hashes, |
| 522 uint16_t port, |
| 523 const scoped_refptr<X509Certificate>& served_certificate_chain, |
| 524 const scoped_refptr<X509Certificate>& validated_certificate_chain, |
| 525 const PublicKeyPinReportStatus report_status, |
522 std::string* pinning_failure_log) { | 526 std::string* pinning_failure_log) { |
523 // Perform pin validation if, and only if, all these conditions obtain: | 527 // Perform pin validation if, and only if, all these conditions obtain: |
524 // | 528 // |
525 // * the server's certificate chain chains up to a known root (i.e. not a | 529 // * the server's certificate chain chains up to a known root (i.e. not a |
526 // user-installed trust anchor); and | 530 // user-installed trust anchor); and |
527 // * the server actually has public key pins. | 531 // * the server actually has public key pins. |
528 if (!is_issued_by_known_root || !HasPublicKeyPins(host)) { | 532 if (!is_issued_by_known_root || !HasPublicKeyPins(host)) { |
529 return true; | 533 return true; |
530 } | 534 } |
531 | 535 |
532 bool pins_are_valid = | 536 bool pins_are_valid = CheckPublicKeyPinsImpl( |
533 CheckPublicKeyPinsImpl(host, public_key_hashes, pinning_failure_log); | 537 host, public_key_hashes, port, served_certificate_chain, |
| 538 validated_certificate_chain, report_status, pinning_failure_log); |
534 if (!pins_are_valid) { | 539 if (!pins_are_valid) { |
535 LOG(ERROR) << *pinning_failure_log; | 540 LOG(ERROR) << *pinning_failure_log; |
536 ReportUMAOnPinFailure(host); | 541 ReportUMAOnPinFailure(host); |
537 } | 542 } |
538 | 543 |
539 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); | 544 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); |
540 return pins_are_valid; | 545 return pins_are_valid; |
541 } | 546 } |
542 | 547 |
543 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { | 548 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) { |
544 DomainState dynamic_state; | 549 DomainState dynamic_state; |
545 if (GetDynamicDomainState(host, &dynamic_state)) | 550 if (GetDynamicDomainState(host, &dynamic_state)) |
546 return dynamic_state.HasPublicKeyPins(); | 551 return dynamic_state.HasPublicKeyPins(); |
547 | 552 |
548 DomainState static_state; | 553 DomainState static_state; |
549 if (GetStaticDomainState(host, &static_state)) { | 554 if (GetStaticDomainState(host, &static_state)) { |
550 if (static_state.HasPublicKeyPins()) | 555 if (static_state.HasPublicKeyPins()) |
551 return true; | 556 return true; |
552 } | 557 } |
553 | 558 |
554 return false; | 559 return false; |
555 } | 560 } |
556 | 561 |
557 void TransportSecurityState::SetDelegate( | 562 void TransportSecurityState::SetDelegate( |
558 TransportSecurityState::Delegate* delegate) { | 563 TransportSecurityState::Delegate* delegate) { |
559 DCHECK(CalledOnValidThread()); | 564 DCHECK(CalledOnValidThread()); |
560 delegate_ = delegate; | 565 delegate_ = delegate; |
561 } | 566 } |
562 | 567 |
| 568 void TransportSecurityState::SetReporter( |
| 569 TransportSecurityState::Reporter* reporter) { |
| 570 DCHECK(CalledOnValidThread()); |
| 571 reporter_ = reporter; |
| 572 } |
| 573 |
563 void TransportSecurityState::AddHSTSInternal( | 574 void TransportSecurityState::AddHSTSInternal( |
564 const std::string& host, | 575 const std::string& host, |
565 TransportSecurityState::DomainState::UpgradeMode upgrade_mode, | 576 TransportSecurityState::DomainState::UpgradeMode upgrade_mode, |
566 const base::Time& expiry, | 577 const base::Time& expiry, |
567 bool include_subdomains) { | 578 bool include_subdomains) { |
568 DCHECK(CalledOnValidThread()); | 579 DCHECK(CalledOnValidThread()); |
569 | 580 |
570 // Copy-and-modify the existing DomainState for this host (if any). | 581 // Copy-and-modify the existing DomainState for this host (if any). |
571 DomainState domain_state; | 582 DomainState domain_state; |
572 const std::string canonicalized_host = CanonicalizeHost(host); | 583 const std::string canonicalized_host = CanonicalizeHost(host); |
573 const std::string hashed_host = HashHost(canonicalized_host); | 584 const std::string hashed_host = HashHost(canonicalized_host); |
574 DomainStateMap::const_iterator i = enabled_hosts_.find(hashed_host); | 585 DomainStateMap::const_iterator i = enabled_hosts_.find(hashed_host); |
575 if (i != enabled_hosts_.end()) | 586 if (i != enabled_hosts_.end()) |
576 domain_state = i->second; | 587 domain_state = i->second; |
577 | 588 |
578 domain_state.sts.last_observed = base::Time::Now(); | 589 domain_state.sts.last_observed = base::Time::Now(); |
579 domain_state.sts.include_subdomains = include_subdomains; | 590 domain_state.sts.include_subdomains = include_subdomains; |
580 domain_state.sts.expiry = expiry; | 591 domain_state.sts.expiry = expiry; |
581 domain_state.sts.upgrade_mode = upgrade_mode; | 592 domain_state.sts.upgrade_mode = upgrade_mode; |
582 EnableHost(host, domain_state); | 593 EnableHost(host, domain_state); |
583 } | 594 } |
584 | 595 |
585 void TransportSecurityState::AddHPKPInternal(const std::string& host, | 596 void TransportSecurityState::AddHPKPInternal(const std::string& host, |
586 const base::Time& last_observed, | 597 const base::Time& last_observed, |
587 const base::Time& expiry, | 598 const base::Time& expiry, |
588 bool include_subdomains, | 599 bool include_subdomains, |
589 const HashValueVector& hashes) { | 600 const HashValueVector& hashes, |
| 601 const std::string& report_uri) { |
590 DCHECK(CalledOnValidThread()); | 602 DCHECK(CalledOnValidThread()); |
591 | 603 |
592 // Copy-and-modify the existing DomainState for this host (if any). | 604 // Copy-and-modify the existing DomainState for this host (if any). |
593 DomainState domain_state; | 605 DomainState domain_state; |
594 const std::string canonicalized_host = CanonicalizeHost(host); | 606 const std::string canonicalized_host = CanonicalizeHost(host); |
595 const std::string hashed_host = HashHost(canonicalized_host); | 607 const std::string hashed_host = HashHost(canonicalized_host); |
596 DomainStateMap::const_iterator i = enabled_hosts_.find(hashed_host); | 608 DomainStateMap::const_iterator i = enabled_hosts_.find(hashed_host); |
597 if (i != enabled_hosts_.end()) | 609 if (i != enabled_hosts_.end()) |
598 domain_state = i->second; | 610 domain_state = i->second; |
599 | 611 |
600 domain_state.pkp.last_observed = last_observed; | 612 domain_state.pkp.last_observed = last_observed; |
601 domain_state.pkp.expiry = expiry; | 613 domain_state.pkp.expiry = expiry; |
602 domain_state.pkp.include_subdomains = include_subdomains; | 614 domain_state.pkp.include_subdomains = include_subdomains; |
603 domain_state.pkp.spki_hashes = hashes; | 615 domain_state.pkp.spki_hashes = hashes; |
| 616 domain_state.pkp.report_uri = report_uri; |
604 EnableHost(host, domain_state); | 617 EnableHost(host, domain_state); |
605 } | 618 } |
606 | 619 |
607 void TransportSecurityState::EnableHost(const std::string& host, | 620 void TransportSecurityState::EnableHost(const std::string& host, |
608 const DomainState& state) { | 621 const DomainState& state) { |
609 DCHECK(CalledOnValidThread()); | 622 DCHECK(CalledOnValidThread()); |
610 | 623 |
611 const std::string canonicalized_host = CanonicalizeHost(host); | 624 const std::string canonicalized_host = CanonicalizeHost(host); |
612 if (canonicalized_host.empty()) | 625 if (canonicalized_host.empty()) |
613 return; | 626 return; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 | 724 |
712 bool TransportSecurityState::AddHPKPHeader(const std::string& host, | 725 bool TransportSecurityState::AddHPKPHeader(const std::string& host, |
713 const std::string& value, | 726 const std::string& value, |
714 const SSLInfo& ssl_info) { | 727 const SSLInfo& ssl_info) { |
715 DCHECK(CalledOnValidThread()); | 728 DCHECK(CalledOnValidThread()); |
716 | 729 |
717 base::Time now = base::Time::Now(); | 730 base::Time now = base::Time::Now(); |
718 base::TimeDelta max_age; | 731 base::TimeDelta max_age; |
719 bool include_subdomains; | 732 bool include_subdomains; |
720 HashValueVector spki_hashes; | 733 HashValueVector spki_hashes; |
| 734 std::string report_uri; |
| 735 |
721 if (!ParseHPKPHeader(value, ssl_info.public_key_hashes, &max_age, | 736 if (!ParseHPKPHeader(value, ssl_info.public_key_hashes, &max_age, |
722 &include_subdomains, &spki_hashes)) { | 737 &include_subdomains, &spki_hashes, &report_uri)) { |
723 return false; | 738 return false; |
724 } | 739 } |
725 // Handle max-age == 0. | 740 // Handle max-age == 0. |
726 if (max_age.InSeconds() == 0) | 741 if (max_age.InSeconds() == 0) |
727 spki_hashes.clear(); | 742 spki_hashes.clear(); |
728 AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes); | 743 AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes, |
| 744 report_uri); |
729 return true; | 745 return true; |
730 } | 746 } |
731 | 747 |
732 void TransportSecurityState::AddHSTS(const std::string& host, | 748 void TransportSecurityState::AddHSTS(const std::string& host, |
733 const base::Time& expiry, | 749 const base::Time& expiry, |
734 bool include_subdomains) { | 750 bool include_subdomains) { |
735 DCHECK(CalledOnValidThread()); | 751 DCHECK(CalledOnValidThread()); |
736 AddHSTSInternal(host, DomainState::MODE_FORCE_HTTPS, expiry, | 752 AddHSTSInternal(host, DomainState::MODE_FORCE_HTTPS, expiry, |
737 include_subdomains); | 753 include_subdomains); |
738 } | 754 } |
739 | 755 |
740 void TransportSecurityState::AddHPKP(const std::string& host, | 756 void TransportSecurityState::AddHPKP(const std::string& host, |
741 const base::Time& expiry, | 757 const base::Time& expiry, |
742 bool include_subdomains, | 758 bool include_subdomains, |
743 const HashValueVector& hashes) { | 759 const HashValueVector& hashes, |
| 760 const std::string& report_uri) { |
744 DCHECK(CalledOnValidThread()); | 761 DCHECK(CalledOnValidThread()); |
745 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes); | 762 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes, |
| 763 report_uri); |
746 } | 764 } |
747 | 765 |
748 // static | 766 // static |
749 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) { | 767 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) { |
750 PreloadResult result; | 768 PreloadResult result; |
751 return DecodeHSTSPreload(host, &result) && result.has_pins && | 769 return DecodeHSTSPreload(host, &result) && result.has_pins && |
752 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts; | 770 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts; |
753 } | 771 } |
754 | 772 |
755 // static | 773 // static |
(...skipping 22 matching lines...) Expand all Loading... |
778 #else | 796 #else |
779 const base::Time build_time = base::GetBuildTime(); | 797 const base::Time build_time = base::GetBuildTime(); |
780 // We consider built-in information to be timely for 10 weeks. | 798 // We consider built-in information to be timely for 10 weeks. |
781 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 799 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
782 #endif | 800 #endif |
783 } | 801 } |
784 | 802 |
785 bool TransportSecurityState::CheckPublicKeyPinsImpl( | 803 bool TransportSecurityState::CheckPublicKeyPinsImpl( |
786 const std::string& host, | 804 const std::string& host, |
787 const HashValueVector& hashes, | 805 const HashValueVector& hashes, |
| 806 uint16_t port, |
| 807 const scoped_refptr<X509Certificate>& served_certificate_chain, |
| 808 const scoped_refptr<X509Certificate>& validated_certificate_chain, |
| 809 const PublicKeyPinReportStatus report_status, |
788 std::string* failure_log) { | 810 std::string* failure_log) { |
789 DomainState dynamic_state; | 811 DomainState dynamic_state; |
790 if (GetDynamicDomainState(host, &dynamic_state)) | 812 if (GetDynamicDomainState(host, &dynamic_state)) { |
791 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); | 813 bool result = dynamic_state.CheckPublicKeyPins(hashes, failure_log); |
| 814 |
| 815 if (result || !reporter_ || |
| 816 report_status == DO_NOT_SEND_PUBLIC_KEY_PIN_REPORT) |
| 817 return result; |
| 818 |
| 819 GURL report_uri; |
| 820 std::string serialized_report; |
| 821 |
| 822 if (!reporter_->GetHPKPReportUri(dynamic_state.pkp, &report_uri)) |
| 823 return result; |
| 824 |
| 825 if (!reporter_->BuildHPKPReport( |
| 826 host, port, dynamic_state.pkp.expiry, |
| 827 dynamic_state.pkp.include_subdomains, dynamic_state.pkp.domain, |
| 828 served_certificate_chain, validated_certificate_chain, |
| 829 dynamic_state.pkp.spki_hashes, &serialized_report)) { |
| 830 LOG(ERROR) << "Failed to build HPKP report"; |
| 831 return result; |
| 832 } |
| 833 |
| 834 reporter_->SendHPKPReport(report_uri, serialized_report); |
| 835 } |
792 | 836 |
793 DomainState static_state; | 837 DomainState static_state; |
794 if (GetStaticDomainState(host, &static_state)) | 838 if (GetStaticDomainState(host, &static_state)) |
795 return static_state.CheckPublicKeyPins(hashes, failure_log); | 839 return static_state.CheckPublicKeyPins(hashes, failure_log); |
796 | 840 |
797 // HasPublicKeyPins should have returned true in order for this method | 841 // HasPublicKeyPins should have returned true in order for this method |
798 // to have been called, so if we fall through to here, it's an error. | 842 // to have been called, so if we fall through to here, it's an error. |
799 return false; | 843 return false; |
800 } | 844 } |
801 | 845 |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 TransportSecurityState::DomainState::STSState::~STSState() { | 1037 TransportSecurityState::DomainState::STSState::~STSState() { |
994 } | 1038 } |
995 | 1039 |
996 TransportSecurityState::DomainState::PKPState::PKPState() { | 1040 TransportSecurityState::DomainState::PKPState::PKPState() { |
997 } | 1041 } |
998 | 1042 |
999 TransportSecurityState::DomainState::PKPState::~PKPState() { | 1043 TransportSecurityState::DomainState::PKPState::~PKPState() { |
1000 } | 1044 } |
1001 | 1045 |
1002 } // namespace | 1046 } // namespace |
OLD | NEW |