1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/socket/client_socket_factory.h" 6 7 #include "base/lazy_instance.h" 8 #include "base/thread_task_runner_handle.h" 9 #include "base/threading/sequenced_worker_pool.h" 10 #include "build/build_config.h" 11 #include "net/cert/cert_database.h" 12 #include "net/socket/client_socket_handle.h" 13 #if defined(USE_OPENSSL) 14 #include "net/socket/ssl_client_socket_openssl.h" 15 #elif defined(USE_NSS) || defined(OS_MACOSX) || defined(OS_WIN) 16 #include "net/socket/ssl_client_socket_nss.h" 17 #endif 18 #include "net/socket/tcp_client_socket.h" 19 #include "net/udp/udp_client_socket.h" 20 21 namespace net { 22 23 class X509Certificate; 24 25 namespace { 26 27 // ChromeOS and Linux may require interaction with smart cards or TPMs, which 28 // may cause NSS functions to block for upwards of several seconds. To avoid 29 // blocking all activity on the current task runner, such as network or IPC 30 // traffic, run NSS SSL functions on a dedicated thread. 31 #if defined(OS_CHROMEOS) || defined(OS_LINUX) 32 bool g_use_dedicated_nss_thread = true; 33 #else 34 bool g_use_dedicated_nss_thread = false; 35 #endif 36 37 class DefaultClientSocketFactory : public ClientSocketFactory, 38 public CertDatabase::Observer { 39 public: 40 DefaultClientSocketFactory() { 41 if (g_use_dedicated_nss_thread) { 42 // Use a single thread for the worker pool. 43 worker_pool_ = new base::SequencedWorkerPool(1, "NSS SSL Thread"); 44 nss_thread_task_runner_ = 45 worker_pool_->GetSequencedTaskRunnerWithShutdownBehavior( 46 worker_pool_->GetSequenceToken(), 47 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); 48 } 49 50 CertDatabase::GetInstance()->AddObserver(this); 51 } 52 53 virtual ~DefaultClientSocketFactory() { 54 // Note: This code never runs, as the factory is defined as a Leaky 55 // singleton. 56 CertDatabase::GetInstance()->RemoveObserver(this); 57 } 58 59 virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE { 60 ClearSSLSessionCache(); 61 } 62 63 virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE { 64 // Per wtc, we actually only need to flush when trust is reduced. 65 // Always flush now because OnCertTrustChanged does not tell us this. 66 // See comments in ClientSocketPoolManager::OnCertTrustChanged. 67 ClearSSLSessionCache(); 68 } 69 70 virtual DatagramClientSocket* CreateDatagramClientSocket( 71 DatagramSocket::BindType bind_type, 72 const RandIntCallback& rand_int_cb, 73 NetLog* net_log, 74 const NetLog::Source& source) OVERRIDE { 75 return new UDPClientSocket(bind_type, rand_int_cb, net_log, source); 76 } 77 78 virtual StreamSocket* CreateTransportClientSocket( 79 const AddressList& addresses, 80 NetLog* net_log, 81 const NetLog::Source& source) OVERRIDE { 82 return new TCPClientSocket(addresses, net_log, source); 83 } 84 85 virtual SSLClientSocket* CreateSSLClientSocket( 86 ClientSocketHandle* transport_socket, 87 const HostPortPair& host_and_port, 88 const SSLConfig& ssl_config, 89 const SSLClientSocketContext& context) OVERRIDE { 90 // nss_thread_task_runner_ may be NULL if g_use_dedicated_nss_thread is 91 // false or if the dedicated NSS thread failed to start. If so, cause NSS 92 // functions to execute on the current task runner. 93 // 94 // Note: The current task runner is obtained on each call due to unit 95 // tests, which may create and tear down the current thread's TaskRunner 96 // between each test. Because the DefaultClientSocketFactory is leaky, it 97 // may span multiple tests, and thus the current task runner may change 98 // from call to call. 99 scoped_refptr<base::SequencedTaskRunner> nss_task_runner( 100 nss_thread_task_runner_); 101 if (!nss_task_runner.get()) 102 nss_task_runner = base::ThreadTaskRunnerHandle::Get(); 103 104 #if defined(USE_OPENSSL) 105 return new SSLClientSocketOpenSSL(transport_socket, host_and_port, 106 ssl_config, context); 107 #elif defined(USE_NSS) || defined(OS_MACOSX) || defined(OS_WIN) 108 return new SSLClientSocketNSS(nss_task_runner.get(), 109 transport_socket, 110 host_and_port, 111 ssl_config, 112 context); 113 #else 114 NOTIMPLEMENTED(); 115 return NULL; 116 #endif 117 } 118 119 virtual void ClearSSLSessionCache() OVERRIDE { 120 SSLClientSocket::ClearSessionCache(); 121 } 122 123 private: 124 scoped_refptr<base::SequencedWorkerPool> worker_pool_; 125 scoped_refptr<base::SequencedTaskRunner> nss_thread_task_runner_; 126 }; 127 128 static base::LazyInstance<DefaultClientSocketFactory>::Leaky 129 g_default_client_socket_factory = LAZY_INSTANCE_INITIALIZER; 130 131 } // namespace 132 133 // Deprecated function (http://crbug.com/37810) that takes a StreamSocket. 134 SSLClientSocket* ClientSocketFactory::CreateSSLClientSocket( 135 StreamSocket* transport_socket, 136 const HostPortPair& host_and_port, 137 const SSLConfig& ssl_config, 138 const SSLClientSocketContext& context) { 139 ClientSocketHandle* socket_handle = new ClientSocketHandle(); 140 socket_handle->set_socket(transport_socket); 141 return CreateSSLClientSocket(socket_handle, host_and_port, ssl_config, 142 context); 143 } 144 145 // static 146 ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() { 147 return g_default_client_socket_factory.Pointer(); 148 } 149 150 } // namespace net 151