]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #12828 from yuwata/network-routing-policy-rule-add-missing-entries
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 19 Jun 2019 13:25:31 +0000 (15:25 +0200)
committerGitHub <noreply@github.com>
Wed, 19 Jun 2019 13:25:31 +0000 (15:25 +0200)
network: add missing entries in routing_policy_rule_{hash,compare}_func()

22 files changed:
man/resolved.conf.xml
man/systemd.network.xml
meson.build
meson_options.txt
shell-completion/bash/resolvectl
shell-completion/bash/systemd-resolve
src/resolve/resolved-conf.c
src/resolve/resolved-dns-server.c
src/resolve/resolved-dns-server.h
src/resolve/resolved-dns-stream.h
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-dnstls-gnutls.c
src/resolve/resolved-dnstls-gnutls.h
src/resolve/resolved-dnstls-openssl.c
src/resolve/resolved-dnstls-openssl.h
src/resolve/resolved-dnstls.h
src/resolve/resolved-link.c
src/resolve/resolved-manager.c
src/resolve/resolved-manager.h
src/shared/resolve-util.c
src/shared/resolve-util.h
src/systemd/sd-network.h

index c8ab6942c1409f1394bf467193c11a2699f0ecca..a647a4ace7786018a98ac5a74101acef3efbf8b7 100644 (file)
       <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"
index d832e68d71c5f781ec4fb52de5096b0aa1302e80..bad673b44e1c54bf460d9c37d51b1cc148d95761 100644 (file)
         <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
index 19c005141fb98ac82769a54be43e772d982c8d22..0a9b3d5b857e1e679314f8caf8aae9116163eeea 100644 (file)
@@ -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',
index 494a8de43c487ec17f145ea0a6a411f549267473..b96e49d825782b8caa698e562f4a3da5feb96bdc 100644 (file)
@@ -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')
index 161ac4d3c577a38c8b8b31063c958592b1bcc85e..d4ac339038126371fc8cbc30478b1b555361fdab 100644 (file)
@@ -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 )
 
index 84747b7462f31ab9ee45fee48d97b9d2aaa55578..66f0ae04a0a54abd9061df1f0f1039bc808f446e 100644 (file)
@@ -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") )
index 79e388f8a2d7cefec1f6bbb62d9c81d8fa9ffaa7..7b2938fea3fd97fb84b0c95fc11cddd18715b084 100644 (file)
@@ -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
index cd6e42e5945f100a0d320bbc2832188e62cf440f..78e5953b3001095e74077678ace923e6e639fcde 100644 (file)
@@ -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 */
index 3c4627bca5a3d0d0c86e867667ca63717dd6d8b6..2c0457243bc0d7cefe9e08841fcf612216ca1d08 100644 (file)
@@ -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;
index 780051b38a419ae5e6e25cff5adf4b7b7de2fb52..1013f6e45e6a0dc0cdff39ceae9ef6e70462024f 100644 (file)
@@ -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
 
index 2ef02348064bf8cf9488a12d9b8fa2373f330869..deb46fae7a19a6262b4b22c41dcb31f4304acc62 100644 (file)
 #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
index 4da5121e6256a18e1c0bee70415bf51528626244..06d635fcc444f77302398131a50d660846269965 100644 (file)
@@ -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);
 }
index 41c89f273751eb0c366af65b246898ae747fdfd9..af52f04fdf28bb1c3c4d25462b29f41e0a1b5ed2 100644 (file)
@@ -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;
 };
 
index 1a21b9224b44e680f378193c77bc308cb73f2bd7..85e202ff741d46a09911c1247577ef980f6a2952 100644 (file)
@@ -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);
 }
index 0fe72afd0ae62c4562e338be79b745f927838870..8100d2ba6b027bcf7e859bdca2c79bc548553591 100644 (file)
@@ -8,8 +8,11 @@
 #include <openssl/ssl.h>
 #include <stdbool.h>
 
-struct DnsTlsServerData {
+struct DnsTlsManagerData {
         SSL_CTX *ctx;
+};
+
+struct DnsTlsServerData {
         SSL_SESSION *session;
 };
 
index fdd85eece6a8903078db9d7f7ad2c3ad6c3f1c63..1b9121171e98d55f3fa6c04786170857943e5097 100644 (file)
@@ -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 */
index dd8b5a574b003f5ae92902689087f4c790a75ede..96ebb4d23d360020a39eeb98d6f2a7a619d4c1a6 100644 (file)
@@ -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
 
index 5f63a21e01d1b5e6501f391dc88ab67a72ff3a31..02153b929fb9e19fa78d1dbb47616d74a1333ebc 100644 (file)
@@ -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);
 
index 72171f8c975b1dc8cb9292d997eab2011c821aab..0f7d8ee5ee1b13bf95b43a689c38e47b122e10d1 100644 (file)
@@ -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;
 
index a5d4a14344f8a160b26c1f487d786815d9b52bb9..b433cd24bca9071bf76ed6a07a8ec3df23dde993 100644 (file)
@@ -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);
index 5883342e653c2f054c11d277e71ff45bb05bd1e5..6ce250846609982b1a8d462f0411967b5ce0cca8 100644 (file)
@@ -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
 };
index 166c30185a1e67515bb0cf0cd916fcd83abd693a..9ab4426b8b7bf32760e1daea0db7883a6fd7abce 100644 (file)
@@ -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
  */