@@ -42,12 +42,15 @@ 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
52+
53+ #if !USE_OPENSSL_INIT_SSL
5154/* Will be set to true if mod_ssl is built statically into httpd. */
5255static int modssl_running_statically = 0 ;
5356#endif
@@ -328,7 +331,7 @@ static const command_rec ssl_config_cmds[] = {
328331 AP_END_CMD
329332};
330333
331- #ifdef NEED_MANUAL_OPENSSL_INIT
334+ #if ! USE_OPENSSL_INIT_SSL
332335static int modssl_is_prelinked (void )
333336{
334337 apr_size_t i = 0 ;
@@ -340,11 +343,26 @@ static int modssl_is_prelinked(void)
340343 }
341344 return 0 ;
342345}
346+ #endif /* !USE_OPENSSL_INIT_SSL */
343347
344- /* Termination below is for legacy Openssl versions v1.0.x and
345- * older. */
348+ /* Cleanup what's done in ssl_hook_pre_config() */
346349static apr_status_t ssl_cleanup_pre_config (void * data )
347350{
351+ #if USE_OPENSSL_INIT_SSL
352+ /* Nothing to do when an OpenSSL builtin atexit() handler is registered,
353+ * but with OPENSSL_INIT_NO_ATEXIT we want to call OPENSSL_cleanup() when
354+ * exiting only, not on restart/reload or the next OPENSSL_init_ssl() in
355+ * pre_config would not (re)initialize anything.
356+ */
357+ #ifdef OPENSSL_INIT_NO_ATEXIT
358+ if (ap_state_query (AP_SQ_MAIN_STATE ) == AP_SQ_MS_EXITING )
359+ OPENSSL_cleanup ();
360+ #endif
361+
362+ #else /* USE_OPENSSL_INIT_SSL */
363+ /* Termination below is for legacy Openssl versions v1.0.x and
364+ * older. */
365+
348366 /* Corresponds to OBJ_create()s */
349367 OBJ_cleanup ();
350368 /* Corresponds to OPENSSL_load_builtin_modules() */
@@ -367,7 +385,7 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
367385#else
368386 ERR_remove_state (0 );
369387#endif
370- #endif
388+ #endif /* USE_OPENSSL_INIT_SSL */
371389
372390 /* Don't call ERR_free_strings in earlier versions, ERR_load_*_strings only
373391 * actually loaded the error strings once per process due to static
@@ -391,9 +409,10 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
391409 * CRYPTO_mem_leaks_fp(stderr);
392410 */
393411
412+ #endif /* USE_OPENSSL_INIT_SSL */
413+
394414 return APR_SUCCESS ;
395415}
396- #endif /* NEED_MANUAL_OPENSSL_INIT */
397416
398417static int ssl_hook_pre_config (apr_pool_t * pconf ,
399418 apr_pool_t * plog ,
@@ -403,17 +422,26 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
403422 ssl_running_on_valgrind = RUNNING_ON_VALGRIND ;
404423#endif
405424
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.
425+ #if USE_OPENSSL_INIT_SSL
426+ /* Openssl v1.1+ handles all initialisation and termination automatically,
427+ * apart from hints as to how we want to use the library. We tell openssl
428+ * we want to include engine support.
409429 *
410- * We tell openssl we want to include engine support.
430+ * Openssl v3.0+ allows to disable builtin atexit() handler for termination
431+ * by using OPENSSL_INIT_NO_ATEXIT, which we use because atexit() handlers
432+ * are inherited by children processes and can cause issues/crashes when
433+ * run multiple times. This allows to call OPENSSL_cleanup() manually from
434+ * ssl_cleanup_pre_config() when (and only when) httpd is exiting.
411435 */
412- OPENSSL_init_ssl (OPENSSL_INIT_ENGINE_ALL_BUILTIN , NULL );
436+ OPENSSL_init_ssl (OPENSSL_INIT_ENGINE_ALL_BUILTIN
437+ #ifdef OPENSSL_INIT_NO_ATEXIT
438+ | OPENSSL_INIT_NO_ATEXIT
439+ #endif
440+ , NULL );
413441
414- #else
442+ #else /* USE_OPENSSL_INIT_SSL */
415443 /* Configuration below is for legacy versions Openssl v1.0 and
416- * older.
444+ * older, "manual" initialization and cleanup are required .
417445 */
418446 modssl_running_statically = modssl_is_prelinked ();
419447
@@ -433,7 +461,7 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
433461#endif
434462 OpenSSL_add_all_algorithms ();
435463 OPENSSL_load_builtin_modules ();
436- #endif /* NEED_MANUAL_OPENSSL_INIT */
464+ #endif /* USE_OPENSSL_INIT_SSL */
437465
438466 if (OBJ_txt2nid ("id-on-dnsSRV" ) == NID_undef ) {
439467 (void )OBJ_create ("1.3.6.1.5.5.7.8.7" , "id-on-dnsSRV" ,
@@ -444,13 +472,11 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
444472 ERR_clear_error ();
445473
446474
447- #ifdef NEED_MANUAL_OPENSSL_INIT
448475 /*
449476 * Let us cleanup the ssl library when the module is unloaded
450477 */
451478 apr_pool_cleanup_register (pconf , NULL , ssl_cleanup_pre_config ,
452- apr_pool_cleanup_null );
453- #endif
479+ apr_pool_cleanup_null );
454480
455481 /* Register to handle mod_status status page generation */
456482 ssl_scache_status_register (pconf );
0 commit comments