diff options
author | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-10 04:16:25 +0000 |
---|---|---|
committer | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-10 04:16:25 +0000 |
commit | 62635c758fce2b22a1cf5acdc57579bb5801b2e3 (patch) | |
tree | 4085d65bbf01078b722cbcef5930e157d7f793be /net | |
parent | d7f6e73fb05992d784e55df2a1ed25924b5d79f3 (diff) | |
download | chromium_src-62635c758fce2b22a1cf5acdc57579bb5801b2e3.zip chromium_src-62635c758fce2b22a1cf5acdc57579bb5801b2e3.tar.gz chromium_src-62635c758fce2b22a1cf5acdc57579bb5801b2e3.tar.bz2 |
Define a new CertDatabase::Observer abstract class which can be implemented by classes which wish to be notified when a new ssl client cert is added.
Register SpdySessionPool, SocketPoolManager and SSLClientAuthCache as observers.
Notify observers in CertDatabase::AddUserCert();
BUG=75326
Review URL: http://codereview.chromium.org/6588014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77599 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/cert_database.cc | 35 | ||||
-rw-r--r-- | net/base/cert_database.h | 31 | ||||
-rw-r--r-- | net/base/cert_database_mac.cc | 2 | ||||
-rw-r--r-- | net/base/cert_database_nss.cc | 1 | ||||
-rw-r--r-- | net/base/cert_database_win.cc | 1 | ||||
-rw-r--r-- | net/base/ssl_client_auth_cache.cc | 10 | ||||
-rw-r--r-- | net/base/ssl_client_auth_cache.h | 7 | ||||
-rw-r--r-- | net/base/ssl_client_auth_cache_unittest.cc | 6 | ||||
-rw-r--r-- | net/socket/client_socket_factory.cc | 18 | ||||
-rw-r--r-- | net/socket/client_socket_pool_manager.cc | 17 | ||||
-rw-r--r-- | net/socket/client_socket_pool_manager.h | 7 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.cc | 6 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.h | 7 |
13 files changed, 133 insertions, 15 deletions
diff --git a/net/base/cert_database.cc b/net/base/cert_database.cc index 313a6dd0..f049aca 100644 --- a/net/base/cert_database.cc +++ b/net/base/cert_database.cc @@ -4,6 +4,8 @@ #include "net/base/cert_database.h" +#include "base/observer_list_threadsafe.h" +#include "base/singleton.h" #include "net/base/x509_certificate.h" namespace net { @@ -16,4 +18,37 @@ CertDatabase::ImportCertFailure::ImportCertFailure( CertDatabase::ImportCertFailure::~ImportCertFailure() { } +// CertDatabaseNotifier notifies registered observers when new user certificates +// are added to the database. +class CertDatabaseNotifier { + public: + CertDatabaseNotifier() + : observer_list_(new ObserverListThreadSafe<CertDatabase::Observer>) { + } + + static CertDatabaseNotifier* GetInstance() { + return Singleton<CertDatabaseNotifier>::get(); + } + + friend struct DefaultSingletonTraits<CertDatabaseNotifier>; + friend class CertDatabase; + + private: + const scoped_refptr<ObserverListThreadSafe<CertDatabase::Observer> > + observer_list_; +}; + +void CertDatabase::AddObserver(Observer* observer) { + CertDatabaseNotifier::GetInstance()->observer_list_->AddObserver(observer); +} + +void CertDatabase::RemoveObserver(Observer* observer) { + CertDatabaseNotifier::GetInstance()->observer_list_->RemoveObserver(observer); +} + +void CertDatabase::NotifyObserversOfUserCertAdded(X509Certificate* cert) { + CertDatabaseNotifier::GetInstance()->observer_list_->Notify( + &CertDatabase::Observer::OnUserCertAdded, make_scoped_refptr(cert)); +} + } // namespace net diff --git a/net/base/cert_database.h b/net/base/cert_database.h index 0e7bdbd..5760dff 100644 --- a/net/base/cert_database.h +++ b/net/base/cert_database.h @@ -31,6 +31,25 @@ typedef std::vector<scoped_refptr<X509Certificate> > CertificateList; class CertDatabase { public: + + // A CertDatabase::Observer will be notified every time a new user + // certificate is added to the database. Observers can register themselves + // via CertDatabase::AddObserver, and can un-register with + // CertDatabase::RemoveObserver. + class Observer { + public: + virtual ~Observer() {} + + // Will be called when a new user certificate is added. + virtual void OnUserCertAdded(X509Certificate* cert) = 0; + + protected: + Observer() {} + + private: + DISALLOW_COPY_AND_ASSIGN(Observer); + }; + // Stores per-certificate error codes for import failures. struct ImportCertFailure { public: @@ -141,7 +160,19 @@ class CertDatabase { bool IsReadOnly(const X509Certificate* cert) const; #endif + // Registers |observer| to receive notifications of certificate changes. The + // thread on which this is called is the thread on which |observer| will be + // called back with notifications. + static void AddObserver(Observer* observer); + + // Unregisters |observer| from receiving notifications. This must be called + // on the same thread on which AddObserver() was called. + static void RemoveObserver(Observer* observer); + private: + // Broadcasts a notification to all registered observers. + static void NotifyObserversOfUserCertAdded(X509Certificate* cert); + DISALLOW_COPY_AND_ASSIGN(CertDatabase); }; diff --git a/net/base/cert_database_mac.cc b/net/base/cert_database_mac.cc index e90a712..66828ad 100644 --- a/net/base/cert_database_mac.cc +++ b/net/base/cert_database_mac.cc @@ -48,6 +48,8 @@ int CertDatabase::AddUserCert(X509Certificate* cert) { } switch (err) { case noErr: + CertDatabase::NotifyObserversOfUserCertAdded(cert); + // Fall through. case errSecDuplicateItem: return OK; default: diff --git a/net/base/cert_database_nss.cc b/net/base/cert_database_nss.cc index 7e1abaa9..60cc4bc 100644 --- a/net/base/cert_database_nss.cc +++ b/net/base/cert_database_nss.cc @@ -89,6 +89,7 @@ int CertDatabase::AddUserCert(X509Certificate* cert_obj) { return ERR_ADD_USER_CERT_FAILED; } PK11_FreeSlot(slot); + CertDatabase::NotifyObserversOfUserCertAdded(cert_obj); return OK; } diff --git a/net/base/cert_database_win.cc b/net/base/cert_database_win.cc index 4c5e8df..038fc1c 100644 --- a/net/base/cert_database_win.cc +++ b/net/base/cert_database_win.cc @@ -50,6 +50,7 @@ int CertDatabase::AddUserCert(X509Certificate* cert) { if (!added) return ERR_ADD_USER_CERT_FAILED; + CertDatabase::NotifyObserversOfUserCertAdded(cert); return OK; } diff --git a/net/base/ssl_client_auth_cache.cc b/net/base/ssl_client_auth_cache.cc index cdaad7f..ecfada8 100644 --- a/net/base/ssl_client_auth_cache.cc +++ b/net/base/ssl_client_auth_cache.cc @@ -9,9 +9,13 @@ namespace net { -SSLClientAuthCache::SSLClientAuthCache() {} +SSLClientAuthCache::SSLClientAuthCache() { + CertDatabase::AddObserver(this); +} -SSLClientAuthCache::~SSLClientAuthCache() {} +SSLClientAuthCache::~SSLClientAuthCache() { + CertDatabase::RemoveObserver(this); +} bool SSLClientAuthCache::Lookup( const std::string& server, @@ -37,7 +41,7 @@ void SSLClientAuthCache::Remove(const std::string& server) { cache_.erase(server); } -void SSLClientAuthCache::Clear() { +void SSLClientAuthCache::OnUserCertAdded(X509Certificate* cert) { cache_.clear(); } diff --git a/net/base/ssl_client_auth_cache.h b/net/base/ssl_client_auth_cache.h index b37164a..6cc1d12 100644 --- a/net/base/ssl_client_auth_cache.h +++ b/net/base/ssl_client_auth_cache.h @@ -10,6 +10,7 @@ #include <map> #include "base/ref_counted.h" +#include "net/base/cert_database.h" namespace net { @@ -22,7 +23,7 @@ class X509Certificate; // // TODO(wtc): This class is based on FtpAuthCache. We can extract the common // code to a template class. -class SSLClientAuthCache { +class SSLClientAuthCache : public CertDatabase::Observer { public: SSLClientAuthCache(); ~SSLClientAuthCache(); @@ -44,8 +45,8 @@ class SSLClientAuthCache { // Remove the client certificate for |server| from the cache, if one exists. void Remove(const std::string& server); - // Removes all cache entries. - void Clear(); + // CertDatabase::Observer methods: + virtual void OnUserCertAdded(X509Certificate* cert); private: typedef std::string AuthCacheKey; diff --git a/net/base/ssl_client_auth_cache_unittest.cc b/net/base/ssl_client_auth_cache_unittest.cc index 144e114..6408887 100644 --- a/net/base/ssl_client_auth_cache_unittest.cc +++ b/net/base/ssl_client_auth_cache_unittest.cc @@ -137,8 +137,8 @@ TEST(SSLClientAuthCacheTest, LookupNullPreference) { EXPECT_EQ(NULL, cached_cert.get()); } -// Check that the Clear() method removes all cache entries. -TEST(SSLClientAuthCacheTest, Clear) { +// Check that the OnUserCertAdded() method removes all cache entries. +TEST(SSLClientAuthCacheTest, OnUserCertAdded) { SSLClientAuthCache cache; base::Time start_date = base::Time::Now(); base::Time expiration_date = start_date + base::TimeDelta::FromDays(1); @@ -161,7 +161,7 @@ TEST(SSLClientAuthCacheTest, Clear) { EXPECT_TRUE(cache.Lookup(server2, &cached_cert)); EXPECT_EQ(NULL, cached_cert.get()); - cache.Clear(); + cache.OnUserCertAdded(NULL); // Check that we no longer have entries for either server. EXPECT_FALSE(cache.Lookup(server1, &cached_cert)); diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc index 2eb90e5..e8e6f2f 100644 --- a/net/socket/client_socket_factory.cc +++ b/net/socket/client_socket_factory.cc @@ -6,6 +6,7 @@ #include "base/lazy_instance.h" #include "build/build_config.h" +#include "net/base/cert_database.h" #include "net/socket/client_socket_handle.h" #if defined(OS_WIN) #include "net/socket/ssl_client_socket_nss.h" @@ -23,12 +24,27 @@ namespace net { +class X509Certificate; + namespace { bool g_use_system_ssl = false; -class DefaultClientSocketFactory : public ClientSocketFactory { +class DefaultClientSocketFactory : public ClientSocketFactory, + public CertDatabase::Observer { public: + DefaultClientSocketFactory() { + CertDatabase::AddObserver(this); + } + + virtual ~DefaultClientSocketFactory() { + CertDatabase::RemoveObserver(this); + } + + virtual void OnUserCertAdded(X509Certificate* cert) { + ClearSSLSessionCache(); + } + virtual ClientSocket* CreateTCPClientSocket( const AddressList& addresses, NetLog* net_log, diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc index 999b4e6..3d12256 100644 --- a/net/socket/client_socket_pool_manager.cc +++ b/net/socket/client_socket_pool_manager.cc @@ -8,12 +8,15 @@ #include "net/socket/client_socket_pool_manager.h" +#include <string> + #include "base/logging.h" #include "base/values.h" #include "net/base/ssl_config_service.h" #include "net/http/http_proxy_client_socket_pool.h" -#include "net/socket/client_socket_pool_histograms.h" #include "net/proxy/proxy_service.h" +#include "net/socket/client_socket_factory.h" +#include "net/socket/client_socket_pool_histograms.h" #include "net/socket/socks_client_socket_pool.h" #include "net/socket/ssl_client_socket_pool.h" #include "net/socket/tcp_client_socket_pool.h" @@ -98,9 +101,13 @@ ClientSocketPoolManager::ClientSocketPoolManager( tcp_for_https_proxy_pool_histograms_("TCPforHTTPSProxy"), ssl_for_https_proxy_pool_histograms_("SSLforHTTPSProxy"), http_proxy_pool_histograms_("HTTPProxy"), - ssl_socket_pool_for_proxies_histograms_("SSLForProxies") {} + ssl_socket_pool_for_proxies_histograms_("SSLForProxies") { + CertDatabase::AddObserver(this); +} -ClientSocketPoolManager::~ClientSocketPoolManager() {} +ClientSocketPoolManager::~ClientSocketPoolManager() { + CertDatabase::RemoveObserver(this); +} void ClientSocketPoolManager::FlushSocketPools() { // Flush the highest level pools first, since higher level pools may release @@ -392,4 +399,8 @@ Value* ClientSocketPoolManager::SocketPoolInfoToValue() const { return list; } +void ClientSocketPoolManager::OnUserCertAdded(X509Certificate* cert) { + FlushSocketPools(); +} + } // namespace net diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h index 7d610a9..45a0c23 100644 --- a/net/socket/client_socket_pool_manager.h +++ b/net/socket/client_socket_pool_manager.h @@ -17,6 +17,7 @@ #include "base/stl_util-inl.h" #include "base/template_util.h" #include "base/threading/non_thread_safe.h" +#include "net/base/cert_database.h" #include "net/socket/client_socket_pool_histograms.h" class Value; @@ -57,7 +58,8 @@ class OwnedPoolMap : public std::map<Key, Value> { } // namespace internal -class ClientSocketPoolManager : public base::NonThreadSafe { +class ClientSocketPoolManager : public base::NonThreadSafe, + public CertDatabase::Observer { public: ClientSocketPoolManager(NetLog* net_log, ClientSocketFactory* socket_factory, @@ -94,6 +96,9 @@ class ClientSocketPoolManager : public base::NonThreadSafe { // responsible for deleting the returned value. Value* SocketPoolInfoToValue() const; + // CertDatabase::Observer methods: + virtual void OnUserCertAdded(X509Certificate* cert); + private: friend class HttpNetworkSessionPeer; diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index e2cae2b..0220d11 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc @@ -22,6 +22,7 @@ SpdySessionPool::SpdySessionPool(SSLConfigService* ssl_config_service) NetworkChangeNotifier::AddIPAddressObserver(this); if (ssl_config_service_) ssl_config_service_->AddObserver(this); + CertDatabase::AddObserver(this); } SpdySessionPool::~SpdySessionPool() { @@ -30,6 +31,7 @@ SpdySessionPool::~SpdySessionPool() { if (ssl_config_service_) ssl_config_service_->RemoveObserver(this); NetworkChangeNotifier::RemoveIPAddressObserver(this); + CertDatabase::RemoveObserver(this); } scoped_refptr<SpdySession> SpdySessionPool::Get( @@ -136,6 +138,10 @@ void SpdySessionPool::OnSSLConfigChanged() { CloseCurrentSessions(); } +void SpdySessionPool::OnUserCertAdded(X509Certificate* cert) { + CloseCurrentSessions(); +} + const HostPortProxyPair& SpdySessionPool::NormalizeListPair( const HostPortProxyPair& host_port_proxy_pair) const { if (!g_force_single_domain) diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 16125e0..caaaa67 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h @@ -14,6 +14,7 @@ #include "base/gtest_prod_util.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" +#include "net/base/cert_database.h" #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" #include "net/base/network_change_notifier.h" @@ -33,7 +34,8 @@ class SpdySession; // TODO(mbelshe): Make this production ready. class SpdySessionPool : public NetworkChangeNotifier::IPAddressObserver, - public SSLConfigService::Observer { + public SSLConfigService::Observer, + public CertDatabase::Observer { public: explicit SpdySessionPool(SSLConfigService* ssl_config_service); virtual ~SpdySessionPool(); @@ -105,6 +107,9 @@ class SpdySessionPool // A debugging mode where we compress all accesses through a single domain. static void ForceSingleDomain() { g_force_single_domain = true; } + // CertDatabase::Observer methods: + virtual void OnUserCertAdded(X509Certificate* cert); + private: friend class SpdySessionPoolPeer; // For testing. friend class SpdyNetworkTransactionTest; // For testing. |