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:
@@ -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に設定されます。
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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, ©);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
@@ -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), \
|
||||
|
||||
Reference in New Issue
Block a user