X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fnet%2Fhttp%2Ftransport_security_state.cc;h=e967c659c07c65828fe704f4dfc3083820e3126f;hb=004985e17e624662a4c85c76a7654039dc83f028;hp=8142e09e8251070669d49e6a52561d4f2b1d6536;hpb=42dcc1327bbd3f24706b73963db769f667a58196;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/net/http/transport_security_state.cc b/src/net/http/transport_security_state.cc index 8142e09..e967c65 100644 --- a/src/net/http/transport_security_state.cc +++ b/src/net/http/transport_security_state.cc @@ -95,6 +95,61 @@ TransportSecurityState::Iterator::Iterator(const TransportSecurityState& state) TransportSecurityState::Iterator::~Iterator() {} +bool TransportSecurityState::ShouldSSLErrorsBeFatal(const std::string& host, + bool sni_enabled) { + DomainState state; + if (GetStaticDomainState(host, sni_enabled, &state)) + return true; + return GetDynamicDomainState(host, &state); +} + +bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host, + bool sni_enabled) { + DomainState dynamic_state; + if (GetDynamicDomainState(host, &dynamic_state)) + return dynamic_state.ShouldUpgradeToSSL(); + + DomainState static_state; + if (GetStaticDomainState(host, sni_enabled, &static_state) && + static_state.ShouldUpgradeToSSL()) { + return true; + } + + return false; +} + +bool TransportSecurityState::CheckPublicKeyPins(const std::string& host, + bool sni_enabled, + const HashValueVector& hashes, + std::string* failure_log) { + DomainState dynamic_state; + if (GetDynamicDomainState(host, &dynamic_state)) + return dynamic_state.CheckPublicKeyPins(hashes, failure_log); + + DomainState static_state; + if (GetStaticDomainState(host, sni_enabled, &static_state) && + static_state.CheckPublicKeyPins(hashes, failure_log)) { + return true; + } + + return false; +} + +bool TransportSecurityState::HasPublicKeyPins(const std::string& host, + bool sni_enabled) { + DomainState dynamic_state; + if (GetDynamicDomainState(host, &dynamic_state)) + return dynamic_state.HasPublicKeyPins(); + + DomainState static_state; + if (GetStaticDomainState(host, sni_enabled, &static_state)) { + if (static_state.HasPublicKeyPins()) + return true; + } + + return false; +} + void TransportSecurityState::SetDelegate( TransportSecurityState::Delegate* delegate) { DCHECK(CalledOnValidThread()); @@ -135,61 +190,6 @@ bool TransportSecurityState::DeleteDynamicDataForHost(const std::string& host) { 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(); @@ -201,18 +201,20 @@ void TransportSecurityState::DeleteAllDynamicDataSince(const base::Time& time) { bool dirtied = false; DomainStateMap::iterator i = enabled_hosts_.begin(); while (i != enabled_hosts_.end()) { - if (i->second.sts_observed >= time && i->second.pkp_observed >= time) { + if (i->second.sts.last_observed >= time && + i->second.pkp.last_observed >= time) { dirtied = true; enabled_hosts_.erase(i++); continue; } - if (i->second.sts_observed >= time) { + if (i->second.sts.last_observed >= time) { dirtied = true; - i->second.upgrade_mode = DomainState::MODE_DEFAULT; - } else if (i->second.pkp_observed >= time) { + i->second.sts.upgrade_mode = DomainState::MODE_DEFAULT; + } else if (i->second.pkp.last_observed >= time) { dirtied = true; - i->second.dynamic_spki_hashes.clear(); + i->second.pkp.spki_hashes.clear(); + i->second.pkp.expiry = base::Time(); } ++i; } @@ -522,6 +524,7 @@ enum SecondLevelDomainName { DOMAIN_LAVABIT_COM, DOMAIN_GOOGLETAGMANAGER_COM, + DOMAIN_GOOGLETAGSERVICES_COM, // Boundary value for UMA_HISTOGRAM_ENUMERATION: DOMAIN_NUM_EVENTS @@ -554,22 +557,27 @@ static bool HasPreload(const struct HSTSPreload* entries, size_t num_entries, 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; + out->sts.include_subdomains = entries[j].include_subdomains; + out->sts.last_observed = base::GetBuildTime(); + out->pkp.include_subdomains = entries[j].include_subdomains; + out->pkp.last_observed = base::GetBuildTime(); *ret = true; + out->sts.upgrade_mode = + TransportSecurityState::DomainState::MODE_FORCE_HTTPS; if (!entries[j].https_required) - out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT; + out->sts.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); + AddHash(*sha1_hash, &out->pkp.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); + AddHash(*sha1_hash, &out->pkp.bad_spki_hashes); sha1_hash++; } } @@ -617,14 +625,14 @@ bool TransportSecurityState::AddHSTSHeader(const std::string& host, base::TimeDelta max_age; TransportSecurityState::DomainState domain_state; GetDynamicDomainState(host, &domain_state); - if (ParseHSTSHeader(value, &max_age, &domain_state.sts_include_subdomains)) { + 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; + domain_state.sts.upgrade_mode = DomainState::MODE_DEFAULT; else - domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; - domain_state.sts_observed = now; - domain_state.upgrade_expiry = now + max_age; + domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; + domain_state.sts.last_observed = now; + domain_state.sts.expiry = now + max_age; EnableHost(host, domain_state); return true; } @@ -640,12 +648,14 @@ bool TransportSecurityState::AddHPKPHeader(const std::string& host, 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)) { + if (ParseHPKPHeader(value, + ssl_info.public_key_hashes, + &max_age, + &domain_state.pkp.include_subdomains, + &domain_state.pkp.spki_hashes)) { // TODO(palmer): http://crbug.com/243865 handle max-age == 0. - domain_state.pkp_observed = now; - domain_state.dynamic_spki_hashes_expiry = now + max_age; + domain_state.pkp.last_observed = now; + domain_state.pkp.expiry = now + max_age; EnableHost(host, domain_state); return true; } @@ -666,10 +676,10 @@ bool TransportSecurityState::AddHSTS(const std::string& host, if (i != enabled_hosts_.end()) domain_state = i->second; - domain_state.sts_observed = base::Time::Now(); - domain_state.sts_include_subdomains = include_subdomains; - domain_state.upgrade_expiry = expiry; - domain_state.upgrade_mode = DomainState::MODE_FORCE_HTTPS; + domain_state.sts.last_observed = base::Time::Now(); + domain_state.sts.include_subdomains = include_subdomains; + domain_state.sts.expiry = expiry; + domain_state.sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; EnableHost(host, domain_state); return true; } @@ -689,10 +699,10 @@ bool TransportSecurityState::AddHPKP(const std::string& host, if (i != enabled_hosts_.end()) domain_state = i->second; - domain_state.pkp_observed = base::Time::Now(); - domain_state.pkp_include_subdomains = include_subdomains; - domain_state.dynamic_spki_hashes_expiry = expiry; - domain_state.dynamic_spki_hashes = hashes; + domain_state.pkp.last_observed = base::Time::Now(); + domain_state.pkp.include_subdomains = include_subdomains; + domain_state.pkp.expiry = expiry; + domain_state.pkp.spki_hashes = hashes; EnableHost(host, domain_state); return true; } @@ -718,21 +728,6 @@ bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host, } // static -bool TransportSecurityState::GetPinsForDebugging( - const std::string& host, - const char* const** out_required_pins, - const char* const** out_excluded_pins) { - const std::string canonicalized_host = CanonicalizeHost(host); - const struct HSTSPreload* entry = - GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS); - if (!entry) - return false; - *out_required_pins = entry->pins.required_hashes; - *out_excluded_pins = entry->pins.excluded_hashes; - return true; -} - -// static void TransportSecurityState::ReportUMAOnPinFailure(const std::string& host) { std::string canonicalized_host = CanonicalizeHost(host); @@ -764,15 +759,16 @@ bool TransportSecurityState::IsBuildTimely() { return (base::Time::Now() - build_time).InDays() < 70 /* 10 weeks */; } -bool TransportSecurityState::GetStaticDomainState( - const std::string& canonicalized_host, - bool sni_enabled, - DomainState* out) { +bool TransportSecurityState::GetStaticDomainState(const std::string& host, + bool sni_enabled, + DomainState* out) const { DCHECK(CalledOnValidThread()); - out->upgrade_mode = DomainState::MODE_FORCE_HTTPS; - out->sts_include_subdomains = false; - out->pkp_include_subdomains = false; + const std::string canonicalized_host = CanonicalizeHost(host); + + out->sts.upgrade_mode = DomainState::MODE_FORCE_HTTPS; + out->sts.include_subdomains = false; + out->pkp.include_subdomains = false; const bool is_build_timely = IsBuildTimely(); @@ -816,8 +812,8 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host, if (j == enabled_hosts_.end()) continue; - if (current_time > j->second.upgrade_expiry && - current_time > j->second.dynamic_spki_hashes_expiry) { + if (current_time > j->second.sts.expiry && + current_time > j->second.pkp.expiry) { enabled_hosts_.erase(j); DirtyNotify(); continue; @@ -828,8 +824,8 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host, // 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) { + if (i == 0 || j->second.sts.include_subdomains || + j->second.pkp.include_subdomains) { *result = state; return true; } @@ -840,62 +836,57 @@ bool TransportSecurityState::GetDynamicDomainState(const std::string& host, 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), - sts_include_subdomains(false), - pkp_include_subdomains(false) { - base::Time now(base::Time::Now()); - sts_observed = now; - pkp_observed = now; +TransportSecurityState::DomainState::DomainState() { + sts.upgrade_mode = MODE_DEFAULT; + sts.include_subdomains = false; + pkp.include_subdomains = false; } TransportSecurityState::DomainState::~DomainState() { } bool TransportSecurityState::DomainState::CheckPublicKeyPins( - const HashValueVector& hashes) const { + const HashValueVector& hashes, std::string* failure_log) 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; + failure_log->append( + "Rejecting empty public key chain for public-key-pinned domains: " + + 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); + if (HashesIntersect(pkp.bad_spki_hashes, hashes)) { + failure_log->append("Rejecting public key chain for domain " + domain + + ". Validated chain: " + HashesToBase64String(hashes) + + ", matches one or more bad hashes: " + + HashesToBase64String(pkp.bad_spki_hashes)); return false; } // If there are no pins, then any valid chain is acceptable. - if (dynamic_spki_hashes.empty() && static_spki_hashes.empty()) + if (pkp.spki_hashes.empty()) return true; - if (HashesIntersect(dynamic_spki_hashes, hashes) || - HashesIntersect(static_spki_hashes, hashes)) { + if (HashesIntersect(pkp.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); + failure_log->append("Rejecting public key chain for domain " + domain + + ". Validated chain: " + HashesToBase64String(hashes) + + ", expected: " + HashesToBase64String(pkp.spki_hashes)); return false; } bool TransportSecurityState::DomainState::ShouldUpgradeToSSL() const { - return upgrade_mode == MODE_FORCE_HTTPS; + return sts.upgrade_mode == MODE_FORCE_HTTPS; } bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { @@ -903,9 +894,13 @@ bool TransportSecurityState::DomainState::ShouldSSLErrorsBeFatal() const { } bool TransportSecurityState::DomainState::HasPublicKeyPins() const { - return static_spki_hashes.size() > 0 || - bad_static_spki_hashes.size() > 0 || - dynamic_spki_hashes.size() > 0; + return pkp.spki_hashes.size() > 0 || pkp.bad_spki_hashes.size() > 0; +} + +TransportSecurityState::DomainState::PKPState::PKPState() { +} + +TransportSecurityState::DomainState::PKPState::~PKPState() { } } // namespace