Folks,The following patch against trunk adds dynamic locking callbacks to mod_ssl. OpenSSL uses these in several places, including the CHIL engine that interfaces with the nCipher products. I work at nCipher, and this patch makes the CHIL engine load into a stock, unpatched openssl 0.9.8.
I've tested this on Linux (Ubuntu 7.10 w/ OpensSSL 0.9.8e-5ubuntu3.2) and put some load on this on Solaris 10 x86_64 with OpenSSL 0.9.8h. It's not a lot of code, and I don't think it gets in anyone's way. Opinions appreciated, especially on whether I'm doing the right thing with that pool:
Index: modules/ssl/ssl_private.h
===================================================================
--- modules/ssl/ssl_private.h (revision 686142)
+++ modules/ssl/ssl_private.h (working copy)
@@ -463,6 +463,16 @@
} SSLDirConfigRec;
/**
+ * Dynamic lock structure
+ */
+typedef struct {
+ apr_pool_t *pool;
+ const char* file;
+ int line;
+ apr_thread_mutex_t *mutex;
+} CRYPTO_dynlock_value;
+
+/**
* function prototypes
*/
Index: modules/ssl/ssl_engine_init.c
===================================================================
--- modules/ssl/ssl_engine_init.c (revision 686142)
+++ modules/ssl/ssl_engine_init.c (working copy)
@@ -321,6 +321,9 @@
ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
ssl_die();
}
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+ "Init: loaded Crypto Device API `%s'",
+ mc->szCryptoDevice);
ENGINE_free(e);
}
Index: modules/ssl/ssl_util.c
===================================================================
--- modules/ssl/ssl_util.c (revision 686142)
+++ modules/ssl/ssl_util.c (working copy)
@@ -351,6 +351,106 @@
}
}
+/* Global reference to the pool used by the dynamic mutexes */
+apr_pool_t *dynlockpool;
+
+/*
+ * Dynamic lock creation callback
+ */
+static CRYPTO_dynlock_value *dyn_create_function(const char *file,
+ int line)
+{
+ CRYPTO_dynlock_value *value;
+ apr_pool_t *p;
+ apr_status_t r;
+
+ /*
+ * 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.
+ */
+ r = apr_pool_create(&p, dynlockpool);
+ if (r != APR_SUCCESS) {
+ ap_log_perror(file, line, APLOG_ERR, r, dynlockpool,
+ "Failed to create subpool for dynamic lock");
+ return NULL;
+ }
+
+ ap_log_perror(file, line, APLOG_DEBUG, 0, p,
+ "Creating dynamic lock");
+
+ value = (CRYPTO_dynlock_value *)apr_palloc(p,
+
sizeof(CRYPTO_dynlock_value));
+ if (!value) {
+ ap_log_perror(file, line, APLOG_ERR, 0, p,
+ "Failed to allocate dynamic lock structure");
+ return NULL;
+ }
+
+ value->pool = p;
+ /* Keep our own copy of the place from which we were created,
+ using our own pool. */
+ value->file = apr_psprintf(p, "%s", file);
+ value->line = line;
+ r = apr_thread_mutex_create(&(value->mutex),
APR_THREAD_MUTEX_DEFAULT,
+ p);
+ if (r != APR_SUCCESS) {
+ ap_log_perror(file, line, APLOG_ERR, r, p,
+ "Failed to create thread mutex for dynamic
lock");
+ apr_pool_destroy(p);
+ return NULL;
+ }
+ return value;
+}
+
+/*
+ * Dynamic locking and unlocking function
+ */
+
+static void dyn_lock_function(int mode, CRYPTO_dynlock_value *l,
+ const char *file, int line)
+{
+ apr_status_t r;
+
+ if (mode & CRYPTO_LOCK) {
+ ap_log_perror(file, line, APLOG_DEBUG, 0, l->pool,
+ "Acquiring mutex %s:%d", l->file, l->line);
+ r = apr_thread_mutex_lock(l->mutex);
+ ap_log_perror(file, line, APLOG_DEBUG, r, l->pool,
+ "Mutex %s:%d acquired!", l->file, l->line);
+ }
+ else {
+ ap_log_perror(file, line, APLOG_DEBUG, 0, l->pool,
+ "Releasing mutex %s:%d", l->file, l->line);
+ r = apr_thread_mutex_unlock(l->mutex);
+ ap_log_perror(file, line, APLOG_DEBUG, r, l->pool,
+ "Mutex %s:%d released!", l->file, l->line);
+ }
+}
+
+/*
+ * Dynamic lock destruction callback
+ */
+static void dyn_destroy_function(CRYPTO_dynlock_value *l,
+ const char *file, int line)
+{
+ apr_status_t r;
+
+ ap_log_perror(file, line, APLOG_DEBUG, 0, l->pool,
+ "Destroying dynamic lock %s:%d", l->file, l->line);
+ r = apr_thread_mutex_destroy(l->mutex);
+ if (r != APR_SUCCESS) {
+ ap_log_perror(file, line, APLOG_ERR, r, l->pool,
+ "Failed to destroy mutex for dynamic lock %s:%d",
+ l->file, l->line);
+ }
+
+ /* Trust that whomever owned the CRYPTO_dynlock_value we were
+ * passed has no future use for it...
+ */
+ apr_pool_destroy(l->pool);
+}
+
static unsigned long ssl_util_thr_id(void)
{
/* OpenSSL needs this to return an unsigned long. On OS/390,
the pthread
@@ -393,6 +493,15 @@
CRYPTO_set_id_callback(ssl_util_thr_id);
CRYPTO_set_locking_callback(ssl_util_thr_lock);
+
+ /* Set up dynamic locking scaffolding for OpenSSL to use at its
+ * convenience.
+ */
+ apr_pool_create(&dynlockpool, NULL);
+ apr_pool_tag(dynlockpool, "dynlockpool");
+ CRYPTO_set_dynlock_create_callback(dyn_create_function);
+ CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
+ CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
apr_pool_cleanup_register(p, NULL, ssl_util_thread_cleanup,
apr_pool_cleanup_null);
Thanks,
S.
--
Sander Temme
[EMAIL PROTECTED]
PGP FP: 51B4 8727 466A 0BC3 69F4 B7B8 B2BE BC40 1529 24AF
mod_ssl_dynamic_lock.patch
Description: Binary data
smime.p7s
Description: S/MIME cryptographic signature
