// Copyright 2013 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/socket/ssl_session_cache_openssl.h"

#include <list>
#include <map>

#include <openssl/rand.h>
#include <openssl/ssl.h>

#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/profiler/scoped_tracker.h"
#include "base/synchronization/lock.h"

namespace net {

namespace {

// A helper class to lazily create a new EX_DATA index to map SSL_CTX handles
// to their corresponding SSLSessionCacheOpenSSLImpl object.
class SSLContextExIndex {
public:
  SSLContextExIndex() {
    context_index_ = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
    DCHECK_NE(-1, context_index_);
    session_index_ = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL);
    DCHECK_NE(-1, session_index_);
  }

  int context_index() const { return context_index_; }
  int session_index() const { return session_index_; }

 private:
  int context_index_;
  int session_index_;
};

// static
base::LazyInstance<SSLContextExIndex>::Leaky s_ssl_context_ex_instance =
    LAZY_INSTANCE_INITIALIZER;

// Retrieve the global EX_DATA index, created lazily on first call, to
// be used with SSL_CTX_set_ex_data() and SSL_CTX_get_ex_data().
static int GetSSLContextExIndex() {
  return s_ssl_context_ex_instance.Get().context_index();
}

// Retrieve the global EX_DATA index, created lazily on first call, to
// be used with SSL_SESSION_set_ex_data() and SSL_SESSION_get_ex_data().
static int GetSSLSessionExIndex() {
  return s_ssl_context_ex_instance.Get().session_index();
}

// Helper struct used to store session IDs in a SessionIdIndex container
// (see definition below). To save memory each entry only holds a pointer
// to the session ID buffer, which must outlive the entry itself. On the
// other hand, a hash is included to minimize the number of hashing
// computations during cache operations.
struct SessionId {
  SessionId(const unsigned char* a_id, unsigned a_id_len)
      : id(a_id), id_len(a_id_len), hash(ComputeHash(a_id, a_id_len)) {}

  explicit SessionId(const SessionId& other)
      : id(other.id), id_len(other.id_len), hash(other.hash) {}

  explicit SessionId(SSL_SESSION* session)
      : id(session->session_id),
        id_len(session->session_id_length),
        hash(ComputeHash(session->session_id, session->session_id_length)) {}

  bool operator==(const SessionId& other) const {
    return hash == other.hash && id_len == other.id_len &&
           !memcmp(id, other.id, id_len);
  }

  const unsigned char* id;
  unsigned id_len;
  size_t hash;

 private:
  // Session ID are random strings of bytes. This happens to compute the same
  // value as std::hash<std::string> without the extra string copy. See
  // base/containers/hash_tables.h. Other hashing computations are possible,
  // this one is just simple enough to do the job.
  size_t ComputeHash(const unsigned char* id, unsigned id_len) {
    size_t result = 0;
    for (unsigned n = 0; n < id_len; ++n) {
      result = (result * 131) + id[n];
    }
    return result;
  }
};

}  // namespace

}  // namespace net

namespace BASE_HASH_NAMESPACE {

template <>
struct hash<net::SessionId> {
  std::size_t operator()(const net::SessionId& entry) const {
    return entry.hash;
  }
};

}  // namespace BASE_HASH_NAMESPACE

