MINOR: ssl: allow to change the server signature algorithm on server lines

This patch introduces the "sigalgs" keyword for the server line, which
allows to configure the list of server signature algorithms negociated
during the handshake. Also available as "ssl-default-server-sigalgs" in
the global section.
This commit is contained in:
William Lallemand 2023-06-29 13:29:59 +02:00
parent f473eb7206
commit 717f0ad995
5 changed files with 75 additions and 2 deletions

View File

@ -1121,6 +1121,7 @@ The following keywords are supported in the "global" section :
- ssl-default-server-ciphers - ssl-default-server-ciphers
- ssl-default-server-ciphersuites - ssl-default-server-ciphersuites
- ssl-default-server-options - ssl-default-server-options
- ssl-default-server-sigalgs
- ssl-dh-param-file - ssl-dh-param-file
- ssl-propquery - ssl-propquery
- ssl-provider - ssl-provider
@ -2279,6 +2280,22 @@ ssl-default-server-options [<option>]...
default ssl-options to force on all "server" lines. Please check the "server" default ssl-options to force on all "server" lines. Please check the "server"
keyword to see available options. keyword to see available options.
ssl-default-server-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 "server" 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-dh-param-file <file> ssl-dh-param-file <file>
This setting is only available when support for OpenSSL was built in. It sets This setting is only available when support for OpenSSL was built in. It sets
the default DH parameters that are used during the SSL/TLS handshake when the default DH parameters that are used during the SSL/TLS handshake when
@ -16536,6 +16553,13 @@ shard <shard>
peer C 127.0.0.1:40003 shard 2 peer C 127.0.0.1:40003 shard 2
peer D 127.0.0.1:40004 shard 3 peer D 127.0.0.1:40004 shard 3
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.
slowstart <start_time_in_ms> slowstart <start_time_in_ms>
The "slowstart" parameter for a server accepts a value in milliseconds which The "slowstart" parameter for a server accepts a value in milliseconds which

View File

