summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2020-06-06 04:40:23 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2020-07-08 22:51:31 -0400
commit60ddaf26c4dc535d8f6bc69fc3e6fd306114f04c (patch)
tree5c02f03a1cd1e67fec37d215c3c6ea117f891bd2
parent1ba36fda9385cb7bf52fd6f08f8c81491af0f522 (diff)
downloadlighttpd-git-60ddaf26c4dc535d8f6bc69fc3e6fd306114f04c.tar.gz
[mod_openssl] basic SSL_CONF_cmd for alt TLS libs
provide *basic* (limited) parsing of ssl.openssl.ssl-conf-cmd for BoringSSL, LibreSSL, WolfSSL
-rw-r--r--src/mod_openssl.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/mod_openssl.c b/src/mod_openssl.c
index 6d5f6d7b..e8dca1cc 100644
--- a/src/mod_openssl.c
+++ b/src/mod_openssl.c
@@ -1520,6 +1520,14 @@ mod_openssl_alpn_select_cb (SSL *ssl, const unsigned char **out, unsigned char *
#endif /* OPENSSL_NO_TLSEXT */
+#if defined(BORINGSSL_API_VERSION) \
+ || defined(LIBRESSL_VERSION_NUMBER) \
+ || defined(WOLFSSL_VERSION)
+static int
+mod_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s);
+#endif
+
+
static int
network_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s)
{
@@ -1567,6 +1575,12 @@ network_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s)
SSL_CONF_CTX_free(cctx);
return rc;
+ #elif defined(BORINGSSL_API_VERSION) \
+ || defined(LIBRESSL_VERSION_NUMBER) \
+ || defined(WOLFSSL_VERSION)
+
+ return mod_openssl_ssl_conf_cmd(srv, s);
+
#else
UNUSED(s);
@@ -3183,3 +3197,197 @@ int mod_openssl_plugin_init (plugin *p)
return 0;
}
+
+
+#if defined(BORINGSSL_API_VERSION) \
+ || defined(LIBRESSL_VERSION_NUMBER) \
+ || defined(WOLFSSL_VERSION)
+
+static int
+mod_openssl_ssl_conf_proto_val (server *srv, plugin_config_socket *s, const buffer *b, int max)
+{
+ if (NULL == b) /* default: min TLSv1.2, max TLSv1.3 */
+ #ifdef TLS1_3_VERSION
+ return max ? TLS1_3_VERSION : TLS1_2_VERSION;
+ #else
+ return TLS1_2_VERSION;
+ #endif
+ else if (buffer_eq_icase_slen(b, CONST_STR_LEN("None"))) /*"disable" limit*/
+ return max
+ ?
+ #ifdef TLS1_3_VERSION
+ TLS1_3_VERSION
+ #else
+ TLS1_2_VERSION
+ #endif
+ : (s->ssl_use_sslv3 ? SSL3_VERSION : TLS1_VERSION);
+ else if (buffer_eq_icase_slen(b, CONST_STR_LEN("SSLv3")))
+ return SSL3_VERSION;
+ else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.0")))
+ return TLS1_VERSION;
+ else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.1")))
+ return TLS1_1_VERSION;
+ else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.2")))
+ return TLS1_2_VERSION;
+ #ifdef TLS1_3_VERSION
+ else if (buffer_eq_icase_slen(b, CONST_STR_LEN("TLSv1.3")))
+ return TLS1_3_VERSION;
+ #endif
+ else {
+ if (buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1"))
+ || buffer_eq_icase_slen(b, CONST_STR_LEN("DTLSv1.2")))
+ log_error(srv->errh, __FILE__, __LINE__,
+ "SSL: ssl.openssl.ssl-conf-cmd %s %s ignored",
+ max ? "MaxProtocol" : "MinProtocol", b->ptr);
+ else
+ log_error(srv->errh, __FILE__, __LINE__,
+ "SSL: ssl.openssl.ssl-conf-cmd %s %s invalid; ignored",
+ max ? "MaxProtocol" : "MinProtocol", b->ptr);
+ }
+ #ifdef TLS1_3_VERSION
+ return max ? TLS1_3_VERSION : TLS1_2_VERSION;
+ #else
+ return TLS1_2_VERSION;
+ #endif
+}
+
+
+static int
+mod_openssl_ssl_conf_cmd (server *srv, plugin_config_socket *s)
+{
+ /* reference:
+ * https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html */
+ int rc = 0;
+ buffer *cipherstring = NULL;
+ /*buffer *ciphersuites = NULL;*/
+ buffer *minb = NULL;
+ buffer *maxb = NULL;
+ buffer *curves = NULL;
+
+ for (size_t i = 0; i < s->ssl_conf_cmd->used; ++i) {
+ data_string *ds = (data_string *)s->ssl_conf_cmd->data[i];
+ if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("CipherString")))
+ cipherstring = &ds->value;
+ #if 0
+ else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Ciphersuites")))
+ ciphersuites = &ds->value;
+ #endif
+ else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Curves"))
+ || buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Groups")))
+ curves = &ds->value;
+ else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MaxProtocol")))
+ maxb = &ds->value;
+ else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("MinProtocol")))
+ minb = &ds->value;
+ else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Protocol"))) {
+ /* openssl config for Protocol=... is complex and deprecated */
+ log_error(srv->errh, __FILE__, __LINE__,
+ "SSL: ssl.openssl.ssl-conf-cmd %s ignored; "
+ "use MinProtocol=... and MaxProtocol=... instead",
+ ds->key.ptr);
+ }
+ else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("Options"))) {
+ for (char *v = ds->value.ptr, *e; *v; v = e) {
+ while (*v == ' ' || *v == '\t' || *v == ',') ++v;
+ int flag = 1;
+ if (*v == '-') {
+ flag = 0;
+ ++v;
+ }
+ for (e = v; light_isalpha(*e); ++e) ;
+ switch ((int)(e-v)) {
+ case 11:
+ if (buffer_eq_icase_ssn(v, "Compression", 11)) {
+ if (flag)
+ SSL_CTX_clear_options(s->ssl_ctx,
+ SSL_OP_NO_COMPRESSION);
+ else
+ SSL_CTX_set_options(s->ssl_ctx,
+ SSL_OP_NO_COMPRESSION);
+ continue;
+ }
+ break;
+ case 13:
+ if (buffer_eq_icase_ssn(v, "SessionTicket", 13)) {
+ if (flag)
+ SSL_CTX_clear_options(s->ssl_ctx,
+ SSL_OP_NO_TICKET);
+ else
+ SSL_CTX_set_options(s->ssl_ctx,
+ SSL_OP_NO_TICKET);
+ continue;
+ }
+ break;
+ case 16:
+ if (buffer_eq_icase_ssn(v, "ServerPreference", 16)) {
+ if (flag)
+ SSL_CTX_set_options(s->ssl_ctx,
+ SSL_OP_CIPHER_SERVER_PREFERENCE);
+ else
+ SSL_CTX_clear_options(s->ssl_ctx,
+ SSL_OP_CIPHER_SERVER_PREFERENCE);
+ s->ssl_honor_cipher_order = flag;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ /* warn if not explicitly handled or ignored above */
+ if (!flag) --v;
+ log_error(srv->errh, __FILE__, __LINE__,
+ "SSL: ssl.openssl.ssl-conf-cmd Options %.*s "
+ "ignored", (int)(e-v), v);
+ }
+ }
+ #if 0
+ else if (buffer_eq_icase_slen(&ds->key, CONST_STR_LEN("..."))) {
+ }
+ #endif
+ else {
+ /* warn if not explicitly handled or ignored above */
+ log_error(srv->errh, __FILE__, __LINE__,
+ "SSL: ssl.openssl.ssl-conf-cmd %s ignored",
+ ds->key.ptr);
+ }
+
+ }
+
+ if (minb) {
+ /*(wolfSSL_CTX_SetMinVersion() alt uses enums with different values)*/
+ int n = mod_openssl_ssl_conf_proto_val(srv, s, minb, 0);
+ if (!SSL_CTX_set_min_proto_version(s->ssl_ctx, n))
+ rc = -1;
+ }
+
+ if (maxb) {
+ #ifndef WOLFSSL_VERSION /*WolfSSL max ver is set at WolfSSL compile-time*/
+ int x = mod_openssl_ssl_conf_proto_val(srv, s, maxb, 1);
+ if (!SSL_CTX_set_max_proto_version(s->ssl_ctx, x))
+ rc = -1;
+ #endif
+ }
+
+ if (cipherstring) {
+ /* Disable support for low encryption ciphers */
+ buffer_append_string_len(cipherstring,
+ CONST_STR_LEN(":!aNULL:!eNULL:!EXP"));
+ if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
+ log_error(srv->errh, __FILE__, __LINE__,
+ "SSL: %s", ERR_error_string(ERR_get_error(), NULL));
+ rc = -1;
+ }
+
+ if (s->ssl_honor_cipher_order)
+ SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
+ }
+
+ if (curves) {
+ if (!mod_openssl_ssl_conf_curves(srv, s, curves))
+ rc = -1;
+ }
+
+ return rc;
+}
+
+#endif /* BORINGSSL_API_VERSION || LIBRESSL_VERSION_NUMBER || WOLFSSL_VERSION */