• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SSLSessionCacheOpenSSL()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.
SSLSessionCacheOpenSSL(SSL_CTX * ctx,const Config & config)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   // Indicates that the SSL session associated with |ssl| is "good" - that is,
117   // that all associated cryptographic parameters that were negotiated,
118   // including the peer's certificate, were successfully validated. Because
119   // OpenSSL does not provide an asynchronous certificate verification
120   // callback, it's necessary to manually manage the sessions to ensure that
121   // only validated sessions are resumed.
122   void MarkSSLSessionAsGood(SSL* ssl);
123 
124   // Flush removes all entries from the cache. This is typically called when
125   // the system's certificate store has changed.
126   void Flush();
127 
128   // TODO(digit): Move to client code.
129   static const int kDefaultTimeoutSeconds = 60 * 60;
130   static const size_t kMaxEntries = 1024;
131   static const size_t kMaxExpirationChecks = 256;
132 
133  private:
134   DISALLOW_COPY_AND_ASSIGN(SSLSessionCacheOpenSSL);
135 
136   SSLSessionCacheOpenSSLImpl* impl_;
137 };
138 
139 }  // namespace net
140 
141 #endif  // NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
142