namespace net {

// Implementation of the real SSLSessionCache.
//
// The implementation is inspired by base::MRUCache, except that the deletor
// also needs to remove the entry from other containers. In a nutshell, this
// uses several basic containers:
//
//   |ordering_| is a doubly-linked list of SSL_SESSION handles, ordered in
//   MRU order.
//
//   |key_index_| is a hash table mapping unique cache keys (e.g. host/port
//   values) to a single iterator of |ordering_|. It is used to efficiently
//   find the cached session associated with a given key.
//
//   |id_index_| is a hash table mapping SessionId values to iterators
//   of |key_index_|. If is used to efficiently remove sessions from the cache,
//   as well as check for the existence of a session ID value in the cache.
//
//   SSL_SESSION objects are reference-counted, and owned by the cache. This
//   means that their reference count is incremented when they are added, and
//   decremented when they are removed.
//
// Assuming an average key size of 100 characters, each node requires the
// following memory usage on 32-bit Android, when linked against STLport:
//
//      12   (ordering_ node, including SSL_SESSION handle)
//     100   (key characters)
//    + 24   (std::string header/minimum size)
//    +  8   (key_index_ node, excluding the 2 lines above for the key).
//    + 20   (id_index_ node)
//  --------
//     164   bytes/node
//
// Hence, 41 KiB for a full cache with a maximum of 1024 entries, excluding
// the size of SSL_SESSION objects and heap fragmentation.
//

class SSLSessionCacheOpenSSLImpl {
 public:
  // Construct new instance. This registers various hooks into the SSL_CTX
  // context |ctx|. OpenSSL will call back during SSL connection
  // operations. |key_func| is used to map a SSL handle to a unique cache
  // string, according to the client's preferences.
  SSLSessionCacheOpenSSLImpl(SSL_CTX* ctx,
                             const SSLSessionCacheOpenSSL::Config& config)
      : ctx_(ctx), config_(config), expiration_check_(0) {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::SSLSessionCacheOpenSSLImpl"));

    DCHECK(ctx);

    // NO_INTERNAL_STORE disables OpenSSL's builtin cache, and
    // NO_AUTO_CLEAR disables the call to SSL_CTX_flush_sessions
    // every 256 connections (this number is hard-coded in the library
    // and can't be changed).
    SSL_CTX_set_session_cache_mode(ctx_,
                                   SSL_SESS_CACHE_CLIENT |
                                       SSL_SESS_CACHE_NO_INTERNAL_STORE |
                                       SSL_SESS_CACHE_NO_AUTO_CLEAR);

    SSL_CTX_sess_set_new_cb(ctx_, NewSessionCallbackStatic);
    SSL_CTX_sess_set_remove_cb(ctx_, RemoveSessionCallbackStatic);
    SSL_CTX_set_generate_session_id(ctx_, GenerateSessionIdStatic);
    SSL_CTX_set_timeout(ctx_, config_.timeout_seconds);

    SSL_CTX_set_ex_data(ctx_, GetSSLContextExIndex(), this);
  }

  // Destroy this instance. Must happen before |ctx_| is destroyed.
  ~SSLSessionCacheOpenSSLImpl() {
    Flush();
    SSL_CTX_set_ex_data(ctx_, GetSSLContextExIndex(), NULL);
    SSL_CTX_sess_set_new_cb(ctx_, NULL);
    SSL_CTX_sess_set_remove_cb(ctx_, NULL);
    SSL_CTX_set_generate_session_id(ctx_, NULL);
  }

  // Return the number of items in this cache.
  size_t size() const { return key_index_.size(); }

  // Retrieve the cache key from |ssl| and look for a corresponding
  // cached session ID. If one is found, call SSL_set_session() to associate
  // it with the |ssl| connection.
  //
  // Will also check for expired sessions every |expiration_check_count|
  // calls.
  //
  // Return true if a cached session ID was found, false otherwise.
  bool SetSSLSession(SSL* ssl) {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::SetSSLSession"));

    std::string cache_key = config_.key_func(ssl);
    if (cache_key.empty())
      return false;

    return SetSSLSessionWithKey(ssl, cache_key);
  }

  // Variant of SetSSLSession to be used when the client already has computed
  // the cache key. Avoid a call to the configuration's |key_func| function.
  bool SetSSLSessionWithKey(SSL* ssl, const std::string& cache_key) {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::SetSSLSessionWithKey"));

    base::AutoLock locked(lock_);

    DCHECK_EQ(config_.key_func(ssl), cache_key);

    if (++expiration_check_ >= config_.expiration_check_count) {
      expiration_check_ = 0;
      FlushExpiredSessionsLocked();
    }

    KeyIndex::iterator it = key_index_.find(cache_key);
    if (it == key_index_.end())
      return false;

    SSL_SESSION* session = *it->second;
    DCHECK(session);

    DVLOG(2) << "Lookup session: " << session << " for " << cache_key;

    void* session_is_good =
        SSL_SESSION_get_ex_data(session, GetSSLSessionExIndex());
    if (!session_is_good)
      return false;  // Session has not yet been marked good. Treat as a miss.

    // Move to front of MRU list.
    ordering_.push_front(session);
    ordering_.erase(it->second);
    it->second = ordering_.begin();

    return SSL_set_session(ssl, session) == 1;
  }

