Make Ctrl + T from apps focus the new tab's omnibox on Linux and ChromeOS.
[chromium-blink-merge.git] / net / http / transport_security_state.cc
blob7147b48287f19f2bd9d1eaeb13e2beae24a5d340
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
3 // found in the LICENSE file.
5 #include "net/http/transport_security_state.h"
7 #if defined(USE_OPENSSL)
8 #include <openssl/ecdsa.h>
9 #include <openssl/ssl.h>
10 #else // !defined(USE_OPENSSL)
11 #include <cryptohi.h>
12 #include <hasht.h>
13 #include <keyhi.h>
14 #include <nspr.h>
15 #include <pk11pub.h>
16 #endif
18 #include <algorithm>
20 #include "base/base64.h"
21 #include "base/build_time.h"
22 #include "base/logging.h"
23 #include "base/memory/scoped_ptr.h"
24 #include "base/metrics/histogram.h"
25 #include "base/metrics/sparse_histogram.h"
26 #include "base/sha1.h"
27 #include "base/strings/string_number_conversions.h"
28 #include "base/strings/string_util.h"
29 #include "base/strings/utf_string_conversions.h"
30 #include "base/time/time.h"
31 #include "base/values.h"
32 #include "crypto/sha2.h"
33 #include "net/base/dns_util.h"
34 #include "net/cert/x509_cert_types.h"
35 #include "net/cert/x509_certificate.h"
36 #include "net/http/http_security_headers.h"
37 #include "net/ssl/ssl_info.h"
38 #include "url/gurl.h"
40 #if defined(USE_OPENSSL)
41 #include "crypto/openssl_util.h"
42 #endif
44 namespace net {
46 namespace {
48 std::string HashesToBase64String(const HashValueVector& hashes) {
49 std::string str;
50 for (size_t i = 0; i != hashes.size(); ++i) {
51 if (i != 0)
52 str += ",";
53 str += hashes[i].ToString();
55 return str;
58 std::string HashHost(const std::string& canonicalized_host) {
59 char hashed[crypto::kSHA256Length];
60 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
61 return std::string(hashed, sizeof(hashed));
64 // Returns true if the intersection of |a| and |b| is not empty. If either
65 // |a| or |b| is empty, returns false.
66 bool HashesIntersect(const HashValueVector& a,
67 const HashValueVector& b) {
68 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
69 HashValueVector::const_iterator j =
70 std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
71 if (j != b.end())
72 return true;
74 return false;
77 bool AddHash(const char* sha1_hash,
78 HashValueVector* out) {
79 HashValue hash(HASH_VALUE_SHA1);
80 memcpy(hash.data(), sha1_hash, hash.size());
81 out->push_back(hash);
82 return true;
85 } // namespace
87 TransportSecurityState::TransportSecurityState()
88 : delegate_(NULL), enable_static_pins_(true) {
89 // Static pinning is only enabled for official builds to make sure that
90 // others don't end up with pins that cannot be easily updated.
91 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
92 enable_static_pins_ = false;
93 #endif
94 DCHECK(CalledOnValidThread());
97 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
98 : iterator_(state.enabled_hosts_.begin()),
99 end_(state.enabled_hosts_.end()) {
102 TransportSecurityState::Iterator::~Iterator() {}
104 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host) {
105 DomainState state;
106 if (GetStaticDomainState(host, &state))
107 return true;
108 return GetDynamicDomainState(host, &state);
111 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host) {
112 DomainState dynamic_state;
113 if (GetDynamicDomainState(host, &dynamic_state))
114 return dynamic_state.ShouldUpgradeToSSL();
116 DomainState static_state;
117 if (GetStaticDomainState(host, &static_state) &&
118 static_state.ShouldUpgradeToSSL()) {
119 return true;
122 return false;
125 bool TransportSecurityState::CheckPublicKeyPins(
126 const std::string& host,
127 bool is_issued_by_known_root,
128 const HashValueVector& public_key_hashes,
129 std::string* pinning_failure_log) {
130 // Perform pin validation if, and only if, all these conditions obtain:
132 // * the server's certificate chain chains up to a known root (i.e. not a
133 // user-installed trust anchor); and
134 // * the server actually has public key pins.
135 if (!is_issued_by_known_root || !HasPublicKeyPins(host)) {
136 return true;
139 bool pins_are_valid = CheckPublicKeyPinsImpl(
140 host, public_key_hashes, pinning_failure_log);
141 if (!pins_are_valid) {
142 LOG(ERROR) << *pinning_failure_log;
143 ReportUMAOnPinFailure(host);
146 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
147 return pins_are_valid;
150 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
151 DomainState dynamic_state;
152 if (GetDynamicDomainState(host, &dynamic_state))
153 return dynamic_state.HasPublicKeyPins();
155 DomainState static_state;
156 if (GetStaticDomainState(host, &static_state)) {
157 if (static_state.HasPublicKeyPins())
158 return true;
161 return false;
164 void TransportSecurityState::SetDelegate(
165 TransportSecurityState::Delegate* delegate) {
166 DCHECK(CalledOnValidThread());
167 delegate_ = delegate;
170 void TransportSecurityState::AddHSTSInternal(
171 const std::string& host,
172 TransportSecurityState::DomainState::UpgradeMode upgrade_mode,
173 const base::Time& expiry,
174 bool include_subdomains) {
175 DCHECK(CalledOnValidThread());
177 // Copy-and-modify the existing DomainState for this host (if any).
178 DomainState domain_state;
179 const std::string canonicalized_host = CanonicalizeHost(host);
180 const std::string hashed_host = HashHost(canonicalized_host);
181 DomainStateMap::const_iterator i = enabled_hosts_.find(hashed_host);
182 if (i != enabled_hosts_.end())
183 domain_state = i->second;
185 domain_state.sts.last_observed = base::Time::Now();
186 domain_state.sts.include_subdomains = include_subdomains;
187 domain_state.sts.expiry = expiry;
188 domain_state.sts.upgrade_mode = upgrade_mode;
189 EnableHost(host, domain_state);
192 void TransportSecurityState::AddHPKPInternal(const std::string& host,
193 const base::Time& last_observed,
194 const base::Time& expiry,
195 bool include_subdomains,
196 const HashValueVector& hashes) {
197 DCHECK(CalledOnValidThread());
199 // Copy-and-modify the existing DomainState for this host (if any).
200 DomainState domain_state;
201 const std::string canonicalized_host = CanonicalizeHost(host);
202 const std::string hashed_host = HashHost(canonicalized_host);
203 DomainStateMap::const_iterator i = enabled_hosts_.find(hashed_host);
204 if (i != enabled_hosts_.end())
205 domain_state = i->second;
207 domain_state.pkp.last_observed = last_observed;
208 domain_state.pkp.expiry = expiry;
209 domain_state.pkp.include_subdomains = include_subdomains;
210 domain_state.pkp.spki_hashes = hashes;
211 EnableHost(host, domain_state);
214 void TransportSecurityState::EnableHost(const std::string& host,
215 const DomainState& state) {
216 DCHECK(CalledOnValidThread());
218 const std::string canonicalized_host = CanonicalizeHost(host);
219 if (canonicalized_host.empty())
220 return;
222 DomainState state_copy(state);
223 // No need to store this value since it is redundant. (|canonicalized_host|
224 // is the map key.)
225 state_copy.sts.domain.clear();
226 state_copy.pkp.domain.clear();
228 enabled_hosts_[HashHost(canonicalized_host)] = state_copy;
229 DirtyNotify();
232 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
233 DCHECK(CalledOnValidThread());
235 const std::string canonicalized_host = CanonicalizeHost(host);
236 if (canonicalized_host.empty())
237 return false;
239 DomainStateMap::iterator i = enabled_hosts_.find(
240 HashHost(canonicalized_host));
241 if (i != enabled_hosts_.end()) {
242 enabled_hosts_.erase(i);
243 DirtyNotify();
244 return true;
246 return false;
249 void TransportSecurityState::ClearDynamicData() {
250 DCHECK(CalledOnValidThread());
251 enabled_hosts_.clear();
254 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
255 DCHECK(CalledOnValidThread());
257 bool dirtied = false;
258 DomainStateMap::iterator i = enabled_hosts_.begin();
259 while (i != enabled_hosts_.end()) {
260 // Clear STS and PKP state independently.
261 if (i->second.sts.last_observed >= time) {
262 dirtied = true;
263 i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT;
265 if (i->second.pkp.last_observed >= time) {
266 dirtied = true;
267 i->second.pkp.spki_hashes.clear();
268 i->second.pkp.expiry = base::Time();
271 // If both are now invalid, drop the entry altogether.
272 if (!i->second.ShouldUpgradeToSSL() && !i->second.HasPublicKeyPins()) {
273 dirtied = true;
274 enabled_hosts_.erase(i++);
275 continue;
278 ++i;
281 if (dirtied)
282 DirtyNotify();
285 TransportSecurityState::~TransportSecurityState() {
286 DCHECK(CalledOnValidThread());
289 void TransportSecurityState::DirtyNotify() {
290 DCHECK(CalledOnValidThread());
292 if (delegate_)
293 delegate_->StateIsDirty(this);
296 // static
297 std::string TransportSecurityState::CanonicalizeHost(const std::string& host) {
298 // We cannot perform the operations as detailed in the spec here as |host|
299 // has already undergone IDN processing before it reached us. Thus, we check
300 // that there are no invalid characters in the host and lowercase the result.
302 std::string new_host;
303 if (!DNSDomainFromDot(host, &new_host)) {
304 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
305 // name is >255 bytes. However, search terms can have those properties.
306 return std::string();
309 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
310 const unsigned label_length = static_cast<unsigned>(new_host[i]);
311 if (!label_length)
312 break;
314 for (size_t j = 0; j < label_length; ++j) {
315 new_host[i + 1 + j] = static_cast<char>(tolower(new_host[i + 1 + j]));
319 return new_host;
322 // BitReader is a class that allows a bytestring to be read bit-by-bit.
323 class BitReader {
324 public:
325 BitReader(const uint8* bytes, size_t num_bits)
326 : bytes_(bytes),
327 num_bits_(num_bits),
328 num_bytes_((num_bits + 7) / 8),
329 current_byte_index_(0),
330 num_bits_used_(8) {}
332 // Next sets |*out| to the next bit from the input. It returns false if no
333 // more bits are available or true otherwise.
334 bool Next(bool* out) {
335 if (num_bits_used_ == 8) {
336 if (current_byte_index_ >= num_bytes_) {
337 return false;
339 current_byte_ = bytes_[current_byte_index_++];
340 num_bits_used_ = 0;
343 *out = 1 & (current_byte_ >> (7 - num_bits_used_));
344 num_bits_used_++;
345 return true;
348 // Read sets the |num_bits| least-significant bits of |*out| to the value of
349 // the next |num_bits| bits from the input. It returns false if there are
350 // insufficient bits in the input or true otherwise.
351 bool Read(unsigned num_bits, uint32* out) {
352 DCHECK_LE(num_bits, 32u);
354 uint32 ret = 0;
355 for (unsigned i = 0; i < num_bits; ++i) {
356 bool bit;
357 if (!Next(&bit)) {
358 return false;
360 ret |= static_cast<uint32>(bit) << (num_bits - 1 - i);
363 *out = ret;
364 return true;
367 // Unary sets |*out| to the result of decoding a unary value from the input.
368 // It returns false if there were insufficient bits in the input and true
369 // otherwise.
370 bool Unary(size_t* out) {
371 size_t ret = 0;
373 for (;;) {
374 bool bit;
375 if (!Next(&bit)) {
376 return false;
378 if (!bit) {
379 break;
381 ret++;
384 *out = ret;
385 return true;
388 // Seek sets the current offest in the input to bit number |offset|. It
389 // returns true if |offset| is within the range of the input and false
390 // otherwise.
391 bool Seek(size_t offset) {
392 if (offset >= num_bits_) {
393 return false;
395 current_byte_index_ = offset / 8;
396 current_byte_ = bytes_[current_byte_index_++];
397 num_bits_used_ = offset % 8;
398 return true;
401 private:
402 const uint8* const bytes_;
403 const size_t num_bits_;
404 const size_t num_bytes_;
405 // current_byte_index_ contains the current byte offset in |bytes_|.
406 size_t current_byte_index_;
407 // current_byte_ contains the current byte of the input.
408 uint8 current_byte_;
409 // num_bits_used_ contains the number of bits of |current_byte_| that have
410 // been read.
411 unsigned num_bits_used_;
414 // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
415 // simply encoded as a series of two-byte structures. The first byte determines
416 // the "0" pointer for that node and the second the "1" pointer. Each byte
417 // either has the MSB set, in which case the bottom 7 bits are the value for
418 // that position, or else the bottom seven bits contain the index of a node.
420 // The tree is decoded by walking rather than a table-driven approach.
421 class HuffmanDecoder {
422 public:
423 HuffmanDecoder(const uint8* tree, size_t tree_bytes)
424 : tree_(tree),
425 tree_bytes_(tree_bytes) {}
427 bool Decode(BitReader* reader, char* out) {
428 const uint8* current = &tree_[tree_bytes_-2];
430 for (;;) {
431 bool bit;
432 if (!reader->Next(&bit)) {
433 return false;
436 uint8 b = current[bit];
437 if (b & 0x80) {
438 *out = static_cast<char>(b & 0x7f);
439 return true;
442 unsigned offset = static_cast<unsigned>(b) * 2;
443 DCHECK_LT(offset, tree_bytes_);
444 if (offset >= tree_bytes_) {
445 return false;
448 current = &tree_[offset];
452 private:
453 const uint8* const tree_;
454 const size_t tree_bytes_;
457 #include "net/http/transport_security_state_static.h"
459 // PreloadResult is the result of resolving a specific name in the preloaded
460 // data.
461 struct PreloadResult {
462 uint32 pinset_id;
463 uint32 domain_id;
464 // hostname_offset contains the number of bytes from the start of the given
465 // hostname where the name of the matching entry starts.
466 size_t hostname_offset;
467 bool sts_include_subdomains;
468 bool pkp_include_subdomains;
469 bool force_https;
470 bool has_pins;
473 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns
474 // false on internal error and true otherwise. After a successful return,
475 // |*out_found| is true iff a relevant entry has been found. If so, |*out|
476 // contains the details.
478 // Don't call this function, call DecodeHSTSPreload, below.
480 // Although this code should be robust, it never processes attacker-controlled
481 // data -- it only operates on the preloaded data built into the binary.
483 // The preloaded data is represented as a trie and matches the hostname
484 // backwards. Each node in the trie starts with a number of characters, which
485 // must match exactly. After that is a dispatch table which maps the next
486 // character in the hostname to another node in the trie.
488 // In the dispatch table, the zero character represents the "end of string"
489 // (which is the *beginning* of a hostname since we process it backwards). The
490 // value in that case is special -- rather than an offset to another trie node,
491 // it contains the HSTS information: whether subdomains are included, pinsets
492 // etc. If an "end of string" matches a period in the hostname then the
493 // information is remembered because, if no more specific node is found, then
494 // that information applies to the hostname.
496 // Dispatch tables are always given in order, but the "end of string" (zero)
497 // value always comes before an entry for '.'.
498 bool DecodeHSTSPreloadRaw(const std::string& hostname,
499 bool* out_found,
500 PreloadResult* out) {
501 HuffmanDecoder huffman(kHSTSHuffmanTree, sizeof(kHSTSHuffmanTree));
502 BitReader reader(kPreloadedHSTSData, kPreloadedHSTSBits);
503 size_t bit_offset = kHSTSRootPosition;
504 static const char kEndOfString = 0;
505 static const char kEndOfTable = 127;
507 *out_found = false;
509 if (hostname.empty()) {
510 return true;
512 // hostname_offset contains one more than the index of the current character
513 // in the hostname that is being considered. It's one greater so that we can
514 // represent the position just before the beginning (with zero).
515 size_t hostname_offset = hostname.size();
517 for (;;) {
518 // Seek to the desired location.
519 if (!reader.Seek(bit_offset)) {
520 return false;
523 // Decode the unary length of the common prefix.
524 size_t prefix_length;
525 if (!reader.Unary(&prefix_length)) {
526 return false;
529 // Match each character in the prefix.
530 for (size_t i = 0; i < prefix_length; ++i) {
531 if (hostname_offset == 0) {
532 // We can't match the terminator with a prefix string.
533 return true;
536 char c;
537 if (!huffman.Decode(&reader, &c)) {
538 return false;
540 if (hostname[hostname_offset - 1] != c) {
541 return true;
543 hostname_offset--;
546 bool is_first_offset = true;
547 size_t current_offset = 0;
549 // Next is the dispatch table.
550 for (;;) {
551 char c;
552 if (!huffman.Decode(&reader, &c)) {
553 return false;
555 if (c == kEndOfTable) {
556 // No exact match.
557 return true;
560 if (c == kEndOfString) {
561 PreloadResult tmp;
562 if (!reader.Next(&tmp.sts_include_subdomains) ||
563 !reader.Next(&tmp.force_https) ||
564 !reader.Next(&tmp.has_pins)) {
565 return false;
568 tmp.pkp_include_subdomains = tmp.sts_include_subdomains;
570 if (tmp.has_pins) {
571 if (!reader.Read(4, &tmp.pinset_id) ||
572 !reader.Read(9, &tmp.domain_id) ||
573 (!tmp.sts_include_subdomains &&
574 !reader.Next(&tmp.pkp_include_subdomains))) {
575 return false;
579 tmp.hostname_offset = hostname_offset;
581 if (hostname_offset == 0 || hostname[hostname_offset - 1] == '.') {
582 *out_found =
583 tmp.sts_include_subdomains || tmp.pkp_include_subdomains;
584 *out = tmp;
586 if (hostname_offset > 0) {
587 out->force_https &= tmp.sts_include_subdomains;
588 } else {
589 *out_found = true;
590 return true;
594 continue;
597 // The entries in a dispatch table are in order thus we can tell if there
598 // will be no match if the current character past the one that we want.
599 if (hostname_offset == 0 || hostname[hostname_offset-1] < c) {
600 return true;
603 if (is_first_offset) {
604 // The first offset is backwards from the current position.
605 uint32 jump_delta_bits;
606 uint32 jump_delta;
607 if (!reader.Read(5, &jump_delta_bits) ||
608 !reader.Read(jump_delta_bits, &jump_delta)) {
609 return false;
612 if (bit_offset < jump_delta) {
613 return false;
616 current_offset = bit_offset - jump_delta;
617 is_first_offset = false;
618 } else {
619 // Subsequent offsets are forward from the target of the first offset.
620 uint32 is_long_jump;
621 if (!reader.Read(1, &is_long_jump)) {
622 return false;
625 uint32 jump_delta;
626 if (!is_long_jump) {
627 if (!reader.Read(7, &jump_delta)) {
628 return false;
630 } else {
631 uint32 jump_delta_bits;
632 if (!reader.Read(4, &jump_delta_bits) ||
633 !reader.Read(jump_delta_bits + 8, &jump_delta)) {
634 return false;
638 current_offset += jump_delta;
639 if (current_offset >= bit_offset) {
640 return false;
644 DCHECK_LT(0u, hostname_offset);
645 if (hostname[hostname_offset - 1] == c) {
646 bit_offset = current_offset;
647 hostname_offset--;
648 break;
654 bool DecodeHSTSPreload(const std::string& hostname,
655 PreloadResult* out) {
656 bool found;
657 if (!DecodeHSTSPreloadRaw(hostname, &found, out)) {
658 DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
659 << hostname;
660 return false;
663 return found;
666 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
667 const std::string& value) {
668 DCHECK(CalledOnValidThread());
670 base::Time now = base::Time::Now();
671 base::TimeDelta max_age;
672 bool include_subdomains;
673 if (!ParseHSTSHeader(value, &max_age, &include_subdomains)) {
674 return false;
677 // Handle max-age == 0.
678 DomainState::UpgradeMode upgrade_mode;
679 if (max_age.InSeconds() == 0) {
680 upgrade_mode = DomainState::MODE_DEFAULT;
681 } else {
682 upgrade_mode = DomainState::MODE_FORCE_HTTPS;
685 AddHSTSInternal(host, upgrade_mode, now + max_age, include_subdomains);
686 return true;
689 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
690 const std::string& value,
691 const SSLInfo& ssl_info) {
692 DCHECK(CalledOnValidThread());
694 base::Time now = base::Time::Now();
695 base::TimeDelta max_age;
696 bool include_subdomains;
697 HashValueVector spki_hashes;
698 if (!ParseHPKPHeader(value, ssl_info.public_key_hashes, &max_age,
699 &include_subdomains, &spki_hashes)) {
700 return false;
702 // Handle max-age == 0.
703 if (max_age.InSeconds() == 0)
704 spki_hashes.clear();
705 AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes);
706 return true;
709 void TransportSecurityState::AddHSTS(const std::string& host,
710 const base::Time& expiry,
711 bool include_subdomains) {
712 DCHECK(CalledOnValidThread());
713 AddHSTSInternal(host, DomainState::MODE_FORCE_HTTPS, expiry,
714 include_subdomains);
717 void TransportSecurityState::AddHPKP(const std::string& host,
718 const base::Time& expiry,
719 bool include_subdomains,
720 const HashValueVector& hashes) {
721 DCHECK(CalledOnValidThread());
722 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes);
725 // static
726 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) {
727 PreloadResult result;
728 return DecodeHSTSPreload(host, &result) && result.has_pins &&
729 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts;
732 // static
733 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
734 PreloadResult result;
735 if (!DecodeHSTSPreload(host, &result) ||
736 !result.has_pins) {
737 return;
740 DCHECK(result.domain_id != DOMAIN_NOT_PINNED);
742 UMA_HISTOGRAM_SPARSE_SLOWLY(
743 "Net.PublicKeyPinFailureDomain", result.domain_id);
746 // static
747 bool TransportSecurityState::IsBuildTimely() {
748 // If the build metadata aren't embedded in the binary then we can't use the
749 // build time to determine if the build is timely, return true by default. If
750 // we're building an official build then keep using the build time, even if
751 // it's invalid it'd be a date in the past and this function will return
752 // false.
753 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
754 return true;
755 #else
756 const base::Time build_time = base::GetBuildTime();
757 // We consider built-in information to be timely for 10 weeks.
758 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
759 #endif
762 bool TransportSecurityState::CheckPublicKeyPinsImpl(
763 const std::string& host,
764 const HashValueVector& hashes,
765 std::string* failure_log) {
766 DomainState dynamic_state;
767 if (GetDynamicDomainState(host, &dynamic_state))
768 return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
770 DomainState static_state;
771 if (GetStaticDomainState(host, &static_state))
772 return static_state.CheckPublicKeyPins(hashes, failure_log);
774 // HasPublicKeyPins should have returned true in order for this method
775 // to have been called, so if we fall through to here, it's an error.
776 return false;
779 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
780 DomainState* out) const {
781 DCHECK(CalledOnValidThread());
783 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
784 out->sts.include_subdomains = false;
785 out->pkp.include_subdomains = false;
787 if (!IsBuildTimely())
788 return false;
790 PreloadResult result;
791 if (!DecodeHSTSPreload(host, &result))
792 return false;
794 out->sts.domain = host.substr(result.hostname_offset);
795 out->pkp.domain = out->sts.domain;
796 out->sts.include_subdomains = result.sts_include_subdomains;
797 out->sts.last_observed = base::GetBuildTime();
798 out->sts.upgrade_mode =
799 TransportSecurityState::DomainState::MODE_DEFAULT;
800 if (result.force_https) {
801 out->sts.upgrade_mode =
802 TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
805 if (enable_static_pins_ && result.has_pins) {
806 out->pkp.include_subdomains = result.pkp_include_subdomains;
807 out->pkp.last_observed = base::GetBuildTime();
809 if (result.pinset_id >= arraysize(kPinsets))
810 return false;
811 const Pinset *pinset = &kPinsets[result.pinset_id];
813 if (pinset->accepted_pins) {
814 const char* const* sha1_hash = pinset->accepted_pins;
815 while (*sha1_hash) {
816 AddHash(*sha1_hash, &out->pkp.spki_hashes);
817 sha1_hash++;
820 if (pinset->rejected_pins) {
821 const char* const* sha1_hash = pinset->rejected_pins;
822 while (*sha1_hash) {
823 AddHash(*sha1_hash, &out->pkp.bad_spki_hashes);
824 sha1_hash++;
829 return true;
832 bool TransportSecurityState::GetDynamicDomainState(const std::string& host,
833 DomainState* result) {
834 DCHECK(CalledOnValidThread());
836 DomainState state;
837 const std::string canonicalized_host = CanonicalizeHost(host);
838 if (canonicalized_host.empty())
839 return false;
841 base::Time current_time(base::Time::Now());
843 // Although STS and PKP states are completely independent, they are currently
844 // stored and processed together. This loop performs both independent queries
845 // together and combines the two results into a single output. See
846 // https://crbug.com/470295
847 bool found_sts = false;
848 bool found_pkp = false;
849 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
850 std::string host_sub_chunk(&canonicalized_host[i],
851 canonicalized_host.size() - i);
852 DomainStateMap::iterator j =
853 enabled_hosts_.find(HashHost(host_sub_chunk));
854 if (j == enabled_hosts_.end())
855 continue;
857 // If both halves of the entry are invalid, drop it.
858 if (current_time > j->second.sts.expiry &&
859 current_time > j->second.pkp.expiry) {
860 enabled_hosts_.erase(j);
861 DirtyNotify();
862 continue;
865 // If this is the most specific STS match, add it to the result. Note: a STS
866 // entry at a more specific domain overrides a less specific domain whether
867 // or not |include_subdomains| is set.
868 if (!found_sts && current_time <= j->second.sts.expiry &&
869 j->second.ShouldUpgradeToSSL()) {
870 found_sts = true;
871 if (i == 0 || j->second.sts.include_subdomains) {
872 state.sts = j->second.sts;
873 state.sts.domain = DNSDomainToString(host_sub_chunk);
877 // If this is the most specific PKP match, add it to the result. Note: a PKP
878 // entry at a more specific domain overrides a less specific domain whether
879 // or not |include_subdomains| is set.
880 if (!found_pkp && current_time <= j->second.pkp.expiry &&
881 j->second.HasPublicKeyPins()) {
882 found_pkp = true;
883 if (i == 0 || j->second.pkp.include_subdomains) {
884 state.pkp = j->second.pkp;
885 state.pkp.domain = DNSDomainToString(host_sub_chunk);
889 // Both queries have terminated. Abort the loop early.
890 if (found_sts && found_pkp)
891 break;
894 // If neither STS nor PKP state was found, do not return any DomainState. This
895 // determines whether ShouldSSLErrorsBeFatal returns true or false.
896 if (!state.ShouldUpgradeToSSL() && !state.HasPublicKeyPins())
897 return false;
899 *result = state;
900 return true;
903 void TransportSecurityState::AddOrUpdateEnabledHosts(
904 const std::string& hashed_host, const DomainState& state) {
905 DCHECK(CalledOnValidThread());
906 enabled_hosts_[hashed_host] = state;
909 TransportSecurityState::DomainState::DomainState() {
910 sts.upgrade_mode = MODE_DEFAULT;
911 sts.include_subdomains = false;
912 pkp.include_subdomains = false;
915 TransportSecurityState::DomainState::~DomainState() {
918 bool TransportSecurityState::DomainState::CheckPublicKeyPins(
919 const HashValueVector& hashes, std::string* failure_log) const {
920 // Validate that hashes is not empty. By the time this code is called (in
921 // production), that should never happen, but it's good to be defensive.
922 // And, hashes *can* be empty in some test scenarios.
923 if (hashes.empty()) {
924 failure_log->append(
925 "Rejecting empty public key chain for public-key-pinned domains: " +
926 pkp.domain);
927 return false;
930 if (HashesIntersect(pkp.bad_spki_hashes, hashes)) {
931 failure_log->append("Rejecting public key chain for domain " + pkp.domain +
932 ". Validated chain: " + HashesToBase64String(hashes) +
933 ", matches one or more bad hashes: " +
934 HashesToBase64String(pkp.bad_spki_hashes));
935 return false;
938 // If there are no pins, then any valid chain is acceptable.
939 if (pkp.spki_hashes.empty())
940 return true;
942 if (HashesIntersect(pkp.spki_hashes, hashes)) {
943 return true;
946 failure_log->append("Rejecting public key chain for domain " + pkp.domain +
947 ". Validated chain: " + HashesToBase64String(hashes) +
948 ", expected: " + HashesToBase64String(pkp.spki_hashes));
949 return false;
952 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
953 return sts.upgrade_mode == MODE_FORCE_HTTPS;
956 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
957 // Both HSTS and HPKP cause fatal SSL errors, so enable this on the presense
958 // of either. (If neither is active, no DomainState will be returned from
959 // GetDynamicDomainState.)
960 return true;
963 bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
964 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0;
967 TransportSecurityState::DomainState::STSState::STSState() {
970 TransportSecurityState::DomainState::STSState::~STSState() {
973 TransportSecurityState::DomainState::PKPState::PKPState() {
976 TransportSecurityState::DomainState::PKPState::~PKPState() {
979 } // namespace