summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crypto/apr_crypto.c84
-rw-r--r--crypto/apr_crypto_internal.c4
-rw-r--r--test/testcrypto.c7
-rw-r--r--util-misc/apu_dso.c17
4 files changed, 72 insertions, 40 deletions
diff --git a/crypto/apr_crypto.c b/crypto/apr_crypto.c
index 07cc672d9..e7c11b734 100644
--- a/crypto/apr_crypto.c
+++ b/crypto/apr_crypto.c
@@ -37,8 +37,6 @@ static apr_hash_t *drivers = NULL;
#define ERROR_SIZE 1024
-#define CLEANUP_CAST (apr_status_t (*)(void*))
-
APR_TYPEDEF_STRUCT(apr_crypto_t,
apr_pool_t *pool;
apr_crypto_driver_t *provider;
@@ -87,26 +85,29 @@ static apr_status_t apr_crypto_term(void *ptr)
APR_DECLARE(apr_status_t) apr_crypto_init(apr_pool_t *pool)
{
apr_status_t rv;
- apr_pool_t *parent;
+ apr_pool_t *rootp;
int flags = 0;
if (drivers != NULL) {
return APR_SUCCESS;
}
- /* Top level pool scope, need process-scope lifetime */
- for (parent = apr_pool_parent_get(pool);
- parent && parent != pool;
- parent = apr_pool_parent_get(pool))
- pool = parent;
+ /* Top level pool scope, for drivers' process-scope lifetime */
+ rootp = pool;
+ for (;;) {
+ apr_pool_t *p = apr_pool_parent_get(rootp);
+ if (!p || p == rootp) {
+ break;
+ }
+ rootp = p;
+ }
#if APR_HAVE_MODULAR_DSO
/* deprecate in 2.0 - permit implicit initialization */
- apu_dso_init(pool);
+ apu_dso_init(rootp);
#endif
- drivers = apr_hash_make(pool);
-
- apr_pool_cleanup_register(pool, NULL, apr_crypto_term,
- apr_pool_cleanup_null);
+ drivers = apr_hash_make(rootp);
+ apr_pool_cleanup_register(rootp, NULL, apr_crypto_term,
+ apr_pool_cleanup_null);
/* apr_crypto_prng_init() may already have been called with
* non-default parameters, so ignore APR_EREINIT.
@@ -203,6 +204,7 @@ APR_DECLARE(apr_status_t) apr_crypto_get_driver(
char symname[34];
apr_dso_handle_t *dso;
apr_dso_handle_sym_t symbol;
+ apr_pool_t *rootp;
#endif
apr_status_t rv;
@@ -227,7 +229,7 @@ APR_DECLARE(apr_status_t) apr_crypto_get_driver(
#if APR_HAVE_MODULAR_DSO
/* The driver DSO must have exactly the same lifetime as the
* drivers hash table; ignore the passed-in pool */
- pool = apr_hash_pool_get(drivers);
+ rootp = apr_hash_pool_get(drivers);
#if defined(NETWARE)
apr_snprintf(modname, sizeof(modname), "crypto%s.nlm", name);
@@ -239,21 +241,19 @@ APR_DECLARE(apr_status_t) apr_crypto_get_driver(
"apr_crypto_%s-" APR_STRINGIFY(APR_MAJOR_VERSION) ".so", name);
#endif
apr_snprintf(symname, sizeof(symname), "apr_crypto_%s_driver", name);
- rv = apu_dso_load(&dso, &symbol, modname, symname, pool);
+ rv = apu_dso_load(&dso, &symbol, modname, symname, rootp);
if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
apr_crypto_driver_t *d = symbol;
rv = APR_SUCCESS;
if (d->init) {
- rv = d->init(pool, params, result);
+ rv = d->init(rootp, params, result);
if (rv == APR_EREINIT) {
rv = APR_SUCCESS;
}
}
if (rv == APR_SUCCESS) {
- *driver = symbol;
- name = apr_pstrdup(pool, name);
- apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
- rv = APR_SUCCESS;
+ apr_hash_set(drivers, d->name, APR_HASH_KEY_STRING, d);
+ *driver = d;
}
}
apu_dso_mutex_unlock();
@@ -274,32 +274,38 @@ APR_DECLARE(apr_status_t) apr_crypto_get_driver(
/* Load statically-linked drivers: */
#if APU_HAVE_OPENSSL
- if (name[0] == 'o' && !strcmp(name, "openssl")) {
+ if (!strcmp(name, "openssl")) {
DRIVER_LOAD("openssl", apr_crypto_openssl_driver, pool, params, rv, result);
}
+ else
#endif
#if APU_HAVE_NSS
- if (name[0] == 'n' && !strcmp(name, "nss")) {
+ if (!strcmp(name, "nss")) {
DRIVER_LOAD("nss", apr_crypto_nss_driver, pool, params, rv, result);
}
+ else
#endif
#if APU_HAVE_COMMONCRYPTO
- if (name[0] == 'c' && !strcmp(name, "commoncrypto")) {
+ if (!strcmp(name, "commoncrypto")) {
DRIVER_LOAD("commoncrypto", apr_crypto_commoncrypto_driver, pool, params, rv, result);
}
+ else
#endif
#if APU_HAVE_MSCAPI
- if (name[0] == 'm' && !strcmp(name, "mscapi")) {
+ if (!strcmp(name, "mscapi")) {
DRIVER_LOAD("mscapi", apr_crypto_mscapi_driver, pool, params, rv, result);
}
+ else
#endif
#if APU_HAVE_MSCNG
- if (name[0] == 'm' && !strcmp(name, "mscng")) {
+ if (!strcmp(name, "mscng")) {
DRIVER_LOAD("mscng", apr_crypto_mscng_driver, pool, params, rv, result);
}
+ else
#endif
+ ;
-#endif
+#endif /* !APR_HAVE_MODULAR_DSO */
return rv;
}
@@ -407,7 +413,7 @@ APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name,
apr_pool_t *pool)
{
apr_status_t rv;
- apr_pool_t *rootp, *p;
+ apr_pool_t *rootp;
struct crypto_lib *lib;
if (!name) {
@@ -419,7 +425,11 @@ APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name,
}
rootp = pool;
- while ((p = apr_pool_parent_get(rootp))) {
+ for (;;) {
+ apr_pool_t *p = apr_pool_parent_get(rootp);
+ if (!p || p == rootp) {
+ break;
+ }
rootp = p;
}
@@ -495,8 +505,10 @@ APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name,
if (rv == APR_SUCCESS) {
lib->pool = pool;
apr_hash_set(active_libs, lib->name, APR_HASH_KEY_STRING, lib);
- apr_pool_cleanup_register(lib->pool, lib, crypto_lib_cleanup,
- apr_pool_cleanup_null);
+ if (apr_pool_parent_get(pool)) {
+ apr_pool_cleanup_register(pool, lib, crypto_lib_cleanup,
+ apr_pool_cleanup_null);
+ }
}
else {
spare_lib_push(lib);
@@ -513,6 +525,9 @@ static apr_status_t crypto_lib_term(const char *name)
if (!lib) {
return APR_EINIT;
}
+ if (!apr_pool_parent_get(lib->pool)) {
+ return APR_EBUSY;
+ }
rv = APR_ENOTIMPL;
#if APU_HAVE_OPENSSL
@@ -560,12 +575,15 @@ APR_DECLARE(apr_status_t) apr_crypto_lib_term(const char *name)
}
if (!name) {
+ apr_status_t rv = APR_SUCCESS;
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);
+ apr_status_t rt = crypto_lib_term(apr_hash_this_key(hi));
+ if (rt != APR_SUCCESS && (rv == APR_SUCCESS || rv == APR_EBUSY)) {
+ rv = rt;
+ }
}
- return APR_SUCCESS;
+ return rv;
}
return crypto_lib_term(name);
diff --git a/crypto/apr_crypto_internal.c b/crypto/apr_crypto_internal.c
index 09148e386..3f09f417f 100644
--- a/crypto/apr_crypto_internal.c
+++ b/crypto/apr_crypto_internal.c
@@ -284,8 +284,8 @@ const char *apr__crypto_mscng_version(void)
}
apr_status_t apr__crypto_mscng_init(const char *params,
- const apu_err_t **result,
- apr_pool_t *pool)
+ const apu_err_t **result,
+ apr_pool_t *pool)
{
return APR_ENOTIMPL;
}
diff --git a/test/testcrypto.c b/test/testcrypto.c
index e25095450..7c8a7c95e 100644
--- a/test/testcrypto.c
+++ b/test/testcrypto.c
@@ -559,7 +559,10 @@ static void test_crypto_init(abts_case *tc, void *data)
apr_pool_create(&pool, NULL);
- rv = apr_crypto_init(pool);
+ /* Use root pool (top level init) so that the crypto lib is
+ * not cleanup on pool destroy below (e.g. openssl can't re-init).
+ */
+ rv = apr_crypto_init(apr_pool_parent_get(pool));
ABTS_ASSERT(tc, "failed to init apr_crypto", rv == APR_SUCCESS);
apr_pool_destroy(pool);
@@ -1680,7 +1683,7 @@ abts_suite *testcrypto(abts_suite *suite)
{
suite = ADD_SUITE(suite);
- /* test simple init and shutdown */
+ /* test simple init and shutdown (keep first) */
abts_run_test(suite, test_crypto_init, NULL);
/* test key parsing - openssl */
diff --git a/util-misc/apu_dso.c b/util-misc/apu_dso.c
index dd29076eb..83ab33eca 100644
--- a/util-misc/apu_dso.c
+++ b/util-misc/apu_dso.c
@@ -106,6 +106,11 @@ apr_status_t apu_dso_init(apr_pool_t *pool)
return ret;
}
+struct dso_entry {
+ apr_dso_handle_t *handle;
+ apr_dso_handle_sym_t *sym;
+};
+
apr_status_t apu_dso_load(apr_dso_handle_t **dlhandleptr,
apr_dso_handle_sym_t *dsoptr,
const char *module,
@@ -118,11 +123,14 @@ apr_status_t apu_dso_load(apr_dso_handle_t **dlhandleptr,
apr_array_header_t *paths;
apr_pool_t *global;
apr_status_t rv = APR_EDSOOPEN;
+ struct dso_entry *entry;
char *eos = NULL;
int i;
- *dsoptr = apr_hash_get(dsos, module, APR_HASH_KEY_STRING);
- if (*dsoptr) {
+ entry = apr_hash_get(dsos, module, APR_HASH_KEY_STRING);
+ if (entry) {
+ *dlhandleptr = entry->handle;
+ *dsoptr = entry->sym;
return APR_EINIT;
}
@@ -199,7 +207,10 @@ apr_status_t apu_dso_load(apr_dso_handle_t **dlhandleptr,
}
else {
module = apr_pstrdup(global, module);
- apr_hash_set(dsos, module, APR_HASH_KEY_STRING, *dsoptr);
+ entry = apr_palloc(global, sizeof(*entry));
+ entry->handle = dlhandle;
+ entry->sym = *dsoptr;
+ apr_hash_set(dsos, module, APR_HASH_KEY_STRING, entry);
}
return rv;
}