  // Return true iff a cached session was associated with the given |cache_key|.
  bool SSLSessionIsInCache(const std::string& cache_key) const {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::SSLSessionIsInCache"));

    base::AutoLock locked(lock_);
    KeyIndex::const_iterator it = key_index_.find(cache_key);
    if (it == key_index_.end())
      return false;

    SSL_SESSION* session = *it->second;
    DCHECK(session);

    void* session_is_good =
        SSL_SESSION_get_ex_data(session, GetSSLSessionExIndex());

    return session_is_good != NULL;
  }

  void MarkSSLSessionAsGood(SSL* ssl) {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::MarkSSLSessionAsGood"));

    SSL_SESSION* session = SSL_get_session(ssl);
    CHECK(session);

    // Mark the session as good, allowing it to be used for future connections.
    SSL_SESSION_set_ex_data(
        session, GetSSLSessionExIndex(), reinterpret_cast<void*>(1));
  }

  // Flush all entries from the cache.
  void Flush() {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::Flush"));

    base::AutoLock lock(lock_);
    id_index_.clear();
    key_index_.clear();
    while (!ordering_.empty()) {
      SSL_SESSION* session = ordering_.front();
      ordering_.pop_front();
      SSL_SESSION_free(session);
    }
  }

 private:
  // Type for list of SSL_SESSION handles, ordered in MRU order.
  typedef std::list<SSL_SESSION*> MRUSessionList;
  // Type for a dictionary from unique cache keys to session list nodes.
  typedef base::hash_map<std::string, MRUSessionList::iterator> KeyIndex;
  // Type for a dictionary from SessionId values to key index nodes.
  typedef base::hash_map<SessionId, KeyIndex::iterator> SessionIdIndex;

  // Return the key associated with a given session, or the empty string if
  // none exist. This shall only be used for debugging.
  std::string SessionKey(SSL_SESSION* session) {
    if (!session)
      return std::string("<null-session>");

    if (session->session_id_length == 0)
      return std::string("<empty-session-id>");

    SessionIdIndex::iterator it = id_index_.find(SessionId(session));
    if (it == id_index_.end())
      return std::string("<unknown-session>");

    return it->second->first;
  }

  // Remove a given |session| from the cache. Lock must be held.
  void RemoveSessionLocked(SSL_SESSION* session) {
    lock_.AssertAcquired();
    DCHECK(session);
    DCHECK_GT(session->session_id_length, 0U);
    SessionId session_id(session);
    SessionIdIndex::iterator id_it = id_index_.find(session_id);
    if (id_it == id_index_.end()) {
      LOG(ERROR) << "Trying to remove unknown session from cache: " << session;
      return;
    }
    KeyIndex::iterator key_it = id_it->second;
    DCHECK(key_it != key_index_.end());
    DCHECK_EQ(session, *key_it->second);

    id_index_.erase(session_id);
    ordering_.erase(key_it->second);
    key_index_.erase(key_it);

    SSL_SESSION_free(session);

    DCHECK_EQ(key_index_.size(), id_index_.size());
  }

