OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // OpenSSL binding for SSLClientSocket. The class layout and general principle | 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle |
6 // of operation is derived from SSLClientSocketNSS. | 6 // of operation is derived from SSLClientSocketNSS. |
7 | 7 |
8 #include "net/socket/ssl_client_socket_openssl.h" | 8 #include "net/socket/ssl_client_socket_openssl.h" |
9 | 9 |
10 #include <openssl/ssl.h> | 10 #include <openssl/ssl.h> |
11 #include <openssl/err.h> | 11 #include <openssl/err.h> |
12 | 12 |
13 #include "base/lock.h" | |
14 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
15 #include "base/openssl_util.h" | 14 #include "base/openssl_util.h" |
16 #include "base/singleton.h" | 15 #include "base/singleton.h" |
| 16 #include "base/synchronization/lock.h" |
17 #include "net/base/cert_verifier.h" | 17 #include "net/base/cert_verifier.h" |
18 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
19 #include "net/base/openssl_private_key_store.h" | 19 #include "net/base/openssl_private_key_store.h" |
20 #include "net/base/ssl_cert_request_info.h" | 20 #include "net/base/ssl_cert_request_info.h" |
21 #include "net/base/ssl_connection_status_flags.h" | 21 #include "net/base/ssl_connection_status_flags.h" |
22 #include "net/base/ssl_info.h" | 22 #include "net/base/ssl_info.h" |
23 #include "net/socket/ssl_error_params.h" | 23 #include "net/socket/ssl_error_params.h" |
24 | 24 |
25 namespace net { | 25 namespace net { |
26 | 26 |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 // side policy for that cache about session re-use: we retain one session per | 200 // side policy for that cache about session re-use: we retain one session per |
201 // unique HostPortPair. | 201 // unique HostPortPair. |
202 class SSLSessionCache { | 202 class SSLSessionCache { |
203 public: | 203 public: |
204 SSLSessionCache() {} | 204 SSLSessionCache() {} |
205 | 205 |
206 void OnSessionAdded(const HostPortPair& host_and_port, SSL_SESSION* session) { | 206 void OnSessionAdded(const HostPortPair& host_and_port, SSL_SESSION* session) { |
207 // Declare the session cleaner-upper before the lock, so any call into | 207 // Declare the session cleaner-upper before the lock, so any call into |
208 // OpenSSL to free the session will happen after the lock is released. | 208 // OpenSSL to free the session will happen after the lock is released. |
209 base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; | 209 base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; |
210 AutoLock lock(lock_); | 210 base::AutoLock lock(lock_); |
211 | 211 |
212 DCHECK_EQ(0U, session_map_.count(session)); | 212 DCHECK_EQ(0U, session_map_.count(session)); |
213 std::pair<HostPortMap::iterator, bool> res = | 213 std::pair<HostPortMap::iterator, bool> res = |
214 host_port_map_.insert(std::make_pair(host_and_port, session)); | 214 host_port_map_.insert(std::make_pair(host_and_port, session)); |
215 if (!res.second) { // Already exists: replace old entry. | 215 if (!res.second) { // Already exists: replace old entry. |
216 session_to_free.reset(res.first->second); | 216 session_to_free.reset(res.first->second); |
217 session_map_.erase(session_to_free.get()); | 217 session_map_.erase(session_to_free.get()); |
218 res.first->second = session; | 218 res.first->second = session; |
219 } | 219 } |
220 DVLOG(2) << "Adding session " << session << " => " | 220 DVLOG(2) << "Adding session " << session << " => " |
221 << host_and_port.ToString() << ", new entry = " << res.second; | 221 << host_and_port.ToString() << ", new entry = " << res.second; |
222 DCHECK(host_port_map_[host_and_port] == session); | 222 DCHECK(host_port_map_[host_and_port] == session); |
223 session_map_[session] = res.first; | 223 session_map_[session] = res.first; |
224 DCHECK_EQ(host_port_map_.size(), session_map_.size()); | 224 DCHECK_EQ(host_port_map_.size(), session_map_.size()); |
225 DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires); | 225 DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires); |
226 } | 226 } |
227 | 227 |
228 void OnSessionRemoved(SSL_SESSION* session) { | 228 void OnSessionRemoved(SSL_SESSION* session) { |
229 // Declare the session cleaner-upper before the lock, so any call into | 229 // Declare the session cleaner-upper before the lock, so any call into |
230 // OpenSSL to free the session will happen after the lock is released. | 230 // OpenSSL to free the session will happen after the lock is released. |
231 base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; | 231 base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; |
232 AutoLock lock(lock_); | 232 base::AutoLock lock(lock_); |
233 | 233 |
234 SessionMap::iterator it = session_map_.find(session); | 234 SessionMap::iterator it = session_map_.find(session); |
235 if (it == session_map_.end()) | 235 if (it == session_map_.end()) |
236 return; | 236 return; |
237 DVLOG(2) << "Remove session " << session << " => " | 237 DVLOG(2) << "Remove session " << session << " => " |
238 << it->second->first.ToString(); | 238 << it->second->first.ToString(); |
239 DCHECK(it->second->second == session); | 239 DCHECK(it->second->second == session); |
240 host_port_map_.erase(it->second); | 240 host_port_map_.erase(it->second); |
241 session_map_.erase(it); | 241 session_map_.erase(it); |
242 session_to_free.reset(session); | 242 session_to_free.reset(session); |
243 DCHECK_EQ(host_port_map_.size(), session_map_.size()); | 243 DCHECK_EQ(host_port_map_.size(), session_map_.size()); |
244 } | 244 } |
245 | 245 |
246 // Looks up the host:port in the cache, and if a session is found it is added | 246 // Looks up the host:port in the cache, and if a session is found it is added |
247 // to |ssl|, returning true on success. | 247 // to |ssl|, returning true on success. |
248 bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port) { | 248 bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port) { |
249 AutoLock lock(lock_); | 249 base::AutoLock lock(lock_); |
250 HostPortMap::iterator it = host_port_map_.find(host_and_port); | 250 HostPortMap::iterator it = host_port_map_.find(host_and_port); |
251 if (it == host_port_map_.end()) | 251 if (it == host_port_map_.end()) |
252 return false; | 252 return false; |
253 DVLOG(2) << "Lookup session: " << it->second << " => " | 253 DVLOG(2) << "Lookup session: " << it->second << " => " |
254 << host_and_port.ToString(); | 254 << host_and_port.ToString(); |
255 SSL_SESSION* session = it->second; | 255 SSL_SESSION* session = it->second; |
256 DCHECK(session); | 256 DCHECK(session); |
257 DCHECK(session_map_[session] == it); | 257 DCHECK(session_map_[session] == it); |
258 // Ideally we'd release |lock_| before calling into OpenSSL here, however | 258 // Ideally we'd release |lock_| before calling into OpenSSL here, however |
259 // that opens a small risk |session| will go out of scope before it is used. | 259 // that opens a small risk |session| will go out of scope before it is used. |
260 // Alternatively we would take a temporary local refcount on |session|, | 260 // Alternatively we would take a temporary local refcount on |session|, |
261 // except OpenSSL does not provide a public API for adding a ref (c.f. | 261 // except OpenSSL does not provide a public API for adding a ref (c.f. |
262 // SSL_SESSION_free which decrements the ref). | 262 // SSL_SESSION_free which decrements the ref). |
263 return SSL_set_session(ssl, session) == 1; | 263 return SSL_set_session(ssl, session) == 1; |
264 } | 264 } |
265 | 265 |
266 private: | 266 private: |
267 // A pair of maps to allow bi-directional lookups between host:port and an | 267 // A pair of maps to allow bi-directional lookups between host:port and an |
268 // associated session. | 268 // associated session. |
269 // TODO(joth): When client certificates are implemented we should key the | 269 // TODO(joth): When client certificates are implemented we should key the |
270 // cache on the client certificate used in addition to the host-port pair. | 270 // cache on the client certificate used in addition to the host-port pair. |
271 typedef std::map<HostPortPair, SSL_SESSION*> HostPortMap; | 271 typedef std::map<HostPortPair, SSL_SESSION*> HostPortMap; |
272 typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap; | 272 typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap; |
273 HostPortMap host_port_map_; | 273 HostPortMap host_port_map_; |
274 SessionMap session_map_; | 274 SessionMap session_map_; |
275 | 275 |
276 // Protects access to both the above maps. | 276 // Protects access to both the above maps. |
277 Lock lock_; | 277 base::Lock lock_; |
278 | 278 |
279 DISALLOW_COPY_AND_ASSIGN(SSLSessionCache); | 279 DISALLOW_COPY_AND_ASSIGN(SSLSessionCache); |
280 }; | 280 }; |
281 | 281 |
282 class SSLContext { | 282 class SSLContext { |
283 public: | 283 public: |
284 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } | 284 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } |
285 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } | 285 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } |
286 SSLSessionCache* session_cache() { return &session_cache_; } | 286 SSLSessionCache* session_cache() { return &session_cache_; } |
287 | 287 |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1183 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); | 1183 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
1184 | 1184 |
1185 if (rv >= 0) | 1185 if (rv >= 0) |
1186 return rv; | 1186 return rv; |
1187 | 1187 |
1188 int err = SSL_get_error(ssl_, rv); | 1188 int err = SSL_get_error(ssl_, rv); |
1189 return MapOpenSSLError(err, err_tracer); | 1189 return MapOpenSSLError(err, err_tracer); |
1190 } | 1190 } |
1191 | 1191 |
1192 } // namespace net | 1192 } // namespace net |
OLD | NEW |