Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: net/http/transport_security_state.cc

Issue 103803012: Make HSTS headers not clobber preloaded pins. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase and updated comment. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 } 74 }
75 75
76 bool AddHash(const char* sha1_hash, 76 bool AddHash(const char* sha1_hash,
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 // Updates |other| to contain the most recent observations found
85 // between the states |state| and |other|.
86 void MergeDomainStates(const TransportSecurityState::DomainState& state,
87 TransportSecurityState::DomainState* other) {
88 if (other->dynamic_pkp.last_observed < state.dynamic_pkp.last_observed)
89 other->dynamic_pkp = state.dynamic_pkp;
90 if (other->dynamic_sts.last_observed < state.dynamic_sts.last_observed)
91 other->dynamic_sts = state.dynamic_sts;
92 }
93
84 } // namespace 94 } // namespace
85 95
86 TransportSecurityState::TransportSecurityState() 96 TransportSecurityState::TransportSecurityState()
87 : delegate_(NULL) { 97 : delegate_(NULL) {
88 DCHECK(CalledOnValidThread()); 98 DCHECK(CalledOnValidThread());
89 } 99 }
90 100
91 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) 101 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
92 : iterator_(state.enabled_hosts_.begin()), 102 : iterator_(state.enabled_hosts_.begin()),
93 end_(state.enabled_hosts_.end()) { 103 end_(state.enabled_hosts_.end()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 return true; 143 return true;
134 } 144 }
135 return false; 145 return false;
136 } 146 }
137 147
138 bool TransportSecurityState::GetDomainState(const std::string& host, 148 bool TransportSecurityState::GetDomainState(const std::string& host,
139 bool sni_enabled, 149 bool sni_enabled,
140 DomainState* result) { 150 DomainState* result) {
141 DCHECK(CalledOnValidThread()); 151 DCHECK(CalledOnValidThread());
142 152
143 DomainState state;
144 const std::string canonicalized_host = CanonicalizeHost(host); 153 const std::string canonicalized_host = CanonicalizeHost(host);
145 if (canonicalized_host.empty()) 154 if (canonicalized_host.empty())
146 return false; 155 return false;
147 156
148 bool has_preload = GetStaticDomainState(canonicalized_host, sni_enabled, 157 DomainState static_state;
149 &state); 158 bool has_static = GetStaticDomainState(canonicalized_host, sni_enabled,
150 std::string canonicalized_preload = CanonicalizeHost(state.domain); 159 &static_state);
151 GetDynamicDomainState(host, &state); 160 std::string canonicalized_preload = CanonicalizeHost(static_state.domain);
152 161 DomainState dynamic_state;
162 bool has_dynamic = GetDynamicDomainState(host, &dynamic_state);
153 base::Time current_time(base::Time::Now()); 163 base::Time current_time(base::Time::Now());
154 164
155 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 165 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
156 std::string host_sub_chunk(&canonicalized_host[i], 166 std::string host_sub_chunk(&canonicalized_host[i],
157 canonicalized_host.size() - i); 167 canonicalized_host.size() - i);
158 // Exact match of a preload always wins. 168 // Exact match of a preload always wins.
159 if (has_preload && host_sub_chunk == canonicalized_preload) { 169 if (has_static && host_sub_chunk == canonicalized_preload) {
160 *result = state; 170 // If we have dynamic state, merge the newer parts of it into the static
171 // state. Then set the |result|.
172 if (has_dynamic)
173 MergeDomainStates(dynamic_state, &static_state);
Ryan Sleevi 2014/03/07 01:39:19 BUG: static_state.domain gets all full of lies her
palmer 2014/03/14 21:33:39 Ah, yes. OK, I'm going to change the code so that
174 *result = static_state;
161 return true; 175 return true;
162 } 176 }
163 177
164 DomainStateMap::iterator j = 178 DomainStateMap::iterator j = enabled_hosts_.find(HashHost(host_sub_chunk));
165 enabled_hosts_.find(HashHost(host_sub_chunk));
166 if (j == enabled_hosts_.end()) 179 if (j == enabled_hosts_.end())
167 continue; 180 continue;
168 181
169 if (current_time > j->second.upgrade_expiry && 182 if (current_time > j->second.dynamic_sts.expiry &&
170 current_time > j->second.dynamic_spki_hashes_expiry) { 183 current_time > j->second.dynamic_pkp.expiry) {
171 enabled_hosts_.erase(j); 184 enabled_hosts_.erase(j);
172 DirtyNotify(); 185 DirtyNotify();
173 continue; 186 continue;
174 } 187 }
175 188
176 state = j->second; 189 dynamic_state = j->second;
177 state.domain = DNSDomainToString(host_sub_chunk); 190 dynamic_state.domain = DNSDomainToString(host_sub_chunk);
178 191
179 // Succeed if we matched the domain exactly or if subdomain matches are 192 // Succeed if we matched the domain exactly or if subdomain matches are
180 // allowed. 193 // allowed.
181 if (i == 0 || j->second.sts_include_subdomains || 194 if (i == 0 || j->second.dynamic_sts.include_subdomains ||
182 j->second.pkp_include_subdomains) { 195 j->second.dynamic_pkp.include_subdomains) {
183 *result = state; 196 *result = dynamic_state;
184 return true; 197 return true;
185 } 198 }
186 199
187 return false; 200 return false;
188 } 201 }
189 202
190 return false; 203 return false;
191 } 204 }
192 205
193 void TransportSecurityState::ClearDynamicData() { 206 void TransportSecurityState::ClearDynamicData() {
194 DCHECK(CalledOnValidThread()); 207 DCHECK(CalledOnValidThread());
195 enabled_hosts_.clear(); 208 enabled_hosts_.clear();
196 } 209 }
197 210
198 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { 211 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
199 DCHECK(CalledOnValidThread()); 212 DCHECK(CalledOnValidThread());
200 213
201 bool dirtied = false; 214 bool dirtied = false;
202 DomainStateMap::iterator i = enabled_hosts_.begin(); 215 DomainStateMap::iterator i = enabled_hosts_.begin();
203 while (i != enabled_hosts_.end()) { 216 while (i != enabled_hosts_.end()) {
204 if (i->second.sts_observed >= time && i->second.pkp_observed >= time) { 217 if (i->second.dynamic_sts.last_observed >= time &&
218 i->second.dynamic_pkp.last_observed >= time) {
205 dirtied = true; 219 dirtied = true;
206 enabled_hosts_.erase(i++); 220 enabled_hosts_.erase(i++);
207 continue; 221 continue;
208 } 222 }
209 223
210 if (i->second.sts_observed >= time) { 224 if (i->second.dynamic_sts.last_observed >= time) {
211 dirtied = true; 225 dirtied = true;
212 i->second.upgrade_mode = DomainState::MODE_DEFAULT; 226 i->second.dynamic_sts.upgrade_mode = DomainState::MODE_DEFAULT;
213 } else if (i->second.pkp_observed >= time) { 227 } else if (i->second.dynamic_pkp.last_observed >= time) {
214 dirtied = true; 228 dirtied = true;
215 i->second.dynamic_spki_hashes.clear(); 229 i->second.dynamic_pkp.spki_hashes.clear();
216 } 230 }
217 ++i; 231 ++i;
218 } 232 }
219 233
220 if (dirtied) 234 if (dirtied)
221 DirtyNotify(); 235 DirtyNotify();
222 } 236 }
223 237
224 TransportSecurityState::~TransportSecurityState() { 238 TransportSecurityState::~TransportSecurityState() {
225 DCHECK(CalledOnValidThread()); 239 DCHECK(CalledOnValidThread());
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, 561 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries,
548 const std::string& canonicalized_host, size_t i, 562 const std::string& canonicalized_host, size_t i,
549 TransportSecurityState::DomainState* out, bool* ret) { 563 TransportSecurityState::DomainState* out, bool* ret) {
550 for (size_t j = 0; j < num_entries; j++) { 564 for (size_t j = 0; j < num_entries; j++) {
551 if (entries[j].length == canonicalized_host.size() - i && 565 if (entries[j].length == canonicalized_host.size() - i &&
552 memcmp(entries[j].dns_name, &canonicalized_host[i], 566 memcmp(entries[j].dns_name, &canonicalized_host[i],
553 entries[j].length) == 0) { 567 entries[j].length) == 0) {
554 if (!entries[j].include_subdomains && i != 0) { 568 if (!entries[j].include_subdomains && i != 0) {
555 *ret = false; 569 *ret = false;
556 } else { 570 } else {
557 out->sts_include_subdomains = entries[j].include_subdomains; 571 out->static_sts.include_subdomains = entries[j].include_subdomains;
558 out->pkp_include_subdomains = entries[j].include_subdomains; 572 out->static_sts.last_observed = base::GetBuildTime();
573 out->static_pkp.include_subdomains = entries[j].include_subdomains;
574 out->static_pkp.last_observed = base::GetBuildTime();
559 *ret = true; 575 *ret = true;
576 out->has_static_sts = entries[j].https_required;
560 if (!entries[j].https_required) 577 if (!entries[j].https_required)
561 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; 578 out->static_sts.upgrade_mode =
579 TransportSecurityState::DomainState::MODE_DEFAULT;
562 if (entries[j].pins.required_hashes) { 580 if (entries[j].pins.required_hashes) {
581 out->has_static_pkp = true;
563 const char* const* sha1_hash = entries[j].pins.required_hashes; 582 const char* const* sha1_hash = entries[j].pins.required_hashes;
564 while (*sha1_hash) { 583 while (*sha1_hash) {
565 AddHash(*sha1_hash, &out->static_spki_hashes); 584 AddHash(*sha1_hash, &out->static_pkp.spki_hashes);
566 sha1_hash++; 585 sha1_hash++;
567 } 586 }
568 } 587 }
569 if (entries[j].pins.excluded_hashes) { 588 if (entries[j].pins.excluded_hashes) {
589 out->has_static_pkp = true;
570 const char* const* sha1_hash = entries[j].pins.excluded_hashes; 590 const char* const* sha1_hash = entries[j].pins.excluded_hashes;
571 while (*sha1_hash) { 591 while (*sha1_hash) {
572 AddHash(*sha1_hash, &out->bad_static_spki_hashes); 592 AddHash(*sha1_hash, &out->static_pkp.bad_spki_hashes);
573 sha1_hash++; 593 sha1_hash++;
574 } 594 }
575 } 595 }
576 } 596 }
577 return true; 597 return true;
578 } 598 }
579 } 599 }
580 return false; 600 return false;
581 } 601 }
582 602
(...skipping 27 matching lines...) Expand all
610 } 630 }
611 631
612 bool TransportSecurityState::AddHSTSHeader(const std::string& host, 632 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
613 const std::string& value) { 633 const std::string& value) {
614 DCHECK(CalledOnValidThread()); 634 DCHECK(CalledOnValidThread());
615 635
616 base::Time now = base::Time::Now(); 636 base::Time now = base::Time::Now();
617 base::TimeDelta max_age; 637 base::TimeDelta max_age;
618 TransportSecurityState::DomainState domain_state; 638 TransportSecurityState::DomainState domain_state;
619 GetDynamicDomainState(host, &domain_state); 639 GetDynamicDomainState(host, &domain_state);
620 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { 640 if (ParseHSTSHeader(value, &max_age,
641 &domain_state.dynamic_sts.include_subdomains)) {
621 // Handle max-age == 0 642 // Handle max-age == 0
622 if (max_age.InSeconds() == 0) 643 if (max_age.InSeconds() == 0)
623 domain_state.upgrade_mode = DomainState::MODE_DEFAULT; 644 domain_state.dynamic_sts.upgrade_mode = DomainState::MODE_DEFAULT;
624 else 645 else
625 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 646 domain_state.dynamic_sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
626 domain_state.sts_observed = now; 647 domain_state.dynamic_sts.last_observed = now;
627 domain_state.upgrade_expiry = now + max_age; 648 domain_state.dynamic_sts.expiry = now + max_age;
628 EnableHost(host, domain_state); 649 EnableHost(host, domain_state);
629 return true; 650 return true;
630 } 651 }
631 return false; 652 return false;
632 } 653 }
633 654
634 bool TransportSecurityState::AddHPKPHeader(const std::string& host, 655 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
635 const std::string& value, 656 const std::string& value,
636 const SSLInfo& ssl_info) { 657 const SSLInfo& ssl_info) {
637 DCHECK(CalledOnValidThread()); 658 DCHECK(CalledOnValidThread());
638 659
639 base::Time now = base::Time::Now(); 660 base::Time now = base::Time::Now();
640 base::TimeDelta max_age; 661 base::TimeDelta max_age;
641 TransportSecurityState::DomainState domain_state; 662 TransportSecurityState::DomainState domain_state;
642 GetDynamicDomainState(host, &domain_state); 663 GetDynamicDomainState(host, &domain_state);
643 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, 664 if (ParseHPKPHeader(value, ssl_info.public_key_hashes,
644 &max_age, &domain_state.pkp_include_subdomains, 665 &max_age, &domain_state.dynamic_pkp.include_subdomains,
645 &domain_state.dynamic_spki_hashes)) { 666 &domain_state.dynamic_pkp.spki_hashes)) {
646 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. 667 // TODO(palmer): http://crbug.com/243865 handle max-age == 0.
647 domain_state.pkp_observed = now; 668 domain_state.dynamic_pkp.last_observed = now;
648 domain_state.dynamic_spki_hashes_expiry = now + max_age; 669 domain_state.dynamic_pkp.expiry = now + max_age;
649 EnableHost(host, domain_state); 670 EnableHost(host, domain_state);
650 return true; 671 return true;
651 } 672 }
652 return false; 673 return false;
653 } 674 }
654 675
655 bool TransportSecurityState::AddHSTS(const std::string& host, 676 bool TransportSecurityState::AddHSTS(const std::string& host,
656 const base::Time& expiry, 677 const base::Time& expiry,
657 bool include_subdomains) { 678 bool include_subdomains) {
658 DCHECK(CalledOnValidThread()); 679 DCHECK(CalledOnValidThread());
659 680
660 // Copy-and-modify the existing DomainState for this host (if any). 681 // Copy-and-modify the existing DomainState for this host (if any).
661 TransportSecurityState::DomainState domain_state; 682 TransportSecurityState::DomainState domain_state;
662 const std::string canonicalized_host = CanonicalizeHost(host); 683 const std::string canonicalized_host = CanonicalizeHost(host);
663 const std::string hashed_host = HashHost(canonicalized_host); 684 const std::string hashed_host = HashHost(canonicalized_host);
664 DomainStateMap::const_iterator i = enabled_hosts_.find( 685 DomainStateMap::const_iterator i = enabled_hosts_.find(
665 hashed_host); 686 hashed_host);
666 if (i != enabled_hosts_.end()) 687 if (i != enabled_hosts_.end())
667 domain_state = i->second; 688 domain_state = i->second;
668 689
669 domain_state.sts_observed = base::Time::Now(); 690 domain_state.dynamic_sts.last_observed = base::Time::Now();
670 domain_state.sts_include_subdomains = include_subdomains; 691 domain_state.dynamic_sts.include_subdomains = include_subdomains;
671 domain_state.upgrade_expiry = expiry; 692 domain_state.dynamic_sts.expiry = expiry;
672 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 693 domain_state.dynamic_sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
673 EnableHost(host, domain_state); 694 EnableHost(host, domain_state);
674 return true; 695 return true;
675 } 696 }
676 697
677 bool TransportSecurityState::AddHPKP(const std::string& host, 698 bool TransportSecurityState::AddHPKP(const std::string& host,
678 const base::Time& expiry, 699 const base::Time& expiry,
679 bool include_subdomains, 700 bool include_subdomains,
680 const HashValueVector& hashes) { 701 const HashValueVector& hashes) {
681 DCHECK(CalledOnValidThread()); 702 DCHECK(CalledOnValidThread());
682 703
683 // Copy-and-modify the existing DomainState for this host (if any). 704 // Copy-and-modify the existing DomainState for this host (if any).
684 TransportSecurityState::DomainState domain_state; 705 TransportSecurityState::DomainState domain_state;
685 const std::string canonicalized_host = CanonicalizeHost(host); 706 const std::string canonicalized_host = CanonicalizeHost(host);
686 const std::string hashed_host = HashHost(canonicalized_host); 707 const std::string hashed_host = HashHost(canonicalized_host);
687 DomainStateMap::const_iterator i = enabled_hosts_.find( 708 DomainStateMap::const_iterator i = enabled_hosts_.find(
688 hashed_host); 709 hashed_host);
689 if (i != enabled_hosts_.end()) 710 if (i != enabled_hosts_.end())
690 domain_state = i->second; 711 domain_state = i->second;
691 712
692 domain_state.pkp_observed = base::Time::Now(); 713 domain_state.dynamic_pkp.last_observed = base::Time::Now();
693 domain_state.pkp_include_subdomains = include_subdomains; 714 domain_state.dynamic_pkp.include_subdomains = include_subdomains;
694 domain_state.dynamic_spki_hashes_expiry = expiry; 715 domain_state.dynamic_pkp.expiry = expiry;
695 domain_state.dynamic_spki_hashes = hashes; 716 domain_state.dynamic_pkp.spki_hashes = hashes;
696 EnableHost(host, domain_state); 717 EnableHost(host, domain_state);
697 return true; 718 return true;
698 } 719 }
699 720
700 // static 721 // static
701 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, 722 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
702 bool sni_enabled) { 723 bool sni_enabled) {
703 std::string canonicalized_host = CanonicalizeHost(host); 724 std::string canonicalized_host = CanonicalizeHost(host);
704 const struct HSTSPreload* entry = 725 const struct HSTSPreload* entry =
705 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); 726 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 // We consider built-in information to be timely for 10 weeks. 769 // We consider built-in information to be timely for 10 weeks.
749 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; 770 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
750 } 771 }
751 772
752 bool TransportSecurityState::GetStaticDomainState( 773 bool TransportSecurityState::GetStaticDomainState(
753 const std::string& canonicalized_host, 774 const std::string& canonicalized_host,
754 bool sni_enabled, 775 bool sni_enabled,
755 DomainState* out) { 776 DomainState* out) {
756 DCHECK(CalledOnValidThread()); 777 DCHECK(CalledOnValidThread());
757 778
758 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; 779 out->static_sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
759 out->sts_include_subdomains = false; 780 out->static_sts.include_subdomains = false;
760 out->pkp_include_subdomains = false; 781 out->static_pkp.include_subdomains = false;
761 782
762 const bool is_build_timely = IsBuildTimely(); 783 const bool is_build_timely = IsBuildTimely();
763 784
764 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 785 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
765 std::string host_sub_chunk(&canonicalized_host[i], 786 std::string host_sub_chunk(&canonicalized_host[i],
766 canonicalized_host.size() - i); 787 canonicalized_host.size() - i);
767 out->domain = DNSDomainToString(host_sub_chunk); 788 out->domain = DNSDomainToString(host_sub_chunk);
768 bool ret; 789 bool ret;
769 if (is_build_timely && 790 if (is_build_timely &&
770 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, 791 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out,
(...skipping 23 matching lines...) Expand all
794 base::Time current_time(base::Time::Now()); 815 base::Time current_time(base::Time::Now());
795 816
796 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 817 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
797 std::string host_sub_chunk(&canonicalized_host[i], 818 std::string host_sub_chunk(&canonicalized_host[i],
798 canonicalized_host.size() - i); 819 canonicalized_host.size() - i);
799 DomainStateMap::iterator j = 820 DomainStateMap::iterator j =
800 enabled_hosts_.find(HashHost(host_sub_chunk)); 821 enabled_hosts_.find(HashHost(host_sub_chunk));
801 if (j == enabled_hosts_.end()) 822 if (j == enabled_hosts_.end())
802 continue; 823 continue;
803 824
804 if (current_time > j->second.upgrade_expiry && 825 if (current_time > j->second.dynamic_sts.expiry &&
805 current_time > j->second.dynamic_spki_hashes_expiry) { 826 current_time > j->second.dynamic_pkp.expiry) {
806 enabled_hosts_.erase(j); 827 enabled_hosts_.erase(j);
807 DirtyNotify(); 828 DirtyNotify();
808 continue; 829 continue;
809 } 830 }
810 831
811 state = j->second; 832 state = j->second;
812 state.domain = DNSDomainToString(host_sub_chunk); 833 state.domain = DNSDomainToString(host_sub_chunk);
813 834
814 // Succeed if we matched the domain exactly or if subdomain matches are 835 // Succeed if we matched the domain exactly or if subdomain matches are
815 // allowed. 836 // allowed.
816 if (i == 0 || j->second.sts_include_subdomains || 837 if (i == 0 || j->second.dynamic_sts.include_subdomains ||
817 j->second.pkp_include_subdomains) { 838 j->second.dynamic_pkp.include_subdomains) {
818 *result = state; 839 *result = state;
819 return true; 840 return true;
820 } 841 }
821 842
822 return false; 843 return false;
823 } 844 }
824 845
825 return false; 846 return false;
826 } 847 }
827 848
828
829 void TransportSecurityState::AddOrUpdateEnabledHosts( 849 void TransportSecurityState::AddOrUpdateEnabledHosts(
830 const std::string& hashed_host, const DomainState& state) { 850 const std::string& hashed_host, const DomainState& state) {
831 DCHECK(CalledOnValidThread()); 851 DCHECK(CalledOnValidThread());
832 enabled_hosts_[hashed_host] = state; 852 enabled_hosts_[hashed_host] = state;
833 } 853 }
834 854
835 TransportSecurityState::DomainState::DomainState() 855 TransportSecurityState::DomainState::DomainState()
836 : upgrade_mode(MODE_DEFAULT), 856 : has_static_sts(false),
837 sts_include_subdomains(false), 857 has_static_pkp(false) {
838 pkp_include_subdomains(false) { 858 dynamic_sts.upgrade_mode = MODE_DEFAULT;
839 base::Time now(base::Time::Now()); 859 dynamic_sts.include_subdomains = false;
840 sts_observed = now; 860 dynamic_pkp.include_subdomains = false;
841 pkp_observed = now;
842 } 861 }
843 862
844 TransportSecurityState::DomainState::~DomainState() { 863 TransportSecurityState::DomainState::~DomainState() {
845 } 864 }
846 865
847 bool TransportSecurityState::DomainState::CheckPublicKeyPins( 866 bool TransportSecurityState::DomainState::CheckPublicKeyPins(
848 const HashValueVector& hashes) const { 867 const HashValueVector& hashes) const {
849 // Validate that hashes is not empty. By the time this code is called (in 868 // Validate that hashes is not empty. By the time this code is called (in
850 // production), that should never happen, but it's good to be defensive. 869 // production), that should never happen, but it's good to be defensive.
851 // And, hashes *can* be empty in some test scenarios. 870 // And, hashes *can* be empty in some test scenarios.
852 if (hashes.empty()) { 871 if (hashes.empty()) {
853 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned " 872 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned "
854 "domain " << domain; 873 "domain " << domain;
855 return false; 874 return false;
856 } 875 }
857 876
858 if (HashesIntersect(bad_static_spki_hashes, hashes)) { 877 if (HashesIntersect(static_pkp.bad_spki_hashes, hashes) ||
878 HashesIntersect(dynamic_pkp.bad_spki_hashes, hashes)) {
859 LOG(ERROR) << "Rejecting public key chain for domain " << domain 879 LOG(ERROR) << "Rejecting public key chain for domain " << domain
860 << ". Validated chain: " << HashesToBase64String(hashes) 880 << ". Validated chain: " << HashesToBase64String(hashes)
861 << ", matches one or more bad hashes: " 881 << ", matches one or more bad hashes: "
862 << HashesToBase64String(bad_static_spki_hashes); 882 << HashesToBase64String(static_pkp.bad_spki_hashes) <<
883 ", " << HashesToBase64String(dynamic_pkp.bad_spki_hashes);
863 return false; 884 return false;
864 } 885 }
865 886
866 // If there are no pins, then any valid chain is acceptable. 887 // If there are no pins, then any valid chain is acceptable.
867 if (dynamic_spki_hashes.empty() && static_spki_hashes.empty()) 888 if (dynamic_pkp.spki_hashes.empty() && static_pkp.spki_hashes.empty()) {
868 return true; 889 return true;
890 }
869 891
870 if (HashesIntersect(dynamic_spki_hashes, hashes) || 892 if (HashesIntersect(dynamic_pkp.spki_hashes, hashes) ||
871 HashesIntersect(static_spki_hashes, hashes)) { 893 HashesIntersect(static_pkp.spki_hashes, hashes)) {
872 return true; 894 return true;
873 } 895 }
874 896
875 LOG(ERROR) << "Rejecting public key chain for domain " << domain 897 LOG(ERROR) << "Rejecting public key chain for domain " << domain
876 << ". Validated chain: " << HashesToBase64String(hashes) 898 << ". Validated chain: " << HashesToBase64String(hashes)
877 << ", expected: " << HashesToBase64String(dynamic_spki_hashes) 899 << ", expected: " << HashesToBase64String(dynamic_pkp.spki_hashes)
878 << " or: " << HashesToBase64String(static_spki_hashes); 900 << " or: " << HashesToBase64String(static_pkp.spki_hashes);
879 return false; 901 return false;
880 } 902 }
881 903
882 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { 904 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
883 return upgrade_mode == MODE_FORCE_HTTPS; 905 return dynamic_sts.upgrade_mode == MODE_FORCE_HTTPS ||
906 static_sts.upgrade_mode == MODE_FORCE_HTTPS;
884 } 907 }
885 908
886 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { 909 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
887 return true; 910 return true;
888 } 911 }
889 912
890 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { 913 bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
891 return static_spki_hashes.size() > 0 || 914 return static_pkp.spki_hashes.size() > 0 ||
892 bad_static_spki_hashes.size() > 0 || 915 static_pkp.bad_spki_hashes.size() > 0 ||
893 dynamic_spki_hashes.size() > 0; 916 dynamic_pkp.spki_hashes.size() > 0;
894 } 917 }
895 918
896 } // namespace 919 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698