]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: load libcrypto/libssl lazily on first use and make them optional 42681/head
authorLuca Boccassi <luca.boccassi@gmail.com>
Sun, 21 Jun 2026 09:42:02 +0000 (10:42 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Mon, 22 Jun 2026 09:56:10 +0000 (10:56 +0100)
Currently they are marked as required, as resolved aborts on startup if
dns-over-tls is built in, even if it is not enabled in the config.
Change initialization to be done lazily on first use, so that if the
config is not enabled, it never runs, and the libraries are never
dlopened, so they can be downgraded to recommends.

src/resolve/resolved-dns-dnssec.c
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dnstls.c
src/resolve/resolved-manager.c
src/resolve/resolved-util.h

index d987ee4fa4a229d87803646ebc526264bf3bcd71..36eb3595d5becfe432d5df3e394f52aced7a33e2 100644 (file)
@@ -12,7 +12,6 @@
 #include "memory-util.h"
 #include "memstream-util.h"
 #include "resolved-dns-dnssec.h"
-#include "resolved-util.h"
 #include "sort-util.h"
 #include "string-table.h"
 #include "string-util.h"
@@ -717,7 +716,7 @@ int dnssec_verify_rrset(
         assert(dnskey);
         assert(result);
 
-        r = DLOPEN_LIBCRYPTO(LOG_DEBUG, DLOPEN_LIBCRYPTO_PRIORITY);
+        r = DLOPEN_LIBCRYPTO(LOG_WARNING, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED);
         if (r < 0)
                 return r;
 
@@ -1074,7 +1073,7 @@ int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds,
         assert(dnskey);
         assert(ds);
 
-        r = DLOPEN_LIBCRYPTO(LOG_DEBUG, DLOPEN_LIBCRYPTO_PRIORITY);
+        r = DLOPEN_LIBCRYPTO(LOG_WARNING, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED);
         if (r < 0)
                 return r;
 
@@ -1214,7 +1213,7 @@ int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
         assert(name);
         assert(ret);
 
-        r = DLOPEN_LIBCRYPTO(LOG_DEBUG, DLOPEN_LIBCRYPTO_PRIORITY);
+        r = DLOPEN_LIBCRYPTO(LOG_WARNING, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED);
         if (r < 0)
                 return r;
 
index a14aa0de7dbf609fc1cb66d92cdce516c340afcc..4268cd3ff08714af9049be888742ea8cadc3dfde 100644 (file)
@@ -786,8 +786,20 @@ static int dns_transaction_emit_tcp(DnsTransaction *t) {
 
                         assert(t->server);
                         r = dnstls_stream_connect_tls(s, t->server);
-                        if (r < 0)
+                        if (r < 0) {
+                                /* If libcrypto is not available treat this like a TLS connection loss, so
+                                 * that opportunistic DNS-over-TLS downgrades to plaintext instead of
+                                 * re-selecting a TLS feature level and failing on every attempt. */
+                                if (r == -EOPNOTSUPP) {
+                                        log_struct_once(LOG_WARNING,
+                                                        LOG_MESSAGE_ID(SD_MESSAGE_MISSING_DEPENDENCY_STR),
+                                                        LOG_ITEM("FEATURE=DNS-over-TLS"),
+                                                        LOG_MESSAGE("DNS-over-TLS has been requested but the required TLS libraries (libssl/libcrypto) are not installed."));
+                                        dns_server_packet_lost(t->server, IPPROTO_TCP, t->current_feature_level);
+                                        return -ECONNREFUSED;
+                                }
                                 return r;
+                        }
                 }
 #endif
 
index 6f489ae3bdb9845c29316c8f0f5cd0766dd6b4b3..6bcbdb526023faa0ae98a92f04856ad68271dd12 100644 (file)
@@ -71,6 +71,10 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
         assert(stream->manager);
         assert(server);
 
+        r = dnstls_manager_init(stream->manager);
+        if (r < 0)
+                return r;
+
         rb = sym_BIO_new_socket(stream->fd, 0);
         if (!rb)
                 return -ENOMEM;
@@ -398,31 +402,39 @@ void dnstls_server_free(DnsServer *server) {
 }
 
 int dnstls_manager_init(Manager *manager) {
+        _cleanup_(SSL_CTX_freep) SSL_CTX *ctx = NULL;
         int r;
 
         assert(manager);
 
-        r = DLOPEN_LIBCRYPTO(LOG_WARNING, SD_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED);
+        /* Load libcrypto/libssl on first use, so that the dependencies can be optional. */
+
+        if (manager->dnstls_data.ctx)
+                return 0;
+
+        r = DLOPEN_LIBCRYPTO(LOG_WARNING, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED);
         if (r < 0)
                 return r;
 
-        r = DLOPEN_LIBSSL(LOG_WARNING, SD_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED);
+        r = DLOPEN_LIBSSL(LOG_WARNING, SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED);
         if (r < 0)
                 return r;
 
-        manager->dnstls_data.ctx = sym_SSL_CTX_new(sym_TLS_client_method());
-        if (!manager->dnstls_data.ctx)
+        ctx = sym_SSL_CTX_new(sym_TLS_client_method());
+        if (!ctx)
                 return log_openssl_errors(LOG_WARNING, "Failed to create SSL context");
 
-        r = sym_SSL_CTX_set_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION);
+        r = sym_SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
         if (r == 0)
                 return log_openssl_errors(LOG_WARNING, "Failed to set protocol version on SSL context");
 
-        (void) sym_SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION);
+        (void) sym_SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
 
-        r = sym_SSL_CTX_set_default_verify_paths(manager->dnstls_data.ctx);
+        r = sym_SSL_CTX_set_default_verify_paths(ctx);
         if (r == 0)
                 return log_openssl_errors(LOG_WARNING, "Failed to load system trust store");
+
+        manager->dnstls_data.ctx = TAKE_PTR(ctx);
         return 0;
 }
 
index 29a7046be3e4a1152452cba31776d9fa7dccf426..faf539195b04868d03e106fd0ba92b0d39708c16 100644 (file)
@@ -754,12 +754,6 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 log_warning_errno(r, "Failed to parse configuration file, ignoring: %m");
 
-#if ENABLE_DNS_OVER_TLS
-        r = dnstls_manager_init(m);
-        if (r < 0)
-                return r;
-#endif
-
         r = sd_event_default(&m->event);
         if (r < 0)
                 return r;
index 9e84b44145f5021e72bab5ff87a9334e3bc82e96..446b7c9f1b6a3adb803e1934ccd00c801f7ffe73 100644 (file)
@@ -1,12 +1,4 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
-#include "sd-dlopen.h"
-
-#if ENABLE_DNS_OVER_TLS
-#  define DLOPEN_LIBCRYPTO_PRIORITY SD_ELF_NOTE_DLOPEN_PRIORITY_REQUIRED
-#else
-#  define DLOPEN_LIBCRYPTO_PRIORITY SD_ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED
-#endif
-
 int resolve_system_hostname(char **full_hostname, char **first_label);