From 876b00fcbe7d4a27065ec1eada56d352e990eee0 Mon Sep 17 00:00:00 2001
From: Kaspar Brand
Date: Mon, 6 Jan 2014 06:02:42 +0000
Subject: [PATCH] Backport r1421323, r1534754, r1546693, r1555464 from trunk:
Add support for OpenSSL configuration commands by introducing
the SSLOpenSSLConfCmd directive.
Proposed by: kbrand
Reviewed by: drh, trawick
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1555683 13f79535-47bb-0310-9956-ffa450edef68
---
CHANGES | 3 ++
STATUS | 8 ----
docs/manual/mod/mod_ssl.xml | 38 +++++++++++++++++++
modules/ssl/mod_ssl.c | 5 +++
modules/ssl/ssl_engine_config.c | 66 ++++++++++++++++++++++++++++-----
modules/ssl/ssl_engine_init.c | 50 +++++++++++++++++++++++++
modules/ssl/ssl_private.h | 20 +++++++++-
7 files changed, 171 insertions(+), 19 deletions(-)
diff --git a/CHANGES b/CHANGES
index 628586dc63..893a63df0f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@
Changes with Apache 2.4.8
+ *) mod_ssl: Add support for OpenSSL configuration commands by introducing
+ the SSLOpenSSLConfCmd directive. [Stephen Henson, Kaspar Brand]
+
*) mod_proxy: Remove (never documented) syntax which
is equivalent to . [Christophe Jaillet]
diff --git a/STATUS b/STATUS
index 6d4d6b61d9..8b223aca98 100644
--- a/STATUS
+++ b/STATUS
@@ -98,14 +98,6 @@ RELEASE SHOWSTOPPERS:
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- * mod_ssl: Add support for OpenSSL configuration commands (SSLOpenSSLConfCmd)
- trunk patches: https://svn.apache.org/r1421323
- https://svn.apache.org/r1534754
- https://svn.apache.org/r1546693
- https://svn.apache.org/r1555464
- 2.4.x patch: https://people.apache.org/~kbrand/mod_ssl-2.4.x-confcmd.diff
- +1: kbrand, drh, trawick
-
* mod_cache_disk hangs on windows reading from closed files
trunk patch: http://svn.apache.org/r1547845
2.4.x patch: trunk works
diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml
index 84dbe5159a..d0a16d6909 100644
--- a/docs/manual/mod/mod_ssl.xml
+++ b/docs/manual/mod/mod_ssl.xml
@@ -2535,5 +2535,43 @@ CRIME attack).
+
+SSLOpenSSLConfCmd
+Configure OpenSSL parameters through its SSL_CONF API
+SSLOpenSSLConfCmd command-name command-value
+server config
+virtual host
+Available in httpd 2.4.8 and later, if using OpenSSL 1.0.2 or later
+
+
+This directive exposes OpenSSL's SSL_CONF API to mod_ssl,
+allowing a flexible configuration of OpenSSL parameters without the need
+of implementing additional mod_ssl directives when new
+features are added to OpenSSL.
+
+The set of available SSLOpenSSLConfCmd commands
+depends on the OpenSSL version being used for mod_ssl
+(at least version 1.0.2 is required). For a list of supported command
+names, see the section Supported configuration file commands in the
+SSL_CONF_cmd(3) manual page for OpenSSL.
+
+Some of the SSLOpenSSLConfCmd commands can be used
+as an alternative to existing directives (such as
+SSLCipherSuite or
+SSLProtocol),
+though it should be noted that the syntax / allowable values for the parameters
+may sometimes differ.
+
+Examples
+
+SSLOpenSSLConfCmd Options -SessionTicket,ServerPreference
+SSLOpenSSLConfCmd ECDHParameters brainpoolP256r1
+SSLOpenSSLConfCmd ServerInfoFile /usr/local/apache2/conf/server-info.pem
+SSLOpenSSLConfCmd Protocol "-ALL, TLSv1.2"
+SSLOpenSSLConfCmd SignatureAlgorithms RSA+SHA384:ECDSA+SHA256
+
+
+
+
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
index f0499405d8..2afca28194 100644
--- a/modules/ssl/mod_ssl.c
+++ b/modules/ssl/mod_ssl.c
@@ -266,6 +266,11 @@ static const command_rec ssl_config_cmds[] = {
"SSL stapling option to Force the OCSP Stapling URL")
#endif
+#ifdef HAVE_SSL_CONF_CMD
+ SSL_CMD_SRV(OpenSSLConfCmd, TAKE2,
+ "OpenSSL configuration command")
+#endif
+
/* Deprecated directives. */
AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
"SSLLog directive is no longer supported - use ErrorLog."),
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
index f519151eda..cf003e98b7 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -98,7 +98,7 @@ BOOL ssl_config_global_isfixed(SSLModConfigRec *mc)
** _________________________________________________________________
*/
-static void modssl_ctx_init(modssl_ctx_t *mctx)
+static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p)
{
mctx->sc = NULL; /* set during module init */
@@ -153,6 +153,13 @@ static void modssl_ctx_init(modssl_ctx_t *mctx)
mctx->srp_unknown_user_seed = NULL;
mctx->srp_vbase = NULL;
#endif
+#ifdef HAVE_SSL_CONF_CMD
+ mctx->ssl_ctx_config = SSL_CONF_CTX_new();
+ SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_FILE);
+ SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_SERVER);
+ SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE);
+ mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t));
+#endif
}
static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
@@ -162,7 +169,7 @@ static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
mctx = sc->proxy = apr_palloc(p, sizeof(*sc->proxy));
- modssl_ctx_init(mctx);
+ modssl_ctx_init(mctx, p);
mctx->pkp = apr_palloc(p, sizeof(*mctx->pkp));
@@ -180,7 +187,7 @@ static void modssl_ctx_init_server(SSLSrvConfigRec *sc,
mctx = sc->server = apr_palloc(p, sizeof(*sc->server));
- modssl_ctx_init(mctx);
+ modssl_ctx_init(mctx, p);
mctx->pks = apr_pcalloc(p, sizeof(*mctx->pks));
@@ -241,7 +248,8 @@ void *ssl_config_server_create(apr_pool_t *p, server_rec *s)
#define cfgMergeBool(el) cfgMerge(el, UNSET)
#define cfgMergeInt(el) cfgMerge(el, UNSET)
-static void modssl_ctx_cfg_merge(modssl_ctx_t *base,
+static void modssl_ctx_cfg_merge(apr_pool_t *p,
+ modssl_ctx_t *base,
modssl_ctx_t *add,
modssl_ctx_t *mrg)
{
@@ -284,26 +292,32 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base,
cfgMergeString(srp_vfile);
cfgMergeString(srp_unknown_user_seed);
#endif
+
+#ifdef HAVE_SSL_CONF_CMD
+ cfgMergeArray(ssl_ctx_param);
+#endif
}
-static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base,
+static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p,
+ modssl_ctx_t *base,
modssl_ctx_t *add,
modssl_ctx_t *mrg)
{
- modssl_ctx_cfg_merge(base, add, mrg);
+ modssl_ctx_cfg_merge(p, base, add, mrg);
cfgMergeString(pkp->cert_file);
cfgMergeString(pkp->cert_path);
cfgMergeString(pkp->ca_cert_file);
}
-static void modssl_ctx_cfg_merge_server(modssl_ctx_t *base,
+static void modssl_ctx_cfg_merge_server(apr_pool_t *p,
+ modssl_ctx_t *base,
modssl_ctx_t *add,
modssl_ctx_t *mrg)
{
int i;
- modssl_ctx_cfg_merge(base, add, mrg);
+ modssl_ctx_cfg_merge(p, base, add, mrg);
for (i = 0; i < SSL_AIDX_MAX; i++) {
cfgMergeString(pks->cert_files[i]);
@@ -346,9 +360,9 @@ void *ssl_config_server_merge(apr_pool_t *p, void *basev, void *addv)
cfgMergeBool(compression);
#endif
- modssl_ctx_cfg_merge_proxy(base->proxy, add->proxy, mrg->proxy);
+ modssl_ctx_cfg_merge_proxy(p, base->proxy, add->proxy, mrg->proxy);
- modssl_ctx_cfg_merge_server(base->server, add->server, mrg->server);
+ modssl_ctx_cfg_merge_server(p, base->server, add->server, mrg->server);
return mrg;
}
@@ -1808,6 +1822,38 @@ const char *ssl_cmd_SSLStaplingForceURL(cmd_parms *cmd, void *dcfg,
#endif /* HAVE_OCSP_STAPLING */
+#ifdef HAVE_SSL_CONF_CMD
+const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg,
+ const char *arg1, const char *arg2)
+{
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+ SSL_CONF_CTX *cctx = sc->server->ssl_ctx_config;
+ int value_type = SSL_CONF_cmd_value_type(cctx, arg1);
+ const char *err;
+ ssl_ctx_param_t *param;
+
+ if (value_type == SSL_CONF_TYPE_UNKNOWN) {
+ return apr_psprintf(cmd->pool,
+ "'%s': invalid OpenSSL configuration command",
+ arg1);
+ }
+
+ if (value_type == SSL_CONF_TYPE_FILE) {
+ if ((err = ssl_cmd_check_file(cmd, &arg2)))
+ return err;
+ }
+ else if (value_type == SSL_CONF_TYPE_DIR) {
+ if ((err = ssl_cmd_check_dir(cmd, &arg2)))
+ return err;
+ }
+
+ param = apr_array_push(sc->server->ssl_ctx_param);
+ param->name = arg1;
+ param->value = arg2;
+ return NULL;
+}
+#endif
+
#ifdef HAVE_SRP
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg,
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index f6e010de7a..59a466b6d4 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -1287,12 +1287,62 @@ static void ssl_init_server_ctx(server_rec *s,
apr_pool_t *ptemp,
SSLSrvConfigRec *sc)
{
+#ifdef HAVE_SSL_CONF_CMD
+ ssl_ctx_param_t *param = (ssl_ctx_param_t *)sc->server->ssl_ctx_param->elts;
+ SSL_CONF_CTX *cctx = sc->server->ssl_ctx_config;
+ int i;
+#endif
+
ssl_init_server_check(s, p, ptemp, sc->server);
ssl_init_ctx(s, p, ptemp, sc->server);
ssl_init_server_certs(s, p, ptemp, sc->server);
+#ifdef HAVE_SSL_CONF_CMD
+ SSL_CONF_CTX_set_ssl_ctx(cctx, sc->server->ssl_ctx);
+ for (i = 0; i < sc->server->ssl_ctx_param->nelts; i++, param++) {
+ ERR_clear_error();
+ if (SSL_CONF_cmd(cctx, param->name, param->value) <= 0) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02407)
+ "\"SSLOpenSSLConfCmd %s %s\" failed for %s",
+ param->name, param->value, sc->vhost_id);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ ssl_die(s);
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02556)
+ "\"SSLOpenSSLConfCmd %s %s\" applied to %s",
+ param->name, param->value, sc->vhost_id);
+ }
+#ifdef HAVE_OCSP_STAPLING
+ /*
+ * Special case: if OCSP stapling is enabled, and a certificate
+ * has been loaded via "SSLOpenSSLConfCmd Certificate ...", then
+ * we also need to call ssl_stapling_init_cert here.
+ */
+ if ((sc->server->stapling_enabled == TRUE) &&
+ !strcasecmp(param->name, "Certificate")) {
+ X509 *cert = SSL_CTX_get0_certificate(sc->server->ssl_ctx);
+ if (!cert || !ssl_stapling_init_cert(s, sc->server, cert)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02571)
+ "Unable to configure certificate loaded "
+ "from %s for %s for stapling",
+ param->value, sc->vhost_id);
+ }
+ }
+#endif
+ }
+
+ if (SSL_CONF_CTX_finish(cctx) == 0) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02547)
+ "SSL_CONF_CTX_finish() failed");
+ SSL_CONF_CTX_free(cctx);
+ ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
+ ssl_die(s);
+ }
+ SSL_CONF_CTX_free(cctx);
+#endif
+
#ifdef HAVE_TLS_SESSION_TICKETS
ssl_init_ticket_key(s, p, ptemp, sc->server);
#endif
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 4ea924f339..af873ec634 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -131,6 +131,10 @@
#define HAVE_TLSV1_X
#endif
+#if defined(SSL_CONF_FLAG_FILE)
+#define HAVE_SSL_CONF_CMD
+#endif
+
/**
* The following features all depend on TLS extension support.
* Within this block, check again for features (not version numbers).
@@ -577,6 +581,13 @@ typedef struct {
} modssl_ticket_key_t;
#endif
+#ifdef HAVE_SSL_CONF_CMD
+typedef struct {
+ const char *name;
+ const char *value;
+} ssl_ctx_param_t;
+#endif
+
typedef struct SSLSrvConfigRec SSLSrvConfigRec;
typedef struct {
@@ -633,7 +644,10 @@ typedef struct {
long ocsp_resptime_skew;
long ocsp_resp_maxage;
apr_interval_time_t ocsp_responder_timeout;
-
+#ifdef HAVE_SSL_CONF_CMD
+ SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */
+ apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */
+#endif
} modssl_ctx_t;
struct SSLSrvConfigRec {
@@ -754,6 +768,10 @@ const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char
const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg);
const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag);
+#ifdef HAVE_SSL_CONF_CMD
+const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2);
+#endif
+
#ifdef HAVE_SRP
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg);
const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg);
--
2.40.0