summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2017-11-04 21:39:30 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2017-11-04 21:45:33 -0400
commitc09acbeb8a030942d9825b3d0dd01c84e0a0b919 (patch)
tree5a526d0dccaf09da43cd176ab92a767aaff3b738
parent1a22ca87f91905a4efd903218348803b199b3956 (diff)
downloadlighttpd1.4-c09acbeb8a030942d9825b3d0dd01c84e0a0b919.tar.gz
lighttpd1.4-c09acbeb8a030942d9825b3d0dd01c84e0a0b919.zip
[mod_openssl] ssl.openssl.ssl-conf-cmd (fixes #2758)
(similar to Apache mod_ssl SSLOpenSSLConfCmd directive) (experimental) This new directive is for use with OpenSSL only, and is not currently available in LibreSSL. https://wiki.openssl.org/index.php/Manual:SSL_CONF_cmd(3) lighttpd takes "file commands" not "command line commands" as openssl SSL_CONF_cmd() appears to permit only one mode at a time. lighttpd processes this directive after all other ssl.* directives have been applied for the $SERVER["socket"] scope. x-ref: "Option to disable TLS session tickets" https://redmine.lighttpd.net/issues/2758 "Allow to selectively disable TLS 1.0, 1.1 and 1.2 versions" https://github.com/lighttpd/lighttpd1.4/pull/84 github: closes #84
-rw-r--r--src/mod_openssl.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/src/mod_openssl.c b/src/mod_openssl.c
index 6001b3fd..88520edb 100644
--- a/src/mod_openssl.c
+++ b/src/mod_openssl.c
@@ -62,6 +62,7 @@ typedef struct {
buffer *ssl_cipher_list;
buffer *ssl_dh_file;
buffer *ssl_ec_curve;
+ array *ssl_conf_cmd;
} plugin_config;
typedef struct {
@@ -129,6 +130,8 @@ FREE_FUNC(mod_openssl_free)
buffer_free(s->ssl_dh_file);
buffer_free(s->ssl_ec_curve);
buffer_free(s->ssl_verifyclient_username);
+ array_free(s->ssl_conf_cmd);
+
if (copy) continue;
SSL_CTX_free(s->ssl_ctx);
EVP_PKEY_free(s->ssl_pemfile_pkey);
@@ -489,6 +492,62 @@ network_openssl_load_pemfile (server *srv, plugin_config *s, size_t ndx)
static int
+network_openssl_ssl_conf_cmd (server *srv, plugin_config *s)
+{
+ #ifdef SSL_CONF_FLAG_CMDLINE
+
+ int rc = 0;
+ data_string *ds;
+ SSL_CONF_CTX * const cctx = SSL_CONF_CTX_new();
+ SSL_CONF_CTX_set_ssl_ctx(cctx, s->ssl_ctx);
+ SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE
+ | SSL_CONF_FLAG_SERVER
+ | SSL_CONF_FLAG_SHOW_ERRORS
+ | SSL_CONF_FLAG_CERTIFICATE);
+
+ /* always disable null and export ciphers */
+ ds = (data_string *)
+ array_get_element_klen(s->ssl_conf_cmd,
+ CONST_STR_LEN("CipherString"));
+ if (NULL != ds) {
+ buffer_append_string_len(ds->value,
+ CONST_STR_LEN(":!aNULL:!eNULL:!EXP"));
+ }
+
+ for (size_t i = 0; i < s->ssl_conf_cmd->used; ++i) {
+ ds = (data_string *)s->ssl_conf_cmd->data[i];
+ ERR_clear_error();
+ if (SSL_CONF_cmd(cctx, ds->key->ptr, ds->value->ptr) <= 0) {
+ log_error_write(srv, __FILE__, __LINE__, "ssbbss", "SSL:",
+ "SSL_CONF_cmd", ds->key, ds->value, ":",
+ ERR_error_string(ERR_get_error(), NULL));
+ rc = -1;
+ break;
+ }
+ }
+
+ if (0 == rc && 1 != SSL_CONF_CTX_finish(cctx)) {
+ log_error_write(srv, __FILE__, __LINE__, "sss", "SSL:",
+ "SSL_CONF_CTX_finish():",
+ ERR_error_string(ERR_get_error(), NULL));
+ rc = -1;
+ }
+
+ SSL_CONF_CTX_free(cctx);
+ return rc;
+
+ #else
+
+ UNUSED(s);
+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ "ssl.openssl.ssl-conf-cmd not available; ignored");
+ return 0;
+
+ #endif
+}
+
+
+static int
network_init_ssl (server *srv, void *p_d)
{
plugin_data *p = p_d;
@@ -883,6 +942,10 @@ network_init_ssl (server *srv, void *p_d)
return -1;
}
#endif
+
+ if (s->ssl_conf_cmd->used) {
+ if (0 != network_openssl_ssl_conf_cmd(srv, s)) return -1;
+ }
}
return 0;
@@ -913,6 +976,7 @@ SETDEFAULTS_FUNC(mod_openssl_set_defaults)
{ "ssl.use-sslv3", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
{ "ssl.ca-crl-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
{ "ssl.ca-dn-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
+ { "ssl.openssl.ssl-conf-cmd", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
@@ -947,6 +1011,9 @@ SETDEFAULTS_FUNC(mod_openssl_set_defaults)
: p->config_storage[0]->ssl_read_ahead;
if (0 != i) buffer_copy_buffer(s->ssl_ca_crl_file, p->config_storage[0]->ssl_ca_crl_file);
if (0 != i) buffer_copy_buffer(s->ssl_ca_dn_file, p->config_storage[0]->ssl_ca_dn_file);
+ s->ssl_conf_cmd = (0 == i)
+ ? array_init()
+ : array_init_array(p->config_storage[0]->ssl_conf_cmd);
cv[0].destination = &(s->ssl_log_noise);
cv[1].destination = &(s->ssl_enabled);
@@ -968,6 +1035,7 @@ SETDEFAULTS_FUNC(mod_openssl_set_defaults)
cv[17].destination = &(s->ssl_use_sslv3);
cv[18].destination = s->ssl_ca_crl_file;
cv[19].destination = s->ssl_ca_dn_file;
+ cv[20].destination = s->ssl_conf_cmd;
p->config_storage[i] = s;
@@ -997,6 +1065,12 @@ SETDEFAULTS_FUNC(mod_openssl_set_defaults)
"ssl.engine is valid only in global scope "
"or $SERVER[\"socket\"] condition");
}
+
+ if (!array_is_kvstring(s->ssl_conf_cmd)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ssl.openssl.ssl-conf-cmd must be array "
+ "of \"key\" => \"value\" strings");
+ }
}
if (0 != network_init_ssl(srv, p)) return HANDLER_ERROR;
@@ -1027,6 +1101,7 @@ mod_openssl_patch_connection (server *srv, connection *con, handler_ctx *hctx)
/*PATCH(ssl_empty_fragments);*//*(not patched)*/
/*PATCH(ssl_use_sslv2);*//*(not patched)*/
/*PATCH(ssl_use_sslv3);*//*(not patched)*/
+ /*PATCH(ssl_conf_cmd);*//*(not patched)*/
PATCH(ssl_verifyclient);
PATCH(ssl_verifyclient_enforce);
@@ -1095,6 +1170,8 @@ mod_openssl_patch_connection (server *srv, connection *con, handler_ctx *hctx)
PATCH(ssl_ec_curve);
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) {
PATCH(ssl_enabled);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.openssl.ssl-conf-cmd"))) {
+ PATCH(ssl_conf_cmd);
#endif
}
}