Never use the internal session cache for a client.

The internal session cache is keyed on session ID, so this is completely
useless for clients (indeed we never look it up internally). Along the way,
tidy up ssl_update_cache to be more readable. The slight behavior change is
that SSL_CTX_add_session's return code no longer controls the external
callback. It's not clear to me what that could have accomplished. (It can only
fail on allocation error. We only call it for new sessions, so the duplicate
case is impossible.)

The one thing of value the internal cache might have provided is managing the
timeout. The SSL_CTX_flush_sessions logic would flip the not_resumable bit and
cause us not to offer expired sessions (modulo SSL_CTX_flush_sessions's delay
and any discrepancies between the two caches). Instead, just check expiration
when deciding whether or not to offer a session.

This way clients that set SSL_SESS_CACHE_CLIENT blindly don't accidentally
consume gobs of memory.

BUG=531194

Change-Id: If97485beab21874f37737edc44df24e61ce23705
Reviewed-on: https://boringssl-review.googlesource.com/6321
Reviewed-by: Adam Langley <alangley@gmail.com>
This commit is contained in:
David Benjamin 2015-10-18 15:18:55 -04:00 committed by Adam Langley
parent 415660b26b
commit 1269ddd377
5 changed files with 36 additions and 34 deletions

View File

@ -1456,11 +1456,8 @@ OPENSSL_EXPORT int SSL_SESSION_set1_id_context(SSL_SESSION *session,
/* 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|. */
/* SSL_SESS_CACHE_CLIENT enables session caching for a client. The internal
* cache is never used on a client, so this only enables the callbacks. */
#define SSL_SESS_CACHE_CLIENT 0x0001
/* SSL_SESS_CACHE_SERVER enables session caching for a server. */
@ -1473,15 +1470,16 @@ OPENSSL_EXPORT int SSL_SESSION_set1_id_context(SSL_SESSION *session,
* |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. */
/* SSL_SESS_CACHE_NO_INTERNAL_LOOKUP, on a server, 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. */
/* SSL_SESS_CACHE_NO_INTERNAL_STORE, on a server, 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. */
/* SSL_SESS_CACHE_NO_INTERNAL, on a server, disables the internal session
* cache. */
#define SSL_SESS_CACHE_NO_INTERNAL \
(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | SSL_SESS_CACHE_NO_INTERNAL_STORE)

View File

@ -993,7 +993,7 @@ void ssl_cert_set_cert_cb(CERT *cert,
int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
int ssl_add_cert_chain(SSL *s, unsigned long *l);
void ssl_update_cache(SSL *s, int mode);
void ssl_update_cache(SSL *ssl, int mode);
/* ssl_get_compatible_server_ciphers determines the key exchange and
* authentication cipher suite masks compatible with the server configuration

View File

@ -665,10 +665,11 @@ int ssl3_send_client_hello(SSL *ssl) {
ssl->client_version = max_version;
}
/* If the configured session was created at a version higher than our
* maximum version, drop it. */
/* If the configured session has expired or was created at a version higher
* than our maximum version, drop it. */
if (ssl->session != NULL &&
(ssl->session->session_id_length == 0 || ssl->session->not_resumable ||
ssl->session->timeout < (long)(time(NULL) - ssl->session->time) ||
(!SSL_IS_DTLS(ssl) && ssl->session->ssl_version > ssl->version) ||
(SSL_IS_DTLS(ssl) && ssl->session->ssl_version < ssl->version))) {
SSL_set_session(ssl, NULL);

View File

@ -1805,35 +1805,34 @@ void ssl_get_compatible_server_ciphers(SSL *s, uint32_t *out_mask_k,
*out_mask_a = mask_a;
}
void ssl_update_cache(SSL *s, int mode) {
void ssl_update_cache(SSL *ssl, int mode) {
SSL_CTX *ctx = ssl->initial_ctx;
/* Never cache sessions with empty session IDs. */
if (s->session->session_id_length == 0) {
if (ssl->session->session_id_length == 0 ||
(ctx->session_cache_mode & mode) != mode) {
return;
}
int has_new_session = !s->hit;
if (!s->server && s->tlsext_ticket_expected) {
/* A client may see new sessions on abbreviated handshakes if the server
* decides to renew the ticket. Once the handshake is completed, it should
* be inserted into the cache. */
has_new_session = 1;
}
/* Clients never use the internal session cache. */
int use_internal_cache = ssl->server && !(ctx->session_cache_mode &
SSL_SESS_CACHE_NO_INTERNAL_STORE);
SSL_CTX *ctx = s->initial_ctx;
if ((ctx->session_cache_mode & mode) == mode && has_new_session &&
((ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) ||
SSL_CTX_add_session(ctx, s->session)) &&
ctx->new_session_cb != NULL) {
/* Note: |new_session_cb| is called whether the internal session cache is
* used or not. */
if (!ctx->new_session_cb(s, SSL_SESSION_up_ref(s->session))) {
SSL_SESSION_free(s->session);
/* A client may see new sessions on abbreviated handshakes if the server
* decides to renew the ticket. Once the handshake is completed, it should be
* inserted into the cache. */
if (!ssl->hit || (!ssl->server && ssl->tlsext_ticket_expected)) {
if (use_internal_cache) {
SSL_CTX_add_session(ctx, ssl->session);
}
if (ctx->new_session_cb != NULL &&
!ctx->new_session_cb(ssl, SSL_SESSION_up_ref(ssl->session))) {
/* |new_session_cb|'s return value signals whether it took ownership. */
SSL_SESSION_free(ssl->session);
}
}
if (!(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR) &&
!(ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) &&
(ctx->session_cache_mode & mode) == mode) {
if (use_internal_cache &&
!(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR)) {
/* Automatically flush the internal session cache every 255 connections. */
int flush_cache = 0;
CRYPTO_MUTEX_lock_write(&ctx->lock);

View File

@ -14,6 +14,7 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <string>
@ -713,6 +714,9 @@ static ScopedSSL_SESSION CreateSessionWithTicket(size_t ticket_len) {
}
memset(session->tlsext_tick, 'a', ticket_len);
session->tlsext_ticklen = ticket_len;
// Fix up the timeout.
session->time = time(NULL);
return session;
}