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)
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_macros.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"
40 #if defined(USE_OPENSSL)
41 #include "crypto/openssl_util.h"
48 #include "net/http/transport_security_state_static.h"
50 std::string
HashesToBase64String(const HashValueVector
& hashes
) {
52 for (size_t i
= 0; i
!= hashes
.size(); ++i
) {
55 str
+= hashes
[i
].ToString();
60 std::string
HashHost(const std::string
& canonicalized_host
) {
61 char hashed
[crypto::kSHA256Length
];
62 crypto::SHA256HashString(canonicalized_host
, hashed
, sizeof(hashed
));
63 return std::string(hashed
, sizeof(hashed
));
66 // Returns true if the intersection of |a| and |b| is not empty. If either
67 // |a| or |b| is empty, returns false.
68 bool HashesIntersect(const HashValueVector
& a
,
69 const HashValueVector
& b
) {
70 for (HashValueVector::const_iterator i
= a
.begin(); i
!= a
.end(); ++i
) {
71 HashValueVector::const_iterator j
=
72 std::find_if(b
.begin(), b
.end(), HashValuesEqual(*i
));
79 bool AddHash(const char* sha1_hash
,
80 HashValueVector
* out
) {
81 HashValue
hash(HASH_VALUE_SHA1
);
82 memcpy(hash
.data(), sha1_hash
, hash
.size());
87 // Converts |hostname| from dotted form ("www.google.com") to the form
88 // used in DNS: "\x03www\x06google\x03com", lowercases that, and returns
90 std::string
CanonicalizeHost(const std::string
& host
) {
91 // We cannot perform the operations as detailed in the spec here as |host|
92 // has already undergone IDN processing before it reached us. Thus, we check
93 // that there are no invalid characters in the host and lowercase the result.
95 if (!DNSDomainFromDot(host
, &new_host
)) {
96 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
97 // name is >255 bytes. However, search terms can have those properties.
101 for (size_t i
= 0; new_host
[i
]; i
+= new_host
[i
] + 1) {
102 const unsigned label_length
= static_cast<unsigned>(new_host
[i
]);
106 for (size_t j
= 0; j
< label_length
; ++j
) {
107 new_host
[i
+ 1 + j
] = static_cast<char>(tolower(new_host
[i
+ 1 + j
]));
114 // BitReader is a class that allows a bytestring to be read bit-by-bit.
117 BitReader(const uint8
* bytes
, size_t num_bits
)
120 num_bytes_((num_bits
+ 7) / 8),
121 current_byte_index_(0),
124 // Next sets |*out| to the next bit from the input. It returns false if no
125 // more bits are available or true otherwise.
126 bool Next(bool* out
) {
127 if (num_bits_used_
== 8) {
128 if (current_byte_index_
>= num_bytes_
) {
131 current_byte_
= bytes_
[current_byte_index_
++];
135 *out
= 1 & (current_byte_
>> (7 - num_bits_used_
));
140 // Read sets the |num_bits| least-significant bits of |*out| to the value of
141 // the next |num_bits| bits from the input. It returns false if there are
142 // insufficient bits in the input or true otherwise.
143 bool Read(unsigned num_bits
, uint32
* out
) {
144 DCHECK_LE(num_bits
, 32u);
147 for (unsigned i
= 0; i
< num_bits
; ++i
) {
152 ret
|= static_cast<uint32
>(bit
) << (num_bits
- 1 - i
);
159 // Unary sets |*out| to the result of decoding a unary value from the input.
160 // It returns false if there were insufficient bits in the input and true
162 bool Unary(size_t* out
) {
180 // Seek sets the current offest in the input to bit number |offset|. It
181 // returns true if |offset| is within the range of the input and false
183 bool Seek(size_t offset
) {
184 if (offset
>= num_bits_
) {
187 current_byte_index_
= offset
/ 8;
188 current_byte_
= bytes_
[current_byte_index_
++];
189 num_bits_used_
= offset
% 8;
194 const uint8
* const bytes_
;
195 const size_t num_bits_
;
196 const size_t num_bytes_
;
197 // current_byte_index_ contains the current byte offset in |bytes_|.
198 size_t current_byte_index_
;
199 // current_byte_ contains the current byte of the input.
201 // num_bits_used_ contains the number of bits of |current_byte_| that have
203 unsigned num_bits_used_
;
206 // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
207 // simply encoded as a series of two-byte structures. The first byte determines
208 // the "0" pointer for that node and the second the "1" pointer. Each byte
209 // either has the MSB set, in which case the bottom 7 bits are the value for
210 // that position, or else the bottom seven bits contain the index of a node.
212 // The tree is decoded by walking rather than a table-driven approach.
213 class HuffmanDecoder
{
215 HuffmanDecoder(const uint8
* tree
, size_t tree_bytes
)
216 : tree_(tree
), tree_bytes_(tree_bytes
) {}
218 bool Decode(BitReader
* reader
, char* out
) {
219 const uint8
* current
= &tree_
[tree_bytes_
- 2];
223 if (!reader
->Next(&bit
)) {
227 uint8 b
= current
[bit
];
229 *out
= static_cast<char>(b
& 0x7f);
233 unsigned offset
= static_cast<unsigned>(b
) * 2;
234 DCHECK_LT(offset
, tree_bytes_
);
235 if (offset
>= tree_bytes_
) {
239 current
= &tree_
[offset
];
244 const uint8
* const tree_
;
245 const size_t tree_bytes_
;
248 // PreloadResult is the result of resolving a specific name in the preloaded
250 struct PreloadResult
{
253 // hostname_offset contains the number of bytes from the start of the given
254 // hostname where the name of the matching entry starts.
255 size_t hostname_offset
;
256 bool sts_include_subdomains
;
257 bool pkp_include_subdomains
;
262 // DecodeHSTSPreloadRaw resolves |hostname| in the preloaded data. It returns
263 // false on internal error and true otherwise. After a successful return,
264 // |*out_found| is true iff a relevant entry has been found. If so, |*out|
265 // contains the details.
267 // Don't call this function, call DecodeHSTSPreload, below.
269 // Although this code should be robust, it never processes attacker-controlled
270 // data -- it only operates on the preloaded data built into the binary.
272 // The preloaded data is represented as a trie and matches the hostname
273 // backwards. Each node in the trie starts with a number of characters, which
274 // must match exactly. After that is a dispatch table which maps the next
275 // character in the hostname to another node in the trie.
277 // In the dispatch table, the zero character represents the "end of string"
278 // (which is the *beginning* of a hostname since we process it backwards). The
279 // value in that case is special -- rather than an offset to another trie node,
280 // it contains the HSTS information: whether subdomains are included, pinsets
281 // etc. If an "end of string" matches a period in the hostname then the
282 // information is remembered because, if no more specific node is found, then
283 // that information applies to the hostname.
285 // Dispatch tables are always given in order, but the "end of string" (zero)
286 // value always comes before an entry for '.'.
287 bool DecodeHSTSPreloadRaw(const std::string
& search_hostname
,
289 PreloadResult
* out
) {
290 HuffmanDecoder
huffman(kHSTSHuffmanTree
, sizeof(kHSTSHuffmanTree
));
291 BitReader
reader(kPreloadedHSTSData
, kPreloadedHSTSBits
);
292 size_t bit_offset
= kHSTSRootPosition
;
293 static const char kEndOfString
= 0;
294 static const char kEndOfTable
= 127;
298 // Ensure that |search_hostname| is a valid hostname before
300 if (CanonicalizeHost(search_hostname
).empty()) {
304 // Normalize any trailing '.' used for DNS suffix searches.
305 std::string hostname
= search_hostname
;
306 size_t found
= hostname
.find_last_not_of('.');
307 if (found
!= std::string::npos
) {
308 hostname
.erase(found
+ 1);
313 // |hostname| has already undergone IDN conversion, so should be
314 // entirely A-Labels. The preload data is entirely normalized to
316 base::StringToLowerASCII(&hostname
);
318 if (hostname
.empty()) {
322 // hostname_offset contains one more than the index of the current character
323 // in the hostname that is being considered. It's one greater so that we can
324 // represent the position just before the beginning (with zero).
325 size_t hostname_offset
= hostname
.size();
328 // Seek to the desired location.
329 if (!reader
.Seek(bit_offset
)) {
333 // Decode the unary length of the common prefix.
334 size_t prefix_length
;
335 if (!reader
.Unary(&prefix_length
)) {
339 // Match each character in the prefix.
340 for (size_t i
= 0; i
< prefix_length
; ++i
) {
341 if (hostname_offset
== 0) {
342 // We can't match the terminator with a prefix string.
347 if (!huffman
.Decode(&reader
, &c
)) {
350 if (hostname
[hostname_offset
- 1] != c
) {
356 bool is_first_offset
= true;
357 size_t current_offset
= 0;
359 // Next is the dispatch table.
362 if (!huffman
.Decode(&reader
, &c
)) {
365 if (c
== kEndOfTable
) {
370 if (c
== kEndOfString
) {
372 if (!reader
.Next(&tmp
.sts_include_subdomains
) ||
373 !reader
.Next(&tmp
.force_https
) || !reader
.Next(&tmp
.has_pins
)) {
377 tmp
.pkp_include_subdomains
= tmp
.sts_include_subdomains
;
380 if (!reader
.Read(4, &tmp
.pinset_id
) ||
381 !reader
.Read(9, &tmp
.domain_id
) ||
382 (!tmp
.sts_include_subdomains
&&
383 !reader
.Next(&tmp
.pkp_include_subdomains
))) {
388 tmp
.hostname_offset
= hostname_offset
;
390 if (hostname_offset
== 0 || hostname
[hostname_offset
- 1] == '.') {
391 *out_found
= tmp
.sts_include_subdomains
|| tmp
.pkp_include_subdomains
;
394 if (hostname_offset
> 0) {
395 out
->force_https
&= tmp
.sts_include_subdomains
;
405 // The entries in a dispatch table are in order thus we can tell if there
406 // will be no match if the current character past the one that we want.
407 if (hostname_offset
== 0 || hostname
[hostname_offset
- 1] < c
) {
411 if (is_first_offset
) {
412 // The first offset is backwards from the current position.
413 uint32 jump_delta_bits
;
415 if (!reader
.Read(5, &jump_delta_bits
) ||
416 !reader
.Read(jump_delta_bits
, &jump_delta
)) {
420 if (bit_offset
< jump_delta
) {
424 current_offset
= bit_offset
- jump_delta
;
425 is_first_offset
= false;
427 // Subsequent offsets are forward from the target of the first offset.
429 if (!reader
.Read(1, &is_long_jump
)) {
435 if (!reader
.Read(7, &jump_delta
)) {
439 uint32 jump_delta_bits
;
440 if (!reader
.Read(4, &jump_delta_bits
) ||
441 !reader
.Read(jump_delta_bits
+ 8, &jump_delta
)) {
446 current_offset
+= jump_delta
;
447 if (current_offset
>= bit_offset
) {
452 DCHECK_LT(0u, hostname_offset
);
453 if (hostname
[hostname_offset
- 1] == c
) {
454 bit_offset
= current_offset
;
462 bool DecodeHSTSPreload(const std::string
& hostname
, PreloadResult
* out
) {
464 if (!DecodeHSTSPreloadRaw(hostname
, &found
, out
)) {
465 DCHECK(false) << "Internal error in DecodeHSTSPreloadRaw for hostname "
475 TransportSecurityState::TransportSecurityState()
476 : delegate_(NULL
), enable_static_pins_(true) {
477 // Static pinning is only enabled for official builds to make sure that
478 // others don't end up with pins that cannot be easily updated.
479 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
480 enable_static_pins_
= false;
482 DCHECK(CalledOnValidThread());
485 // Both HSTS and HPKP cause fatal SSL errors, so return true if a
487 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string
& host
) {
490 if (GetStaticDomainState(host
, &sts_state
, &pkp_state
))
492 if (GetDynamicSTSState(host
, &sts_state
))
494 return GetDynamicPKPState(host
, &pkp_state
);
497 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string
& host
) {
498 STSState dynamic_sts_state
;
499 if (GetDynamicSTSState(host
, &dynamic_sts_state
))
500 return dynamic_sts_state
.ShouldUpgradeToSSL();
502 STSState static_sts_state
;
504 if (GetStaticDomainState(host
, &static_sts_state
, &unused
) &&
505 static_sts_state
.ShouldUpgradeToSSL()) {
512 bool TransportSecurityState::CheckPublicKeyPins(
513 const std::string
& host
,
514 bool is_issued_by_known_root
,
515 const HashValueVector
& public_key_hashes
,
516 std::string
* pinning_failure_log
) {
517 // Perform pin validation if, and only if, all these conditions obtain:
519 // * the server's certificate chain chains up to a known root (i.e. not a
520 // user-installed trust anchor); and
521 // * the server actually has public key pins.
522 if (!is_issued_by_known_root
|| !HasPublicKeyPins(host
)) {
526 bool pins_are_valid
=
527 CheckPublicKeyPinsImpl(host
, public_key_hashes
, pinning_failure_log
);
528 if (!pins_are_valid
) {
529 LOG(ERROR
) << *pinning_failure_log
;
530 ReportUMAOnPinFailure(host
);
533 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid
);
534 return pins_are_valid
;
537 bool TransportSecurityState::HasPublicKeyPins(const std::string
& host
) {
538 PKPState dynamic_state
;
539 if (GetDynamicPKPState(host
, &dynamic_state
))
540 return dynamic_state
.HasPublicKeyPins();
543 PKPState static_pkp_state
;
544 if (GetStaticDomainState(host
, &unused
, &static_pkp_state
)) {
545 if (static_pkp_state
.HasPublicKeyPins())
552 void TransportSecurityState::SetDelegate(
553 TransportSecurityState::Delegate
* delegate
) {
554 DCHECK(CalledOnValidThread());
555 delegate_
= delegate
;
558 void TransportSecurityState::AddHSTSInternal(
559 const std::string
& host
,
560 TransportSecurityState::STSState::UpgradeMode upgrade_mode
,
561 const base::Time
& expiry
,
562 bool include_subdomains
) {
563 DCHECK(CalledOnValidThread());
566 sts_state
.last_observed
= base::Time::Now();
567 sts_state
.include_subdomains
= include_subdomains
;
568 sts_state
.expiry
= expiry
;
569 sts_state
.upgrade_mode
= upgrade_mode
;
571 EnableSTSHost(host
, sts_state
);
574 void TransportSecurityState::AddHPKPInternal(const std::string
& host
,
575 const base::Time
& last_observed
,
576 const base::Time
& expiry
,
577 bool include_subdomains
,
578 const HashValueVector
& hashes
,
579 const GURL
& report_uri
) {
580 DCHECK(CalledOnValidThread());
583 pkp_state
.last_observed
= last_observed
;
584 pkp_state
.expiry
= expiry
;
585 pkp_state
.include_subdomains
= include_subdomains
;
586 pkp_state
.spki_hashes
= hashes
;
587 pkp_state
.report_uri
= report_uri
;
589 EnablePKPHost(host
, pkp_state
);
592 void TransportSecurityState::EnableSTSHost(const std::string
& host
,
593 const STSState
& state
) {
594 DCHECK(CalledOnValidThread());
596 const std::string canonicalized_host
= CanonicalizeHost(host
);
597 if (canonicalized_host
.empty())
600 // Only store new state when HSTS is explicitly enabled. If it is
601 // disabled, remove the state from the enabled hosts.
602 if (state
.ShouldUpgradeToSSL()) {
603 STSState
sts_state(state
);
604 // No need to store this value since it is redundant. (|canonicalized_host|
606 sts_state
.domain
.clear();
608 enabled_sts_hosts_
[HashHost(canonicalized_host
)] = sts_state
;
610 const std::string hashed_host
= HashHost(canonicalized_host
);
611 enabled_sts_hosts_
.erase(hashed_host
);
617 void TransportSecurityState::EnablePKPHost(const std::string
& host
,
618 const PKPState
& state
) {
619 DCHECK(CalledOnValidThread());
621 const std::string canonicalized_host
= CanonicalizeHost(host
);
622 if (canonicalized_host
.empty())
625 // Only store new state when HPKP is explicitly enabled. If it is
626 // disabled, remove the state from the enabled hosts.
627 if (state
.HasPublicKeyPins()) {
628 PKPState
pkp_state(state
);
629 // No need to store this value since it is redundant. (|canonicalized_host|
631 pkp_state
.domain
.clear();
633 enabled_pkp_hosts_
[HashHost(canonicalized_host
)] = pkp_state
;
635 const std::string hashed_host
= HashHost(canonicalized_host
);
636 enabled_pkp_hosts_
.erase(hashed_host
);
642 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string
& host
) {
643 DCHECK(CalledOnValidThread());
645 const std::string canonicalized_host
= CanonicalizeHost(host
);
646 if (canonicalized_host
.empty())
649 const std::string hashed_host
= HashHost(canonicalized_host
);
650 bool deleted
= false;
651 STSStateMap::iterator sts_interator
= enabled_sts_hosts_
.find(hashed_host
);
652 if (sts_interator
!= enabled_sts_hosts_
.end()) {
653 enabled_sts_hosts_
.erase(sts_interator
);
657 PKPStateMap::iterator pkp_iterator
= enabled_pkp_hosts_
.find(hashed_host
);
658 if (pkp_iterator
!= enabled_pkp_hosts_
.end()) {
659 enabled_pkp_hosts_
.erase(pkp_iterator
);
668 void TransportSecurityState::ClearDynamicData() {
669 DCHECK(CalledOnValidThread());
670 enabled_sts_hosts_
.clear();
671 enabled_pkp_hosts_
.clear();
674 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time
& time
) {
675 DCHECK(CalledOnValidThread());
677 bool dirtied
= false;
678 STSStateMap::iterator sts_iterator
= enabled_sts_hosts_
.begin();
679 while (sts_iterator
!= enabled_sts_hosts_
.end()) {
680 if (sts_iterator
->second
.last_observed
>= time
) {
682 enabled_sts_hosts_
.erase(sts_iterator
++);
689 PKPStateMap::iterator pkp_iterator
= enabled_pkp_hosts_
.begin();
690 while (pkp_iterator
!= enabled_pkp_hosts_
.end()) {
691 if (pkp_iterator
->second
.last_observed
>= time
) {
693 enabled_pkp_hosts_
.erase(pkp_iterator
++);
704 TransportSecurityState::~TransportSecurityState() {
705 DCHECK(CalledOnValidThread());
708 void TransportSecurityState::DirtyNotify() {
709 DCHECK(CalledOnValidThread());
712 delegate_
->StateIsDirty(this);
715 bool TransportSecurityState::AddHSTSHeader(const std::string
& host
,
716 const std::string
& value
) {
717 DCHECK(CalledOnValidThread());
719 base::Time now
= base::Time::Now();
720 base::TimeDelta max_age
;
721 bool include_subdomains
;
722 if (!ParseHSTSHeader(value
, &max_age
, &include_subdomains
)) {
726 // Handle max-age == 0.
727 STSState::UpgradeMode upgrade_mode
;
728 if (max_age
.InSeconds() == 0) {
729 upgrade_mode
= STSState::MODE_DEFAULT
;
731 upgrade_mode
= STSState::MODE_FORCE_HTTPS
;
734 AddHSTSInternal(host
, upgrade_mode
, now
+ max_age
, include_subdomains
);
738 bool TransportSecurityState::AddHPKPHeader(const std::string
& host
,
739 const std::string
& value
,
740 const SSLInfo
& ssl_info
) {
741 DCHECK(CalledOnValidThread());
743 base::Time now
= base::Time::Now();
744 base::TimeDelta max_age
;
745 bool include_subdomains
;
746 HashValueVector spki_hashes
;
749 if (!ParseHPKPHeader(value
, ssl_info
.public_key_hashes
, &max_age
,
750 &include_subdomains
, &spki_hashes
, &report_uri
)) {
753 // Handle max-age == 0.
754 if (max_age
.InSeconds() == 0)
756 AddHPKPInternal(host
, now
, now
+ max_age
, include_subdomains
, spki_hashes
,
761 void TransportSecurityState::AddHSTS(const std::string
& host
,
762 const base::Time
& expiry
,
763 bool include_subdomains
) {
764 DCHECK(CalledOnValidThread());
765 AddHSTSInternal(host
, STSState::MODE_FORCE_HTTPS
, expiry
, include_subdomains
);
768 void TransportSecurityState::AddHPKP(const std::string
& host
,
769 const base::Time
& expiry
,
770 bool include_subdomains
,
771 const HashValueVector
& hashes
,
772 const GURL
& report_uri
) {
773 DCHECK(CalledOnValidThread());
774 AddHPKPInternal(host
, base::Time::Now(), expiry
, include_subdomains
, hashes
,
779 bool TransportSecurityState::IsGooglePinnedProperty(const std::string
& host
) {
780 PreloadResult result
;
781 return DecodeHSTSPreload(host
, &result
) && result
.has_pins
&&
782 kPinsets
[result
.pinset_id
].accepted_pins
== kGoogleAcceptableCerts
;
786 void TransportSecurityState::ReportUMAOnPinFailure(const std::string
& host
) {
787 PreloadResult result
;
788 if (!DecodeHSTSPreload(host
, &result
) ||
793 DCHECK(result
.domain_id
!= DOMAIN_NOT_PINNED
);
795 UMA_HISTOGRAM_SPARSE_SLOWLY(
796 "Net.PublicKeyPinFailureDomain", result
.domain_id
);
800 bool TransportSecurityState::IsBuildTimely() {
801 // If the build metadata aren't embedded in the binary then we can't use the
802 // build time to determine if the build is timely, return true by default. If
803 // we're building an official build then keep using the build time, even if
804 // it's invalid it'd be a date in the past and this function will return
806 #if defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
809 const base::Time build_time
= base::GetBuildTime();
810 // We consider built-in information to be timely for 10 weeks.
811 return (base::Time::Now() - build_time
).InDays() < 70 /* 10 weeks */;
815 bool TransportSecurityState::CheckPublicKeyPinsImpl(
816 const std::string
& host
,
817 const HashValueVector
& hashes
,
818 std::string
* failure_log
) {
819 PKPState dynamic_state
;
820 if (GetDynamicPKPState(host
, &dynamic_state
))
821 return dynamic_state
.CheckPublicKeyPins(hashes
, failure_log
);
823 PKPState static_pkp_state
;
825 if (GetStaticDomainState(host
, &unused
, &static_pkp_state
))
826 return static_pkp_state
.CheckPublicKeyPins(hashes
, failure_log
);
828 // HasPublicKeyPins should have returned true in order for this method
829 // to have been called, so if we fall through to here, it's an error.
833 bool TransportSecurityState::GetStaticDomainState(const std::string
& host
,
835 PKPState
* pkp_state
) const {
836 DCHECK(CalledOnValidThread());
838 sts_state
->upgrade_mode
= STSState::MODE_FORCE_HTTPS
;
839 sts_state
->include_subdomains
= false;
840 pkp_state
->include_subdomains
= false;
842 if (!IsBuildTimely())
845 PreloadResult result
;
846 if (!DecodeHSTSPreload(host
, &result
))
849 sts_state
->domain
= host
.substr(result
.hostname_offset
);
850 pkp_state
->domain
= sts_state
->domain
;
851 sts_state
->include_subdomains
= result
.sts_include_subdomains
;
852 sts_state
->last_observed
= base::GetBuildTime();
853 sts_state
->upgrade_mode
= STSState::MODE_DEFAULT
;
854 if (result
.force_https
) {
855 sts_state
->upgrade_mode
= STSState::MODE_FORCE_HTTPS
;
858 if (enable_static_pins_
&& result
.has_pins
) {
859 pkp_state
->include_subdomains
= result
.pkp_include_subdomains
;
860 pkp_state
->last_observed
= base::GetBuildTime();
862 if (result
.pinset_id
>= arraysize(kPinsets
))
864 const Pinset
*pinset
= &kPinsets
[result
.pinset_id
];
866 if (pinset
->accepted_pins
) {
867 const char* const* sha1_hash
= pinset
->accepted_pins
;
869 AddHash(*sha1_hash
, &pkp_state
->spki_hashes
);
873 if (pinset
->rejected_pins
) {
874 const char* const* sha1_hash
= pinset
->rejected_pins
;
876 AddHash(*sha1_hash
, &pkp_state
->bad_spki_hashes
);
885 bool TransportSecurityState::GetDynamicSTSState(const std::string
& host
,
887 DCHECK(CalledOnValidThread());
889 const std::string canonicalized_host
= CanonicalizeHost(host
);
890 if (canonicalized_host
.empty())
893 base::Time
current_time(base::Time::Now());
895 for (size_t i
= 0; canonicalized_host
[i
]; i
+= canonicalized_host
[i
] + 1) {
896 std::string
host_sub_chunk(&canonicalized_host
[i
],
897 canonicalized_host
.size() - i
);
898 STSStateMap::iterator j
= enabled_sts_hosts_
.find(HashHost(host_sub_chunk
));
899 if (j
== enabled_sts_hosts_
.end())
902 // If the entry is invalid, drop it.
903 if (current_time
> j
->second
.expiry
) {
904 enabled_sts_hosts_
.erase(j
);
909 // If this is the most specific STS match, add it to the result. Note: a STS
910 // entry at a more specific domain overrides a less specific domain whether
911 // or not |include_subdomains| is set.
912 if (current_time
<= j
->second
.expiry
) {
913 if (i
== 0 || j
->second
.include_subdomains
) {
915 result
->domain
= DNSDomainToString(host_sub_chunk
);
926 bool TransportSecurityState::GetDynamicPKPState(const std::string
& host
,
928 DCHECK(CalledOnValidThread());
930 const std::string canonicalized_host
= CanonicalizeHost(host
);
931 if (canonicalized_host
.empty())
934 base::Time
current_time(base::Time::Now());
936 for (size_t i
= 0; canonicalized_host
[i
]; i
+= canonicalized_host
[i
] + 1) {
937 std::string
host_sub_chunk(&canonicalized_host
[i
],
938 canonicalized_host
.size() - i
);
939 PKPStateMap::iterator j
= enabled_pkp_hosts_
.find(HashHost(host_sub_chunk
));
940 if (j
== enabled_pkp_hosts_
.end())
943 // If the entry is invalid, drop it.
944 if (current_time
> j
->second
.expiry
) {
945 enabled_pkp_hosts_
.erase(j
);
950 // If this is the most specific PKP match, add it to the result. Note: a PKP
951 // entry at a more specific domain overrides a less specific domain whether
952 // or not |include_subdomains| is set.
953 if (current_time
<= j
->second
.expiry
) {
954 if (i
== 0 || j
->second
.include_subdomains
) {
956 result
->domain
= DNSDomainToString(host_sub_chunk
);
967 void TransportSecurityState::AddOrUpdateEnabledSTSHosts(
968 const std::string
& hashed_host
,
969 const STSState
& state
) {
970 DCHECK(CalledOnValidThread());
971 DCHECK(state
.ShouldUpgradeToSSL());
972 enabled_sts_hosts_
[hashed_host
] = state
;
975 void TransportSecurityState::AddOrUpdateEnabledPKPHosts(
976 const std::string
& hashed_host
,
977 const PKPState
& state
) {
978 DCHECK(CalledOnValidThread());
979 DCHECK(state
.HasPublicKeyPins());
980 enabled_pkp_hosts_
[hashed_host
] = state
;
983 TransportSecurityState::STSState::STSState()
984 : upgrade_mode(MODE_DEFAULT
), include_subdomains(false) {
987 TransportSecurityState::STSState::~STSState() {
990 bool TransportSecurityState::STSState::ShouldUpgradeToSSL() const {
991 return upgrade_mode
== MODE_FORCE_HTTPS
;
994 bool TransportSecurityState::STSState::ShouldSSLErrorsBeFatal() const {
998 TransportSecurityState::STSStateIterator::STSStateIterator(
999 const TransportSecurityState
& state
)
1000 : iterator_(state
.enabled_sts_hosts_
.begin()),
1001 end_(state
.enabled_sts_hosts_
.end()) {
1004 TransportSecurityState::STSStateIterator::~STSStateIterator() {
1007 TransportSecurityState::PKPState::PKPState() : include_subdomains(false) {
1010 TransportSecurityState::PKPState::~PKPState() {
1013 bool TransportSecurityState::PKPState::CheckPublicKeyPins(
1014 const HashValueVector
& hashes
,
1015 std::string
* failure_log
) const {
1016 // Validate that hashes is not empty. By the time this code is called (in
1017 // production), that should never happen, but it's good to be defensive.
1018 // And, hashes *can* be empty in some test scenarios.
1019 if (hashes
.empty()) {
1020 failure_log
->append(
1021 "Rejecting empty public key chain for public-key-pinned domains: " +
1026 if (HashesIntersect(bad_spki_hashes
, hashes
)) {
1027 failure_log
->append("Rejecting public key chain for domain " + domain
+
1028 ". Validated chain: " + HashesToBase64String(hashes
) +
1029 ", matches one or more bad hashes: " +
1030 HashesToBase64String(bad_spki_hashes
));
1034 // If there are no pins, then any valid chain is acceptable.
1035 if (spki_hashes
.empty())
1038 if (HashesIntersect(spki_hashes
, hashes
)) {
1042 failure_log
->append("Rejecting public key chain for domain " + domain
+
1043 ". Validated chain: " + HashesToBase64String(hashes
) +
1044 ", expected: " + HashesToBase64String(spki_hashes
));
1048 bool TransportSecurityState::PKPState::HasPublicKeyPins() const {
1049 return spki_hashes
.size() > 0 || bad_spki_hashes
.size() > 0;
1052 bool TransportSecurityState::PKPState::ShouldSSLErrorsBeFatal() const {
1056 TransportSecurityState::PKPStateIterator::PKPStateIterator(
1057 const TransportSecurityState
& state
)
1058 : iterator_(state
.enabled_pkp_hosts_
.begin()),
1059 end_(state
.enabled_pkp_hosts_
.end()) {
1062 TransportSecurityState::PKPStateIterator::~PKPStateIterator() {