summaryrefslogtreecommitdiffstats
path: root/modules/ssl/mod_ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ssl/mod_ssl.c')
-rw-r--r--modules/ssl/mod_ssl.c162
1 files changed, 93 insertions, 69 deletions
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
index 9fdf9e0..fb66d18 100644
--- a/modules/ssl/mod_ssl.c
+++ b/modules/ssl/mod_ssl.c
@@ -25,8 +25,7 @@
*/
#include "ssl_private.h"
-#include "mod_ssl.h"
-#include "mod_ssl_openssl.h"
+
#include "util_md5.h"
#include "util_mutex.h"
#include "ap_provider.h"
@@ -75,11 +74,9 @@ static const command_rec ssl_config_cmds[] = {
SSL_CMD_SRV(SessionCache, TAKE1,
"SSL Session Cache storage "
"('none', 'nonenotnull', 'dbm:/path/to/file')")
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT)
SSL_CMD_SRV(CryptoDevice, TAKE1,
"SSL external Crypto Device usage "
"('builtin', '...')")
-#endif
SSL_CMD_SRV(RandomSeed, TAKE23,
"SSL Pseudo Random Number Generator (PRNG) seeding source "
"('startup|connect builtin|file:/path|exec:/path [bytes]')")
@@ -94,7 +91,7 @@ static const command_rec ssl_config_cmds[] = {
"Enable FIPS-140 mode "
"(`on', `off')")
SSL_CMD_ALL(CipherSuite, TAKE12,
- "Colon-delimited list of permitted SSL Ciphers, optional preceeded "
+ "Colon-delimited list of permitted SSL Ciphers, optional preceded "
"by protocol identifier ('XXX:...:XXX' - see manual)")
SSL_CMD_SRV(CertificateFile, TAKE1,
"SSL Server Certificate file "
@@ -187,7 +184,7 @@ static const command_rec ssl_config_cmds[] = {
"('[+-][" SSL_PROTOCOLS "] ...' - see manual)")
SSL_CMD_PXY(ProxyCipherSuite, TAKE12,
"SSL Proxy: colon-delimited list of permitted SSL ciphers "
- ", optionally preceeded by protocol specifier ('XXX:...:XXX' - see manual)")
+ ", optionally preceded by protocol specifier ('XXX:...:XXX' - see manual)")
SSL_CMD_PXY(ProxyVerify, TAKE1,
"SSL Proxy: whether to verify the remote certificate "
"('on' or 'off')")
@@ -328,12 +325,17 @@ static int modssl_is_prelinked(void)
static apr_status_t ssl_cleanup_pre_config(void *data)
{
- /*
- * Try to kill the internals of the SSL library.
+#if HAVE_OPENSSL_INIT_SSL || (OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !defined(LIBRESSL_VERSION_NUMBER))
+ /* Openssl v1.1+ handles all termination automatically from
+ * OPENSSL_init_ssl(). Do nothing in this case.
*/
-#ifdef HAVE_FIPS
- FIPS_mode_set(0);
-#endif
+
+#else
+ /* Termination below is for legacy Openssl versions v1.0.x and
+ * older.
+ */
+
/* Corresponds to OBJ_create()s */
OBJ_cleanup();
/* Corresponds to OPENSSL_load_builtin_modules() */
@@ -373,12 +375,14 @@ static apr_status_t ssl_cleanup_pre_config(void *data)
if (!modssl_running_statically) {
CRYPTO_cleanup_all_ex_data();
}
+#endif
/*
* TODO: determine somewhere we can safely shove out diagnostics
* (when enabled) at this late stage in the game:
* CRYPTO_mem_leaks_fp(stderr);
*/
+
return APR_SUCCESS;
}
@@ -388,16 +392,23 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
{
modssl_running_statically = modssl_is_prelinked();
- /* Some OpenSSL internals are allocated per-thread, make sure they
- * are associated to the/our same thread-id until cleaned up.
+#if HAVE_OPENSSL_INIT_SSL || (OPENSSL_VERSION_NUMBER >= 0x10100000L && \
+ !defined(LIBRESSL_VERSION_NUMBER))
+ /* Openssl v1.1+ handles all initialisation automatically, apart
+ * from hints as to how we want to use the library.
+ *
+ * We tell openssl we want to include engine support.
+ */
+ OPENSSL_init_ssl(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL);
+
+#else
+ /* Configuration below is for legacy versions Openssl v1.0 and
+ * older.
*/
+
#if APR_HAS_THREADS && MODSSL_USE_OPENSSL_PRE_1_1_API
ssl_util_thread_id_setup(pconf);
#endif
-
- /* We must register the library in full, to ensure our configuration
- * code can successfully test the SSL environment.
- */
#if MODSSL_USE_OPENSSL_PRE_1_1_API || defined(LIBRESSL_VERSION_NUMBER)
(void)CRYPTO_malloc_init();
#else
@@ -411,6 +422,7 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
#endif
OpenSSL_add_all_algorithms();
OPENSSL_load_builtin_modules();
+#endif
if (OBJ_txt2nid("id-on-dnsSRV") == NID_undef) {
(void)OBJ_create("1.3.6.1.5.5.7.8.7", "id-on-dnsSRV",
@@ -445,17 +457,30 @@ static int ssl_hook_pre_config(apr_pool_t *pconf,
}
static SSLConnRec *ssl_init_connection_ctx(conn_rec *c,
- ap_conf_vector_t *per_dir_config)
+ ap_conf_vector_t *per_dir_config,
+ int reinit)
{
SSLConnRec *sslconn = myConnConfig(c);
- SSLSrvConfigRec *sc;
-
- if (sslconn) {
+ int need_setup = 0;
+
+ /* mod_proxy's (r->)per_dir_config has the lifetime of the request, thus
+ * it uses ssl_engine_set() to reset sslconn->dc when reusing SSL backend
+ * connections, so we must fall through here. But in the case where we are
+ * called from ssl_init_ssl_connection() with no per_dir_config (which also
+ * includes mod_proxy's later run_pre_connection call), sslconn->dc should
+ * be preserved if it's already set.
+ */
+ if (!sslconn) {
+ sslconn = apr_pcalloc(c->pool, sizeof(*sslconn));
+ need_setup = 1;
+ }
+ else if (!reinit) {
return sslconn;
}
- sslconn = apr_pcalloc(c->pool, sizeof(*sslconn));
-
+ /* Reinit dc in any case because it may be r->per_dir_config scoped
+ * and thus a caller like mod_proxy needs to update it per request.
+ */
if (per_dir_config) {
sslconn->dc = ap_get_module_config(per_dir_config, &ssl_module);
}
@@ -464,12 +489,19 @@ static SSLConnRec *ssl_init_connection_ctx(conn_rec *c,
&ssl_module);
}
- sslconn->server = c->base_server;
- sslconn->verify_depth = UNSET;
- sc = mySrvConfig(c->base_server);
- sslconn->cipher_suite = sc->server->auth.cipher_suite;
+ if (need_setup) {
+ sslconn->server = c->base_server;
+ sslconn->verify_depth = UNSET;
+ if (c->outgoing) {
+ sslconn->cipher_suite = sslconn->dc->proxy->auth.cipher_suite;
+ }
+ else {
+ SSLSrvConfigRec *sc = mySrvConfig(c->base_server);
+ sslconn->cipher_suite = sc->server->auth.cipher_suite;
+ }
- myConnConfigSet(c, sslconn);
+ myConnConfigSet(c, sslconn);
+ }
return sslconn;
}
@@ -480,10 +512,11 @@ static int ssl_engine_status(conn_rec *c, SSLConnRec *sslconn)
return DECLINED;
}
if (sslconn) {
+ /* This connection has already been configured. Check what applies. */
if (sslconn->disabled) {
return SUSPENDED;
}
- if (sslconn->is_proxy) {
+ if (c->outgoing) {
if (!sslconn->dc->proxy_enabled) {
return DECLINED;
}
@@ -495,54 +528,48 @@ static int ssl_engine_status(conn_rec *c, SSLConnRec *sslconn)
}
}
else {
- if (mySrvConfig(c->base_server)->enabled != SSL_ENABLED_TRUE) {
+ /* we decline by default for outgoing connections and for incoming
+ * where the base_server is not enabled. */
+ if (c->outgoing || mySrvConfig(c->base_server)->enabled != SSL_ENABLED_TRUE) {
return DECLINED;
}
}
return OK;
}
-static int ssl_engine_set(conn_rec *c,
- ap_conf_vector_t *per_dir_config,
- int proxy, int enable)
+static int ssl_hook_ssl_bind_outgoing(conn_rec *c,
+ ap_conf_vector_t *per_dir_config,
+ int enable_ssl)
{
SSLConnRec *sslconn;
int status;
-
- if (proxy) {
- sslconn = ssl_init_connection_ctx(c, per_dir_config);
- sslconn->is_proxy = 1;
- }
- else {
- sslconn = myConnConfig(c);
+
+ sslconn = ssl_init_connection_ctx(c, per_dir_config, 1);
+ if (sslconn->ssl) {
+ /* we are already bound to this connection. We have rebound
+ * or removed the reference to a previous per_dir_config,
+ * there is nothing more to do. */
+ return OK;
}
status = ssl_engine_status(c, sslconn);
-
- if (proxy && status == DECLINED) {
- if (enable) {
+ if (enable_ssl) {
+ if (status != OK) {
SSLSrvConfigRec *sc = mySrvConfig(sslconn->server);
- ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01961)
- "SSL Proxy requested for %s but not enabled "
- "[Hint: SSLProxyEngine]", sc->vhost_id);
+ sslconn->disabled = 1;
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10272)
+ "SSL Proxy requested for %s but not enabled for us.",
+ sc->vhost_id);
+ }
+ else {
+ sslconn->disabled = 0;
+ return OK;
}
- sslconn->disabled = 1;
}
- else if (sslconn) {
- sslconn->disabled = !enable;
+ else {
+ sslconn->disabled = 1;
}
-
- return status != DECLINED;
-}
-
-static int ssl_proxy_enable(conn_rec *c)
-{
- return ssl_engine_set(c, NULL, 1, 1);
-}
-
-static int ssl_engine_disable(conn_rec *c)
-{
- return ssl_engine_set(c, NULL, 0, 0);
+ return DECLINED;
}
int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
@@ -558,7 +585,7 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
/*
* Create or retrieve SSL context
*/
- sslconn = ssl_init_connection_ctx(c, r ? r->per_dir_config : NULL);
+ sslconn = ssl_init_connection_ctx(c, r ? r->per_dir_config : NULL, 0);
server = sslconn->server;
sc = mySrvConfig(server);
@@ -566,9 +593,9 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
* Seed the Pseudo Random Number Generator (PRNG)
*/
ssl_rand_seed(server, c->pool, SSL_RSCTX_CONNECT,
- sslconn->is_proxy ? "Proxy: " : "Server: ");
+ c->outgoing ? "Proxy: " : "Server: ");
- mctx = myCtxConfig(sslconn, sc);
+ mctx = myConnCtxConfig(c, sc);
/*
* Create a new SSL connection with the configured server SSL context and
@@ -586,7 +613,7 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
return DECLINED; /* XXX */
}
- rc = ssl_run_pre_handshake(c, ssl, sslconn->is_proxy ? 1 : 0);
+ rc = ssl_run_pre_handshake(c, ssl, c->outgoing ? 1 : 0);
if (rc != OK && rc != DECLINED) {
return rc;
}
@@ -718,10 +745,7 @@ static void ssl_register_hooks(apr_pool_t *p)
APR_HOOK_MIDDLE);
ssl_var_register(p);
-
- APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
- APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
- APR_REGISTER_OPTIONAL_FN(ssl_engine_set);
+ ap_hook_ssl_bind_outgoing (ssl_hook_ssl_bind_outgoing, NULL, NULL, APR_HOOK_MIDDLE);
ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl",
AUTHZ_PROVIDER_VERSION,