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