summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-06-19 14:56:36 +0200
committerGitHub <noreply@github.com>2019-06-19 14:56:36 +0200
commit43786739bf7693641f9ec728d974dbb374945f14 (patch)
tree0eebdfbb7b117dd30dbae27deca790d56571ff57
parenta4eb991831099756e9debc2cfeaf689584deed08 (diff)
parent9c0624dcdb86360d5cd5eb8c6093b3cd2e6d281b (diff)
downloadsystemd-43786739bf7693641f9ec728d974dbb374945f14.tar.gz
Merge pull request #12815 from irtimmer/dot-strict
resolved: strict mode for DNS-over-TLS
-rw-r--r--man/resolved.conf.xml7
-rw-r--r--man/systemd.network.xml11
-rw-r--r--meson.build2
-rw-r--r--meson_options.txt2
-rw-r--r--shell-completion/bash/resolvectl2
-rw-r--r--shell-completion/bash/systemd-resolve2
-rw-r--r--src/resolve/resolved-conf.c2
-rw-r--r--src/resolve/resolved-dns-server.c6
-rw-r--r--src/resolve/resolved-dns-server.h4
-rw-r--r--src/resolve/resolved-dns-stream.h4
-rw-r--r--src/resolve/resolved-dns-transaction.c4
-rw-r--r--src/resolve/resolved-dnstls-gnutls.c42
-rw-r--r--src/resolve/resolved-dnstls-gnutls.h5
-rw-r--r--src/resolve/resolved-dnstls-openssl.c52
-rw-r--r--src/resolve/resolved-dnstls-openssl.h5
-rw-r--r--src/resolve/resolved-dnstls.h12
-rw-r--r--src/resolve/resolved-link.c2
-rw-r--r--src/resolve/resolved-manager.c10
-rw-r--r--src/resolve/resolved-manager.h5
-rw-r--r--src/shared/resolve-util.c3
-rw-r--r--src/shared/resolve-util.h3
-rw-r--r--src/systemd/sd-network.h2
22 files changed, 129 insertions, 58 deletions
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index c8ab6942c1..a647a4ace7 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -193,8 +193,11 @@
<varlistentry>
<term><varname>DNSOverTLS=</varname></term>
<listitem>
- <para>Takes false or
- <literal>opportunistic</literal>. When set to <literal>opportunistic</literal>
+ <para>Takes a boolean argument or <literal>opportunistic</literal>.
+ If true all connections to the server will be encrypted. Note that
+ this mode requires a DNS server that supports DNS-over-TLS and has
+ a valid certificate for it's IP. If the DNS server does not support
+ DNS-over-TLS all DNS requests will fail. When set to <literal>opportunistic</literal>
DNS request are attempted to send encrypted with DNS-over-TLS.
If the DNS server does not support TLS, DNS-over-TLS is disabled.
Note that this mode makes DNS-over-TLS vulnerable to "downgrade"
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index d832e68d71..bad673b44e 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -395,12 +395,15 @@
<varlistentry>
<term><varname>DNSOverTLS=</varname></term>
<listitem>
- <para>Takes false or
- <literal>opportunistic</literal>. When set to <literal>opportunistic</literal>, enables
+ <para>Takes a boolean or <literal>opportunistic</literal>.
+ When true, enables
<ulink
url="https://tools.ietf.org/html/rfc7858">DNS-over-TLS</ulink>
- support on the link. This option defines a
- per-interface setting for
+ support on the link.
+ When set to <literal>opportunistic</literal>, compatibility with
+ non-DNS-over-TLS servers is increased, by automatically
+ turning off DNS-over-TLS servers in this case.
+ This option defines a per-interface setting for
<citerefentry><refentrytitle>resolved.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s
global <varname>DNSOverTLS=</varname> option. Defaults to
false. This setting is read by
diff --git a/meson.build b/meson.build
index 19c005141f..0a9b3d5b85 100644
--- a/meson.build
+++ b/meson.build
@@ -1221,7 +1221,7 @@ if skip_deps
default_dns_over_tls = 'no'
endif
if default_dns_over_tls != 'no' and conf.get('ENABLE_DNS_OVER_TLS') == 0
- message('default-dns-over-tls cannot be set to opportunistic when DNS-over-TLS support is disabled. Setting default-dns-over-tls to no.')
+ message('default-dns-over-tls cannot be enabled or set to opportunistic when DNS-over-TLS support is disabled. Setting default-dns-over-tls to no.')
default_dns_over_tls = 'no'
endif
conf.set('DEFAULT_DNS_OVER_TLS_MODE',
diff --git a/meson_options.txt b/meson_options.txt
index 494a8de43c..b96e49d825 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -206,7 +206,7 @@ option('default-dnssec', type : 'combo',
value : 'allow-downgrade')
option('default-dns-over-tls', type : 'combo',
description : 'default DNS-over-TLS mode',
- choices : ['opportunistic', 'no'],
+ choices : ['yes', 'opportunistic', 'no'],
value : 'no')
option('dns-over-tls', type : 'combo', choices : ['auto', 'gnutls', 'openssl', 'true', 'false'],
description : 'DNS-over-TLS support')
diff --git a/shell-completion/bash/resolvectl b/shell-completion/bash/resolvectl
index 161ac4d3c5..d4ac339038 100644
--- a/shell-completion/bash/resolvectl
+++ b/shell-completion/bash/resolvectl
@@ -53,7 +53,7 @@ _resolvectl() {
[FAMILY]='tcp udp sctp'
[RESOLVE]='yes no resolve'
[DNSSEC]='yes no allow-downgrade'
- [DNSOVERTLS]='no opportunistic'
+ [DNSOVERTLS]='yes no opportunistic'
)
local interfaces=$( __get_interfaces )
diff --git a/shell-completion/bash/systemd-resolve b/shell-completion/bash/systemd-resolve
index 84747b7462..66f0ae04a0 100644
--- a/shell-completion/bash/systemd-resolve
+++ b/shell-completion/bash/systemd-resolve
@@ -64,7 +64,7 @@ _systemd-resolve() {
comps="yes no allow-downgrade"
;;
--set-dnsovertls)
- comps="no opportunistic"
+ comps="yes no opportunistic"
;;
esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index 79e388f8a2..7b2938fea3 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -394,7 +394,7 @@ int manager_parse_config_file(Manager *m) {
#if ! ENABLE_DNS_OVER_TLS
if (m->dns_over_tls_mode != DNS_OVER_TLS_NO) {
- log_warning("DNS-over-TLS option cannot be set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
+ log_warning("DNS-over-TLS option cannot be enabled or set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
m->dns_over_tls_mode = DNS_OVER_TLS_NO;
}
#endif
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index cd6e42e594..78e5953b30 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -82,10 +82,6 @@ int dns_server_new(
s->linked = true;
-#if ENABLE_DNS_OVER_TLS
- dnstls_server_init(s);
-#endif
-
/* A new DNS server that isn't fallback is added and the one
* we used so far was a fallback one? Then let's try to pick
* the new one */
@@ -423,7 +419,7 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
} else if (s->n_failed_tls > 0 &&
- DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level)) {
+ DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) && dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
/* We tried to connect using DNS-over-TLS, and it didn't work. Downgrade to plaintext UDP
* if we don't require DNS-over-TLS */
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
index 3c4627bca5..2c0457243b 100644
--- a/src/resolve/resolved-dns-server.h
+++ b/src/resolve/resolved-dns-server.h
@@ -35,11 +35,9 @@ typedef enum DnsServerFeatureLevel {
const char* dns_server_feature_level_to_string(int i) _const_;
int dns_server_feature_level_from_string(const char *s) _pure_;
+#include "resolved-dnstls.h"
#include "resolved-link.h"
#include "resolved-manager.h"
-#if ENABLE_DNS_OVER_TLS
-#include "resolved-dnstls.h"
-#endif
struct DnsServer {
Manager *manager;
diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h
index 780051b38a..1013f6e45e 100644
--- a/src/resolve/resolved-dns-stream.h
+++ b/src/resolve/resolved-dns-stream.h
@@ -16,10 +16,8 @@ typedef enum DnsStreamType {
#include "resolved-dns-packet.h"
#include "resolved-dns-transaction.h"
-#include "resolved-manager.h"
-#if ENABLE_DNS_OVER_TLS
#include "resolved-dnstls.h"
-#endif
+#include "resolved-manager.h"
#define DNS_STREAM_WRITE_TLS_DATA 1
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 2ef0234806..deb46fae7a 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -11,10 +11,8 @@
#include "random-util.h"
#include "resolved-dns-cache.h"
#include "resolved-dns-transaction.h"
-#include "resolved-llmnr.h"
-#if ENABLE_DNS_OVER_TLS
#include "resolved-dnstls.h"
-#endif
+#include "resolved-llmnr.h"
#include "string-table.h"
#define TRANSACTIONS_MAX 4096
diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c
index 4da5121e62..06d635fcc4 100644
--- a/src/resolve/resolved-dnstls-gnutls.c
+++ b/src/resolve/resolved-dnstls-gnutls.c
@@ -9,6 +9,11 @@
#include "resolved-dns-stream.h"
#include "resolved-dnstls.h"
+#if GNUTLS_VERSION_NUMBER >= 0x030600
+#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3"
+#else
+#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.2"
+#endif
DEFINE_TRIVIAL_CLEANUP_FUNC(gnutls_session_t, gnutls_deinit);
static ssize_t dnstls_stream_writev(gnutls_transport_ptr_t p, const giovec_t *iov, int iovcnt) {
@@ -37,11 +42,11 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
return r;
/* As DNS-over-TLS is a recent protocol, older TLS versions can be disabled */
- r = gnutls_priority_set_direct(gs, "NORMAL:-VERS-ALL:+VERS-TLS1.2", NULL);
+ r = gnutls_priority_set_direct(gs, PRIORTY_STRING, NULL);
if (r < 0)
return r;
- r = gnutls_credentials_set(gs, GNUTLS_CRD_CERTIFICATE, server->dnstls_data.cert_cred);
+ r = gnutls_credentials_set(gs, GNUTLS_CRD_CERTIFICATE, stream->manager->dnstls_data.cert_cred);
if (r < 0)
return r;
@@ -54,6 +59,9 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
server->dnstls_data.session_data.size = 0;
}
+ if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES)
+ gnutls_session_set_verify_cert(gs, NULL, 0);
+
gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
gnutls_transport_set_ptr2(gs, (gnutls_transport_ptr_t) (long) stream->fd, stream);
@@ -187,19 +195,31 @@ ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) {
return ss;
}
-void dnstls_server_init(DnsServer *server) {
+void dnstls_server_free(DnsServer *server) {
assert(server);
- /* Do not verify cerificate */
- gnutls_certificate_allocate_credentials(&server->dnstls_data.cert_cred);
+ if (server->dnstls_data.session_data.data)
+ gnutls_free(server->dnstls_data.session_data.data);
}
-void dnstls_server_free(DnsServer *server) {
- assert(server);
+int dnstls_manager_init(Manager *manager) {
+ int r;
+ assert(manager);
- if (server->dnstls_data.cert_cred)
- gnutls_certificate_free_credentials(server->dnstls_data.cert_cred);
+ r = gnutls_certificate_allocate_credentials(&manager->dnstls_data.cert_cred);
+ if (r < 0)
+ return -ENOMEM;
- if (server->dnstls_data.session_data.data)
- gnutls_free(server->dnstls_data.session_data.data);
+ r = gnutls_certificate_set_x509_system_trust(manager->dnstls_data.cert_cred);
+ if (r < 0)
+ log_warning("Failed to load system trust store: %s", gnutls_strerror(r));
+
+ return 0;
+}
+
+void dnstls_manager_free(Manager *manager) {
+ assert(manager);
+
+ if (manager->dnstls_data.cert_cred)
+ gnutls_certificate_free_credentials(manager->dnstls_data.cert_cred);
}
diff --git a/src/resolve/resolved-dnstls-gnutls.h b/src/resolve/resolved-dnstls-gnutls.h
index 41c89f2737..af52f04fdf 100644
--- a/src/resolve/resolved-dnstls-gnutls.h
+++ b/src/resolve/resolved-dnstls-gnutls.h
@@ -8,8 +8,11 @@
#include <gnutls/gnutls.h>
#include <stdbool.h>
-struct DnsTlsServerData {
+struct DnsTlsManagerData {
gnutls_certificate_credentials_t cert_cred;
+};
+
+struct DnsTlsServerData {
gnutls_datum_t session_data;
};
diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c
index 1a21b9224b..85e202ff74 100644
--- a/src/resolve/resolved-dnstls-openssl.c
+++ b/src/resolve/resolved-dnstls-openssl.c
@@ -54,6 +54,7 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
int error, r;
assert(stream);
+ assert(stream->manager);
assert(server);
rb = BIO_new_socket(stream->fd, 0);
@@ -67,7 +68,7 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
BIO_get_mem_ptr(wb, &stream->dnstls_data.write_buffer);
stream->dnstls_data.buffer_offset = 0;
- s = SSL_new(server->dnstls_data.ctx);
+ s = SSL_new(stream->manager->dnstls_data.ctx);
if (!s)
return -ENOMEM;
@@ -75,6 +76,17 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
SSL_set_session(s, server->dnstls_data.session);
SSL_set_bio(s, TAKE_PTR(rb), TAKE_PTR(wb));
+ if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) {
+ X509_VERIFY_PARAM *v;
+ const unsigned char *ip;
+
+ SSL_set_verify(s, SSL_VERIFY_PEER, NULL);
+ v = SSL_get0_param(s);
+ ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr;
+ if (!X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)))
+ return -ECONNREFUSED;
+ }
+
ERR_clear_error();
stream->dnstls_data.handshake = SSL_do_handshake(s);
if (stream->dnstls_data.handshake <= 0) {
@@ -336,22 +348,36 @@ ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) {
return ss;
}
-void dnstls_server_init(DnsServer *server) {
+void dnstls_server_free(DnsServer *server) {
assert(server);
- server->dnstls_data.ctx = SSL_CTX_new(TLS_client_method());
- if (server->dnstls_data.ctx) {
- SSL_CTX_set_min_proto_version(server->dnstls_data.ctx, TLS1_2_VERSION);
- SSL_CTX_set_options(server->dnstls_data.ctx, SSL_OP_NO_COMPRESSION);
- }
+ if (server->dnstls_data.session)
+ SSL_SESSION_free(server->dnstls_data.session);
}
-void dnstls_server_free(DnsServer *server) {
- assert(server);
+int dnstls_manager_init(Manager *manager) {
+ int r;
+ assert(manager);
- if (server->dnstls_data.ctx)
- SSL_CTX_free(server->dnstls_data.ctx);
+ ERR_load_crypto_strings();
+ SSL_load_error_strings();
+ manager->dnstls_data.ctx = SSL_CTX_new(TLS_client_method());
- if (server->dnstls_data.session)
- SSL_SESSION_free(server->dnstls_data.session);
+ if (!manager->dnstls_data.ctx)
+ return -ENOMEM;
+
+ SSL_CTX_set_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION);
+ SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION);
+ r = SSL_CTX_set_default_verify_paths(manager->dnstls_data.ctx);
+ if (r < 0)
+ log_warning("Failed to load system trust store: %s", ERR_error_string(ERR_get_error(), NULL));
+
+ return 0;
+}
+
+void dnstls_manager_free(Manager *manager) {
+ assert(manager);
+
+ if (manager->dnstls_data.ctx)
+ SSL_CTX_free(manager->dnstls_data.ctx);
}
diff --git a/src/resolve/resolved-dnstls-openssl.h b/src/resolve/resolved-dnstls-openssl.h
index 0fe72afd0a..8100d2ba6b 100644
--- a/src/resolve/resolved-dnstls-openssl.h
+++ b/src/resolve/resolved-dnstls-openssl.h
@@ -8,8 +8,11 @@
#include <openssl/ssl.h>
#include <stdbool.h>
-struct DnsTlsServerData {
+struct DnsTlsManagerData {
SSL_CTX *ctx;
+};
+
+struct DnsTlsServerData {
SSL_SESSION *session;
};
diff --git a/src/resolve/resolved-dnstls.h b/src/resolve/resolved-dnstls.h
index fdd85eece6..1b9121171e 100644
--- a/src/resolve/resolved-dnstls.h
+++ b/src/resolve/resolved-dnstls.h
@@ -1,10 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-#if !ENABLE_DNS_OVER_TLS
-#error This source file requires DNS-over-TLS to be enabled
-#endif
+#if ENABLE_DNS_OVER_TLS
+typedef struct DnsTlsManagerData DnsTlsManagerData;
typedef struct DnsTlsServerData DnsTlsServerData;
typedef struct DnsTlsStreamData DnsTlsStreamData;
@@ -18,6 +17,7 @@ typedef struct DnsTlsStreamData DnsTlsStreamData;
#include "resolved-dns-stream.h"
#include "resolved-dns-transaction.h"
+#include "resolved-manager.h"
#define DNSTLS_STREAM_CLOSED 1
@@ -28,5 +28,9 @@ int dnstls_stream_shutdown(DnsStream *stream, int error);
ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t count);
ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count);
-void dnstls_server_init(DnsServer *server);
void dnstls_server_free(DnsServer *server);
+
+int dnstls_manager_init(Manager *manager);
+void dnstls_manager_free(Manager *manager);
+
+#endif /* ENABLE_DNS_OVER_TLS */
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index dd8b5a574b..96ebb4d23d 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -384,7 +384,7 @@ void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode) {
#if ! ENABLE_DNS_OVER_TLS
if (mode != DNS_OVER_TLS_NO)
- log_warning("DNS-over-TLS option for the link cannot be set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
+ log_warning("DNS-over-TLS option for the link cannot be enabled or set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
return;
#endif
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 5f63a21e01..02153b929f 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -597,6 +597,12 @@ int manager_new(Manager **ret) {
if (r < 0)
log_warning_errno(r, "Failed to parse configuration file: %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;
@@ -677,6 +683,10 @@ Manager *manager_free(Manager *m) {
while (m->dns_streams)
dns_stream_unref(m->dns_streams);
+#if ENABLE_DNS_OVER_TLS
+ dnstls_manager_free(m);
+#endif
+
hashmap_free(m->links);
hashmap_free(m->dns_transactions);
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index 72171f8c97..0f7d8ee5ee 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -18,6 +18,7 @@ typedef struct Manager Manager;
#include "resolved-dns-server.h"
#include "resolved-dns-stream.h"
#include "resolved-dns-trust-anchor.h"
+#include "resolved-dnstls.h"
#include "resolved-link.h"
#define MANAGER_SEARCH_DOMAINS_MAX 256
@@ -39,6 +40,10 @@ struct Manager {
bool enable_cache;
DnsStubListenerMode dns_stub_listener_mode;
+#if ENABLE_DNS_OVER_TLS
+ DnsTlsManagerData dnstls_data;
+#endif
+
/* Network */
Hashmap *links;
diff --git a/src/shared/resolve-util.c b/src/shared/resolve-util.c
index a5d4a14344..b433cd24bc 100644
--- a/src/shared/resolve-util.c
+++ b/src/shared/resolve-util.c
@@ -25,5 +25,6 @@ DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES);
static const char* const dns_over_tls_mode_table[_DNS_OVER_TLS_MODE_MAX] = {
[DNS_OVER_TLS_NO] = "no",
[DNS_OVER_TLS_OPPORTUNISTIC] = "opportunistic",
+ [DNS_OVER_TLS_YES] = "yes",
};
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_over_tls_mode, DnsOverTlsMode, _DNS_OVER_TLS_MODE_INVALID);
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_over_tls_mode, DnsOverTlsMode, DNS_OVER_TLS_YES);
diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h
index 5883342e65..6ce2508466 100644
--- a/src/shared/resolve-util.h
+++ b/src/shared/resolve-util.h
@@ -42,6 +42,9 @@ enum DnsOverTlsMode {
* fallback to using an unencrypted connection */
DNS_OVER_TLS_OPPORTUNISTIC,
+ /* Enforce DNS-over-TLS and require valid server certificates */
+ DNS_OVER_TLS_YES,
+
_DNS_OVER_TLS_MODE_MAX,
_DNS_OVER_TLS_MODE_INVALID = -1
};
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index 166c30185a..9ab4426b8b 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -127,7 +127,7 @@ int sd_network_link_get_mdns(int ifindex, char **mdns);
/* Indicates whether or not DNS-over-TLS should be enabled for the
* link.
- * Possible levels of support: strict, no, opportunistic
+ * Possible levels of support: yes, no, opportunistic
* Possible return codes:
* -ENODATA: networkd is not aware of the link
*/