1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

Merge pull request #11460 from yosuke-wolfssl/fix/f_14055

session: initialize the external cache copy flag to 1
This commit is contained in:
philljj
2026-10-13 08:36:50 -05:00
committed by GitHub
7 changed files with 228 additions and 11 deletions

View File

@@ -2536,6 +2536,38 @@ int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
*/
long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode);
/*!
\ingroup Setup
\brief この関数は、アプリケーションが管理する外部セッションキャッシュからセッションを検索するためにwolfSSLが使用するコールバックを登録します。このコールバックはサーバー側で、ピアが再開のためにセッションIDを提示した際、内部キャッシュを参照する前に呼び出されます。互換レイヤのSSL_CTX_sess_set_get_cb()に相当します。
\return none 戻り値はありません。
\param ctx wolfSSL_CTX_new()で作成されたSSLコンテキストへのポインタ。
\param f 検索コールバック。既に登録されているコールバックを解除する場合はNULLを指定します。コールバックには、ネゴシエーション中のWOLFSSLオブジェクト、検索対象のセッションIDとその長さ、およびcopyフラグへのポインタが渡されます。コールバックは一致したWOLFSSL_SESSIONを返し、そのIDに対応するセッションがキャッシュに無い場合はNULLを返します。wolfSSLは呼び出し前にcopyフラグを1に設定します。1のままにした場合、コールバックは自身の参照を保持し続け、wolfSSLがその参照を解放することはありません。そのため、wolfSSLが検索を処理している間、セッションは有効である必要があります。セッションをより長く保持するTLS 1.3のステートフルチケットによる再開では、wolfSSLは独自に参照カウントをインクリメントし、使用を終えた時点でデクリメントします。この場合、参照カウントをインクリメントできないセッションは、該当セッション無しとして扱われます。0に設定した場合は、コールバックが保持していた参照をwolfSSLが引き継ぎ、セッションの使用を終えた時点で解放します。
_Example_
\code
WOLFSSL_SESSION* myGetSession(WOLFSSL* ssl, const unsigned char* id,
int idLen, int* copy)
{
(void)ssl;
// キャッシュがセッションを保持し続けるため、copyは変更しません。
return myCacheLookup(id, idLen);
}
...
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(method);
wolfSSL_CTX_sess_set_get_cb(ctx, myGetSession);
\endcode
\sa wolfSSL_CTX_set_session_cache_mode
\sa wolfSSL_get1_session
\sa wolfSSL_SESSION_free
\sa wolfSSL_flush_sessions
*/
void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,
WOLFSSL_SESSION*(*f)(WOLFSSL* ssl, const unsigned char*, int, int*));
/*!
\brief この関数は、セッションシークレットコールバック関数を設定します。SessionSecretCb型は次のシグネチャを持ちます:int (*SessionSecretCb)(WOLFSSL* ssl, void* secret, int* secretSz, void* ctx)。WOLFSSL構造体のsessionSecretCbメンバが、パラメータcbに設定されます。

View File

@@ -3511,6 +3511,53 @@ int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
*/
long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode);
/*!
\ingroup Setup
\brief This function registers the callback wolfSSL uses to look a session
up in an application managed (external) session cache. It is called on the
server side when a peer offers a session id to resume, before the internal
cache is consulted. Compatibility layer equivalent of
SSL_CTX_sess_set_get_cb().
\return none No return.
\param ctx pointer to the SSL context, created with wolfSSL_CTX_new().
\param f the lookup callback, or NULL to remove a previously registered
one. It is passed the WOLFSSL object being negotiated, the session id to
look up and its length, and a pointer to a copy flag. It returns the
matching WOLFSSL_SESSION, or NULL when the cache holds no session for that
id. wolfSSL sets the copy flag to 1 before the call. Left at 1, the
callback keeps its reference and wolfSSL never releases it, so the session
must stay valid while wolfSSL processes the lookup. For TLS 1.3 stateful
ticket resumption, which keeps the session longer, wolfSSL takes a
reference of its own and releases it when done; a session it cannot take a
reference on is then treated as no session found. Set to 0, the callback
hands its reference to wolfSSL, which releases it once done with the
session.
_Example_
\code
WOLFSSL_SESSION* myGetSession(WOLFSSL* ssl, const unsigned char* id,
int idLen, int* copy)
{
(void)ssl;
// The cache keeps its session, so leave copy alone.
return myCacheLookup(id, idLen);
}
...
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(method);
wolfSSL_CTX_sess_set_get_cb(ctx, myGetSession);
\endcode
\sa wolfSSL_CTX_set_session_cache_mode
\sa wolfSSL_get1_session
\sa wolfSSL_SESSION_free
\sa wolfSSL_flush_sessions
*/
void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx,
WOLFSSL_SESSION*(*f)(WOLFSSL* ssl, const unsigned char*, int, int*));
/*!
\brief This function sets the session secret callback function. The
SessionSecretCb type has the signature: int (*SessionSecretCb)(WOLFSSL* ssl,

View File

@@ -467,7 +467,7 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID
int ret;
#endif
#ifdef HAVE_EXT_CACHE
int copy;
int copy = 1;
#endif
*resume = FALSE;

View File

@@ -44650,14 +44650,18 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
XMEMSET(freeCtx, 0, sizeof(*freeCtx));
#ifdef HAVE_EXT_CACHE
if (ssl->ctx->get_sess_cb != NULL) {
int copy = 0;
int copy = 1;
sess = ssl->ctx->get_sess_cb((WOLFSSL*)ssl,
id, ID_LEN, &copy);
if (sess != NULL) {
freeCtx->extCache = 1;
/* If copy not set then free immediately */
if (!copy)
if (copy && wolfSSL_SESSION_up_ref((WOLFSSL_SESSION*)sess)
!= WOLFSSL_SUCCESS) {
sess = NULL;
}
else {
freeCtx->extCache = 1;
freeCtx->freeSess = 1;
}
}
}
#endif
@@ -44681,8 +44685,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
#ifdef HAVE_EXT_CACHE
if (freeCtx->extCache) {
if (freeCtx->freeSess)
/* In this case sess is not longer const and the external cache
* wants us to free it. */
/* Release the reference this lookup took. */
wolfSSL_FreeSession(ssl->ctx, (WOLFSSL_SESSION*)sess);
return;
}

