]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl: allow to change the server signature algorithm on server lines
authorWilliam Lallemand <wlallemand@haproxy.org>
Thu, 29 Jun 2023 11:29:59 +0000 (13:29 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Thu, 29 Jun 2023 11:40:18 +0000 (13:40 +0200)
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.

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

index 8bcfc3c0640a8862974a53063004622cb0ba814b..d7f69514a34d4e81deb3055ae88915334f963e54 100644 (file)
@@ -1121,6 +1121,7 @@ The following keywords are supported in the "global" section :
    - ssl-default-server-ciphers
    - ssl-default-server-ciphersuites
    - ssl-default-server-options
+   - ssl-default-server-sigalgs
    - ssl-dh-param-file
    - ssl-propquery
    - ssl-provider
@@ -2279,6 +2280,22 @@ ssl-default-server-options [<option>]...
   default ssl-options to force on all "server" lines. Please check the "server"
   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>
   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
@@ -16536,6 +16553,13 @@ shard <shard>
        peer C 127.0.0.1:40003 shard 2
        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>
   The "slowstart" parameter for a server accepts a value in milliseconds which
index bdbde022f71e1ca8c7a96c001f0e7ee6db51c7aa..732098d4d99fa9406cbf0ee3963e9c0fee86e444 100644 (file)
@@ -392,6 +392,7 @@ struct server {
                char *ca_file;                  /* CAfile to use on verify */
                char *crl_file;                 /* CRLfile to use on verify */
                char *client_crt;               /* client certificate to send */
+               char *sigalgs;                  /* Signature algorithms */
                struct sample_expr *sni;        /* sample expression for SNI */
                char *npn_str;                  /* NPN protocol string */
                int npn_len;                    /* NPN protocol string length */
index 0b94a0eab4905a04bb87c58b17d67688bcd89951..3c87d844bf4ca7bedef836f369e84dd69fc68193 100644 (file)
@@ -281,6 +281,7 @@ struct global_ssl {
 #endif
 #if defined(SSL_CTX_set1_sigalgs_list)
        char *listen_default_sigalgs;
+       char *connect_default_sigalgs;
 #endif
 #if defined(SSL_CTX_set1_sigalgs_list)
        char *listen_default_client_sigalgs;
index 42d7f404b764c609fc22b5c214def9433ce1b582..8ed958eaae4dcace8cc4e7c8ca389e6e2ca970e9 100644 (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)
 /*
- * 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.
  */
 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;
 
-       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))
                return -1;
@@ -1653,6 +1653,14 @@ static int ssl_sock_init_srv(struct server *s)
        if (!s->ssl_ctx.methods.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;
 }
 
@@ -1832,6 +1840,29 @@ static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px,
        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 */
 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 */
        { "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 */
+       { "sigalgs",                 srv_parse_sigalgs,            1, 1, 1 }, /* signature algorithms */
        { "sni",                     srv_parse_sni,                1, 1, 1 }, /* send SNI extension */
        { "ssl",                     srv_parse_ssl,                0, 1, 1 }, /* enable SSL processing */
        { "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
 #if defined(SSL_CTX_set1_sigalgs_list)
        { CFG_GLOBAL, "ssl-default-bind-sigalgs", ssl_parse_global_sigalgs },
+       { CFG_GLOBAL, "ssl-default-server-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 },
index d075333a65c7304efcbe728c5e0974934a561ec4..61e988b60351eab376069993729d8ae478f4df50 100644 (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;
        int i, min, max, hole;
        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))
                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);
 #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;
 }