]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
crypto-util: make OpenSSL UI API symbols optional during dlopen
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 1 Jul 2026 18:47:06 +0000 (03:47 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 2 Jul 2026 18:02:57 +0000 (03:02 +0900)
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

index f9e0c7f628374f3abb6198235a4c4ecf53ec9cdd..a6aa020bdce14e55e05e980d1652aa12f37d98d9 100644 (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
 }