From d26da0a7057cd0db563c12d2297a57e20528253d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 2 Jul 2026 03:47:06 +0900 Subject: [PATCH] crypto-util: make OpenSSL UI API symbols optional during dlopen Previously, if systemd was built with OpenSSL UI support, it would fail to load libcrypto at runtime if the library lacked UI support, requiring a recompilation of systemd to fix. Let's relax this strict requirement by making the UI methods optional during dlopen(). openssl_ui_supported() is added to dynamically check if all required UI symbols were successfully loaded. --- src/shared/crypto-util.c | 72 +++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/src/shared/crypto-util.c b/src/shared/crypto-util.c index f9e0c7f628..a6aa020bdc 100644 --- a/src/shared/crypto-util.c +++ b/src/shared/crypto-util.c @@ -628,23 +628,7 @@ int dlopen_libcrypto(int log_level) { DLSYM_ARG(i2d_PUBKEY), DLSYM_ARG(i2d_PublicKey), DLSYM_ARG(i2d_X509), - DLSYM_ARG(i2d_X509_NAME), -#ifndef OPENSSL_NO_UI_CONSOLE - DLSYM_ARG(UI_OpenSSL), - DLSYM_ARG(UI_create_method), - DLSYM_ARG(UI_destroy_method), - DLSYM_ARG(UI_get0_output_string), - DLSYM_ARG(UI_get_default_method), - DLSYM_ARG(UI_get_method), - DLSYM_ARG(UI_get_string_type), - DLSYM_ARG(UI_method_get_ex_data), - DLSYM_ARG(UI_method_get_reader), - DLSYM_ARG(UI_method_set_ex_data), - DLSYM_ARG(UI_method_set_reader), - DLSYM_ARG(UI_set_default_method), - DLSYM_ARG(UI_set_result), -#endif - NULL); + DLSYM_ARG(i2d_X509_NAME)); if (r >= 0) break; } @@ -653,6 +637,24 @@ int dlopen_libcrypto(int log_level) { return -EOPNOTSUPP; /* turn into recognizable error */ } +#ifndef OPENSSL_NO_UI_CONSOLE + /* Load UI API optionally so we don't fail to load libcrypto.so lacking UI support, + * even if systemd is built with UI support enabled in the headers. */ + DLSYM_OPTIONAL(libcrypto_dl, UI_OpenSSL); + DLSYM_OPTIONAL(libcrypto_dl, UI_create_method); + DLSYM_OPTIONAL(libcrypto_dl, UI_destroy_method); + DLSYM_OPTIONAL(libcrypto_dl, UI_get0_output_string); + DLSYM_OPTIONAL(libcrypto_dl, UI_get_default_method); + DLSYM_OPTIONAL(libcrypto_dl, UI_get_method); + DLSYM_OPTIONAL(libcrypto_dl, UI_get_string_type); + DLSYM_OPTIONAL(libcrypto_dl, UI_method_get_ex_data); + DLSYM_OPTIONAL(libcrypto_dl, UI_method_get_reader); + DLSYM_OPTIONAL(libcrypto_dl, UI_method_set_ex_data); + DLSYM_OPTIONAL(libcrypto_dl, UI_method_set_reader); + DLSYM_OPTIONAL(libcrypto_dl, UI_set_default_method); + DLSYM_OPTIONAL(libcrypto_dl, UI_set_result); +#endif + #if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_DEPRECATED_3_0) /* Load ENGINE API optionally so we don't fail when loading libcrypto.so.4 even if systemd is built * with openssl-3 headers. */ @@ -2104,10 +2106,33 @@ static int openssl_load_private_key_from_file(const char *path, EVP_PKEY **ret) return 0; } +static bool openssl_ui_supported(void) { +#ifndef OPENSSL_NO_UI_CONSOLE + return + sym_UI_OpenSSL && + sym_UI_create_method && + sym_UI_destroy_method && + sym_UI_get0_output_string && + sym_UI_get_default_method && + sym_UI_get_method && + sym_UI_get_string_type && + sym_UI_method_get_ex_data && + sym_UI_method_get_reader && + sym_UI_method_set_ex_data && + sym_UI_method_set_reader && + sym_UI_set_default_method && + sym_UI_set_result; +#else + return false; +#endif +} + OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) { if (!ui) return NULL; + assert(openssl_ui_supported()); + #ifndef OPENSSL_NO_UI_CONSOLE assert(sym_UI_get_default_method() == ui->method); sym_UI_set_default_method(sym_UI_OpenSSL()); @@ -2120,7 +2145,9 @@ OpenSSLAskPasswordUI* openssl_ask_password_ui_free(OpenSSLAskPasswordUI *ui) { static int openssl_ask_password_ui_read(UI *ui, UI_STRING *uis) { int r; - switch(sym_UI_get_string_type(uis)) { + assert(openssl_ui_supported()); + + switch (sym_UI_get_string_type(uis)) { case UIT_PROMPT: { /* If no ask password request was configured use the default openssl UI. */ AskPasswordRequest *req = (AskPasswordRequest*) sym_UI_method_get_ex_data(sym_UI_get_method(ui), 0); @@ -2158,6 +2185,12 @@ static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSS assert(request); assert(ret); + if (!openssl_ui_supported()) { + log_debug("OpenSSL UI API is not supported."); + *ret = NULL; + return 0; + } + #ifndef OPENSSL_NO_UI_CONSOLE _cleanup_(UI_destroy_methodp) UI_METHOD *method = sym_UI_create_method("systemd-ask-password"); if (!method) @@ -2183,8 +2216,7 @@ static int openssl_ask_password_ui_new(const AskPasswordRequest *request, OpenSS *ret = TAKE_PTR(ui); return 0; #else - *ret = NULL; - return 0; + assert_not_reached(); #endif }