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


Reply via email to