Hello Hyeonggeun, Sorry for the late feedback, the way it's done seems good, but I think we could improve the error messages a little bit, because that can be a bit obscur for users.
My comments below: On Sat, Jan 31, 2026 at 04:59:09PM +0900, Hyeonggeun Oh wrote: > Subject: [PATCH 1/1] MINOR: ssl: clarify error reporting for unsupported > keywords > This patch changes the registration of the following keywords to be > unconditional: > - ssl-dh-param-file > - ssl-engine > - ssl-propquery, ssl-provider, ssl-provider-path > - ssl-default-bind-curves, ssl-default-server-curves > - ssl-default-bind-sigalgs, ssl-default-server-sigalgs > - ssl-default-bind-client-sigalgs, ssl-default-server-client-sigalgs > > Instead of excluding them from the build, their parsing functions now > check for the required feature support. If the feature is missing, a > specific error message is returned, explaining that the SSL library > doesn't support it or that HAProxy was compiled with a flag disabling it. > > This addresses issue https://github.com/haproxy/haproxy/issues/3246. > --- > src/cfgparse-ssl.c | 65 ++++++++++++++++++++++++++++------------------ > 1 file changed, 40 insertions(+), 25 deletions(-) > > diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c > index 660f88b42..cc6d17a60 100644 > --- a/src/cfgparse-ssl.c > +++ b/src/cfgparse-ssl.c > @@ -143,7 +143,6 @@ static int ssl_parse_global_ssl_async(char **args, int > section_type, struct prox > #endif > } > > -#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE) > /* parse the "ssl-engine" keyword in global section. > * Returns <0 on alert, >0 on warning, 0 on success. > */ > @@ -151,6 +150,7 @@ static int ssl_parse_global_ssl_engine(char **args, int > section_type, struct pro > const struct proxy *defpx, const char > *file, int line, > char **err) > { > +#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE) > char *algo; > int ret = -1; > > @@ -184,10 +184,12 @@ static int ssl_parse_global_ssl_engine(char **args, int > section_type, struct pro > } > free(algo); > return ret; > -} > +#else > + memprintf(err, "'%s' is not supported (compiled without USE_ENGINE or > with OPENSSL_NO_ENGINE).", args[0]); > + return -1; > #endif > +} > > -#ifdef HAVE_SSL_PROVIDERS > /* parse the "ssl-propquery" keyword in global section. > * Returns <0 on alert, >0 on warning, 0 on success. > */ > @@ -195,6 +197,7 @@ static int ssl_parse_global_ssl_propquery(char **args, > int section_type, struct > const struct proxy *defpx, const char > *file, int line, > char **err) > { > +#ifdef HAVE_SSL_PROVIDERS > int ret = -1; > > if (*(args[1]) == 0) { > @@ -206,6 +209,10 @@ static int ssl_parse_global_ssl_propquery(char **args, > int section_type, struct > ret = 0; > > return ret; > +#else HAVE_SSL_PROVIDERS is define in the code, so you probably just need to say that it's not supported by the SSL library with something like: memprintf(err, "'%s' is not supported by %s", args[0], OpenSSL_version(OPENSSL_VERSION)); > + memprintf(err, "'%s' is not supported (compiled without > HAVE_SSL_PROVIDERS).", args[0]); > + return -1; > +#endif > } > > /* parse the "ssl-provider" keyword in global section. > @@ -215,6 +222,7 @@ static int ssl_parse_global_ssl_provider(char **args, int > section_type, struct p > const struct proxy *defpx, const char > *file, int line, > char **err) > { > +#ifdef HAVE_SSL_PROVIDERS > int ret = -1; > > if (*(args[1]) == 0) { > @@ -226,6 +234,10 @@ static int ssl_parse_global_ssl_provider(char **args, > int section_type, struct p > ret = 0; > > return ret; > +#else same thing there > + memprintf(err, "'%s' is not supported (compiled without > HAVE_SSL_PROVIDERS).", args[0]); > + return -1; > +#endif > } > > /* parse the "ssl-provider-path" keyword in global section. > @@ -235,6 +247,7 @@ static int ssl_parse_global_ssl_provider_path(char > **args, int section_type, str > const struct proxy *defpx, const > char *file, int line, > char **err) > { > +#ifdef HAVE_SSL_PROVIDERS > if (*(args[1]) == 0) { > memprintf(err, "global statement '%s' expects a directory path > as an argument.", args[0]); > return -1; > @@ -243,8 +256,11 @@ static int ssl_parse_global_ssl_provider_path(char > **args, int section_type, str > OSSL_PROVIDER_set_default_search_path(NULL, args[1]); > > return 0; > -} > +#else same there > + memprintf(err, "'%s' is not supported (compiled without > HAVE_SSL_PROVIDERS).", args[0]); > + return -1; > #endif > +} > > /* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" > keywords > * in global section. Returns <0 on alert, >0 on warning, 0 on success. > @@ -300,7 +316,6 @@ static int ssl_parse_global_ciphersuites(char **args, int > section_type, struct p > #endif > } > > -#if defined(SSL_CTX_set1_curves_list) > /* > * parse the "ssl-default-bind-curves" keyword in a global section. > * Returns <0 on alert, >0 on warning, 0 on success. > @@ -309,6 +324,7 @@ static int ssl_parse_global_curves(char **args, int > section_type, struct proxy * > const struct proxy *defpx, const char > *file, int line, > char **err) > { > +#if defined(SSL_CTX_set1_curves_list) > char **target; > target = (args[0][12] == 'b') ? &global_ssl.listen_default_curves : > &global_ssl.connect_default_curves; > > @@ -323,10 +339,12 @@ static int ssl_parse_global_curves(char **args, int > section_type, struct proxy * > free(*target); > *target = strdup(args[1]); > return 0; > -} > +#else That's a define in the code also, you can just use the same method as well > + memprintf(err, "'%s' is not supported (compiled without > SSL_CTX_set1_curves_list).", args[0]); > + return -1; > #endif > +} > > -#if defined(SSL_CTX_set1_sigalgs_list) > /* > * 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. > @@ -335,6 +353,7 @@ static int ssl_parse_global_sigalgs(char **args, int > section_type, struct proxy > const struct proxy *defpx, const char > *file, int line, > char **err) > { > +#if defined(SSL_CTX_set1_sigalgs_list) > char **target; > > target = (args[0][12] == 'b') ? &global_ssl.listen_default_sigalgs : > &global_ssl.connect_default_sigalgs; > @@ -350,10 +369,12 @@ static int ssl_parse_global_sigalgs(char **args, int > section_type, struct proxy > free(*target); > *target = strdup(args[1]); > return 0; > -} > +#else same there > + memprintf(err, "'%s' is not supported (compiled without > SSL_CTX_set1_sigalgs_list).", args[0]); > + return -1; > #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. > @@ -362,6 +383,7 @@ static int ssl_parse_global_client_sigalgs(char **args, > int section_type, struct > const struct proxy *defpx, const char > *file, int line, > char **err) > { > +#if defined(SSL_CTX_set1_client_sigalgs_list) > char **target; > > target = (args[0][12] == 'b') ? > &global_ssl.listen_default_client_sigalgs : > &global_ssl.connect_default_client_sigalgs; > @@ -377,8 +399,11 @@ static int ssl_parse_global_client_sigalgs(char **args, > int section_type, struct > free(*target); > *target = strdup(args[1]); > return 0; > -} > +#else same > + memprintf(err, "'%s' is not supported (compiled without > SSL_CTX_set1_client_sigalgs_list).", args[0]); > + return -1; > #endif > +} > > /* parse various global tune.ssl settings consisting in positive integers. > * Returns <0 on alert, >0 on warning, 0 on success. > @@ -575,7 +600,6 @@ static int ssl_parse_global_lifetime(char **args, int > section_type, struct proxy > return 0; > } > > -#ifndef OPENSSL_NO_DH > /* parse "ssl-dh-param-file". > * Returns <0 on alert, >0 on warning, 0 on success. > */ > @@ -583,6 +607,7 @@ static int ssl_parse_global_dh_param_file(char **args, > int section_type, struct > const struct proxy *defpx, const char > *file, int line, > char **err) > { > +#ifndef OPENSSL_NO_DH > if (too_many_args(1, args, err, NULL)) > return -1; > > @@ -596,9 +621,11 @@ static int ssl_parse_global_dh_param_file(char **args, > int section_type, struct > return -1; > } > return 0; > -} > - > +#else This one is a bit special because OPENSSL_NO_DH is a that can be configured on a OpenSSL build, but the haproxy sets it in certain case. So maybe a message like: "'%s' is not supported by %s (no DH support).", args[0], OpenSSL_version(OPENSSL_VERSION) > + memprintf(err, "'%s' is not supported by this SSL library (compiled > with OPENSSL_NO_DH).", args[0]); > + return -1; > #endif > +} > > /* parse "ssl.default-dh-param". > * Returns <0 on alert, >0 on warning, 0 on success. > @@ -2774,18 +2801,12 @@ static struct cfg_kw_list cfg_kws = {ILH, { > { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int }, > { CFG_GLOBAL, "ssl-default-bind-options", > ssl_parse_default_bind_options }, > { CFG_GLOBAL, "ssl-default-server-options", > ssl_parse_default_server_options }, > -#ifndef OPENSSL_NO_DH > { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file }, > -#endif > { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async }, > -#if defined(USE_ENGINE) && !defined(OPENSSL_NO_ENGINE) > { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine }, > -#endif > -#ifdef HAVE_SSL_PROVIDERS > { CFG_GLOBAL, "ssl-propquery", ssl_parse_global_ssl_propquery }, > { CFG_GLOBAL, "ssl-provider", ssl_parse_global_ssl_provider }, > { CFG_GLOBAL, "ssl-provider-path", ssl_parse_global_ssl_provider_path > }, > -#endif > { CFG_GLOBAL, "ssl-security-level", ssl_parse_security_level }, > { CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca > }, > { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int }, > @@ -2801,18 +2822,12 @@ static struct cfg_kw_list cfg_kws = {ILH, { > { CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog }, > { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers }, > { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers }, > -#if defined(SSL_CTX_set1_curves_list) > { CFG_GLOBAL, "ssl-default-bind-curves", ssl_parse_global_curves }, > { CFG_GLOBAL, "ssl-default-server-curves", ssl_parse_global_curves }, > -#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 }, > { CFG_GLOBAL, "ssl-default-server-client-sigalgs", > ssl_parse_global_client_sigalgs }, > -#endif > { CFG_GLOBAL, "ssl-default-bind-ciphersuites", > ssl_parse_global_ciphersuites }, > { CFG_GLOBAL, "ssl-default-server-ciphersuites", > ssl_parse_global_ciphersuites }, > { CFG_GLOBAL, "ssl-load-extra-files", ssl_parse_global_extra_files }, > -- > 2.48.1 > > > -- William Lallemand

