// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/transport_security_state.h"

#if defined(USE_OPENSSL)
#include <openssl/ecdsa.h>
#include <openssl/ssl.h>
#else  // !defined(USE_OPENSSL)
#include <cryptohi.h>
#include <hasht.h>
#include <keyhi.h>
#include <nspr.h>
#include <pk11pub.h>
#endif

#include <algorithm>

#include "base/base64.h"
#include "base/build_time.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "crypto/sha2.h"
#include "net/base/dns_util.h"
#include "net/cert/x509_cert_types.h"
#include "net/cert/x509_certificate.h"
#include "net/http/http_security_headers.h"
#include "net/ssl/ssl_info.h"
#include "url/gurl.h"

#if defined(USE_OPENSSL)
#include "crypto/openssl_util.h"
#endif

namespace net {

namespace {

std::string HashesToBase64String(const HashValueVector& hashes) {
  std::string str;
  for (size_t i = 0; i != hashes.size(); ++i) {
    if (i != 0)
      str += ",";
    str += hashes[i].ToString();
  }
  return str;
}

std::string HashHost(const std::string& canonicalized_host) {
  char hashed[crypto::kSHA256Length];
  crypto::SHA256HashString(canonicalized_host, hashed, sizeof(hashed));
  return std::string(hashed, sizeof(hashed));
}

// Returns true if the intersection of |a| and |b| is not empty. If either
// |a| or |b| is empty, returns false.
bool HashesIntersect(const HashValueVector& a,
                     const HashValueVector& b) {
  for (HashValueVector::const_iterator i = a.begin(); i != a.end(); ++i) {
    HashValueVector::const_iterator j =
        std::find_if(b.begin(), b.end(), HashValuesEqual(*i));
    if (j != b.end())
      return true;
  }
  return false;
}

bool AddHash(const char* sha1_hash,
             HashValueVector* out) {
  HashValue hash(HASH_VALUE_SHA1);
  memcpy(hash.data(), sha1_hash, hash.size());
  out->push_back(hash);
  return true;
}

}  // namespace

TransportSecurityState::TransportSecurityState()
  : delegate_(NULL) {
  DCHECK(CalledOnValidThread());
}

TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state)
    : iterator_(state.enabled_hosts_.begin()),
      end_(state.enabled_hosts_.end()) {
}

TransportSecurityState::Iterator::~Iterator() {}

void TransportSecurityState::SetDelegate(
    TransportSecurityState::Delegate* delegate) {
  DCHECK(CalledOnValidThread());
  delegate_ = delegate;
}

void TransportSecurityState::EnableHost(const std::string& host,
                                        const DomainState& state) {
  DCHECK(CalledOnValidThread());

  const std::string canonicalized_host = CanonicalizeHost(host);
  if (canonicalized_host.empty())
    return;

  DomainState state_copy(state);
  // No need to store this value since it is redundant. (|canonicalized_host|
  // is the map key.)
  state_copy.domain.clear();

  enabled_hosts_[HashHost(canonicalized_host)] = state_copy;
  DirtyNotify();
}

bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) {
  DCHECK(CalledOnValidThread());

  const std::string canonicalized_host = CanonicalizeHost(host);
  if (canonicalized_host.empty())
    return false;

  DomainStateMap::iterator i = enabled_hosts_.find(
      HashHost(canonicalized_host));
  if (i != enabled_hosts_.end()) {
    enabled_hosts_.erase(i);
    DirtyNotify();
    return true;
  }
  return false;
}