@ -392,6 +392,7 @@ struct server {
char *ca_file; /* CAfile to use on verify */ char *ca_file; /* CAfile to use on verify */
char *crl_file; /* CRLfile to use on verify */ char *crl_file; /* CRLfile to use on verify */
char *client_crt; /* client certificate to send */ char *client_crt; /* client certificate to send */
char *sigalgs; /* Signature algorithms */
struct sample_expr *sni; /* sample expression for SNI */ struct sample_expr *sni; /* sample expression for SNI */
char *npn_str; /* NPN protocol string */ char *npn_str; /* NPN protocol string */
int npn_len; /* NPN protocol string length */ int npn_len; /* NPN protocol string length */

View File

@ -281,6 +281,7 @@ struct global_ssl {
#endif #endif
#if defined(SSL_CTX_set1_sigalgs_list) #if defined(SSL_CTX_set1_sigalgs_list)
char *listen_default_sigalgs; char *listen_default_sigalgs;
char *connect_default_sigalgs;
#endif #endif
#if defined(SSL_CTX_set1_sigalgs_list) #if defined(SSL_CTX_set1_sigalgs_list)
char *listen_default_client_sigalgs; char *listen_default_client_sigalgs;

View File

@ -319,7 +319,7 @@ static int ssl_parse_global_curves(char **args, int section_type, struct proxy *
#if defined(SSL_CTX_set1_sigalgs_list) #if defined(SSL_CTX_set1_sigalgs_list)
/* /*
* parse the "ssl-default-bind-sigalgs" keyword in a global section. * parse the "ssl-default-bind-sigalgs" and "ssl-default-server-sigalgs" keyword in a global section.
* Returns <0 on alert, >0 on warning, 0 on success. * Returns <0 on alert, >0 on warning, 0 on success.
*/ */
static int ssl_parse_global_sigalgs(char **args, int section_type, struct proxy *curpx, static int ssl_parse_global_sigalgs(char **args, int section_type, struct proxy *curpx,
@ -328,7 +328,7 @@ static int ssl_parse_global_sigalgs(char **args, int section_type, struct proxy
{ {
char **target; char **target;
target = &global_ssl.listen_default_sigalgs; target = (args[0][12] == 'b') ? &global_ssl.listen_default_sigalgs : &global_ssl.connect_default_sigalgs;
if (too_many_args(1, args, err, NULL)) if (too_many_args(1, args, err, NULL))
return -1; return -1;
@ -1653,6 +1653,14 @@ static int ssl_sock_init_srv(struct server *s)
if (!s->ssl_ctx.methods.max) if (!s->ssl_ctx.methods.max)
s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max; s->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
#if defined(SSL_CTX_set1_sigalgs_list)
if (global_ssl.connect_default_sigalgs && !s->ssl_ctx.sigalgs) {
s->ssl_ctx.sigalgs = strdup(global_ssl.connect_default_sigalgs);
if (!s->ssl_ctx.sigalgs)
return 1;
}
#endif
return 0; return 0;
} }
@ -1832,6 +1840,29 @@ static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px,
return 0; return 0;
} }
/* parse the "sigalgs" server keyword */
static int srv_parse_sigalgs(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
{
#ifndef SSL_CTX_set1_sigalgs_list
memprintf(err, "'%s' : library does not support setting signature algorithms", args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
#else
char *arg;
arg = args[*cur_arg + 1];
if (!*arg) {
memprintf(err, "'%s' : missing signature algorithm list", args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
newsrv->ssl_ctx.sigalgs = strdup(arg);
if (!newsrv->ssl_ctx.sigalgs) {
memprintf(err, "out of memory");
return ERR_ALERT | ERR_FATAL;
}
return 0;
#endif
}
/* parse the "sni" server keyword */ /* parse the "sni" server keyword */
static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err) static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
{ {
@ -2206,6 +2237,7 @@ static struct srv_kw_list srv_kws = { "SSL", { }, {
{ "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */ { "npn", srv_parse_npn, 1, 1, 1 }, /* Set NPN supported protocols */
{ "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */ { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 1 }, /* send PROXY protocol header v2 with SSL info */
{ "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */ { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 1 }, /* send PROXY protocol header v2 with CN */
{ "sigalgs", srv_parse_sigalgs, 1, 1, 1 }, /* signature algorithms */
{ "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */ { "sni", srv_parse_sni, 1, 1, 1 }, /* send SNI extension */
{ "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */ { "ssl", srv_parse_ssl, 0, 1, 1 }, /* enable SSL processing */
{ "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */ { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 1 }, /* minimum version */
@ -2258,6 +2290,7 @@ static struct cfg_kw_list cfg_kws = {ILH, {
#endif #endif
#if defined(SSL_CTX_set1_sigalgs_list) #if defined(SSL_CTX_set1_sigalgs_list)
{ CFG_GLOBAL, "ssl-default-bind-sigalgs", ssl_parse_global_sigalgs }, { CFG_GLOBAL, "ssl-default-bind-sigalgs", ssl_parse_global_sigalgs },
{ CFG_GLOBAL, "ssl-default-server-sigalgs", ssl_parse_global_sigalgs },
#endif #endif
#if defined(SSL_CTX_set1_client_sigalgs_list) #if defined(SSL_CTX_set1_client_sigalgs_list)
{ CFG_GLOBAL, "ssl-default-bind-client-sigalgs", ssl_parse_global_client_sigalgs }, { CFG_GLOBAL, "ssl-default-bind-client-sigalgs", ssl_parse_global_client_sigalgs },

View File

@ -5047,6 +5047,10 @@ static int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx)
const struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods; const struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
int i, min, max, hole; int i, min, max, hole;
int flags = MC_SSL_O_ALL; int flags = MC_SSL_O_ALL;
#if defined(SSL_CTX_set1_sigalgs_list)
const char *conf_sigalgs = NULL;
#endif
if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max)) if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
ha_warning("no-sslv3/no-tlsv1x are ignored for this server. " ha_warning("no-sslv3/no-tlsv1x are ignored for this server. "
@ -5185,6 +5189,16 @@ static int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx)
SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len); SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
#endif #endif
#if defined(SSL_CTX_set1_sigalgs_list)
conf_sigalgs = srv->ssl_ctx.sigalgs;
if (conf_sigalgs) {
if (!SSL_CTX_set1_sigalgs_list(ctx, conf_sigalgs)) {
ha_alert("Proxy '%s': unable to set SSL Signature Algorithm list to '%s' for server '%s'.\n",
curproxy->id, conf_sigalgs, srv->id);
cfgerr++;
}
}
#endif
return cfgerr; return cfgerr;
} }