Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / net / http / transport_security_state.cc
blob724235b8f13102506b41dcd9c2eaff42ac7d3650
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/json/json_writer.h"
23 #include "base/logging.h"
24 #include "base/memory/scoped_ptr.h"
25 #include "base/metrics/histogram_macros.h"
26 #include "base/metrics/sparse_histogram.h"
27 #include "base/sha1.h"
28 #include "base/strings/string_number_conversions.h"
29 #include "base/strings/string_util.h"
30 #include "base/strings/stringprintf.h"
31 #include "base/strings/utf_string_conversions.h"
32 #include "base/time/time.h"
33 #include "base/values.h"
34 #include "crypto/sha2.h"
35 #include "net/base/dns_util.h"
36 #include "net/base/host_port_pair.h"
37 #include "net/cert/x509_cert_types.h"
38 #include "net/cert/x509_certificate.h"
39 #include "net/http/http_security_headers.h"
40 #include "net/ssl/ssl_info.h"
41 #include "url/gurl.h"
43 #if defined(USE_OPENSSL)
44 #include "crypto/openssl_util.h"
45 #endif
47 namespace net {
49 namespace {
51 #include "net/http/transport_security_state_static.h"
53 std::string TimeToISO8601(const base::Time& t) {
54 base::Time::Exploded exploded;
55 t.UTCExplode(&exploded);
56 return base::StringPrintf(
57 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month,
58 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second,
59 exploded.millisecond);
62 scoped_ptr<base::ListValue> GetPEMEncodedChainAsList(
63 const net::X509Certificate* cert_chain) {
64 if (!cert_chain)
65 return make_scoped_ptr(new base::ListValue());
67 scoped_ptr<base::ListValue> result(new base::ListValue());
68 std::vector<std::string> pem_encoded_chain;
69 cert_chain->GetPEMEncodedChain(&pem_encoded_chain);
70 for (const std::string& cert : pem_encoded_chain)
71 result->Append(make_scoped_ptr(new base::StringValue(cert)));
73 return result.Pass();
76 bool GetHPKPReport(const HostPortPair& host_port_pair,
77 const TransportSecurityState::PKPState& pkp_state,
78 const X509Certificate* served_certificate_chain,
79 const X509Certificate* validated_certificate_chain,
80 std::string* serialized_report) {
81 // TODO(estark): keep track of reports already sent and rate-limit,
82 // break loops
83 if (pkp_state.report_uri.is_empty())
84 return false;
86 base::DictionaryValue report;
87 base::Time now = base::Time::Now();
88 report.SetString("date-time", TimeToISO8601(now));
89 report.SetString("hostname", host_port_pair.host());
90 report.SetInteger("port", host_port_pair.port());
91 report.SetString("effective-expiration-date",
92 TimeToISO8601(pkp_state.expiry));
93 report.SetBoolean("include-subdomains", pkp_state.include_subdomains);
94 report.SetString("noted-hostname", pkp_state.domain);
96 scoped_ptr<base::ListValue> served_certificate_chain_list =
97 GetPEMEncodedChainAsList(served_certificate_chain);
98 scoped_ptr<base::ListValue> validated_certificate_chain_list =
99 GetPEMEncodedChainAsList(validated_certificate_chain);
100 report.Set("served-certificate-chain", served_certificate_chain_list.Pass());
101 report.Set("validated-certificate-chain",
102 validated_certificate_chain_list.Pass());
104 scoped_ptr<base::ListValue> known_pin_list(new base::ListValue());
105 for (const auto& hash_value : pkp_state.spki_hashes) {
106 std::string known_pin;
108 switch (hash_value.tag) {
109 case HASH_VALUE_SHA1:
110 known_pin += "pin-sha1=";
111 break;
112 case HASH_VALUE_SHA256:
113 known_pin += "pin-sha256=";
114 break;
117 std::string base64_value;
118 base::Base64Encode(
119 base::StringPiece(reinterpret_cast<const char*>(hash_value.data()),
120 hash_value.size()),
121 &base64_value);
122 known_pin += "\"" + base64_value + "\"";
124 known_pin_list->Append(
125 scoped_ptr<base::Value>(new base::StringValue(known_pin)));
128 report.Set("known-pins", known_pin_list.Pass());
130 if (!base::JSONWriter::Write(report, serialized_report)) {
131 LOG(ERROR) << "Failed to serialize HPKP violation report.";
132 return false;
135 return true;
138 bool CheckPinsAndMaybeSendReport(
139 const HostPortPair& host_port_pair,
140 const TransportSecurityState::PKPState& pkp_state,
141 const HashValueVector& hashes,
142 const X509Certificate* served_certificate_chain,
143 const X509Certificate* validated_certificate_chain,
144 const TransportSecurityState::PublicKeyPinReportStatus report_status,
145 TransportSecurityState::ReportSender* report_sender,
146 std::string* failure_log) {
147 if (pkp_state.CheckPublicKeyPins(hashes, failure_log))
148 return true;
150 if (!report_sender ||
151 report_status != TransportSecurityState::ENABLE_PIN_REPORTS ||
152 pkp_state.report_uri.is_empty()) {
153 return false;
156 DCHECK(pkp_state.report_uri.is_valid());
158 std::string serialized_report;
160 if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain,
161 validated_certificate_chain, &serialized_report)) {
162 return false;
165 report_sender->Send(pkp_state.report_uri, serialized_report);
167 return false;
170 std::string HashesToBase64String(const HashValueVector& hashes) {
171 std::string str;
172 for (size_t i = 0; i != hashes.size(); ++i) {
173 if (i != 0)
174 str += ",";
175 str += hashes[i].ToString();
177 return str;
180 std::string HashHost(const std::string& canonicalized_host) {
181 char hashed[crypto::kSHA256Length];
182 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
183 return std::string(hashed, sizeof(hashed));
186 // Returns true if the intersection of |a| and |b| is not empty. If either
187 // |a| or |b| is empty, returns false.
188 bool HashesIntersect(const HashValueVector& a,
189 const HashValueVector& b) {
190 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
191 HashValueVector::const_iterator j =
192 std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
193 if (j != b.end())
194 return true;
196 return false;
199 bool AddHash(const char* sha1_hash,
200 HashValueVector* out) {
201 HashValue hash(HASH_VALUE_SHA1);
202 memcpy(hash.data(), sha1_hash, hash.size());
203 out->push_back(hash);
204 return true;
207 // Converts |hostname| from dotted form ("www.google.com") to the form
208 // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns
209 // the result.
210 std::string CanonicalizeHost(const std::string& host) {
211 // We cannot perform the operations as detailed in the spec here as |host|
212 // has already undergone IDN processing before it reached us. Thus, we check
213 // that there are no invalid characters in the host and lowercase the result.
214 std::string new_host;
215 if (!DNSDomainFromDot(host, &new_host)) {
216 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
217 // name is >255 bytes. However, search terms can have those properties.
218 return std::string();
221 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
222 const unsigned label_length = static_cast<unsigned>(new_host[i]);
223 if (!label_length)
224 break;
226 for (size_t j = 0; j < label_length; ++j) {
227 new_host[i + 1 + j] = static_cast<char>(tolower(new_host[i + 1 + j]));
231 return new_host;
234 // BitReader is a class that allows a bytestring to be read bit-by-bit.
235 class BitReader {
236 public:
237 BitReader(const uint8* bytes, size_t num_bits)
238 : bytes_(bytes),
239 num_bits_(num_bits),
240 num_bytes_((num_bits + 7) / 8),
241 current_byte_index_(0),
242 num_bits_used_(8) {}
244 // Next sets |*out| to the next bit from the input. It returns false if no
245 // more bits are available or true otherwise.
246 bool Next(bool* out) {
247 if (num_bits_used_ == 8) {
248 if (current_byte_index_ >= num_bytes_) {
249 return false;
251 current_byte_ = bytes_[current_byte_index_++];
252 num_bits_used_ = 0;
255 *out = 1 & (current_byte_ >> (7 - num_bits_used_));
256 num_bits_used_++;
257 return true;
260 // Read sets the |num_bits| least-significant bits of |*out| to the value of
261 // the next |num_bits| bits from the input. It returns false if there are
262 // insufficient bits in the input or true otherwise.
263 bool Read(unsigned num_bits, uint32* out) {
264 DCHECK_LE(num_bits, 32u);
266 uint32 ret = 0;
267 for (unsigned i = 0; i < num_bits; ++i) {
268 bool bit;
269 if (!Next(&bit)) {
270 return false;
272 ret |= static_cast<uint32>(bit) << (num_bits - 1 - i);
275 *out = ret;
276 return true;
279 // Unary sets |*out| to the result of decoding a unary value from the input.
280 // It returns false if there were insufficient bits in the input and true
281 // otherwise.
282 bool Unary(size_t* out) {
283 size_t ret = 0;
285 for (;;) {
286 bool bit;
287 if (!Next(&bit)) {
288 return false;
290 if (!bit) {
291 break;
293 ret++;
296 *out = ret;
297 return true;
300 // Seek sets the current offest in the input to bit number |offset|. It
301 // returns true if |offset| is within the range of the input and false
302 // otherwise.
303 bool Seek(size_t offset) {
304 if (offset >= num_bits_) {
305 return false;
307 current_byte_index_ = offset / 8;
308 current_byte_ = bytes_[current_byte_index_++];
309 num_bits_used_ = offset % 8;
310 return true;
313 private:
314 const uint8* const bytes_;
315 const size_t num_bits_;
316 const size_t num_bytes_;
317 // current_byte_index_ contains the current byte offset in |bytes_|.
318 size_t current_byte_index_;
319 // current_byte_ contains the current byte of the input.
320 uint8 current_byte_;
321 // num_bits_used_ contains the number of bits of |current_byte_| that have
322 // been read.
323 unsigned num_bits_used_;
326 // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
327 // simply encoded as a series of two-byte structures. The first byte determines
328 // the "0" pointer for that node and the second the "1" pointer. Each byte
329 // either has the MSB set, in which case the bottom 7 bits are the value for
330 // that position, or else the bottom seven bits contain the index of a node.
332 // The tree is decoded by walking rather than a table-driven approach.
333 class HuffmanDecoder {
334 public:
335 HuffmanDecoder(const uint8* tree, size_t tree_bytes)
336 : tree_(tree), tree_bytes_(tree_bytes) {}
338 bool Decode(BitReader* reader, char* out) {
339 const uint8* current = &tree_[tree_bytes_ - 2];
341 for (;;) {
342 bool bit;
343 if (!reader->Next(&bit)) {
344 return false;
347 uint8 b = current[bit];
348 if (b & 0x80) {
349 *out = static_cast<char>(b & 0x7f);
350 return true;
353 unsigned offset = static_cast<unsigned>(b) * 2;
354 DCHECK_LT(offset, tree_bytes_);
355 if (offset >= tree_bytes_) {
356 return false;
359 current = &tree_[offset];
363 private:
364 const uint8* const tree_;
365 const size_t tree_bytes_;
368 // PreloadResult is the result of resolving a specific name in the preloaded
369 // data.
370 struct PreloadResult {
371 uint32 pinset_id;
372 uint32 domain_id;
373 // hostname_offset contains the number of bytes from the start of the given
374 // hostname where the name of the matching entry starts.
375 size_t hostname_offset;
376 bool sts_include_subdomains;
377 bool pkp_include_subdomains;
378 bool force_https;
379 bool has_pins;
382 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns
383 // false on internal error and true otherwise. After a successful return,
384 // |*out_found| is true iff a relevant entry has been found. If so, |*out|
385 // contains the details.
387 // Don't call this function, call DecodeHSTSPreload, below.
389 // Although this code should be robust, it never processes attacker-controlled
390 // data -- it only operates on the preloaded data built into the binary.
392 // The preloaded data is represented as a trie and matches the hostname
393 // backwards. Each node in the trie starts with a number of characters, which
394 // must match exactly. After that is a dispatch table which maps the next
395 // character in the hostname to another node in the trie.
397 // In the dispatch table, the zero character represents the "end of string"
398 // (which is the *beginning* of a hostname since we process it backwards). The
399 // value in that case is special -- rather than an offset to another trie node,
400 // it contains the HSTS information: whether subdomains are included, pinsets
401 // etc. If an "end of string" matches a period in the hostname then the
402 // information is remembered because, if no more specific node is found, then
403 // that information applies to the hostname.
405 // Dispatch tables are always given in order, but the "end of string" (zero)
406 // value always comes before an entry for '.'.
407 bool DecodeHSTSPreloadRaw(const std::string& search_hostname,
408 bool* out_found,
409 PreloadResult* out) {
410 HuffmanDecoder huffman(kHSTSHuffmanTree, sizeof(kHSTSHuffmanTree));
411 BitReader reader(kPreloadedHSTSData, kPreloadedHSTSBits);
412 size_t bit_offset = kHSTSRootPosition;
413 static const char kEndOfString = 0;
414 static const char kEndOfTable = 127;
416 *out_found = false;
418 // Ensure that |search_hostname| is a valid hostname before
419 // processing.
420 if (CanonicalizeHost(search_hostname).empty()) {
421 return true;
424 // Normalize any trailing '.' used for DNS suffix searches.
425 std::string hostname = search_hostname;
426 size_t found = hostname.find_last_not_of('.');
427 if (found != std::string::npos) {
428 hostname.erase(found + 1);
429 } else {
430 hostname.clear();
433 // |hostname| has already undergone IDN conversion, so should be
434 // entirely A-Labels. The preload data is entirely normalized to
435 // lower case.
436 hostname = base::ToLowerASCII(hostname);
437 if (hostname.empty()) {
438 return true;
441 // hostname_offset contains one more than the index of the current character
442 // in the hostname that is being considered. It's one greater so that we can
443 // represent the position just before the beginning (with zero).
444 size_t hostname_offset = hostname.size();
446 for (;;) {
447 // Seek to the desired location.
448 if (!reader.Seek(bit_offset)) {
449 return false;
452 // Decode the unary length of the common prefix.
453 size_t prefix_length;
454 if (!reader.Unary(&prefix_length)) {
455 return false;
458 // Match each character in the prefix.
459 for (size_t i = 0; i < prefix_length; ++i) {
460 if (hostname_offset == 0) {
461 // We can't match the terminator with a prefix string.
462 return true;
465 char c;
466 if (!huffman.Decode(&reader, &c)) {
467 return false;
469 if (hostname[hostname_offset - 1] != c) {
470 return true;
472 hostname_offset--;
475 bool is_first_offset = true;
476 size_t current_offset = 0;
478 // Next is the dispatch table.
479 for (;;) {
480 char c;
481 if (!huffman.Decode(&reader, &c)) {
482 return false;
484 if (c == kEndOfTable) {
485 // No exact match.
486 return true;
489 if (c == kEndOfString) {
490 PreloadResult tmp;
491 if (!reader.Next(&tmp.sts_include_subdomains) ||
492 !reader.Next(&tmp.force_https) || !reader.Next(&tmp.has_pins)) {
493 return false;
496 tmp.pkp_include_subdomains = tmp.sts_include_subdomains;
498 if (tmp.has_pins) {
499 if (!reader.Read(4, &tmp.pinset_id) ||
500 !reader.Read(9, &tmp.domain_id) ||
501 (!tmp.sts_include_subdomains &&
502 !reader.Next(&tmp.pkp_include_subdomains))) {
503 return false;
507 tmp.hostname_offset = hostname_offset;
509 if (hostname_offset == 0 || hostname[hostname_offset - 1] == '.') {
510 *out_found = tmp.sts_include_subdomains || tmp.pkp_include_subdomains;
511 *out = tmp;
513 if (hostname_offset > 0) {
514 out->force_https &= tmp.sts_include_subdomains;
515 } else {
516 *out_found = true;
517 return true;
521 continue;
524 // The entries in a dispatch table are in order thus we can tell if there
525 // will be no match if the current character past the one that we want.
526 if (hostname_offset == 0 || hostname[hostname_offset - 1] < c) {
527 return true;
530 if (is_first_offset) {
531 // The first offset is backwards from the current position.
532 uint32 jump_delta_bits;
533 uint32 jump_delta;
534 if (!reader.Read(5, &jump_delta_bits) ||
535 !reader.Read(jump_delta_bits, &jump_delta)) {
536 return false;
539 if (bit_offset < jump_delta) {
540 return false;
543 current_offset = bit_offset - jump_delta;
544 is_first_offset = false;
545 } else {
546 // Subsequent offsets are forward from the target of the first offset.
547 uint32 is_long_jump;
548 if (!reader.Read(1, &is_long_jump)) {
549 return false;
552 uint32 jump_delta;
553 if (!is_long_jump) {
554 if (!reader.Read(7, &jump_delta)) {
555 return false;
557 } else {
558 uint32 jump_delta_bits;
559 if (!reader.Read(4, &jump_delta_bits) ||
560 !reader.Read(jump_delta_bits + 8, &jump_delta)) {
561 return false;
565 current_offset += jump_delta;
566 if (current_offset >= bit_offset) {
567 return false;
571 DCHECK_LT(0u, hostname_offset);
572 if (hostname[hostname_offset - 1] == c) {
573 bit_offset = current_offset;
574 hostname_offset--;
575 break;
581 bool DecodeHSTSPreload(const std::string& hostname, PreloadResult* out) {
582 bool found;
583 if (!DecodeHSTSPreloadRaw(hostname, &found, out)) {
584 DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
585 << hostname;
586 return false;
589 return found;
592 } // namespace
594 TransportSecurityState::TransportSecurityState()
595 : delegate_(nullptr), report_sender_(nullptr), enable_static_pins_(true) {
596 // Static pinning is only enabled for official builds to make sure that
597 // others don't end up with pins that cannot be easily updated.
598 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
599 enable_static_pins_ = false;
600 #endif
601 DCHECK(CalledOnValidThread());
604 // Both HSTS and HPKP cause fatal SSL errors, so return true if a
605 // host has either.
606 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host) {
607 STSState sts_state;
608 PKPState pkp_state;
609 if (GetStaticDomainState(host, &sts_state, &pkp_state))
610 return true;
611 if (GetDynamicSTSState(host, &sts_state))
612 return true;
613 return GetDynamicPKPState(host, &pkp_state);
616 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host) {
617 STSState dynamic_sts_state;
618 if (GetDynamicSTSState(host, &dynamic_sts_state))
619 return dynamic_sts_state.ShouldUpgradeToSSL();
621 STSState static_sts_state;
622 PKPState unused;
623 if (GetStaticDomainState(host, &static_sts_state, &unused) &&
624 static_sts_state.ShouldUpgradeToSSL()) {
625 return true;
628 return false;
631 bool TransportSecurityState::CheckPublicKeyPins(
632 const HostPortPair& host_port_pair,
633 bool is_issued_by_known_root,
634 const HashValueVector& public_key_hashes,
635 const X509Certificate* served_certificate_chain,
636 const X509Certificate* validated_certificate_chain,
637 const PublicKeyPinReportStatus report_status,
638 std::string* pinning_failure_log) {
639 // Perform pin validation if, and only if, all these conditions obtain:
641 // * the server's certificate chain chains up to a known root (i.e. not a
642 // user-installed trust anchor); and
643 // * the server actually has public key pins.
644 if (!is_issued_by_known_root || !HasPublicKeyPins(host_port_pair.host())) {
645 return true;
648 bool pins_are_valid = CheckPublicKeyPinsImpl(
649 host_port_pair, public_key_hashes, served_certificate_chain,
650 validated_certificate_chain, report_status, pinning_failure_log);
651 if (!pins_are_valid) {
652 LOG(ERROR) << *pinning_failure_log;
653 ReportUMAOnPinFailure(host_port_pair.host());
656 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
657 return pins_are_valid;
660 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
661 PKPState dynamic_state;
662 if (GetDynamicPKPState(host, &dynamic_state))
663 return dynamic_state.HasPublicKeyPins();
665 STSState unused;
666 PKPState static_pkp_state;
667 if (GetStaticDomainState(host, &unused, &static_pkp_state)) {
668 if (static_pkp_state.HasPublicKeyPins())
669 return true;
672 return false;
675 void TransportSecurityState::SetDelegate(
676 TransportSecurityState::Delegate* delegate) {
677 DCHECK(CalledOnValidThread());
678 delegate_ = delegate;
681 void TransportSecurityState::SetReportSender(
682 TransportSecurityState::ReportSender* report_sender) {
683 DCHECK(CalledOnValidThread());
684 report_sender_ = report_sender;
687 void TransportSecurityState::AddHSTSInternal(
688 const std::string& host,
689 TransportSecurityState::STSState::UpgradeMode upgrade_mode,
690 const base::Time& expiry,
691 bool include_subdomains) {
692 DCHECK(CalledOnValidThread());
694 STSState sts_state;
695 sts_state.last_observed = base::Time::Now();
696 sts_state.include_subdomains = include_subdomains;
697 sts_state.expiry = expiry;
698 sts_state.upgrade_mode = upgrade_mode;
700 EnableSTSHost(host, sts_state);
703 void TransportSecurityState::AddHPKPInternal(const std::string& host,
704 const base::Time& last_observed,
705 const base::Time& expiry,
706 bool include_subdomains,
707 const HashValueVector& hashes,
708 const GURL& report_uri) {
709 DCHECK(CalledOnValidThread());
711 PKPState pkp_state;
712 pkp_state.last_observed = last_observed;
713 pkp_state.expiry = expiry;
714 pkp_state.include_subdomains = include_subdomains;
715 pkp_state.spki_hashes = hashes;
716 pkp_state.report_uri = report_uri;
718 EnablePKPHost(host, pkp_state);
721 void TransportSecurityState::EnableSTSHost(const std::string& host,
722 const STSState& state) {
723 DCHECK(CalledOnValidThread());
725 const std::string canonicalized_host = CanonicalizeHost(host);
726 if (canonicalized_host.empty())
727 return;
729 // Only store new state when HSTS is explicitly enabled. If it is
730 // disabled, remove the state from the enabled hosts.
731 if (state.ShouldUpgradeToSSL()) {
732 STSState sts_state(state);
733 // No need to store this value since it is redundant. (|canonicalized_host|
734 // is the map key.)
735 sts_state.domain.clear();
737 enabled_sts_hosts_[HashHost(canonicalized_host)] = sts_state;
738 } else {
739 const std::string hashed_host = HashHost(canonicalized_host);
740 enabled_sts_hosts_.erase(hashed_host);
743 DirtyNotify();
746 void TransportSecurityState::EnablePKPHost(const std::string& host,
747 const PKPState& state) {
748 DCHECK(CalledOnValidThread());
750 const std::string canonicalized_host = CanonicalizeHost(host);
751 if (canonicalized_host.empty())
752 return;
754 // Only store new state when HPKP is explicitly enabled. If it is
755 // disabled, remove the state from the enabled hosts.
756 if (state.HasPublicKeyPins()) {
757 PKPState pkp_state(state);
758 // No need to store this value since it is redundant. (|canonicalized_host|
759 // is the map key.)
760 pkp_state.domain.clear();
762 enabled_pkp_hosts_[HashHost(canonicalized_host)] = pkp_state;
763 } else {
764 const std::string hashed_host = HashHost(canonicalized_host);
765 enabled_pkp_hosts_.erase(hashed_host);
768 DirtyNotify();
771 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
772 DCHECK(CalledOnValidThread());
774 const std::string canonicalized_host = CanonicalizeHost(host);
775 if (canonicalized_host.empty())
776 return false;
778 const std::string hashed_host = HashHost(canonicalized_host);
779 bool deleted = false;
780 STSStateMap::iterator sts_interator = enabled_sts_hosts_.find(hashed_host);
781 if (sts_interator != enabled_sts_hosts_.end()) {
782 enabled_sts_hosts_.erase(sts_interator);
783 deleted = true;
786 PKPStateMap::iterator pkp_iterator = enabled_pkp_hosts_.find(hashed_host);
787 if (pkp_iterator != enabled_pkp_hosts_.end()) {
788 enabled_pkp_hosts_.erase(pkp_iterator);
789 deleted = true;
792 if (deleted)
793 DirtyNotify();
794 return deleted;
797 void TransportSecurityState::ClearDynamicData() {
798 DCHECK(CalledOnValidThread());
799 enabled_sts_hosts_.clear();
800 enabled_pkp_hosts_.clear();
803 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
804 DCHECK(CalledOnValidThread());
806 bool dirtied = false;
807 STSStateMap::iterator sts_iterator = enabled_sts_hosts_.begin();
808 while (sts_iterator != enabled_sts_hosts_.end()) {
809 if (sts_iterator->second.last_observed >= time) {
810 dirtied = true;
811 enabled_sts_hosts_.erase(sts_iterator++);
812 continue;
815 ++sts_iterator;
818 PKPStateMap::iterator pkp_iterator = enabled_pkp_hosts_.begin();
819 while (pkp_iterator != enabled_pkp_hosts_.end()) {
820 if (pkp_iterator->second.last_observed >= time) {
821 dirtied = true;
822 enabled_pkp_hosts_.erase(pkp_iterator++);
823 continue;
826 ++pkp_iterator;
829 if (dirtied)
830 DirtyNotify();
833 TransportSecurityState::~TransportSecurityState() {
834 DCHECK(CalledOnValidThread());
837 void TransportSecurityState::DirtyNotify() {
838 DCHECK(CalledOnValidThread());
840 if (delegate_)
841 delegate_->StateIsDirty(this);
844 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
845 const std::string& value) {
846 DCHECK(CalledOnValidThread());
848 base::Time now = base::Time::Now();
849 base::TimeDelta max_age;
850 bool include_subdomains;
851 if (!ParseHSTSHeader(value, &max_age, &include_subdomains)) {
852 return false;
855 // Handle max-age == 0.
856 STSState::UpgradeMode upgrade_mode;
857 if (max_age.InSeconds() == 0) {
858 upgrade_mode = STSState::MODE_DEFAULT;
859 } else {
860 upgrade_mode = STSState::MODE_FORCE_HTTPS;
863 AddHSTSInternal(host, upgrade_mode, now + max_age, include_subdomains);
864 return true;
867 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
868 const std::string& value,
869 const SSLInfo& ssl_info) {
870 DCHECK(CalledOnValidThread());
872 base::Time now = base::Time::Now();
873 base::TimeDelta max_age;
874 bool include_subdomains;
875 HashValueVector spki_hashes;
876 GURL report_uri;
878 if (!ParseHPKPHeader(value, ssl_info.public_key_hashes, &max_age,
879 &include_subdomains, &spki_hashes, &report_uri)) {
880 return false;
882 // Handle max-age == 0.
883 if (max_age.InSeconds() == 0)
884 spki_hashes.clear();
885 AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes,
886 report_uri);
887 return true;
890 void TransportSecurityState::AddHSTS(const std::string& host,
891 const base::Time& expiry,
892 bool include_subdomains) {
893 DCHECK(CalledOnValidThread());
894 AddHSTSInternal(host, STSState::MODE_FORCE_HTTPS, expiry, include_subdomains);
897 void TransportSecurityState::AddHPKP(const std::string& host,
898 const base::Time& expiry,
899 bool include_subdomains,
900 const HashValueVector& hashes,
901 const GURL& report_uri) {
902 DCHECK(CalledOnValidThread());
903 AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes,
904 report_uri);
907 bool TransportSecurityState::ProcessHPKPReportOnlyHeader(
908 const std::string& value,
909 const HostPortPair& host_port_pair,
910 const SSLInfo& ssl_info) {
911 DCHECK(CalledOnValidThread());
913 base::Time now = base::Time::Now();
914 bool include_subdomains;
915 HashValueVector spki_hashes;
916 GURL report_uri;
917 std::string unused_failure_log;
919 if (!ParseHPKPReportOnlyHeader(value, &include_subdomains, &spki_hashes,
920 &report_uri) ||
921 !report_uri.is_valid() || report_uri.is_empty())
922 return false;
924 PKPState pkp_state;
925 pkp_state.last_observed = now;
926 pkp_state.expiry = now;
927 pkp_state.include_subdomains = include_subdomains;
928 pkp_state.spki_hashes = spki_hashes;
929 pkp_state.report_uri = report_uri;
930 pkp_state.domain = DNSDomainToString(CanonicalizeHost(host_port_pair.host()));
932 // Only perform pin validation if the cert chains up to a known root.
933 if (!ssl_info.is_issued_by_known_root)
934 return true;
936 CheckPinsAndMaybeSendReport(
937 host_port_pair, pkp_state, ssl_info.public_key_hashes,
938 ssl_info.unverified_cert.get(), ssl_info.cert.get(), ENABLE_PIN_REPORTS,
939 report_sender_, &unused_failure_log);
940 return true;
943 // static
944 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host) {
945 PreloadResult result;
946 return DecodeHSTSPreload(host, &result) && result.has_pins &&
947 kPinsets[result.pinset_id].accepted_pins == kGoogleAcceptableCerts;
950 // static
951 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
952 PreloadResult result;
953 if (!DecodeHSTSPreload(host, &result) ||
954 !result.has_pins) {
955 return;
958 DCHECK(result.domain_id != DOMAIN_NOT_PINNED);
960 UMA_HISTOGRAM_SPARSE_SLOWLY(
961 "Net.PublicKeyPinFailureDomain", result.domain_id);
964 // static
965 bool TransportSecurityState::IsBuildTimely() {
966 // If the build metadata aren't embedded in the binary then we can't use the
967 // build time to determine if the build is timely, return true by default. If
968 // we're building an official build then keep using the build time, even if
969 // it's invalid it'd be a date in the past and this function will return
970 // false.
971 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
972 return true;
973 #else
974 const base::Time build_time = base::GetBuildTime();
975 // We consider built-in information to be timely for 10 weeks.
976 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
977 #endif
980 bool TransportSecurityState::CheckPublicKeyPinsImpl(
981 const HostPortPair& host_port_pair,
982 const HashValueVector& hashes,
983 const X509Certificate* served_certificate_chain,
984 const X509Certificate* validated_certificate_chain,
985 const PublicKeyPinReportStatus report_status,
986 std::string* failure_log) {
987 PKPState pkp_state;
988 STSState unused;
990 if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) &&
991 !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) {
992 // HasPublicKeyPins should have returned true in order for this method
993 // to have been called, so if we fall through to here, it's an error.
994 return false;
997 return CheckPinsAndMaybeSendReport(
998 host_port_pair, pkp_state, hashes, served_certificate_chain,
999 validated_certificate_chain, report_status, report_sender_, failure_log);
1002 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
1003 STSState* sts_state,
1004 PKPState* pkp_state) const {
1005 DCHECK(CalledOnValidThread());
1007 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
1008 sts_state->include_subdomains = false;
1009 pkp_state->include_subdomains = false;
1011 if (!IsBuildTimely())
1012 return false;
1014 PreloadResult result;
1015 if (!DecodeHSTSPreload(host, &result))
1016 return false;
1018 sts_state->domain = host.substr(result.hostname_offset);
1019 pkp_state->domain = sts_state->domain;
1020 sts_state->include_subdomains = result.sts_include_subdomains;
1021 sts_state->last_observed = base::GetBuildTime();
1022 sts_state->upgrade_mode = STSState::MODE_DEFAULT;
1023 if (result.force_https) {
1024 sts_state->upgrade_mode = STSState::MODE_FORCE_HTTPS;
1027 if (enable_static_pins_ && result.has_pins) {
1028 pkp_state->include_subdomains = result.pkp_include_subdomains;
1029 pkp_state->last_observed = base::GetBuildTime();
1031 if (result.pinset_id >= arraysize(kPinsets))
1032 return false;
1033 const Pinset *pinset = &kPinsets[result.pinset_id];
1035 if (pinset->report_uri != kNoReportURI)
1036 pkp_state->report_uri = GURL(pinset->report_uri);
1038 if (pinset->accepted_pins) {
1039 const char* const* sha1_hash = pinset->accepted_pins;
1040 while (*sha1_hash) {
1041 AddHash(*sha1_hash, &pkp_state->spki_hashes);
1042 sha1_hash++;
1045 if (pinset->rejected_pins) {
1046 const char* const* sha1_hash = pinset->rejected_pins;
1047 while (*sha1_hash) {
1048 AddHash(*sha1_hash, &pkp_state->bad_spki_hashes);
1049 sha1_hash++;
1054 return true;
1057 bool TransportSecurityState::GetDynamicSTSState(const std::string& host,
1058 STSState* result) {
1059 DCHECK(CalledOnValidThread());
1061 const std::string canonicalized_host = CanonicalizeHost(host);
1062 if (canonicalized_host.empty())
1063 return false;
1065 base::Time current_time(base::Time::Now());
1067 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
1068 std::string host_sub_chunk(&canonicalized_host[i],
1069 canonicalized_host.size() - i);
1070 STSStateMap::iterator j = enabled_sts_hosts_.find(HashHost(host_sub_chunk));
1071 if (j == enabled_sts_hosts_.end())
1072 continue;
1074 // If the entry is invalid, drop it.
1075 if (current_time > j->second.expiry) {
1076 enabled_sts_hosts_.erase(j);
1077 DirtyNotify();
1078 continue;
1081 // If this is the most specific STS match, add it to the result. Note: a STS
1082 // entry at a more specific domain overrides a less specific domain whether
1083 // or not |include_subdomains| is set.
1084 if (current_time <= j->second.expiry) {
1085 if (i == 0 || j->second.include_subdomains) {
1086 *result = j->second;
1087 result->domain = DNSDomainToString(host_sub_chunk);
1088 return true;
1091 break;
1095 return false;
1098 bool TransportSecurityState::GetDynamicPKPState(const std::string& host,
1099 PKPState* result) {
1100 DCHECK(CalledOnValidThread());
1102 const std::string canonicalized_host = CanonicalizeHost(host);
1103 if (canonicalized_host.empty())
1104 return false;
1106 base::Time current_time(base::Time::Now());
1108 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
1109 std::string host_sub_chunk(&canonicalized_host[i],
1110 canonicalized_host.size() - i);
1111 PKPStateMap::iterator j = enabled_pkp_hosts_.find(HashHost(host_sub_chunk));
1112 if (j == enabled_pkp_hosts_.end())
1113 continue;
1115 // If the entry is invalid, drop it.
1116 if (current_time > j->second.expiry) {
1117 enabled_pkp_hosts_.erase(j);
1118 DirtyNotify();
1119 continue;
1122 // If this is the most specific PKP match, add it to the result. Note: a PKP
1123 // entry at a more specific domain overrides a less specific domain whether
1124 // or not |include_subdomains| is set.
1125 if (current_time <= j->second.expiry) {
1126 if (i == 0 || j->second.include_subdomains) {
1127 *result = j->second;
1128 result->domain = DNSDomainToString(host_sub_chunk);
1129 return true;
1132 break;
1136 return false;
1139 void TransportSecurityState::AddOrUpdateEnabledSTSHosts(
1140 const std::string& hashed_host,
1141 const STSState& state) {
1142 DCHECK(CalledOnValidThread());
1143 DCHECK(state.ShouldUpgradeToSSL());
1144 enabled_sts_hosts_[hashed_host] = state;
1147 void TransportSecurityState::AddOrUpdateEnabledPKPHosts(
1148 const std::string& hashed_host,
1149 const PKPState& state) {
1150 DCHECK(CalledOnValidThread());
1151 DCHECK(state.HasPublicKeyPins());
1152 enabled_pkp_hosts_[hashed_host] = state;
1155 TransportSecurityState::STSState::STSState()
1156 : upgrade_mode(MODE_DEFAULT), include_subdomains(false) {
1159 TransportSecurityState::STSState::~STSState() {
1162 bool TransportSecurityState::STSState::ShouldUpgradeToSSL() const {
1163 return upgrade_mode == MODE_FORCE_HTTPS;
1166 bool TransportSecurityState::STSState::ShouldSSLErrorsBeFatal() const {
1167 return true;
1170 TransportSecurityState::STSStateIterator::STSStateIterator(
1171 const TransportSecurityState& state)
1172 : iterator_(state.enabled_sts_hosts_.begin()),
1173 end_(state.enabled_sts_hosts_.end()) {
1176 TransportSecurityState::STSStateIterator::~STSStateIterator() {
1179 TransportSecurityState::PKPState::PKPState() : include_subdomains(false) {
1182 TransportSecurityState::PKPState::~PKPState() {
1185 bool TransportSecurityState::PKPState::CheckPublicKeyPins(
1186 const HashValueVector& hashes,
1187 std::string* failure_log) const {
1188 // Validate that hashes is not empty. By the time this code is called (in
1189 // production), that should never happen, but it's good to be defensive.
1190 // And, hashes *can* be empty in some test scenarios.
1191 if (hashes.empty()) {
1192 failure_log->append(
1193 "Rejecting empty public key chain for public-key-pinned domains: " +
1194 domain);
1195 return false;
1198 if (HashesIntersect(bad_spki_hashes, hashes)) {
1199 failure_log->append("Rejecting public key chain for domain " + domain +
1200 ". Validated chain: " + HashesToBase64String(hashes) +
1201 ", matches one or more bad hashes: " +
1202 HashesToBase64String(bad_spki_hashes));
1203 return false;
1206 // If there are no pins, then any valid chain is acceptable.
1207 if (spki_hashes.empty())
1208 return true;
1210 if (HashesIntersect(spki_hashes, hashes)) {
1211 return true;
1214 failure_log->append("Rejecting public key chain for domain " + domain +
1215 ". Validated chain: " + HashesToBase64String(hashes) +
1216 ", expected: " + HashesToBase64String(spki_hashes));
1217 return false;
1220 bool TransportSecurityState::PKPState::HasPublicKeyPins() const {
1221 return spki_hashes.size() > 0 || bad_spki_hashes.size() > 0;
1224 bool TransportSecurityState::PKPState::ShouldSSLErrorsBeFatal() const {
1225 return true;
1228 TransportSecurityState::PKPStateIterator::PKPStateIterator(
1229 const TransportSecurityState& state)
1230 : iterator_(state.enabled_pkp_hosts_.begin()),
1231 end_(state.enabled_pkp_hosts_.end()) {
1234 TransportSecurityState::PKPStateIterator::~PKPStateIterator() {
1237 } // namespace