bool TransportSecurityState::GetDomainState(const std::string& host,
                                            bool sni_enabled,
                                            DomainState* result) {
  DCHECK(CalledOnValidThread());

  DomainState state;
  const std::string canonicalized_host = CanonicalizeHost(host);
  if (canonicalized_host.empty())
    return false;

  bool has_preload = GetStaticDomainState(canonicalized_host, sni_enabled,
                                          &state);
  std::string canonicalized_preload = CanonicalizeHost(state.domain);
  GetDynamicDomainState(host, &state);

  base::Time current_time(base::Time::Now());

  for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
    std::string host_sub_chunk(&canonicalized_host[i],
                               canonicalized_host.size() - i);
    // Exact match of a preload always wins.
    if (has_preload && host_sub_chunk == canonicalized_preload) {
      *result = state;
      return true;
    }

    DomainStateMap::iterator j =
        enabled_hosts_.find(HashHost(host_sub_chunk));
    if (j == enabled_hosts_.end())
      continue;

    if (current_time > j->second.upgrade_expiry &&
        current_time > j->second.dynamic_spki_hashes_expiry) {
      enabled_hosts_.erase(j);
      DirtyNotify();
      continue;
    }

    state = j->second;
    state.domain = DNSDomainToString(host_sub_chunk);

    // Succeed if we matched the domain exactly or if subdomain matches are
    // allowed.
    if (i == 0 || j->second.sts_include_subdomains ||
        j->second.pkp_include_subdomains) {
      *result = state;
      return true;
    }

    return false;
  }

  return false;
}

void TransportSecurityState::ClearDynamicData() {
  DCHECK(CalledOnValidThread());
  enabled_hosts_.clear();
}

void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) {
  DCHECK(CalledOnValidThread());

  bool dirtied = false;

  DomainStateMap::iterator i = enabled_hosts_.begin();
  while (i != enabled_hosts_.end()) {
    if (i->second.created >= time) {
      dirtied = true;
      enabled_hosts_.erase(i++);
    } else {
      i++;
    }
  }

  if (dirtied)
    DirtyNotify();
}

TransportSecurityState::~TransportSecurityState() {
  DCHECK(CalledOnValidThread());
}

void TransportSecurityState::DirtyNotify() {
  DCHECK(CalledOnValidThread());

  if (delegate_)
    delegate_->StateIsDirty(this);
}

// static
std::string TransportSecurityState::CanonicalizeHost(const std::string& host) {
  // We cannot perform the operations as detailed in the spec here as |host|
  // has already undergone IDN processing before it reached us. Thus, we check
  // that there are no invalid characters in the host and lowercase the result.

  std::string new_host;
  if (!DNSDomainFromDot(host, &new_host)) {
    // DNSDomainFromDot can fail if any label is > 63 bytes or if the whole
    // name is >255 bytes. However, search terms can have those properties.
    return std::string();
  }

  for (size_t i = 0; new_host[i]; i += new_host[i] + 1) {
    const unsigned label_length = static_cast<unsigned>(new_host[i]);
    if (!label_length)
      break;

    for (size_t j = 0; j < label_length; ++j) {
      new_host[i + 1 + j] = tolower(new_host[i + 1 + j]);
    }
  }

  return new_host;
}

// |ReportUMAOnPinFailure| uses these to report which domain was associated
// with the public key pinning failure.
//
// DO NOT CHANGE THE ORDERING OF THESE NAMES OR REMOVE ANY OF THEM. Add new
// domains at the END of the listing (but before DOMAIN_NUM_EVENTS).
enum SecondLevelDomainName {
  DOMAIN_NOT_PINNED,

  DOMAIN_GOOGLE_COM,
  DOMAIN_ANDROID_COM,
  DOMAIN_GOOGLE_ANALYTICS_COM,
  DOMAIN_GOOGLEPLEX_COM,
  DOMAIN_YTIMG_COM,
  DOMAIN_GOOGLEUSERCONTENT_COM,
  DOMAIN_YOUTUBE_COM,
  DOMAIN_GOOGLEAPIS_COM,
  DOMAIN_GOOGLEADSERVICES_COM,
  DOMAIN_GOOGLECODE_COM,
  DOMAIN_APPSPOT_COM,
  DOMAIN_GOOGLESYNDICATION_COM,
  DOMAIN_DOUBLECLICK_NET,
  DOMAIN_GSTATIC_COM,
  DOMAIN_GMAIL_COM,
  DOMAIN_GOOGLEMAIL_COM,
  DOMAIN_GOOGLEGROUPS_COM,

  DOMAIN_TORPROJECT_ORG,

  DOMAIN_TWITTER_COM,
  DOMAIN_TWIMG_COM,

  DOMAIN_AKAMAIHD_NET,

  DOMAIN_TOR2WEB_ORG,

