From 209da5174d0af52cd2d3bec390c17f43f2c7db49 Mon Sep 17 00:00:00 2001 From: dmiller Date: Mon, 6 Apr 2026 21:33:44 +0000 Subject: [PATCH] Track and unload OpenSSL providers --- nse_openssl.cc | 42 ++++++++++++++++++++++++-- nsock/src/nsock_internal.h | 4 +++ nsock/src/nsock_ssl.c | 62 ++++++++++++++++++++++++-------------- 3 files changed, 82 insertions(+), 26 deletions(-) diff --git a/nse_openssl.cc b/nse_openssl.cc index 218b193d2..c89a4e87c 100644 --- a/nse_openssl.cc +++ b/nse_openssl.cc @@ -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 diff --git a/nsock/src/nsock_internal.h b/nsock/src/nsock_internal.h index 4ef523cd7..11b5082aa 100644 --- a/nsock/src/nsock_internal.h +++ b/nsock/src/nsock_internal.h @@ -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 diff --git a/nsock/src/nsock_ssl.c b/nsock/src/nsock_ssl.c index c1ff6082d..26e9a7f57 100644 --- a/nsock/src/nsock_ssl.c +++ b/nsock/src/nsock_ssl.c @@ -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