MINOR: ssl: allow to change the signature algorithm for client authentication
This commit introduces the keyword "client-sigalgs" for the bind line,
which does the same as "sigalgs" but for the client authentication.
"ssl-default-bind-client-sigalgs" allows to set the default parameter
for all the bind lines.
This patch should fix issue #2081.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 0111b61..7926b72 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -1095,6 +1095,7 @@
- setenv
- ssl-default-bind-ciphers
- ssl-default-bind-ciphersuites
+ - ssl-default-bind-client-sigalgs
- ssl-default-bind-curves
- ssl-default-bind-options
- ssl-default-bind-sigalgs
@@ -2168,6 +2169,21 @@
"ssl-default-bind-ciphers" keyword. Please check the "bind" keyword for more
information.
+ssl-default-bind-client-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 related to
+ client authentication 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_client_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-bind-curves <curves>
This setting is only available when support for OpenSSL was built in. It sets
the default string describing the list of elliptic curves algorithms ("curve
@@ -14809,6 +14825,13 @@
OpenSSL man pages under the "ciphersuites" section. For cipher configuration
for TLSv1.2 and earlier, please check the "ciphers" keyword.
+client-sigalgs <sigalgs>
+ This setting is only available when support for OpenSSL was built in. It sets
+ the string describing the list of signature algorithms related to client
+ authentication that are negotiated . The format of the string is defined in
+ "man 3 SSL_CTX_set1_client_sigalgs" from the OpenSSL man pages. It is not
+ recommended to use this setting if no specific usecase was identified.
+
crl-file <crlfile>
This setting is only available when support for OpenSSL was built in. It
designates a PEM file from which to load certificate revocation list used
diff --git a/include/haproxy/listener-t.h b/include/haproxy/listener-t.h
index ff5b30d..7384739 100644
--- a/include/haproxy/listener-t.h
+++ b/include/haproxy/listener-t.h
@@ -144,6 +144,7 @@
char *curves; /* curves suite to use for ECDHE */
char *ecdhe; /* named curve to use for ECDHE */
char *sigalgs; /* Signature algorithms */
+ char *client_sigalgs; /* Client 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
diff --git a/include/haproxy/ssl_sock-t.h b/include/haproxy/ssl_sock-t.h
index b4d3502..0b94a0e 100644
--- a/include/haproxy/ssl_sock-t.h
+++ b/include/haproxy/ssl_sock-t.h
@@ -282,6 +282,9 @@
#if defined(SSL_CTX_set1_sigalgs_list)
char *listen_default_sigalgs;
#endif
+#if defined(SSL_CTX_set1_sigalgs_list)
+ char *listen_default_client_sigalgs;
+#endif
int listen_default_ssloptions;
int connect_default_ssloptions;
struct tls_version_filter listen_default_sslmethods;
diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c
index 48e1450..42d7f40 100644
--- a/src/cfgparse-ssl.c
+++ b/src/cfgparse-ssl.c
@@ -344,6 +344,33 @@
}
#endif
+#if defined(SSL_CTX_set1_client_sigalgs_list)
+/*
+ * parse the "ssl-default-bind-client-sigalgs" keyword in a global section.
+ * Returns <0 on alert, >0 on warning, 0 on success.
+ */
+static int ssl_parse_global_client_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_client_sigalgs;
+
+ if (too_many_args(1, args, err, NULL))
+ return -1;
+
+ if (*(args[1]) == 0) {
+ memprintf(err, "global statement '%s' expects signature algorithms 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.
*/
@@ -846,6 +873,26 @@
return ssl_bind_parse_sigalgs(args, cur_arg, px, &conf->ssl_conf, 0, err);
}
+/* parse the "client-sigalgs" bind keyword */
+static int ssl_bind_parse_client_sigalgs(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, int from_cli, char **err)
+{
+#if defined(SSL_CTX_set1_client_sigalgs_list)
+ if (!*args[cur_arg + 1]) {
+ memprintf(err, "'%s' : missing signature algorithm list", args[cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ conf->client_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_client_sigalgs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
+{
+ return ssl_bind_parse_client_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)
@@ -2056,6 +2103,7 @@
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
{ "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
#endif
+ { "client-sigalgs", ssl_bind_parse_client_sigalgs, 1 }, /* set SSL client signature algorithms */
{ "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
{ "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
{ "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
@@ -2084,6 +2132,7 @@
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
{ "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
#endif
+ { "client-sigalgs", bind_parse_client_sigalgs, 1 }, /* set SSL client signature algorithms */
{ "crl-file", bind_parse_crl_file, 1 }, /* set certificate revocation list file use on client cert verify */
{ "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
{ "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth == 0 */
@@ -2210,6 +2259,9 @@
#if defined(SSL_CTX_set1_sigalgs_list)
{ CFG_GLOBAL, "ssl-default-bind-sigalgs", ssl_parse_global_sigalgs },
#endif
+#if defined(SSL_CTX_set1_client_sigalgs_list)
+ { CFG_GLOBAL, "ssl-default-bind-client-sigalgs", ssl_parse_global_client_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 },
diff --git a/src/ssl_crtlist.c b/src/ssl_crtlist.c
index 3d3ae40..9ea5ea0 100644
--- a/src/ssl_crtlist.c
+++ b/src/ssl_crtlist.c
@@ -77,6 +77,9 @@
#if defined(SSL_CTX_set1_sigalgs_list)
ha_free(&conf->sigalgs);
#endif
+#if defined(SSL_CTX_set1_client_sigalgs_list)
+ ha_free(&conf->client_sigalgs);
+#endif
}
}
@@ -161,6 +164,13 @@
goto error;
}
#endif
+#if defined(SSL_CTX_set1_client_sigalgs_list)
+ if (src->client_sigalgs) {
+ dst->client_sigalgs = strdup(src->client_sigalgs);
+ if (!dst->client_sigalgs)
+ goto error;
+ }
+#endif
return dst;
error:
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index b44b5ce..79ac2d6 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -4573,6 +4573,9 @@
#if defined(SSL_CTX_set1_sigalgs_list)
const char *conf_sigalgs = NULL;
#endif
+#if defined(SSL_CTX_set1_client_sigalgs_list)
+ const char *conf_client_sigalgs = NULL;
+#endif
if (ssl_conf) {
struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
@@ -4786,6 +4789,17 @@
}
#endif
+#if defined(SSL_CTX_set1_client_sigalgs_list)
+ conf_client_sigalgs = (ssl_conf && ssl_conf->client_sigalgs) ? ssl_conf->client_sigalgs : bind_conf->ssl_conf.client_sigalgs;
+ if (conf_client_sigalgs) {
+ if (!SSL_CTX_set1_client_sigalgs_list(ctx, conf_client_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_client_sigalgs, bind_conf->arg, bind_conf->file, bind_conf->line);
+ cfgerr |= ERR_ALERT | ERR_FATAL;
+ }
+ }
+#endif
+
return cfgerr;
}