  DOMAIN_YOUTU_BE,
  DOMAIN_GOOGLECOMMERCE_COM,
  DOMAIN_URCHIN_COM,
  DOMAIN_GOO_GL,
  DOMAIN_G_CO,
  DOMAIN_GOOGLE_AC,
  DOMAIN_GOOGLE_AD,
  DOMAIN_GOOGLE_AE,
  DOMAIN_GOOGLE_AF,
  DOMAIN_GOOGLE_AG,
  DOMAIN_GOOGLE_AM,
  DOMAIN_GOOGLE_AS,
  DOMAIN_GOOGLE_AT,
  DOMAIN_GOOGLE_AZ,
  DOMAIN_GOOGLE_BA,
  DOMAIN_GOOGLE_BE,
  DOMAIN_GOOGLE_BF,
  DOMAIN_GOOGLE_BG,
  DOMAIN_GOOGLE_BI,
  DOMAIN_GOOGLE_BJ,
  DOMAIN_GOOGLE_BS,
  DOMAIN_GOOGLE_BY,
  DOMAIN_GOOGLE_CA,
  DOMAIN_GOOGLE_CAT,
  DOMAIN_GOOGLE_CC,
  DOMAIN_GOOGLE_CD,
  DOMAIN_GOOGLE_CF,
  DOMAIN_GOOGLE_CG,
  DOMAIN_GOOGLE_CH,
  DOMAIN_GOOGLE_CI,
  DOMAIN_GOOGLE_CL,
  DOMAIN_GOOGLE_CM,
  DOMAIN_GOOGLE_CN,
  DOMAIN_CO_AO,
  DOMAIN_CO_BW,
  DOMAIN_CO_CK,
  DOMAIN_CO_CR,
  DOMAIN_CO_HU,
  DOMAIN_CO_ID,
  DOMAIN_CO_IL,
  DOMAIN_CO_IM,
  DOMAIN_CO_IN,
  DOMAIN_CO_JE,
  DOMAIN_CO_JP,
  DOMAIN_CO_KE,
  DOMAIN_CO_KR,
  DOMAIN_CO_LS,
  DOMAIN_CO_MA,
  DOMAIN_CO_MZ,
  DOMAIN_CO_NZ,
  DOMAIN_CO_TH,
  DOMAIN_CO_TZ,
  DOMAIN_CO_UG,
  DOMAIN_CO_UK,
  DOMAIN_CO_UZ,
  DOMAIN_CO_VE,
  DOMAIN_CO_VI,
  DOMAIN_CO_ZA,
  DOMAIN_CO_ZM,
  DOMAIN_CO_ZW,
  DOMAIN_COM_AF,
  DOMAIN_COM_AG,
  DOMAIN_COM_AI,
  DOMAIN_COM_AR,
  DOMAIN_COM_AU,
  DOMAIN_COM_BD,
  DOMAIN_COM_BH,
  DOMAIN_COM_BN,
  DOMAIN_COM_BO,
  DOMAIN_COM_BR,
  DOMAIN_COM_BY,
  DOMAIN_COM_BZ,
  DOMAIN_COM_CN,
  DOMAIN_COM_CO,
  DOMAIN_COM_CU,
  DOMAIN_COM_CY,
  DOMAIN_COM_DO,
  DOMAIN_COM_EC,
  DOMAIN_COM_EG,
  DOMAIN_COM_ET,
  DOMAIN_COM_FJ,
  DOMAIN_COM_GE,
  DOMAIN_COM_GH,
  DOMAIN_COM_GI,
  DOMAIN_COM_GR,
  DOMAIN_COM_GT,
  DOMAIN_COM_HK,
  DOMAIN_COM_IQ,
  DOMAIN_COM_JM,
  DOMAIN_COM_JO,
  DOMAIN_COM_KH,
  DOMAIN_COM_KW,
  DOMAIN_COM_LB,
  DOMAIN_COM_LY,
  DOMAIN_COM_MT,
  DOMAIN_COM_MX,
  DOMAIN_COM_MY,
  DOMAIN_COM_NA,
  DOMAIN_COM_NF,
  DOMAIN_COM_NG,
  DOMAIN_COM_NI,
  DOMAIN_COM_NP,
  DOMAIN_COM_NR,
  DOMAIN_COM_OM,
  DOMAIN_COM_PA,
  DOMAIN_COM_PE,
  DOMAIN_COM_PH,
  DOMAIN_COM_PK,
  DOMAIN_COM_PL,
  DOMAIN_COM_PR,
  DOMAIN_COM_PY,
  DOMAIN_COM_QA,
  DOMAIN_COM_RU,
  DOMAIN_COM_SA,
  DOMAIN_COM_SB,
  DOMAIN_COM_SG,
  DOMAIN_COM_SL,
  DOMAIN_COM_SV,
  DOMAIN_COM_TJ,
  DOMAIN_COM_TN,
  DOMAIN_COM_TR,
  DOMAIN_COM_TW,
  DOMAIN_COM_UA,
  DOMAIN_COM_UY,
  DOMAIN_COM_VC,
  DOMAIN_COM_VE,
  DOMAIN_COM_VN,
  DOMAIN_GOOGLE_CV,
  DOMAIN_GOOGLE_CZ,
  DOMAIN_GOOGLE_DE,
  DOMAIN_GOOGLE_DJ,
  DOMAIN_GOOGLE_DK,
  DOMAIN_GOOGLE_DM,
  DOMAIN_GOOGLE_DZ,
  DOMAIN_GOOGLE_EE,
  DOMAIN_GOOGLE_ES,
  DOMAIN_GOOGLE_FI,
  DOMAIN_GOOGLE_FM,
  DOMAIN_GOOGLE_FR,
  DOMAIN_GOOGLE_GA,
  DOMAIN_GOOGLE_GE,
  DOMAIN_GOOGLE_GG,
  DOMAIN_GOOGLE_GL,
  DOMAIN_GOOGLE_GM,
  DOMAIN_GOOGLE_GP,
  DOMAIN_GOOGLE_GR,
  DOMAIN_GOOGLE_GY,
  DOMAIN_GOOGLE_HK,
  DOMAIN_GOOGLE_HN,
  DOMAIN_GOOGLE_HR,
  DOMAIN_GOOGLE_HT,
  DOMAIN_GOOGLE_HU,
  DOMAIN_GOOGLE_IE,
  DOMAIN_GOOGLE_IM,
  DOMAIN_GOOGLE_INFO,
  DOMAIN_GOOGLE_IQ,
  DOMAIN_GOOGLE_IS,
  DOMAIN_GOOGLE_IT,
  DOMAIN_IT_AO,
  DOMAIN_GOOGLE_JE,
  DOMAIN_GOOGLE_JO,
  DOMAIN_GOOGLE_JOBS,
  DOMAIN_GOOGLE_JP,
  DOMAIN_GOOGLE_KG,
  DOMAIN_GOOGLE_KI,
  DOMAIN_GOOGLE_KZ,
  DOMAIN_GOOGLE_LA,
  DOMAIN_GOOGLE_LI,
  DOMAIN_GOOGLE_LK,
  DOMAIN_GOOGLE_LT,
  DOMAIN_GOOGLE_LU,
  DOMAIN_GOOGLE_LV,
  DOMAIN_GOOGLE_MD,
  DOMAIN_GOOGLE_ME,
  DOMAIN_GOOGLE_MG,
  DOMAIN_GOOGLE_MK,
  DOMAIN_GOOGLE_ML,
  DOMAIN_GOOGLE_MN,
  DOMAIN_GOOGLE_MS,
  DOMAIN_GOOGLE_MU,
  DOMAIN_GOOGLE_MV,
  DOMAIN_GOOGLE_MW,
  DOMAIN_GOOGLE_NE,
  DOMAIN_NE_JP,
  DOMAIN_GOOGLE_NET,
  DOMAIN_GOOGLE_NL,
  DOMAIN_GOOGLE_NO,
  DOMAIN_GOOGLE_NR,
  DOMAIN_GOOGLE_NU,
  DOMAIN_OFF_AI,
  DOMAIN_GOOGLE_PK,
  DOMAIN_GOOGLE_PL,
  DOMAIN_GOOGLE_PN,
  DOMAIN_GOOGLE_PS,
  DOMAIN_GOOGLE_PT,
  DOMAIN_GOOGLE_RO,
  DOMAIN_GOOGLE_RS,
  DOMAIN_GOOGLE_RU,
  DOMAIN_GOOGLE_RW,
  DOMAIN_GOOGLE_SC,
  DOMAIN_GOOGLE_SE,
  DOMAIN_GOOGLE_SH,
  DOMAIN_GOOGLE_SI,
  DOMAIN_GOOGLE_SK,
  DOMAIN_GOOGLE_SM,
  DOMAIN_GOOGLE_SN,
  DOMAIN_GOOGLE_SO,
  DOMAIN_GOOGLE_ST,
  DOMAIN_GOOGLE_TD,
  DOMAIN_GOOGLE_TG,
  DOMAIN_GOOGLE_TK,
  DOMAIN_GOOGLE_TL,
  DOMAIN_GOOGLE_TM,
  DOMAIN_GOOGLE_TN,
  DOMAIN_GOOGLE_TO,
  DOMAIN_GOOGLE_TP,
  DOMAIN_GOOGLE_TT,
  DOMAIN_GOOGLE_US,
  DOMAIN_GOOGLE_UZ,
  DOMAIN_GOOGLE_VG,
  DOMAIN_GOOGLE_VU,
  DOMAIN_GOOGLE_WS,

