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