Skip to content

Commit

Permalink
Add a test for session cache overflow
Browse files Browse the repository at this point in the history
Test sessions behave as we expect even in the case that an overflow
occurs when adding a new session into the session cache.

Related to CVE-2024-2511

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from openssl/openssl#24044)

(cherry picked from commit ddead0935d77ba9b771d632ace61b145d7153f18)
Signed-off-by: hhhFun <fanghaojie@huawei.com>
  • Loading branch information
mattcaswell authored and hhhFun committed Apr 12, 2024
1 parent 746a5c6 commit 2b0c38d
Showing 1 changed file with 123 additions and 1 deletion.
124 changes: 123 additions & 1 deletion test/sslapitest.c
Original file line number Diff line number Diff line change
Expand Up @@ -2386,7 +2386,6 @@ static int test_session_wo_ca_names(void)
#endif
}


#ifndef OSSL_NO_USABLE_TLS1_3
static SSL_SESSION *sesscache[6];
static int do_cache;
Expand Down Expand Up @@ -8938,6 +8937,126 @@ static int test_session_timeout(int test)
return testresult;
}

/*
* Test that a session cache overflow works as expected
* Test 0: TLSv1.3, timeout on new session later than old session
* Test 1: TLSv1.2, timeout on new session later than old session
* Test 2: TLSv1.3, timeout on new session earlier than old session
* Test 3: TLSv1.2, timeout on new session earlier than old session
*/
#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
static int test_session_cache_overflow(int idx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
SSL *serverssl = NULL, *clientssl = NULL;
int testresult = 0;
SSL_SESSION *sess = NULL;

#ifdef OSSL_NO_USABLE_TLS1_3
/* If no TLSv1.3 available then do nothing in this case */
if (idx % 2 == 0)
return TEST_skip("No TLSv1.3 available");
#endif
#ifdef OPENSSL_NO_TLS1_2
/* If no TLSv1.2 available then do nothing in this case */
if (idx % 2 == 1)
return TEST_skip("No TLSv1.2 available");
#endif

if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
TLS_client_method(), TLS1_VERSION,
(idx % 2 == 0) ? TLS1_3_VERSION
: TLS1_2_VERSION,
&sctx, &cctx, cert, privkey))
|| !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET)))
goto end;

SSL_CTX_sess_set_get_cb(sctx, get_session_cb);
get_sess_val = NULL;

SSL_CTX_sess_set_cache_size(sctx, 1);

if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;

if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;

if (idx > 1) {
sess = SSL_get_session(serverssl);
if (!TEST_ptr(sess))
goto end;

/*
* Cause this session to have a longer timeout than the next session to
* be added.
*/
if (!TEST_true(SSL_SESSION_set_timeout(sess, LONG_MAX / 2))) {
sess = NULL;
goto end;
}
sess = NULL;
}

SSL_shutdown(serverssl);
SSL_shutdown(clientssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;

/*
* Session cache size is 1 and we already populated the cache with a session
* so the next connection should cause an overflow.
*/

if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;

if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;

/*
* The session we just negotiated may have been already removed from the
* internal cache - but we will return it anyway from our external cache.
*/
get_sess_val = SSL_get_session(serverssl);
if (!TEST_ptr(get_sess_val))
goto end;
sess = SSL_get1_session(clientssl);
if (!TEST_ptr(sess))
goto end;

SSL_shutdown(serverssl);
SSL_shutdown(clientssl);
SSL_free(serverssl);
SSL_free(clientssl);
serverssl = clientssl = NULL;

if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
NULL, NULL)))
goto end;

if (!TEST_true(SSL_set_session(clientssl, sess)))
goto end;

if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
goto end;

testresult = 1;

end:
SSL_free(serverssl);
SSL_free(clientssl);
SSL_CTX_free(sctx);
SSL_CTX_free(cctx);
SSL_SESSION_free(sess);

return testresult;
}
#endif /* !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) */

/*
* Test 0: Client sets servername and server acknowledges it (TLSv1.2)
* Test 1: Client sets servername and server does not acknowledge it (TLSv1.2)
Expand Down Expand Up @@ -10739,6 +10858,9 @@ int setup_tests(void)
ADD_TEST(test_set_verify_cert_store_ssl_ctx);
ADD_TEST(test_set_verify_cert_store_ssl);
ADD_ALL_TESTS(test_session_timeout, 1);
#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
ADD_ALL_TESTS(test_session_cache_overflow, 4);
#endif
ADD_TEST(test_load_dhfile);
#if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3)
ADD_ALL_TESTS(test_serverinfo_custom, 4);
Expand Down

0 comments on commit 2b0c38d

Please sign in to comment.