From 9f59fac37e0af9a1e8a840fa18b6c1c69f221cdf Mon Sep 17 00:00:00 2001 From: "rsleevi@chromium.org" Date: Wed, 21 Mar 2012 23:18:11 +0000 Subject: [PATCH] Make CertVerifier a pure virtual interface. The existing CertVerifier implementation has been renamed to MultiThreadedCertVerifier, consistent with ProxyResolver naming. This is patch 1 of N for http://crbug.com/114343 BUG=114343 TEST=Compiles and existing unittests pass. Review URL: https://chromiumcodereview.appspot.com/9476035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@128090 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/chromeos/web_socket_proxy.cc | 2 +- chrome/browser/io_thread.cc | 2 +- chrome/browser/net/connection_tester.cc | 2 +- .../browser/net/connection_tester_unittest.cc | 7 +- .../net/service_url_request_context.cc | 2 +- .../renderer_host/pepper_message_filter.cc | 2 +- .../shell/shell_url_request_context_getter.cc | 2 +- .../base/chrome_async_socket_unittest.cc | 7 +- net/base/cert_database.cc | 1 - net/base/cert_database.h | 4 +- net/base/cert_verifier.cc | 493 +----------------- net/base/cert_verifier.h | 179 +------ net/base/multi_threaded_cert_verifier.cc | 444 ++++++++++++++++ net/base/multi_threaded_cert_verifier.h | 142 +++++ ... multi_threaded_cert_verifier_unittest.cc} | 63 ++- net/base/single_request_cert_verifier.cc | 74 +++ net/base/single_request_cert_verifier.h | 53 ++ net/base/transport_security_state_unittest.cc | 1 + ...disk_cache_based_ssl_host_info_unittest.cc | 21 +- net/http/http_network_layer_unittest.cc | 10 +- ...ttp_network_transaction_spdy21_unittest.cc | 4 +- ...http_network_transaction_spdy2_unittest.cc | 4 +- ...http_network_transaction_spdy3_unittest.cc | 5 +- ...roxy_client_socket_pool_spdy21_unittest.cc | 7 +- ...proxy_client_socket_pool_spdy2_unittest.cc | 7 +- ...proxy_client_socket_pool_spdy3_unittest.cc | 8 +- net/http/http_stream_factory_impl_unittest.cc | 2 +- net/net.gyp | 6 +- .../proxy_script_fetcher_impl_unittest.cc | 3 +- net/socket/ssl_client_socket_mac.cc | 1 + net/socket/ssl_client_socket_nss.cc | 1 + net/socket/ssl_client_socket_openssl.cc | 1 + net/socket/ssl_client_socket_pool_unittest.cc | 4 +- net/socket/ssl_client_socket_unittest.cc | 2 +- net/socket/ssl_client_socket_win.cc | 1 + net/socket/ssl_host_info.h | 1 + net/socket/ssl_server_socket_unittest.cc | 7 +- net/spdy/spdy_test_util_spdy2.cc | 7 +- net/spdy/spdy_test_util_spdy3.cc | 6 +- net/tools/fetch/fetch_client.cc | 5 +- net/url_request/url_request_test_util.cc | 3 +- remoting/host/url_request_context.cc | 2 +- remoting/jingle_glue/ssl_socket_adapter.cc | 4 +- .../ssl_hmac_channel_authenticator.cc | 2 +- .../test_shell/test_shell_request_context.cc | 2 +- 45 files changed, 870 insertions(+), 736 deletions(-) create mode 100644 net/base/multi_threaded_cert_verifier.cc create mode 100644 net/base/multi_threaded_cert_verifier.h rename net/base/{cert_verifier_unittest.cc => multi_threaded_cert_verifier_unittest.cc} (81%) create mode 100644 net/base/single_request_cert_verifier.cc create mode 100644 net/base/single_request_cert_verifier.h diff --git a/chrome/browser/chromeos/web_socket_proxy.cc b/chrome/browser/chromeos/web_socket_proxy.cc index 66a3e1aef10660..78236b62b0f01d 100644 --- a/chrome/browser/chromeos/web_socket_proxy.cc +++ b/chrome/browser/chromeos/web_socket_proxy.cc @@ -615,7 +615,7 @@ class SSLChan : public MessageLoopForIO::Watcher { net::ClientSocketFactory::GetDefaultFactory(); net::SSLClientSocketContext ssl_context; if (!cert_verifier_.get()) - cert_verifier_.reset(new net::CertVerifier()); + cert_verifier_.reset(net::CertVerifier::CreateDefault()); ssl_context.cert_verifier = cert_verifier_.get(); socket_.reset(factory->CreateSSLClientSocket( handle, host_port_pair_, ssl_config_, NULL, ssl_context)); diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 9d5dd5fe71a3ea..e9196e7a99e4e8 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -393,7 +393,7 @@ void IOThread::Init() { &system_enable_referrers_)); globals_->host_resolver.reset( CreateGlobalHostResolver(net_log_)); - globals_->cert_verifier.reset(new net::CertVerifier); + globals_->cert_verifier.reset(net::CertVerifier::CreateDefault()); globals_->transport_security_state.reset(new net::TransportSecurityState("")); globals_->ssl_config_service = GetSSLConfigService(); globals_->http_auth_handler_factory.reset(CreateDefaultAuthHandlerFactory( diff --git a/chrome/browser/net/connection_tester.cc b/chrome/browser/net/connection_tester.cc index 59da2b87e4b42e..453c901d55d31d 100644 --- a/chrome/browser/net/connection_tester.cc +++ b/chrome/browser/net/connection_tester.cc @@ -72,7 +72,7 @@ class ExperimentURLRequestContext : public net::URLRequestContext { // The rest of the dependencies are standard, and don't depend on the // experiment being run. - storage_.set_cert_verifier(new net::CertVerifier); + storage_.set_cert_verifier(net::CertVerifier::CreateDefault()); storage_.set_ftp_transaction_factory( new net::FtpNetworkLayer(host_resolver())); storage_.set_ssl_config_service(new net::SSLConfigServiceDefaults); diff --git a/chrome/browser/net/connection_tester_unittest.cc b/chrome/browser/net/connection_tester_unittest.cc index 50c43e7e1a9674..099b355ff89bdb 100644 --- a/chrome/browser/net/connection_tester_unittest.cc +++ b/chrome/browser/net/connection_tester_unittest.cc @@ -108,7 +108,7 @@ class ConnectionTesterTest : public PlatformTest { net::TestServer test_server_; ConnectionTesterDelegate test_delegate_; net::MockHostResolver host_resolver_; - net::CertVerifier cert_verifier_; + scoped_ptr cert_verifier_; scoped_ptr proxy_service_; scoped_refptr ssl_config_service_; scoped_ptr http_transaction_factory_; @@ -119,7 +119,8 @@ class ConnectionTesterTest : public PlatformTest { private: void InitializeRequestContext() { proxy_script_fetcher_context_->set_host_resolver(&host_resolver_); - proxy_script_fetcher_context_->set_cert_verifier(&cert_verifier_); + cert_verifier_.reset(net::CertVerifier::CreateDefault()); + proxy_script_fetcher_context_->set_cert_verifier(cert_verifier_.get()); proxy_script_fetcher_context_->set_http_auth_handler_factory( &http_auth_handler_factory_); proxy_service_.reset(net::ProxyService::CreateDirect()); @@ -127,7 +128,7 @@ class ConnectionTesterTest : public PlatformTest { ssl_config_service_ = new net::SSLConfigServiceDefaults; net::HttpNetworkSession::Params session_params; session_params.host_resolver = &host_resolver_; - session_params.cert_verifier = &cert_verifier_; + session_params.cert_verifier = cert_verifier_.get(); session_params.http_auth_handler_factory = &http_auth_handler_factory_; session_params.ssl_config_service = ssl_config_service_; session_params.proxy_service = proxy_service_.get(); diff --git a/chrome/service/net/service_url_request_context.cc b/chrome/service/net/service_url_request_context.cc index 2cf2b43d736a49..4fb23854ce66ee 100644 --- a/chrome/service/net/service_url_request_context.cc +++ b/chrome/service/net/service_url_request_context.cc @@ -115,7 +115,7 @@ ServiceURLRequestContext::ServiceURLRequestContext( NULL)); storage_.set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver( net_proxy_config_service, 0u, NULL)); - storage_.set_cert_verifier(new net::CertVerifier); + storage_.set_cert_verifier(net::CertVerifier::CreateDefault()); storage_.set_ftp_transaction_factory( new net::FtpNetworkLayer(host_resolver())); storage_.set_ssl_config_service(new net::SSLConfigServiceDefaults); diff --git a/content/browser/renderer_host/pepper_message_filter.cc b/content/browser/renderer_host/pepper_message_filter.cc index 7d69fd2753be58..4b8ef39042d298 100644 --- a/content/browser/renderer_host/pepper_message_filter.cc +++ b/content/browser/renderer_host/pepper_message_filter.cc @@ -167,7 +167,7 @@ net::HostResolver* PepperMessageFilter::GetHostResolver() { net::CertVerifier* PepperMessageFilter::GetCertVerifier() { if (!cert_verifier_.get()) - cert_verifier_.reset(new net::CertVerifier()); + cert_verifier_.reset(net::CertVerifier::CreateDefault()); return cert_verifier_.get(); } diff --git a/content/shell/shell_url_request_context_getter.cc b/content/shell/shell_url_request_context_getter.cc index 9a35da82782889..48c72b01d446e2 100644 --- a/content/shell/shell_url_request_context_getter.cc +++ b/content/shell/shell_url_request_context_getter.cc @@ -61,7 +61,7 @@ net::URLRequestContext* ShellURLRequestContextGetter::GetURLRequestContext() { net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism, net::HostResolver::kDefaultRetryAttempts, NULL)); - storage_->set_cert_verifier(new net::CertVerifier); + storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); // TODO(jam): use v8 if possible, look at chrome code. storage_->set_proxy_service( net::ProxyService::CreateUsingSystemProxyResolver( diff --git a/jingle/notifier/base/chrome_async_socket_unittest.cc b/jingle/notifier/base/chrome_async_socket_unittest.cc index 9b1d07abee9cef..08dbf301a46306 100644 --- a/jingle/notifier/base/chrome_async_socket_unittest.cc +++ b/jingle/notifier/base/chrome_async_socket_unittest.cc @@ -120,7 +120,8 @@ class MockXmppClientSocketFactory : public ResolvingClientSocketFactory { net::ClientSocketFactory* mock_client_socket_factory, const net::AddressList& address_list) : mock_client_socket_factory_(mock_client_socket_factory), - address_list_(address_list) { + address_list_(address_list), + cert_verifier_(net::CertVerifier::CreateDefault()) { } // ResolvingClientSocketFactory implementation. @@ -134,7 +135,7 @@ class MockXmppClientSocketFactory : public ResolvingClientSocketFactory { net::ClientSocketHandle* transport_socket, const net::HostPortPair& host_and_port) { net::SSLClientSocketContext context; - context.cert_verifier = &cert_verifier_; + context.cert_verifier = cert_verifier_.get(); return mock_client_socket_factory_->CreateSSLClientSocket( transport_socket, host_and_port, ssl_config_, NULL, context); } @@ -143,7 +144,7 @@ class MockXmppClientSocketFactory : public ResolvingClientSocketFactory { scoped_ptr mock_client_socket_factory_; net::AddressList address_list_; net::SSLConfig ssl_config_; - net::CertVerifier cert_verifier_; + scoped_ptr cert_verifier_; }; class ChromeAsyncSocketTest diff --git a/net/base/cert_database.cc b/net/base/cert_database.cc index 6f9c609ccaddaa..7930750757de37 100644 --- a/net/base/cert_database.cc +++ b/net/base/cert_database.cc @@ -6,7 +6,6 @@ #include "base/memory/singleton.h" #include "base/observer_list_threadsafe.h" -#include "net/base/x509_certificate.h" namespace net { diff --git a/net/base/cert_database.h b/net/base/cert_database.h index 9761bd199b09dd..2e95624c911c1d 100644 --- a/net/base/cert_database.h +++ b/net/base/cert_database.h @@ -14,14 +14,12 @@ #include "base/string16.h" #include "net/base/cert_type.h" #include "net/base/net_export.h" +#include "net/base/x509_certificate.h" namespace net { class CryptoModule; typedef std::vector > CryptoModuleList; -class X509Certificate; -typedef std::vector > CertificateList; - // This class provides functions to manipulate the local // certificate store. diff --git a/net/base/cert_verifier.cc b/net/base/cert_verifier.cc index f5f0bc20909520..c86c97b40f2354 100644 --- a/net/base/cert_verifier.cc +++ b/net/base/cert_verifier.cc @@ -4,499 +4,12 @@ #include "net/base/cert_verifier.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/compiler_specific.h" -#include "base/message_loop.h" -#include "base/metrics/histogram.h" -#include "base/stl_util.h" -#include "base/synchronization/lock.h" -#include "base/time.h" -#include "base/threading/worker_pool.h" -#include "net/base/crl_set.h" -#include "net/base/net_errors.h" -#include "net/base/net_log.h" -#include "net/base/x509_certificate.h" -#include "net/base/x509_certificate_net_log_param.h" - -#if defined(USE_NSS) -#include // PR_DetachThread -#endif +#include "net/base/multi_threaded_cert_verifier.h" namespace net { -//////////////////////////////////////////////////////////////////////////// - -// Life of a request: -// -// CertVerifier CertVerifierJob CertVerifierWorker Request -// | (origin loop) (worker loop) -// | -// Verify() -// |---->------------------- -// | -// |---->---- -// | -// |---->--------------------------------------------------- -// | -// |---->--------------------Start -// | | -// | PostTask -// | -// | -// |---->-----AddRequest | -// | -// | -// | -// Finish -// | -// PostTask -// -// | -// DoReply -// |----<-----------------------| -// HandleResult -// | -// |---->-----HandleResult -// | -// |------>-----------------------------------Post -// -// -// -// On a cache hit, CertVerifier::Verify() returns synchronously without -// posting a task to a worker thread. - -namespace { - -// The default value of max_cache_entries_. -const unsigned kMaxCacheEntries = 256; - -// The number of seconds for which we'll cache a cache entry. -const unsigned kTTLSecs = 1800; // 30 minutes. - -} // namespace - -CertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} - -CertVerifier::CachedResult::~CachedResult() {} - -// Represents the output and result callback of a request. -class CertVerifierRequest { - public: - CertVerifierRequest(const CompletionCallback& callback, - CertVerifyResult* verify_result, - const BoundNetLog& net_log) - : callback_(callback), - verify_result_(verify_result), - net_log_(net_log) { - net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); - } - - ~CertVerifierRequest() { - } - - // Ensures that the result callback will never be made. - void Cancel() { - callback_.Reset(); - verify_result_ = NULL; - net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); - net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); - } - - // Copies the contents of |verify_result| to the caller's - // CertVerifyResult and calls the callback. - void Post(const CertVerifier::CachedResult& verify_result) { - if (!callback_.is_null()) { - net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); - *verify_result_ = verify_result.result; - callback_.Run(verify_result.error); - } - delete this; - } - - bool canceled() const { return callback_.is_null(); } - - const BoundNetLog& net_log() const { return net_log_; } - - private: - CompletionCallback callback_; - CertVerifyResult* verify_result_; - const BoundNetLog net_log_; -}; - - -// CertVerifierWorker runs on a worker thread and takes care of the blocking -// process of performing the certificate verification. Deletes itself -// eventually if Start() succeeds. -class CertVerifierWorker { - public: - CertVerifierWorker(X509Certificate* cert, - const std::string& hostname, - int flags, - CRLSet* crl_set, - CertVerifier* cert_verifier) - : cert_(cert), - hostname_(hostname), - flags_(flags), - crl_set_(crl_set), - origin_loop_(MessageLoop::current()), - cert_verifier_(cert_verifier), - canceled_(false), - error_(ERR_FAILED) { - } - - // Returns the certificate being verified. May only be called /before/ - // Start() is called. - X509Certificate* certificate() const { return cert_; } - - bool Start() { - DCHECK_EQ(MessageLoop::current(), origin_loop_); - - return base::WorkerPool::PostTask( - FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)), - true /* task is slow */); - } - - // Cancel is called from the origin loop when the CertVerifier is getting - // deleted. - void Cancel() { - DCHECK_EQ(MessageLoop::current(), origin_loop_); - base::AutoLock locked(lock_); - canceled_ = true; - } - - private: - void Run() { - // Runs on a worker thread. - error_ = cert_->Verify(hostname_, flags_, crl_set_, &verify_result_); -#if defined(USE_NSS) - // Detach the thread from NSPR. - // Calling NSS functions attaches the thread to NSPR, which stores - // the NSPR thread ID in thread-specific data. - // The threads in our thread pool terminate after we have called - // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets - // segfaults on shutdown when the threads' thread-specific data - // destructors run. - PR_DetachThread(); -#endif - Finish(); - } - - // DoReply runs on the origin thread. - void DoReply() { - DCHECK_EQ(MessageLoop::current(), origin_loop_); - { - // We lock here because the worker thread could still be in Finished, - // after the PostTask, but before unlocking |lock_|. If we do not lock in - // this case, we will end up deleting a locked Lock, which can lead to - // memory leaks or worse errors. - base::AutoLock locked(lock_); - if (!canceled_) { - cert_verifier_->HandleResult(cert_, hostname_, flags_, - error_, verify_result_); - } - } - delete this; - } - - void Finish() { - // Runs on the worker thread. - // We assume that the origin loop outlives the CertVerifier. If the - // CertVerifier is deleted, it will call Cancel on us. If it does so - // before the Acquire, we'll delete ourselves and return. If it's trying to - // do so concurrently, then it'll block on the lock and we'll call PostTask - // while the CertVerifier (and therefore the MessageLoop) is still alive. - // If it does so after this function, we assume that the MessageLoop will - // process pending tasks. In which case we'll notice the |canceled_| flag - // in DoReply. - - bool canceled; - { - base::AutoLock locked(lock_); - canceled = canceled_; - if (!canceled) { - origin_loop_->PostTask( - FROM_HERE, base::Bind( - &CertVerifierWorker::DoReply, base::Unretained(this))); - } - } - - if (canceled) - delete this; - } - - scoped_refptr cert_; - const std::string hostname_; - const int flags_; - scoped_refptr crl_set_; - MessageLoop* const origin_loop_; - CertVerifier* const cert_verifier_; - - // lock_ protects canceled_. - base::Lock lock_; - - // If canceled_ is true, - // * origin_loop_ cannot be accessed by the worker thread, - // * cert_verifier_ cannot be accessed by any thread. - bool canceled_; - - int error_; - CertVerifyResult verify_result_; - - DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker); -}; - -// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It -// lives only on the CertVerifier's origin message loop. -class CertVerifierJob { - public: - CertVerifierJob(CertVerifierWorker* worker, - const BoundNetLog& net_log) - : start_time_(base::TimeTicks::Now()), - worker_(worker), - net_log_(net_log) { - scoped_refptr params( - new X509CertificateNetLogParam(worker_->certificate())); - net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_JOB, params); - } - - ~CertVerifierJob() { - if (worker_) { - net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); - net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL); - worker_->Cancel(); - DeleteAllCanceled(); - } - } - - void AddRequest(CertVerifierRequest* request) { - request->net_log().AddEvent( - NetLog::TYPE_CERT_VERIFIER_REQUEST_BOUND_TO_JOB, - make_scoped_refptr(new NetLogSourceParameter( - "source_dependency", net_log_.source()))); - - requests_.push_back(request); - } - - void HandleResult(const CertVerifier::CachedResult& verify_result) { - worker_ = NULL; - net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL); - UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency", - base::TimeTicks::Now() - start_time_, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(10), - 100); - PostAll(verify_result); - } - - private: - void PostAll(const CertVerifier::CachedResult& verify_result) { - std::vector requests; - requests_.swap(requests); - - for (std::vector::iterator - i = requests.begin(); i != requests.end(); i++) { - (*i)->Post(verify_result); - // Post() causes the CertVerifierRequest to delete itself. - } - } - - void DeleteAllCanceled() { - for (std::vector::iterator - i = requests_.begin(); i != requests_.end(); i++) { - if ((*i)->canceled()) { - delete *i; - } else { - LOG(DFATAL) << "CertVerifierRequest leaked!"; - } - } - } - - const base::TimeTicks start_time_; - std::vector requests_; - CertVerifierWorker* worker_; - const BoundNetLog net_log_; -}; - -CertVerifier::CertVerifier() - : cache_(kMaxCacheEntries), - requests_(0), - cache_hits_(0), - inflight_joins_(0) { - CertDatabase::AddObserver(this); -} - -CertVerifier::~CertVerifier() { - STLDeleteValues(&inflight_); - - CertDatabase::RemoveObserver(this); -} - -int CertVerifier::Verify(X509Certificate* cert, - const std::string& hostname, - int flags, - CRLSet* crl_set, - CertVerifyResult* verify_result, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log) { - DCHECK(CalledOnValidThread()); - - if (callback.is_null() || !verify_result || hostname.empty()) { - *out_req = NULL; - return ERR_INVALID_ARGUMENT; - } - - requests_++; - - const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), - hostname, flags); - const CertVerifierCache::value_type* cached_entry = - cache_.Get(key, base::TimeTicks::Now()); - if (cached_entry) { - ++cache_hits_; - *out_req = NULL; - *verify_result = cached_entry->result; - return cached_entry->error; - } - - // No cache hit. See if an identical request is currently in flight. - CertVerifierJob* job; - std::map::const_iterator j; - j = inflight_.find(key); - if (j != inflight_.end()) { - // An identical request is in flight already. We'll just attach our - // callback. - inflight_joins_++; - job = j->second; - } else { - // Need to make a new request. - CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags, - crl_set, this); - job = new CertVerifierJob( - worker, - BoundNetLog::Make(net_log.net_log(), NetLog::SOURCE_CERT_VERIFIER_JOB)); - if (!worker->Start()) { - delete job; - delete worker; - *out_req = NULL; - // TODO(wtc): log to the NetLog. - LOG(ERROR) << "CertVerifierWorker couldn't be started."; - return ERR_INSUFFICIENT_RESOURCES; // Just a guess. - } - inflight_.insert(std::make_pair(key, job)); - } - - CertVerifierRequest* request = - new CertVerifierRequest(callback, verify_result, net_log); - job->AddRequest(request); - *out_req = request; - return ERR_IO_PENDING; -} - -void CertVerifier::CancelRequest(RequestHandle req) { - DCHECK(CalledOnValidThread()); - CertVerifierRequest* request = reinterpret_cast(req); - request->Cancel(); -} - -// HandleResult is called by CertVerifierWorker on the origin message loop. -// It deletes CertVerifierJob. -void CertVerifier::HandleResult(X509Certificate* cert, - const std::string& hostname, - int flags, - int error, - const CertVerifyResult& verify_result) { - DCHECK(CalledOnValidThread()); - - const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), - hostname, flags); - - CachedResult cached_result; - cached_result.error = error; - cached_result.result = verify_result; - cache_.Put(key, cached_result, base::TimeTicks::Now(), - base::TimeDelta::FromSeconds(kTTLSecs)); - - std::map::iterator j; - j = inflight_.find(key); - if (j == inflight_.end()) { - NOTREACHED(); - return; - } - CertVerifierJob* job = j->second; - inflight_.erase(j); - - job->HandleResult(cached_result); - delete job; -} - -void CertVerifier::OnCertTrustChanged(const X509Certificate* cert) { - DCHECK(CalledOnValidThread()); - - ClearCache(); -} - -///////////////////////////////////////////////////////////////////// - -SingleRequestCertVerifier::SingleRequestCertVerifier( - CertVerifier* cert_verifier) - : cert_verifier_(cert_verifier), - cur_request_(NULL) { - DCHECK(cert_verifier_ != NULL); -} - -SingleRequestCertVerifier::~SingleRequestCertVerifier() { - if (cur_request_) { - cert_verifier_->CancelRequest(cur_request_); - cur_request_ = NULL; - } -} - -int SingleRequestCertVerifier::Verify(X509Certificate* cert, - const std::string& hostname, - int flags, - CRLSet* crl_set, - CertVerifyResult* verify_result, - const CompletionCallback& callback, - const BoundNetLog& net_log) { - // Should not be already in use. - DCHECK(!cur_request_ && cur_request_callback_.is_null()); - - // Do a synchronous verification. - if (callback.is_null()) - return cert->Verify(hostname, flags, crl_set, verify_result); - - CertVerifier::RequestHandle request = NULL; - - // We need to be notified of completion before |callback| is called, so that - // we can clear out |cur_request_*|. - int rv = cert_verifier_->Verify( - cert, hostname, flags, crl_set, verify_result, - base::Bind(&SingleRequestCertVerifier::OnVerifyCompletion, - base::Unretained(this)), - &request, net_log); - - if (rv == ERR_IO_PENDING) { - // Cleared in OnVerifyCompletion(). - cur_request_ = request; - cur_request_callback_ = callback; - } - - return rv; -} - -void SingleRequestCertVerifier::OnVerifyCompletion(int result) { - DCHECK(cur_request_ && !cur_request_callback_.is_null()); - - CompletionCallback callback = cur_request_callback_; - - // Clear the outstanding request information. - cur_request_ = NULL; - cur_request_callback_.Reset(); - - // Call the user's original callback. - callback.Run(result); +CertVerifier* CertVerifier::CreateDefault() { + return new MultiThreadedCertVerifier(); } } // namespace net diff --git a/net/base/cert_verifier.h b/net/base/cert_verifier.h index fae7ec4586ef41..18c035f4605a44 100644 --- a/net/base/cert_verifier.h +++ b/net/base/cert_verifier.h @@ -6,50 +6,36 @@ #define NET_BASE_CERT_VERIFIER_H_ #pragma once -#include #include #include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "net/base/cert_database.h" -#include "net/base/cert_verify_result.h" #include "net/base/completion_callback.h" -#include "net/base/expiring_cache.h" #include "net/base/net_export.h" -#include "net/base/x509_cert_types.h" namespace net { class BoundNetLog; -class CertVerifierJob; -class CertVerifierWorker; +class CertVerifyResult; class CRLSet; class X509Certificate; // CertVerifier represents a service for verifying certificates. // -// CertVerifier can handle multiple requests at a time, so when canceling a -// request the RequestHandle that was returned by Verify() needs to be -// given. A simpler alternative for consumers that only have 1 outstanding -// request at a time is to create a SingleRequestCertVerifier wrapper around -// CertVerifier (which will automatically cancel the single request when it -// goes out of scope). -class NET_EXPORT CertVerifier : NON_EXPORTED_BASE(public base::NonThreadSafe), - public CertDatabase::Observer { +// CertVerifiers can handle multiple requests at a time. A simpler alternative +// for consumers that only have 1 outstanding request at a time is to create a +// SingleRequestCertVerifier wrapper around CertVerifier (which will +// automatically cancel the single request when it goes out of scope). +class NET_EXPORT CertVerifier { public: - // Opaque type used to cancel a request. + // Opaque pointer type used to cancel outstanding requests. typedef void* RequestHandle; - CertVerifier(); - - // When the verifier is destroyed, all certificate verifications requests are + // When the verifier is destroyed, all certificate verification requests are // canceled, and their completion callbacks will not be called. - virtual ~CertVerifier(); + virtual ~CertVerifier() {} - // Verifies the given certificate against the given hostname. Returns OK if - // successful or an error code upon failure. + // Verifies the given certificate against the given hostname as an SSL server. + // Returns OK if successful or an error code upon failure. // // The |*verify_result| structure, including the |verify_result->cert_status| // bitmask, is always filled out regardless of the return value. If the @@ -76,139 +62,24 @@ class NET_EXPORT CertVerifier : NON_EXPORTED_BASE(public base::NonThreadSafe), // If |out_req| is non-NULL, then |*out_req| will be filled with a handle to // the async request. This handle is not valid after the request has // completed. - int Verify(X509Certificate* cert, - const std::string& hostname, - int flags, - CRLSet* crl_set, - CertVerifyResult* verify_result, - const CompletionCallback& callback, - RequestHandle* out_req, - const BoundNetLog& net_log); + // + // TODO(rsleevi): Move CRLSet* out of the CertVerifier signature. + virtual int Verify(X509Certificate* cert, + const std::string& hostname, + int flags, + CRLSet* crl_set, + CertVerifyResult* verify_result, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) = 0; // Cancels the specified request. |req| is the handle returned by Verify(). // After a request is canceled, its completion callback will not be called. - void CancelRequest(RequestHandle req); - - private: - friend class CertVerifierWorker; // Calls HandleResult. - friend class CertVerifierRequest; - friend class CertVerifierJob; - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, CacheHit); - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, DifferentCACerts); - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, InflightJoin); - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, CancelRequest); - FRIEND_TEST_ALL_PREFIXES(CertVerifierTest, RequestParamsComparators); - - // Input parameters of a certificate verification request. - struct RequestParams { - RequestParams(const SHA1Fingerprint& cert_fingerprint_arg, - const SHA1Fingerprint& ca_fingerprint_arg, - const std::string& hostname_arg, - int flags_arg) - : cert_fingerprint(cert_fingerprint_arg), - ca_fingerprint(ca_fingerprint_arg), - hostname(hostname_arg), - flags(flags_arg) {} - - bool operator<(const RequestParams& other) const { - // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, and - // |hostname| under assumption that integer comparisons are faster than - // memory and string comparisons. - if (flags != other.flags) - return flags < other.flags; - int rv = memcmp(cert_fingerprint.data, other.cert_fingerprint.data, - sizeof(cert_fingerprint.data)); - if (rv != 0) - return rv < 0; - rv = memcmp(ca_fingerprint.data, other.ca_fingerprint.data, - sizeof(ca_fingerprint.data)); - if (rv != 0) - return rv < 0; - return hostname < other.hostname; - } - - SHA1Fingerprint cert_fingerprint; - SHA1Fingerprint ca_fingerprint; - std::string hostname; - int flags; - }; - - // CachedResult contains the result of a certificate verification. - struct CachedResult { - CachedResult(); - ~CachedResult(); - - int error; // The return value of CertVerifier::Verify. - CertVerifyResult result; // The output of CertVerifier::Verify. - }; - - void HandleResult(X509Certificate* cert, - const std::string& hostname, - int flags, - int error, - const CertVerifyResult& verify_result); - - // CertDatabase::Observer methods: - virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE; - - // For unit testing. - void ClearCache() { cache_.Clear(); } - size_t GetCacheSize() const { return cache_.size(); } - uint64 cache_hits() const { return cache_hits_; } - uint64 requests() const { return requests_; } - uint64 inflight_joins() const { return inflight_joins_; } - - // cache_ maps from a request to a cached result. - typedef ExpiringCache CertVerifierCache; - CertVerifierCache cache_; - - // inflight_ maps from a request to an active verification which is taking - // place. - std::map inflight_; - - uint64 requests_; - uint64 cache_hits_; - uint64 inflight_joins_; - - DISALLOW_COPY_AND_ASSIGN(CertVerifier); -}; - -// This class represents the task of verifying a certificate. It wraps -// CertVerifier to verify only a single certificate at a time and cancels this -// request when going out of scope. -class SingleRequestCertVerifier { - public: - // |cert_verifier| must remain valid for the lifetime of |this|. - explicit SingleRequestCertVerifier(CertVerifier* cert_verifier); - - // If a completion callback is pending when the verifier is destroyed, the - // certificate verification is canceled, and the completion callback will - // not be called. - ~SingleRequestCertVerifier(); - - // Verifies the given certificate, filling out the |verify_result| object - // upon success. See CertVerifier::Verify() for details. - int Verify(X509Certificate* cert, - const std::string& hostname, - int flags, - CRLSet* crl_set, - CertVerifyResult* verify_result, - const CompletionCallback& callback, - const BoundNetLog& net_log); - - private: - // Callback for when the request to |cert_verifier_| completes, so we - // dispatch to the user's callback. - void OnVerifyCompletion(int result); - - // The actual certificate verifier that will handle the request. - CertVerifier* const cert_verifier_; - - // The current request (if any). - CertVerifier::RequestHandle cur_request_; - CompletionCallback cur_request_callback_; + virtual void CancelRequest(RequestHandle req) = 0; - DISALLOW_COPY_AND_ASSIGN(SingleRequestCertVerifier); + // Creates a CertVerifier implementation that verifies certificates using + // the preferred underlying cryptographic libraries. + static CertVerifier* CreateDefault(); }; } // namespace net diff --git a/net/base/multi_threaded_cert_verifier.cc b/net/base/multi_threaded_cert_verifier.cc new file mode 100644 index 00000000000000..6a3037bd073e7d --- /dev/null +++ b/net/base/multi_threaded_cert_verifier.cc @@ -0,0 +1,444 @@ +// Copyright (c) 2012 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 "net/base/multi_threaded_cert_verifier.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/compiler_specific.h" +#include "base/message_loop.h" +#include "base/metrics/histogram.h" +#include "base/stl_util.h" +#include "base/synchronization/lock.h" +#include "base/time.h" +#include "base/threading/worker_pool.h" +#include "net/base/crl_set.h" +#include "net/base/net_errors.h" +#include "net/base/net_log.h" +#include "net/base/x509_certificate.h" +#include "net/base/x509_certificate_net_log_param.h" + +#if defined(USE_NSS) +#include // PR_DetachThread +#endif + +namespace net { + +//////////////////////////////////////////////////////////////////////////// + +// Life of a request: +// +// MultiThreadedCertVerifier CertVerifierJob CertVerifierWorker Request +// | (origin loop) (worker loop) +// | +// Verify() +// |---->------------------------------------- +// | +// |---->------------------- +// | +// |---->------------------------------------------------------- +// | +// |---->---------------------------------------Start +// | | +// | PostTask +// | +// | +// |---->-------------------AddRequest | +// | +// | +// | +// Finish +// | +// PostTask +// +// | +// DoReply +// |----<-----------------------------------------| +// HandleResult +// | +// |---->------------------HandleResult +// | +// |------>---------------------------Post +// +// +// +// On a cache hit, MultiThreadedCertVerifier::Verify() returns synchronously +// without posting a task to a worker thread. + +namespace { + +// The default value of max_cache_entries_. +const unsigned kMaxCacheEntries = 256; + +// The number of seconds for which we'll cache a cache entry. +const unsigned kTTLSecs = 1800; // 30 minutes. + +} // namespace + +MultiThreadedCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} + +MultiThreadedCertVerifier::CachedResult::~CachedResult() {} + +// Represents the output and result callback of a request. +class CertVerifierRequest { + public: + CertVerifierRequest(const CompletionCallback& callback, + CertVerifyResult* verify_result, + const BoundNetLog& net_log) + : callback_(callback), + verify_result_(verify_result), + net_log_(net_log) { + net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); + } + + ~CertVerifierRequest() { + } + + // Ensures that the result callback will never be made. + void Cancel() { + callback_.Reset(); + verify_result_ = NULL; + net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); + net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); + } + + // Copies the contents of |verify_result| to the caller's + // CertVerifyResult and calls the callback. + void Post(const MultiThreadedCertVerifier::CachedResult& verify_result) { + if (!callback_.is_null()) { + net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_REQUEST, NULL); + *verify_result_ = verify_result.result; + callback_.Run(verify_result.error); + } + delete this; + } + + bool canceled() const { return callback_.is_null(); } + + const BoundNetLog& net_log() const { return net_log_; } + + private: + CompletionCallback callback_; + CertVerifyResult* verify_result_; + const BoundNetLog net_log_; +}; + + +// CertVerifierWorker runs on a worker thread and takes care of the blocking +// process of performing the certificate verification. Deletes itself +// eventually if Start() succeeds. +class CertVerifierWorker { + public: + CertVerifierWorker(X509Certificate* cert, + const std::string& hostname, + int flags, + CRLSet* crl_set, + MultiThreadedCertVerifier* cert_verifier) + : cert_(cert), + hostname_(hostname), + flags_(flags), + crl_set_(crl_set), + origin_loop_(MessageLoop::current()), + cert_verifier_(cert_verifier), + canceled_(false), + error_(ERR_FAILED) { + } + + // Returns the certificate being verified. May only be called /before/ + // Start() is called. + X509Certificate* certificate() const { return cert_; } + + bool Start() { + DCHECK_EQ(MessageLoop::current(), origin_loop_); + + return base::WorkerPool::PostTask( + FROM_HERE, base::Bind(&CertVerifierWorker::Run, base::Unretained(this)), + true /* task is slow */); + } + + // Cancel is called from the origin loop when the MultiThreadedCertVerifier is + // getting deleted. + void Cancel() { + DCHECK_EQ(MessageLoop::current(), origin_loop_); + base::AutoLock locked(lock_); + canceled_ = true; + } + + private: + void Run() { + // Runs on a worker thread. + error_ = cert_->Verify(hostname_, flags_, crl_set_, &verify_result_); +#if defined(USE_NSS) + // Detach the thread from NSPR. + // Calling NSS functions attaches the thread to NSPR, which stores + // the NSPR thread ID in thread-specific data. + // The threads in our thread pool terminate after we have called + // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets + // segfaults on shutdown when the threads' thread-specific data + // destructors run. + PR_DetachThread(); +#endif + Finish(); + } + + // DoReply runs on the origin thread. + void DoReply() { + DCHECK_EQ(MessageLoop::current(), origin_loop_); + { + // We lock here because the worker thread could still be in Finished, + // after the PostTask, but before unlocking |lock_|. If we do not lock in + // this case, we will end up deleting a locked Lock, which can lead to + // memory leaks or worse errors. + base::AutoLock locked(lock_); + if (!canceled_) { + cert_verifier_->HandleResult(cert_, hostname_, flags_, + error_, verify_result_); + } + } + delete this; + } + + void Finish() { + // Runs on the worker thread. + // We assume that the origin loop outlives the MultiThreadedCertVerifier. If + // the MultiThreadedCertVerifier is deleted, it will call Cancel on us. If + // it does so before the Acquire, we'll delete ourselves and return. If it's + // trying to do so concurrently, then it'll block on the lock and we'll call + // PostTask while the MultiThreadedCertVerifier (and therefore the + // MessageLoop) is still alive. + // If it does so after this function, we assume that the MessageLoop will + // process pending tasks. In which case we'll notice the |canceled_| flag + // in DoReply. + + bool canceled; + { + base::AutoLock locked(lock_); + canceled = canceled_; + if (!canceled) { + origin_loop_->PostTask( + FROM_HERE, base::Bind( + &CertVerifierWorker::DoReply, base::Unretained(this))); + } + } + + if (canceled) + delete this; + } + + scoped_refptr cert_; + const std::string hostname_; + const int flags_; + scoped_refptr crl_set_; + MessageLoop* const origin_loop_; + MultiThreadedCertVerifier* const cert_verifier_; + + // lock_ protects canceled_. + base::Lock lock_; + + // If canceled_ is true, + // * origin_loop_ cannot be accessed by the worker thread, + // * cert_verifier_ cannot be accessed by any thread. + bool canceled_; + + int error_; + CertVerifyResult verify_result_; + + DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker); +}; + +// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It +// lives only on the CertVerifier's origin message loop. +class CertVerifierJob { + public: + CertVerifierJob(CertVerifierWorker* worker, + const BoundNetLog& net_log) + : start_time_(base::TimeTicks::Now()), + worker_(worker), + net_log_(net_log) { + scoped_refptr params( + new X509CertificateNetLogParam(worker_->certificate())); + net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_JOB, params); + } + + ~CertVerifierJob() { + if (worker_) { + net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); + net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL); + worker_->Cancel(); + DeleteAllCanceled(); + } + } + + void AddRequest(CertVerifierRequest* request) { + request->net_log().AddEvent( + NetLog::TYPE_CERT_VERIFIER_REQUEST_BOUND_TO_JOB, + make_scoped_refptr(new NetLogSourceParameter( + "source_dependency", net_log_.source()))); + + requests_.push_back(request); + } + + void HandleResult( + const MultiThreadedCertVerifier::CachedResult& verify_result) { + worker_ = NULL; + net_log_.EndEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL); + UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency", + base::TimeTicks::Now() - start_time_, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMinutes(10), + 100); + PostAll(verify_result); + } + + private: + void PostAll(const MultiThreadedCertVerifier::CachedResult& verify_result) { + std::vector requests; + requests_.swap(requests); + + for (std::vector::iterator + i = requests.begin(); i != requests.end(); i++) { + (*i)->Post(verify_result); + // Post() causes the CertVerifierRequest to delete itself. + } + } + + void DeleteAllCanceled() { + for (std::vector::iterator + i = requests_.begin(); i != requests_.end(); i++) { + if ((*i)->canceled()) { + delete *i; + } else { + LOG(DFATAL) << "CertVerifierRequest leaked!"; + } + } + } + + const base::TimeTicks start_time_; + std::vector requests_; + CertVerifierWorker* worker_; + const BoundNetLog net_log_; +}; + +MultiThreadedCertVerifier::MultiThreadedCertVerifier() + : cache_(kMaxCacheEntries), + requests_(0), + cache_hits_(0), + inflight_joins_(0) { + CertDatabase::AddObserver(this); +} + +MultiThreadedCertVerifier::~MultiThreadedCertVerifier() { + STLDeleteValues(&inflight_); + + CertDatabase::RemoveObserver(this); +} + +int MultiThreadedCertVerifier::Verify(X509Certificate* cert, + const std::string& hostname, + int flags, + CRLSet* crl_set, + CertVerifyResult* verify_result, + const CompletionCallback& callback, + RequestHandle* out_req, + const BoundNetLog& net_log) { + DCHECK(CalledOnValidThread()); + + if (callback.is_null() || !verify_result || hostname.empty()) { + *out_req = NULL; + return ERR_INVALID_ARGUMENT; + } + + requests_++; + + const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), + hostname, flags); + const CertVerifierCache::value_type* cached_entry = + cache_.Get(key, base::TimeTicks::Now()); + if (cached_entry) { + ++cache_hits_; + *out_req = NULL; + *verify_result = cached_entry->result; + return cached_entry->error; + } + + // No cache hit. See if an identical request is currently in flight. + CertVerifierJob* job; + std::map::const_iterator j; + j = inflight_.find(key); + if (j != inflight_.end()) { + // An identical request is in flight already. We'll just attach our + // callback. + inflight_joins_++; + job = j->second; + } else { + // Need to make a new request. + CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags, + crl_set, this); + job = new CertVerifierJob( + worker, + BoundNetLog::Make(net_log.net_log(), NetLog::SOURCE_CERT_VERIFIER_JOB)); + if (!worker->Start()) { + delete job; + delete worker; + *out_req = NULL; + // TODO(wtc): log to the NetLog. + LOG(ERROR) << "CertVerifierWorker couldn't be started."; + return ERR_INSUFFICIENT_RESOURCES; // Just a guess. + } + inflight_.insert(std::make_pair(key, job)); + } + + CertVerifierRequest* request = + new CertVerifierRequest(callback, verify_result, net_log); + job->AddRequest(request); + *out_req = request; + return ERR_IO_PENDING; +} + +void MultiThreadedCertVerifier::CancelRequest(RequestHandle req) { + DCHECK(CalledOnValidThread()); + CertVerifierRequest* request = reinterpret_cast(req); + request->Cancel(); +} + +// HandleResult is called by CertVerifierWorker on the origin message loop. +// It deletes CertVerifierJob. +void MultiThreadedCertVerifier::HandleResult( + X509Certificate* cert, + const std::string& hostname, + int flags, + int error, + const CertVerifyResult& verify_result) { + DCHECK(CalledOnValidThread()); + + const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), + hostname, flags); + + CachedResult cached_result; + cached_result.error = error; + cached_result.result = verify_result; + cache_.Put(key, cached_result, base::TimeTicks::Now(), + base::TimeDelta::FromSeconds(kTTLSecs)); + + std::map::iterator j; + j = inflight_.find(key); + if (j == inflight_.end()) { + NOTREACHED(); + return; + } + CertVerifierJob* job = j->second; + inflight_.erase(j); + + job->HandleResult(cached_result); + delete job; +} + +void MultiThreadedCertVerifier::OnCertTrustChanged( + const X509Certificate* cert) { + DCHECK(CalledOnValidThread()); + + ClearCache(); +} + +} // namespace net diff --git a/net/base/multi_threaded_cert_verifier.h b/net/base/multi_threaded_cert_verifier.h new file mode 100644 index 00000000000000..c8eca2e2cded6a --- /dev/null +++ b/net/base/multi_threaded_cert_verifier.h @@ -0,0 +1,142 @@ +// Copyright (c) 2012 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 NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_ +#define NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_ +#pragma once + +#include +#include + +#include "base/basictypes.h" +#include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/threading/non_thread_safe.h" +#include "net/base/cert_database.h" +#include "net/base/cert_verifier.h" +#include "net/base/cert_verify_result.h" +#include "net/base/completion_callback.h" +#include "net/base/expiring_cache.h" +#include "net/base/net_export.h" +#include "net/base/x509_cert_types.h" + +namespace net { + +class CertVerifierJob; +class CertVerifierRequest; +class CertVerifierWorker; + +// MultiThreadedCertVerifier is a CertVerifier implementation that runs +// synchronous CertVerifier implementations on worker threads. +class NET_EXPORT MultiThreadedCertVerifier : + public CertVerifier, + NON_EXPORTED_BASE(public base::NonThreadSafe), + public CertDatabase::Observer { + public: + MultiThreadedCertVerifier(); + + // When the verifier is destroyed, all certificate verifications requests are + // canceled, and their completion callbacks will not be called. + virtual ~MultiThreadedCertVerifier(); + + // CertVerifier implementation + virtual int Verify(X509Certificate* cert, + const std::string& hostname, + int flags, + CRLSet* crl_set, + CertVerifyResult* verify_result, + const CompletionCallback& callback, + CertVerifier::RequestHandle* out_req, + const BoundNetLog& net_log) OVERRIDE; + + virtual void CancelRequest(CertVerifier::RequestHandle req) OVERRIDE; + + private: + friend class CertVerifierWorker; // Calls HandleResult. + friend class CertVerifierRequest; + friend class CertVerifierJob; + FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, CacheHit); + FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, DifferentCACerts); + FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, InflightJoin); + FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, CancelRequest); + FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, + RequestParamsComparators); + + // Input parameters of a certificate verification request. + struct RequestParams { + RequestParams(const SHA1Fingerprint& cert_fingerprint_arg, + const SHA1Fingerprint& ca_fingerprint_arg, + const std::string& hostname_arg, + int flags_arg) + : cert_fingerprint(cert_fingerprint_arg), + ca_fingerprint(ca_fingerprint_arg), + hostname(hostname_arg), + flags(flags_arg) {} + + bool operator<(const RequestParams& other) const { + // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, and + // |hostname| under assumption that integer comparisons are faster than + // memory and string comparisons. + if (flags != other.flags) + return flags < other.flags; + int rv = memcmp(cert_fingerprint.data, other.cert_fingerprint.data, + sizeof(cert_fingerprint.data)); + if (rv != 0) + return rv < 0; + rv = memcmp(ca_fingerprint.data, other.ca_fingerprint.data, + sizeof(ca_fingerprint.data)); + if (rv != 0) + return rv < 0; + return hostname < other.hostname; + } + + SHA1Fingerprint cert_fingerprint; + SHA1Fingerprint ca_fingerprint; + std::string hostname; + int flags; + }; + + // CachedResult contains the result of a certificate verification. + struct CachedResult { + CachedResult(); + ~CachedResult(); + + int error; // The return value of CertVerifier::Verify. + CertVerifyResult result; // The output of CertVerifier::Verify. + }; + + void HandleResult(X509Certificate* cert, + const std::string& hostname, + int flags, + int error, + const CertVerifyResult& verify_result); + + // CertDatabase::Observer methods: + virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE; + + // For unit testing. + void ClearCache() { cache_.Clear(); } + size_t GetCacheSize() const { return cache_.size(); } + uint64 cache_hits() const { return cache_hits_; } + uint64 requests() const { return requests_; } + uint64 inflight_joins() const { return inflight_joins_; } + + // cache_ maps from a request to a cached result. + typedef ExpiringCache CertVerifierCache; + CertVerifierCache cache_; + + // inflight_ maps from a request to an active verification which is taking + // place. + std::map inflight_; + + uint64 requests_; + uint64 cache_hits_; + uint64 inflight_joins_; + + DISALLOW_COPY_AND_ASSIGN(MultiThreadedCertVerifier); +}; + +} // namespace net + +#endif // NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_ diff --git a/net/base/cert_verifier_unittest.cc b/net/base/multi_threaded_cert_verifier_unittest.cc similarity index 81% rename from net/base/cert_verifier_unittest.cc rename to net/base/multi_threaded_cert_verifier_unittest.cc index 9d2528ce4e874c..17eed9904a6d66 100644 --- a/net/base/cert_verifier_unittest.cc +++ b/net/base/multi_threaded_cert_verifier_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/base/cert_verifier.h" +#include "net/base/multi_threaded_cert_verifier.h" #include "base/bind.h" #include "base/file_path.h" @@ -32,8 +32,8 @@ void FailTest(int /* result */) { #else #define MAYBE_CacheHit CacheHit #endif // defined(OS_MACOSX) -TEST(CertVerifierTest, MAYBE_CacheHit) { - CertVerifier verifier; +TEST(MultiThreadedCertVerifierTest, MAYBE_CacheHit) { + MultiThreadedCertVerifier verifier; FilePath certs_dir = GetTestCertsDirectory(); scoped_refptr test_cert( @@ -71,8 +71,8 @@ TEST(CertVerifierTest, MAYBE_CacheHit) { // Tests the same server certificate with different intermediate CA // certificates. These should be treated as different certificate chains even // though the two X509Certificate objects contain the same server certificate. -TEST(CertVerifierTest, DifferentCACerts) { - CertVerifier verifier; +TEST(MultiThreadedCertVerifierTest, DifferentCACerts) { + MultiThreadedCertVerifier verifier; FilePath certs_dir = GetTestCertsDirectory(); @@ -131,8 +131,8 @@ TEST(CertVerifierTest, DifferentCACerts) { } // Tests an inflight join. -TEST(CertVerifierTest, InflightJoin) { - CertVerifier verifier; +TEST(MultiThreadedCertVerifierTest, InflightJoin) { + MultiThreadedCertVerifier verifier; FilePath certs_dir = GetTestCertsDirectory(); scoped_refptr test_cert( @@ -166,8 +166,8 @@ TEST(CertVerifierTest, InflightJoin) { } // Tests that the callback of a canceled request is never made. -TEST(CertVerifierTest, CancelRequest) { - CertVerifier verifier; +TEST(MultiThreadedCertVerifierTest, CancelRequest) { + MultiThreadedCertVerifier verifier; FilePath certs_dir = GetTestCertsDirectory(); scoped_refptr test_cert( @@ -201,8 +201,8 @@ TEST(CertVerifierTest, CancelRequest) { } // Tests that a canceled request is not leaked. -TEST(CertVerifierTest, CancelRequestThenQuit) { - CertVerifier verifier; +TEST(MultiThreadedCertVerifierTest, CancelRequestThenQuit) { + MultiThreadedCertVerifier verifier; FilePath certs_dir = GetTestCertsDirectory(); scoped_refptr test_cert( @@ -222,7 +222,7 @@ TEST(CertVerifierTest, CancelRequestThenQuit) { // Destroy |verifier| by going out of scope. } -TEST(CertVerifierTest, RequestParamsComparators) { +TEST(MultiThreadedCertVerifierTest, RequestParamsComparators) { SHA1Fingerprint a_key; memset(a_key.data, 'a', sizeof(a_key.data)); @@ -231,8 +231,8 @@ TEST(CertVerifierTest, RequestParamsComparators) { struct { // Keys to test - CertVerifier::RequestParams key1; - CertVerifier::RequestParams key2; + MultiThreadedCertVerifier::RequestParams key1; + MultiThreadedCertVerifier::RequestParams key2; // Expectation: // -1 means key1 is less than key2 @@ -241,41 +241,50 @@ TEST(CertVerifierTest, RequestParamsComparators) { int expected_result; } tests[] = { { // Test for basic equivalence. - CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0), - CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0), + MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", + 0), + MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", + 0), 0, }, { // Test that different certificates but with the same CA and for // the same host are different validation keys. - CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0), - CertVerifier::RequestParams(z_key, a_key, "www.example.test", 0), + MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", + 0), + MultiThreadedCertVerifier::RequestParams(z_key, a_key, "www.example.test", + 0), -1, }, { // Test that the same EE certificate for the same host, but with // different chains are different validation keys. - CertVerifier::RequestParams(a_key, z_key, "www.example.test", 0), - CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0), + MultiThreadedCertVerifier::RequestParams(a_key, z_key, "www.example.test", + 0), + MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", + 0), 1, }, { // The same certificate, with the same chain, but for different // hosts are different validation keys. - CertVerifier::RequestParams(a_key, a_key, "www1.example.test", 0), - CertVerifier::RequestParams(a_key, a_key, "www2.example.test", 0), + MultiThreadedCertVerifier::RequestParams(a_key, a_key, + "www1.example.test", 0), + MultiThreadedCertVerifier::RequestParams(a_key, a_key, + "www2.example.test", 0), -1, }, { // The same certificate, chain, and host, but with different flags // are different validation keys. - CertVerifier::RequestParams(a_key, a_key, "www.example.test", - X509Certificate::VERIFY_EV_CERT), - CertVerifier::RequestParams(a_key, a_key, "www.example.test", 0), + MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", + X509Certificate::VERIFY_EV_CERT), + MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", + 0), 1, } }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i)); - const CertVerifier::RequestParams& key1 = tests[i].key1; - const CertVerifier::RequestParams& key2 = tests[i].key2; + const MultiThreadedCertVerifier::RequestParams& key1 = tests[i].key1; + const MultiThreadedCertVerifier::RequestParams& key2 = tests[i].key2; switch (tests[i].expected_result) { case -1: diff --git a/net/base/single_request_cert_verifier.cc b/net/base/single_request_cert_verifier.cc new file mode 100644 index 00000000000000..337060047d0186 --- /dev/null +++ b/net/base/single_request_cert_verifier.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2012 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 "net/base/single_request_cert_verifier.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "net/base/net_errors.h" +#include "net/base/x509_certificate.h" + +namespace net { + +SingleRequestCertVerifier::SingleRequestCertVerifier( + CertVerifier* cert_verifier) + : cert_verifier_(cert_verifier), + cur_request_(NULL) { + DCHECK(cert_verifier_ != NULL); +} + +SingleRequestCertVerifier::~SingleRequestCertVerifier() { + if (cur_request_) { + cert_verifier_->CancelRequest(cur_request_); + cur_request_ = NULL; + } +} + +int SingleRequestCertVerifier::Verify(X509Certificate* cert, + const std::string& hostname, + int flags, + CRLSet* crl_set, + CertVerifyResult* verify_result, + const CompletionCallback& callback, + const BoundNetLog& net_log) { + // Should not be already in use. + DCHECK(!cur_request_ && cur_request_callback_.is_null()); + + // Do a synchronous verification. + if (callback.is_null()) + return cert->Verify(hostname, flags, crl_set, verify_result); + + CertVerifier::RequestHandle request = NULL; + + // We need to be notified of completion before |callback| is called, so that + // we can clear out |cur_request_*|. + int rv = cert_verifier_->Verify( + cert, hostname, flags, crl_set, verify_result, + base::Bind(&SingleRequestCertVerifier::OnVerifyCompletion, + base::Unretained(this)), + &request, net_log); + + if (rv == ERR_IO_PENDING) { + // Cleared in OnVerifyCompletion(). + cur_request_ = request; + cur_request_callback_ = callback; + } + + return rv; +} + +void SingleRequestCertVerifier::OnVerifyCompletion(int result) { + DCHECK(cur_request_ && !cur_request_callback_.is_null()); + + CompletionCallback callback = cur_request_callback_; + + // Clear the outstanding request information. + cur_request_ = NULL; + cur_request_callback_.Reset(); + + // Call the user's original callback. + callback.Run(result); +} + +} // namespace net diff --git a/net/base/single_request_cert_verifier.h b/net/base/single_request_cert_verifier.h new file mode 100644 index 00000000000000..6ae8bb6deb6186 --- /dev/null +++ b/net/base/single_request_cert_verifier.h @@ -0,0 +1,53 @@ +// Copyright (c) 2012 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 NET_BASE_SINGLE_REQUEST_CERT_VERIFIER_H_ +#define NET_BASE_SINGLE_REQUEST_CERT_VERIFIER_H_ +#pragma once + +#include "net/base/cert_verifier.h" + +namespace net { + +// This class represents the task of verifying a certificate. It wraps +// CertVerifier to verify only a single certificate at a time and cancels this +// request when going out of scope. +class SingleRequestCertVerifier { + public: + // |cert_verifier| must remain valid for the lifetime of |this|. + explicit SingleRequestCertVerifier(CertVerifier* cert_verifier); + + // If a completion callback is pending when the verifier is destroyed, the + // certificate verification is canceled, and the completion callback will + // not be called. + ~SingleRequestCertVerifier(); + + // Verifies the given certificate, filling out the |verify_result| object + // upon success. See CertVerifier::Verify() for details. + int Verify(X509Certificate* cert, + const std::string& hostname, + int flags, + CRLSet* crl_set, + CertVerifyResult* verify_result, + const CompletionCallback& callback, + const BoundNetLog& net_log); + + private: + // Callback for when the request to |cert_verifier_| completes, so we + // dispatch to the user's callback. + void OnVerifyCompletion(int result); + + // The actual certificate verifier that will handle the request. + CertVerifier* const cert_verifier_; + + // The current request (if any). + CertVerifier::RequestHandle cur_request_; + CompletionCallback cur_request_callback_; + + DISALLOW_COPY_AND_ASSIGN(SingleRequestCertVerifier); +}; + +} // namespace net + +#endif // NET_BASE_SINGLE_REQUEST_CERT_VERIFIER_H_ diff --git a/net/base/transport_security_state_unittest.cc b/net/base/transport_security_state_unittest.cc index 3fc656286e31cb..cc681dd56fc990 100644 --- a/net/base/transport_security_state_unittest.cc +++ b/net/base/transport_security_state_unittest.cc @@ -14,6 +14,7 @@ #include "net/base/asn1_util.h" #include "net/base/cert_test_util.h" #include "net/base/cert_verifier.h" +#include "net/base/cert_verify_result.h" #include "net/base/ssl_info.h" #include "net/base/test_root_certs.h" #include "net/base/x509_certificate.h" diff --git a/net/http/disk_cache_based_ssl_host_info_unittest.cc b/net/http/disk_cache_based_ssl_host_info_unittest.cc index 9fb4727b1d3d60..41b200ff2746cf 100644 --- a/net/http/disk_cache_based_ssl_host_info_unittest.cc +++ b/net/http/disk_cache_based_ssl_host_info_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -6,6 +6,7 @@ #include "base/bind_helpers.h" #include "base/compiler_specific.h" #include "base/message_loop.h" +#include "net/base/cert_verifier.h" #include "net/base/net_errors.h" #include "net/base/ssl_config_service.h" #include "net/http/disk_cache_based_ssl_host_info.h" @@ -33,7 +34,8 @@ const MockTransaction kHostInfoTransaction = { // Tests that we can delete a DiskCacheBasedSSLHostInfo object in a // completion callback for DiskCacheBasedSSLHostInfo::WaitForDataReady. TEST(DiskCacheBasedSSLHostInfo, DeleteInCallback) { - net::CertVerifier cert_verifier; + scoped_ptr cert_verifier( + net::CertVerifier::CreateDefault()); // Use the blocking mock backend factory to force asynchronous completion // of ssl_host_info->WaitForDataReady(), so that the callback will run. MockBlockingBackendFactory* factory = new MockBlockingBackendFactory(); @@ -41,7 +43,8 @@ TEST(DiskCacheBasedSSLHostInfo, DeleteInCallback) { net::SSLConfig ssl_config; scoped_ptr ssl_host_info( new net::DiskCacheBasedSSLHostInfo("https://www.verisign.com", ssl_config, - &cert_verifier, cache.http_cache())); + cert_verifier.get(), + cache.http_cache())); ssl_host_info->Start(); net::TestCompletionCallback callback; int rv = ssl_host_info->WaitForDataReady(callback.callback()); @@ -58,11 +61,13 @@ TEST(DiskCacheBasedSSLHostInfo, Update) { net::TestCompletionCallback callback; // Store a certificate chain. - net::CertVerifier cert_verifier; + scoped_ptr cert_verifier( + net::CertVerifier::CreateDefault()); net::SSLConfig ssl_config; scoped_ptr ssl_host_info( new net::DiskCacheBasedSSLHostInfo("https://www.google.com", ssl_config, - &cert_verifier, cache.http_cache())); + cert_verifier.get(), + cache.http_cache())); ssl_host_info->Start(); int rv = ssl_host_info->WaitForDataReady(callback.callback()); EXPECT_EQ(net::OK, callback.GetResult(rv)); @@ -78,7 +83,8 @@ TEST(DiskCacheBasedSSLHostInfo, Update) { // Open the stored certificate chain. ssl_host_info.reset( new net::DiskCacheBasedSSLHostInfo("https://www.google.com", ssl_config, - &cert_verifier, cache.http_cache())); + cert_verifier.get(), + cache.http_cache())); ssl_host_info->Start(); rv = ssl_host_info->WaitForDataReady(callback.callback()); EXPECT_EQ(net::OK, callback.GetResult(rv)); @@ -97,7 +103,8 @@ TEST(DiskCacheBasedSSLHostInfo, Update) { // Verify that the state was updated. ssl_host_info.reset( new net::DiskCacheBasedSSLHostInfo("https://www.google.com", ssl_config, - &cert_verifier, cache.http_cache())); + cert_verifier.get(), + cache.http_cache())); ssl_host_info->Start(); rv = ssl_host_info->WaitForDataReady(callback.callback()); EXPECT_EQ(net::OK, callback.GetResult(rv)); diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc index bdb777c0ad1fe0..596b1ab2b60003 100644 --- a/net/http/http_network_layer_unittest.cc +++ b/net/http/http_network_layer_unittest.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "net/http/http_network_layer.h" + #include "net/base/cert_verifier.h" #include "net/base/mock_host_resolver.h" #include "net/base/net_log.h" #include "net/base/ssl_config_service_defaults.h" -#include "net/http/http_network_layer.h" #include "net/http/http_network_session.h" #include "net/http/http_server_properties_impl.h" #include "net/http/http_transaction_unittest.h" @@ -23,12 +24,13 @@ namespace { class HttpNetworkLayerTest : public PlatformTest { protected: HttpNetworkLayerTest() - : proxy_service_(ProxyService::CreateDirect()), + : cert_verifier_(CertVerifier::CreateDefault()), + proxy_service_(ProxyService::CreateDirect()), ssl_config_service_(new SSLConfigServiceDefaults) { HttpNetworkSession::Params session_params; session_params.client_socket_factory = &mock_socket_factory_; session_params.host_resolver = &host_resolver_; - session_params.cert_verifier = &cert_verifier_; + session_params.cert_verifier = cert_verifier_.get(); session_params.proxy_service = proxy_service_.get(); session_params.ssl_config_service = ssl_config_service_; session_params.http_server_properties = &http_server_properties_; @@ -38,7 +40,7 @@ class HttpNetworkLayerTest : public PlatformTest { MockClientSocketFactory mock_socket_factory_; MockHostResolver host_resolver_; - CertVerifier cert_verifier_; + scoped_ptr cert_verifier_; const scoped_ptr proxy_service_; const scoped_refptr ssl_config_service_; scoped_refptr network_session_; diff --git a/net/http/http_network_transaction_spdy21_unittest.cc b/net/http/http_network_transaction_spdy21_unittest.cc index 0f21f9d797e969..fed205f9706bab 100644 --- a/net/http/http_network_transaction_spdy21_unittest.cc +++ b/net/http/http_network_transaction_spdy21_unittest.cc @@ -122,7 +122,7 @@ struct SessionDependencies { // Default set of dependencies -- "null" proxy service. SessionDependencies() : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(ProxyService::CreateDirect()), ssl_config_service(new SSLConfigServiceDefaults), http_auth_handler_factory( @@ -132,7 +132,7 @@ struct SessionDependencies { // Custom proxy service dependency. explicit SessionDependencies(ProxyService* proxy_service) : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(proxy_service), ssl_config_service(new SSLConfigServiceDefaults), http_auth_handler_factory( diff --git a/net/http/http_network_transaction_spdy2_unittest.cc b/net/http/http_network_transaction_spdy2_unittest.cc index b09ca1194007cd..49d5ae55d5ede0 100644 --- a/net/http/http_network_transaction_spdy2_unittest.cc +++ b/net/http/http_network_transaction_spdy2_unittest.cc @@ -122,7 +122,7 @@ struct SessionDependencies { // Default set of dependencies -- "null" proxy service. SessionDependencies() : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(ProxyService::CreateDirect()), ssl_config_service(new SSLConfigServiceDefaults), http_auth_handler_factory( @@ -132,7 +132,7 @@ struct SessionDependencies { // Custom proxy service dependency. explicit SessionDependencies(ProxyService* proxy_service) : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(proxy_service), ssl_config_service(new SSLConfigServiceDefaults), http_auth_handler_factory( diff --git a/net/http/http_network_transaction_spdy3_unittest.cc b/net/http/http_network_transaction_spdy3_unittest.cc index 631e80351b49c6..40529594f625fe 100644 --- a/net/http/http_network_transaction_spdy3_unittest.cc +++ b/net/http/http_network_transaction_spdy3_unittest.cc @@ -19,6 +19,7 @@ #include "base/utf_string_conversions.h" #include "net/base/auth.h" #include "net/base/capturing_net_log.h" +#include "net/base/cert_verifier.h" #include "net/base/completion_callback.h" #include "net/base/host_cache.h" #include "net/base/mock_host_resolver.h" @@ -122,7 +123,7 @@ struct SessionDependencies { // Default set of dependencies -- "null" proxy service. SessionDependencies() : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(ProxyService::CreateDirect()), ssl_config_service(new SSLConfigServiceDefaults), http_auth_handler_factory( @@ -132,7 +133,7 @@ struct SessionDependencies { // Custom proxy service dependency. explicit SessionDependencies(ProxyService* proxy_service) : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(proxy_service), ssl_config_service(new SSLConfigServiceDefaults), http_auth_handler_factory( diff --git a/net/http/http_proxy_client_socket_pool_spdy21_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy21_unittest.cc index 25f8c642ff66dc..ba0b9e11be80ba 100644 --- a/net/http/http_proxy_client_socket_pool_spdy21_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_spdy21_unittest.cc @@ -63,12 +63,13 @@ class HttpProxyClientSocketPoolSpdy21Test : public TestWithHttpParam { &tcp_histograms_, &socket_factory_), ssl_histograms_("MockSSL"), + cert_verifier_(CertVerifier::CreateDefault()), proxy_service_(ProxyService::CreateDirect()), ssl_config_service_(new SSLConfigServiceDefaults), ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup, &ssl_histograms_, &host_resolver_, - &cert_verifier_, + cert_verifier_.get(), NULL /* server_bound_cert_store */, NULL /* transport_security_state */, NULL /* ssl_host_info_factory */, @@ -181,7 +182,7 @@ class HttpProxyClientSocketPoolSpdy21Test : public TestWithHttpParam { HttpNetworkSession* CreateNetworkSession() { HttpNetworkSession::Params params; params.host_resolver = &host_resolver_; - params.cert_verifier = &cert_verifier_; + params.cert_verifier = cert_verifier_.get(); params.proxy_service = proxy_service_.get(); params.client_socket_factory = &socket_factory_; params.ssl_config_service = ssl_config_service_; @@ -200,7 +201,7 @@ class HttpProxyClientSocketPoolSpdy21Test : public TestWithHttpParam { MockTransportClientSocketPool transport_socket_pool_; ClientSocketPoolHistograms ssl_histograms_; MockHostResolver host_resolver_; - CertVerifier cert_verifier_; + scoped_ptr cert_verifier_; const scoped_ptr proxy_service_; const scoped_refptr ssl_config_service_; SSLClientSocketPool ssl_socket_pool_; diff --git a/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc index f54e7d20381fbe..00e55b36a41fd0 100644 --- a/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_spdy2_unittest.cc @@ -63,12 +63,13 @@ class HttpProxyClientSocketPoolSpdy2Test : public TestWithHttpParam { &tcp_histograms_, &socket_factory_), ssl_histograms_("MockSSL"), + cert_verifier_(CertVerifier::CreateDefault()), proxy_service_(ProxyService::CreateDirect()), ssl_config_service_(new SSLConfigServiceDefaults), ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup, &ssl_histograms_, &host_resolver_, - &cert_verifier_, + cert_verifier_.get(), NULL /* server_bound_cert_store */, NULL /* transport_security_state */, NULL /* ssl_host_info_factory */, @@ -181,7 +182,7 @@ class HttpProxyClientSocketPoolSpdy2Test : public TestWithHttpParam { HttpNetworkSession* CreateNetworkSession() { HttpNetworkSession::Params params; params.host_resolver = &host_resolver_; - params.cert_verifier = &cert_verifier_; + params.cert_verifier = cert_verifier_.get(); params.proxy_service = proxy_service_.get(); params.client_socket_factory = &socket_factory_; params.ssl_config_service = ssl_config_service_; @@ -200,7 +201,7 @@ class HttpProxyClientSocketPoolSpdy2Test : public TestWithHttpParam { MockTransportClientSocketPool transport_socket_pool_; ClientSocketPoolHistograms ssl_histograms_; MockHostResolver host_resolver_; - CertVerifier cert_verifier_; + scoped_ptr cert_verifier_; const scoped_ptr proxy_service_; const scoped_refptr ssl_config_service_; SSLClientSocketPool ssl_socket_pool_; diff --git a/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc b/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc index 0bc603ed1c6d0f..4aead9067a6b71 100644 --- a/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_spdy3_unittest.cc @@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" +#include "net/base/cert_verifier.h" #include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" #include "net/base/ssl_config_service_defaults.h" @@ -63,12 +64,13 @@ class HttpProxyClientSocketPoolSpdy3Test : public TestWithHttpParam { &tcp_histograms_, &socket_factory_), ssl_histograms_("MockSSL"), + cert_verifier_(CertVerifier::CreateDefault()), proxy_service_(ProxyService::CreateDirect()), ssl_config_service_(new SSLConfigServiceDefaults), ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup, &ssl_histograms_, &host_resolver_, - &cert_verifier_, + cert_verifier_.get(), NULL /* server_bound_cert_store */, NULL /* transport_security_state */, NULL /* ssl_host_info_factory */, @@ -181,7 +183,7 @@ class HttpProxyClientSocketPoolSpdy3Test : public TestWithHttpParam { HttpNetworkSession* CreateNetworkSession() { HttpNetworkSession::Params params; params.host_resolver = &host_resolver_; - params.cert_verifier = &cert_verifier_; + params.cert_verifier = cert_verifier_.get(); params.proxy_service = proxy_service_.get(); params.client_socket_factory = &socket_factory_; params.ssl_config_service = ssl_config_service_; @@ -200,7 +202,7 @@ class HttpProxyClientSocketPoolSpdy3Test : public TestWithHttpParam { MockTransportClientSocketPool transport_socket_pool_; ClientSocketPoolHistograms ssl_histograms_; MockHostResolver host_resolver_; - CertVerifier cert_verifier_; + scoped_ptr cert_verifier_; const scoped_ptr proxy_service_; const scoped_refptr ssl_config_service_; SSLClientSocketPool ssl_socket_pool_; diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc index d55425610b7ef3..c69ef8f0d9fa2a 100644 --- a/net/http/http_stream_factory_impl_unittest.cc +++ b/net/http/http_stream_factory_impl_unittest.cc @@ -118,7 +118,7 @@ struct SessionDependencies { // Custom proxy service dependency. explicit SessionDependencies(ProxyService* proxy_service) : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(proxy_service), ssl_config_service(new SSLConfigServiceDefaults), http_auth_handler_factory( diff --git a/net/net.gyp b/net/net.gyp index 4360fc018d1082..5c70b88acb65b3 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -154,6 +154,8 @@ 'base/mime_sniffer.h', 'base/mime_util.cc', 'base/mime_util.h', + 'base/multi_threaded_cert_verifier.cc', + 'base/multi_threaded_cert_verifier.h', 'base/net_error_list.h', 'base/net_errors.cc', 'base/net_errors.h', @@ -212,6 +214,8 @@ 'base/sdch_filter.h', 'base/sdch_manager.cc', 'base/sdch_manager.h', + 'base/single_request_cert_verifier.cc', + 'base/single_request_cert_verifier.h', 'base/single_request_host_resolver.cc', 'base/single_request_host_resolver.h', 'base/ssl_cert_request_info.cc', @@ -1019,7 +1023,6 @@ 'base/backoff_entry_unittest.cc', 'base/big_endian_unittest.cc', 'base/cert_database_nss_unittest.cc', - 'base/cert_verifier_unittest.cc', 'base/crl_set_unittest.cc', 'base/data_url_unittest.cc', 'base/default_origin_bound_cert_store_unittest.cc', @@ -1046,6 +1049,7 @@ 'base/mime_util_unittest.cc', 'base/mock_filter_context.cc', 'base/mock_filter_context.h', + 'base/multi_threaded_cert_verifier_unittest.cc', 'base/net_log_unittest.cc', 'base/net_log_unittest.h', 'base/net_util_unittest.cc', diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc index d29dcba23ce7fa..f3653933b2b3a1 100644 --- a/net/proxy/proxy_script_fetcher_impl_unittest.cc +++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc @@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/path_service.h" #include "base/utf_string_conversions.h" +#include "net/base/cert_verifier.h" #include "net/base/net_util.h" #include "net/base/load_flags.h" #include "net/base/ssl_config_service_defaults.h" @@ -72,7 +73,7 @@ class RequestContext : public URLRequestContext { CreateSystemHostResolver(HostResolver::kDefaultParallelism, HostResolver::kDefaultRetryAttempts, NULL)); - storage_.set_cert_verifier(new CertVerifier); + storage_.set_cert_verifier(CertVerifier::CreateDefault()); storage_.set_proxy_service(ProxyService::CreateFixed(no_proxy)); storage_.set_ssl_config_service(new SSLConfigServiceDefaults); storage_.set_http_server_properties(new HttpServerPropertiesImpl); diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc index 7bb1dcd00aa766..e847c15db5fc20 100644 --- a/net/socket/ssl_client_socket_mac.cc +++ b/net/socket/ssl_client_socket_mac.cc @@ -21,6 +21,7 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" +#include "net/base/single_request_cert_verifier.h" #include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 0d712e38754903..3ae9eb1b3b7db2 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -90,6 +90,7 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/net_log.h" +#include "net/base/single_request_cert_verifier.h" #include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index d691f2217491eb..3ee788668709d2 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc @@ -18,6 +18,7 @@ #include "net/base/cert_verifier.h" #include "net/base/net_errors.h" #include "net/base/openssl_private_key_store.h" +#include "net/base/single_request_cert_verifier.h" #include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc index c6896ec209ee35..0ca0cb88ad2215 100644 --- a/net/socket/ssl_client_socket_pool_unittest.cc +++ b/net/socket/ssl_client_socket_pool_unittest.cc @@ -137,7 +137,7 @@ class SSLClientSocketPoolTest : public testing::Test { HttpNetworkSession* CreateNetworkSession() { HttpNetworkSession::Params params; params.host_resolver = &host_resolver_; - params.cert_verifier = &cert_verifier_; + params.cert_verifier = cert_verifier_.get(); params.proxy_service = proxy_service_.get(); params.client_socket_factory = &socket_factory_; params.ssl_config_service = ssl_config_service_; @@ -148,7 +148,7 @@ class SSLClientSocketPoolTest : public testing::Test { MockClientSocketFactory socket_factory_; MockCachingHostResolver host_resolver_; - CertVerifier cert_verifier_; + scoped_ptr cert_verifier_; const scoped_ptr proxy_service_; const scoped_refptr ssl_config_service_; const scoped_ptr http_auth_handler_factory_; diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index c8dfc8a815f99e..85ef0a71314cd1 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc @@ -31,7 +31,7 @@ class SSLClientSocketTest : public PlatformTest { public: SSLClientSocketTest() : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()), - cert_verifier_(new net::CertVerifier) { + cert_verifier_(net::CertVerifier::CreateDefault()) { } protected: diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc index b2054eb5bd50b8..1442ad66209c9d 100644 --- a/net/socket/ssl_client_socket_win.cc +++ b/net/socket/ssl_client_socket_win.cc @@ -22,6 +22,7 @@ #include "net/base/io_buffer.h" #include "net/base/net_log.h" #include "net/base/net_errors.h" +#include "net/base/single_request_cert_verifier.h" #include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" diff --git a/net/socket/ssl_host_info.h b/net/socket/ssl_host_info.h index 34fb0efb9bb781..af2c418b7d9a2b 100644 --- a/net/socket/ssl_host_info.h +++ b/net/socket/ssl_host_info.h @@ -16,6 +16,7 @@ #include "net/base/cert_verify_result.h" #include "net/base/completion_callback.h" #include "net/base/net_export.h" +#include "net/base/single_request_cert_verifier.h" #include "net/socket/ssl_client_socket.h" namespace net { diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index ce998e408f26a1..ccb8ac1e92fbb3 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc @@ -245,7 +245,8 @@ TEST(FakeSocketTest, DataTransfer) { class SSLServerSocketTest : public PlatformTest { public: SSLServerSocketTest() - : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()) { + : socket_factory_(net::ClientSocketFactory::GetDefaultFactory()), + cert_verifier_(net::CertVerifier::CreateDefault()) { } protected: @@ -293,7 +294,7 @@ class SSLServerSocketTest : public PlatformTest { net::HostPortPair host_and_pair("unittest", 0); net::SSLClientSocketContext context; - context.cert_verifier = &cert_verifier_; + context.cert_verifier = cert_verifier_.get(); client_socket_.reset( socket_factory_->CreateSSLClientSocket( fake_client_socket, host_and_pair, ssl_config, NULL, context)); @@ -307,7 +308,7 @@ class SSLServerSocketTest : public PlatformTest { scoped_ptr client_socket_; scoped_ptr server_socket_; net::ClientSocketFactory* socket_factory_; - net::CertVerifier cert_verifier_; + scoped_ptr cert_verifier_; }; // SSLServerSocket is only implemented using NSS. diff --git a/net/spdy/spdy_test_util_spdy2.cc b/net/spdy/spdy_test_util_spdy2.cc index aadd177f55cbfa..9c095f424cde81 100644 --- a/net/spdy/spdy_test_util_spdy2.cc +++ b/net/spdy/spdy_test_util_spdy2.cc @@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/string_number_conversions.h" #include "base/string_util.h" +#include "net/base/cert_verifier.h" #include "net/http/http_network_session.h" #include "net/http/http_network_transaction.h" #include "net/http/http_server_properties_impl.h" @@ -903,7 +904,7 @@ int CombineFrames(const spdy::SpdyFrame** frames, int num_frames, SpdySessionDependencies::SpdySessionDependencies() : host_resolver(new MockCachingHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(ProxyService::CreateDirect()), ssl_config_service(new SSLConfigServiceDefaults), socket_factory(new MockClientSocketFactory), @@ -921,7 +922,7 @@ SpdySessionDependencies::SpdySessionDependencies() SpdySessionDependencies::SpdySessionDependencies(ProxyService* proxy_service) : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(proxy_service), ssl_config_service(new SSLConfigServiceDefaults), socket_factory(new MockClientSocketFactory), @@ -965,7 +966,7 @@ HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic( SpdyURLRequestContext::SpdyURLRequestContext() : ALLOW_THIS_IN_INITIALIZER_LIST(storage_(this)) { storage_.set_host_resolver(new MockHostResolver()); - storage_.set_cert_verifier(new CertVerifier); + storage_.set_cert_verifier(CertVerifier::CreateDefault()); storage_.set_proxy_service(ProxyService::CreateDirect()); storage_.set_ssl_config_service(new SSLConfigServiceDefaults); storage_.set_http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault( diff --git a/net/spdy/spdy_test_util_spdy3.cc b/net/spdy/spdy_test_util_spdy3.cc index 1958fdaf0b91cd..f0d7e49b81e80d 100644 --- a/net/spdy/spdy_test_util_spdy3.cc +++ b/net/spdy/spdy_test_util_spdy3.cc @@ -904,7 +904,7 @@ int CombineFrames(const spdy::SpdyFrame** frames, int num_frames, SpdySessionDependencies::SpdySessionDependencies() : host_resolver(new MockCachingHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(ProxyService::CreateDirect()), ssl_config_service(new SSLConfigServiceDefaults), socket_factory(new MockClientSocketFactory), @@ -922,7 +922,7 @@ SpdySessionDependencies::SpdySessionDependencies() SpdySessionDependencies::SpdySessionDependencies(ProxyService* proxy_service) : host_resolver(new MockHostResolver), - cert_verifier(new CertVerifier), + cert_verifier(CertVerifier::CreateDefault()), proxy_service(proxy_service), ssl_config_service(new SSLConfigServiceDefaults), socket_factory(new MockClientSocketFactory), @@ -966,7 +966,7 @@ HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic( SpdyURLRequestContext::SpdyURLRequestContext() : ALLOW_THIS_IN_INITIALIZER_LIST(storage_(this)) { storage_.set_host_resolver(new MockHostResolver()); - storage_.set_cert_verifier(new CertVerifier); + storage_.set_cert_verifier(CertVerifier::CreateDefault()); storage_.set_proxy_service(ProxyService::CreateDirect()); storage_.set_ssl_config_service(new SSLConfigServiceDefaults); storage_.set_http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault( diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc index 7b8c7e25c0acf6..32feba3c4b651a 100644 --- a/net/tools/fetch/fetch_client.cc +++ b/net/tools/fetch/fetch_client.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -145,7 +145,8 @@ int main(int argc, char** argv) { net::HostResolver::kDefaultRetryAttempts, NULL)); - scoped_ptr cert_verifier(new net::CertVerifier); + scoped_ptr cert_verifier( + net::CertVerifier::CreateDefault()); scoped_ptr proxy_service( net::ProxyService::CreateDirect()); scoped_refptr ssl_config_service( diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 165382a7009789..2ed65bd33350be 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/threading/thread.h" +#include "net/base/cert_verifier.h" #include "net/base/default_origin_bound_cert_store.h" #include "net/base/host_port_pair.h" #include "net/base/origin_bound_cert_service.h" @@ -111,7 +112,7 @@ void TestURLRequestContext::Init() { DCHECK(!initialized_); initialized_ = true; if (!cert_verifier()) - context_storage_.set_cert_verifier(new net::CertVerifier); + context_storage_.set_cert_verifier(net::CertVerifier::CreateDefault()); if (!ftp_transaction_factory()) { context_storage_.set_ftp_transaction_factory( new net::FtpNetworkLayer(host_resolver())); diff --git a/remoting/host/url_request_context.cc b/remoting/host/url_request_context.cc index 4ba46ff5579f15..ec5ac132c556ce 100644 --- a/remoting/host/url_request_context.cc +++ b/remoting/host/url_request_context.cc @@ -28,7 +28,7 @@ URLRequestContext::URLRequestContext( NULL)); storage_.set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver( proxy_config_service, 0u, NULL)); - storage_.set_cert_verifier(new net::CertVerifier); + storage_.set_cert_verifier(net::CertVerifier::CreateDefault()); storage_.set_ssl_config_service(new net::SSLConfigServiceDefaults); storage_.set_http_auth_handler_factory( net::HttpAuthHandlerFactory::CreateDefault(host_resolver())); diff --git a/remoting/jingle_glue/ssl_socket_adapter.cc b/remoting/jingle_glue/ssl_socket_adapter.cc index 314e3cd5649862..5c3d2bf3dcbfca 100644 --- a/remoting/jingle_glue/ssl_socket_adapter.cc +++ b/remoting/jingle_glue/ssl_socket_adapter.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -26,7 +26,7 @@ SSLSocketAdapter* SSLSocketAdapter::Create(AsyncSocket* socket) { SSLSocketAdapter::SSLSocketAdapter(AsyncSocket* socket) : SSLAdapter(socket), ignore_bad_cert_(false), - cert_verifier_(new net::CertVerifier()), + cert_verifier_(net::CertVerifier::CreateDefault()), ssl_state_(SSLSTATE_NONE), read_state_(IOSTATE_NONE), write_state_(IOSTATE_NONE), diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.cc b/remoting/protocol/ssl_hmac_channel_authenticator.cc index 99df7673d5a163..93f38244edb5e0 100644 --- a/remoting/protocol/ssl_hmac_channel_authenticator.cc +++ b/remoting/protocol/ssl_hmac_channel_authenticator.cc @@ -86,7 +86,7 @@ void SslHmacChannelAuthenticator::SecureAndAuthenticate( result = server_socket->Handshake(base::Bind( &SslHmacChannelAuthenticator::OnConnected, base::Unretained(this))); } else { - cert_verifier_.reset(new net::CertVerifier()); + cert_verifier_.reset(net::CertVerifier::CreateDefault()); net::SSLConfig::CertAndStatus cert_and_status; cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID; diff --git a/webkit/tools/test_shell/test_shell_request_context.cc b/webkit/tools/test_shell/test_shell_request_context.cc index 217eac409d491c..2cddd59b54ad29 100644 --- a/webkit/tools/test_shell/test_shell_request_context.cc +++ b/webkit/tools/test_shell/test_shell_request_context.cc @@ -77,7 +77,7 @@ void TestShellRequestContext::Init( net::CreateSystemHostResolver(net::HostResolver::kDefaultParallelism, net::HostResolver::kDefaultRetryAttempts, NULL)); - storage_.set_cert_verifier(new net::CertVerifier); + storage_.set_cert_verifier(net::CertVerifier::CreateDefault()); storage_.set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver( proxy_config_service.release(), 0, NULL)); storage_.set_ssl_config_service(