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.
This commit is contained in:
Yu Watanabe
2026-07-03 03:02:57 +09:00
parent 805f8c6503
commit d26da0a705
+52 -20
View File
@@ -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
}