Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(308)

Unified Diff: net/base/transport_security_state.cc

Issue 9415040: Refactor TransportSecurityState. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/base/transport_security_state.cc
===================================================================
--- net/base/transport_security_state.cc (revision 133741)
+++ net/base/transport_security_state.cc (working copy)
@@ -19,8 +19,6 @@
#include <utility>
#include "base/base64.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
@@ -33,7 +31,6 @@
#include "base/values.h"
#include "crypto/sha2.h"
#include "googleurl/src/gurl.h"
-#include "net/base/asn1_util.h"
#include "net/base/dns_util.h"
#include "net/base/ssl_info.h"
#include "net/base/x509_certificate.h"
@@ -47,20 +44,15 @@
const long int TransportSecurityState::kMaxHSTSAgeSecs = 86400 * 365; // 1 year
-TransportSecurityState::TransportSecurityState(const std::string& hsts_hosts)
- : delegate_(NULL) {
- if (!hsts_hosts.empty()) {
- bool dirty;
- Deserialise(hsts_hosts, &dirty, &forced_hosts_);
- }
-}
-
static 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));
}
+TransportSecurityState::TransportSecurityState()
+ : delegate_(NULL) { }
Ryan Sleevi 2012/04/26 19:21:12 nit: move } to a new line
palmer 2012/04/27 23:52:34 Done.
+
void TransportSecurityState::SetDelegate(
TransportSecurityState::Delegate* delegate) {
delegate_ = delegate;
@@ -74,24 +66,19 @@
if (canonicalized_host.empty())
return;
- // Only override a preloaded state if the new state describes a more strict
- // policy. TODO(palmer): Reconsider this?
DomainState existing_state;
- if (IsPreloadedSTS(canonicalized_host, true, &existing_state) &&
- canonicalized_host == CanonicalizeHost(existing_state.domain) &&
- existing_state.IsMoreStrict(state)) {
- return;
- }
- // Use the original creation date if we already have this host.
+ // Use the original creation date if we already have this host. (But note
+ // that statically-defined states have no |created| date. Therefore, we do
+ // not bother to search the SNI-only static states.)
DomainState state_copy(state);
- if (GetDomainState(&existing_state, host, true) &&
+ if (GetDomainState(host, false /* sni_enabled */, &existing_state) &&
!existing_state.created.is_null()) {
state_copy.created = existing_state.created;
}
- // We don't store these values.
- state_copy.preloaded = false;
+ // 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;
@@ -115,35 +102,18 @@
return false;
}
-bool TransportSecurityState::HasPinsForHost(DomainState* result,
- const std::string& host,
- bool sni_available) {
+bool TransportSecurityState::GetDomainState(const std::string& host,
+ bool sni_enabled,
+ DomainState* result) {
DCHECK(CalledOnValidThread());
- return HasMetadata(result, host, sni_available) &&
- (!result->dynamic_spki_hashes.empty() ||
- !result->preloaded_spki_hashes.empty());
-}
-
-bool TransportSecurityState::GetDomainState(DomainState* result,
- const std::string& host,
- bool sni_available) {
- DCHECK(CalledOnValidThread());
-
- return HasMetadata(result, host, sni_available);
-}
-
-bool TransportSecurityState::HasMetadata(DomainState* result,
- const std::string& host,
- bool sni_available) {
- DCHECK(CalledOnValidThread());
-
DomainState state;
const std::string canonicalized_host = CanonicalizeHost(host);
if (canonicalized_host.empty())
return false;
- bool has_preload = IsPreloadedSTS(canonicalized_host, sni_available, &state);
+ bool has_preload = GetStaticDomainState(canonicalized_host, sni_enabled,
+ &state);
std::string canonicalized_preload = CanonicalizeHost(state.domain);
base::Time current_time(base::Time::Now());
@@ -162,7 +132,7 @@
if (j == enabled_hosts_.end())
continue;
- if (current_time > j->second.expiry &&
+ if (current_time > j->second.upgrade_expiry &&
current_time > j->second.dynamic_spki_hashes_expiry) {
enabled_hosts_.erase(j);
DirtyNotify();
@@ -290,23 +260,6 @@
return true;
}
-// static
-bool TransportSecurityState::GetPublicKeyHash(
- const X509Certificate& cert, SHA1Fingerprint* spki_hash) {
- std::string der_bytes;
- if (!X509Certificate::GetDEREncoded(cert.os_cert_handle(), &der_bytes))
- return false;
-
- base::StringPiece spki;
- if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki))
- return false;
-
- base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(spki.data()),
- spki.size(), spki_hash->data);
-
- return true;
-}
-
struct FingerprintsEqualPredicate {
explicit FingerprintsEqualPredicate(const SHA1Fingerprint& fingerprint) :
fingerprint_(fingerprint) {}
@@ -368,13 +321,12 @@
// "Public-Key-Pins" ":"
// "max-age" "=" delta-seconds ";"
// "pin-" algo "=" base64 [ ";" ... ]
-//
-// static
-bool TransportSecurityState::ParsePinsHeader(const std::string& value,
- const SSLInfo& ssl_info,
- DomainState* state) {
+bool TransportSecurityState::DomainState::ParsePinsHeader(
+ const base::Time& now,
+ const std::string& value,
+ const SSLInfo& ssl_info) {
bool parsed_max_age = false;
- int max_age = 0;
+ int max_age_candidate = 0;
FingerprintVector pins;
std::string source = value;
@@ -389,11 +341,12 @@
if (LowerCaseEqualsASCII(equals.first, "max-age")) {
if (equals.second.empty() ||
- !MaxAgeToInt(equals.second.begin(), equals.second.end(), &max_age)) {
+ !MaxAgeToInt(equals.second.begin(), equals.second.end(),
+ &max_age_candidate)) {
return false;
}
- if (max_age > kMaxHSTSAgeSecs)
- max_age = kMaxHSTSAgeSecs;
+ if (max_age_candidate > kMaxHSTSAgeSecs)
+ max_age_candidate = kMaxHSTSAgeSecs;
parsed_max_age = true;
} else if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) {
if (!ParseAndAppendPin(equals.second, &pins))
@@ -410,15 +363,14 @@
if (!parsed_max_age || !IsPinListValid(pins, ssl_info))
return false;
- state->max_age = max_age;
- state->dynamic_spki_hashes_expiry =
- base::Time::Now() + base::TimeDelta::FromSeconds(max_age);
+ dynamic_spki_hashes_expiry =
+ now + base::TimeDelta::FromSeconds(max_age_candidate);
- state->dynamic_spki_hashes.clear();
- if (max_age > 0) {
+ dynamic_spki_hashes.clear();
+ if (max_age_candidate > 0) {
for (FingerprintVector::const_iterator i = pins.begin();
- i != pins.end(); i++) {
- state->dynamic_spki_hashes.push_back(*i);
+ i != pins.end(); ++i) {
+ dynamic_spki_hashes.push_back(*i);
}
}
@@ -427,14 +379,9 @@
// "Strict-Transport-Security" ":"
// "max-age" "=" delta-seconds [ ";" "includeSubDomains" ]
-//
-// static
-bool TransportSecurityState::ParseHeader(const std::string& value,
- int* max_age,
- bool* include_subdomains) {
- DCHECK(max_age);
- DCHECK(include_subdomains);
-
+bool TransportSecurityState::DomainState::ParseSTSHeader(
+ const base::Time& now,
+ const std::string& value) {
int max_age_candidate = 0;
enum ParserState {
@@ -511,14 +458,18 @@
case AFTER_MAX_AGE_EQUALS:
return false;
case AFTER_MAX_AGE:
- *max_age = max_age_candidate;
- *include_subdomains = false;
+ upgrade_expiry =
+ now + base::TimeDelta::FromSeconds(max_age_candidate);
+ include_subdomains = false;
+ upgrade_mode = MODE_FORCE_HTTPS;
return true;
case AFTER_MAX_AGE_INCLUDE_SUB_DOMAINS_DELIMITER:
return false;
case AFTER_INCLUDE_SUBDOMAINS:
- *max_age = max_age_candidate;
- *include_subdomains = true;
+ upgrade_expiry =
+ now + base::TimeDelta::FromSeconds(max_age_candidate);
+ include_subdomains = true;
+ upgrade_mode = MODE_FORCE_HTTPS;
return true;
default:
NOTREACHED();
@@ -526,370 +477,6 @@
}
}
-// Side pinning and superfluous certificates:
-//
-// In SSLClientSocketNSS::DoVerifyCertComplete we look for certificates with a
-// Subject of CN=meta. When we find one we'll currently try and parse side
-// pinned key from it.
-//
-// A side pin is a key which can be pinned to, but also can be kept offline and
-// still held by the site owner. The CN=meta certificate is just a backwards
-// compatiable method of carrying a lump of bytes to the client. (We could use
-// a TLS extension just as well, but it's a lot easier for admins to add extra
-// certificates to the chain.)
-
-// A TagMap represents the simple key-value structure that we use. Keys are
-// 32-bit ints. Values are byte strings.
-typedef std::map<uint32, base::StringPiece> TagMap;
-
-// ParseTags parses a list of key-value pairs from |in| to |out| and advances
-// |in| past the data. The key-value pair data is:
-// u16le num_tags
-// u32le tag[num_tags]
-// u16le lengths[num_tags]
-// ...data...
-static bool ParseTags(base::StringPiece* in, TagMap *out) {
- // Many part of Chrome already assume little-endian. This is just to help
- // anyone who should try to port it in the future.
-#if defined(__BYTE_ORDER)
- // Linux check
- COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian);
-#elif defined(__BIG_ENDIAN__)
- // Mac check
- #error assumes little endian
-#endif
-
- uint16 num_tags_16;
- if (in->size() < sizeof(num_tags_16))
- return false;
-
- memcpy(&num_tags_16, in->data(), sizeof(num_tags_16));
- in->remove_prefix(sizeof(num_tags_16));
- unsigned num_tags = num_tags_16;
-
- if (in->size() < 6 * num_tags)
- return false;
-
- const uint32* tags = reinterpret_cast<const uint32*>(in->data());
- const uint16* lens = reinterpret_cast<const uint16*>(
- in->data() + 4*num_tags);
- in->remove_prefix(6*num_tags);
-
- uint32 prev_tag = 0;
- for (unsigned i = 0; i < num_tags; i++) {
- size_t len = lens[i];
- uint32 tag = tags[i];
-
- if (in->size() < len)
- return false;
- // tags must be in ascending order.
- if (i > 0 && prev_tag >= tag)
- return false;
- (*out)[tag] = base::StringPiece(in->data(), len);
- in->remove_prefix(len);
- prev_tag = tag;
- }
-
- return true;
-}
-
-// GetTag extracts the data associated with |tag| in |tags|.
-static bool GetTag(uint32 tag, const TagMap& tags, base::StringPiece* out) {
- TagMap::const_iterator i = tags.find(tag);
- if (i == tags.end())
- return false;
-
- *out = i->second;
- return true;
-}
-
-// kP256SubjectPublicKeyInfoPrefix can be prepended onto a P256 elliptic curve
-// point in X9.62 format in order to make a valid SubjectPublicKeyInfo. The
-// ASN.1 interpretation of these bytes is:
-//
-// 0:d=0 hl=2 l= 89 cons: SEQUENCE
-// 2:d=1 hl=2 l= 19 cons: SEQUENCE
-// 4:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
-// 13:d=2 hl=2 l= 8 prim: OBJECT :prime256v1
-// 23:d=1 hl=2 l= 66 prim: BIT STRING
-static const uint8 kP256SubjectPublicKeyInfoPrefix[] = {
- 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
- 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
- 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
- 0x42, 0x00,
-};
-
-// VerifySignature returns true iff |sig| is a valid signature of
-// |hash| by |pubkey|. The actual implementation is crypto library
-// specific.
-static bool VerifySignature(const base::StringPiece& pubkey,
- const base::StringPiece& sig,
- const base::StringPiece& hash);
-
-#if defined(USE_OPENSSL)
-
-static EVP_PKEY* DecodeX962P256PublicKey(
- const base::StringPiece& pubkey_bytes) {
- // The public key is an X9.62 encoded P256 point.
- if (pubkey_bytes.size() != 1 + 2*32)
- return NULL;
-
- std::string pubkey_spki(
- reinterpret_cast<const char*>(kP256SubjectPublicKeyInfoPrefix),
- sizeof(kP256SubjectPublicKeyInfoPrefix));
- pubkey_spki += pubkey_bytes.as_string();
-
- EVP_PKEY* ret = NULL;
- const unsigned char* der_pubkey =
- reinterpret_cast<const unsigned char*>(pubkey_spki.data());
- d2i_PUBKEY(&ret, &der_pubkey, pubkey_spki.size());
- return ret;
-}
-
-static bool VerifySignature(const base::StringPiece& pubkey,
- const base::StringPiece& sig,
- const base::StringPiece& hash) {
- crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> secpubkey(
- DecodeX962P256PublicKey(pubkey));
- if (!secpubkey.get())
- return false;
-
-
- crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> ec_key(
- EVP_PKEY_get1_EC_KEY(secpubkey.get()));
- if (!ec_key.get())
- return false;
-
- return ECDSA_verify(0, reinterpret_cast<const unsigned char*>(hash.data()),
- hash.size(),
- reinterpret_cast<const unsigned char*>(sig.data()),
- sig.size(), ec_key.get()) == 1;
-}
-
-#else
-
-// DecodeX962P256PublicKey parses an uncompressed, X9.62 format, P256 elliptic
-// curve point from |pubkey_bytes| and returns it as a SECKEYPublicKey.
-static SECKEYPublicKey* DecodeX962P256PublicKey(
- const base::StringPiece& pubkey_bytes) {
- // The public key is an X9.62 encoded P256 point.
- if (pubkey_bytes.size() != 1 + 2*32)
- return NULL;
-
- std::string pubkey_spki(
- reinterpret_cast<const char*>(kP256SubjectPublicKeyInfoPrefix),
- sizeof(kP256SubjectPublicKeyInfoPrefix));
- pubkey_spki += pubkey_bytes.as_string();
-
- SECItem der;
- memset(&der, 0, sizeof(der));
- der.data = reinterpret_cast<uint8*>(const_cast<char*>(pubkey_spki.data()));
- der.len = pubkey_spki.size();
-
- CERTSubjectPublicKeyInfo* spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
- if (!spki)
- return NULL;
- SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
- SECKEY_DestroySubjectPublicKeyInfo(spki);
-
- return public_key;
-}
-
-static bool VerifySignature(const base::StringPiece& pubkey,
- const base::StringPiece& sig,
- const base::StringPiece& hash) {
- SECKEYPublicKey* secpubkey = DecodeX962P256PublicKey(pubkey);
- if (!secpubkey)
- return false;
-
- SECItem sigitem;
- memset(&sigitem, 0, sizeof(sigitem));
- sigitem.data = reinterpret_cast<uint8*>(const_cast<char*>(sig.data()));
- sigitem.len = sig.size();
-
- // |decoded_sigitem| is newly allocated, as is the data that it points to.
- SECItem* decoded_sigitem = DSAU_DecodeDerSigToLen(
- &sigitem, SECKEY_SignatureLen(secpubkey));
-
- if (!decoded_sigitem) {
- SECKEY_DestroyPublicKey(secpubkey);
- return false;
- }
-
- SECItem hashitem;
- memset(&hashitem, 0, sizeof(hashitem));
- hashitem.data = reinterpret_cast<unsigned char*>(
- const_cast<char*>(hash.data()));
- hashitem.len = hash.size();
-
- SECStatus rv = PK11_Verify(secpubkey, decoded_sigitem, &hashitem, NULL);
- SECKEY_DestroyPublicKey(secpubkey);
- SECITEM_FreeItem(decoded_sigitem, PR_TRUE);
- return rv == SECSuccess;
-}
-
-#endif // !defined(USE_OPENSSL)
-
-// These are the tag values that we use. Tags are little-endian on the wire and
-// these values correspond to the ASCII of the name.
-static const uint32 kTagALGO = 0x4f474c41;
-static const uint32 kTagP256 = 0x36353250;
-static const uint32 kTagPUBK = 0x4b425550;
-static const uint32 kTagSIG = 0x474953;
-static const uint32 kTagSPIN = 0x4e495053;
-
-// static
-bool TransportSecurityState::ParseSidePin(
- const base::StringPiece& leaf_spki,
- const base::StringPiece& in_side_info,
- FingerprintVector* out_pub_key_hash) {
- base::StringPiece side_info(in_side_info);
-
- TagMap outer;
- if (!ParseTags(&side_info, &outer))
- return false;
- // trailing data is not allowed
- if (side_info.size())
- return false;
-
- base::StringPiece side_pin_bytes;
- if (!GetTag(kTagSPIN, outer, &side_pin_bytes))
- return false;
-
- bool have_parsed_a_key = false;
- uint8 leaf_spki_hash[crypto::kSHA256Length];
- bool have_leaf_spki_hash = false;
-
- while (side_pin_bytes.size() > 0) {
- TagMap side_pin;
- if (!ParseTags(&side_pin_bytes, &side_pin))
- return false;
-
- base::StringPiece algo, pubkey, sig;
- if (!GetTag(kTagALGO, side_pin, &algo) ||
- !GetTag(kTagPUBK, side_pin, &pubkey) ||
- !GetTag(kTagSIG, side_pin, &sig)) {
- return false;
- }
-
- if (algo.size() != sizeof(kTagP256) ||
- 0 != memcmp(algo.data(), &kTagP256, sizeof(kTagP256))) {
- // We don't support anything but P256 at the moment.
- continue;
- }
-
- if (!have_leaf_spki_hash) {
- crypto::SHA256HashString(
- leaf_spki.as_string(), leaf_spki_hash, sizeof(leaf_spki_hash));
- have_leaf_spki_hash = true;
- }
-
- if (VerifySignature(pubkey, sig, base::StringPiece(
- reinterpret_cast<const char*>(leaf_spki_hash),
- sizeof(leaf_spki_hash)))) {
- SHA1Fingerprint fpr;
- base::SHA1HashBytes(
- reinterpret_cast<const uint8*>(pubkey.data()),
- pubkey.size(),
- fpr.data);
- out_pub_key_hash->push_back(fpr);
- have_parsed_a_key = true;
- }
- }
-
- return have_parsed_a_key;
-}
-
-// This function converts the binary hashes, which we store in
-// |enabled_hosts_|, to a base64 string which we can include in a JSON file.
-static std::string HashedDomainToExternalString(const std::string& hashed) {
- std::string out;
- CHECK(base::Base64Encode(hashed, &out));
- return out;
-}
-
-// This inverts |HashedDomainToExternalString|, above. It turns an external
-// string (from a JSON file) into an internal (binary) string.
-static std::string ExternalStringToHashedDomain(const std::string& external) {
- std::string out;
- if (!base::Base64Decode(external, &out) ||
- out.size() != crypto::kSHA256Length) {
- return std::string();
- }
-
- return out;
-}
-
-static ListValue* SPKIHashesToListValue(const FingerprintVector& hashes) {
- ListValue* pins = new ListValue;
-
- for (FingerprintVector::const_iterator i = hashes.begin();
- i != hashes.end(); ++i) {
- std::string hash_str(reinterpret_cast<const char*>(i->data),
- sizeof(i->data));
- std::string b64;
- base::Base64Encode(hash_str, &b64);
- pins->Append(new StringValue("sha1/" + b64));
- }
-
- return pins;
-}
-
-bool TransportSecurityState::Serialise(std::string* output) {
- DCHECK(CalledOnValidThread());
-
- DictionaryValue toplevel;
- base::Time now = base::Time::Now();
- for (std::map<std::string, DomainState>::const_iterator
- i = enabled_hosts_.begin(); i != enabled_hosts_.end(); ++i) {
- DictionaryValue* state = new DictionaryValue;
- state->SetBoolean("include_subdomains", i->second.include_subdomains);
- state->SetDouble("created", i->second.created.ToDoubleT());
- state->SetDouble("expiry", i->second.expiry.ToDoubleT());
- state->SetDouble("dynamic_spki_hashes_expiry",
- i->second.dynamic_spki_hashes_expiry.ToDoubleT());
-
- switch (i->second.mode) {
- case DomainState::MODE_STRICT:
- state->SetString("mode", "strict");
- break;
- case DomainState::MODE_SPDY_ONLY:
- state->SetString("mode", "spdy-only");
- break;
- case DomainState::MODE_PINNING_ONLY:
- state->SetString("mode", "pinning-only");
- break;
- default:
- NOTREACHED() << "DomainState with unknown mode";
- delete state;
- continue;
- }
-
- state->Set("preloaded_spki_hashes",
- SPKIHashesToListValue(i->second.preloaded_spki_hashes));
-
- if (now < i->second.dynamic_spki_hashes_expiry) {
- state->Set("dynamic_spki_hashes",
- SPKIHashesToListValue(i->second.dynamic_spki_hashes));
- }
-
- toplevel.Set(HashedDomainToExternalString(i->first), state);
- }
-
- base::JSONWriter::WriteWithOptions(&toplevel,
- base::JSONWriter::OPTIONS_PRETTY_PRINT,
- output);
- return true;
-}
-
-bool TransportSecurityState::LoadEntries(const std::string& input,
- bool* dirty) {
- DCHECK(CalledOnValidThread());
-
- enabled_hosts_.clear();
- return Deserialise(input, dirty, &enabled_hosts_);
-}
-
static bool AddHash(const std::string& type_and_base64,
FingerprintVector* out) {
SHA1Fingerprint hash;
@@ -901,114 +488,6 @@
return true;
}
-static void SPKIHashesFromListValue(FingerprintVector* hashes,
- const ListValue& pins) {
- size_t num_pins = pins.GetSize();
- for (size_t i = 0; i < num_pins; ++i) {
- std::string type_and_base64;
- if (pins.GetString(i, &type_and_base64))
- AddHash(type_and_base64, hashes);
- }
-}
-
-// static
-bool TransportSecurityState::Deserialise(
- const std::string& input,
- bool* dirty,
- std::map<std::string, DomainState>* out) {
- scoped_ptr<Value> value(base::JSONReader::Read(input));
- if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY))
- return false;
-
- DictionaryValue* dict_value = reinterpret_cast<DictionaryValue*>(value.get());
- const base::Time current_time(base::Time::Now());
- bool dirtied = false;
-
- for (DictionaryValue::key_iterator i = dict_value->begin_keys();
- i != dict_value->end_keys(); ++i) {
- DictionaryValue* state;
- if (!dict_value->GetDictionaryWithoutPathExpansion(*i, &state))
- continue;
-
- bool include_subdomains;
- std::string mode_string;
- double created;
- double expiry;
- double dynamic_spki_hashes_expiry = 0.0;
-
- if (!state->GetBoolean("include_subdomains", &include_subdomains) ||
- !state->GetString("mode", &mode_string) ||
- !state->GetDouble("expiry", &expiry)) {
- continue;
- }
-
- // Don't fail if this key is not present.
- (void) state->GetDouble("dynamic_spki_hashes_expiry",
- &dynamic_spki_hashes_expiry);
-
- ListValue* pins_list = NULL;
- FingerprintVector preloaded_spki_hashes;
- if (state->GetList("preloaded_spki_hashes", &pins_list))
- SPKIHashesFromListValue(&preloaded_spki_hashes, *pins_list);
-
- FingerprintVector dynamic_spki_hashes;
- if (state->GetList("dynamic_spki_hashes", &pins_list))
- SPKIHashesFromListValue(&dynamic_spki_hashes, *pins_list);
-
- DomainState::Mode mode;
- if (mode_string == "strict") {
- mode = DomainState::MODE_STRICT;
- } else if (mode_string == "spdy-only") {
- mode = DomainState::MODE_SPDY_ONLY;
- } else if (mode_string == "pinning-only") {
- mode = DomainState::MODE_PINNING_ONLY;
- } else {
- LOG(WARNING) << "Unknown TransportSecurityState mode string found: "
- << mode_string;
- continue;
- }
-
- base::Time expiry_time = base::Time::FromDoubleT(expiry);
- base::Time dynamic_spki_hashes_expiry_time =
- base::Time::FromDoubleT(dynamic_spki_hashes_expiry);
- base::Time created_time;
- if (state->GetDouble("created", &created)) {
- created_time = base::Time::FromDoubleT(created);
- } else {
- // We're migrating an old entry with no creation date. Make sure we
- // write the new date back in a reasonable time frame.
- dirtied = true;
- created_time = base::Time::Now();
- }
-
- if (expiry_time <= current_time &&
- dynamic_spki_hashes_expiry_time <= current_time) {
- // Make sure we dirty the state if we drop an entry.
- dirtied = true;
- continue;
- }
-
- std::string hashed = ExternalStringToHashedDomain(*i);
- if (hashed.empty()) {
- dirtied = true;
- continue;
- }
-
- DomainState new_state;
- new_state.mode = mode;
- new_state.created = created_time;
- new_state.expiry = expiry_time;
- new_state.include_subdomains = include_subdomains;
- new_state.preloaded_spki_hashes = preloaded_spki_hashes;
- new_state.dynamic_spki_hashes = dynamic_spki_hashes;
- new_state.dynamic_spki_hashes_expiry = dynamic_spki_hashes_expiry_time;
- (*out)[hashed] = new_state;
- }
-
- *dirty = dirtied;
- return true;
-}
-
TransportSecurityState::~TransportSecurityState() {
}
Ryan Sleevi 2012/04/26 19:21:12 nit: move } to line 491
palmer 2012/04/27 23:52:34 Done.
@@ -1122,11 +601,11 @@
out->include_subdomains = entries[j].include_subdomains;
*ret = true;
if (!entries[j].https_required)
- out->mode = TransportSecurityState::DomainState::MODE_PINNING_ONLY;
+ out->upgrade_mode = TransportSecurityState::DomainState::MODE_DEFAULT;
if (entries[j].pins.required_hashes) {
const char* const* hash = entries[j].pins.required_hashes;
while (*hash) {
- bool ok = AddHash(*hash, &out->preloaded_spki_hashes);
+ bool ok = AddHash(*hash, &out->static_spki_hashes);
DCHECK(ok) << " failed to parse " << *hash;
hash++;
}
@@ -1134,7 +613,7 @@
if (entries[j].pins.excluded_hashes) {
const char* const* hash = entries[j].pins.excluded_hashes;
while (*hash) {
- bool ok = AddHash(*hash, &out->bad_preloaded_spki_hashes);
+ bool ok = AddHash(*hash, &out->bad_static_spki_hashes);
DCHECK(ok) << " failed to parse " << *hash;
hash++;
}
@@ -1177,7 +656,7 @@
// static
bool TransportSecurityState::IsGooglePinnedProperty(const std::string& host,
- bool sni_available) {
+ bool sni_enabled) {
std::string canonicalized_host = CanonicalizeHost(host);
const struct HSTSPreload* entry =
GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
@@ -1185,7 +664,7 @@
if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
return true;
- if (sni_available) {
+ if (sni_enabled) {
entry = GetHSTSPreload(canonicalized_host, kPreloadedSNISTS,
kNumPreloadedSNISTS);
if (entry && entry->pins.required_hashes == kGoogleAcceptableCerts)
@@ -1215,16 +694,13 @@
entry->second_level_domain_name, DOMAIN_NUM_EVENTS);
}
-// IsPreloadedSTS returns true if the canonicalized hostname should always be
-// considered to have STS enabled.
-bool TransportSecurityState::IsPreloadedSTS(
+bool TransportSecurityState::GetStaticDomainState(
const std::string& canonicalized_host,
- bool sni_available,
+ bool sni_enabled,
DomainState* out) {
DCHECK(CalledOnValidThread());
- out->preloaded = true;
- out->mode = DomainState::MODE_STRICT;
+ out->upgrade_mode = DomainState::MODE_FORCE_HTTPS;
out->include_subdomains = false;
for (size_t i = 0; canonicalized_host[i]; i += canonicalized_host[i] + 1) {
@@ -1235,7 +711,6 @@
if (forced_hosts_.find(hashed_host) != forced_hosts_.end()) {
*out = forced_hosts_[hashed_host];
out->domain = DNSDomainToString(host_sub_chunk);
- out->preloaded = true;
return true;
}
bool ret;
@@ -1243,7 +718,7 @@
&ret)) {
return ret;
}
- if (sni_available &&
+ if (sni_enabled &&
HasPreload(kPreloadedSNISTS, kNumPreloadedSNISTS, canonicalized_host, i,
out, &ret)) {
return ret;
@@ -1269,33 +744,31 @@
}
TransportSecurityState::DomainState::DomainState()
- : mode(MODE_STRICT),
+ : upgrade_mode(MODE_FORCE_HTTPS),
created(base::Time::Now()),
- include_subdomains(false),
- preloaded(false) {
+ include_subdomains(false) {
}
TransportSecurityState::DomainState::~DomainState() {
}
bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted(
- const FingerprintVector& hashes) {
-
- if (HashesIntersect(bad_preloaded_spki_hashes, hashes)) {
+ const FingerprintVector& hashes) const {
+ 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_preloaded_spki_hashes);
+ << HashesToBase64String(bad_static_spki_hashes);
return false;
}
- if (!(dynamic_spki_hashes.empty() && preloaded_spki_hashes.empty()) &&
+ if (!(dynamic_spki_hashes.empty() && static_spki_hashes.empty()) &&
!HashesIntersect(dynamic_spki_hashes, hashes) &&
- !HashesIntersect(preloaded_spki_hashes, hashes)) {
+ !HashesIntersect(static_spki_hashes, hashes)) {
LOG(ERROR) << "Rejecting public key chain for domain " << domain
<< ". Validated chain: " << HashesToBase64String(hashes)
<< ", expected: " << HashesToBase64String(dynamic_spki_hashes)
- << " or: " << HashesToBase64String(preloaded_spki_hashes);
+ << " or: " << HashesToBase64String(static_spki_hashes);
return false;
}
@@ -1303,20 +776,14 @@
return true;
}
-bool TransportSecurityState::DomainState::IsMoreStrict(
- const TransportSecurityState::DomainState& other) {
- if (this->dynamic_spki_hashes.empty() && !other.dynamic_spki_hashes.empty())
- return false;
-
- if (!this->include_subdomains && other.include_subdomains)
- return false;
-
- return true;
+bool TransportSecurityState::DomainState::ShouldRedirectHTTPToHTTPS() const {
+ return upgrade_mode == MODE_FORCE_HTTPS;
}
-bool TransportSecurityState::DomainState::ShouldRedirectHTTPToHTTPS()
- const {
- return mode == MODE_STRICT;
+bool TransportSecurityState::DomainState::HasPins() const {
+ return static_spki_hashes.size() > 0 ||
+ bad_static_spki_hashes.size() > 0 ||
+ dynamic_spki_hashes.size() > 0;
}
} // namespace

Powered by Google App Engine
This is Rietveld 408576698