Home | History | Annotate | Download | only in socket
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
      6 #define NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
      7 
      8 #include <string>
      9 
     10 #include "base/basictypes.h"
     11 #include "net/base/net_export.h"
     12 
     13 // Avoid including OpenSSL headers here.
     14 typedef struct ssl_ctx_st SSL_CTX;
     15 typedef struct ssl_st SSL;
     16 
     17 namespace net {
     18 
     19 class SSLSessionCacheOpenSSLImpl;
     20 
     21 // A class used to implement a custom cache of SSL_SESSION objects.
     22 // Usage is as follows:
     23 //
     24 //  - Client creates a new cache instance with appropriate configuration,
     25 //    associating it with a given SSL_CTX object.
     26 //
     27 //    The configuration must include a pointer to a client-provided function
     28 //    that can retrieve a unique cache key from an existing SSL handle.
     29 //
     30 //  - When creating a new SSL connection, call SetSSLSession() with the newly
     31 //    created SSL handle, and a cache key for the current host/port. If a
     32 //    session is already in the cache, it will be added to the connection
     33 //    through SSL_set_session().
     34 //
     35 //  - Otherwise, OpenSSL will create a new SSL_SESSION object during the
     36 //    connection, and will pass it to the cache's internal functions,
     37 //    transparently to the client.
     38 //
     39 //  - Each session has a timeout in seconds, which are checked every N-th call
     40 //    to SetSSLSession(), where N is the current configuration's
     41 //    |check_expiration_count|. Expired sessions are removed automatically
     42 //    from the cache.
     43 //
     44 //  - Clients can call Flush() to remove all sessions from the cache, this is
     45 //    useful when the system's certificate store has changed.
     46 //
     47 // This class is thread-safe. There shouldn't be any issue with multiple
     48 // SSL connections being performed in parallel in multiple threads.
     49 class NET_EXPORT SSLSessionCacheOpenSSL {
     50  public:
     51   // Type of a function that takes a SSL handle and returns a unique cache
     52   // key string to identify it.
     53   typedef std::string GetSessionKeyFunction(const SSL* ssl);
     54 
     55   // A small structure used to configure a cache on creation.
     56   // |key_func| is a function used at runtime to retrieve the unique cache key
     57   // from a given SSL connection handle.
     58   // |max_entries| is the maximum number of entries in the cache.
     59   // |expiration_check_count| is the number of calls to SetSSLSession() that
     60   // will trigger a check for expired sessions.
     61   // |timeout_seconds| is the timeout of new cached sessions in seconds.
     62   struct Config {
     63     GetSessionKeyFunction* key_func;
     64     size_t max_entries;
     65     size_t expiration_check_count;
     66     int timeout_seconds;
     67   };
     68 
     69   SSLSessionCacheOpenSSL() : impl_(NULL) {}
     70 
     71   // Construct a new cache instance.
     72   // |ctx| is a SSL_CTX context handle that will be associated with this cache.
     73   // |key_func| is a function that will be used at runtime to retrieve the
     74   // unique cache key from a SSL connection handle.
     75   // |max_entries| is the maximum number of entries in the cache.
     76   // |timeout_seconds| is the timeout of new cached sessions in seconds.
     77   // |expiration_check_count| is the number of calls to SetSSLSession() that
     78   // will trigger a check for expired sessions.
     79   SSLSessionCacheOpenSSL(SSL_CTX* ctx, const Config& config) : impl_(NULL) {
     80     Reset(ctx, config);
     81   }
     82 
     83   // Destroy this instance. This must be called before the SSL_CTX handle
     84   // is destroyed.
     85   ~SSLSessionCacheOpenSSL();
     86 
     87   // Reset the cache configuration. This flushes any existing entries.
     88   void Reset(SSL_CTX* ctx, const Config& config);
     89 
     90   size_t size() const;
     91 
     92   // Lookup the unique cache key associated with |ssl| connection handle,
     93   // and find a cached session for it in the cache. If one is found, associate
     94   // it with the |ssl| connection through SSL_set_session(). Consider using
     95   // SetSSLSessionWithKey() if you already have the key.
     96   //
     97   // Every |check_expiration_count| call to either SetSSLSession() or
     98   // SetSSLSessionWithKey() triggers a check for, and removal of, expired
     99   // sessions.
    100   //
    101   // Return true iff a cached session was associated with the |ssl| connection.
    102   bool SetSSLSession(SSL* ssl);
    103 
    104   // A more efficient variant of SetSSLSession() that can be used if the caller
    105   // already has the cache key for the session of interest. The caller must
    106   // ensure that the value of |cache_key| matches the result of calling the
    107   // configuration's |key_func| function with the |ssl| as parameter.
    108   //
    109   // Every |check_expiration_count| call to either SetSSLSession() or
    110   // SetSSLSessionWithKey() triggers a check for, and removal of, expired
    111   // sessions.
    112   //
    113   // Return true iff a cached session was associated with the |ssl| connection.
    114   bool SetSSLSessionWithKey(SSL* ssl, const std::string& cache_key);
    115 
    116   // Return true iff a cached session was associated with the given |cache_key|.
    117   bool SSLSessionIsInCache(const std::string& cache_key) const;
    118 
    119   // Indicates that the SSL session associated with |ssl| is "good" - that is,
    120   // that all associated cryptographic parameters that were negotiated,
    121   // including the peer's certificate, were successfully validated. Because
    122   // OpenSSL does not provide an asynchronous certificate verification
    123   // callback, it's necessary to manually manage the sessions to ensure that
    124   // only validated sessions are resumed.
    125   void MarkSSLSessionAsGood(SSL* ssl);
    126 
    127   // Flush removes all entries from the cache. This is typically called when
    128   // the system's certificate store has changed.
    129   void Flush();
    130 
    131   // TODO(digit): Move to client code.
    132   static const int kDefaultTimeoutSeconds = 60 * 60;
    133   static const size_t kMaxEntries = 1024;
    134   static const size_t kMaxExpirationChecks = 256;
    135 
    136  private:
    137   DISALLOW_COPY_AND_ASSIGN(SSLSessionCacheOpenSSL);
    138 
    139   SSLSessionCacheOpenSSLImpl* impl_;
    140 };
    141 
    142 }  // namespace net
    143 
    144 #endif  // NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
    145