]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl: allow to change the signature algorithm for client authentication
authorWilliam Lallemand <wlallemand@haproxy.org>
Thu, 4 May 2023 22:05:46 +0000 (00:05 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Thu, 4 May 2023 22:05:46 +0000 (00:05 +0200)
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.

doc/configuration.txt
include/haproxy/listener-t.h
include/haproxy/ssl_sock-t.h
src/cfgparse-ssl.c
src/ssl_crtlist.c
src/ssl_sock.c

index 0111b6125aa8fe61c6f5c3025b26589a31f15495..7926b72efac6acfc7e1eceb881e7e612cb9763fe 100644 (file)
@@ -1095,6 +1095,7 @@ The following keywords are supported in the "global" section :
    - 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-ciphersuites <ciphersuites>
   "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 @@ ciphersuites <ciphersuites>
   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
index ff5b30da720f281abbd1932078667a296f92276f..7384739be17f613d8f4dc177ee61c59f2bcfe6fb 100644 (file)
@@ -144,6 +144,7 @@ struct ssl_bind_conf {
        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
index b4d350215e7245a04f2bb627d4630268b6ecaab4..0b94a0eab4905a04bb87c58b17d67688bcd89951 100644 (file)
@@ -281,6 +281,9 @@ struct global_ssl {
 #endif
 #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;
index 48e14508902d672e61de550b955d7185fd5dae5b..42d7f404b764c609fc22b5c214def9433ce1b582 100644 (file)
@@ -344,6 +344,33 @@ static int ssl_parse_global_sigalgs(char **args, int section_type, struct proxy
 }
 #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 @@ static int bind_parse_sigalgs(char **args, int cur_arg, struct proxy *px, struct
        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 @@ struct ssl_crtlist_kw ssl_crtlist_kws[] = {
 #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 @@ static struct bind_kw_list bind_kws = { "SSL", { }, {
 #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 @@ static struct cfg_kw_list cfg_kws = {ILH, {
 #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 },
index 3d3ae407e3efc284654df5613911c6a05d2f1c65..9ea5ea0e123d9135fbaf8f9fd845d238b2aed663 100644 (file)
@@ -76,6 +76,9 @@ void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
                ha_free(&conf->ecdhe);
 #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
        }
 }
@@ -160,6 +163,13 @@ struct ssl_bind_conf *crtlist_dup_ssl_conf(struct ssl_bind_conf *src)
                if (!dst->sigalgs)
                        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;
 
index b44b5ce9283e805dc89e7bc8dc284fc58c9f5c21..79ac2d66f44f88440d08ce0cacef696f27b7186b 100644 (file)
@@ -4573,6 +4573,9 @@ static int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_con
 #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 @@ static int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_con
        }
 #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;
 }