  DOMAIN_CHROMIUM_ORG,

  DOMAIN_CRYPTO_CAT,
  DOMAIN_LAVABIT_COM,

  // Boundary value for UMA_HISTOGRAM_ENUMERATION:
  DOMAIN_NUM_EVENTS
};

// PublicKeyPins contains a number of SubjectPublicKeyInfo hashes for a site.
// The validated certificate chain for the site must not include any of
// |excluded_hashes| and must include one or more of |required_hashes|.
struct PublicKeyPins {
  const char* const* required_hashes;
  const char* const* excluded_hashes;
};

struct HSTSPreload {
  uint8 length;
  bool include_subdomains;
  char dns_name[38];
  bool https_required;
  PublicKeyPins pins;
  SecondLevelDomainName second_level_domain_name;
};

static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries,
                       const std::string& canonicalized_host, size_t i,
                       TransportSecurityState::DomainState* out, bool* ret) {
  for (size_t j = 0; j < num_entries; j++) {
    if (entries[j].length == canonicalized_host.size() - i &&
        memcmp(entries[j].dns_name, &canonicalized_host[i],
               entries[j].length) == 0) {
      if (!entries[j].include_subdomains && i != 0) {
        *ret = false;
      } else {
        out->sts_include_subdomains = entries[j].include_subdomains;
        out->pkp_include_subdomains = entries[j].include_subdomains;
        *ret = true;
        if (!entries[j].https_required)
          out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT;
        if (entries[j].pins.required_hashes) {
          const char* const* sha1_hash = entries[j].pins.required_hashes;
          while (*sha1_hash) {
            AddHash(*sha1_hash, &out->static_spki_hashes);
            sha1_hash++;
          }
        }
        if (entries[j].pins.excluded_hashes) {
          const char* const* sha1_hash = entries[j].pins.excluded_hashes;
          while (*sha1_hash) {
            AddHash(*sha1_hash, &out->bad_static_spki_hashes);
            sha1_hash++;
          }
        }
      }
      return true;
    }
  }
  return false;
}

