diff options
author | Graham Leggett <minfrin@apache.org> | 2019-06-23 22:15:31 +0000 |
---|---|---|
committer | Graham Leggett <minfrin@apache.org> | 2019-06-23 22:15:31 +0000 |
commit | 39f444510548b97f6e46e16df675bdce5f943920 (patch) | |
tree | a1b7204505c4d4271d180730b5fe57eb6a478e7e /crypto | |
parent | 6c6926d56bf0a4c4939bf3e5200539200b198cff (diff) | |
download | apr-39f444510548b97f6e46e16df675bdce5f943920.tar.gz |
Revert r1833421 et al:
Move OpenSSL initialisation back to apr_crypto_openssl, reinstate
DSO support.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1861951 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/apr_crypto.c | 25 | ||||
-rw-r--r-- | crypto/apr_crypto_internal.c | 357 | ||||
-rw-r--r-- | crypto/apr_crypto_openssl.c | 46 |
3 files changed, 45 insertions, 383 deletions
diff --git a/crypto/apr_crypto.c b/crypto/apr_crypto.c index ea6575b4f..478e3a4a7 100644 --- a/crypto/apr_crypto.c +++ b/crypto/apr_crypto.c @@ -379,14 +379,7 @@ APR_DECLARE(apr_status_t) apr_crypto_lib_version(const char *name, const char **version) { apr_status_t rv = APR_ENOTIMPL; -#if APU_HAVE_OPENSSL - if (!strcmp(name, "openssl")) { - *version = apr__crypto_openssl_version(); - rv = *version ? APR_SUCCESS : APR_NOTFOUND; - } - else -#endif - ; + return rv; } @@ -434,16 +427,6 @@ APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name, } rv = APR_ENOTIMPL; -#if APU_HAVE_OPENSSL - if (!strcmp(name, "openssl")) { - rv = apr__crypto_openssl_init(params, result, pool); - if (rv == APR_SUCCESS) { - lib->term = apr__crypto_openssl_term; - lib->name = "openssl"; - } - } - else -#endif ; if (rv == APR_SUCCESS) { lib->pool = pool; @@ -473,12 +456,6 @@ static apr_status_t crypto_lib_term(const char *name) } rv = APR_ENOTIMPL; -#if APU_HAVE_OPENSSL - if (!strcmp(name, "openssl")) { - rv = APR_SUCCESS; - } - else -#endif ; if (rv == APR_SUCCESS) { apr_pool_cleanup_kill(lib->pool, lib, crypto_lib_cleanup); diff --git a/crypto/apr_crypto_internal.c b/crypto/apr_crypto_internal.c deleted file mode 100644 index 2dcd24a7c..000000000 --- a/crypto/apr_crypto_internal.c +++ /dev/null @@ -1,357 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "apr_lib.h" -#include "apu.h" -#include "apr_private.h" -#include "apr_crypto.h" -#include "apr_crypto_internal.h" -#include "apr_strings.h" - -#if APU_HAVE_CRYPTO - -#if APU_HAVE_OPENSSL -#include "apr_thread_mutex.h" - -#include <openssl/crypto.h> -#include <openssl/engine.h> -#include <openssl/conf.h> -#include <openssl/comp.h> -#include <openssl/evp.h> -#include <openssl/ssl.h> - -#if APR_HAS_THREADS && APR_USE_OPENSSL_PRE_1_1_API -static apr_status_t ossl_thread_setup(apr_pool_t *pool); -#else -static APR_INLINE apr_status_t ossl_thread_setup(apr_pool_t *pool) -{ - return APR_SUCCESS; -} -#endif - -const char *apr__crypto_openssl_version(void) -{ - return OPENSSL_VERSION_TEXT; -} - -apr_status_t apr__crypto_openssl_init(const char *params, - const apu_err_t **result, - apr_pool_t *pool) -{ - /* Both undefined (or no-op) with LibreSSL */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - CRYPTO_malloc_init(); -#elif !defined(LIBRESSL_VERSION_NUMBER) - OPENSSL_malloc_init(); -#endif - ERR_load_crypto_strings(); - OpenSSL_add_all_algorithms(); - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); - - SSL_load_error_strings(); - SSL_library_init(); - - return ossl_thread_setup(pool); -} - -apr_status_t apr__crypto_openssl_term(void) -{ -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) - -#ifdef OPENSSL_FIPS - FIPS_mode_set(0); -#endif - CONF_modules_unload(1); - OBJ_cleanup(); - EVP_cleanup(); -#if !defined(LIBRESSL_VERSION_NUMBER) - RAND_cleanup(); -#endif - ENGINE_cleanup(); -#ifndef OPENSSL_NO_COMP - COMP_zlib_cleanup(); -#endif -#if OPENSSL_VERSION_NUMBER >= 0x1000000fL - ERR_remove_thread_state(NULL); -#else - ERR_remove_state(0); -#endif - ERR_free_strings(); - CRYPTO_cleanup_all_ex_data(); - -#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ - OPENSSL_cleanup(); -#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ - - return APR_SUCCESS; -} - -/* - * To ensure thread-safetyness in OpenSSL - work in progress - * Taken from httpd's mod_ssl code. - */ - -#if APR_HAS_THREADS && APR_USE_OPENSSL_PRE_1_1_API - -static apr_thread_mutex_t **ossl_locks; -static int ossl_num_locks; - -static void ossl_thread_locking(int mode, int type, const char *file, int line) -{ - if (type < ossl_num_locks) { - if (mode & CRYPTO_LOCK) { - (void)apr_thread_mutex_lock(ossl_locks[type]); - } - else { - (void)apr_thread_mutex_unlock(ossl_locks[type]); - } - } -} - -/* Dynamic lock structure */ -struct CRYPTO_dynlock_value { - apr_pool_t *pool; - apr_thread_mutex_t *mutex; - const char* file; - int line; -}; - -/* Global reference to the pool passed into ossl_thread_setup() */ -static apr_pool_t *ossl_dynlock_pool = NULL; - -/* - * Dynamic lock creation callback - */ -static -struct CRYPTO_dynlock_value *ossl_dynlock_create(const char *file, int line) -{ - struct CRYPTO_dynlock_value *value; - apr_status_t rv; - apr_pool_t *p; - - /* - * We need a pool to allocate our mutex. Since we can't clear - * allocated memory from a pool, create a subpool that we can blow - * away in the destruction callback. - */ - rv = apr_pool_create(&p, ossl_dynlock_pool); - if (rv != APR_SUCCESS) { - return NULL; - } - - value = apr_palloc(p, sizeof(*value)); - - rv = apr_thread_mutex_create(&value->mutex, APR_THREAD_MUTEX_DEFAULT, p); - if (rv != APR_SUCCESS) { - apr_pool_destroy(p); - return NULL; - } - - /* Keep our own copy of the place from which we were created, - using our own pool. */ - value->file = apr_pstrdup(p, file); - value->line = line; - value->pool = p; - return value; -} - -/* - * Dynamic locking and unlocking function - */ - -static void ossl_dynlock_locking(int mode, struct CRYPTO_dynlock_value *l, - const char *file, int line) -{ - if (mode & CRYPTO_LOCK) { - (void)apr_thread_mutex_lock(l->mutex); - } - else { - (void)apr_thread_mutex_unlock(l->mutex); - } -} - -/* - * Dynamic lock destruction callback - */ -static void ossl_dynlock_destroy(struct CRYPTO_dynlock_value *l, - const char *file, int line) -{ - /* Trust that whomever owned the CRYPTO_dynlock_value we were - * passed has no future use for it... - */ - apr_pool_destroy(l->pool); -} - -/* Windows and BeOS can use the default THREADID callback shipped with OpenSSL - * 1.0.x, as can any platform with a thread-safe errno. - */ -#define OSSL_DEFAULT_THREADID_IS_SAFE (OPENSSL_VERSION_NUMBER >= 0x10000000L \ - && (defined(_REENTRANT) \ - || __BEOS__ \ - || _WIN32 \ - )) -#if OSSL_DEFAULT_THREADID_IS_SAFE - -/* We don't need to set up a threadid callback on this platform. */ -static APR_INLINE apr_status_t ossl_thread_id_setup(apr_pool_t *pool) -{ - return APR_SUCCESS; -} - -static APR_INLINE apr_status_t ossl_thread_id_cleanup(void) -{ - return APR_SUCCESS; -} - -#else - -/** - * Used by both versions of ossl_thread_id(). Returns an unsigned long that - * should be unique to the currently executing thread. - */ -static unsigned long ossl_thread_id_internal(void) -{ - /* OpenSSL needs this to return an unsigned long. On OS/390, the pthread - * id is a structure twice that big. Use the TCB pointer instead as a - * unique unsigned long. - */ -#ifdef __MVS__ - struct PSA { - char unmapped[540]; /* PSATOLD is at offset 540 in the PSA */ - unsigned long PSATOLD; - } *psaptr = 0; /* PSA is at address 0 */ - - return psaptr->PSATOLD; -#else - return (unsigned long) apr_os_thread_current(); -#endif -} - -#ifndef OPENSSL_NO_DEPRECATED - -static unsigned long ossl_thread_id(void) -{ - return ossl_thread_id_internal(); -} - -#else - -static void ossl_thread_id(CRYPTO_THREADID *id) -{ - /* XXX Ideally we would be using the _set_pointer() callback on platforms - * that have a pointer-based thread "identity". But this entire API is - * fraught with problems (see PR60947) and has been removed completely in - * OpenSSL 1.1.0, so I'm not too invested in fixing it right now. */ - CRYPTO_THREADID_set_numeric(id, ossl_thread_id_internal()); -} - -#endif /* OPENSSL_NO_DEPRECATED */ - -static apr_status_t ossl_thread_id_cleanup(void) -{ -#ifndef OPENSSL_NO_DEPRECATED - CRYPTO_set_id_callback(NULL); -#else - /* XXX This does nothing. The new-style THREADID callback is write-once. */ - CRYPTO_THREADID_set_callback(NULL); -#endif - - return APR_SUCCESS; -} - -static apr_status_t ossl_thread_id_setup(apr_pool_t *pool) -{ -#ifndef OPENSSL_NO_DEPRECATED - /* This API is deprecated, but we prefer it to its replacement since it - * allows us to unset the callback when this module is being unloaded. */ - CRYPTO_set_id_callback(ossl_thread_id); -#else - /* This is a last resort. We can only set this once, which means that we'd - * better not get reloaded into a different address. See PR60947. - */ - CRYPTO_THREADID_set_callback(ossl_thread_id); - - if (CRYPTO_THREADID_get_callback() != ossl_thread_id) { - return APR_EGENERAL; - } -#endif - - return APR_SUCCESS; -} - -#endif /* OSSL_DEFAULT_THREADID_IS_SAFE */ - -static apr_status_t ossl_thread_cleanup(void *data) -{ - CRYPTO_set_dynlock_create_callback(NULL); - CRYPTO_set_dynlock_lock_callback(NULL); - CRYPTO_set_dynlock_destroy_callback(NULL); - ossl_dynlock_pool = NULL; - - CRYPTO_set_locking_callback(NULL); - - ossl_thread_id_cleanup(); - - return APR_SUCCESS; -} - -static apr_status_t ossl_thread_setup(apr_pool_t *pool) -{ - apr_status_t rv; - int i, num_locks; - - rv = ossl_thread_id_setup(pool); - if (rv != APR_SUCCESS) { - return rv; - } - - num_locks = CRYPTO_num_locks(); - ossl_locks = apr_palloc(pool, num_locks * sizeof(*ossl_locks)); - if (!ossl_locks) { - return APR_ENOMEM; - } - for (i = 0; i < num_locks; i++) { - rv = apr_thread_mutex_create(&ossl_locks[i], - APR_THREAD_MUTEX_DEFAULT, pool); - if (rv != APR_SUCCESS) { - return rv; - } - } - ossl_num_locks = num_locks; - - CRYPTO_set_locking_callback(ossl_thread_locking); - - /* Set up dynamic locking scaffolding for OpenSSL to use at its - * convenience. - */ - ossl_dynlock_pool = pool; - CRYPTO_set_dynlock_create_callback(ossl_dynlock_create); - CRYPTO_set_dynlock_lock_callback(ossl_dynlock_locking); - CRYPTO_set_dynlock_destroy_callback(ossl_dynlock_destroy); - - apr_pool_cleanup_register(pool, NULL, ossl_thread_cleanup, - apr_pool_cleanup_null); - return APR_SUCCESS; -} - -#endif /* #if APR_HAS_THREADS && APR_USE_OPENSSL_PRE_1_1_API */ - - -#endif /* APU_HAVE_OPENSSL */ - - -#endif /* APU_HAVE_CRYPTO */ diff --git a/crypto/apr_crypto_openssl.c b/crypto/apr_crypto_openssl.c index 3220eef6b..7a9c40459 100644 --- a/crypto/apr_crypto_openssl.c +++ b/crypto/apr_crypto_openssl.c @@ -26,6 +26,7 @@ #include "apr_strings.h" #include "apr_time.h" #include "apr_buckets.h" +#include "apr_thread_mutex.h" #include "apr_crypto_internal.h" @@ -36,9 +37,28 @@ #include <openssl/engine.h> #include <openssl/crypto.h> #include <openssl/obj_mac.h> /* for NID_* */ +#include <openssl/conf.h> +#include <openssl/comp.h> +#include <openssl/ssl.h> #define LOG_PREFIX "apr_crypto_openssl: " +#ifndef APR_USE_OPENSSL_PRE_1_1_API +#if defined(LIBRESSL_VERSION_NUMBER) +/* LibreSSL declares OPENSSL_VERSION_NUMBER == 2.0 but does not necessarily + * include changes from OpenSSL >= 1.1 (new functions, macros, * deprecations, + * ...), so we have to work around this... + */ +#define APR_USE_OPENSSL_PRE_1_0_API (0) +#define APR_USE_OPENSSL_PRE_1_1_API (LIBRESSL_VERSION_NUMBER < 0x2070000f) +#define APR_USE_OPENSSL_PRE_1_1_1_API (1) +#else /* defined(LIBRESSL_VERSION_NUMBER) */ +#define APR_USE_OPENSSL_PRE_1_0_API (OPENSSL_VERSION_NUMBER < 0x10000000L) +#define APR_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L) +#define APR_USE_OPENSSL_PRE_1_1_1_API (OPENSSL_VERSION_NUMBER < 0x10101000L) +#endif /* defined(LIBRESSL_VERSION_NUMBER) */ +#endif /* ndef APR_USE_OPENSSL_PRE_1_1_API */ + struct apr_crypto_t { apr_pool_t *pool; const apr_crypto_driver_t *provider; @@ -133,7 +153,15 @@ static apr_status_t crypto_error(const apu_err_t **result, */ static apr_status_t crypto_shutdown(void) { - return apr_crypto_lib_term("openssl"); + ERR_free_strings(); + EVP_cleanup(); + ENGINE_cleanup(); + return APR_SUCCESS; +} + +static apr_status_t crypto_shutdown_helper(void *data) +{ + return crypto_shutdown(); } /** @@ -142,7 +170,21 @@ static apr_status_t crypto_shutdown(void) static apr_status_t crypto_init(apr_pool_t *pool, const char *params, const apu_err_t **result) { - return apr_crypto_lib_init("openssl", params, result, pool); +#if APR_USE_OPENSSL_PRE_1_1_API + (void)CRYPTO_malloc_init(); +#else + OPENSSL_malloc_init(); +#endif + ERR_load_crypto_strings(); + /* SSL_load_error_strings(); */ + OpenSSL_add_all_algorithms(); + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); + + apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper, + apr_pool_cleanup_null); + + return APR_SUCCESS; } #if OPENSSL_VERSION_NUMBER < 0x0090802fL |