From 09c91eb59a6a6acc1bccd8cb03275e2228093b27 Mon Sep 17 00:00:00 2001 From: Frederic Lecaille Date: Mon, 18 May 2026 20:14:30 +0200 Subject: [PATCH] to be merged: add --tls-ciphers --tls-ciphersuites --tls-curves opts also improve the server options parsing (several options for the same --server opt), reuse this for the newly added tls opts --- include/haproxy/haload.h | 9 +-- src/haload.c | 67 +++++++++++++-------- src/haload_init.c | 124 +++++++++++++++++++++++++++++++++++---- 3 files changed, 160 insertions(+), 40 deletions(-) diff --git a/include/haproxy/haload.h b/include/haproxy/haload.h index b275b62ae..c5f3a000a 100644 --- a/include/haproxy/haload.h +++ b/include/haproxy/haload.h @@ -8,15 +8,16 @@ #include struct hld_path { - const char *path; + char *path; struct hld_path *next; }; struct hld_url_cfg { int ssl; - const char *addr; - const char *raw_addr; - char *ssl_opts; + char *addr; + char *raw_addr; + char *srv_opts; + char *tls_opts; struct server *srv; struct hld_path *paths; struct hld_url_cfg *next; diff --git a/src/haload.c b/src/haload.c index e01ae1205..14f0557db 100644 --- a/src/haload.c +++ b/src/haload.c @@ -1662,18 +1662,55 @@ static inline struct hld_usr *hld_new_usr(int nreqs) return NULL; } +/* Parse options for server */ +static int hld_srv_parse_opts(char *opts, struct server *s) +{ + int ret = 0; + size_t outlen = 256; + int cur_arg = 0; + char *outline; + uint32_t err; + int err_code; + int arg = sizeof(hld_args) / sizeof(*hld_args); + const char *errptr = NULL; + + outline = malloc(256); + if (!outline) + return 0; + + err = parse_line(opts, outline, &outlen, hld_args, &arg, + PARSE_OPT_ENV | PARSE_OPT_DQUOTE | + PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH | + PARSE_OPT_SHARP | PARSE_OPT_WORD_EXPAND, &errptr); + if (err) { + ha_alert("ssl opts parsing error\n"); + goto err; + } + + while (*hld_args[cur_arg]) { + err_code = _srv_parse_kw(s, hld_args, &cur_arg, &hld_proxy, 0); + if (err_code) + goto err; + } + + ret = 1; + leave: + free(outline); + return ret; + err: + goto leave; +} + static int hld_cfg_finalize(void) { int ret = 0; struct hld_url_cfg *cfg; - const char *errptr = NULL; for (cfg = hld_url_cfgs; cfg; cfg = cfg->next) { struct server *srv; struct sockaddr_storage *sk; int alt_proto, port; char *errmsg = NULL; - int arg = sizeof(hld_args) / sizeof(*hld_args); /* Same as _srv_parse_init() from here */ srv = new_server(&hld_proxy); @@ -1706,29 +1743,11 @@ static int hld_cfg_finalize(void) //srv_set_addr_desc(srv, 0); srv_settings_init(srv); - if (cfg->ssl_opts) { - size_t outlen = 256; - int cur_arg = 0; - char *outline = malloc(256); - uint32_t err; - int err_code; + if (cfg->srv_opts && !hld_srv_parse_opts(cfg->srv_opts, srv)) + goto leave; - err = parse_line(cfg->ssl_opts, outline, &outlen, hld_args, &arg, - PARSE_OPT_ENV | PARSE_OPT_DQUOTE | - PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH | - PARSE_OPT_SHARP | PARSE_OPT_WORD_EXPAND, &errptr); - if (err) { - ha_alert("ssl opts parsing error\n"); - goto leave; - } - - err_code = _srv_parse_kw(srv, hld_args, &cur_arg, &hld_proxy, 0); - if (err_code) - goto leave; - - free(outline); - } - /* Should parse server keywords here with _srv_parse_kw() */ + if (cfg->tls_opts && !hld_srv_parse_opts(cfg->tls_opts, srv)) + goto leave; /* Same as _srv_parse_finalize() from here */ if (srv_is_quic(srv)) { diff --git a/src/haload_init.c b/src/haload_init.c index 3f981b884..f5d42f42c 100644 --- a/src/haload_init.c +++ b/src/haload_init.c @@ -11,7 +11,7 @@ static int hld_debug; struct hld_url_cfg *hld_url_cfgs; -char *ssl_opts; +char *srv_opts, *tls_ciphers, *tls_ciphersuites, *tls_curves; static void hld_usage(char *name, int argc, int line) { @@ -31,10 +31,15 @@ static void hld_usage(char *name, int argc, int line) " -H \"foo:bar\" add this header name and value\n" " -I use HEAD instead of GET\n" " -v shows version\n" + " --default add a string to default section\n" " --global add a string to global section\n" " --server set server options as defined for \"server\" haproxy keyword\n" " --show-status-codes show HTTP status codes distribution\n" " --traces enable the traces for all the HTTP protocols\n" + "SSL options:\n" + " --tls-ciphers for TLS1.2 and below\n" + " --tls-ciphersuites for TLS1.3 and above\n" + " --tls-curves \n" "URL formats:\n" " (http|https)://:/ with any address as supported by haproxy\n" " (see haproxy documentation about addresses formats)\n", @@ -77,6 +82,59 @@ static struct hld_hdr *hld_parse_hdr(char *hdr_str) return hdr; } +static int hld_add_opt_to_buf(struct hbuf *buf, + const char *kw, const char *value) +{ + if (hbuf_is_null(buf)) { + if (hbuf_alloc(buf) == NULL) { + ha_alert("failed to allocate a buffer.\n"); + return 0; + } + } + else + hbuf_appendf(buf, " "); + + hbuf_appendf(buf, "%s", kw); + hbuf_appendf(buf, " "); + hbuf_appendf(buf, "%s", value); + return 1; +} + +static inline void hld_free_url_cfg(struct hld_url_cfg *h) +{ + free(h->addr); + free(h->srv_opts); + free(h->tls_opts); + free(h); +} + +static inline void hld_free_url_cfgs(void) +{ + struct hld_url_cfg *purl; + + purl = hld_url_cfgs; + + while (purl) { + struct hld_url_cfg *purl_next; + struct hld_path *path; + + path = purl->paths; + while (path) { + struct hld_path *path_next; + + path_next = path->next; + free(path->path); + free(path); + path = path_next; + } + + purl_next = purl->next; + + hld_free_url_cfg(purl); + purl = purl_next; + } +} + /* Allocate a URL from command line argument without * duplicating it, and append it to list of URL. * A URL is identified by its peer address and if it uses @@ -91,7 +149,8 @@ static struct hld_url_cfg *hld_alloc_url(char *url) char *addr = NULL, *raw_addr = NULL, *path = NULL; struct hld_url_cfg *hld_url_cfg = NULL; struct hld_url_cfg *purl; - struct hld_path *p; + struct hld_path *p = NULL; + struct hbuf opts_buf = HBUF_NULL; if (strncmp(url, "http://", 7) == 0) addr = url + 7; @@ -120,7 +179,7 @@ static struct hld_url_cfg *hld_alloc_url(char *url) /* Already existing URL with the same address. */ hld_url_cfg = purl; - p = malloc(sizeof(*p)); + p = calloc(1, sizeof(*p)); if (!p) goto err; @@ -143,7 +202,7 @@ static struct hld_url_cfg *hld_alloc_url(char *url) raw_addr = raw_addr ? raw_addr + 1: addr; - hld_url_cfg = malloc(sizeof(*hld_url_cfg)); + hld_url_cfg = calloc(1, sizeof(*hld_url_cfg)); p = malloc(sizeof(*p)); if (!hld_url_cfg || !p) goto err; @@ -155,13 +214,28 @@ static struct hld_url_cfg *hld_alloc_url(char *url) hld_url_cfg->addr = addr; hld_url_cfg->raw_addr = raw_addr; - if (ssl_opts) { - hld_url_cfg->ssl_opts = ssl_opts; - ssl_opts = NULL; + if (srv_opts) { + hld_url_cfg->srv_opts = strdup(srv_opts); + if (!hld_url_cfg->srv_opts) + goto err; } - else - hld_url_cfg->ssl_opts = NULL; + if (tls_ciphers && + !hld_add_opt_to_buf(&opts_buf, "ciphers", tls_ciphers)) + goto err; + + if (tls_ciphersuites && + !hld_add_opt_to_buf(&opts_buf, "ciphersuites", tls_ciphersuites)) + goto err; + + if (tls_curves && + !hld_add_opt_to_buf(&opts_buf, "curves", tls_curves)) + goto err; + + if (!hbuf_is_null(&opts_buf)) + hld_url_cfg->tls_opts = strdup(opts_buf.area); + + free_hbuf(&opts_buf); hld_url_cfg->srv = NULL; hld_url_cfg->paths = p; /* Append this new URL to the list */ @@ -170,7 +244,9 @@ static struct hld_url_cfg *hld_alloc_url(char *url) return hld_url_cfg; err: - free(addr); + hld_free_url_cfgs(); + hld_free_url_cfg(hld_url_cfg); + free(p); free(path); return NULL; } @@ -286,16 +362,40 @@ void haproxy_init_args(int argc, char **argv) } else if (strcmp(opt, "server") == 0) { argv++, argc--; - if ((argc <= 0 || **argv == '-')) hld_usage(progname, argc, __LINE__); opt = *argv; - ssl_opts = strdup(opt); + free(srv_opts); + srv_opts = strdup(opt); } else if (strcmp(opt, "show-status-codes") == 0) { arg_hscd = 1; } + else if (strcmp(opt, "tls-ciphers") == 0) { + argv++, argc--; + if ((argc <= 0 || **argv == '-')) + hld_usage(progname, argc, __LINE__); + opt = *argv; + free(tls_ciphers); + tls_ciphers = strdup(opt); + } + else if (strcmp(opt, "tls-ciphersuites") == 0) { + argv++, argc--; + if ((argc <= 0 || **argv == '-')) + hld_usage(progname, argc, __LINE__); + opt = *argv; + free(tls_ciphersuites); + tls_ciphersuites = strdup(opt); + } + else if (strcmp(opt, "tls-curves") == 0) { + argv++, argc--; + if ((argc <= 0 || **argv == '-')) + hld_usage(progname, argc, __LINE__); + opt = *argv; + free(tls_curves); + tls_curves = strdup(opt); + } else if (strcmp(opt, "traces") == 0) { hld_debug = 1; }