MINOR: ssl: support ssl-min-ver and ssl-max-ver with crt-list
SSL/TLS version can be changed per certificat if and only if openssl lib support
earlier callback on handshake and, of course, is implemented in haproxy. It's ok
for BoringSSL. For Openssl, version 1.1.1 have such callback and could support it.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 969734c..19c1132 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -10415,7 +10415,8 @@
<crtfile> [\[<sslbindconf> ...\]] [[!]<snifilter> ...]
sslbindconf support "npn", "alpn", "verify", "ca_file", "crl_file", "ecdhe",
- "curves", "ciphers" configuration.
+ "curves", "ciphers" configuration. With BoringSSL "ssl-min-ver" and
+ "ssl-max-ver" are also supported.
It override the configuration set in bind line for the certificate.
Wildcards are supported in the SNI filter. Negative filter are also supported,
diff --git a/include/types/listener.h b/include/types/listener.h
index 93f3662..9a77e96 100644
--- a/include/types/listener.h
+++ b/include/types/listener.h
@@ -124,6 +124,7 @@
char *ciphers; /* cipher suite to use if non-null */
char *curves; /* curves suite to use for ECDHE */
char *ecdhe; /* named curve to use for ECDHE */
+ struct tls_version_filter ssl_methods; /* ssl methods */
#endif
};
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 67fa2ae..776140f 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -2106,8 +2106,15 @@
node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
if (node) {
+ int min, max;
/* switch ctx */
ssl_sock_switchctx_set(ctx->ssl, container_of(node, struct sni_ctx, name)->ctx);
+ min = container_of(node, struct sni_ctx, name)->conf->ssl_methods.min;
+ if (min != s->ssl_methods.min)
+ methodVersions[min].ssl_set_version(ctx->ssl, SET_MIN);
+ max = container_of(node, struct sni_ctx, name)->conf->ssl_methods.max;
+ if (max != s->ssl_methods.max)
+ methodVersions[max].ssl_set_version(ctx->ssl, SET_MAX);
return 1;
}
if (!s->strict_sni) {
@@ -3572,6 +3579,9 @@
bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
cfgerr += 1;
}
+ /* save real min/max in bind_conf */
+ conf_ssl_methods->min = min;
+ conf_ssl_methods->max = max;
#if (OPENSSL_VERSION_NUMBER < 0x1010000fL) && !defined(OPENSSL_IS_BORINGSSL)
/* Keep force-xxx implementation as it is in older haproxy. It's a
@@ -3623,6 +3633,36 @@
const char *conf_ciphers;
const char *conf_curves = NULL;
+ if (ssl_conf) {
+ struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
+ int i, min, max;
+ int flags = MC_SSL_O_ALL;
+
+ /* Real min and max should be determinate with configuration and openssl's capabilities */
+ min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_methods.min;
+ max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_methods.max;
+ if (min)
+ flags |= (methodVersions[min].flag - 1);
+ if (max)
+ flags |= ~((methodVersions[max].flag << 1) - 1);
+ min = max = CONF_TLSV_NONE;
+ for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
+ if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
+ if (min)
+ max = i;
+ else
+ min = max = i;
+ }
+ /* save real min/max */
+ conf_ssl_methods->min = min;
+ conf_ssl_methods->max = max;
+ if (!min) {
+ Alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
+ bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
+ cfgerr += 1;
+ }
+ }
+
switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
case SSL_SOCK_VERIFY_NONE:
verify = SSL_VERIFY_NONE;
@@ -6641,6 +6681,14 @@
return 0;
}
+static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
+{
+#if !defined(OPENSSL_IS_BORINGSSL)
+ Warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
+#endif
+ return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
+}
+
static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
@@ -7831,6 +7879,8 @@
{ "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
{ "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
{ "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
+ { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
+ { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
{ "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
{ NULL, NULL, 0 },
};