Index: net/base/transport_security_state.cc |
=================================================================== |
--- net/base/transport_security_state.cc (revision 80114) |
+++ net/base/transport_security_state.cc (working copy) |
@@ -4,6 +4,8 @@ |
#include "net/base/transport_security_state.h" |
+#include <set> |
+ |
#include "base/base64.h" |
#include "base/json/json_reader.h" |
#include "base/json/json_writer.h" |
@@ -17,6 +19,8 @@ |
#include "base/values.h" |
#include "googleurl/src/gurl.h" |
#include "net/base/dns_util.h" |
+#include "net/base/x509_cert_types.h" |
+#include "net/base/x509_certificate.h" |
namespace net { |
@@ -32,6 +36,9 @@ |
if (canonicalized_host.empty()) |
return; |
+ // TODO(cevans) -- we likely want to permit a host to override a built-in, |
+ // for at least the case where the override is stricter (i.e. includes |
+ // subdomains, or includes cert locks). |
bool temp; |
if (IsPreloadedSTS(canonicalized_host, &temp)) |
return; |
@@ -128,6 +135,40 @@ |
return false; |
} |
+bool TransportSecurityState::IsAcceptableCertificate(const std::string& host, |
+ X509Certificate* cert) { |
+ DomainState state; |
+ if (!IsEnabledForHost(&state, host)) |
+ return true; |
+ |
+ if (state.cert_locks.empty()) |
+ return true; |
+ |
+ std::set<std::string> fingerprints; |
+ X509Certificate::OSCertHandles cert_chain; |
+ X509Certificate::GetCertChainFromCert(cert->os_cert_handle(), &cert_chain); |
+ { |
+ X509Certificate::OSCertHandles::const_iterator i; |
+ for (i = cert_chain.begin(); i != cert_chain.end(); ++i) { |
+ net::SHA1Fingerprint fingerprint = |
+ X509Certificate::CalculateFingerprint(*i); |
+ std::string hash; |
+ for (size_t i = 0; i < sizeof(fingerprint.data); ++i) |
+ hash += StringPrintf("%02X", fingerprint.data[i]); |
abarth-chromium
2011/04/04 22:49:36
This code looks pretty low-level. Why can't SHA1F
|
+ fingerprints.insert(hash); |
+ } |
+ } |
+ X509Certificate::DestroyCertChain(&cert_chain); |
+ std::vector<std::string>::const_iterator locks_iter; |
+ for (locks_iter = state.cert_locks.begin(); |
+ locks_iter != state.cert_locks.end(); ++locks_iter) { |
+ std::string cert_lock = *locks_iter; |
+ if (fingerprints.find(cert_lock) != fingerprints.end()) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
void TransportSecurityState::DeleteSince(const base::Time& time) { |
bool dirtied = false; |
@@ -312,6 +353,14 @@ |
continue; |
} |
+ ListValue* locks = new ListValue; |
+ std::vector<std::string>::const_iterator lock_strings; |
+ for (lock_strings = i->second.cert_locks.begin(); |
+ lock_strings != i->second.cert_locks.end(); |
+ ++lock_strings) |
+ locks->Append(new StringValue(*lock_strings)); |
+ state->Set("cert_locks", locks); |
abarth-chromium
2011/04/04 22:49:36
Again, pin is probably a better term.
|
+ |
toplevel.Set(HashedDomainToExternalString(i->first), state); |
} |
@@ -349,6 +398,17 @@ |
continue; |
} |
+ ListValue* locks_list; |
+ std::vector<std::string> cert_locks; |
+ if (state->GetList("cert_locks", &locks_list)) { |
+ size_t num_locks = locks_list->GetSize(); |
+ for (size_t i = 0; i < num_locks; ++i) { |
+ std::string lock_string; |
+ if (locks_list->GetString(i, &lock_string)) |
+ cert_locks.push_back(lock_string); |
+ } |
+ } |
+ |
DomainState::Mode mode; |
if (mode_string == "strict") { |
mode = DomainState::MODE_STRICT; |
@@ -380,14 +440,17 @@ |
} |
std::string hashed = ExternalStringToHashedDomain(*i); |
- if (hashed.empty()) |
+ 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.cert_locks = cert_locks; |
enabled_hosts_[hashed] = new_state; |
} |