Certificate Transparency: Wire the TreeStateTracker up.
This change puts into use the TreeStateTracker class by wiring it to:
* A global STHDistributor for receiving fresh STHs via the component
updater.
* The per-profile CTVerifier for receiving notification of verified
SCTs that should be checked for inclusion.
As discussed with sorin and rsleevi, the wiring of the STHSetComponentInstaller
is via a globally-accessible STHDistributor, created by the IOThread.
BUG=613501
Review-Url: https://codereview.chromium.org/2014573002
Cr-Commit-Position: refs/heads/master@{#397096}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index dfc340a..f079086b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -117,6 +117,7 @@
"//components/browser_sync/common",
"//components/captive_portal",
"//components/certificate_reporting",
+ "//components/certificate_transparency",
"//components/cloud_devices/common",
"//components/component_updater",
"//components/content_settings/content/common",
diff --git a/chrome/browser/component_updater/sth_set_component_installer.cc b/chrome/browser/component_updater/sth_set_component_installer.cc
index 401a79f..c4f2ba5 100644
--- a/chrome/browser/component_updater/sth_set_component_installer.cc
+++ b/chrome/browser/component_updater/sth_set_component_installer.cc
@@ -15,6 +15,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "base/version.h"
+#include "chrome/browser/net/sth_distributor_provider.h"
#include "components/component_updater/component_updater_paths.h"
#include "components/safe_json/safe_json_parser.h"
#include "content/public/browser/browser_thread.h"
@@ -49,8 +50,8 @@
const char kSTHSetFetcherManifestName[] = "Signed Tree Heads";
STHSetComponentInstallerTraits::STHSetComponentInstallerTraits(
- std::unique_ptr<net::ct::STHObserver> sth_observer)
- : sth_observer_(std::move(sth_observer)) {}
+ net::ct::STHObserver* sth_observer)
+ : sth_observer_(sth_observer) {}
STHSetComponentInstallerTraits::~STHSetComponentInstallerTraits() {}
@@ -168,7 +169,7 @@
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&net::ct::STHObserver::NewSTHObserved,
- base::Unretained(sth_observer_.get()), signed_tree_head));
+ base::Unretained(sth_observer_), signed_tree_head));
}
void STHSetComponentInstallerTraits::OnJsonParseError(
@@ -182,14 +183,13 @@
const base::FilePath& user_data_dir) {
DVLOG(1) << "Registering STH Set fetcher component.";
- // TODO(eranm): The next step in auditing CT logs (crbug.com/506227) is to
- // pass the distributor to the IOThread so it can be used in a per-profile
- // context for checking inclusion of SCTs.
- std::unique_ptr<net::ct::STHDistributor> distributor(
- new net::ct::STHDistributor());
+ net::ct::STHDistributor* distributor =
+ chrome_browser_net::GetGlobalSTHDistributor();
+ // The global STHDistributor should have been created by this point.
+ DCHECK(distributor);
std::unique_ptr<ComponentInstallerTraits> traits(
- new STHSetComponentInstallerTraits(std::move(distributor)));
+ new STHSetComponentInstallerTraits(distributor));
// |cus| will take ownership of |installer| during installer->Register(cus).
DefaultComponentInstaller* installer =
new DefaultComponentInstaller(std::move(traits));
diff --git a/chrome/browser/component_updater/sth_set_component_installer.h b/chrome/browser/component_updater/sth_set_component_installer.h
index 4223aa37..1279706 100644
--- a/chrome/browser/component_updater/sth_set_component_installer.h
+++ b/chrome/browser/component_updater/sth_set_component_installer.h
@@ -40,8 +40,7 @@
class STHSetComponentInstallerTraits : public ComponentInstallerTraits {
public:
// The |sth_distributor| will be notified each time a new STH is observed.
- explicit STHSetComponentInstallerTraits(
- std::unique_ptr<net::ct::STHObserver> sth_observer);
+ explicit STHSetComponentInstallerTraits(net::ct::STHObserver* sth_observer);
~STHSetComponentInstallerTraits() override;
private:
@@ -73,7 +72,10 @@
// STH parsing failed - do nothing.
void OnJsonParseError(const std::string& log_id, const std::string& error);
- std::unique_ptr<net::ct::STHObserver> sth_observer_;
+ // The observer is not owned by this class, so the code creating an instance
+ // of this class is expected to ensure the STHObserver lives as long as
+ // this class does. Typically the observer provided will be a global.
+ net::ct::STHObserver* sth_observer_;
DISALLOW_COPY_AND_ASSIGN(STHSetComponentInstallerTraits);
};
diff --git a/chrome/browser/component_updater/sth_set_component_installer_unittest.cc b/chrome/browser/component_updater/sth_set_component_installer_unittest.cc
index 5b6b101..d965fc0 100644
--- a/chrome/browser/component_updater/sth_set_component_installer_unittest.cc
+++ b/chrome/browser/component_updater/sth_set_component_installer_unittest.cc
@@ -44,9 +44,8 @@
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- std::unique_ptr<StoringSTHObserver> observer(new StoringSTHObserver());
- observer_ = observer.get();
- traits_.reset(new STHSetComponentInstallerTraits(std::move(observer)));
+ observer_.reset(new StoringSTHObserver());
+ traits_.reset(new STHSetComponentInstallerTraits(observer_.get()));
}
void WriteSTHToFile(const std::string& sth_json,
@@ -82,8 +81,10 @@
content::TestBrowserThreadBundle thread_bundle_;
base::ScopedTempDir temp_dir_;
+ std::unique_ptr<StoringSTHObserver> observer_;
+ // |traits_| should be destroyed before the |observer_| as it holds a pointer
+ // to it.
std::unique_ptr<STHSetComponentInstallerTraits> traits_;
- StoringSTHObserver* observer_;
safe_json::TestingJsonParser::ScopedFactoryOverride factory_override_;
private:
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 5210f4b8..063d370 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -39,10 +39,12 @@
#include "chrome/browser/net/chrome_network_delegate.h"
#include "chrome/browser/net/dns_probe_service.h"
#include "chrome/browser/net/proxy_service_factory.h"
+#include "chrome/browser/net/sth_distributor_provider.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
+#include "components/certificate_transparency/tree_state_tracker.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
#include "components/data_usage/core/data_use_aggregator.h"
#include "components/data_usage/core/data_use_amortizer.h"
@@ -72,6 +74,8 @@
#include "net/cert/ct_verifier.h"
#include "net/cert/multi_log_ct_verifier.h"
#include "net/cert/multi_threaded_cert_verifier.h"
+#include "net/cert/sth_distributor.h"
+#include "net/cert/sth_observer.h"
#include "net/cookies/cookie_store.h"
#include "net/dns/host_cache.h"
#include "net/dns/host_resolver.h"
@@ -393,6 +397,9 @@
g_browser_process->metrics_service()->GetDataUseForwardingCallback();
}
+ chrome_browser_net::SetGlobalSTHDistributor(
+ std::unique_ptr<net::ct::STHDistributor>(new net::ct::STHDistributor()));
+
BrowserThread::SetDelegate(BrowserThread::IO, this);
}
@@ -403,6 +410,10 @@
pref_proxy_config_tracker_->DetachFromPrefService();
DCHECK(!globals_);
+
+ // Destroy the old distributor to check that the observers list it holds is
+ // empty.
+ chrome_browser_net::SetGlobalSTHDistributor(nullptr);
}
IOThread::Globals* IOThread::globals() {
@@ -607,6 +618,13 @@
// Add built-in logs
ct_verifier->AddLogs(globals_->ct_logs);
+ ct_tree_tracker_.reset(
+ new certificate_transparency::TreeStateTracker(globals_->ct_logs));
+ // Register the ct_tree_tracker_ as observer for new STHs.
+ RegisterSTHObserver(ct_tree_tracker_.get());
+ // Register the ct_tree_tracker_ as observer for verified SCTs.
+ globals_->cert_transparency_verifier->SetObserver(ct_tree_tracker_.get());
+
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466432
// is fixed.
tracked_objects::ScopedTracker tracking_profile10(
@@ -766,6 +784,14 @@
system_url_request_context_getter_ = NULL;
+ // Unlink the ct_tree_tracker_ from the global cert_transparency_verifier
+ // and unregister it from new STH notifications so it will take no actions
+ // on anything observed during CleanUp process.
+ globals()->cert_transparency_verifier->SetObserver(nullptr);
+ UnregisterSTHObserver(ct_tree_tracker_.get());
+
+ ct_tree_tracker_.reset();
+
// Release objects that the net::URLRequestContext could have been pointing
// to.
@@ -917,6 +943,14 @@
globals()->host_resolver->SetDnsClientEnabled(*dns_client_enabled_);
}
+void IOThread::RegisterSTHObserver(net::ct::STHObserver* observer) {
+ chrome_browser_net::GetGlobalSTHDistributor()->RegisterObserver(observer);
+}
+
+void IOThread::UnregisterSTHObserver(net::ct::STHObserver* observer) {
+ chrome_browser_net::GetGlobalSTHDistributor()->UnregisterObserver(observer);
+}
+
// static
net::URLRequestContext* IOThread::ConstructSystemRequestContext(
IOThread::Globals* globals,
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h
index 2f1103d4..d6fff07 100644
--- a/chrome/browser/io_thread.h
+++ b/chrome/browser/io_thread.h
@@ -44,6 +44,10 @@
}
#endif // BUILDFLAG(ANDROID_JAVA_UI)
+namespace certificate_transparency {
+class TreeStateTracker;
+}
+
namespace chrome_browser_net {
class DnsProbeService;
}
@@ -81,6 +85,11 @@
class URLRequestContext;
class URLRequestContextGetter;
class URLRequestJobFactory;
+
+namespace ct {
+class STHObserver;
+}
+
} // namespace net
namespace net_log {
@@ -223,6 +232,12 @@
// Returns the callback for updating data use prefs.
const metrics::UpdateUsagePrefCallbackType& GetMetricsDataUseForwarder();
+ // Registers the |observer| for new STH notifications.
+ void RegisterSTHObserver(net::ct::STHObserver* observer);
+
+ // Un-registers the |observer|.
+ void UnregisterSTHObserver(net::ct::STHObserver* observer);
+
private:
// Provide SystemURLRequestContextGetter with access to
// InitSystemRequestContext().
@@ -305,6 +320,8 @@
// Observer that logs network changes to the ChromeNetLog.
std::unique_ptr<net::LoggingNetworkChangeObserver> network_change_observer_;
+ std::unique_ptr<certificate_transparency::TreeStateTracker> ct_tree_tracker_;
+
BooleanPrefMember system_enable_referrers_;
BooleanPrefMember dns_client_enabled_;
diff --git a/chrome/browser/net/sth_distributor_provider.cc b/chrome/browser/net/sth_distributor_provider.cc
new file mode 100644
index 0000000..97a109e
--- /dev/null
+++ b/chrome/browser/net/sth_distributor_provider.cc
@@ -0,0 +1,27 @@
+// Copyright 2016 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 "chrome/browser/net/sth_distributor_provider.h"
+
+#include "base/lazy_instance.h"
+#include "net/cert/sth_distributor.h"
+
+namespace chrome_browser_net {
+
+namespace {
+base::LazyInstance<std::unique_ptr<net::ct::STHDistributor>>
+ global_sth_distributor = LAZY_INSTANCE_INITIALIZER;
+} // namespace
+
+void SetGlobalSTHDistributor(
+ std::unique_ptr<net::ct::STHDistributor> distributor) {
+ global_sth_distributor.Get().swap(distributor);
+}
+
+net::ct::STHDistributor* GetGlobalSTHDistributor() {
+ CHECK(global_sth_distributor.Get());
+ return global_sth_distributor.Get().get();
+}
+
+} // namespace chrome_browser_net
diff --git a/chrome/browser/net/sth_distributor_provider.h b/chrome/browser/net/sth_distributor_provider.h
new file mode 100644
index 0000000..b8e36676
--- /dev/null
+++ b/chrome/browser/net/sth_distributor_provider.h
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+#ifndef CHROME_BROWSER_NET_STH_DISTRIBUTOR_PROVIDER_H_
+#define CHROME_BROWSER_NET_STH_DISTRIBUTOR_PROVIDER_H_
+
+#include <memory>
+
+namespace net {
+
+namespace ct {
+class STHDistributor;
+} // namespace ct
+
+} // namespace net
+
+namespace chrome_browser_net {
+
+void SetGlobalSTHDistributor(
+ std::unique_ptr<net::ct::STHDistributor> distributor);
+net::ct::STHDistributor* GetGlobalSTHDistributor();
+
+} // namespace chrome_browser_net
+
+#endif // CHROME_BROWSER_NET_STH_DISTRIBUTOR_PROVIDER_H_
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index a3bda6c..11c06609c1 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -58,6 +58,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/about_handler/about_protocol_handler.h"
+#include "components/certificate_transparency/tree_state_tracker.h"
#include "components/content_settings/core/browser/content_settings_provider.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
@@ -81,6 +82,7 @@
#include "content/public/browser/resource_context.h"
#include "net/base/keygen_handler.h"
#include "net/cert/cert_verifier.h"
+#include "net/cert/ct_log_verifier.h"
#include "net/cert/multi_log_ct_verifier.h"
#include "net/cookies/canonical_cookie.h"
#include "net/http/http_network_session.h"
@@ -1150,7 +1152,16 @@
new net::MultiLogCTVerifier());
ct_verifier->AddLogs(io_thread_globals->ct_logs);
main_request_context_->set_cert_transparency_verifier(ct_verifier.get());
+
+ ct_tree_tracker_.reset(new certificate_transparency::TreeStateTracker(
+ io_thread_globals->ct_logs));
+ ct_verifier->SetObserver(ct_tree_tracker_.get());
+
cert_transparency_verifier_ = std::move(ct_verifier);
+ io_thread->RegisterSTHObserver(ct_tree_tracker_.get());
+ ct_tree_tracker_unregistration_ =
+ base::Bind(&IOThread::UnregisterSTHObserver, base::Unretained(io_thread),
+ ct_tree_tracker_.get());
InitializeInternal(std::move(network_delegate), profile_params_.get(),
protocol_handlers, std::move(request_interceptors));
@@ -1299,6 +1310,12 @@
void ProfileIOData::DestroyResourceContext() {
resource_context_.reset();
+ // Prevent the cert_transparency_observer_ from getting any more
+ // notifications by severing the link between it and the
+ // cert_transparency_verifier_ and unregistering it from new STH
+ // notifications.
+ cert_transparency_verifier_->SetObserver(nullptr);
+ ct_tree_tracker_unregistration_.Run();
}
std::unique_ptr<net::HttpNetworkSession>
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h
index 116d98b..6b00aa8 100644
--- a/chrome/browser/profiles/profile_io_data.h
+++ b/chrome/browser/profiles/profile_io_data.h
@@ -54,6 +54,10 @@
class ResourcePrefetchPredictorObserver;
}
+namespace certificate_transparency {
+class TreeStateTracker;
+}
+
namespace content_settings {
class CookieSettings;
}
@@ -610,6 +614,10 @@
mutable DevToolsNetworkControllerHandle network_controller_handle_;
+ mutable std::unique_ptr<certificate_transparency::TreeStateTracker>
+ ct_tree_tracker_;
+ mutable base::Closure ct_tree_tracker_unregistration_;
+
const Profile::ProfileType profile_type_;
DISALLOW_COPY_AND_ASSIGN(ProfileIOData);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 8698d038..c446ccf2 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2183,6 +2183,8 @@
'browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h',
'browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.cc',
'browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h',
+ 'browser/net/sth_distributor_provider.cc',
+ 'browser/net/sth_distributor_provider.h',
'browser/net/timed_cache.cc',
'browser/net/timed_cache.h',
'browser/net/url_info.cc',
@@ -3327,6 +3329,7 @@
'../components/components.gyp:autofill_content_browser',
'../components/components.gyp:browsing_data',
'../components/components.gyp:certificate_reporting',
+ '../components/components.gyp:certificate_transparency',
'../components/components.gyp:contextual_search_browser',
'../components/components.gyp:cookie_config',
'../components/components.gyp:data_reduction_proxy_content_browser',