MINOR: ssl: allow to change the server signature algorithm

This patch introduces the "sigalgs" keyword for the bind line, which
allows to configure the list of server signature algorithms negociated
during the handshake. Also available as "ssl-default-bind-sigalgs" in
the default section.

This patch was originally written by Bruno Henc.
This commit is contained in:
William Lallemand 2023-05-04 15:33:55 +02:00
parent e69919d1ba
commit 1d3c822300
7 changed files with 115 additions and 0 deletions

View File

@ -1097,6 +1097,7 @@ The following keywords are supported in the "global" section :
- ssl-default-bind-ciphersuites
- ssl-default-bind-curves
- ssl-default-bind-options
- ssl-default-bind-sigalgs
- ssl-default-server-ciphers
- ssl-default-server-ciphersuites
- ssl-default-server-options
@ -2183,6 +2184,22 @@ ssl-default-bind-options [<option>]...
global
ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets
ssl-default-bind-sigalgs <sigalgs>
This setting is only available when support for OpenSSL was built in. It
sets the default string describing the list of signature algorithms that
are negotiated during the TLSv1.2 and TLSv1.3 handshake for all "bind" lines
which do not explicitly define theirs. The format of the string is a
colon-delimited list of signature algorithms. Each signature algorithm can
use one of two forms: TLS1.3 signature scheme names ("rsa_pss_rsae_sha256")
or the public key algorithm + digest form ("ECDSA+SHA256"). A list
can contain both forms. For more information on the format,
see SSL_CTX_set1_sigalgs(3). A list of signature algorithms is also
available in RFC8446 section 4.2.3 and in OpenSSL in the ssl/t1_lib.c file.
This setting is not applicable to TLSv1.1 and earlier versions of the
protocol as the signature algorithms aren't separately negotiated in these
versions. It is not recommended to change this setting unless compatibility
with a middlebox is required.
ssl-default-server-ciphers <ciphers>
This setting is only available when support for OpenSSL was built in. It
sets the default string describing the list of cipher algorithms that are
@ -15330,6 +15347,14 @@ shards <number> | by-thread | by-group
warning will be emitted if this happens since the resulting number of
listeners will not be the expected one.
sigalgs <sigalgs>
This setting is only available when support for OpenSSL was built in. It sets
the string describing the list of signature algorithms that are negotiated
during the TLSv1.2 and TLSv1.3 handshake. The format of the string is defined
in "man 3 SSL_CTX_set1_sigalgs" from the OpenSSL man pages. It is not
recommended to use this setting unless compatibility with a middlebox is
required.
ssl
This setting is only available when support for OpenSSL was built in. It
enables SSL deciphering on connections instantiated from this listener. A

View File

