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

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: Fix browser_tests by setting the domain name correctly. Rebase. Created 6 years, 8 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->pkp.last_observed < state.pkp.last_observed)
89 other->pkp = state.pkp;
90 if (other->sts.last_observed < state.sts.last_observed)
91 other->sts = state.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()) {
94 } 104 }
95 105
96 TransportSecurityState::Iterator::~Iterator() {} 106 TransportSecurityState::Iterator::~Iterator() {}
97 107
108 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host,
109 bool sni_enabled) {
110 DomainState state;
111 if (GetStaticDomainState(host, sni_enabled, &state))
112 return true;
113 return GetDynamicDomainState(host, &state);
agl 2014/04/24 20:51:09 Doesn't this mean that HPKP headers make SSL error
Ryan Sleevi 2014/04/24 21:40:21 No, it's a bug.
palmer 2014/04/25 00:59:59 According to our draft as written, it's a feature:
114 }
115
116 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host,
117 bool sni_enabled) {
118 DomainState static_state;
119 if (GetStaticDomainState(host, sni_enabled, &static_state)) {
120 if (static_state.ShouldUpgradeToSSL())
agl 2014/04/24 20:51:09 just return static_state.ShouldUpgradeToSSL() dire
Ryan Sleevi 2014/04/24 21:40:21 No, this is to catch the fall through where the st
agl 2014/04/24 21:45:55 Ah, I see. I was thinking that if positive static
palmer 2014/04/25 00:59:59 Done.
121 return true;
122 }
123
124 DomainState dynamic_state;
125 if (GetDynamicDomainState(host, &dynamic_state))
126 return dynamic_state.ShouldUpgradeToSSL();
127
128 return false;
129 }
130
131 bool TransportSecurityState::CheckPublicKeyPins(const std::string& host,
132 bool sni_enabled,
133 const HashValueVector& hashes,
134 std::string* failure_log) {
135 DomainState static_state;
136 if (GetStaticDomainState(host, sni_enabled, &static_state)) {
137 if (static_state.CheckPublicKeyPins(hashes, failure_log))
agl 2014/04/24 20:51:09 again, can just return the function's return value
agl 2014/04/24 21:45:55 Again, I was assuming that static pins overrode, b
palmer 2014/04/25 00:59:59 Applied the same "dynamic first" policy as above.
138 return true;
139 }
140
141 DomainState dynamic_state;
142 if (GetDynamicDomainState(host, &dynamic_state))
143 return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
144
145 return false;
146 }
147
148 bool TransportSecurityState::HasPublicKeyPins(const std::string& host,
149 bool sni_enabled) {
150 DomainState static_state;
151 if (GetStaticDomainState(host, sni_enabled, &static_state)) {
152 if (static_state.HasPublicKeyPins())
agl 2014/04/24 20:51:09 ... and here.
agl 2014/04/24 21:45:55 Sorry, this one was nonsense.
palmer 2014/04/25 00:59:59 Dynamic first, as above.
153 return true;
154 }
155
156 DomainState dynamic_state;
157 if (GetDynamicDomainState(host, &dynamic_state))
158 return dynamic_state.HasPublicKeyPins();
159
160 return false;
161 }
162
98 void TransportSecurityState::SetDelegate( 163 void TransportSecurityState::SetDelegate(
99 TransportSecurityState::Delegate* delegate) { 164 TransportSecurityState::Delegate* delegate) {
100 DCHECK(CalledOnValidThread()); 165 DCHECK(CalledOnValidThread());
101 delegate_ = delegate; 166 delegate_ = delegate;
102 } 167 }
103 168
104 void TransportSecurityState::EnableHost(const std::string& host, 169 void TransportSecurityState::EnableHost(const std::string& host,
105 const DomainState& state) { 170 const DomainState& state) {
106 DCHECK(CalledOnValidThread()); 171 DCHECK(CalledOnValidThread());
107 172
(...skipping 20 matching lines...) Expand all
128 DomainStateMap::iterator i = enabled_hosts_.find( 193 DomainStateMap::iterator i = enabled_hosts_.find(
129 HashHost(canonicalized_host)); 194 HashHost(canonicalized_host));
130 if (i != enabled_hosts_.end()) { 195 if (i != enabled_hosts_.end()) {
131 enabled_hosts_.erase(i); 196 enabled_hosts_.erase(i);
132 DirtyNotify(); 197 DirtyNotify();
133 return true; 198 return true;
134 } 199 }
135 return false; 200 return false;
136 } 201 }
137 202
138 bool TransportSecurityState::GetDomainState(const std::string& host,
139 bool sni_enabled,
140 DomainState* result) {
141 DCHECK(CalledOnValidThread());
142
143 DomainState state;
144 const std::string canonicalized_host = CanonicalizeHost(host);
145 if (canonicalized_host.empty())
146 return false;
147
148 bool has_preload = GetStaticDomainState(canonicalized_host, sni_enabled,
149 &state);
150 std::string canonicalized_preload = CanonicalizeHost(state.domain);
151 GetDynamicDomainState(host, &state);
152
153 base::Time current_time(base::Time::Now());
154
155 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
156 std::string host_sub_chunk(&canonicalized_host[i],
157 canonicalized_host.size() - i);
158 // Exact match of a preload always wins.
159 if (has_preload && host_sub_chunk == canonicalized_preload) {
160 *result = state;
161 return true;
162 }
163
164 DomainStateMap::iterator j =
165 enabled_hosts_.find(HashHost(host_sub_chunk));
166 if (j == enabled_hosts_.end())
167 continue;
168
169 if (current_time > j->second.upgrade_expiry &&
170 current_time > j->second.dynamic_spki_hashes_expiry) {
171 enabled_hosts_.erase(j);
172 DirtyNotify();
173 continue;
174 }
175
176 state = j->second;
177 state.domain = DNSDomainToString(host_sub_chunk);
178
179 // Succeed if we matched the domain exactly or if subdomain matches are
180 // allowed.
181 if (i == 0 || j->second.sts_include_subdomains ||
182 j->second.pkp_include_subdomains) {
183 *result = state;
184 return true;
185 }
186
187 return false;
188 }
189
190 return false;
191 }
192
193 void TransportSecurityState::ClearDynamicData() { 203 void TransportSecurityState::ClearDynamicData() {
194 DCHECK(CalledOnValidThread()); 204 DCHECK(CalledOnValidThread());
195 enabled_hosts_.clear(); 205 enabled_hosts_.clear();
196 } 206 }
197 207
198 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { 208 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
199 DCHECK(CalledOnValidThread()); 209 DCHECK(CalledOnValidThread());
200 210
201 bool dirtied = false; 211 bool dirtied = false;
202 DomainStateMap::iterator i = enabled_hosts_.begin(); 212 DomainStateMap::iterator i = enabled_hosts_.begin();
203 while (i != enabled_hosts_.end()) { 213 while (i != enabled_hosts_.end()) {
204 if (i->second.sts_observed >= time && i->second.pkp_observed >= time) { 214 if (i->second.sts.last_observed >= time &&
215 i->second.pkp.last_observed >= time) {
205 dirtied = true; 216 dirtied = true;
206 enabled_hosts_.erase(i++); 217 enabled_hosts_.erase(i++);
207 continue; 218 continue;
208 } 219 }
209 220
210 if (i->second.sts_observed >= time) { 221 if (i->second.sts.last_observed >= time) {
211 dirtied = true; 222 dirtied = true;
212 i->second.upgrade_mode = DomainState::MODE_DEFAULT; 223 i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT;
213 } else if (i->second.pkp_observed >= time) { 224 } else if (i->second.pkp.last_observed >= time) {
214 dirtied = true; 225 dirtied = true;
215 i->second.dynamic_spki_hashes.clear(); 226 i->second.pkp.spki_hashes.clear();
216 } 227 }
217 ++i; 228 ++i;
218 } 229 }
219 230
220 if (dirtied) 231 if (dirtied)
221 DirtyNotify(); 232 DirtyNotify();
222 } 233 }
223 234
224 TransportSecurityState::~TransportSecurityState() { 235 TransportSecurityState::~TransportSecurityState() {
225 DCHECK(CalledOnValidThread()); 236 DCHECK(CalledOnValidThread());
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, 559 static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries,
549 const std::string& canonicalized_host, size_t i, 560 const std::string& canonicalized_host, size_t i,
550 TransportSecurityState::DomainState* out, bool* ret) { 561 TransportSecurityState::DomainState* out, bool* ret) {
551 for (size_t j = 0; j < num_entries; j++) { 562 for (size_t j = 0; j < num_entries; j++) {
552 if (entries[j].length == canonicalized_host.size() - i && 563 if (entries[j].length == canonicalized_host.size() - i &&
553 memcmp(entries[j].dns_name, &canonicalized_host[i], 564 memcmp(entries[j].dns_name, &canonicalized_host[i],
554 entries[j].length) == 0) { 565 entries[j].length) == 0) {
555 if (!entries[j].include_subdomains && i != 0) { 566 if (!entries[j].include_subdomains && i != 0) {
556 *ret = false; 567 *ret = false;
557 } else { 568 } else {
558 out->sts_include_subdomains = entries[j].include_subdomains; 569 out->sts.include_subdomains = entries[j].include_subdomains;
559 out->pkp_include_subdomains = entries[j].include_subdomains; 570 out->sts.last_observed = base::GetBuildTime();
571 out->pkp.include_subdomains = entries[j].include_subdomains;
572 out->pkp.last_observed = base::GetBuildTime();
560 *ret = true; 573 *ret = true;
574 out->sts.upgrade_mode =
575 TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
561 if (!entries[j].https_required) 576 if (!entries[j].https_required)
562 out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; 577 out->sts.upgrade_mode =
578 TransportSecurityState::DomainState::MODE_DEFAULT;
563 if (entries[j].pins.required_hashes) { 579 if (entries[j].pins.required_hashes) {
564 const char* const* sha1_hash = entries[j].pins.required_hashes; 580 const char* const* sha1_hash = entries[j].pins.required_hashes;
565 while (*sha1_hash) { 581 while (*sha1_hash) {
566 AddHash(*sha1_hash, &out->static_spki_hashes); 582 AddHash(*sha1_hash, &out->pkp.spki_hashes);
567 sha1_hash++; 583 sha1_hash++;
568 } 584 }
569 } 585 }
570 if (entries[j].pins.excluded_hashes) { 586 if (entries[j].pins.excluded_hashes) {
571 const char* const* sha1_hash = entries[j].pins.excluded_hashes; 587 const char* const* sha1_hash = entries[j].pins.excluded_hashes;
572 while (*sha1_hash) { 588 while (*sha1_hash) {
573 AddHash(*sha1_hash, &out->bad_static_spki_hashes); 589 AddHash(*sha1_hash, &out->pkp.bad_spki_hashes);
574 sha1_hash++; 590 sha1_hash++;
575 } 591 }
576 } 592 }
577 } 593 }
578 return true; 594 return true;
579 } 595 }
580 } 596 }
581 return false; 597 return false;
582 } 598 }
583 599
(...skipping 27 matching lines...) Expand all
611 } 627 }
612 628
613 bool TransportSecurityState::AddHSTSHeader(const std::string& host, 629 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
614 const std::string& value) { 630 const std::string& value) {
615 DCHECK(CalledOnValidThread()); 631 DCHECK(CalledOnValidThread());
616 632
617 base::Time now = base::Time::Now(); 633 base::Time now = base::Time::Now();
618 base::TimeDelta max_age; 634 base::TimeDelta max_age;
619 TransportSecurityState::DomainState domain_state; 635 TransportSecurityState::DomainState domain_state;
620 GetDynamicDomainState(host, &domain_state); 636 GetDynamicDomainState(host, &domain_state);
621 if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { 637 if (ParseHSTSHeader(value, &max_age, &domain_state.sts.include_subdomains)) {
622 // Handle max-age == 0 638 // Handle max-age == 0
623 if (max_age.InSeconds() == 0) 639 if (max_age.InSeconds() == 0)
624 domain_state.upgrade_mode = DomainState::MODE_DEFAULT; 640 domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT;
625 else 641 else
626 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 642 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
627 domain_state.sts_observed = now; 643 domain_state.sts.last_observed = now;
628 domain_state.upgrade_expiry = now + max_age; 644 domain_state.sts.expiry = now + max_age;
629 EnableHost(host, domain_state); 645 EnableHost(host, domain_state);
630 return true; 646 return true;
631 } 647 }
632 return false; 648 return false;
633 } 649 }
634 650
635 bool TransportSecurityState::AddHPKPHeader(const std::string& host, 651 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
636 const std::string& value, 652 const std::string& value,
637 const SSLInfo& ssl_info) { 653 const SSLInfo& ssl_info) {
638 DCHECK(CalledOnValidThread()); 654 DCHECK(CalledOnValidThread());
639 655
640 base::Time now = base::Time::Now(); 656 base::Time now = base::Time::Now();
641 base::TimeDelta max_age; 657 base::TimeDelta max_age;
642 TransportSecurityState::DomainState domain_state; 658 TransportSecurityState::DomainState domain_state;
643 GetDynamicDomainState(host, &domain_state); 659 GetDynamicDomainState(host, &domain_state);
644 if (ParseHPKPHeader(value, ssl_info.public_key_hashes, 660 if (ParseHPKPHeader(value,
645 &max_age, &domain_state.pkp_include_subdomains, 661 ssl_info.public_key_hashes,
646 &domain_state.dynamic_spki_hashes)) { 662 &max_age,
663 &domain_state.pkp.include_subdomains,
664 &domain_state.pkp.spki_hashes)) {
647 // TODO(palmer): http://crbug.com/243865 handle max-age == 0. 665 // TODO(palmer): http://crbug.com/243865 handle max-age == 0.
648 domain_state.pkp_observed = now; 666 domain_state.pkp.last_observed = now;
649 domain_state.dynamic_spki_hashes_expiry = now + max_age; 667 domain_state.pkp.expiry = now + max_age;
650 EnableHost(host, domain_state); 668 EnableHost(host, domain_state);
651 return true; 669 return true;
652 } 670 }
653 return false; 671 return false;
654 } 672 }
655 673
656 bool TransportSecurityState::AddHSTS(const std::string& host, 674 bool TransportSecurityState::AddHSTS(const std::string& host,
657 const base::Time& expiry, 675 const base::Time& expiry,
658 bool include_subdomains) { 676 bool include_subdomains) {
659 DCHECK(CalledOnValidThread()); 677 DCHECK(CalledOnValidThread());
660 678
661 // Copy-and-modify the existing DomainState for this host (if any). 679 // Copy-and-modify the existing DomainState for this host (if any).
662 TransportSecurityState::DomainState domain_state; 680 TransportSecurityState::DomainState domain_state;
663 const std::string canonicalized_host = CanonicalizeHost(host); 681 const std::string canonicalized_host = CanonicalizeHost(host);
664 const std::string hashed_host = HashHost(canonicalized_host); 682 const std::string hashed_host = HashHost(canonicalized_host);
665 DomainStateMap::const_iterator i = enabled_hosts_.find( 683 DomainStateMap::const_iterator i = enabled_hosts_.find(
666 hashed_host); 684 hashed_host);
667 if (i != enabled_hosts_.end()) 685 if (i != enabled_hosts_.end())
668 domain_state = i->second; 686 domain_state = i->second;
669 687
670 domain_state.sts_observed = base::Time::Now(); 688 domain_state.sts.last_observed = base::Time::Now();
671 domain_state.sts_include_subdomains = include_subdomains; 689 domain_state.sts.include_subdomains = include_subdomains;
672 domain_state.upgrade_expiry = expiry; 690 domain_state.sts.expiry = expiry;
673 domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; 691 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
674 EnableHost(host, domain_state); 692 EnableHost(host, domain_state);
675 return true; 693 return true;
676 } 694 }
677 695
678 bool TransportSecurityState::AddHPKP(const std::string& host, 696 bool TransportSecurityState::AddHPKP(const std::string& host,
679 const base::Time& expiry, 697 const base::Time& expiry,
680 bool include_subdomains, 698 bool include_subdomains,
681 const HashValueVector& hashes) { 699 const HashValueVector& hashes) {
682 DCHECK(CalledOnValidThread()); 700 DCHECK(CalledOnValidThread());
683 701
684 // Copy-and-modify the existing DomainState for this host (if any). 702 // Copy-and-modify the existing DomainState for this host (if any).
685 TransportSecurityState::DomainState domain_state; 703 TransportSecurityState::DomainState domain_state;
686 const std::string canonicalized_host = CanonicalizeHost(host); 704 const std::string canonicalized_host = CanonicalizeHost(host);
687 const std::string hashed_host = HashHost(canonicalized_host); 705 const std::string hashed_host = HashHost(canonicalized_host);
688 DomainStateMap::const_iterator i = enabled_hosts_.find( 706 DomainStateMap::const_iterator i = enabled_hosts_.find(
689 hashed_host); 707 hashed_host);
690 if (i != enabled_hosts_.end()) 708 if (i != enabled_hosts_.end())
691 domain_state = i->second; 709 domain_state = i->second;
692 710
693 domain_state.pkp_observed = base::Time::Now(); 711 domain_state.pkp.last_observed = base::Time::Now();
694 domain_state.pkp_include_subdomains = include_subdomains; 712 domain_state.pkp.include_subdomains = include_subdomains;
695 domain_state.dynamic_spki_hashes_expiry = expiry; 713 domain_state.pkp.expiry = expiry;
696 domain_state.dynamic_spki_hashes = hashes; 714 domain_state.pkp.spki_hashes = hashes;
697 EnableHost(host, domain_state); 715 EnableHost(host, domain_state);
698 return true; 716 return true;
699 } 717 }
700 718
701 // static 719 // static
702 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, 720 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
703 bool sni_enabled) { 721 bool sni_enabled) {
704 std::string canonicalized_host = CanonicalizeHost(host); 722 std::string canonicalized_host = CanonicalizeHost(host);
705 const struct HSTSPreload* entry = 723 const struct HSTSPreload* entry =
706 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); 724 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 entry->second_level_domain_name, DOMAIN_NUM_EVENTS); 761 entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
744 } 762 }
745 763
746 // static 764 // static
747 bool TransportSecurityState::IsBuildTimely() { 765 bool TransportSecurityState::IsBuildTimely() {
748 const base::Time build_time = base::GetBuildTime(); 766 const base::Time build_time = base::GetBuildTime();
749 // We consider built-in information to be timely for 10 weeks. 767 // We consider built-in information to be timely for 10 weeks.
750 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; 768 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
751 } 769 }
752 770
753 bool TransportSecurityState::GetStaticDomainState( 771 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
754 const std::string& canonicalized_host, 772 bool sni_enabled,
755 bool sni_enabled, 773 DomainState* out) {
756 DomainState* out) {
757 DCHECK(CalledOnValidThread()); 774 DCHECK(CalledOnValidThread());
758 775
759 out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; 776 const std::string canonicalized_host = CanonicalizeHost(host);
760 out->sts_include_subdomains = false; 777
761 out->pkp_include_subdomains = false; 778 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
779 out->sts.include_subdomains = false;
780 out->pkp.include_subdomains = false;
762 781
763 const bool is_build_timely = IsBuildTimely(); 782 const bool is_build_timely = IsBuildTimely();
764 783
765 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) {
766 std::string host_sub_chunk(&canonicalized_host[i], 785 std::string host_sub_chunk(&canonicalized_host[i],
767 canonicalized_host.size() - i); 786 canonicalized_host.size() - i);
768 out->domain = DNSDomainToString(host_sub_chunk); 787 out->domain = DNSDomainToString(host_sub_chunk);
769 bool ret; 788 bool ret;
770 if (is_build_timely && 789 if (is_build_timely &&
771 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out, 790 HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out,
(...skipping 23 matching lines...) Expand all
795 base::Time current_time(base::Time::Now()); 814 base::Time current_time(base::Time::Now());
796 815
797 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) {
798 std::string host_sub_chunk(&canonicalized_host[i], 817 std::string host_sub_chunk(&canonicalized_host[i],
799 canonicalized_host.size() - i); 818 canonicalized_host.size() - i);
800 DomainStateMap::iterator j = 819 DomainStateMap::iterator j =
801 enabled_hosts_.find(HashHost(host_sub_chunk)); 820 enabled_hosts_.find(HashHost(host_sub_chunk));
802 if (j == enabled_hosts_.end()) 821 if (j == enabled_hosts_.end())
803 continue; 822 continue;
804 823
805 if (current_time > j->second.upgrade_expiry && 824 if (current_time > j->second.sts.expiry &&
806 current_time > j->second.dynamic_spki_hashes_expiry) { 825 current_time > j->second.pkp.expiry) {
807 enabled_hosts_.erase(j); 826 enabled_hosts_.erase(j);
808 DirtyNotify(); 827 DirtyNotify();
809 continue; 828 continue;
810 } 829 }
811 830
812 state = j->second; 831 state = j->second;
813 state.domain = DNSDomainToString(host_sub_chunk); 832 state.domain = DNSDomainToString(host_sub_chunk);
814 833
815 // 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
816 // allowed. 835 // allowed.
817 if (i == 0 || j->second.sts_include_subdomains || 836 if (i == 0 || j->second.sts.include_subdomains ||
818 j->second.pkp_include_subdomains) { 837 j->second.pkp.include_subdomains) {
819 *result = state; 838 *result = state;
820 return true; 839 return true;
821 } 840 }
822 841
823 return false; 842 return false;
824 } 843 }
825 844
826 return false; 845 return false;
827 } 846 }
828 847
829
830 void TransportSecurityState::AddOrUpdateEnabledHosts( 848 void TransportSecurityState::AddOrUpdateEnabledHosts(
831 const std::string& hashed_host, const DomainState& state) { 849 const std::string& hashed_host, const DomainState& state) {
832 DCHECK(CalledOnValidThread()); 850 DCHECK(CalledOnValidThread());
833 enabled_hosts_[hashed_host] = state; 851 enabled_hosts_[hashed_host] = state;
834 } 852 }
835 853
836 TransportSecurityState::DomainState::DomainState() 854 TransportSecurityState::DomainState::DomainState() {
837 : upgrade_mode(MODE_DEFAULT), 855 sts.upgrade_mode = MODE_DEFAULT;
838 sts_include_subdomains(false), 856 sts.include_subdomains = false;
839 pkp_include_subdomains(false) { 857 pkp.include_subdomains = false;
840 base::Time now(base::Time::Now());
841 sts_observed = now;
842 pkp_observed = now;
843 } 858 }
844 859
845 TransportSecurityState::DomainState::~DomainState() { 860 TransportSecurityState::DomainState::~DomainState() {
846 } 861 }
847 862
848 bool TransportSecurityState::DomainState::CheckPublicKeyPins( 863 bool TransportSecurityState::DomainState::CheckPublicKeyPins(
849 const HashValueVector& hashes, std::string* failure_log) const { 864 const HashValueVector& hashes, std::string* failure_log) const {
850 // Validate that hashes is not empty. By the time this code is called (in 865 // Validate that hashes is not empty. By the time this code is called (in
851 // production), that should never happen, but it's good to be defensive. 866 // production), that should never happen, but it's good to be defensive.
852 // And, hashes *can* be empty in some test scenarios. 867 // And, hashes *can* be empty in some test scenarios.
853 if (hashes.empty()) { 868 if (hashes.empty()) {
854 *failure_log = "Rejecting empty public key chain for public-key-pinned " 869 failure_log->append(
855 "domains: " + domain; 870 "Rejecting empty public key chain for public-key-pinned domains: " +
871 domain);
856 return false; 872 return false;
857 } 873 }
858 874
859 if (HashesIntersect(bad_static_spki_hashes, hashes)) { 875 if (HashesIntersect(pkp.bad_spki_hashes, hashes)) {
860 *failure_log = "Rejecting public key chain for domain " + domain + 876 failure_log->append("Rejecting public key chain for domain " + domain +
861 ". Validated chain: " + HashesToBase64String(hashes) + 877 ". Validated chain: " + HashesToBase64String(hashes) +
862 ", matches one or more bad hashes: " + 878 ", matches one or more bad hashes: " +
863 HashesToBase64String(bad_static_spki_hashes); 879 HashesToBase64String(pkp.bad_spki_hashes));
864 return false; 880 return false;
865 } 881 }
866 882
867 // If there are no pins, then any valid chain is acceptable. 883 // If there are no pins, then any valid chain is acceptable.
868 if (dynamic_spki_hashes.empty() && static_spki_hashes.empty()) 884 if (pkp.spki_hashes.empty())
869 return true; 885 return true;
870 886
871 if (HashesIntersect(dynamic_spki_hashes, hashes) || 887 if (HashesIntersect(pkp.spki_hashes, hashes)) {
872 HashesIntersect(static_spki_hashes, hashes)) {
873 return true; 888 return true;
874 } 889 }
875 890
876 *failure_log = "Rejecting public key chain for domain " + domain + 891 failure_log->append("Rejecting public key chain for domain " + domain +
877 ". Validated chain: " + HashesToBase64String(hashes) + 892 ". Validated chain: " + HashesToBase64String(hashes) +
878 ", expected: " + HashesToBase64String(dynamic_spki_hashes) + 893 ", expected: " + HashesToBase64String(pkp.spki_hashes));
879 " or: " + HashesToBase64String(static_spki_hashes);
880 return false; 894 return false;
881 } 895 }
882 896
883 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { 897 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
884 return upgrade_mode == MODE_FORCE_HTTPS; 898 return sts.upgrade_mode == MODE_FORCE_HTTPS;
885 } 899 }
886 900
887 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { 901 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
888 return true; 902 return true;
889 } 903 }
890 904
891 bool TransportSecurityState::DomainState::HasPublicKeyPins() const { 905 bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
892 return static_spki_hashes.size() > 0 || 906 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0;
893 bad_static_spki_hashes.size() > 0 ||
894 dynamic_spki_hashes.size() > 0;
895 } 907 }
896 908
897 } // namespace 909 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698