1// Copyright (c) 2011 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 "build/build_config.h"
9#include "net/base/cert_database.h"
10#include "net/socket/client_socket_handle.h"
11#if defined(OS_WIN)
12#include "net/socket/ssl_client_socket_nss.h"
13#include "net/socket/ssl_client_socket_win.h"
14#elif defined(USE_OPENSSL)
15#include "net/socket/ssl_client_socket_openssl.h"
16#elif defined(USE_NSS)
17#include "net/socket/ssl_client_socket_nss.h"
18#elif defined(OS_MACOSX)
19#include "net/socket/ssl_client_socket_mac.h"
20#include "net/socket/ssl_client_socket_nss.h"
21#endif
22#include "net/socket/ssl_host_info.h"
23#include "net/socket/tcp_client_socket.h"
24
25namespace net {
26
27class X509Certificate;
28
29namespace {
30
31bool g_use_system_ssl = false;
32
33class DefaultClientSocketFactory : public ClientSocketFactory,
34                                   public CertDatabase::Observer {
35 public:
36  DefaultClientSocketFactory() {
37    CertDatabase::AddObserver(this);
38  }
39
40  virtual ~DefaultClientSocketFactory() {
41    CertDatabase::RemoveObserver(this);
42  }
43
44  virtual void OnUserCertAdded(const X509Certificate* cert) {
45    ClearSSLSessionCache();
46  }
47
48  virtual void OnCertTrustChanged(const X509Certificate* cert) {
49    // Per wtc, we actually only need to flush when trust is reduced.
50    // Always flush now because OnCertTrustChanged does not tell us this.
51    // See comments in ClientSocketPoolManager::OnCertTrustChanged.
52    ClearSSLSessionCache();
53  }
54
55  virtual ClientSocket* CreateTransportClientSocket(
56      const AddressList& addresses,
57      NetLog* net_log,
58      const NetLog::Source& source) {
59    return new TCPClientSocket(addresses, net_log, source);
60  }
61
62  virtual SSLClientSocket* CreateSSLClientSocket(
63      ClientSocketHandle* transport_socket,
64      const HostPortPair& host_and_port,
65      const SSLConfig& ssl_config,
66      SSLHostInfo* ssl_host_info,
67      CertVerifier* cert_verifier,
68      DnsCertProvenanceChecker* dns_cert_checker) {
69    scoped_ptr<SSLHostInfo> shi(ssl_host_info);
70#if defined(OS_WIN)
71    if (g_use_system_ssl) {
72      return new SSLClientSocketWin(transport_socket, host_and_port,
73                                    ssl_config, cert_verifier);
74    }
75    return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config,
76                                  shi.release(), cert_verifier,
77                                  dns_cert_checker);
78#elif defined(USE_OPENSSL)
79    return new SSLClientSocketOpenSSL(transport_socket, host_and_port,
80                                      ssl_config, cert_verifier);
81#elif defined(USE_NSS)
82    return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config,
83                                  shi.release(), cert_verifier,
84                                  dns_cert_checker);
85#elif defined(OS_MACOSX)
86    if (g_use_system_ssl) {
87      return new SSLClientSocketMac(transport_socket, host_and_port,
88                                    ssl_config, cert_verifier);
89    }
90    return new SSLClientSocketNSS(transport_socket, host_and_port, ssl_config,
91                                  shi.release(), cert_verifier,
92                                  dns_cert_checker);
93#else
94    NOTIMPLEMENTED();
95    return NULL;
96#endif
97  }
98
99  // TODO(rch): This is only implemented for the NSS SSL library, which is the
100  /// default for Windows, Mac and Linux, but we should implement it everywhere.
101  void ClearSSLSessionCache() {
102#if defined(OS_WIN)
103    if (!g_use_system_ssl)
104      SSLClientSocketNSS::ClearSessionCache();
105#elif defined(USE_OPENSSL)
106    // no-op
107#elif defined(USE_NSS)
108    SSLClientSocketNSS::ClearSessionCache();
109#elif defined(OS_MACOSX)
110    if (!g_use_system_ssl)
111      SSLClientSocketNSS::ClearSessionCache();
112#else
113    NOTIMPLEMENTED();
114#endif
115  }
116
117};
118
119static base::LazyInstance<DefaultClientSocketFactory>
120    g_default_client_socket_factory(base::LINKER_INITIALIZED);
121
122}  // namespace
123
124// Deprecated function (http://crbug.com/37810) that takes a ClientSocket.
125SSLClientSocket* ClientSocketFactory::CreateSSLClientSocket(
126    ClientSocket* transport_socket,
127    const HostPortPair& host_and_port,
128    const SSLConfig& ssl_config,
129    SSLHostInfo* ssl_host_info,
130    CertVerifier* cert_verifier) {
131  ClientSocketHandle* socket_handle = new ClientSocketHandle();
132  socket_handle->set_socket(transport_socket);
133  return CreateSSLClientSocket(socket_handle, host_and_port, ssl_config,
134                               ssl_host_info, cert_verifier,
135                               NULL /* DnsCertProvenanceChecker */);
136}
137
138// static
139ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() {
140  return g_default_client_socket_factory.Pointer();
141}
142
143// static
144void ClientSocketFactory::UseSystemSSL() {
145  g_use_system_ssl = true;
146}
147
148}  // namespace net
149