Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removed unused sessions from SSL_CTX internal cache #101684

Merged
merged 4 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ private static unsafe void RemoveSessionCallback(IntPtr ctx, IntPtr session)

IntPtr name = Ssl.SessionGetHostname(session);
Debug.Assert(name != IntPtr.Zero);
ctxHandle.RemoveSession(name);
ctxHandle.RemoveSession(name, session);
}

[UnmanagedCallersOnly]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ internal static partial class Ssl
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetCaching")]
internal static unsafe partial int SslCtxSetCaching(SafeSslContextHandle ctx, int mode, int cacheSize, int contextIdLength, Span<byte> contextId, delegate* unmanaged<IntPtr, IntPtr, int> neewSessionCallback, delegate* unmanaged<IntPtr, IntPtr, void> removeSessionCallback);

[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxRemoveSession")]
internal static unsafe partial void SslCtxRemoveSession(SafeSslContextHandle ctx, IntPtr session);

internal static bool AddExtraChainCertificates(SafeSslContextHandle ctx, ReadOnlyCollection<X509Certificate2> chain)
{
// send pre-computed list of intermediates.
Expand Down Expand Up @@ -142,27 +145,38 @@ internal bool TryAddSession(IntPtr namePtr, IntPtr session)
// This will use strdup() so it is safe to pass in raw pointer.
Interop.Ssl.SessionSetHostname(session, namePtr);

IntPtr oldSession = IntPtr.Zero;

lock (_sslSessions)
{
if (!_sslSessions.TryAdd(targetName, session))
{
if (_sslSessions.Remove(targetName, out IntPtr oldSession))
{
Interop.Ssl.SessionFree(oldSession);
}

// session to this target host exists, replace it
_sslSessions.Remove(targetName, out oldSession);
bool added = _sslSessions.TryAdd(targetName, session);
Debug.Assert(added);
}
}

if (oldSession != IntPtr.Zero)
{
// remove old session also from the internal OpenSSL cache
// and drop reference count. Since SSL_CTX_remove_session
// will call session_remove_cb, we need to do this outside
// of _sslSessions lock to avoid deadlock with another thread
// which could be holding SSL_CTX lock and trying to acquire
// _sslSessions lock.
Interop.Ssl.SslCtxRemoveSession(this, oldSession);
Interop.Ssl.SessionFree(oldSession);
}

return true;
}

return false;
}

internal void RemoveSession(IntPtr namePtr)
internal void RemoveSession(IntPtr namePtr, IntPtr session)
{
Debug.Assert(_sslSessions != null);

Expand All @@ -171,11 +185,14 @@ internal void RemoveSession(IntPtr namePtr)

if (_sslSessions != null && targetName != null)
{
IntPtr oldSession;
bool removed;
IntPtr oldSession = IntPtr.Zero;
bool removed = false;
lock (_sslSessions)
{
removed = _sslSessions.Remove(targetName, out oldSession);
if (_sslSessions.TryGetValue(targetName, out IntPtr existingSession) && existingSession == session)
{
removed = _sslSessions.Remove(targetName, out oldSession);
}
}

if (removed)
Expand Down Expand Up @@ -209,7 +226,6 @@ internal bool TrySetSession(SafeSslHandle sslHandle, string name)
// This will increase reference count on the session as needed.
// We need to hold lock here to prevent session being deleted before the call is done.
Interop.Ssl.SslSetSession(sslHandle, session);

return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ static const Entry s_cryptoNative[] =
DllImportEntry(CryptoNative_IsSslStateOK)
DllImportEntry(CryptoNative_SslCtxAddExtraChainCert)
DllImportEntry(CryptoNative_SslCtxSetCaching)
DllImportEntry(CryptoNative_SslCtxRemoveSession)
DllImportEntry(CryptoNative_SslCtxSetCiphers)
DllImportEntry(CryptoNative_SslCtxSetDefaultOcspCallback)
DllImportEntry(CryptoNative_SslCtxSetEncryptionPolicy)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen);
REQUIRED_FUNCTION(SSL_CTX_new) \
REQUIRED_FUNCTION(SSL_CTX_sess_set_new_cb) \
REQUIRED_FUNCTION(SSL_CTX_sess_set_remove_cb) \
REQUIRED_FUNCTION(SSL_CTX_remove_session) \
LIGHTUP_FUNCTION(SSL_CTX_set_alpn_protos) \
LIGHTUP_FUNCTION(SSL_CTX_set_alpn_select_cb) \
REQUIRED_FUNCTION(SSL_CTX_set_cipher_list) \
Expand Down Expand Up @@ -1083,6 +1084,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define SSL_CTX_new SSL_CTX_new_ptr
#define SSL_CTX_sess_set_new_cb SSL_CTX_sess_set_new_cb_ptr
#define SSL_CTX_sess_set_remove_cb SSL_CTX_sess_set_remove_cb_ptr
#define SSL_CTX_remove_session SSL_CTX_remove_session_ptr
#define SSL_CTX_set_alpn_protos SSL_CTX_set_alpn_protos_ptr
#define SSL_CTX_set_alpn_select_cb SSL_CTX_set_alpn_select_cb_ptr
#define SSL_CTX_set_cipher_list SSL_CTX_set_cipher_list_ptr
Expand Down
5 changes: 5 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/pal_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,11 @@ int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, int con
return retValue;
}

int CryptoNative_SslCtxRemoveSession(SSL_CTX* ctx, SSL_SESSION* session)
{
return SSL_CTX_remove_session(ctx, session);
}

const char* CryptoNative_SslGetServerName(SSL* ssl)
{
return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Expand Down
5 changes: 5 additions & 0 deletions src/native/libs/System.Security.Cryptography.Native/pal_ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ Sets session caching. 0 is disabled.
*/
PALEXPORT int CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode, int cacheSize, int contextIdLength, uint8_t* contextId, SslCtxNewSessionCallback newSessionCb, SslCtxRemoveSessionCallback removeSessionCb);

/*
Removes a session from internal cache.
*/
PALEXPORT int CryptoNative_SslCtxRemoveSession(SSL_CTX* ctx, SSL_SESSION* session);

/*
Sets callback to log TLS session keys
*/
Expand Down
Loading