diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index d987ee4fa4..36eb3595d5 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -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; diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index a14aa0de7d..4268cd3ff0 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -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 diff --git a/src/resolve/resolved-dnstls.c b/src/resolve/resolved-dnstls.c index 6f489ae3bd..6bcbdb5260 100644 --- a/src/resolve/resolved-dnstls.c +++ b/src/resolve/resolved-dnstls.c @@ -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; } diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 29a7046be3..faf539195b 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -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; diff --git a/src/resolve/resolved-util.h b/src/resolve/resolved-util.h index 9e84b44145..446b7c9f1b 100644 --- a/src/resolve/resolved-util.h +++ b/src/resolve/resolved-util.h @@ -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);