#include "net/http/transport_security_state_static.h"

// Returns the HSTSPreload entry for the |canonicalized_host| in |entries|,
// or NULL if there is none. Prefers exact hostname matches to those that
// match only because HSTSPreload.include_subdomains is true.
//
// |canonicalized_host| should be the hostname as canonicalized by
// CanonicalizeHost.
static const struct HSTSPreload* GetHSTSPreload(
    const std::string& canonicalized_host,
    const struct HSTSPreload* entries,
    size_t num_entries) {
  for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
    for (size_t j = 0; j < num_entries; j++) {
      const struct HSTSPreload* entry = entries + j;

      if (i != 0 && !entry->include_subdomains)
        continue;

      if (entry->length == canonicalized_host.size() - i &&
          memcmp(entry->dns_name, &canonicalized_host[i], entry->length) == 0) {
        return entry;
      }
    }
  }

  return NULL;
}

bool TransportSecurityState::AddHSTSHeader(const std::string& host,
                                           const std::string& value) {
  DCHECK(CalledOnValidThread());

  base::Time now = base::Time::Now();
  base::TimeDelta max_age;
  TransportSecurityState::DomainState domain_state;
  GetDynamicDomainState(host, &domain_state);
  if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) {
    // Handle max-age == 0
    if (max_age.InSeconds() == 0)
      domain_state.upgrade_mode = DomainState::MODE_DEFAULT;
    else
      domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
    domain_state.created = now;
    domain_state.upgrade_expiry = now + max_age;
    EnableHost(host, domain_state);
    return true;
  }
  return false;
}

