Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1138)

Side by Side Diff: net/socket/ssl_session_cache_openssl.cc

Issue 353713005: Implements new, more robust design for communicating between SSLConnectJobs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed error in SSLSessionIsInCache. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 #include "net/socket/ssl_session_cache_openssl.h" 5 #include "net/socket/ssl_session_cache_openssl.h"
6 6
7 #include <list> 7 #include <list>
8 #include <map> 8 #include <map>
9 9
10 #include <openssl/rand.h> 10 #include <openssl/rand.h>
11 #include <openssl/ssl.h> 11 #include <openssl/ssl.h>
12 12
13 #include "base/callback.h"
13 #include "base/containers/hash_tables.h" 14 #include "base/containers/hash_tables.h"
14 #include "base/lazy_instance.h" 15 #include "base/lazy_instance.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 #include "base/synchronization/lock.h" 17 #include "base/synchronization/lock.h"
17 18
18 namespace net { 19 namespace net {
19 20
20 namespace { 21 namespace {
21 22
22 // A helper class to lazily create a new EX_DATA index to map SSL_CTX handles 23 // A helper class to lazily create a new EX_DATA index to map SSL_CTX handles
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 return false; // Session has not yet been marked good. Treat as a miss. 230 return false; // Session has not yet been marked good. Treat as a miss.
230 231
231 // Move to front of MRU list. 232 // Move to front of MRU list.
232 ordering_.push_front(session); 233 ordering_.push_front(session);
233 ordering_.erase(it->second); 234 ordering_.erase(it->second);
234 it->second = ordering_.begin(); 235 it->second = ordering_.begin();
235 236
236 return SSL_set_session(ssl, session) == 1; 237 return SSL_set_session(ssl, session) == 1;
237 } 238 }
238 239
240 bool SSLSessionIsInCache(const std::string& cache_key) const {
241 base::AutoLock locked(lock_);
242 KeyIndex::const_iterator it = key_index_.find(cache_key);
243 if (it == key_index.end())
244 return false;
245
246 SSL_SESSION* session = *it->second;
247 DCHECK(session);
248 DVLOG(2) << "Lookup session: " << session << " for " << cache_key;
wtc 2014/07/18 01:17:15 Delete this log message.
mshelley 2014/07/18 21:08:33 Done.
249
250 void* session_is_good =
251 SSL_SESSION_get_ex_data(session, GetSSLSessionExIndex());
252
253 if (!session_is_good)
254 return false; // Session has not yet been marked good. Treat as a miss.
255 return true;
wtc 2014/07/18 01:17:16 You can replace these three lines with: return
mshelley 2014/07/18 21:08:33 Done.
256 }
257
258 void SetSessionAddedCallback(SSL* ssl, const base::Closure& callback) {
259 // Add this SSL* to the SSLtoCallbackMap.
260 ssl_to_callback_map_[ssl] = CallbackAndCompletionCount(callback, 0);
261 }
262
263 // Determines if the session for |ssl| is in the cache, and calls the
264 // appropriate callback if that is the case.
265 void CheckIfSessionAdded(SSL* ssl) {
266 SSLToCallbackMap::iterator it = ssl_to_callback_map_.find(ssl);
267 if (it == ssl_to_callback_map_.end())
268 return;
269 // Increment the session's completion count.
270 if (++it->second.count == 2) {
271 // The session has been MarkedAsGood and Added, so it can be used.
272 // These two events can occur in either order.
273 base::Closure callback = it->second.callback;
274 ssl_to_callback_map_.erase(it);
275 callback.Run();
276 }
277 }
278
279 void RemoveSessionAddedCallback(SSL* ssl) { ssl_to_callback_map_.erase(ssl); }
280
239 void MarkSSLSessionAsGood(SSL* ssl) { 281 void MarkSSLSessionAsGood(SSL* ssl) {
240 SSL_SESSION* session = SSL_get_session(ssl); 282 SSL_SESSION* session = SSL_get_session(ssl);
241 if (!session) 283 if (!session)
wtc 2014/07/18 01:17:16 IMPORTANT: we should find out whether |session| ma
mshelley 2014/07/18 21:08:33 The code you cited indicates to me that session ca
242 return; 284 return;
243 285
244 // Mark the session as good, allowing it to be used for future connections. 286 // Mark the session as good, allowing it to be used for future connections.
245 SSL_SESSION_set_ex_data( 287 SSL_SESSION_set_ex_data(
246 session, GetSSLSessionExIndex(), reinterpret_cast<void*>(1)); 288 session, GetSSLSessionExIndex(), reinterpret_cast<void*>(1));
289
290 CheckIfSessionAdded(ssl);
247 } 291 }
248 292
249 // Flush all entries from the cache. 293 // Flush all entries from the cache.
250 void Flush() { 294 void Flush() {
251 base::AutoLock lock(lock_); 295 base::AutoLock lock(lock_);
252 id_index_.clear(); 296 id_index_.clear();
253 key_index_.clear(); 297 key_index_.clear();
254 while (!ordering_.empty()) { 298 while (!ordering_.empty()) {
255 SSL_SESSION* session = ordering_.front(); 299 SSL_SESSION* session = ordering_.front();
256 ordering_.pop_front(); 300 ordering_.pop_front();
257 SSL_SESSION_free(session); 301 SSL_SESSION_free(session);
258 } 302 }
259 } 303 }
260 304
261 private: 305 private:
306 // CallbackAndCompletionCounts are used to group callback a callback
wtc 2014/07/18 01:17:15 group callback a callback => group a callback
mshelley 2014/07/18 21:08:33 Done.
307 // that should be run when a certian sesssion is added to the session
308 // cache with an integer indicating the status of that session.
309 struct CallbackAndCompletionCount {
310 CallbackAndCompletionCount(base::Closure completion_callback,
wtc 2014/07/18 01:17:15 I think this input parameter should be a const ref
mshelley 2014/07/18 21:08:33 Done.
311 int completion_count)
312 : callback(completion_callback), count(completion_count) {}
313
314 const base::Closure callback;
315 // |count| < 2 means that the ssl session associated with this object
316 // has not been added to the session cache. |count| == 2 means that the
wtc 2014/07/18 01:17:16 The first sentence in this comment block is not ac
mshelley 2014/07/18 21:08:33 Done.
317 // session has been added to the cache and is ready for use.
318 int count;
319 };
320
262 // Type for list of SSL_SESSION handles, ordered in MRU order. 321 // Type for list of SSL_SESSION handles, ordered in MRU order.
263 typedef std::list<SSL_SESSION*> MRUSessionList; 322 typedef std::list<SSL_SESSION*> MRUSessionList;
264 // Type for a dictionary from unique cache keys to session list nodes. 323 // Type for a dictionary from unique cache keys to session list nodes.
265 typedef base::hash_map<std::string, MRUSessionList::iterator> KeyIndex; 324 typedef base::hash_map<std::string, MRUSessionList::iterator> KeyIndex;
266 // Type for a dictionary from SessionId values to key index nodes. 325 // Type for a dictionary from SessionId values to key index nodes.
267 typedef base::hash_map<SessionId, KeyIndex::iterator> SessionIdIndex; 326 typedef base::hash_map<SessionId, KeyIndex::iterator> SessionIdIndex;
327 // Type for a map from SSL* to associated callbacks
328 typedef std::map<SSL*, CallbackAndCompletionCount> SSLToCallbackMap;
268 329
269 // Return the key associated with a given session, or the empty string if 330 // Return the key associated with a given session, or the empty string if
270 // none exist. This shall only be used for debugging. 331 // none exist. This shall only be used for debugging.
271 std::string SessionKey(SSL_SESSION* session) { 332 std::string SessionKey(SSL_SESSION* session) {
272 if (!session) 333 if (!session)
273 return std::string("<null-session>"); 334 return std::string("<null-session>");
274 335
275 if (session->session_id_length == 0) 336 if (session->session_id_length == 0)
276 return std::string("<empty-session-id>"); 337 return std::string("<empty-session-id>");
277 338
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 DCHECK(result); 396 DCHECK(result);
336 return reinterpret_cast<SSLSessionCacheOpenSSLImpl*>(result); 397 return reinterpret_cast<SSLSessionCacheOpenSSLImpl*>(result);
337 } 398 }
338 399
339 // Called by OpenSSL when a new |session| was created and added to a given 400 // Called by OpenSSL when a new |session| was created and added to a given
340 // |ssl| connection. Note that the session's reference count was already 401 // |ssl| connection. Note that the session's reference count was already
341 // incremented before the function is entered. The function must return 1 402 // incremented before the function is entered. The function must return 1
342 // to indicate that it took ownership of the session, i.e. that the caller 403 // to indicate that it took ownership of the session, i.e. that the caller
343 // should not decrement its reference count after completion. 404 // should not decrement its reference count after completion.
344 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { 405 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
345 GetCache(ssl->ctx)->OnSessionAdded(ssl, session); 406 SSLSessionCacheOpenSSLImpl* cache = GetCache(ssl->ctx);
407 cache->OnSessionAdded(ssl, session);
408 cache->CheckIfSessionAdded(ssl);
wtc 2014/07/18 01:17:15 IMPORTANT: a server may indicate that a session sh
mshelley 2014/07/18 21:08:33 Hmm yeah I see, this is definitely an issue. I'm a
346 return 1; 409 return 1;
347 } 410 }
348 411
349 // Called by OpenSSL to indicate that a session must be removed from the 412 // Called by OpenSSL to indicate that a session must be removed from the
350 // cache. This happens when SSL_CTX is destroyed. 413 // cache. This happens when SSL_CTX is destroyed.
351 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { 414 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
352 GetCache(ctx)->OnSessionRemoved(session); 415 GetCache(ctx)->OnSessionRemoved(session);
353 } 416 }
354 417
355 // Called by OpenSSL to generate a new session ID. This happens during a 418 // Called by OpenSSL to generate a new session ID. This happens during a
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 if (id_index_.find(SessionId(id, id_len)) == id_index_.end()) 522 if (id_index_.find(SessionId(id, id_len)) == id_index_.end())
460 return true; 523 return true;
461 } 524 }
462 DLOG(ERROR) << "Couldn't generate unique session ID of " << id_len 525 DLOG(ERROR) << "Couldn't generate unique session ID of " << id_len
463 << "bytes after " << kMaxTries << " tries."; 526 << "bytes after " << kMaxTries << " tries.";
464 return false; 527 return false;
465 } 528 }
466 529
467 SSL_CTX* ctx_; 530 SSL_CTX* ctx_;
468 SSLSessionCacheOpenSSL::Config config_; 531 SSLSessionCacheOpenSSL::Config config_;
532 SSLToCallbackMap ssl_to_callback_map_;
469 533
470 // method to get the index which can later be used with SSL_CTX_get_ex_data() 534 // method to get the index which can later be used with SSL_CTX_get_ex_data()
471 // or SSL_CTX_set_ex_data(). 535 // or SSL_CTX_set_ex_data().
472 base::Lock lock_; // Protects access to containers below. 536 mutable base::Lock lock_; // Protects access to containers below.
473 537
474 MRUSessionList ordering_; 538 MRUSessionList ordering_;
475 KeyIndex key_index_; 539 KeyIndex key_index_;
476 SessionIdIndex id_index_; 540 SessionIdIndex id_index_;
477 541
478 size_t expiration_check_; 542 size_t expiration_check_;
479 }; 543 };
480 544
481 SSLSessionCacheOpenSSL::~SSLSessionCacheOpenSSL() { delete impl_; } 545 SSLSessionCacheOpenSSL::~SSLSessionCacheOpenSSL() { delete impl_; }
482 546
483 size_t SSLSessionCacheOpenSSL::size() const { return impl_->size(); } 547 size_t SSLSessionCacheOpenSSL::size() const { return impl_->size(); }
484 548
485 void SSLSessionCacheOpenSSL::Reset(SSL_CTX* ctx, const Config& config) { 549 void SSLSessionCacheOpenSSL::Reset(SSL_CTX* ctx, const Config& config) {
486 if (impl_) 550 if (impl_)
487 delete impl_; 551 delete impl_;
488 552
489 impl_ = new SSLSessionCacheOpenSSLImpl(ctx, config); 553 impl_ = new SSLSessionCacheOpenSSLImpl(ctx, config);
490 } 554 }
491 555
492 bool SSLSessionCacheOpenSSL::SetSSLSession(SSL* ssl) { 556 bool SSLSessionCacheOpenSSL::SetSSLSession(SSL* ssl) {
493 return impl_->SetSSLSession(ssl); 557 return impl_->SetSSLSession(ssl);
494 } 558 }
495 559
496 bool SSLSessionCacheOpenSSL::SetSSLSessionWithKey( 560 bool SSLSessionCacheOpenSSL::SetSSLSessionWithKey(
497 SSL* ssl, 561 SSL* ssl,
498 const std::string& cache_key) { 562 const std::string& cache_key) {
499 return impl_->SetSSLSessionWithKey(ssl, cache_key); 563 return impl_->SetSSLSessionWithKey(ssl, cache_key);
500 } 564 }
501 565
566 bool SSLSessionCacheOpenSSL::SSLSessionIsInCache(
567 const std::string& cache_key) const {
568 return impl_->SSLSessionIsInCache(cache_key);
569 }
570
571 void SSLSessionCacheOpenSSL::RemoveSessionAddedCallback(SSL* ssl) {
572 impl_->RemoveSessionAddedCallback(ssl);
573 }
574
575 void SSLSessionCacheOpenSSL::SetSessionAddedCallback(SSL* ssl,
576 const base::Closure& cb) {
577 impl_->SetSessionAddedCallback(ssl, cb);
578 }
579
502 void SSLSessionCacheOpenSSL::MarkSSLSessionAsGood(SSL* ssl) { 580 void SSLSessionCacheOpenSSL::MarkSSLSessionAsGood(SSL* ssl) {
503 return impl_->MarkSSLSessionAsGood(ssl); 581 return impl_->MarkSSLSessionAsGood(ssl);
504 } 582 }
505 583
506 void SSLSessionCacheOpenSSL::Flush() { impl_->Flush(); } 584 void SSLSessionCacheOpenSSL::Flush() { impl_->Flush(); }
507 585
508 } // namespace net 586 } // namespace net
OLDNEW
« net/socket/ssl_session_cache_openssl.h ('K') | « net/socket/ssl_session_cache_openssl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698