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>
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 59a3a50..65cfc33 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c
@@ -1805,35 +1805,34 @@ *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);