summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2018-06-13 09:18:19 +0000
committerYann Ylavic <ylavic@apache.org>2018-06-13 09:18:19 +0000
commitcd3bd5596a0209fc86c69605baa39f794dcfda11 (patch)
tree7eda6dae346965d4b3b78ec2d5b909a52cddeb86 /crypto
parent38d135d8744cf88799af4012084bde1ca256fb9b (diff)
downloadapr-cd3bd5596a0209fc86c69605baa39f794dcfda11.tar.gz
apr_crypto: follow up to r1833359: crypto libs initialization scope.
The crypto libs initialized on (and terminated with) the given pool, not the root pool. The latter is used only to maintain the active libs. This allows the users to control the scope of the lib, e.g. when itself is called by dynamic linking or DSO. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1833449 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'crypto')
-rw-r--r--crypto/apr_crypto.c153
-rw-r--r--crypto/apr_crypto_internal.c12
2 files changed, 124 insertions, 41 deletions
diff --git a/crypto/apr_crypto.c b/crypto/apr_crypto.c
index 221792d26..8b1b0888b 100644
--- a/crypto/apr_crypto.c
+++ b/crypto/apr_crypto.c
@@ -33,7 +33,6 @@
#include "apr_crypto.h"
#include "apr_version.h"
-static apr_hash_t *crypto_libs = NULL;
static apr_hash_t *drivers = NULL;
#define ERROR_SIZE 1024
@@ -305,24 +304,56 @@ APR_DECLARE(apr_status_t) apr_crypto_get_driver(
return rv;
}
-static apr_status_t crypto_libs_cleanup(void *arg)
+struct crypto_lib {
+ const char *name;
+ apr_pool_t *pool;
+ apr_status_t (*term)(void);
+ struct crypto_lib *next;
+};
+static apr_hash_t *active_libs = NULL;
+static struct crypto_lib *spare_libs = NULL;
+
+static apr_status_t crypto_libs_cleanup(void *nil)
{
- apr_hash_index_t *hi;
+ active_libs = NULL;
+ spare_libs = NULL;
+ return APR_SUCCESS;
+}
- for (hi = apr_hash_first(NULL, crypto_libs); hi; hi = apr_hash_next(hi)) {
- const char *name = apr_hash_this_key(hi);
- if (name) {
- apr_crypto_lib_term(name);
- }
+static void spare_lib_push(struct crypto_lib *lib)
+{
+ lib->name = NULL;
+ lib->pool = NULL;
+ lib->term = NULL;
+ lib->next = spare_libs;
+ spare_libs = lib;
+}
+
+static struct crypto_lib *spare_lib_pop(void)
+{
+ struct crypto_lib *lib;
+ lib = spare_libs;
+ if (lib) {
+ spare_libs = lib->next;
+ lib->next = NULL;
}
- crypto_libs = NULL;
+ return lib;
+}
+
+static apr_status_t crypto_lib_cleanup(void *arg)
+{
+ struct crypto_lib *lib = arg;
+
+ apr_hash_set(active_libs, lib->name, APR_HASH_KEY_STRING, NULL);
+ lib->term();
+ spare_lib_push(lib);
return APR_SUCCESS;
}
-APR_DECLARE(int) apr_crypto_lib_is_initialized(const char *name)
+APR_DECLARE(int) apr_crypto_lib_is_active(const char *name)
{
- return crypto_libs && apr_hash_get(crypto_libs, name, APR_HASH_KEY_STRING);
+ return active_libs && apr_hash_get(active_libs, name, APR_HASH_KEY_STRING);
}
APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name,
@@ -331,123 +362,169 @@ APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name,
apr_pool_t *pool)
{
apr_status_t rv;
- apr_pool_t *parent;
+ apr_pool_t *rootp, *p;
+ struct crypto_lib *lib;
if (!name) {
return APR_EINVAL;
}
- if (apr_crypto_lib_is_initialized(name)) {
+ if (apr_crypto_lib_is_active(name)) {
return APR_EREINIT;
}
- while ((parent = apr_pool_parent_get(pool))) {
- pool = parent;
+ rootp = pool;
+ while ((p = apr_pool_parent_get(rootp))) {
+ rootp = p;
}
- if (!crypto_libs) {
- crypto_libs = apr_hash_make(pool);
- if (!crypto_libs) {
+ if (!active_libs) {
+ active_libs = apr_hash_make(rootp);
+ if (!active_libs) {
return APR_ENOMEM;
}
- apr_pool_cleanup_register(pool, NULL, crypto_libs_cleanup,
+ apr_pool_cleanup_register(rootp, NULL, crypto_libs_cleanup,
apr_pool_cleanup_null);
}
+ lib = spare_lib_pop();
+ if (!lib) {
+ lib = apr_pcalloc(rootp, sizeof(*lib));
+ if (!lib) {
+ return APR_ENOMEM;
+ }
+ }
+ lib->pool = pool;
+
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 APU_HAVE_NSS
if (!strcmp(name, "nss")) {
rv = apr__crypto_nss_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_nss_term;
+ lib->name = "nss";
+ }
}
else
#endif
#if APU_HAVE_COMMONCRYPTO
if (!strcmp(name, "commoncrypto")) {
rv = apr__crypto_commoncrypto_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_commoncrypto_term;
+ lib->name = "commoncrypto";
+ }
}
else
#endif
#if APU_HAVE_MSCAPI
if (!strcmp(name, "mscapi")) {
rv = apr__crypto_mscapi_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_mscapi_term;
+ lib->name = "mscapi";
+ }
}
else
#endif
#if APU_HAVE_MSCNG
if (!strcmp(name, "mscng")) {
rv = apr__crypto_mscng_init(params, result, pool);
+ if (rv == APR_SUCCESS) {
+ lib->term = apr__crypto_mscng_term;
+ lib->name = "mscng";
+ }
}
else
#endif
;
if (rv == APR_SUCCESS) {
- name = apr_pstrdup(pool, name);
- apr_hash_set(crypto_libs, name, APR_HASH_KEY_STRING, name);
+ apr_hash_set(active_libs, lib->name, APR_HASH_KEY_STRING, lib);
+ apr_pool_cleanup_register(pool, lib, crypto_lib_cleanup,
+ apr_pool_cleanup_null);
+ }
+ else {
+ spare_lib_push(lib);
}
return rv;
}
-APR_DECLARE(apr_status_t) apr_crypto_lib_term(const char *name)
+static apr_status_t crypto_lib_term(const char *name)
{
apr_status_t rv;
+ struct crypto_lib *lib;
- if (!crypto_libs) {
- return APR_EINIT;
- }
-
- if (!name) {
- apr_pool_t *pool = apr_hash_pool_get(crypto_libs);
- return apr_pool_cleanup_run(pool, NULL, crypto_libs_cleanup);
- }
-
- if (!apr_hash_get(crypto_libs, name, APR_HASH_KEY_STRING)) {
+ lib = apr_hash_get(active_libs, name, APR_HASH_KEY_STRING);
+ if (!lib) {
return APR_EINIT;
}
rv = APR_ENOTIMPL;
#if APU_HAVE_OPENSSL
if (!strcmp(name, "openssl")) {
- rv = apr__crypto_openssl_term();
+ rv = APR_SUCCESS;
}
else
#endif
#if APU_HAVE_NSS
if (!strcmp(name, "nss")) {
- rv = apr__crypto_nss_term();
+ rv = APR_SUCCESS;
}
else
#endif
#if APU_HAVE_COMMONCRYPTO
if (!strcmp(name, "commoncrypto")) {
- rv = apr__crypto_commoncrypto_term();
+ rv = APR_SUCCESS;
}
else
#endif
#if APU_HAVE_MSCAPI
if (!strcmp(name, "mscapi")) {
- rv = apr__crypto_mscapi_term();
+ rv = APR_SUCCESS;
}
else
#endif
#if APU_HAVE_MSCNG
if (!strcmp(name, "mscng")) {
- rv = apr__crypto_mscng_term();
+ rv = APR_SUCCESS;
}
else
#endif
;
if (rv == APR_SUCCESS) {
- apr_hash_set(crypto_libs, name, APR_HASH_KEY_STRING, NULL);
+ rv = apr_pool_cleanup_run(lib->pool, lib, crypto_lib_cleanup);
}
return rv;
}
+APR_DECLARE(apr_status_t) apr_crypto_lib_term(const char *name)
+{
+ if (!active_libs) {
+ return APR_EINIT;
+ }
+
+ if (!name) {
+ apr_hash_index_t *hi = apr_hash_first(NULL, active_libs);
+ for (; hi; hi = apr_hash_next(hi)) {
+ name = apr_hash_this_key(hi);
+ crypto_lib_term(name);
+ }
+ return APR_SUCCESS;
+ }
+
+ return crypto_lib_term(name);
+}
+
/**
* @brief Return the name of the driver.
*
diff --git a/crypto/apr_crypto_internal.c b/crypto/apr_crypto_internal.c
index 8e81f8361..901d69d45 100644
--- a/crypto/apr_crypto_internal.c
+++ b/crypto/apr_crypto_internal.c
@@ -63,6 +63,7 @@ apr_status_t apr__crypto_openssl_init(const char *params,
apr_status_t apr__crypto_openssl_term(void)
{
#if APR_USE_OPENSSL_PRE_1_1_API
+
#ifdef OPENSSL_FIPS
FIPS_mode_set(0);
#endif
@@ -71,12 +72,17 @@ apr_status_t apr__crypto_openssl_term(void)
EVP_cleanup();
RAND_cleanup();
ENGINE_cleanup();
- ERR_free_strings();
- ERR_remove_thread_state(NULL);
- CRYPTO_cleanup_all_ex_data();
#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 /* !APR_USE_OPENSSL_PRE_1_1_API */
OPENSSL_cleanup();
#endif /* !APR_USE_OPENSSL_PRE_1_1_API */