  // Used internally to flush expired sessions. Lock must be held.
  void FlushExpiredSessionsLocked() {
    lock_.AssertAcquired();

    // Unfortunately, OpenSSL initializes |session->time| with a time()
    // timestamps, which makes mocking / unit testing difficult.
    long timeout_secs = static_cast<long>(::time(NULL));
    MRUSessionList::iterator it = ordering_.begin();
    while (it != ordering_.end()) {
      SSL_SESSION* session = *it++;

      // Important, use <= instead of < here to allow unit testing to
      // work properly. That's because unit tests that check the expiration
      // behaviour will use a session timeout of 0 seconds.
      if (session->time + session->timeout <= timeout_secs) {
        DVLOG(2) << "Expiring session " << session << " for "
                 << SessionKey(session);
        RemoveSessionLocked(session);
      }
    }
  }

  // Retrieve the cache associated with a given SSL context |ctx|.
  static SSLSessionCacheOpenSSLImpl* GetCache(SSL_CTX* ctx) {
    DCHECK(ctx);
    void* result = SSL_CTX_get_ex_data(ctx, GetSSLContextExIndex());
    DCHECK(result);
    return reinterpret_cast<SSLSessionCacheOpenSSLImpl*>(result);
  }

  // Called by OpenSSL when a new |session| was created and added to a given
  // |ssl| connection. Note that the session's reference count was already
  // incremented before the function is entered. The function must return 1
  // to indicate that it took ownership of the session, i.e. that the caller
  // should not decrement its reference count after completion.
  static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::NewSessionCallbackStatic"));

    SSLSessionCacheOpenSSLImpl* cache = GetCache(ssl->ctx);
    cache->OnSessionAdded(ssl, session);
    return 1;
  }

  // Called by OpenSSL to indicate that a session must be removed from the
  // cache. This happens when SSL_CTX is destroyed.
  static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::RemoveSessionCallbackStatic"));