@ -143,6 +143,7 @@ struct ssl_bind_conf {
char *ciphersuites; /* TLS 1.3 cipher suite to use if non-null */
char *curves; /* curves suite to use for ECDHE */
char *ecdhe; /* named curve to use for ECDHE */
char *sigalgs; /* Signature algorithms */
struct tls_version_filter ssl_methods_cfg; /* original ssl methods found in configuration */
struct tls_version_filter ssl_methods; /* actual ssl methods used at runtime */
#endif

View File

@ -520,5 +520,9 @@ static inline unsigned long ERR_peek_error_func(const char **func)
#define SSL_CTX_set1_curves_list SSL_CTX_set1_curves_list
#endif
#if !defined(SSL_CTX_set1_sigalgs_list) && defined(SSL_CTRL_SET_SIGALGS_LIST)
#define SSL_CTX_set1_sigalgs_list SSL_CTX_set1_sigalgs_list
#endif
#endif /* USE_OPENSSL */
#endif /* _HAPROXY_OPENSSL_COMPAT_H */

View File

@ -278,6 +278,9 @@ struct global_ssl {
#endif
#if defined(SSL_CTX_set1_curves_list)
char *listen_default_curves;
#endif
#if defined(SSL_CTX_set1_sigalgs_list)
char *listen_default_sigalgs;
#endif
int listen_default_ssloptions;
int connect_default_ssloptions;

View File

@ -316,6 +316,34 @@ static int ssl_parse_global_curves(char **args, int section_type, struct proxy *
return 0;
}
#endif
#if defined(SSL_CTX_set1_sigalgs_list)
/*
* parse the "ssl-default-bind-sigalgs" keyword in a global section.
* Returns <0 on alert, >0 on warning, 0 on success.
*/
static int ssl_parse_global_sigalgs(char **args, int section_type, struct proxy *curpx,
const struct proxy *defpx, const char *file, int line,
char **err)
{
char **target;
target = &global_ssl.listen_default_sigalgs;
if (too_many_args(1, args, err, NULL))
return -1;
if (*(args[1]) == 0) {
memprintf(err, "global statement '%s' expects a curves suite as an arguments.", args[0]);
return -1;
}
free(*target);
*target = strdup(args[1]);
return 0;
}
#endif
/* parse various global tune.ssl settings consisting in positive integers.
* Returns <0 on alert, >0 on warning, 0 on success.
*/
@ -798,6 +826,27 @@ static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct
return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, 0, err);
}
/* parse the "sigalgs" bind keyword */
static int ssl_bind_parse_sigalgs(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
{
#if defined(SSL_CTX_set1_sigalgs_list)
if (!*args[cur_arg + 1]) {
memprintf(err, "'%s' : missing signature algorithm list", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
conf->sigalgs = strdup(args[cur_arg + 1]);
return 0;
#else
memprintf(err, "'%s' : library does not support setting signature algorithms", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
#endif
}
static int bind_parse_sigalgs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
return ssl_bind_parse_sigalgs(args, cur_arg, px, &conf->ssl_conf, 0, err);
}
/* parse the "ecdhe" bind keyword keyword */
static int ssl_bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
{
@ -1153,6 +1202,10 @@ static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bin
if (global_ssl.listen_default_curves && !conf->ssl_conf.curves)
conf->ssl_conf.curves = strdup(global_ssl.listen_default_curves);
#endif
#if defined(SSL_CTX_set1_sigalgs_list)
if (global_ssl.listen_default_sigalgs && !conf->ssl_conf.sigalgs)
conf->ssl_conf.sigalgs = strdup(global_ssl.listen_default_sigalgs);
#endif
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
@ -2009,6 +2062,7 @@ struct ssl_crtlist_kw ssl_crtlist_kws[] = {
{ "no-alpn", ssl_bind_parse_no_alpn, 0 }, /* disable sending ALPN */
{ "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
{ "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
{ "sigalgs", ssl_bind_parse_sigalgs, 1 }, /* set SSL signature algorithms */
{ "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 */
@ -2050,6 +2104,7 @@ static struct bind_kw_list bind_kws = { "SSL", { }, {
{ "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
{ "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
{ "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
{ "sigalgs", bind_parse_sigalgs, 1 }, /* set SSL signature algorithms */
{ "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
{ "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
{ "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
@ -2152,6 +2207,9 @@ static struct cfg_kw_list cfg_kws = {ILH, {
#if defined(SSL_CTX_set1_curves_list)
{ CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves },
#endif
#if defined(SSL_CTX_set1_sigalgs_list)
{ CFG_GLOBAL, "ssl-default-bind-sigalgs", ssl_parse_global_sigalgs },
#endif
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
{ CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
{ CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },

View File

@ -74,6 +74,9 @@ void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
#endif
ha_free(&conf->curves);
ha_free(&conf->ecdhe);
#if defined(SSL_CTX_set1_sigalgs_list)
ha_free(&conf->sigalgs);
#endif
}
}
@ -151,6 +154,13 @@ struct ssl_bind_conf *crtlist_dup_ssl_conf(struct ssl_bind_conf *src)
dst->ssl_methods.min = src->ssl_methods.min;
dst->ssl_methods.max = src->ssl_methods.max;
#if defined(SSL_CTX_set1_sigalgs_list)
if (src->sigalgs) {
dst->sigalgs = strdup(src->sigalgs);
if (!dst->sigalgs)
goto error;
}
#endif
return dst;
error:

View File

@ -4570,6 +4570,9 @@ static int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_con
#endif
const char *conf_curves = NULL;
X509_STORE *store = SSL_CTX_get_cert_store(ctx);
#if defined(SSL_CTX_set1_sigalgs_list)
const char *conf_sigalgs = NULL;
#endif
if (ssl_conf) {
struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
@ -4772,6 +4775,17 @@ static int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_con
#endif /* HA_OPENSSL_VERSION_NUMBER >= 0x10101000L */
}
#if defined(SSL_CTX_set1_sigalgs_list)
conf_sigalgs = (ssl_conf && ssl_conf->sigalgs) ? ssl_conf->sigalgs : bind_conf->ssl_conf.sigalgs;
if (conf_sigalgs) {
if (!SSL_CTX_set1_sigalgs_list(ctx, conf_sigalgs)) {
memprintf(err, "%sProxy '%s': unable to set SSL Signature Algorithm list to '%s' for bind '%s' at [%s:%d].\n",
err && *err ? *err : "", curproxy->id, conf_sigalgs, bind_conf->arg, bind_conf->file, bind_conf->line);
cfgerr |= ERR_ALERT | ERR_FATAL;
}
}
#endif
return cfgerr;
}