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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 HashValueVector* out) { | 77 HashValueVector* out) { |
78 HashValue hash(HASH_VALUE_SHA1); | 78 HashValue hash(HASH_VALUE_SHA1); |
79 memcpy(hash.data(), sha1_hash, hash.size()); | 79 memcpy(hash.data(), sha1_hash, hash.size()); |
80 out->push_back(hash); | 80 out->push_back(hash); |
81 return true; | 81 return true; |
82 } | 82 } |
83 | 83 |
84 } // namespace | 84 } // namespace |
85 | 85 |
86 TransportSecurityState::TransportSecurityState() | 86 TransportSecurityState::TransportSecurityState() |
87 : delegate_(NULL) { | 87 : delegate_(NULL), enable_static_pins_(true) { |
| 88 // Static pinning is only enabled for official builds to make sure that |
| 89 // others don't end up with pins that cannot be easily updated. |
| 90 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS) |
| 91 enable_static_pins_ = false; |
| 92 #endif |
88 DCHECK(CalledOnValidThread()); | 93 DCHECK(CalledOnValidThread()); |
89 } | 94 } |
90 | 95 |
91 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) | 96 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) |
92 : iterator_(state.enabled_hosts_.begin()), | 97 : iterator_(state.enabled_hosts_.begin()), |
93 end_(state.enabled_hosts_.end()) { | 98 end_(state.enabled_hosts_.end()) { |
94 } | 99 } |
95 | 100 |
96 TransportSecurityState::Iterator::~Iterator() {} | 101 TransportSecurityState::Iterator::~Iterator() {} |
97 | 102 |
(...skipping 13 matching lines...) Expand all Loading... |
111 | 116 |
112 DomainState static_state; | 117 DomainState static_state; |
113 if (GetStaticDomainState(host, sni_enabled, &static_state) && | 118 if (GetStaticDomainState(host, sni_enabled, &static_state) && |
114 static_state.ShouldUpgradeToSSL()) { | 119 static_state.ShouldUpgradeToSSL()) { |
115 return true; | 120 return true; |
116 } | 121 } |
117 | 122 |
118 return false; | 123 return false; |
119 } | 124 } |
120 | 125 |
121 bool TransportSecurityState::CheckPublicKeyPins(const std::string& host, | 126 bool TransportSecurityState::CheckPublicKeyPins( |
122 bool sni_enabled, | 127 const std::string& host, |
123 const HashValueVector& hashes, | 128 bool sni_available, |
124 std::string* failure_log) { | 129 bool is_issued_by_known_root, |
125 DomainState dynamic_state; | 130 const HashValueVector& public_key_hashes, |
126 if (GetDynamicDomainState(host, &dynamic_state)) | 131 std::string* pinning_failure_log) { |
127 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); | 132 // Perform pin validation if, and only if, all these conditions obtain: |
128 | 133 // |
129 DomainState static_state; | 134 // * the server's certificate chain chains up to a known root (i.e. not a |
130 if (GetStaticDomainState(host, sni_enabled, &static_state) && | 135 // user-installed trust anchor); and |
131 static_state.CheckPublicKeyPins(hashes, failure_log)) { | 136 // * the build is recent (very old builds should fail open so that users |
132 return true; | 137 // have some chance to recover). |
| 138 // * the server actually has public key pins. |
| 139 // |
| 140 // TODO(rsleevi): http://crbug.com/391032 - Only disable static HPKP if the |
| 141 // build is not timely. |
| 142 if (!is_issued_by_known_root || !IsBuildTimely() || |
| 143 !HasPublicKeyPins(host, sni_available)) { |
| 144 return true; |
133 } | 145 } |
134 | 146 |
135 return false; | 147 bool pins_are_valid = CheckPublicKeyPinsImpl( |
| 148 host, sni_available, public_key_hashes, pinning_failure_log); |
| 149 if (!pins_are_valid) { |
| 150 LOG(ERROR) << *pinning_failure_log; |
| 151 ReportUMAOnPinFailure(host); |
| 152 } |
| 153 |
| 154 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); |
| 155 return pins_are_valid; |
136 } | 156 } |
137 | 157 |
138 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, | 158 bool TransportSecurityState::HasPublicKeyPins(const std::string& host, |
139 bool sni_enabled) { | 159 bool sni_enabled) { |
140 DomainState dynamic_state; | 160 DomainState dynamic_state; |
141 if (GetDynamicDomainState(host, &dynamic_state)) | 161 if (GetDynamicDomainState(host, &dynamic_state)) |
142 return dynamic_state.HasPublicKeyPins(); | 162 return dynamic_state.HasPublicKeyPins(); |
143 | 163 |
144 DomainState static_state; | 164 DomainState static_state; |
145 if (GetStaticDomainState(host, sni_enabled, &static_state)) { | 165 if (GetStaticDomainState(host, sni_enabled, &static_state)) { |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 | 562 |
543 struct HSTSPreload { | 563 struct HSTSPreload { |
544 uint8 length; | 564 uint8 length; |
545 bool include_subdomains; | 565 bool include_subdomains; |
546 char dns_name[38]; | 566 char dns_name[38]; |
547 bool https_required; | 567 bool https_required; |
548 PublicKeyPins pins; | 568 PublicKeyPins pins; |
549 SecondLevelDomainName second_level_domain_name; | 569 SecondLevelDomainName second_level_domain_name; |
550 }; | 570 }; |
551 | 571 |
552 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, | 572 static bool HasPreload(const struct HSTSPreload* entries, |
553 const std::string& canonicalized_host, size_t i, | 573 size_t num_entries, |
554 TransportSecurityState::DomainState* out, bool* ret) { | 574 const std::string& canonicalized_host, |
| 575 size_t i, |
| 576 bool enable_static_pins, |
| 577 TransportSecurityState::DomainState* out, |
| 578 bool* ret) { |
555 for (size_t j = 0; j < num_entries; j++) { | 579 for (size_t j = 0; j < num_entries; j++) { |
556 if (entries[j].length == canonicalized_host.size() - i && | 580 if (entries[j].length == canonicalized_host.size() - i && |
557 memcmp(entries[j].dns_name, &canonicalized_host[i], | 581 memcmp(entries[j].dns_name, &canonicalized_host[i], |
558 entries[j].length) == 0) { | 582 entries[j].length) == 0) { |
559 if (!entries[j].include_subdomains && i != 0) { | 583 if (!entries[j].include_subdomains && i != 0) { |
560 *ret = false; | 584 *ret = false; |
561 } else { | 585 } else { |
562 out->sts.include_subdomains = entries[j].include_subdomains; | 586 out->sts.include_subdomains = entries[j].include_subdomains; |
563 out->sts.last_observed = base::GetBuildTime(); | 587 out->sts.last_observed = base::GetBuildTime(); |
564 out->pkp.include_subdomains = entries[j].include_subdomains; | |
565 out->pkp.last_observed = base::GetBuildTime(); | |
566 *ret = true; | 588 *ret = true; |
567 out->sts.upgrade_mode = | 589 out->sts.upgrade_mode = |
568 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; | 590 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; |
569 if (!entries[j].https_required) | 591 if (!entries[j].https_required) |
570 out->sts.upgrade_mode = | 592 out->sts.upgrade_mode = |
571 TransportSecurityState::DomainState::MODE_DEFAULT; | 593 TransportSecurityState::DomainState::MODE_DEFAULT; |
572 if (entries[j].pins.required_hashes) { | 594 |
573 const char* const* sha1_hash = entries[j].pins.required_hashes; | 595 if (enable_static_pins) { |
574 while (*sha1_hash) { | 596 out->pkp.include_subdomains = entries[j].include_subdomains; |
575 AddHash(*sha1_hash, &out->pkp.spki_hashes); | 597 out->pkp.last_observed = base::GetBuildTime(); |
576 sha1_hash++; | 598 if (entries[j].pins.required_hashes) { |
| 599 const char* const* sha1_hash = entries[j].pins.required_hashes; |
| 600 while (*sha1_hash) { |
| 601 AddHash(*sha1_hash, &out->pkp.spki_hashes); |
| 602 sha1_hash++; |
| 603 } |
577 } | 604 } |
578 } | 605 if (entries[j].pins.excluded_hashes) { |
579 if (entries[j].pins.excluded_hashes) { | 606 const char* const* sha1_hash = entries[j].pins.excluded_hashes; |
580 const char* const* sha1_hash = entries[j].pins.excluded_hashes; | 607 while (*sha1_hash) { |
581 while (*sha1_hash) { | 608 AddHash(*sha1_hash, &out->pkp.bad_spki_hashes); |
582 AddHash(*sha1_hash, &out->pkp.bad_spki_hashes); | 609 sha1_hash++; |
583 sha1_hash++; | 610 } |
584 } | 611 } |
585 } | 612 } |
586 } | 613 } |
587 return true; | 614 return true; |
588 } | 615 } |
589 } | 616 } |
590 return false; | 617 return false; |
591 } | 618 } |
592 | 619 |
593 #include "net/http/transport_security_state_static.h" | 620 #include "net/http/transport_security_state_static.h" |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); | 783 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); |
757 } | 784 } |
758 | 785 |
759 // static | 786 // static |
760 bool TransportSecurityState::IsBuildTimely() { | 787 bool TransportSecurityState::IsBuildTimely() { |
761 const base::Time build_time = base::GetBuildTime(); | 788 const base::Time build_time = base::GetBuildTime(); |
762 // We consider built-in information to be timely for 10 weeks. | 789 // We consider built-in information to be timely for 10 weeks. |
763 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; | 790 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; |
764 } | 791 } |
765 | 792 |
| 793 bool TransportSecurityState::CheckPublicKeyPinsImpl( |
| 794 const std::string& host, |
| 795 bool sni_enabled, |
| 796 const HashValueVector& hashes, |
| 797 std::string* failure_log) { |
| 798 DomainState dynamic_state; |
| 799 if (GetDynamicDomainState(host, &dynamic_state)) |
| 800 return dynamic_state.CheckPublicKeyPins(hashes, failure_log); |
| 801 |
| 802 DomainState static_state; |
| 803 if (GetStaticDomainState(host, sni_enabled, &static_state)) |
| 804 return static_state.CheckPublicKeyPins(hashes, failure_log); |
| 805 |
| 806 // HasPublicKeyPins should have returned true in order for this method |
| 807 // to have been called, so if we fall through to here, it's an error. |
| 808 return false; |
| 809 } |
| 810 |
766 bool TransportSecurityState::GetStaticDomainState(const std::string& host, | 811 bool TransportSecurityState::GetStaticDomainState(const std::string& host, |
767 bool sni_enabled, | 812 bool sni_enabled, |
768 DomainState* out) const { | 813 DomainState* out) const { |
769 DCHECK(CalledOnValidThread()); | 814 DCHECK(CalledOnValidThread()); |
770 | 815 |
771 const std::string canonicalized_host = CanonicalizeHost(host); | 816 const std::string canonicalized_host = CanonicalizeHost(host); |
772 | 817 |
773 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; | 818 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; |
774 out->sts.include_subdomains = false; | 819 out->sts.include_subdomains = false; |
775 out->pkp.include_subdomains = false; | 820 out->pkp.include_subdomains = false; |
776 | 821 |
777 const bool is_build_timely = IsBuildTimely(); | 822 const bool is_build_timely = IsBuildTimely(); |
778 | 823 |
779 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { | 824 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { |
780 std::string host_sub_chunk(&canonicalized_host[i], | 825 std::string host_sub_chunk(&canonicalized_host[i], |
781 canonicalized_host.size() - i); | 826 canonicalized_host.size() - i); |
782 out->domain = DNSDomainToString(host_sub_chunk); | 827 out->domain = DNSDomainToString(host_sub_chunk); |
783 bool ret; | 828 bool ret; |
784 if (is_build_timely && | 829 if (is_build_timely && HasPreload(kPreloadedSTS, |
785 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, | 830 kNumPreloadedSTS, |
786 &ret)) { | 831 canonicalized_host, |
| 832 i, |
| 833 enable_static_pins_, |
| 834 out, |
| 835 &ret)) { |
787 return ret; | 836 return ret; |
788 } | 837 } |
789 if (sni_enabled && | 838 if (sni_enabled && is_build_timely && HasPreload(kPreloadedSNISTS, |
790 is_build_timely && | 839 kNumPreloadedSNISTS, |
791 HasPreload(kPreloadedSNISTS, kNumPreloadedSNISTS, canonicalized_host, i, | 840 canonicalized_host, |
792 out, &ret)) { | 841 i, |
| 842 enable_static_pins_, |
| 843 out, |
| 844 &ret)) { |
793 return ret; | 845 return ret; |
794 } | 846 } |
795 } | 847 } |
796 | 848 |
797 return false; | 849 return false; |
798 } | 850 } |
799 | 851 |
800 bool TransportSecurityState::GetDynamicDomainState(const std::string& host, | 852 bool TransportSecurityState::GetDynamicDomainState(const std::string& host, |
801 DomainState* result) { | 853 DomainState* result) { |
802 DCHECK(CalledOnValidThread()); | 854 DCHECK(CalledOnValidThread()); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; | 953 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; |
902 } | 954 } |
903 | 955 |
904 TransportSecurityState::DomainState::PKPState::PKPState() { | 956 TransportSecurityState::DomainState::PKPState::PKPState() { |
905 } | 957 } |
906 | 958 |
907 TransportSecurityState::DomainState::PKPState::~PKPState() { | 959 TransportSecurityState::DomainState::PKPState::~PKPState() { |
908 } | 960 } |
909 | 961 |
910 } // namespace | 962 } // namespace |
OLD | NEW |