View File

@@ -1314,7 +1314,7 @@ static int GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output,
#ifdef HAVE_EXT_CACHE
if (!internalOnly && ssl->ctx->get_sess_cb != NULL) {
int copy = 0;
int copy = 1;
int found = 0;
WOLFSSL_SESSION* extSess;
/* Attempt to retrieve the session from the external cache. */
@@ -1338,7 +1338,6 @@ static int GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output,
ssl->session->sessionIDSz = bogusIDSz;
}
}
/* If copy not set then free immediately */
if (extSess != NULL && !copy)
wolfSSL_FreeSession(ssl->ctx, extSess);
if (found)

View File

@@ -383,8 +383,7 @@ static WOLFSSL_SESSION *twcase_get_sessionCb(WOLFSSL *ssl,
*/
fprintf(stderr, "\t\ttwcase_get_session_called %d\n",
++twcase_get_session_called);
/* This callback want to retain a copy of the object. If we want wolfSSL to
* be responsible for the pointer then set to 0. */
/* This cache keeps its own reference to the session. */
*ref = 1;
for (i = 0; i < SESSION_CACHE_SIZE; i++) {
@@ -1035,6 +1034,141 @@ int test_wolfSSL_CTX_add_session_ext_dtls1(void)
return EXPECT_RESULT();
}
#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
!defined(NO_SESSION_CACHE) && defined(OPENSSL_EXTRA) && \
!defined(WOLFSSL_NO_TLS12)
/* tdcase - prefix for test_wolfSSL_CTX_sess_get_cb_default_copy */
static WOLFSSL_SESSION* tdcase_server_session_ptr = NULL;
static WOLFSSL_SESSION* tdcase_client_session_ptr = NULL;
static int tdcase_get_session_called = 0;
static int tdcase_clear_copy = 0;
static WOLFSSL_SESSION* tdcase_get_sessionCb(WOLFSSL* ssl,
const unsigned char* id, int len, int* copy)
{
(void)ssl;
(void)id;
(void)len;
/* Left alone, this cache keeps its session. Cleared, it hands the
* reference to wolfSSL. */
if (tdcase_clear_copy)
*copy = 0;
tdcase_get_session_called++;
return tdcase_server_session_ptr;
}
static int tdcase_server_ctx_ready(WOLFSSL_CTX* ctx)
{
EXPECT_DECLS;
/* Only the external cache, so nothing else can reach the session. */
ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx,
WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE), WOLFSSL_SUCCESS);
wolfSSL_CTX_sess_set_get_cb(ctx, tdcase_get_sessionCb);
wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TICKET);
return EXPECT_RESULT();
}
static int tdcase_on_result(WOLFSSL* ssl)
{
EXPECT_DECLS;
WOLFSSL_SESSION** sess;
sess = wolfSSL_is_server(ssl) ? &tdcase_server_session_ptr
: &tdcase_client_session_ptr;
if (*sess == NULL)
ExpectNotNull(*sess = wolfSSL_get1_session(ssl));
return EXPECT_RESULT();
}
static int tdcase_client_ssl_ready(WOLFSSL* ssl)
{
EXPECT_DECLS;
ExpectNotNull(tdcase_client_session_ptr);
ExpectIntEQ(wolfSSL_set_session(ssl, tdcase_client_session_ptr),
WOLFSSL_SUCCESS);
return EXPECT_RESULT();
}
#endif
int test_wolfSSL_CTX_sess_get_cb_default_copy(void)
{
EXPECT_DECLS;
#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_EXT_CACHE) && \
!defined(NO_SESSION_CACHE) && defined(OPENSSL_EXTRA) && \
!defined(WOLFSSL_NO_TLS12)
test_ssl_cbf client_cb;
test_ssl_cbf server_cb;
int refBefore = 0;
tdcase_server_session_ptr = NULL;
tdcase_client_session_ptr = NULL;
tdcase_get_session_called = 0;
tdcase_clear_copy = 0;
XMEMSET(&client_cb, 0, sizeof(client_cb));
XMEMSET(&server_cb, 0, sizeof(server_cb));
client_cb.method = wolfTLSv1_2_client_method;
server_cb.method = wolfTLSv1_2_server_method;
server_cb.ctx_ready = tdcase_server_ctx_ready;
server_cb.on_result = tdcase_on_result;
client_cb.on_result = tdcase_on_result;
/* connection 1 - full handshake */
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb,
&server_cb, NULL), TEST_SUCCESS);
ExpectNotNull(tdcase_server_session_ptr);
ExpectNotNull(tdcase_client_session_ptr);
ExpectIntEQ(tdcase_get_session_called, 0);
/* Hold a second reference so a dropped one is still observable. */
ExpectIntEQ(wolfSSL_SESSION_up_ref(tdcase_server_session_ptr),
WOLFSSL_SUCCESS);
if (tdcase_server_session_ptr != NULL)
refBefore = (int)wolfSSL_RefCur(tdcase_server_session_ptr->ref);
/* connection 2 - resume through the callback, which never writes copy */
server_cb.on_result = NULL;
client_cb.on_result = NULL;
client_cb.ssl_ready = tdcase_client_ssl_ready;
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb,
&server_cb, NULL), TEST_SUCCESS);
ExpectIntEQ(tdcase_get_session_called, 1);
if (tdcase_server_session_ptr != NULL) {
ExpectIntEQ((int)wolfSSL_RefCur(tdcase_server_session_ptr->ref),
refBefore);
}
/* connection 3 - same resume, but the callback clears copy */
tdcase_clear_copy = 1;
tdcase_get_session_called = 0;
ExpectIntEQ(test_wolfSSL_client_server_nofail_memio(&client_cb,
&server_cb, NULL), TEST_SUCCESS);
ExpectIntEQ(tdcase_get_session_called, 1);
if (tdcase_server_session_ptr != NULL) {
ExpectIntEQ((int)wolfSSL_RefCur(tdcase_server_session_ptr->ref),
refBefore - 1);
}
/* The cleared copy consumed one of the two references held here. */
wolfSSL_SESSION_free(tdcase_server_session_ptr);
wolfSSL_SESSION_free(tdcase_client_session_ptr);
tdcase_server_session_ptr = NULL;
tdcase_client_session_ptr = NULL;
#endif
return EXPECT_RESULT();
}
/*----------------------------------------------------------------------------*/
/* WOLFSSL_SESSION, ticket keys and session removal callbacks */
/*----------------------------------------------------------------------------*/

