MINOR: ssl: Add 'show ssl providers' cli command and providers list in -vv option
Starting from OpenSSLv3, providers are at the core of cryptography
functions. Depending on the provider used, the way the SSL
functionalities work could change. This new 'show ssl providers' CLI
command allows to show what providers were loaded by the SSL library.
This is required because the provider configuration is exclusively done
in the OpenSSL configuration file (/usr/local/ssl/openssl.cnf for
instance).
A new line is also added to the 'haproxy -vv' output containing the same
information.
diff --git a/doc/management.txt b/doc/management.txt
index f0fdcc0..d21bc45 100644
--- a/doc/management.txt
+++ b/doc/management.txt
@@ -3359,6 +3359,18 @@
Next Update: Oct 12 15:43:38 2048 GMT
[...]
+show ssl providers
+ Display the names of the providers loaded by OpenSSL during init. Provider
+ loading can indeed be configured via the OpenSSL configuration file and this
+ option allows to check that the right providers were loaded. This command is
+ only available with OpenSSL v3.
+
+ Example :
+ $ echo "show ssl providers" | socat /var/run/haproxy.master -
+ Loaded providers :
+ - fips
+ - base
+
show table
Dump general information on all known stick-tables. Their name is returned
(the name of the proxy which holds them), their type (currently zero, always
diff --git a/include/haproxy/openssl-compat.h b/include/haproxy/openssl-compat.h
index f69139b..5aaa6c7 100644
--- a/include/haproxy/openssl-compat.h
+++ b/include/haproxy/openssl-compat.h
@@ -28,6 +28,7 @@
#include <openssl/core_names.h>
#include <openssl/decoder.h>
#include <openssl/param_build.h>
+#include <openssl/provider.h>
#endif
#if defined(LIBRESSL_VERSION_NUMBER)
@@ -92,6 +93,9 @@
#define HASSL_DH EVP_PKEY
#define HASSL_DH_free EVP_PKEY_free
#define HASSL_DH_up_ref EVP_PKEY_up_ref
+
+#define HAVE_SSL_PROVIDERS
+
#else /* HA_OPENSSL_VERSION_NUMBER >= 0x3000000fL */
#define MAC_CTX HMAC_CTX
#define HASSL_DH DH
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index a7f232e..d823d92 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -7576,6 +7576,84 @@
#endif
}
+#ifdef HAVE_SSL_PROVIDERS
+struct provider_name {
+ const char *name;
+ struct list list;
+};
+
+
+static int ssl_provider_get_name_cb(OSSL_PROVIDER *provider, void *cbdata)
+{
+ struct list *provider_names = cbdata;
+ struct provider_name *item = NULL;
+ const char *name = OSSL_PROVIDER_get0_name(provider);
+
+ if (!provider_names)
+ return 0;
+
+ item = calloc(1, sizeof(*item));
+
+ if (!item)
+ return 0;
+
+ item->name = name;
+ LIST_APPEND(provider_names, &item->list);
+
+ return 1;
+}
+
+static void ssl_provider_get_name_list(struct list *provider_names)
+{
+ if (!provider_names)
+ return;
+
+ OSSL_PROVIDER_do_all(NULL, ssl_provider_get_name_cb, provider_names);
+}
+
+static void ssl_provider_clear_name_list(struct list *provider_names)
+{
+ struct provider_name *item = NULL, *item_s = NULL;
+
+ if (provider_names) {
+ list_for_each_entry_safe(item, item_s, provider_names, list) {
+ LIST_DELETE(&item->list);
+ free(item);
+ }
+ }
+}
+
+static int cli_io_handler_show_providers(struct appctx *appctx)
+{
+ struct buffer *trash = get_trash_chunk();
+ struct conn_stream *cs = appctx->owner;
+ struct list provider_names;
+ struct provider_name *name;
+
+ LIST_INIT(&provider_names);
+
+ chunk_appendf(trash, "Loaded providers : \n");
+
+ ssl_provider_get_name_list(&provider_names);
+
+ list_for_each_entry(name, &provider_names, list) {
+ chunk_appendf(trash, "\t- %s\n", name->name);
+ }
+
+ ssl_provider_clear_name_list(&provider_names);
+
+ if (ci_putchk(cs_ic(cs), trash) == -1) {
+ cs_rx_room_blk(cs);
+ goto yield;
+ }
+
+ return 1;
+
+yield:
+ return 0;
+}
+#endif
+
#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) && !defined OPENSSL_IS_BORINGSSL)
/*
@@ -7715,6 +7793,9 @@
{ { "set", "ssl", "ocsp-response", NULL }, "set ssl ocsp-response <resp|payload> : update a certificate's OCSP Response from a base64-encode DER", cli_parse_set_ocspresponse, NULL },
{ { "show", "ssl", "ocsp-response", NULL },"show ssl ocsp-response [id] : display the IDs of the OCSP responses used in memory, or the details of a single OCSP response", cli_parse_show_ocspresponse, cli_io_handler_show_ocspresponse, NULL },
+#ifdef HAVE_SSL_PROVIDERS
+ { { "show", "ssl", "providers", NULL }, "show ssl providers : show loaded SSL providers", NULL, cli_io_handler_show_providers },
+#endif
{ { NULL }, NULL, NULL, NULL }
}};
@@ -7998,6 +8079,23 @@
if (methodVersions[i].option)
memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
+#ifdef HAVE_SSL_PROVIDERS
+ {
+ struct list provider_names;
+ struct provider_name *name;
+ LIST_INIT(&provider_names);
+ ssl_provider_get_name_list(&provider_names);
+
+ memprintf(&ptr, "%s\nOpenSSL providers loaded :", ptr);
+
+ list_for_each_entry(name, &provider_names, list) {
+ memprintf(&ptr, "%s %s", ptr, name->name);
+ }
+
+ ssl_provider_clear_name_list(&provider_names);
+ }
+#endif
+
hap_register_build_opts(ptr, 1);
}