@@ -42,12 +42,13 @@ int ssl_running_on_valgrind = 0;
4242
4343#if HAVE_OPENSSL_INIT_SSL || (OPENSSL_VERSION_NUMBER >= 0x10100000L && \
4444 !defined(LIBRESSL_VERSION_NUMBER ))
45- /* Openssl v1.1+ handles all termination automatically from
46- * OPENSSL_init_ssl(). No manual initialization is required. */
45+ /* Openssl v1.1+ handles all initializations automatically from
46+ * OPENSSL_init_ssl(). */
47+ #define USE_OPENSSL_INIT_SSL 1
4748#else
4849/* For older OpenSSL releases, "manual" initialization and cleanup are
4950 * required. */
50- #define NEED_MANUAL_OPENSSL_INIT
51+ #define USE_OPENSSL_INIT_SSL 0
5152/* Will be set to true if mod_ssl is built statically into httpd. */
5253static int modssl_running_statically = 0 ;
5354#endif
@@ -328,7 +329,7 @@ static const command_rec ssl_config_cmds[] = {
328329 AP_END_CMD
329330};
330331
331- #ifdef NEED_MANUAL_OPENSSL_INIT
332+ #if ! USE_OPENSSL_INIT_SSL
332333static int modssl_is_prelinked (void )
333334{
334335 apr_size_t i = 0 ;
@@ -340,11 +341,26 @@ static int modssl_is_prelinked(void)
340341 }
341342 return 0 ;
342343}
344+ #endif /* !USE_OPENSSL_INIT_SSL */
343345
344- /* Termination below is for legacy Openssl versions v1.0.x and
345- * older. */
346+ /* Cleanup what's done in ssl_hook_pre_config() */
346347static apr_status_t ssl_cleanup_pre_config (void * data )
347348{
349+ #if USE_OPENSSL_INIT_SSL
350+ /* Nothing to do when an OpenSSL builtin atexit() handler is registered,
351+ * but with OPENSSL_INIT_NO_ATEXIT we want to call OPENSSL_cleanup() when
352+ * exiting only, not on restart/reload or the next OPENSSL_init_ssl() in
353+ * pre_config would not (re)initialize anything.
354+ */
355+ #ifdef OPENSSL_INIT_NO_ATEXIT
356+ if (ap_state_query (AP_SQ_MAIN_STATE ) == AP_SQ_MS_EXITING )
357+ OPENSSL_cleanup ();
358+ #endif
359+
360+ #else /* USE_OPENSSL_INIT_SSL */
361+ /* Termination below is for legacy Openssl versions v1.0.x and
362+ * older. */
363+
348364 /* Corresponds to OBJ_create()s */
349365 OBJ_cleanup ();
350366 /* Corresponds to OPENSSL_load_builtin_modules() */
@@ -367,7 +383,7 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
367383#else
368384 ERR_remove_state (0 );
369385#endif
370- #endif
386+ #endif /* USE_OPENSSL_INIT_SSL */
371387
372388 /* Don't call ERR_free_strings in earlier versions, ERR_load_*_strings only
373389 * actually loaded the error strings once per process due to static
@@ -391,9 +407,10 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
391407 * CRYPTO_mem_leaks_fp(stderr);
392408 */
393409
410+ #endif /* USE_OPENSSL_INIT_SSL */
411+
394412 return APR_SUCCESS ;
395413}
396- #endif /* NEED_MANUAL_OPENSSL_INIT */
397414
398415static int ssl_hook_pre_config (apr_pool_t * pconf ,
399416 apr_pool_t * plog ,
@@ -403,17 +420,26 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
403420 ssl_running_on_valgrind = RUNNING_ON_VALGRIND ;
404421#endif
405422
406- #ifndef NEED_MANUAL_OPENSSL_INIT
407- /* Openssl v1.1+ handles all initialisation automatically, apart
408- * from hints as to how we want to use the library.
423+ #if USE_OPENSSL_INIT_SSL
424+ /* Openssl v1.1+ handles all initialisation and termination automatically,
425+ * apart from hints as to how we want to use the library. We tell openssl
426+ * we want to include engine support.
409427 *
410- * We tell openssl we want to include engine support.
428+ * Openssl v3.0+ allows to disable builtin atexit() handler for termination
429+ * by using OPENSSL_INIT_NO_ATEXIT, which we use because atexit() handlers
430+ * are inherited by children processes and can cause issues/crashes when
431+ * run multiple times. This allows to call OPENSSL_cleanup() manually from
432+ * ssl_cleanup_pre_config() when (and only when) httpd is exiting.
411433 */
412- OPENSSL_init_ssl (OPENSSL_INIT_ENGINE_ALL_BUILTIN , NULL );
434+ OPENSSL_init_ssl (OPENSSL_INIT_ENGINE_ALL_BUILTIN
435+ #ifdef OPENSSL_INIT_NO_ATEXIT
436+ | OPENSSL_INIT_NO_ATEXIT
437+ #endif
438+ , NULL );
413439
414- #else
440+ #else /* USE_OPENSSL_INIT_SSL */
415441 /* Configuration below is for legacy versions Openssl v1.0 and
416- * older.
442+ * older, "manual" initialization and cleanup are required .
417443 */
418444 modssl_running_statically = modssl_is_prelinked ();
419445
@@ -433,7 +459,7 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
433459#endif
434460 OpenSSL_add_all_algorithms ();
435461 OPENSSL_load_builtin_modules ();
436- #endif /* NEED_MANUAL_OPENSSL_INIT */
462+ #endif /* USE_OPENSSL_INIT_SSL */
437463
438464 if (OBJ_txt2nid ("id-on-dnsSRV" ) == NID_undef ) {
439465 (void )OBJ_create ("1.3.6.1.5.5.7.8.7" , "id-on-dnsSRV" ,
@@ -444,13 +470,11 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
444470 ERR_clear_error ();
445471
446472
447- #ifdef NEED_MANUAL_OPENSSL_INIT
448473 /*
449474 * Let us cleanup the ssl library when the module is unloaded
450475 */
451476 apr_pool_cleanup_register (pconf , NULL , ssl_cleanup_pre_config ,
452- apr_pool_cleanup_null );
453- #endif
477+ apr_pool_cleanup_null );
454478
455479 /* Register to handle mod_status status page generation */
456480 ssl_scache_status_register (pconf );
0 commit comments