View File

@@ -31,6 +31,7 @@ int test_wolfSSL_CTX_add_session_ext_tls12(void);
int test_wolfSSL_CTX_add_session_ext_dtls12(void);
int test_wolfSSL_CTX_add_session_ext_tls11(void);
int test_wolfSSL_CTX_add_session_ext_dtls1(void);
int test_wolfSSL_CTX_sess_get_cb_default_copy(void);
int test_wolfSSL_SESSION(void);
int test_wolfSSL_SESSION_expire_downgrade(void);
int test_wolfSSL_CTX_sess_set_remove_cb(void);
@@ -53,6 +54,7 @@ int test_wolfSSL_SetServerID_resume(void);
TEST_DECL_GROUP("session", test_wolfSSL_CTX_add_session_ext_dtls12), \
TEST_DECL_GROUP("session", test_wolfSSL_CTX_add_session_ext_tls11), \
TEST_DECL_GROUP("session", test_wolfSSL_CTX_add_session_ext_dtls1), \
TEST_DECL_GROUP("session", test_wolfSSL_CTX_sess_get_cb_default_copy), \
TEST_DECL_GROUP("session", test_wolfSSL_SESSION), \
TEST_DECL_GROUP("session", test_wolfSSL_SESSION_expire_downgrade), \
TEST_DECL_GROUP("session", test_wolfSSL_CTX_sess_set_remove_cb), \