diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2020-06-06 04:40:23 -0400 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2020-07-08 22:51:31 -0400 |
commit | 60ddaf26c4dc535d8f6bc69fc3e6fd306114f04c (patch) | |
tree | 5c02f03a1cd1e67fec37d215c3c6ea117f891bd2 | |
parent | 1ba36fda9385cb7bf52fd6f08f8c81491af0f522 (diff) | |
download | lighttpd-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.c | 208 |
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 */ |