Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / net / http / transport_security_state.cc
blob79ee302887ce008e7f626048005ba5946d203f69
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/sha1.h"
26 #include "base/strings/string_number_conversions.h"
27 #include "base/strings/string_util.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "base/time/time.h"
30 #include "base/values.h"
31 #include "crypto/sha2.h"
32 #include "net/base/dns_util.h"
33 #include "net/cert/x509_cert_types.h"
34 #include "net/cert/x509_certificate.h"
35 #include "net/http/http_security_headers.h"
36 #include "net/ssl/ssl_info.h"
37 #include "url/gurl.h"
39 #if defined(USE_OPENSSL)
40 #include "crypto/openssl_util.h"
41 #endif
43 namespace net {
45 namespace {
47 std::string HashesToBase64String(const HashValueVector& hashes) {
48 std::string str;
49 for (size_t i = 0; i != hashes.size(); ++i) {
50 if (i != 0)
51 str += ",";
52 str += hashes[i].ToString();
54 return str;
57 std::string HashHost(const std::string& canonicalized_host) {
58 char hashed[crypto::kSHA256Length];
59 crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
60 return std::string(hashed, sizeof(hashed));
63 // Returns true if the intersection of |a| and |b| is not empty. If either
64 // |a| or |b| is empty, returns false.
65 bool HashesIntersect(const HashValueVector& a,
66 const HashValueVector& b) {
67 for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
68 HashValueVector::const_iterator j =
69 std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
70 if (j != b.end())
71 return true;
73 return false;
76 bool AddHash(const char* sha1_hash,
77 HashValueVector* out) {
78 HashValue hash(HASH_VALUE_SHA1);
79 memcpy(hash.data(), sha1_hash, hash.size());
80 out->push_back(hash);
81 return true;
84 } // namespace
86 TransportSecurityState::TransportSecurityState()
87 : delegate_(NULL), enable_static_pins_(true) {
88 // Static pinning is only enabled for official builds to make sure that
89 // others don't end up with pins that cannot be easily updated.
90 #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS)
91 enable_static_pins_ = false;
92 #endif
93 DCHECK(CalledOnValidThread());
96 TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
97 : iterator_(state.enabled_hosts_.begin()),
98 end_(state.enabled_hosts_.end()) {
101 TransportSecurityState::Iterator::~Iterator() {}
103 bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host,
104 bool sni_enabled) {
105 DomainState state;
106 if (GetStaticDomainState(host, sni_enabled, &state))
107 return true;
108 return GetDynamicDomainState(host, &state);
111 bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host,
112 bool sni_enabled) {
113 DomainState dynamic_state;
114 if (GetDynamicDomainState(host, &dynamic_state))
115 return dynamic_state.ShouldUpgradeToSSL();
117 DomainState static_state;
118 if (GetStaticDomainState(host, sni_enabled, &static_state) &&
119 static_state.ShouldUpgradeToSSL()) {
120 return true;
123 return false;
126 bool TransportSecurityState::CheckPublicKeyPins(
127 const std::string& host,
128 bool sni_available,
129 bool is_issued_by_known_root,
130 const HashValueVector& public_key_hashes,
131 std::string* pinning_failure_log) {
132 // Perform pin validation if, and only if, all these conditions obtain:
134 // * the server's certificate chain chains up to a known root (i.e. not a
135 // user-installed trust anchor); and
136 // * the server actually has public key pins.
137 if (!is_issued_by_known_root || !HasPublicKeyPins(host, sni_available)) {
138 return true;
141 bool pins_are_valid = CheckPublicKeyPinsImpl(
142 host, sni_available, public_key_hashes, pinning_failure_log);
143 if (!pins_are_valid) {
144 LOG(ERROR) << *pinning_failure_log;
145 ReportUMAOnPinFailure(host);
148 UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid);
149 return pins_are_valid;
152 bool TransportSecurityState::HasPublicKeyPins(const std::string& host,
153 bool sni_enabled) {
154 DomainState dynamic_state;
155 if (GetDynamicDomainState(host, &dynamic_state))
156 return dynamic_state.HasPublicKeyPins();
158 DomainState static_state;
159 if (GetStaticDomainState(host, sni_enabled, &static_state)) {
160 if (static_state.HasPublicKeyPins())
161 return true;
164 return false;
167 void TransportSecurityState::SetDelegate(
168 TransportSecurityState::Delegate* delegate) {
169 DCHECK(CalledOnValidThread());
170 delegate_ = delegate;
173 void TransportSecurityState::EnableHost(const std::string& host,
174 const DomainState& state) {
175 DCHECK(CalledOnValidThread());
177 const std::string canonicalized_host = CanonicalizeHost(host);
178 if (canonicalized_host.empty())
179 return;
181 DomainState state_copy(state);
182 // No need to store this value since it is redundant. (|canonicalized_host|
183 // is the map key.)
184 state_copy.domain.clear();
186 enabled_hosts_[HashHost(canonicalized_host)] = state_copy;
187 DirtyNotify();
190 bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
191 DCHECK(CalledOnValidThread());
193 const std::string canonicalized_host = CanonicalizeHost(host);
194 if (canonicalized_host.empty())
195 return false;
197 DomainStateMap::iterator i = enabled_hosts_.find(
198 HashHost(canonicalized_host));
199 if (i != enabled_hosts_.end()) {
200 enabled_hosts_.erase(i);
201 DirtyNotify();
202 return true;
204 return false;
207 void TransportSecurityState::ClearDynamicData() {
208 DCHECK(CalledOnValidThread());
209 enabled_hosts_.clear();
212 void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
213 DCHECK(CalledOnValidThread());
215 bool dirtied = false;
216 DomainStateMap::iterator i = enabled_hosts_.begin();
217 while (i != enabled_hosts_.end()) {
218 if (i->second.sts.last_observed >= time &&
219 i->second.pkp.last_observed >= time) {
220 dirtied = true;
221 enabled_hosts_.erase(i++);
222 continue;
225 if (i->second.sts.last_observed >= time) {
226 dirtied = true;
227 i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT;
228 } else if (i->second.pkp.last_observed >= time) {
229 dirtied = true;
230 i->second.pkp.spki_hashes.clear();
231 i->second.pkp.expiry = base::Time();
233 ++i;
236 if (dirtied)
237 DirtyNotify();
240 TransportSecurityState::~TransportSecurityState() {
241 DCHECK(CalledOnValidThread());
244 void TransportSecurityState::DirtyNotify() {
245 DCHECK(CalledOnValidThread());
247 if (delegate_)
248 delegate_->StateIsDirty(this);
251 // static
252 std::string TransportSecurityState::CanonicalizeHost(const std::string& host) {
253 // We cannot perform the operations as detailed in the spec here as |host|
254 // has already undergone IDN processing before it reached us. Thus, we check
255 // that there are no invalid characters in the host and lowercase the result.
257 std::string new_host;
258 if (!DNSDomainFromDot(host, &new_host)) {
259 // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
260 // name is >255 bytes. However, search terms can have those properties.
261 return std::string();
264 for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
265 const unsigned label_length = static_cast<unsigned>(new_host[i]);
266 if (!label_length)
267 break;
269 for (size_t j = 0; j < label_length; ++j) {
270 new_host[i + 1 + j] = tolower(new_host[i + 1 + j]);
274 return new_host;
277 // |ReportUMAOnPinFailure| uses these to report which domain was associated
278 // with the public key pinning failure.
280 // DO NOT CHANGE THE ORDERING OF THESE NAMES OR REMOVE ANY OF THEM. Add new
281 // domains at the END of the listing (but before DOMAIN_NUM_EVENTS).
282 enum SecondLevelDomainName {
283 DOMAIN_NOT_PINNED,
285 DOMAIN_GOOGLE_COM,
286 DOMAIN_ANDROID_COM,
287 DOMAIN_GOOGLE_ANALYTICS_COM,
288 DOMAIN_GOOGLEPLEX_COM,
289 DOMAIN_YTIMG_COM,
290 DOMAIN_GOOGLEUSERCONTENT_COM,
291 DOMAIN_YOUTUBE_COM,
292 DOMAIN_GOOGLEAPIS_COM,
293 DOMAIN_GOOGLEADSERVICES_COM,
294 DOMAIN_GOOGLECODE_COM,
295 DOMAIN_APPSPOT_COM,
296 DOMAIN_GOOGLESYNDICATION_COM,
297 DOMAIN_DOUBLECLICK_NET,
298 DOMAIN_GSTATIC_COM,
299 DOMAIN_GMAIL_COM,
300 DOMAIN_GOOGLEMAIL_COM,
301 DOMAIN_GOOGLEGROUPS_COM,
303 DOMAIN_TORPROJECT_ORG,
305 DOMAIN_TWITTER_COM,
306 DOMAIN_TWIMG_COM,
308 DOMAIN_AKAMAIHD_NET,
310 DOMAIN_TOR2WEB_ORG,
312 DOMAIN_YOUTU_BE,
313 DOMAIN_GOOGLECOMMERCE_COM,
314 DOMAIN_URCHIN_COM,
315 DOMAIN_GOO_GL,
316 DOMAIN_G_CO,
317 DOMAIN_GOOGLE_AC,
318 DOMAIN_GOOGLE_AD,
319 DOMAIN_GOOGLE_AE,
320 DOMAIN_GOOGLE_AF,
321 DOMAIN_GOOGLE_AG,
322 DOMAIN_GOOGLE_AM,
323 DOMAIN_GOOGLE_AS,
324 DOMAIN_GOOGLE_AT,
325 DOMAIN_GOOGLE_AZ,
326 DOMAIN_GOOGLE_BA,
327 DOMAIN_GOOGLE_BE,
328 DOMAIN_GOOGLE_BF,
329 DOMAIN_GOOGLE_BG,
330 DOMAIN_GOOGLE_BI,
331 DOMAIN_GOOGLE_BJ,
332 DOMAIN_GOOGLE_BS,
333 DOMAIN_GOOGLE_BY,
334 DOMAIN_GOOGLE_CA,
335 DOMAIN_GOOGLE_CAT,
336 DOMAIN_GOOGLE_CC,
337 DOMAIN_GOOGLE_CD,
338 DOMAIN_GOOGLE_CF,
339 DOMAIN_GOOGLE_CG,
340 DOMAIN_GOOGLE_CH,
341 DOMAIN_GOOGLE_CI,
342 DOMAIN_GOOGLE_CL,
343 DOMAIN_GOOGLE_CM,
344 DOMAIN_GOOGLE_CN,
345 DOMAIN_CO_AO,
346 DOMAIN_CO_BW,
347 DOMAIN_CO_CK,
348 DOMAIN_CO_CR,
349 DOMAIN_CO_HU,
350 DOMAIN_CO_ID,
351 DOMAIN_CO_IL,
352 DOMAIN_CO_IM,
353 DOMAIN_CO_IN,
354 DOMAIN_CO_JE,
355 DOMAIN_CO_JP,
356 DOMAIN_CO_KE,
357 DOMAIN_CO_KR,
358 DOMAIN_CO_LS,
359 DOMAIN_CO_MA,
360 DOMAIN_CO_MZ,
361 DOMAIN_CO_NZ,
362 DOMAIN_CO_TH,
363 DOMAIN_CO_TZ,
364 DOMAIN_CO_UG,
365 DOMAIN_CO_UK,
366 DOMAIN_CO_UZ,
367 DOMAIN_CO_VE,
368 DOMAIN_CO_VI,
369 DOMAIN_CO_ZA,
370 DOMAIN_CO_ZM,
371 DOMAIN_CO_ZW,
372 DOMAIN_COM_AF,
373 DOMAIN_COM_AG,
374 DOMAIN_COM_AI,
375 DOMAIN_COM_AR,
376 DOMAIN_COM_AU,
377 DOMAIN_COM_BD,
378 DOMAIN_COM_BH,
379 DOMAIN_COM_BN,
380 DOMAIN_COM_BO,
381 DOMAIN_COM_BR,
382 DOMAIN_COM_BY,
383 DOMAIN_COM_BZ,
384 DOMAIN_COM_CN,
385 DOMAIN_COM_CO,
386 DOMAIN_COM_CU,
387 DOMAIN_COM_CY,
388 DOMAIN_COM_DO,
389 DOMAIN_COM_EC,
390 DOMAIN_COM_EG,
391 DOMAIN_COM_ET,
392 DOMAIN_COM_FJ,
393 DOMAIN_COM_GE,
394 DOMAIN_COM_GH,
395 DOMAIN_COM_GI,
396 DOMAIN_COM_GR,
397 DOMAIN_COM_GT,
398 DOMAIN_COM_HK,
399 DOMAIN_COM_IQ,
400 DOMAIN_COM_JM,
401 DOMAIN_COM_JO,
402 DOMAIN_COM_KH,
403 DOMAIN_COM_KW,
404 DOMAIN_COM_LB,
405 DOMAIN_COM_LY,
406 DOMAIN_COM_MT,
407 DOMAIN_COM_MX,
408 DOMAIN_COM_MY,
409 DOMAIN_COM_NA,
410 DOMAIN_COM_NF,
411 DOMAIN_COM_NG,
412 DOMAIN_COM_NI,
413 DOMAIN_COM_NP,
414 DOMAIN_COM_NR,
415 DOMAIN_COM_OM,
416 DOMAIN_COM_PA,
417 DOMAIN_COM_PE,
418 DOMAIN_COM_PH,
419 DOMAIN_COM_PK,
420 DOMAIN_COM_PL,
421 DOMAIN_COM_PR,
422 DOMAIN_COM_PY,
423 DOMAIN_COM_QA,
424 DOMAIN_COM_RU,
425 DOMAIN_COM_SA,
426 DOMAIN_COM_SB,
427 DOMAIN_COM_SG,
428 DOMAIN_COM_SL,
429 DOMAIN_COM_SV,
430 DOMAIN_COM_TJ,
431 DOMAIN_COM_TN,
432 DOMAIN_COM_TR,
433 DOMAIN_COM_TW,
434 DOMAIN_COM_UA,
435 DOMAIN_COM_UY,
436 DOMAIN_COM_VC,
437 DOMAIN_COM_VE,
438 DOMAIN_COM_VN,
439 DOMAIN_GOOGLE_CV,
440 DOMAIN_GOOGLE_CZ,
441 DOMAIN_GOOGLE_DE,
442 DOMAIN_GOOGLE_DJ,
443 DOMAIN_GOOGLE_DK,
444 DOMAIN_GOOGLE_DM,
445 DOMAIN_GOOGLE_DZ,
446 DOMAIN_GOOGLE_EE,
447 DOMAIN_GOOGLE_ES,
448 DOMAIN_GOOGLE_FI,
449 DOMAIN_GOOGLE_FM,
450 DOMAIN_GOOGLE_FR,
451 DOMAIN_GOOGLE_GA,
452 DOMAIN_GOOGLE_GE,
453 DOMAIN_GOOGLE_GG,
454 DOMAIN_GOOGLE_GL,
455 DOMAIN_GOOGLE_GM,
456 DOMAIN_GOOGLE_GP,
457 DOMAIN_GOOGLE_GR,
458 DOMAIN_GOOGLE_GY,
459 DOMAIN_GOOGLE_HK,
460 DOMAIN_GOOGLE_HN,
461 DOMAIN_GOOGLE_HR,
462 DOMAIN_GOOGLE_HT,
463 DOMAIN_GOOGLE_HU,
464 DOMAIN_GOOGLE_IE,
465 DOMAIN_GOOGLE_IM,
466 DOMAIN_GOOGLE_INFO,
467 DOMAIN_GOOGLE_IQ,
468 DOMAIN_GOOGLE_IS,
469 DOMAIN_GOOGLE_IT,
470 DOMAIN_IT_AO,
471 DOMAIN_GOOGLE_JE,
472 DOMAIN_GOOGLE_JO,
473 DOMAIN_GOOGLE_JOBS,
474 DOMAIN_GOOGLE_JP,
475 DOMAIN_GOOGLE_KG,
476 DOMAIN_GOOGLE_KI,
477 DOMAIN_GOOGLE_KZ,
478 DOMAIN_GOOGLE_LA,
479 DOMAIN_GOOGLE_LI,
480 DOMAIN_GOOGLE_LK,
481 DOMAIN_GOOGLE_LT,
482 DOMAIN_GOOGLE_LU,
483 DOMAIN_GOOGLE_LV,
484 DOMAIN_GOOGLE_MD,
485 DOMAIN_GOOGLE_ME,
486 DOMAIN_GOOGLE_MG,
487 DOMAIN_GOOGLE_MK,
488 DOMAIN_GOOGLE_ML,
489 DOMAIN_GOOGLE_MN,
490 DOMAIN_GOOGLE_MS,
491 DOMAIN_GOOGLE_MU,
492 DOMAIN_GOOGLE_MV,
493 DOMAIN_GOOGLE_MW,
494 DOMAIN_GOOGLE_NE,
495 DOMAIN_NE_JP,
496 DOMAIN_GOOGLE_NET,
497 DOMAIN_GOOGLE_NL,
498 DOMAIN_GOOGLE_NO,
499 DOMAIN_GOOGLE_NR,
500 DOMAIN_GOOGLE_NU,
501 DOMAIN_OFF_AI,
502 DOMAIN_GOOGLE_PK,
503 DOMAIN_GOOGLE_PL,
504 DOMAIN_GOOGLE_PN,
505 DOMAIN_GOOGLE_PS,
506 DOMAIN_GOOGLE_PT,
507 DOMAIN_GOOGLE_RO,
508 DOMAIN_GOOGLE_RS,
509 DOMAIN_GOOGLE_RU,
510 DOMAIN_GOOGLE_RW,
511 DOMAIN_GOOGLE_SC,
512 DOMAIN_GOOGLE_SE,
513 DOMAIN_GOOGLE_SH,
514 DOMAIN_GOOGLE_SI,
515 DOMAIN_GOOGLE_SK,
516 DOMAIN_GOOGLE_SM,
517 DOMAIN_GOOGLE_SN,
518 DOMAIN_GOOGLE_SO,
519 DOMAIN_GOOGLE_ST,
520 DOMAIN_GOOGLE_TD,
521 DOMAIN_GOOGLE_TG,
522 DOMAIN_GOOGLE_TK,
523 DOMAIN_GOOGLE_TL,
524 DOMAIN_GOOGLE_TM,
525 DOMAIN_GOOGLE_TN,
526 DOMAIN_GOOGLE_TO,
527 DOMAIN_GOOGLE_TP,
528 DOMAIN_GOOGLE_TT,
529 DOMAIN_GOOGLE_US,
530 DOMAIN_GOOGLE_UZ,
531 DOMAIN_GOOGLE_VG,
532 DOMAIN_GOOGLE_VU,
533 DOMAIN_GOOGLE_WS,
535 DOMAIN_CHROMIUM_ORG,
537 DOMAIN_CRYPTO_CAT,
538 DOMAIN_LAVABIT_COM,
540 DOMAIN_GOOGLETAGMANAGER_COM,
541 DOMAIN_GOOGLETAGSERVICES_COM,
543 DOMAIN_DROPBOX_COM,
544 DOMAIN_YOUTUBE_NOCOOKIE_COM,
545 DOMAIN_2MDN_NET,
547 // Boundary value for UMA_HISTOGRAM_ENUMERATION:
548 DOMAIN_NUM_EVENTS
551 // PublicKeyPins contains a number of SubjectPublicKeyInfo hashes for a site.
552 // The validated certificate chain for the site must not include any of
553 // |excluded_hashes| and must include one or more of |required_hashes|.
554 struct PublicKeyPins {
555 const char* const* required_hashes;
556 const char* const* excluded_hashes;
559 struct HSTSPreload {
560 uint8 length;
561 bool include_subdomains;
562 char dns_name[38];
563 bool https_required;
564 PublicKeyPins pins;
565 SecondLevelDomainName second_level_domain_name;
568 static bool HasPreload(const struct HSTSPreload* entries,
569 size_t num_entries,
570 const std::string& canonicalized_host,
571 size_t i,
572 bool enable_static_pins,
573 TransportSecurityState::DomainState* out,
574 bool* ret) {
575 for (size_t j = 0; j < num_entries; j++) {
576 if (entries[j].length == canonicalized_host.size() - i &&
577 memcmp(entries[j].dns_name, &canonicalized_host[i],
578 entries[j].length) == 0) {
579 if (!entries[j].include_subdomains && i != 0) {
580 *ret = false;
581 } else {
582 out->sts.include_subdomains = entries[j].include_subdomains;
583 out->sts.last_observed = base::GetBuildTime();
584 *ret = true;
585 out->sts.upgrade_mode =
586 TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
587 if (!entries[j].https_required)
588 out->sts.upgrade_mode =
589 TransportSecurityState::DomainState::MODE_DEFAULT;
591 if (enable_static_pins) {
592 out->pkp.include_subdomains = entries[j].include_subdomains;
593 out->pkp.last_observed = base::GetBuildTime();
594 if (entries[j].pins.required_hashes) {
595 const char* const* sha1_hash = entries[j].pins.required_hashes;
596 while (*sha1_hash) {
597 AddHash(*sha1_hash, &out->pkp.spki_hashes);
598 sha1_hash++;
601 if (entries[j].pins.excluded_hashes) {
602 const char* const* sha1_hash = entries[j].pins.excluded_hashes;
603 while (*sha1_hash) {
604 AddHash(*sha1_hash, &out->pkp.bad_spki_hashes);
605 sha1_hash++;
610 return true;
613 return false;
616 #include "net/http/transport_security_state_static.h"
618 // Returns the HSTSPreload entry for the |canonicalized_host| in |entries|,
619 // or NULL if there is none. Prefers exact hostname matches to those that
620 // match only because HSTSPreload.include_subdomains is true.
622 // |canonicalized_host| should be the hostname as canonicalized by
623 // CanonicalizeHost.
624 static const struct HSTSPreload* GetHSTSPreload(
625 const std::string& canonicalized_host,
626 const struct HSTSPreload* entries,
627 size_t num_entries) {
628 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
629 for (size_t j = 0; j < num_entries; j++) {
630 const struct HSTSPreload* entry = entries + j;
632 if (i != 0 && !entry->include_subdomains)
633 continue;
635 if (entry->length == canonicalized_host.size() - i &&
636 memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) {
637 return entry;
642 return NULL;
645 bool TransportSecurityState::AddHSTSHeader(const std::string& host,
646 const std::string& value) {
647 DCHECK(CalledOnValidThread());
649 base::Time now = base::Time::Now();
650 base::TimeDelta max_age;
651 TransportSecurityState::DomainState domain_state;
652 GetDynamicDomainState(host, &domain_state);
653 if (ParseHSTSHeader(value, &max_age, &domain_state.sts.include_subdomains)) {
654 // Handle max-age == 0.
655 if (max_age.InSeconds() == 0)
656 domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT;
657 else
658 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
659 domain_state.sts.last_observed = now;
660 domain_state.sts.expiry = now + max_age;
661 EnableHost(host, domain_state);
662 return true;
664 return false;
667 bool TransportSecurityState::AddHPKPHeader(const std::string& host,
668 const std::string& value,
669 const SSLInfo& ssl_info) {
670 DCHECK(CalledOnValidThread());
672 base::Time now = base::Time::Now();
673 base::TimeDelta max_age;
674 TransportSecurityState::DomainState domain_state;
675 GetDynamicDomainState(host, &domain_state);
676 if (ParseHPKPHeader(value,
677 ssl_info.public_key_hashes,
678 &max_age,
679 &domain_state.pkp.include_subdomains,
680 &domain_state.pkp.spki_hashes)) {
681 // Handle max-age == 0.
682 if (max_age.InSeconds() == 0)
683 domain_state.pkp.spki_hashes.clear();
684 domain_state.pkp.last_observed = now;
685 domain_state.pkp.expiry = now + max_age;
686 EnableHost(host, domain_state);
687 return true;
689 return false;
692 bool TransportSecurityState::AddHSTS(const std::string& host,
693 const base::Time& expiry,
694 bool include_subdomains) {
695 DCHECK(CalledOnValidThread());
697 // Copy-and-modify the existing DomainState for this host (if any).
698 TransportSecurityState::DomainState domain_state;
699 const std::string canonicalized_host = CanonicalizeHost(host);
700 const std::string hashed_host = HashHost(canonicalized_host);
701 DomainStateMap::const_iterator i = enabled_hosts_.find(
702 hashed_host);
703 if (i != enabled_hosts_.end())
704 domain_state = i->second;
706 domain_state.sts.last_observed = base::Time::Now();
707 domain_state.sts.include_subdomains = include_subdomains;
708 domain_state.sts.expiry = expiry;
709 domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
710 EnableHost(host, domain_state);
711 return true;
714 bool TransportSecurityState::AddHPKP(const std::string& host,
715 const base::Time& expiry,
716 bool include_subdomains,
717 const HashValueVector& hashes) {
718 DCHECK(CalledOnValidThread());
720 // Copy-and-modify the existing DomainState for this host (if any).
721 TransportSecurityState::DomainState domain_state;
722 const std::string canonicalized_host = CanonicalizeHost(host);
723 const std::string hashed_host = HashHost(canonicalized_host);
724 DomainStateMap::const_iterator i = enabled_hosts_.find(
725 hashed_host);
726 if (i != enabled_hosts_.end())
727 domain_state = i->second;
729 domain_state.pkp.last_observed = base::Time::Now();
730 domain_state.pkp.include_subdomains = include_subdomains;
731 domain_state.pkp.expiry = expiry;
732 domain_state.pkp.spki_hashes = hashes;
733 EnableHost(host, domain_state);
734 return true;
737 // static
738 bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
739 bool sni_enabled) {
740 std::string canonicalized_host = CanonicalizeHost(host);
741 const struct HSTSPreload* entry =
742 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
744 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
745 return true;
747 if (sni_enabled) {
748 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
749 kNumPreloadedSNISTS);
750 if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
751 return true;
754 return false;
757 // static
758 void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
759 std::string canonicalized_host = CanonicalizeHost(host);
761 const struct HSTSPreload* entry =
762 GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
764 if (!entry) {
765 entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
766 kNumPreloadedSNISTS);
769 if (!entry) {
770 // We don't care to report pin failures for dynamic pins.
771 return;
774 DCHECK(entry);
775 DCHECK(entry->pins.required_hashes);
776 DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED);
778 UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain",
779 entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
782 // static
783 bool TransportSecurityState::IsBuildTimely() {
784 const base::Time build_time = base::GetBuildTime();
785 // We consider built-in information to be timely for 10 weeks.
786 return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
789 bool TransportSecurityState::CheckPublicKeyPinsImpl(
790 const std::string& host,
791 bool sni_enabled,
792 const HashValueVector& hashes,
793 std::string* failure_log) {
794 DomainState dynamic_state;
795 if (GetDynamicDomainState(host, &dynamic_state))
796 return dynamic_state.CheckPublicKeyPins(hashes, failure_log);
798 DomainState static_state;
799 if (GetStaticDomainState(host, sni_enabled, &static_state))
800 return static_state.CheckPublicKeyPins(hashes, failure_log);
802 // HasPublicKeyPins should have returned true in order for this method
803 // to have been called, so if we fall through to here, it's an error.
804 return false;
807 bool TransportSecurityState::GetStaticDomainState(const std::string& host,
808 bool sni_enabled,
809 DomainState* out) const {
810 DCHECK(CalledOnValidThread());
812 const std::string canonicalized_host = CanonicalizeHost(host);
814 out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
815 out->sts.include_subdomains = false;
816 out->pkp.include_subdomains = false;
818 const bool is_build_timely = IsBuildTimely();
820 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
821 std::string host_sub_chunk(&canonicalized_host[i],
822 canonicalized_host.size() - i);
823 out->domain = DNSDomainToString(host_sub_chunk);
824 bool ret;
825 if (is_build_timely && HasPreload(kPreloadedSTS,
826 kNumPreloadedSTS,
827 canonicalized_host,
829 enable_static_pins_,
830 out,
831 &ret)) {
832 return ret;
834 if (sni_enabled && is_build_timely && HasPreload(kPreloadedSNISTS,
835 kNumPreloadedSNISTS,
836 canonicalized_host,
838 enable_static_pins_,
839 out,
840 &ret)) {
841 return ret;
845 return false;
848 bool TransportSecurityState::GetDynamicDomainState(const std::string& host,
849 DomainState* result) {
850 DCHECK(CalledOnValidThread());
852 DomainState state;
853 const std::string canonicalized_host = CanonicalizeHost(host);
854 if (canonicalized_host.empty())
855 return false;
857 base::Time current_time(base::Time::Now());
859 for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
860 std::string host_sub_chunk(&canonicalized_host[i],
861 canonicalized_host.size() - i);
862 DomainStateMap::iterator j =
863 enabled_hosts_.find(HashHost(host_sub_chunk));
864 if (j == enabled_hosts_.end())
865 continue;
867 if (current_time > j->second.sts.expiry &&
868 current_time > j->second.pkp.expiry) {
869 enabled_hosts_.erase(j);
870 DirtyNotify();
871 continue;
874 state = j->second;
875 state.domain = DNSDomainToString(host_sub_chunk);
877 // Succeed if we matched the domain exactly or if subdomain matches are
878 // allowed.
879 if (i == 0 || j->second.sts.include_subdomains ||
880 j->second.pkp.include_subdomains) {
881 *result = state;
882 return true;
885 return false;
888 return false;
891 void TransportSecurityState::AddOrUpdateEnabledHosts(
892 const std::string& hashed_host, const DomainState& state) {
893 DCHECK(CalledOnValidThread());
894 enabled_hosts_[hashed_host] = state;
897 TransportSecurityState::DomainState::DomainState() {
898 sts.upgrade_mode = MODE_DEFAULT;
899 sts.include_subdomains = false;
900 pkp.include_subdomains = false;
903 TransportSecurityState::DomainState::~DomainState() {
906 bool TransportSecurityState::DomainState::CheckPublicKeyPins(
907 const HashValueVector& hashes, std::string* failure_log) const {
908 // Validate that hashes is not empty. By the time this code is called (in
909 // production), that should never happen, but it's good to be defensive.
910 // And, hashes *can* be empty in some test scenarios.
911 if (hashes.empty()) {
912 failure_log->append(
913 "Rejecting empty public key chain for public-key-pinned domains: " +
914 domain);
915 return false;
918 if (HashesIntersect(pkp.bad_spki_hashes, hashes)) {
919 failure_log->append("Rejecting public key chain for domain " + domain +
920 ". Validated chain: " + HashesToBase64String(hashes) +
921 ", matches one or more bad hashes: " +
922 HashesToBase64String(pkp.bad_spki_hashes));
923 return false;
926 // If there are no pins, then any valid chain is acceptable.
927 if (pkp.spki_hashes.empty())
928 return true;
930 if (HashesIntersect(pkp.spki_hashes, hashes)) {
931 return true;
934 failure_log->append("Rejecting public key chain for domain " + domain +
935 ". Validated chain: " + HashesToBase64String(hashes) +
936 ", expected: " + HashesToBase64String(pkp.spki_hashes));
937 return false;
940 bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
941 return sts.upgrade_mode == MODE_FORCE_HTTPS;
944 bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
945 return true;
948 bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
949 return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0;
952 TransportSecurityState::DomainState::PKPState::PKPState() {
955 TransportSecurityState::DomainState::PKPState::~PKPState() {
958 } // namespace