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

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: Make use of has_dynamic. Created 6 years, 10 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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 DomainStateMap::iterator i = enabled_hosts_.find( 128 DomainStateMap::iterator i = enabled_hosts_.find(
129 HashHost(canonicalized_host)); 129 HashHost(canonicalized_host));
130 if (i != enabled_hosts_.end()) { 130 if (i != enabled_hosts_.end()) {
131 enabled_hosts_.erase(i); 131 enabled_hosts_.erase(i);
132 DirtyNotify(); 132 DirtyNotify();
133 return true; 133 return true;
134 } 134 }
135 return false; 135 return false;
136 } 136 }
137 137
138 // Given |older| and |newer|, takes the newest parts of |older| and
139 // |newer| and converges them into |older|.
Ryan Sleevi 2014/01/31 20:24:43 It took me a little bit to parse this comment, in
palmer 2014/01/31 22:20:51 Done.
140 bool MergeDomainStates(TransportSecurityState::DomainState* older,
141 const TransportSecurityState::DomainState& newer) {
142 if (older->dynamic_pkp.last_observed < newer.dynamic_pkp.last_observed) {
143 older->dynamic_pkp = newer.dynamic_pkp;
144 }
145 if (older->dynamic_sts.last_observed < newer.dynamic_sts.last_observed) {
146 older->dynamic_sts = newer.dynamic_sts;
147 }
148 return true;
Ryan Sleevi 2014/01/31 20:24:43 why bool if you always return true?
palmer 2014/01/31 22:20:51 Same reason as I have curly braces for 1-line if b
149 }
150
138 bool TransportSecurityState::GetDomainState(const std::string& host, 151 bool TransportSecurityState::GetDomainState(const std::string& host,
139 bool sni_enabled, 152 bool sni_enabled,
140 DomainState* result) { 153 DomainState* result) {
141 DCHECK(CalledOnValidThread()); 154 DCHECK(CalledOnValidThread());
142 155
143 DomainState state;
144 const std::string canonicalized_host = CanonicalizeHost(host); 156 const std::string canonicalized_host = CanonicalizeHost(host);
145 if (canonicalized_host.empty()) 157 if (canonicalized_host.empty())
146 return false; 158 return false;
147 159
148 bool has_preload = GetStaticDomainState(canonicalized_host, sni_enabled, 160 DomainState static_state;
149 &state); 161 bool has_static = GetStaticDomainState(canonicalized_host, sni_enabled,
150 std::string canonicalized_preload = CanonicalizeHost(state.domain); 162 &static_state);
151 GetDynamicDomainState(host, &state); 163 std::string canonicalized_preload = CanonicalizeHost(static_state.domain);
152 164 DomainState dynamic_state = static_state;
Ryan Sleevi 2014/01/31 20:24:43 Add a comment explaining why you initialize dynami
palmer 2014/01/31 22:20:51 I think this is legacy from before I wrote MergeDo
165 bool has_dynamic = GetDynamicDomainState(host, &dynamic_state);
153 base::Time current_time(base::Time::Now()); 166 base::Time current_time(base::Time::Now());
154 167
155 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 168 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
156 std::string host_sub_chunk(&canonicalized_host[i], 169 std::string host_sub_chunk(&canonicalized_host[i],
157 canonicalized_host.size() - i); 170 canonicalized_host.size() - i);
158 // Exact match of a preload always wins. 171 // Exact match of a preload always wins.
159 if (has_preload && host_sub_chunk == canonicalized_preload) { 172 if (has_static && host_sub_chunk == canonicalized_preload) {
160 *result = state; 173 if (has_dynamic)
174 MergeDomainStates(&static_state, dynamic_state);
Ryan Sleevi 2014/01/31 20:24:43 Add a comment here as to why you're updating |stat
palmer 2014/01/31 22:20:51 Done.
175 *result = static_state;
161 return true; 176 return true;
162 } 177 }
163 178
164 DomainStateMap::iterator j = 179 DomainStateMap::iterator j = enabled_hosts_.find(HashHost(host_sub_chunk));
165 enabled_hosts_.find(HashHost(host_sub_chunk));
166 if (j == enabled_hosts_.end()) 180 if (j == enabled_hosts_.end())
167 continue; 181 continue;
168 182
169 if (current_time > j->second.upgrade_expiry && 183 if (current_time > j->second.dynamic_sts.expiry &&
170 current_time > j->second.dynamic_spki_hashes_expiry) { 184 current_time > j->second.dynamic_pkp.expiry) {
171 enabled_hosts_.erase(j); 185 enabled_hosts_.erase(j);
172 DirtyNotify(); 186 DirtyNotify();
173 continue; 187 continue;
174 } 188 }
175 189
176 state = j->second; 190 dynamic_state = j->second;
177 state.domain = DNSDomainToString(host_sub_chunk); 191 dynamic_state.domain = DNSDomainToString(host_sub_chunk);
178 192
179 // Succeed if we matched the domain exactly or if subdomain matches are 193 // Succeed if we matched the domain exactly or if subdomain matches are
180 // allowed. 194 // allowed.
181 if (i == 0 || j->second.sts_include_subdomains || 195 if (i == 0 || j->second.dynamic_sts.include_subdomains ||
182 j->second.pkp_include_subdomains) { 196 j->second.dynamic_pkp.include_subdomains) {
183 *result = state; 197 *result = dynamic_state;
184 return true; 198 return true;
185 } 199 }
186 200
187 return false; 201 return false;
188 } 202 }
189 203
190 return false; 204 return false;
191 } 205 }
192 206
193 void TransportSecurityState::ClearDynamicData() { 207 void TransportSecurityState::ClearDynamicData() {
194 DCHECK(CalledOnValidThread()); 208 DCHECK(CalledOnValidThread());
195 enabled_hosts_.clear(); 209 enabled_hosts_.clear();
196 } 210 }
197 211
198 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { 212 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
199 DCHECK(CalledOnValidThread()); 213 DCHECK(CalledOnValidThread());
200 214
201 bool dirtied = false; 215 bool dirtied = false;
202 DomainStateMap::iterator i = enabled_hosts_.begin(); 216 DomainStateMap::iterator i = enabled_hosts_.begin();
203 while (i != enabled_hosts_.end()) { 217 while (i != enabled_hosts_.end()) {
204 if (i->second.sts_observed >= time && i->second.pkp_observed >= time) { 218 if (i->second.dynamic_sts.last_observed >= time &&
219 i->second.dynamic_pkp.last_observed >= time) {
205 dirtied = true; 220 dirtied = true;
206 enabled_hosts_.erase(i++); 221 enabled_hosts_.erase(i++);
207 continue; 222 continue;
208 } 223 }
209 224
210 if (i->second.sts_observed >= time) { 225 if (i->second.dynamic_sts.last_observed >= time) {
211 dirtied = true; 226 dirtied = true;
212 i->second.upgrade_mode = DomainState::MODE_DEFAULT; 227 i->second.dynamic_sts.upgrade_mode = DomainState::MODE_DEFAULT;
213 } else if (i->second.pkp_observed >= time) { 228 } else if (i->second.dynamic_pkp.last_observed >= time) {
214 dirtied = true; 229 dirtied = true;
215 i->second.dynamic_spki_hashes.clear(); 230 i->second.dynamic_pkp.spki_hashes.clear();
216 } 231 }
217 ++i; 232 ++i;
218 } 233 }
219 234
220 if (dirtied) 235 if (dirtied)
221 DirtyNotify(); 236 DirtyNotify();
222 } 237 }
223 238
224 TransportSecurityState::~TransportSecurityState() { 239 TransportSecurityState::~TransportSecurityState() {
225 DCHECK(CalledOnValidThread()); 240 DCHECK(CalledOnValidThread());
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, 560 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries,
546 const std::string& canonicalized_host, size_t i, 561 const std::string& canonicalized_host, size_t i,
547 TransportSecurityState::DomainState* out, bool* ret) { 562 TransportSecurityState::DomainState* out, bool* ret) {
548 for (size_t j = 0; j < num_entries; j++) { 563 for (size_t j = 0; j < num_entries; j++) {
549 if (entries[j].length == canonicalized_host.size() - i && 564 if (entries[j].length == canonicalized_host.size() - i &&
550 memcmp(entries[j].dns_name, &canonicalized_host[i], 565 memcmp(entries[j].dns_name, &canonicalized_host[i],
551 entries[j].length) == 0) { 566 entries[j].length) == 0) {
552 if (!entries[j].include_subdomains && i != 0) { 567 if (!entries[j].include_subdomains && i != 0) {
553 *ret = false; 568 *ret = false;
554 } else { 569 } else {
555 out->sts_include_subdomains = entries[j].include_subdomains; 570 out->static_sts.include_subdomains = entries[j].include_subdomains;
556 out->pkp_include_subdomains = entries[j].include_subdomains; 571 out->static_sts.last_observed = base::GetBuildTime();
572 out->static_pkp.include_subdomains = entries[j].include_subdomains;
573 out->static_pkp.last_observed = base::GetBuildTime();
557 *ret = true; 574 *ret = true;
575 out->has_static_sts = entries[j].https_required;
558 if (!entries[j].https_required) 576 if (!entries[j].https_required)
559 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; 577 out->static_sts.upgrade_mode =
578 TransportSecurityState::DomainState::MODE_DEFAULT;
560 if (entries[j].pins.required_hashes) { 579 if (entries[j].pins.required_hashes) {
580 out->has_static_pkp = true;
561 const char* const* sha1_hash = entries[j].pins.required_hashes; 581 const char* const* sha1_hash = entries[j].pins.required_hashes;
562 while (*sha1_hash) { 582 while (*sha1_hash) {
563 AddHash(*sha1_hash, &out->static_spki_hashes); 583 AddHash(*sha1_hash, &out->static_pkp.spki_hashes);
564 sha1_hash++; 584 sha1_hash++;
565 } 585 }
566 } 586 }
567 if (entries[j].pins.excluded_hashes) { 587 if (entries[j].pins.excluded_hashes) {
588 out->has_static_pkp = true;
568 const char* const* sha1_hash = entries[j].pins.excluded_hashes; 589 const char* const* sha1_hash = entries[j].pins.excluded_hashes;
569 while (*sha1_hash) { 590 while (*sha1_hash) {
570 AddHash(*sha1_hash, &out->bad_static_spki_hashes); 591 AddHash(*sha1_hash, &out->static_pkp.bad_spki_hashes);
571 sha1_hash++; 592 sha1_hash++;
572 } 593 }
573 } 594 }
574 } 595 }
575 return true; 596 return true;
576 } 597 }
577 } 598 }
578 return false; 599 return false;
579 } 600 }
580 601
(...skipping 27 matching lines...) Expand all
608 } 629 }
609 630
610 bool TransportSecurityState::AddHSTSHeader(const std::string& host, 631 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
611 const std::string& value) { 632 const std::string& value) {
612 DCHECK(CalledOnValidThread()); 633 DCHECK(CalledOnValidThread());
613 634
614 base::Time now = base::Time::Now(); 635 base::Time now = base::Time::Now();
615 base::TimeDelta max_age; 636 base::TimeDelta max_age;
616 TransportSecurityState::DomainState domain_state; 637 TransportSecurityState::DomainState domain_state;
617 GetDynamicDomainState(host, &domain_state); 638 GetDynamicDomainState(host, &domain_state);
618 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { 639 if (ParseHSTSHeader(value, &max_age,
640 &domain_state.dynamic_sts.include_subdomains)) {
619 // Handle max-age == 0 641 // Handle max-age == 0
620 if (max_age.InSeconds() == 0) 642 if (max_age.InSeconds() == 0)
621 domain_state.upgrade_mode = DomainState::MODE_DEFAULT; 643 domain_state.dynamic_sts.upgrade_mode = DomainState::MODE_DEFAULT;
622 else 644 else
623 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 645 domain_state.dynamic_sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
624 domain_state.sts_observed = now; 646 domain_state.dynamic_sts.last_observed = now;
625 domain_state.upgrade_expiry = now + max_age; 647 domain_state.dynamic_sts.expiry = now + max_age;
626 EnableHost(host, domain_state); 648 EnableHost(host, domain_state);
627 return true; 649 return true;
628 } 650 }
629 return false; 651 return false;
630 } 652 }
631 653
632 bool TransportSecurityState::AddHPKPHeader(const std::string& host, 654 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
633 const std::string& value, 655 const std::string& value,
634 const SSLInfo& ssl_info) { 656 const SSLInfo& ssl_info) {
635 DCHECK(CalledOnValidThread()); 657 DCHECK(CalledOnValidThread());
636 658
637 base::Time now = base::Time::Now(); 659 base::Time now = base::Time::Now();
638 base::TimeDelta max_age; 660 base::TimeDelta max_age;
639 TransportSecurityState::DomainState domain_state; 661 TransportSecurityState::DomainState domain_state;
640 GetDynamicDomainState(host, &domain_state); 662 GetDynamicDomainState(host, &domain_state);
641 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, 663 if (ParseHPKPHeader(value, ssl_info.public_key_hashes,
642 &max_age, &domain_state.pkp_include_subdomains, 664 &max_age, &domain_state.dynamic_pkp.include_subdomains,
643 &domain_state.dynamic_spki_hashes)) { 665 &domain_state.dynamic_pkp.spki_hashes)) {
644 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. 666 // TODO(palmer): http://crbug.com/243865 handle max-age == 0.
645 domain_state.pkp_observed = now; 667 domain_state.dynamic_pkp.last_observed = now;
646 domain_state.dynamic_spki_hashes_expiry = now + max_age; 668 domain_state.dynamic_pkp.expiry = now + max_age;
647 EnableHost(host, domain_state); 669 EnableHost(host, domain_state);
648 return true; 670 return true;
649 } 671 }
650 return false; 672 return false;
651 } 673 }
652 674
653 bool TransportSecurityState::AddHSTS(const std::string& host, 675 bool TransportSecurityState::AddHSTS(const std::string& host,
654 const base::Time& expiry, 676 const base::Time& expiry,
655 bool include_subdomains) { 677 bool include_subdomains) {
656 DCHECK(CalledOnValidThread()); 678 DCHECK(CalledOnValidThread());
657 679
658 // Copy-and-modify the existing DomainState for this host (if any). 680 // Copy-and-modify the existing DomainState for this host (if any).
659 TransportSecurityState::DomainState domain_state; 681 TransportSecurityState::DomainState domain_state;
660 const std::string canonicalized_host = CanonicalizeHost(host); 682 const std::string canonicalized_host = CanonicalizeHost(host);
661 const std::string hashed_host = HashHost(canonicalized_host); 683 const std::string hashed_host = HashHost(canonicalized_host);
662 DomainStateMap::const_iterator i = enabled_hosts_.find( 684 DomainStateMap::const_iterator i = enabled_hosts_.find(
663 hashed_host); 685 hashed_host);
664 if (i != enabled_hosts_.end()) 686 if (i != enabled_hosts_.end())
665 domain_state = i->second; 687 domain_state = i->second;
666 688
667 domain_state.sts_observed = base::Time::Now(); 689 domain_state.dynamic_sts.last_observed = base::Time::Now();
668 domain_state.sts_include_subdomains = include_subdomains; 690 domain_state.dynamic_sts.include_subdomains = include_subdomains;
669 domain_state.upgrade_expiry = expiry; 691 domain_state.dynamic_sts.expiry = expiry;
670 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 692 domain_state.dynamic_sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
671 EnableHost(host, domain_state); 693 EnableHost(host, domain_state);
672 return true; 694 return true;
673 } 695 }
674 696
675 bool TransportSecurityState::AddHPKP(const std::string& host, 697 bool TransportSecurityState::AddHPKP(const std::string& host,
676 const base::Time& expiry, 698 const base::Time& expiry,
677 bool include_subdomains, 699 bool include_subdomains,
678 const HashValueVector& hashes) { 700 const HashValueVector& hashes) {
679 DCHECK(CalledOnValidThread()); 701 DCHECK(CalledOnValidThread());
680 702
681 // Copy-and-modify the existing DomainState for this host (if any). 703 // Copy-and-modify the existing DomainState for this host (if any).
682 TransportSecurityState::DomainState domain_state; 704 TransportSecurityState::DomainState domain_state;
683 const std::string canonicalized_host = CanonicalizeHost(host); 705 const std::string canonicalized_host = CanonicalizeHost(host);
684 const std::string hashed_host = HashHost(canonicalized_host); 706 const std::string hashed_host = HashHost(canonicalized_host);
685 DomainStateMap::const_iterator i = enabled_hosts_.find( 707 DomainStateMap::const_iterator i = enabled_hosts_.find(
686 hashed_host); 708 hashed_host);
687 if (i != enabled_hosts_.end()) 709 if (i != enabled_hosts_.end())
688 domain_state = i->second; 710 domain_state = i->second;
689 711
690 domain_state.pkp_observed = base::Time::Now(); 712 domain_state.dynamic_pkp.last_observed = base::Time::Now();
691 domain_state.pkp_include_subdomains = include_subdomains; 713 domain_state.dynamic_pkp.include_subdomains = include_subdomains;
692 domain_state.dynamic_spki_hashes_expiry = expiry; 714 domain_state.dynamic_pkp.expiry = expiry;
693 domain_state.dynamic_spki_hashes = hashes; 715 domain_state.dynamic_pkp.spki_hashes = hashes;
694 EnableHost(host, domain_state); 716 EnableHost(host, domain_state);
695 return true; 717 return true;
696 } 718 }
697 719
698 // static 720 // static
699 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, 721 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
700 bool sni_enabled) { 722 bool sni_enabled) {
701 std::string canonicalized_host = CanonicalizeHost(host); 723 std::string canonicalized_host = CanonicalizeHost(host);
702 const struct HSTSPreload* entry = 724 const struct HSTSPreload* entry =
703 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); 725 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 // We consider built-in information to be timely for 10 weeks. 768 // We consider built-in information to be timely for 10 weeks.
747 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; 769 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
748 } 770 }
749 771
750 bool TransportSecurityState::GetStaticDomainState( 772 bool TransportSecurityState::GetStaticDomainState(
751 const std::string& canonicalized_host, 773 const std::string& canonicalized_host,
752 bool sni_enabled, 774 bool sni_enabled,
753 DomainState* out) { 775 DomainState* out) {
754 DCHECK(CalledOnValidThread()); 776 DCHECK(CalledOnValidThread());
755 777
756 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; 778 out->static_sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
757 out->sts_include_subdomains = false; 779 out->static_sts.include_subdomains = false;
758 out->pkp_include_subdomains = false; 780 out->static_pkp.include_subdomains = false;
759 781
760 const bool is_build_timely = IsBuildTimely(); 782 const bool is_build_timely = IsBuildTimely();
761 783
762 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 784 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
763 std::string host_sub_chunk(&canonicalized_host[i], 785 std::string host_sub_chunk(&canonicalized_host[i],
764 canonicalized_host.size() - i); 786 canonicalized_host.size() - i);
765 out->domain = DNSDomainToString(host_sub_chunk); 787 out->domain = DNSDomainToString(host_sub_chunk);
766 bool ret; 788 bool ret;
767 if (is_build_timely && 789 if (is_build_timely &&
768 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, 790 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out,
(...skipping 23 matching lines...) Expand all
792 base::Time current_time(base::Time::Now()); 814 base::Time current_time(base::Time::Now());
793 815
794 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) { 816 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
795 std::string host_sub_chunk(&canonicalized_host[i], 817 std::string host_sub_chunk(&canonicalized_host[i],
796 canonicalized_host.size() - i); 818 canonicalized_host.size() - i);
797 DomainStateMap::iterator j = 819 DomainStateMap::iterator j =
798 enabled_hosts_.find(HashHost(host_sub_chunk)); 820 enabled_hosts_.find(HashHost(host_sub_chunk));
799 if (j == enabled_hosts_.end()) 821 if (j == enabled_hosts_.end())
800 continue; 822 continue;
801 823
802 if (current_time > j->second.upgrade_expiry && 824 if (current_time > j->second.dynamic_sts.expiry &&
803 current_time > j->second.dynamic_spki_hashes_expiry) { 825 current_time > j->second.dynamic_pkp.expiry) {
804 enabled_hosts_.erase(j); 826 enabled_hosts_.erase(j);
805 DirtyNotify(); 827 DirtyNotify();
806 continue; 828 continue;
807 } 829 }
808 830
809 state = j->second; 831 state = j->second;
810 state.domain = DNSDomainToString(host_sub_chunk); 832 state.domain = DNSDomainToString(host_sub_chunk);
811 833
812 // Succeed if we matched the domain exactly or if subdomain matches are 834 // Succeed if we matched the domain exactly or if subdomain matches are
813 // allowed. 835 // allowed.
814 if (i == 0 || j->second.sts_include_subdomains || 836 if (i == 0 || j->second.dynamic_sts.include_subdomains ||
815 j->second.pkp_include_subdomains) { 837 j->second.dynamic_pkp.include_subdomains) {
816 *result = state; 838 *result = state;
817 return true; 839 return true;
818 } 840 }
819 841
820 return false; 842 return false;
821 } 843 }
822 844
823 return false; 845 return false;
824 } 846 }
825 847
826 848
827 void TransportSecurityState::AddOrUpdateEnabledHosts( 849 void TransportSecurityState::AddOrUpdateEnabledHosts(
828 const std::string& hashed_host, const DomainState& state) { 850 const std::string& hashed_host, const DomainState& state) {
829 DCHECK(CalledOnValidThread()); 851 DCHECK(CalledOnValidThread());
830 enabled_hosts_[hashed_host] = state; 852 enabled_hosts_[hashed_host] = state;
831 } 853 }
832 854
833 TransportSecurityState::DomainState::DomainState() 855 TransportSecurityState::DomainState::DomainState()
834 : upgrade_mode(MODE_DEFAULT), 856 : has_static_sts(false),
835 sts_include_subdomains(false), 857 has_static_pkp(false) {
836 pkp_include_subdomains(false) { 858 dynamic_sts.upgrade_mode = MODE_DEFAULT;
837 base::Time now(base::Time::Now()); 859 dynamic_sts.include_subdomains = false;
838 sts_observed = now; 860 dynamic_pkp.include_subdomains = false;
839 pkp_observed = now;
840 } 861 }
841 862
842 TransportSecurityState::DomainState::~DomainState() { 863 TransportSecurityState::DomainState::~DomainState() {
843 } 864 }
844 865
845 bool TransportSecurityState::DomainState::CheckPublicKeyPins( 866 bool TransportSecurityState::DomainState::CheckPublicKeyPins(
846 const HashValueVector& hashes) const { 867 const HashValueVector& hashes) const {
847 // 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
848 // 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.
849 // And, hashes *can* be empty in some test scenarios. 870 // And, hashes *can* be empty in some test scenarios.
850 if (hashes.empty()) { 871 if (hashes.empty()) {
851 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned " 872 LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned "
852 "domain " << domain; 873 "domain " << domain;
853 return false; 874 return false;
854 } 875 }
855 876
856 if (HashesIntersect(bad_static_spki_hashes, hashes)) { 877 if (HashesIntersect(static_pkp.bad_spki_hashes, hashes) ||
878 HashesIntersect(dynamic_pkp.bad_spki_hashes, hashes)) {
857 LOG(ERROR) << "Rejecting public key chain for domain " << domain 879 LOG(ERROR) << "Rejecting public key chain for domain " << domain
858 << ". Validated chain: " << HashesToBase64String(hashes) 880 << ". Validated chain: " << HashesToBase64String(hashes)
859 << ", matches one or more bad hashes: " 881 << ", matches one or more bad hashes: "
860 << HashesToBase64String(bad_static_spki_hashes); 882 << HashesToBase64String(static_pkp.bad_spki_hashes) <<
883 ", " << HashesToBase64String(dynamic_pkp.bad_spki_hashes);
861 return false; 884 return false;
862 } 885 }
863 886
864 // If there are no pins, then any valid chain is acceptable. 887 // If there are no pins, then any valid chain is acceptable.
865 if (dynamic_spki_hashes.empty() && static_spki_hashes.empty()) 888 if (dynamic_pkp.spki_hashes.empty() && static_pkp.spki_hashes.empty()) {
866 return true; 889 return true;
890 }
867 891
868 if (HashesIntersect(dynamic_spki_hashes, hashes) || 892 if (HashesIntersect(dynamic_pkp.spki_hashes, hashes) ||
869 HashesIntersect(static_spki_hashes, hashes)) { 893 HashesIntersect(static_pkp.spki_hashes, hashes)) {
Ryan Sleevi 2014/01/31 20:24:43 This bit surprises me. Consider a preload of (A,
palmer 2014/01/31 22:20:51 Have we in fact decided that? (Maybe we have; I ha
palmer 2014/02/20 22:13:27 Where do we think we are on this? I'd like to get
870 return true; 894 return true;
871 } 895 }
872 896
873 LOG(ERROR) << "Rejecting public key chain for domain " << domain 897 LOG(ERROR) << "Rejecting public key chain for domain " << domain
874 << ". Validated chain: " << HashesToBase64String(hashes) 898 << ". Validated chain: " << HashesToBase64String(hashes)
875 << ", expected: " << HashesToBase64String(dynamic_spki_hashes) 899 << ", expected: " << HashesToBase64String(dynamic_pkp.spki_hashes)
876 << " or: " << HashesToBase64String(static_spki_hashes); 900 << " or: " << HashesToBase64String(static_pkp.spki_hashes);
877 return false; 901 return false;
878 } 902 }
879 903
880 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { 904 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
881 return upgrade_mode == MODE_FORCE_HTTPS; 905 return dynamic_sts.upgrade_mode == MODE_FORCE_HTTPS ||
Ryan Sleevi 2014/01/31 20:24:43 If we observed a dynamic header with an explicit e
palmer 2014/01/31 22:20:51 I think so, following the same logic as above ("st
906 static_sts.upgrade_mode == MODE_FORCE_HTTPS;
882 } 907 }
883 908
884 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { 909 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
885 return true; 910 return true;
886 } 911 }
887 912
888 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { 913 bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
889 return static_spki_hashes.size() > 0 || 914 return static_pkp.spki_hashes.size() > 0 ||
890 bad_static_spki_hashes.size() > 0 || 915 static_pkp.bad_spki_hashes.size() > 0 ||
891 dynamic_spki_hashes.size() > 0; 916 dynamic_pkp.spki_hashes.size() > 0;
892 } 917 }
893 918
894 } // namespace 919 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698