bool TransportSecurityState::AddHPKPHeader(const std::string& host,
                                           const std::string& value,
                                           const SSLInfo& ssl_info) {
  DCHECK(CalledOnValidThread());

  base::Time now = base::Time::Now();
  base::TimeDelta max_age;
  TransportSecurityState::DomainState domain_state;
  GetDynamicDomainState(host, &domain_state);
  if (ParseHPKPHeader(value, ssl_info.public_key_hashes,
                      &max_age, &domain_state.pkp_include_subdomains,
                      &domain_state.dynamic_spki_hashes)) {
    // TODO(palmer): http://crbug.com/243865 handle max-age == 0.
    domain_state.created = now;
    domain_state.dynamic_spki_hashes_expiry = now + max_age;
    EnableHost(host, domain_state);
    return true;
  }
  return false;
}

bool TransportSecurityState::AddHSTS(const std::string& host,
                                     const base::Time& expiry,
                                     bool include_subdomains) {
  DCHECK(CalledOnValidThread());

  // Copy-and-modify the existing DomainState for this host (if any).
  TransportSecurityState::DomainState domain_state;
  const std::string canonicalized_host = CanonicalizeHost(host);
  const std::string hashed_host = HashHost(canonicalized_host);
  DomainStateMap::const_iterator i = enabled_hosts_.find(
      hashed_host);
  if (i != enabled_hosts_.end())
    domain_state = i->second;

  domain_state.created = base::Time::Now();
  domain_state.sts_include_subdomains = include_subdomains;
  domain_state.upgrade_expiry = expiry;
  domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS;
  EnableHost(host, domain_state);
  return true;
}

bool TransportSecurityState::AddHPKP(const std::string& host,
                                     const base::Time& expiry,
                                     bool include_subdomains,
                                     const HashValueVector& hashes) {
  DCHECK(CalledOnValidThread());

  // Copy-and-modify the existing DomainState for this host (if any).
  TransportSecurityState::DomainState domain_state;
  const std::string canonicalized_host = CanonicalizeHost(host);
  const std::string hashed_host = HashHost(canonicalized_host);
  DomainStateMap::const_iterator i = enabled_hosts_.find(
      hashed_host);
  if (i != enabled_hosts_.end())
    domain_state = i->second;

  domain_state.created = base::Time::Now();
  domain_state.pkp_include_subdomains = include_subdomains;
  domain_state.dynamic_spki_hashes_expiry = expiry;
  domain_state.dynamic_spki_hashes = hashes;
  EnableHost(host, domain_state);
  return true;
}

// static
bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
                                                    bool sni_enabled) {
  std::string canonicalized_host = CanonicalizeHost(host);
  const struct HSTSPreload* entry =
      GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);

  if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
    return true;

  if (sni_enabled) {
    entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
                           kNumPreloadedSNISTS);
    if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
      return true;
  }

  return false;
}

// static
void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) {
  std::string canonicalized_host = CanonicalizeHost(host);

  const struct HSTSPreload* entry =
      GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);

  if (!entry) {
    entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
                           kNumPreloadedSNISTS);
  }

  if (!entry) {
    // We don't care to report pin failures for dynamic pins.
    return;
  }

  DCHECK(entry);
  DCHECK(entry->pins.required_hashes);
  DCHECK(entry->second_level_domain_name != DOMAIN_NOT_PINNED);

  UMA_HISTOGRAM_ENUMERATION("Net.PublicKeyPinFailureDomain",
                            entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
}

// static
bool TransportSecurityState::IsBuildTimely() {
  const base::Time build_time = base::GetBuildTime();
  // We consider built-in information to be timely for 10 weeks.
  return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */;
}

