Track and unload OpenSSL providers

This commit is contained in:
dmiller 2026-04-06 21:33:44 +00:00
parent c693c60a54
commit 209da5174d
3 changed files with 82 additions and 26 deletions

View file

@ -579,26 +579,62 @@ static const struct luaL_Reg openssllib[] = {
{ NULL, NULL }
};
LUALIB_API int luaopen_openssl(lua_State *L) {
struct nse_openssl_state {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
OSSL_PROVIDER *legacy_provider;
OSSL_PROVIDER *default_provider;
#endif
};
static int nse_openssl_gc(lua_State *L) {
nse_openssl_state *state = (nse_openssl_state *) luaL_checkudata(L, 1, "NSE_OPENSSL_STATE");
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (state->legacy_provider) {
OSSL_PROVIDER_unload(state->legacy_provider);
state->legacy_provider = NULL;
}
if (state->default_provider) {
OSSL_PROVIDER_unload(state->default_provider);
state->default_provider = NULL;
}
#endif
return 0;
}
static void create_openssl_state(lua_State *L) {
nse_openssl_state *state = (nse_openssl_state *) lua_newuserdatauv(L, sizeof(nse_openssl_state), 0);
if (luaL_newmetatable(L, "NSE_OPENSSL_STATE")) {
lua_pushcfunction(L, nse_openssl_gc);
lua_setfield(L, -2, "__gc");
}
lua_setmetatable(L, -2);
lua_setfield(L, -2, "nse_openssl_state");
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
if (NULL == OSSL_PROVIDER_load(NULL, "legacy") && o.debugging > 1)
state->legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
if (NULL == state->legacy_provider && o.debugging > 1)
{
// Legacy provider may not be available.
// On Windows, legacy crypto is still available even though this fails.
log_write(LOG_STDOUT, "%s: OpenSSL legacy provider failed to load: %s\n", SCRIPT_ENGINE, ERR_error_string(ERR_get_error(), NULL));
}
if (NULL == OSSL_PROVIDER_load(NULL, "default") && o.verbose)
state->default_provider = OSSL_PROVIDER_load(NULL, "default");
if (NULL == state->default_provider && o.verbose)
{
log_write(LOG_STDOUT, "%s: OpenSSL default provider failed to load: %s\n", SCRIPT_ENGINE, ERR_error_string(ERR_get_error(), NULL));
}
#endif
}
LUALIB_API int luaopen_openssl(lua_State *L) {
luaL_newlib(L, openssllib);
create_openssl_state(L);
// create metatable for bignum
luaL_newmetatable( L, "BIGNUM" );
// metatable.__index = metatable

View file

@ -204,6 +204,10 @@ struct npool {
#ifndef OPENSSL_NO_DTLS
SSL_CTX *dtlsctx;
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
OSSL_PROVIDER *legacy_provider;
OSSL_PROVIDER *default_provider;
#endif
#endif
/* Optional proxy chain (NULL is not set). Can only be set once per NSP (using

View file

@ -100,6 +100,16 @@ void nsp_ssl_cleanup(struct npool *nsp)
#ifndef OPENSSL_NO_DTLS
if (nsp->dtlsctx != NULL)
SSL_CTX_free(nsp->dtlsctx);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (nsp->legacy_provider) {
OSSL_PROVIDER_unload(nsp->legacy_provider);
nsp->legacy_provider = NULL;
}
if (nsp->default_provider) {
OSSL_PROVIDER_unload(nsp->default_provider);
nsp->default_provider = NULL;
}
#endif
}
nsp->sslctx = NULL;
@ -119,18 +129,6 @@ static SSL_CTX *ssl_init_helper(const SSL_METHOD *method) {
SSL_library_init();
#else
OPENSSL_atexit(nsock_ssl_atexit);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (NULL == OSSL_PROVIDER_load(NULL, "legacy"))
{
nsock_log_info("OpenSSL legacy provider failed to load: %s",
ERR_error_string(ERR_get_error(), NULL));
}
if (NULL == OSSL_PROVIDER_load(NULL, "default"))
{
nsock_log_error("OpenSSL default provider failed to load: %s",
ERR_error_string(ERR_get_error(), NULL));
}
#endif
#endif
}
@ -151,8 +149,27 @@ static SSL_CTX *ssl_init_helper(const SSL_METHOD *method) {
}
/* Create an SSL_CTX and do initialization that is common to all init modes. */
static SSL_CTX *ssl_init_common() {
return ssl_init_helper(SSLv23_client_method());
static void ssl_init_common(struct npool *ms) {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (NULL == ms->legacy_provider)
{
ms->legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
if (NULL == ms->legacy_provider)
{
nsock_log_info("OpenSSL legacy provider failed to load: %s",
ERR_error_string(ERR_get_error(), NULL));
}
}
if (NULL == ms->default_provider)
{
ms->default_provider = OSSL_PROVIDER_load(NULL, "default");
if (NULL == ms->default_provider)
{
nsock_log_error("OpenSSL default provider failed to load: %s",
ERR_error_string(ERR_get_error(), NULL));
}
}
#endif
}
/* Initializes an Nsock pool to create SSL connections. This sets an internal
@ -195,26 +212,25 @@ static nsock_ssl_ctx nsock_pool_ssl_init_helper(SSL_CTX *ctx, int flags) {
nsock_ssl_ctx nsock_pool_ssl_init(nsock_pool ms_pool, int flags) {
struct npool *ms = (struct npool *)ms_pool;
if (ms->sslctx == NULL)
ms->sslctx = ssl_init_common();
if (ms->sslctx == NULL) {
ssl_init_common(ms);
ms->sslctx = ssl_init_helper(SSLv23_client_method());
}
return nsock_pool_ssl_init_helper(ms->sslctx, flags);
}
#ifndef OPENSSL_NO_DTLS
/* Create an SSL_CTX and do initialisation, creating a DTLS client */
static SSL_CTX *dtls_init_common() {
return ssl_init_helper(DTLS_client_method());
}
/* Initializes an Nsock pool to create DTLS connections. Very much similar to
* nsock_pool_ssl_init, just with DTLS. */
nsock_ssl_ctx nsock_pool_dtls_init(nsock_pool ms_pool, int flags) {
SSL_CTX *dtls_ctx = NULL;
struct npool *ms = (struct npool *)ms_pool;
if (ms->dtlsctx == NULL)
ms->dtlsctx = dtls_init_common();
if (ms->dtlsctx == NULL) {
ssl_init_common(ms);
ms->dtlsctx = ssl_init_helper(DTLS_client_method());
}
dtls_ctx = (SSL_CTX *) nsock_pool_ssl_init_helper(ms->dtlsctx, flags);
#ifdef SSL_OP_TLSEXT_PADDING