    GetCache(ctx)->OnSessionRemoved(session);
  }

  // Called by OpenSSL to generate a new session ID. This happens during a
  // SSL connection operation, when the SSL object doesn't have a session yet.
  //
  // A session ID is a random string of bytes used to uniquely identify the
  // session between a client and a server.
  //
  // |ssl| is a SSL connection handle. Ignored here.
  // |id| is the target buffer where the ID must be generated.
  // |*id_len| is, on input, the size of the desired ID. It will be 16 for
  // SSLv2, and 32 for anything else. OpenSSL allows an implementation
  // to change it on output, but this will not happen here.
  //
  // The function must ensure the generated ID is really unique, i.e. that
  // another session in the cache doesn't already use the same value. It must
  // return 1 to indicate success, or 0 for failure.
  static int GenerateSessionIdStatic(const SSL* ssl,
                                     unsigned char* id,
                                     unsigned* id_len) {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/424386 is fixed.
    tracked_objects::ScopedTracker tracking_profile(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "424386 SSLSessionCacheOpenSSLImpl::GenerateSessionIdStatic"));

    if (!GetCache(ssl->ctx)->OnGenerateSessionId(id, *id_len))
      return 0;

    return 1;
  }

  // Add |session| to the cache in association with |cache_key|. If a session
  // already exists, it is replaced with the new one. This assumes that the
  // caller already incremented the session's reference count.
  void OnSessionAdded(SSL* ssl, SSL_SESSION* session) {
    base::AutoLock locked(lock_);
    DCHECK(ssl);
    DCHECK_GT(session->session_id_length, 0U);
    std::string cache_key = config_.key_func(ssl);
    KeyIndex::iterator it = key_index_.find(cache_key);
    if (it == key_index_.end()) {
      DVLOG(2) << "Add session " << session << " for " << cache_key;
      // This is a new session. Add it to the cache.
      ordering_.push_front(session);
      std::pair<KeyIndex::iterator, bool> ret =
          key_index_.insert(std::make_pair(cache_key, ordering_.begin()));
      DCHECK(ret.second);
      it = ret.first;
      DCHECK(it != key_index_.end());
    } else {
      // An existing session exists for this key, so replace it if needed.
      DVLOG(2) << "Replace session " << *it->second << " with " << session
               << " for " << cache_key;
      SSL_SESSION* old_session = *it->second;
      if (old_session != session) {
        id_index_.erase(SessionId(old_session));
        SSL_SESSION_free(old_session);
      }
      ordering_.erase(it->second);
      ordering_.push_front(session);
      it->second = ordering_.begin();
    }

    id_index_[SessionId(session)] = it;

    if (key_index_.size() > config_.max_entries)
      ShrinkCacheLocked();

    DCHECK_EQ(key_index_.size(), id_index_.size());
    DCHECK_LE(key_index_.size(), config_.max_entries);
  }

  // Shrink the cache to ensure no more than config_.max_entries entries,
  // starting with older entries first. Lock must be acquired.
  void ShrinkCacheLocked() {
    lock_.AssertAcquired();
    DCHECK_EQ(key_index_.size(), ordering_.size());
    DCHECK_EQ(key_index_.size(), id_index_.size());

    while (key_index_.size() > config_.max_entries) {
      MRUSessionList::reverse_iterator it = ordering_.rbegin();
      DCHECK(it != ordering_.rend());

      SSL_SESSION* session = *it;
      DCHECK(session);
      DVLOG(2) << "Evicting session " << session << " for "
               << SessionKey(session);
      RemoveSessionLocked(session);
    }
  }

  // Remove |session| from the cache.
  void OnSessionRemoved(SSL_SESSION* session) {
    base::AutoLock locked(lock_);
    DVLOG(2) << "Remove session " << session << " for " << SessionKey(session);
    RemoveSessionLocked(session);
  }

  // See GenerateSessionIdStatic for a description of what this function does.
  bool OnGenerateSessionId(unsigned char* id, unsigned id_len) {
    base::AutoLock locked(lock_);
    // This mimics def_generate_session_id() in openssl/ssl/ssl_sess.cc,
    // I.e. try to generate a pseudo-random bit string, and check that no
    // other entry in the cache has the same value.
    const size_t kMaxTries = 10;
    for (size_t tries = 0; tries < kMaxTries; ++tries) {
      if (RAND_pseudo_bytes(id, id_len) <= 0) {
        DLOG(ERROR) << "Couldn't generate " << id_len
                    << " pseudo random bytes?";
        return false;
      }
      if (id_index_.find(SessionId(id, id_len)) == id_index_.end())
        return true;
    }
    DLOG(ERROR) << "Couldn't generate unique session ID of " << id_len
                << "bytes after " << kMaxTries << " tries.";
    return false;
  }

  SSL_CTX* ctx_;
  SSLSessionCacheOpenSSL::Config config_;

  // method to get the index which can later be used with SSL_CTX_get_ex_data()
  // or SSL_CTX_set_ex_data().
  mutable base::Lock lock_;  // Protects access to containers below.

  MRUSessionList ordering_;
  KeyIndex key_index_;
  SessionIdIndex id_index_;

  size_t expiration_check_;
};

SSLSessionCacheOpenSSL::~SSLSessionCacheOpenSSL() { delete impl_; }

size_t SSLSessionCacheOpenSSL::size() const { return impl_->size(); }

void SSLSessionCacheOpenSSL::Reset(SSL_CTX* ctx, const Config& config) {
  if (impl_)
    delete impl_;

  impl_ = new SSLSessionCacheOpenSSLImpl(ctx, config);
}

bool SSLSessionCacheOpenSSL::SetSSLSession(SSL* ssl) {
  return impl_->SetSSLSession(ssl);
}

bool SSLSessionCacheOpenSSL::SetSSLSessionWithKey(
    SSL* ssl,
    const std::string& cache_key) {
  return impl_->SetSSLSessionWithKey(ssl, cache_key);
}

bool SSLSessionCacheOpenSSL::SSLSessionIsInCache(
    const std::string& cache_key) const {
  return impl_->SSLSessionIsInCache(cache_key);
}

void SSLSessionCacheOpenSSL::MarkSSLSessionAsGood(SSL* ssl) {
  return impl_->MarkSSLSessionAsGood(ssl);
}

void SSLSessionCacheOpenSSL::Flush() { impl_->Flush(); }

}  // namespace net