bool TransportSecurityState::GetStaticDomainState(
    const std::string& canonicalized_host,
    bool sni_enabled,
    DomainState* out) {
  DCHECK(CalledOnValidThread());

  out->upgrade_mode = DomainState::MODE_FORCE_HTTPS;
  out->sts_include_subdomains = false;
  out->pkp_include_subdomains = false;

  const bool is_build_timely = IsBuildTimely();

  for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
    std::string host_sub_chunk(&canonicalized_host[i],
                               canonicalized_host.size() - i);
    out->domain = DNSDomainToString(host_sub_chunk);
    bool ret;
    if (is_build_timely &&
        HasPreload(kPreloadedSTS, kNumPreloadedSTS, canonicalized_host, i, out,
                   &ret)) {
      return ret;
    }
    if (sni_enabled &&
        is_build_timely &&
        HasPreload(kPreloadedSNISTS, kNumPreloadedSNISTS, canonicalized_host, i,
                   out, &ret)) {
      return ret;
    }
  }

  return false;
}

bool TransportSecurityState::GetDynamicDomainState(const std::string& host,
                                                   DomainState* result) {
  DCHECK(CalledOnValidThread());

  DomainState state;
  const std::string canonicalized_host = CanonicalizeHost(host);
  if (canonicalized_host.empty())
    return false;

  base::Time current_time(base::Time::Now());

  for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
    std::string host_sub_chunk(&canonicalized_host[i],
                               canonicalized_host.size() - i);
    DomainStateMap::iterator j =
        enabled_hosts_.find(HashHost(host_sub_chunk));
    if (j == enabled_hosts_.end())
      continue;

    if (current_time > j->second.upgrade_expiry &&
        current_time > j->second.dynamic_spki_hashes_expiry) {
      enabled_hosts_.erase(j);
      DirtyNotify();
      continue;
    }

    state = j->second;
    state.domain = DNSDomainToString(host_sub_chunk);

    // Succeed if we matched the domain exactly or if subdomain matches are
    // allowed.
    if (i == 0 || j->second.sts_include_subdomains ||
        j->second.pkp_include_subdomains) {
      *result = state;
      return true;
    }

    return false;
  }

  return false;
}


void TransportSecurityState::AddOrUpdateEnabledHosts(
    const std::string& hashed_host, const DomainState& state) {
  DCHECK(CalledOnValidThread());
  enabled_hosts_[hashed_host] = state;
}

TransportSecurityState::DomainState::DomainState()
    : upgrade_mode(MODE_DEFAULT),
      created(base::Time::Now()),
      sts_include_subdomains(false),
      pkp_include_subdomains(false) {
}

TransportSecurityState::DomainState::~DomainState() {
}

bool TransportSecurityState::DomainState::CheckPublicKeyPins(
    const HashValueVector& hashes) const {
  // Validate that hashes is not empty. By the time this code is called (in
  // production), that should never happen, but it's good to be defensive.
  // And, hashes *can* be empty in some test scenarios.
  if (hashes.empty()) {
    LOG(ERROR) << "Rejecting empty public key chain for public-key-pinned "
                  "domain " << domain;
    return false;
  }

  if (HashesIntersect(bad_static_spki_hashes, hashes)) {
    LOG(ERROR) << "Rejecting public key chain for domain " << domain
               << ". Validated chain: " << HashesToBase64String(hashes)
               << ", matches one or more bad hashes: "
               << HashesToBase64String(bad_static_spki_hashes);
    return false;
  }

  // If there are no pins, then any valid chain is acceptable.
  if (dynamic_spki_hashes.empty() && static_spki_hashes.empty())
    return true;

  if (HashesIntersect(dynamic_spki_hashes, hashes) ||
      HashesIntersect(static_spki_hashes, hashes)) {
    return true;
  }

  LOG(ERROR) << "Rejecting public key chain for domain " << domain
             << ". Validated chain: " << HashesToBase64String(hashes)
             << ", expected: " << HashesToBase64String(dynamic_spki_hashes)
             << " or: " << HashesToBase64String(static_spki_hashes);
  return false;
}

bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const {
  return upgrade_mode == MODE_FORCE_HTTPS;
}

bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const {
  return true;
}

bool TransportSecurityState::DomainState::HasPublicKeyPins() const {
  return static_spki_hashes.size() > 0 ||
         bad_static_spki_hashes.size() > 0 ||
         dynamic_spki_hashes.size() > 0;
}

}  // namespace
