From: Sander Temme Date: Thu, 18 Sep 2008 14:34:51 +0000 (+0000) Subject: Commit ssl mutex upcall patch X-Git-Tag: 2.2.10~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d3149536b79fe1c9cc3e560d0a3d6fba1f912455;p=thirdparty%2Fapache%2Fhttpd.git Commit ssl mutex upcall patch git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@696662 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index e1c6e75dbca..d509f77ae3e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.2.10 + *) mod_ssl: implement dynamic mutex callbacks for the benefit of + OpenSSL. [Sander Temme] + *) SECURITY: CVE-2008-2939 (cve.mitre.org) mod_proxy_ftp: Prevent XSS attacks when using wildcards in the path of the FTP URL. Discovered by Marc Bevand of Rapid7. [Ruediger Pluem] diff --git a/STATUS b/STATUS index 73329ece6a5..31db1cbed1f 100644 --- a/STATUS +++ b/STATUS @@ -161,18 +161,6 @@ PATCHES PROPOSED TO BACKPORT FROM TRUNK: +1: chrisd -0: jim (would prefer to see in 2.4, and to push 2.4 out) - * mod_ssl: implement dynamic mutex callbacks for OpenSSL. This - locking infrastructure is currently only used by the chil plugin, - and this plugin won't load into OpenSSL 0.9.8 if these upcalls - aren't set. OpenSSL may start using dynamic locks in more places - in the future and with this patch, Apache 2.2.x is ready for that. - Trunk version of patch: - http://svn.apache.org/viewvc?rev=687550&view=rev - http://svn.apache.org/viewvc?rev=687819&view=rev - Single patch against branches/2.2.x: - http://people.apache.org/~sctemme/httpd-2.2.x-ssl-upcalls.diff - +1: sctemme, rpluem, jerenkrantz - * INSTALL: Provide a breadcrumb as to why you would use --with-included-apr Trunk version of patch: http://svn.apache.org/viewvc?rev=696006&view=rev diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 268f7f24a13..8e3cef8f01a 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -321,6 +321,9 @@ void ssl_init_Engine(server_rec *s, apr_pool_t *p) 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); } diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c index 88410849bb0..e4387e6181f 100644 --- a/modules/ssl/ssl_util.c +++ b/modules/ssl/ssl_util.c @@ -305,6 +305,114 @@ static void ssl_util_thr_lock(int mode, int type, } } +/* Dynamic lock structure */ +struct CRYPTO_dynlock_value { + apr_pool_t *pool; + const char* file; + int line; + apr_thread_mutex_t *mutex; +}; + +/* Global reference to the pool passed into ssl_util_thread_setup() */ +apr_pool_t *dynlockpool = NULL; + +/* + * Dynamic lock creation callback + */ +static struct CRYPTO_dynlock_value *ssl_dyn_create_function(const char *file, + int line) +{ + struct CRYPTO_dynlock_value *value; + apr_pool_t *p; + apr_status_t rv; + + /* + * 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, dynlockpool); + if (rv != APR_SUCCESS) { + ap_log_perror(file, line, APLOG_ERR, rv, dynlockpool, + "Failed to create subpool for dynamic lock"); + return NULL; + } + + ap_log_perror(file, line, APLOG_DEBUG, 0, p, + "Creating dynamic lock"); + + value = (struct CRYPTO_dynlock_value *)apr_palloc(p, + sizeof(struct 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_pstrdup(p, file); + value->line = line; + rv = apr_thread_mutex_create(&(value->mutex), APR_THREAD_MUTEX_DEFAULT, + p); + if (rv != APR_SUCCESS) { + ap_log_perror(file, line, APLOG_ERR, rv, p, + "Failed to create thread mutex for dynamic lock"); + apr_pool_destroy(p); + return NULL; + } + return value; +} + +/* + * Dynamic locking and unlocking function + */ + +static void ssl_dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, + const char *file, int line) +{ + apr_status_t rv; + + if (mode & CRYPTO_LOCK) { + ap_log_perror(file, line, APLOG_DEBUG, 0, l->pool, + "Acquiring mutex %s:%d", l->file, l->line); + rv = apr_thread_mutex_lock(l->mutex); + ap_log_perror(file, line, APLOG_DEBUG, rv, 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); + rv = apr_thread_mutex_unlock(l->mutex); + ap_log_perror(file, line, APLOG_DEBUG, rv, l->pool, + "Mutex %s:%d released!", l->file, l->line); + } +} + +/* + * Dynamic lock destruction callback + */ +static void ssl_dyn_destroy_function(struct CRYPTO_dynlock_value *l, + const char *file, int line) +{ + apr_status_t rv; + + ap_log_perror(file, line, APLOG_DEBUG, 0, l->pool, + "Destroying dynamic lock %s:%d", l->file, l->line); + rv = apr_thread_mutex_destroy(l->mutex); + if (rv != APR_SUCCESS) { + ap_log_perror(file, line, APLOG_ERR, rv, 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 @@ -327,6 +435,12 @@ static apr_status_t ssl_util_thread_cleanup(void *data) { CRYPTO_set_locking_callback(NULL); CRYPTO_set_id_callback(NULL); + + CRYPTO_set_dynlock_create_callback(NULL); + CRYPTO_set_dynlock_lock_callback(NULL); + CRYPTO_set_dynlock_destroy_callback(NULL); + + dynlockpool = NULL; /* Let the registered mutex cleanups do their own thing */ @@ -347,6 +461,14 @@ void ssl_util_thread_setup(apr_pool_t *p) 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. + */ + dynlockpool = p; + CRYPTO_set_dynlock_create_callback(ssl_dyn_create_function); + CRYPTO_set_dynlock_lock_callback(ssl_dyn_lock_function); + CRYPTO_set_dynlock_destroy_callback(ssl_dyn_destroy_function); apr_pool_cleanup_register(p, NULL, ssl_util_thread_cleanup, apr_pool_cleanup_null);