Document session cache functions.

Also switch to the new variable names (SSL_CTX *ctx, SSL *ssl,
SSL_SESSION *session) for all documented functions.

Change-Id: I15e15a703b96af1727601108223c7ce3b0691f1d
Reviewed-on: https://boringssl-review.googlesource.com/5882
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin 2015-09-14 01:40:10 -04:00 committed by Adam Langley
parent 14e2b5070b
commit dafbdd49c7
3 changed files with 357 additions and 200 deletions

View File

@ -431,7 +431,7 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code);
* lookup callback indicated the session was unavailable. The caller may retry
* the operation when lookup has completed.
*
* See also |SSL_CTX_sess_set_get_cb|. */
* See also |SSL_CTX_sess_set_get_cb| and |SSL_magic_pending_session_ptr|. */
#define SSL_ERROR_PENDING_SESSION 11
/* SSL_ERROR_PENDING_CERTIFICATE indicates the operation failed because the
@ -505,7 +505,7 @@ OPENSSL_EXPORT void SSL_set_max_version(SSL *ssl, uint16_t version);
* |BIO|. Instead, the MTU is configured with |SSL_set_mtu|. */
#define SSL_OP_NO_QUERY_MTU 0x00001000L
/* SSL_OP_NO_TICKET disables session ticket support (RFC 4507). */
/* SSL_OP_NO_TICKET disables session ticket support (RFC 5077). */
#define SSL_OP_NO_TICKET 0x00004000L
/* SSL_OP_CIPHER_SERVER_PREFERENCE configures servers to select ciphers and
@ -1135,7 +1135,260 @@ OPENSSL_EXPORT int SSL_SESSION_set1_id_context(SSL_SESSION *session,
unsigned sid_ctx_len);
/* Session tickets. */
/* Session caching.
*
* Session caching allows clients to reconnect to a server based on saved
* parameters from a previous connection.
*
* For a server, the library implements a built-in internal session cache as an
* in-memory hash table. One may also register callbacks to implement a custom
* external session cache. An external cache may be used in addition to or
* instead of the internal one. Use |SSL_CTX_set_session_cache_mode| to toggle
* the internal cache.
*
* For a client, the only option is an external session cache. Prior to
* handshaking, the consumer should look up a session externally (keyed, for
* instance, by hostname) and use |SSL_set_session| to configure which session
* to offer. The callbacks may be used to determine when new sessions are
* available.
*
* Note that offering or accepting a session short-circuits most parameter
* negotiation. Resuming sessions across different configurations may result in
* surprising behavor. So, for instance, a client implementing a version
* fallback should shard its session cache by maximum protocol version. */
/* SSL_SESS_CACHE_OFF disables all session caching. */
#define SSL_SESS_CACHE_OFF 0x0000
/* SSL_SESS_CACHE_CLIENT enables session caching for a client.
*
* TODO(davidben): The internal cache is useless on the client. Always act as if
* SSL_SESS_CACHE_NO_INTERNAL is set. https://crbug.com/531194. Also see TODO
* attached to |SSL_CTX_sess_set_new_cb|. */
#define SSL_SESS_CACHE_CLIENT 0x0001
/* SSL_SESS_CACHE_SERVER enables session caching for a server. */
#define SSL_SESS_CACHE_SERVER 0x0002
/* SSL_SESS_CACHE_SERVER enables session caching for both client and server. */
#define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_SERVER)
/* SSL_SESS_CACHE_NO_AUTO_CLEAR disables automatically calling
* |SSL_CTX_flush_sessions| every 255 connections. */
#define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080
/* SSL_SESS_CACHE_NO_INTERNAL_LOOKUP disables looking up a session from the
* internal session cache. */
#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100
/* SSL_SESS_CACHE_NO_INTERNAL_STORE disables storing sessions in the internal
* session cache. */
#define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200
/* SSL_SESS_CACHE_NO_INTERNAL disables the internal session cache. */
#define SSL_SESS_CACHE_NO_INTERNAL \
(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | SSL_SESS_CACHE_NO_INTERNAL_STORE)
/* SSL_CTX_set_session_cache_mode sets the session cache mode bits for |ctx| to
* |mode|. It returns the previous value. */
OPENSSL_EXPORT int SSL_CTX_set_session_cache_mode(SSL_CTX *ctx, int mode);
/* SSL_CTX_get_session_cache_mode returns the session cache mode bits for
* |ctx| */
OPENSSL_EXPORT int SSL_CTX_get_session_cache_mode(const SSL_CTX *ctx);
/* SSL_set_session, for a client, configures |ssl| to offer to resume |session|
* in the initial handshake. */
OPENSSL_EXPORT int SSL_set_session(SSL *ssl, SSL_SESSION *session);
/* SSL_get_session returns a non-owning pointer to |ssl|'s session. Prior to the
* initial handshake beginning, this is the session to be offered, set by
* |SSL_set_session|. After a handshake has finished, this is the currently
* active session. Its behavior is undefined while a handshake is progress. */
OPENSSL_EXPORT SSL_SESSION *SSL_get_session(const SSL *ssl);
/* SSL_get0_session is an alias for |SSL_get_session|. */
#define SSL_get0_session SSL_get_session
/* SSL_get1_session acts like |SSL_get_session| but returns a new reference to
* the session. */
OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl);
/* SSL_CTX_set_timeout sets the lifetime of sessions created in |ctx| to
* |timeout|. */
OPENSSL_EXPORT long SSL_CTX_set_timeout(SSL_CTX *ctx, long timeout);
/* SSL_CTX_get_timeout returns the lifetime of sessions created in |ctx|. */
OPENSSL_EXPORT long SSL_CTX_get_timeout(const SSL_CTX *ctx);
/* SSL_CTX_set_session_id_context sets |ctx|'s session ID context to |sid_ctx|.
* It returns one on success and zero on error. The session ID context is an
* application-defined opaque byte string. A session will not be used in a
* connection without a matching session ID context.
*
* For a server, if |SSL_VERIFY_PEER| is enabled, it is an error to not set a
* session ID context.
*
* TODO(davidben): Is that check needed? That seems a special case of taking
* care not to cross-resume across configuration changes, and this is only
* relevant if a server requires client auth. */
OPENSSL_EXPORT int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
const uint8_t *sid_ctx,
unsigned sid_ctx_len);
/* SSL_set_session_id_context sets |ssl|'s session ID context to |sid_ctx|. It
* returns one on success and zero on error. See also
* |SSL_CTX_set_session_id_context|. */
OPENSSL_EXPORT int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
unsigned sid_ctx_len);
/* SSL_CTX_sess_set_cache_size sets the maximum size of |ctx|'s internal session
* cache to |size|. It returns the previous value. */
OPENSSL_EXPORT unsigned long SSL_CTX_sess_set_cache_size(SSL_CTX *ctx,
unsigned long size);
/* SSL_CTX_sess_get_cache_size returns the maximum size of |ctx|'s internal
* session cache. */
OPENSSL_EXPORT unsigned long SSL_CTX_sess_get_cache_size(const SSL_CTX *ctx);
/* SSL_CTX_sessions returns |ctx|'s internal session cache. */
OPENSSL_EXPORT LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
/* SSL_CTX_sess_number returns the number of sessions in |ctx|'s internal
* session cache. */
OPENSSL_EXPORT size_t SSL_CTX_sess_number(const SSL_CTX *ctx);
/* SSL_CTX_add_session inserts |session| into |ctx|'s internal session cache. It
* returns one on success and zero on error or if |ctx| already included a
* session with that session ID. The caller retains its reference to
* |session|. */
OPENSSL_EXPORT int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session);
/* SSL_CTX_remove_session removes |session| from |ctx|'s internal session cache.
* It returns one on success and zero on error or if no session with a matching
* ID was found. */
OPENSSL_EXPORT int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session);
/* SSL_CTX_flush_sessions removes all sessions from |ctx| which have expired as
* of time |time|. If |time| is zero, all sessions are removed. */
OPENSSL_EXPORT void SSL_CTX_flush_sessions(SSL_CTX *ctx, long time);
/* SSL_CTX_sess_set_new_cb sets the callback to be called when a new session is
* established and ready to be cached. If the session cache is disabled (the
* appropriate one of |SSL_SESS_CACHE_CLIENT| or |SSL_SESS_CACHE_SERVER| is
* unset), the callback is not called.
*
* The callback is passed a reference to |session|. It returns one if it takes
* ownership and zero otherwise.
*
* Note: For a client, the callback may be called on abbreviated handshakes if a
* ticket is renewed. Further, it may not be called until some time after
* |SSL_do_handshake| or |SSL_connect| completes if False Start is enabled. Thus
* it's recommended to use this callback over checking |SSL_session_reused| on
* handshake completion.
*
* TODO(davidben): Conditioning callbacks on |SSL_SESS_CACHE_CLIENT| or
* |SSL_SESS_CACHE_SERVER| doesn't make any sense when one could just as easily
* not supply the callbacks. Removing that condition and the client internal
* cache would simplify things. */
OPENSSL_EXPORT void SSL_CTX_sess_set_new_cb(
SSL_CTX *ctx, int (*new_session_cb)(SSL *ssl, SSL_SESSION *session));
/* SSL_CTX_sess_get_new_cb returns the callback set by
* |SSL_CTX_sess_set_new_cb|. */
OPENSSL_EXPORT int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(
SSL *ssl, SSL_SESSION *session);
/* SSL_CTX_sess_set_remove_cb sets a callback which is called when a session is
* removed from the internal session cache.
*
* TODO(davidben): What is the point of this callback? It seems useless since it
* only fires on sessions in the internal cache. */
OPENSSL_EXPORT void SSL_CTX_sess_set_remove_cb(
SSL_CTX *ctx,
void (*remove_session_cb)(SSL_CTX *ctx, SSL_SESSION *session));
/* SSL_CTX_sess_get_remove_cb returns the callback set by
* |SSL_CTX_sess_set_remove_cb|. */
OPENSSL_EXPORT void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(
SSL_CTX *ctx, SSL_SESSION *session);
/* SSL_CTX_sess_set_get_cb sets a callback to look up a session by ID for a
* server. The callback is passed the session ID and should return a matching
* |SSL_SESSION| or NULL if not found. It should set |*out_copy| to zero and
* return a new reference to the session. This callback is not used for a
* client.
*
* For historical reasons, if |*out_copy| is set to one (default), the SSL
* library will take a new reference to the returned |SSL_SESSION|, expecting
* the callback to return a non-owning pointer. This is not recommended. If
* |ctx| and thus the callback is used on multiple threads, the session may be
* removed and invalidated before the SSL library calls |SSL_SESSION_up_ref|,
* whereas the callback may synchronize internally.
*
* To look up a session asynchronously, the callback may return
* |SSL_magic_pending_session_ptr|. See the documentation for that function and
* |SSL_ERROR_PENDING_SESSION|.
*
* If the internal session cache is enabled, the callback is only consulted if
* the internal cache does not return a match. */
OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb(
SSL_CTX *ctx,
SSL_SESSION *(*get_session_cb)(SSL *ssl, uint8_t *id, int id_len,
int *out_copy));
/* SSL_CTX_sess_get_get_cb returns the callback set by
* |SSL_CTX_sess_set_get_cb|. */
OPENSSL_EXPORT SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
SSL *ssl, uint8_t *id, int id_len, int *out_copy);
/* SSL_magic_pending_session_ptr returns a magic |SSL_SESSION|* which indicates
* that the session isn't currently unavailable. |SSL_get_error| will then
* return |SSL_ERROR_PENDING_SESSION| and the handshake can be retried later
* when the lookup has completed. */
OPENSSL_EXPORT SSL_SESSION *SSL_magic_pending_session_ptr(void);
/* GEN_SESSION_CB is a callback to generate session IDs for |ssl|. It returns
* one on success and zero on error. On success, the generated ID is written to
* |id| and |*id_len| set to the length. On entry, |*id_len| is the maximum
* length of the ID, but the callback may shorten it if desired. It is an error
* for the callback to set the size to zero.
*
* Callbacks may use |SSL_has_matching_session_id| to check that the generated
* ID is unique. */
typedef int (*GEN_SESSION_CB)(const SSL *ssl, uint8_t *id, unsigned *id_len);
/* SSL_CTX_set_generate_session_id sets the session ID callback of |ctx| to
* |cb| and returns one. It will be called on the server when establishing a new
* session. */
OPENSSL_EXPORT int SSL_CTX_set_generate_session_id(SSL_CTX *ctx,
GEN_SESSION_CB cb);
/* SSL_set_generate_session_id sets the session ID callback of |ssl| to |cb| and
* returns one. It will be called on the server when establishing a new
* session. */
OPENSSL_EXPORT int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb);
/* SSL_has_matching_session_id returns one if |ssl|'s session cache has a
* session of value |id| and zero otherwise. */
OPENSSL_EXPORT int SSL_has_matching_session_id(const SSL *ssl,
const uint8_t *id,
unsigned id_len);
/* Session tickets.
*
* Session tickets, from RFC 5077, allow session resumption without server-side
* state. Session tickets are supported in by default but may be disabled with
* |SSL_OP_NO_TICKET|.
*
* On the client, ticket-based sessions use the same APIs as ID-based tickets.
* Callers do not need to handle them differently.
*
* On the server, tickets are encrypted and authenticated with a secret key. By
* default, an |SSL_CTX| generates a key on creation. Tickets are minted and
* processed transparently. The following functions may be used to configure a
* persistent key or implement more custom behavior. */
/* SSL_CTX_get_tlsext_ticket_keys writes |ctx|'s session ticket key material to
* |len| bytes of |out|. It returns one on success and zero if |len| is not
@ -1368,22 +1621,6 @@ typedef struct ssl_aead_ctx_st SSL_AEAD_CTX;
#define SSL_DEFAULT_SESSION_TIMEOUT (2 * 60 * 60)
/* This callback type is used inside SSL_CTX, SSL, and in the functions that
* set them. It is used to override the generation of SSL/TLS session IDs in a
* server. Return value should be zero on an error, non-zero to proceed. Also,
* callbacks should themselves check if the id they generate is unique
* otherwise the SSL handshake will fail with an error - callbacks can do this
* using the 'ssl' value they're passed by;
* SSL_has_matching_session_id(ssl, id, *id_len)
* The length value passed in is set at the maximum size the session ID can be.
* In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback
* can alter this length to be less if desired, but under SSLv2 session IDs are
* supposed to be fixed at 16 bytes so the id will be padded after the callback
* returns in this case. It is also an error for the callback to set the size
* to zero. */
typedef int (*GEN_SESSION_CB)(const SSL *ssl, uint8_t *id,
unsigned int *id_len);
/* ssl_early_callback_ctx is passed to certain callbacks that are called very
* early on during the server handshake. At this point, much of the SSL* hasn't
* been filled out and only the ClientHello can be depended on. */
@ -1421,32 +1658,6 @@ struct ssl_comp_st {
DECLARE_STACK_OF(SSL_COMP)
DECLARE_LHASH_OF(SSL_SESSION)
OPENSSL_EXPORT LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
/* SSL_CTX_sess_number returns the number of sessions in |ctx|'s internal
* session cache. */
OPENSSL_EXPORT size_t SSL_CTX_sess_number(const SSL_CTX *ctx);
OPENSSL_EXPORT void SSL_CTX_sess_set_new_cb(
SSL_CTX *ctx, int (*new_session_cb)(SSL *ssl, SSL_SESSION *sess));
OPENSSL_EXPORT int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl,
SSL_SESSION *sess);
OPENSSL_EXPORT void SSL_CTX_sess_set_remove_cb(
SSL_CTX *ctx,
void (*remove_session_cb)(SSL_CTX *ctx, SSL_SESSION *sess));
OPENSSL_EXPORT void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(
SSL_CTX *ctx, SSL_SESSION *sess);
OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb(
SSL_CTX *ctx,
SSL_SESSION *(*get_session_cb)(SSL *ssl, uint8_t *data, int len,
int *copy));
OPENSSL_EXPORT SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
SSL *ssl, uint8_t *data, int len, int *copy);
/* SSL_magic_pending_session_ptr returns a magic |SSL_SESSION|* which indicates
* that the session isn't currently unavailable. |SSL_get_error| will then
* return |SSL_ERROR_PENDING_SESSION| and the handshake can be retried later
* when the lookup has completed. */
OPENSSL_EXPORT SSL_SESSION *SSL_magic_pending_session_ptr(void);
OPENSSL_EXPORT void SSL_CTX_set_info_callback(SSL_CTX *ctx,
void (*cb)(const SSL *ssl,
int type, int val));
@ -1840,14 +2051,10 @@ OPENSSL_EXPORT int SSL_set1_curves(SSL *ssl, const int *curves,
OPENSSL_EXPORT int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls10(SSL_CTX *, const char *str);
OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls11(SSL_CTX *, const char *str);
OPENSSL_EXPORT long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
OPENSSL_EXPORT long SSL_CTX_get_timeout(const SSL_CTX *ctx);
OPENSSL_EXPORT X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
OPENSSL_EXPORT void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
OPENSSL_EXPORT int SSL_want(const SSL *s);
OPENSSL_EXPORT void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm);
/* SSL_get_current_cipher returns the cipher used in the current outgoing
* connection state, or NULL if the null cipher is active. */
OPENSSL_EXPORT const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
@ -1883,15 +2090,6 @@ OPENSSL_EXPORT const char *SSL_state_string_long(const SSL *s);
OPENSSL_EXPORT int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses);
OPENSSL_EXPORT int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses);
OPENSSL_EXPORT int SSL_set_session(SSL *to, SSL_SESSION *session);
OPENSSL_EXPORT int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
OPENSSL_EXPORT int SSL_CTX_remove_session(SSL_CTX *, SSL_SESSION *c);
OPENSSL_EXPORT int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
OPENSSL_EXPORT int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
OPENSSL_EXPORT int SSL_has_matching_session_id(const SSL *ssl,
const uint8_t *id,
unsigned int id_len);
OPENSSL_EXPORT int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
OPENSSL_EXPORT int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
OPENSSL_EXPORT int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(
@ -1907,13 +2105,6 @@ OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,
OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,
void *u);
OPENSSL_EXPORT int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
const uint8_t *sid_ctx,
unsigned int sid_ctx_len);
OPENSSL_EXPORT int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
unsigned int sid_ctx_len);
OPENSSL_EXPORT int SSL_CTX_set_purpose(SSL_CTX *s, int purpose);
OPENSSL_EXPORT int SSL_set_purpose(SSL *s, int purpose);
OPENSSL_EXPORT int SSL_CTX_set_trust(SSL_CTX *s, int trust);
@ -1969,10 +2160,6 @@ OPENSSL_EXPORT int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
OPENSSL_EXPORT int SSL_CTX_load_verify_locations(SSL_CTX *ctx,
const char *CAfile,
const char *CApath);
#define SSL_get0_session SSL_get_session /* just peek at pointer */
OPENSSL_EXPORT SSL_SESSION *SSL_get_session(const SSL *ssl);
OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(
SSL *ssl); /* obtain a reference count */
OPENSSL_EXPORT SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
OPENSSL_EXPORT SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
OPENSSL_EXPORT void SSL_set_info_callback(SSL *ssl,
@ -1987,35 +2174,6 @@ OPENSSL_EXPORT long SSL_get_verify_result(const SSL *ssl);
OPENSSL_EXPORT int SSL_get_ex_data_X509_STORE_CTX_idx(void);
/* SSL_CTX_sess_set_cache_size sets the maximum size of |ctx|'s session cache to
* |size|. It returns the previous value. */
OPENSSL_EXPORT unsigned long SSL_CTX_sess_set_cache_size(SSL_CTX *ctx,
unsigned long size);
/* SSL_CTX_sess_get_cache_size returns the maximum size of |ctx|'s session
* cache. */
OPENSSL_EXPORT unsigned long SSL_CTX_sess_get_cache_size(const SSL_CTX *ctx);
/* SSL_SESS_CACHE_* are the possible session cache mode bits.
* TODO(davidben): Document. */
#define SSL_SESS_CACHE_OFF 0x0000
#define SSL_SESS_CACHE_CLIENT 0x0001
#define SSL_SESS_CACHE_SERVER 0x0002
#define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_SERVER)
#define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080
#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100
#define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200
#define SSL_SESS_CACHE_NO_INTERNAL \
(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | SSL_SESS_CACHE_NO_INTERNAL_STORE)
/* SSL_CTX_set_session_cache_mode sets the session cache mode bits for |ctx| to
* |mode|. It returns the previous value. */
OPENSSL_EXPORT int SSL_CTX_set_session_cache_mode(SSL_CTX *ctx, int mode);
/* SSL_CTX_get_session_cache_mode returns the session cache mode bits for
* |ctx| */
OPENSSL_EXPORT int SSL_CTX_get_session_cache_mode(const SSL_CTX *ctx);
/* SSL_CTX_get_max_cert_list returns the maximum length, in bytes, of a peer
* certificate chain accepted by |ctx|. */
OPENSSL_EXPORT size_t SSL_CTX_get_max_cert_list(const SSL_CTX *ctx);

View File

@ -918,8 +918,8 @@ err:
}
int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx,
unsigned int sid_ctx_len) {
if (sid_ctx_len > sizeof ctx->sid_ctx) {
unsigned sid_ctx_len) {
if (sid_ctx_len > sizeof(ctx->sid_ctx)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
@ -930,7 +930,7 @@ int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx,
}
int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
unsigned int sid_ctx_len) {
unsigned sid_ctx_len) {
if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
@ -952,7 +952,7 @@ int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) {
}
int SSL_has_matching_session_id(const SSL *ssl, const uint8_t *id,
unsigned int id_len) {
unsigned id_len) {
/* A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how we
* can "construct" a session to give us the desired check - ie. to find if
* there's a session in the hash table that would conflict with any new

View File

@ -154,9 +154,9 @@ static const char g_pending_session_magic = 0;
static CRYPTO_EX_DATA_CLASS g_ex_data_class =
CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock);
SSL_SESSION *SSL_SESSION_new(void) {
SSL_SESSION *session = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
@ -301,9 +301,9 @@ void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
* server. How you might store that many sessions is perhaps a more interesting
* question ... */
static int def_generate_session_id(const SSL *ssl, uint8_t *id,
unsigned int *id_len) {
unsigned *id_len) {
static const unsigned kMaxAttempts = 10;
unsigned int retry = 0;
unsigned retry = 0;
do {
if (!RAND_bytes(id, *id_len)) {
return 0;
@ -568,49 +568,49 @@ no_session:
return ssl_session_success;
}
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) {
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
int ret = 0;
SSL_SESSION *s;
SSL_SESSION *old_session;
/* add just 1 reference count for the SSL_CTX's session cache even though it
/* Add just 1 reference count for the |SSL_CTX|'s session cache even though it
* has two ways of access: each session is in a doubly linked list and an
* lhash */
SSL_SESSION_up_ref(c);
/* if session c is in already in cache, we take back the increment later */
* lhash. */
SSL_SESSION_up_ref(session);
/* If |session| is in already in cache, we take back the increment later. */
CRYPTO_MUTEX_lock_write(&ctx->lock);
if (!lh_SSL_SESSION_insert(ctx->sessions, &s, c)) {
if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
CRYPTO_MUTEX_unlock(&ctx->lock);
SSL_SESSION_free(c);
SSL_SESSION_free(session);
return 0;
}
/* s != NULL iff we already had a session with the given session ID. In this
* case, s == c should hold (then we did not really modify ctx->sessions), or
* we're in trouble. */
if (s != NULL && s != c) {
/* |old_session| != NULL iff we already had a session with the given session
* ID. In this case, |old_session| == |session| should hold (then we did not
* really modify |ctx->sessions|), or we're in trouble. */
if (old_session != NULL && old_session != session) {
/* We *are* in trouble ... */
SSL_SESSION_list_remove(ctx, s);
SSL_SESSION_free(s);
SSL_SESSION_list_remove(ctx, old_session);
SSL_SESSION_free(old_session);
/* ... so pretend the other session did not exist in cache (we cannot
* handle two SSL_SESSION structures with identical session ID in the same
* handle two |SSL_SESSION| structures with identical session ID in the same
* cache, which could happen e.g. when two threads concurrently obtain the
* same session from an external cache) */
s = NULL;
* same session from an external cache). */
old_session = NULL;
}
/* Put at the head of the queue unless it is already in the cache */
if (s == NULL) {
SSL_SESSION_list_add(ctx, c);
/* Put at the head of the queue unless it is already in the cache. */
if (old_session == NULL) {
SSL_SESSION_list_add(ctx, session);
}
if (s != NULL) {
/* existing cache entry -- decrement previously incremented reference count
* because it already takes into account the cache */
SSL_SESSION_free(s); /* s == c */
if (old_session != NULL) {
/* Existing cache entry -- decrement previously incremented reference count
* because it already takes into account the cache. */
SSL_SESSION_free(old_session); /* |old_session| == |session| */
ret = 0;
} else {
/* new cache entry -- remove old ones if cache has become too large */
/* New cache entry -- remove old ones if cache has become too large. */
ret = 1;
if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
@ -626,23 +626,23 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) {
return ret;
}
int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) {
return remove_session_lock(ctx, c, 1);
int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session) {
return remove_session_lock(ctx, session, 1);
}
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lock) {
SSL_SESSION *r;
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
int ret = 0;
if (c != NULL && c->session_id_length != 0) {
if (session != NULL && session->session_id_length != 0) {
if (lock) {
CRYPTO_MUTEX_lock_write(&ctx->lock);
}
r = lh_SSL_SESSION_retrieve(ctx->sessions, c);
if (r == c) {
SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions,
session);
if (found_session == session) {
ret = 1;
r = lh_SSL_SESSION_delete(ctx->sessions, c);
SSL_SESSION_list_remove(ctx, c);
found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
SSL_SESSION_list_remove(ctx, session);
}
if (lock) {
@ -650,49 +650,48 @@ static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lock) {
}
if (ret) {
r->not_resumable = 1;
found_session->not_resumable = 1;
if (ctx->remove_session_cb != NULL) {
ctx->remove_session_cb(ctx, r);
ctx->remove_session_cb(ctx, found_session);
}
SSL_SESSION_free(r);
SSL_SESSION_free(found_session);
}
}
return ret;
}
int SSL_set_session(SSL *s, SSL_SESSION *session) {
if (s->session == session) {
int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
if (ssl->session == session) {
return 1;
}
SSL_SESSION_free(s->session);
s->session = session;
SSL_SESSION_free(ssl->session);
ssl->session = session;
if (session != NULL) {
SSL_SESSION_up_ref(session);
s->verify_result = session->verify_result;
ssl->verify_result = session->verify_result;
}
return 1;
}
long SSL_CTX_set_timeout(SSL_CTX *s, long t) {
long l;
if (s == NULL) {
long SSL_CTX_set_timeout(SSL_CTX *ctx, long timeout) {
if (ctx == NULL) {
return 0;
}
l = s->session_timeout;
s->session_timeout = t;
return l;
long old_timeout = ctx->session_timeout;
ctx->session_timeout = timeout;
return old_timeout;
}
long SSL_CTX_get_timeout(const SSL_CTX *s) {
if (s == NULL) {
long SSL_CTX_get_timeout(const SSL_CTX *ctx) {
if (ctx == NULL) {
return 0;
}
return s->session_timeout;
return ctx->session_timeout;
}
typedef struct timeout_param_st {
@ -701,25 +700,25 @@ typedef struct timeout_param_st {
LHASH_OF(SSL_SESSION) *cache;
} TIMEOUT_PARAM;
static void timeout_doall_arg(SSL_SESSION *sess, void *void_param) {
static void timeout_doall_arg(SSL_SESSION *session, void *void_param) {
TIMEOUT_PARAM *param = void_param;
if (param->time == 0 ||
param->time > (sess->time + sess->timeout)) {
param->time > (session->time + session->timeout)) {
/* timeout */
/* The reason we don't call SSL_CTX_remove_session() is to
* save on locking overhead */
(void) lh_SSL_SESSION_delete(param->cache, sess);
SSL_SESSION_list_remove(param->ctx, sess);
sess->not_resumable = 1;
(void) lh_SSL_SESSION_delete(param->cache, session);
SSL_SESSION_list_remove(param->ctx, session);
session->not_resumable = 1;
if (param->ctx->remove_session_cb != NULL) {
param->ctx->remove_session_cb(param->ctx, sess);
param->ctx->remove_session_cb(param->ctx, session);
}
SSL_SESSION_free(sess);
SSL_SESSION_free(session);
}
}
void SSL_CTX_flush_sessions(SSL_CTX *ctx, long t) {
void SSL_CTX_flush_sessions(SSL_CTX *ctx, long time) {
TIMEOUT_PARAM tp;
tp.ctx = ctx;
@ -727,7 +726,7 @@ void SSL_CTX_flush_sessions(SSL_CTX *ctx, long t) {
if (tp.cache == NULL) {
return;
}
tp.time = t;
tp.time = time;
CRYPTO_MUTEX_lock_write(&ctx->lock);
lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
CRYPTO_MUTEX_unlock(&ctx->lock);
@ -744,80 +743,80 @@ int ssl_clear_bad_session(SSL *s) {
}
/* locked by SSL_CTX in the calling function */
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) {
if (s->next == NULL || s->prev == NULL) {
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) {
if (session->next == NULL || session->prev == NULL) {
return;
}
if (s->next == (SSL_SESSION *)&ctx->session_cache_tail) {
if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
/* last element in list */
if (s->prev == (SSL_SESSION *)&ctx->session_cache_head) {
if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
/* only one element in list */
ctx->session_cache_head = NULL;
ctx->session_cache_tail = NULL;
} else {
ctx->session_cache_tail = s->prev;
s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
ctx->session_cache_tail = session->prev;
session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
}
} else {
if (s->prev == (SSL_SESSION *)&ctx->session_cache_head) {
if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
/* first element in list */
ctx->session_cache_head = s->next;
s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
ctx->session_cache_head = session->next;
session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
} else { /* middle of list */
s->next->prev = s->prev;
s->prev->next = s->next;
session->next->prev = session->prev;
session->prev->next = session->next;
}
}
s->prev = s->next = NULL;
session->prev = session->next = NULL;
}
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) {
if (s->next != NULL && s->prev != NULL) {
SSL_SESSION_list_remove(ctx, s);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) {
if (session->next != NULL && session->prev != NULL) {
SSL_SESSION_list_remove(ctx, session);
}
if (ctx->session_cache_head == NULL) {
ctx->session_cache_head = s;
ctx->session_cache_tail = s;
s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
s->next = (SSL_SESSION *)&(ctx->session_cache_tail);
ctx->session_cache_head = session;
ctx->session_cache_tail = session;
session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
} else {
s->next = ctx->session_cache_head;
s->next->prev = s;
s->prev = (SSL_SESSION *)&(ctx->session_cache_head);
ctx->session_cache_head = s;
session->next = ctx->session_cache_head;
session->next->prev = session;
session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
ctx->session_cache_head = session;
}
}
void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
int (*cb)(struct ssl_st *ssl, SSL_SESSION *sess)) {
int (*cb)(SSL *ssl, SSL_SESSION *session)) {
ctx->new_session_cb = cb;
}
int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) {
int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *session) {
return ctx->new_session_cb;
}
void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess)) {
void SSL_CTX_sess_set_remove_cb(
SSL_CTX *ctx, void (*cb)(SSL_CTX *ctx, SSL_SESSION *session)) {
ctx->remove_session_cb = cb;
}
void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx,
SSL_SESSION *sess) {
SSL_SESSION *session) {
return ctx->remove_session_cb;
}
void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
SSL_SESSION *(*cb)(struct ssl_st *ssl,
uint8_t *data, int len,
int *copy)) {
SSL_SESSION *(*cb)(SSL *ssl,
uint8_t *id, int id_len,
int *out_copy)) {
ctx->get_session_cb = cb;
}
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, uint8_t *data,
int len, int *copy) {
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
SSL *ssl, uint8_t *id, int id_len, int *out_copy) {
return ctx->get_session_cb;
}