fix cve-2018-21029

This commit is contained in:
overweight 2021-01-28 22:26:52 -08:00
parent de0482fab0
commit d11b24bbe4
8 changed files with 730 additions and 1 deletions

View File

@ -0,0 +1,37 @@
From 2f2b28ab35e80855042c69e324feaf7418636aa2 Mon Sep 17 00:00:00 2001
From: Riccardo Schirone <sirmy15@gmail.com>
Date: Wed, 13 Nov 2019 17:37:15 +0100
Subject: [PATCH] Be more specific in resolved.conf man page with regard to
DNSOverTLS
DNSOverTLS in strict mode (value yes) does check the server, as it is said in
the first few lines of the option documentation. The check is not performed in
"opportunistic" mode, however, as that is allowed by RFC 7858, section "4.1.
Opportunistic Privacy Profile".
> With such a discovered DNS server, the client might or might not validate the
> resolver. These choices maximize availability and performance, but they leave
> the client vulnerable to on-path attacks that remove privacy.
---
man/resolved.conf.xml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index 213be1d7b2..818000145b 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -210,8 +210,9 @@
send for setting up an encrypted connection, and thus results
in a small DNS look-up time penalty.</para>
- <para>Note as the resolver is not capable of authenticating
- the server, it is vulnerable for "man-in-the-middle" attacks.</para>
+ <para>Note that in <literal>opportunistic</literal> mode the
+ resolver is not capable of authenticating the server, so it is
+ vulnerable to "man-in-the-middle" attacks.</para>
<para>In addition to this global DNSOverTLS setting
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
--
2.26.2

View File

@ -0,0 +1,330 @@
From 2e22a54f4e085496088b77085f38b66532da59fb Mon Sep 17 00:00:00 2001
From: Guilhem Lettron <guilhem@barpilot.io>
Date: Sat, 30 Nov 2019 03:51:40 +0100
Subject: [PATCH] Implement SNI when using DNS-over-TLS
Some DNS providers need SNI to identify client.
This can be used by adding #name to a DNS.
Example:
[Resolve]
DNS=192.168.1.1#example.com
---
man/resolved.conf.xml | 3 +++
src/resolve/meson.build | 8 ++++++
src/resolve/resolved-conf.c | 6 +++--
src/resolve/resolved-dns-server.c | 12 ++++++++-
src/resolve/resolved-dns-server.h | 5 +++-
src/resolve/resolved-dnstls-gnutls.c | 6 +++++
src/resolve/resolved-dnstls-openssl.c | 11 ++++++++
src/resolve/resolved-link-bus.c | 2 +-
src/resolve/resolved-link.c | 2 +-
src/resolve/resolved-util.c | 36 +++++++++++++++++++++++++++
src/resolve/resolved-util.h | 6 +++++
src/resolve/test-resolved-util.c | 32 ++++++++++++++++++++++++
12 files changed, 123 insertions(+), 6 deletions(-)
create mode 100644 src/resolve/resolved-util.c
create mode 100644 src/resolve/resolved-util.h
create mode 100644 src/resolve/test-resolved-util.c
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index 818000145b..0f70ced5b5 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -214,6 +214,9 @@
resolver is not capable of authenticating the server, so it is
vulnerable to "man-in-the-middle" attacks.</para>
+ <para>Server Name Indication (SNI) can be used when opening a TLS connection.
+ Entries in <varname>DNS=</varname> should be in format <literal>address#server_name</literal>.</para>
+
<para>In addition to this global DNSOverTLS setting
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
also maintains per-link DNSOverTLS settings. For system DNS
diff --git a/src/resolve/meson.build b/src/resolve/meson.build
index 92b67b6333..c4d8d4e5d9 100644
--- a/src/resolve/meson.build
+++ b/src/resolve/meson.build
@@ -64,6 +64,8 @@ systemd_resolved_sources = files('''
resolved-etc-hosts.h
resolved-etc-hosts.c
resolved-dnstls.h
+ resolved-util.c
+ resolved-util.h
'''.split())
resolvectl_sources = files('''
@@ -228,4 +230,10 @@ tests += [
[],
[],
'ENABLE_RESOLVE', 'manual'],
+
+ [['src/resolve/test-resolved-util.c',
+ 'src/resolve/resolved-util.c',
+ 'src/resolve/resolved-util.h'],
+ [],
+ []],
]
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
index a46c45385b..ca5b8e7918 100644
--- a/src/resolve/resolved-conf.c
+++ b/src/resolve/resolved-conf.c
@@ -8,6 +8,7 @@
#include "parse-util.h"
#include "resolved-conf.h"
#include "resolved-dnssd.h"
+#include "resolved-util.h"
#include "specifier.h"
#include "string-table.h"
#include "string-util.h"
@@ -27,11 +28,12 @@ static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, cons
union in_addr_union address;
int family, r, ifindex = 0;
DnsServer *s;
+ _cleanup_free_ char *server_name = NULL;
assert(m);
assert(word);
- r = in_addr_ifindex_from_string_auto(word, &family, &address, &ifindex);
+ r = in_addr_ifindex_name_from_string_auto(word, &family, &address, &ifindex, &server_name);
if (r < 0)
return r;
@@ -52,7 +54,7 @@ static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, cons
return 0;
}
- return dns_server_new(m, NULL, type, NULL, family, &address, ifindex);
+ return dns_server_new(m, NULL, type, NULL, family, &address, ifindex, server_name);
}
int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) {
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 9f2c97314f..4b0599ab9c 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -25,8 +25,10 @@ int dns_server_new(
Link *l,
int family,
const union in_addr_union *in_addr,
- int ifindex) {
+ int ifindex,
+ const char *server_name) {
+ _cleanup_free_ char *name = NULL;
DnsServer *s;
assert(m);
@@ -44,6 +46,12 @@ int dns_server_new(
return -E2BIG;
}
+ if (server_name) {
+ name = strdup(server_name);
+ if (!name)
+ return -ENOMEM;
+ }
+
s = new(DnsServer, 1);
if (!s)
return -ENOMEM;
@@ -55,6 +63,7 @@ int dns_server_new(
.family = family,
.address = *in_addr,
.ifindex = ifindex,
+ .server_name = TAKE_PTR(name),
};
dns_server_reset_features(s);
@@ -107,6 +116,7 @@ static DnsServer* dns_server_free(DnsServer *s) {
#endif
free(s->server_string);
+ free(s->server_name);
return mfree(s);
}
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
index 54339355aa..889c80a205 100644
--- a/src/resolve/resolved-dns-server.h
+++ b/src/resolve/resolved-dns-server.h
@@ -53,6 +53,8 @@ struct DnsServer {
char *server_string;
+ char *server_name;
+
/* The long-lived stream towards this server. */
DnsStream *stream;
@@ -94,7 +96,8 @@ int dns_server_new(
Link *link,
int family,
const union in_addr_union *address,
- int ifindex);
+ int ifindex,
+ const char *server_string);
DnsServer* dns_server_ref(DnsServer *s);
DnsServer* dns_server_unref(DnsServer *s);
diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c
index ed0a31e8bf..aad3bb4481 100644
--- a/src/resolve/resolved-dnstls-gnutls.c
+++ b/src/resolve/resolved-dnstls-gnutls.c
@@ -67,6 +67,12 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0);
}
+ if (server->server_name) {
+ r = gnutls_server_name_set(gs, GNUTLS_NAME_DNS, server->server_name, strlen(server->server_name));
+ if (r < 0)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set server name: %s", gnutls_strerror(r));
+ }
+
gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
gnutls_transport_set_ptr2(gs, (gnutls_transport_ptr_t) (long) stream->fd, stream);
diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c
index 85e202ff74..ce0a437371 100644
--- a/src/resolve/resolved-dnstls-openssl.c
+++ b/src/resolve/resolved-dnstls-openssl.c
@@ -87,6 +87,17 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
return -ECONNREFUSED;
}
+ if (server->server_name) {
+ r = SSL_set_tlsext_host_name(s, server->server_name);
+ if (r <= 0) {
+ char errbuf[256];
+
+ error = ERR_get_error();
+ ERR_error_string_n(error, errbuf, sizeof(errbuf));
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set server name: %s", errbuf);
+ }
+ }
+
ERR_clear_error();
stream->dnstls_data.handshake = SSL_do_handshake(s);
if (stream->dnstls_data.handshake <= 0) {
diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c
index 8a2768b1e2..dae8435b45 100644
--- a/src/resolve/resolved-link-bus.c
+++ b/src/resolve/resolved-link-bus.c
@@ -284,7 +284,7 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_
if (s)
dns_server_move_back_and_unmark(s);
else {
- r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0);
+ r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0, NULL);
if (r < 0)
goto clear;
}
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index 96ebb4d23d..f19fc2f3aa 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -269,7 +269,7 @@ static int link_update_dns_server_one(Link *l, const char *name) {
return 0;
}
- return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0);
+ return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0, NULL);
}
static int link_update_dns_servers(Link *l) {
diff --git a/src/resolve/resolved-util.c b/src/resolve/resolved-util.c
new file mode 100644
index 0000000000..2f18f8c19d
--- /dev/null
+++ b/src/resolve/resolved-util.c
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "alloc-util.h"
+#include "in-addr-util.h"
+#include "macro.h"
+#include "resolved-util.h"
+
+int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name) {
+ _cleanup_free_ char *buf = NULL, *name = NULL;
+ const char *m;
+ int r;
+
+ assert(s);
+
+ m = strchr(s, '#');
+ if (m) {
+ name = strdup(m+1);
+ if (!name)
+ return -ENOMEM;
+
+ buf = strndup(s, m - s);
+ if (!buf)
+ return -ENOMEM;
+
+ s = buf;
+ }
+
+ r = in_addr_ifindex_from_string_auto(s, family, ret, ifindex);
+ if (r < 0)
+ return r;
+
+ if (server_name)
+ *server_name = TAKE_PTR(name);
+
+ return r;
+}
diff --git a/src/resolve/resolved-util.h b/src/resolve/resolved-util.h
new file mode 100644
index 0000000000..10ebbc0874
--- /dev/null
+++ b/src/resolve/resolved-util.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "in-addr-util.h"
+
+int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name);
diff --git a/src/resolve/test-resolved-util.c b/src/resolve/test-resolved-util.c
new file mode 100644
index 0000000000..35bd73c4f6
--- /dev/null
+++ b/src/resolve/test-resolved-util.c
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "log.h"
+#include "resolved-util.h"
+#include "string-util.h"
+#include "tests.h"
+
+
+static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) {
+ int family, ifindex;
+ union in_addr_union ua;
+ _cleanup_free_ char *server_name = NULL;
+
+ assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0);
+ assert_se(streq_ptr(server_name, expected));
+}
+
+static void test_in_addr_ifindex_name_from_string_auto(void) {
+ log_info("/* %s */", __func__);
+
+ test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL);
+ test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com");
+ test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL);
+ test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com");
+}
+
+int main(int argc, char **argv) {
+ test_setup_logging(LOG_DEBUG);
+
+ test_in_addr_ifindex_name_from_string_auto();
+ return 0;
+}
--
2.26.2

View File

@ -0,0 +1,80 @@
From df70539f9fe01a16d0f561ad9c6f5d7a955039c0 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Mon, 10 Feb 2020 14:50:03 +0900
Subject: [PATCH] resolve: error handling improvements
---
src/resolve/resolved-dnstls-openssl.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c
index ce0a437371..8f58efacbd 100644
--- a/src/resolve/resolved-dnstls-openssl.c
+++ b/src/resolve/resolved-dnstls-openssl.c
@@ -73,7 +73,9 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
return -ENOMEM;
SSL_set_connect_state(s);
- SSL_set_session(s, server->dnstls_data.session);
+ r = SSL_set_session(s, server->dnstls_data.session);
+ if (r == 0)
+ return -EIO;
SSL_set_bio(s, TAKE_PTR(rb), TAKE_PTR(wb));
if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) {
@@ -83,7 +85,7 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
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)))
+ if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0)
return -ECONNREFUSED;
}
@@ -106,8 +108,8 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
char errbuf[256];
ERR_error_string_n(error, errbuf, sizeof(errbuf));
- log_debug("Failed to invoke SSL_do_handshake: %s", errbuf);
- return -ECONNREFUSED;
+ return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED),
+ "Failed to invoke SSL_do_handshake: %s", errbuf);
}
}
@@ -368,20 +370,27 @@ void dnstls_server_free(DnsServer *server) {
int dnstls_manager_init(Manager *manager) {
int r;
+
assert(manager);
ERR_load_crypto_strings();
SSL_load_error_strings();
- manager->dnstls_data.ctx = SSL_CTX_new(TLS_client_method());
+ manager->dnstls_data.ctx = SSL_CTX_new(TLS_client_method());
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_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION);
+ if (r == 0)
+ return -EIO;
+
+ (void) 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));
+ if (r == 0)
+ return log_warning_errno(SYNTHETIC_ERRNO(EIO),
+ "Failed to load system trust store: %s",
+ ERR_error_string(ERR_get_error(), NULL));
return 0;
}
--
2.26.2

View File

@ -0,0 +1,51 @@
From 7f2f4faced3fda47e6b76ab73cde747cc20cf8b8 Mon Sep 17 00:00:00 2001
From: Iwan Timmer <irtimmer@gmail.com>
Date: Tue, 29 Oct 2019 20:32:18 +0100
Subject: [PATCH] resolved: check for IP in certificate when using DoT with
GnuTLS
Validate the IP address in the certificate for DNS-over-TLS in strict mode when GnuTLS is used. As this is not yet the case in contrast to the documentation.
---
src/resolve/resolved-dnstls-gnutls.c | 13 +++++++++++--
src/resolve/resolved-dnstls-gnutls.h | 1 +
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c
index ea276d2c20..9e5e60fcce 100644
--- a/src/resolve/resolved-dnstls-gnutls.c
+++ b/src/resolve/resolved-dnstls-gnutls.c
@@ -55,8 +55,17 @@ 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);
+ if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) {
+ stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS;
+ if (server->family == AF_INET) {
+ stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr;
+ stream->dnstls_data.validation.size = 4;
+ } else {
+ stream->dnstls_data.validation.data = server->address.in6.s6_addr;
+ stream->dnstls_data.validation.size = 16;
+ }
+ gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0);
+ }
gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
diff --git a/src/resolve/resolved-dnstls-gnutls.h b/src/resolve/resolved-dnstls-gnutls.h
index af52f04fdf..d4da2017c3 100644
--- a/src/resolve/resolved-dnstls-gnutls.h
+++ b/src/resolve/resolved-dnstls-gnutls.h
@@ -18,6 +18,7 @@ struct DnsTlsServerData {
struct DnsTlsStreamData {
gnutls_session_t session;
+ gnutls_typed_vdata_st validation;
int handshake;
bool shutdown;
};
--
2.26.2

View File

@ -0,0 +1,34 @@
From 68805580209cfaa50b2400d1a2e6c66500001395 Mon Sep 17 00:00:00 2001
From: Peter Wu <peter@lekensteyn.nl>
Date: Sun, 20 Oct 2019 18:10:31 +0100
Subject: [PATCH] resolved: fix connection failures with TLS 1.3 and GnuTLS
Prefer TLS 1.3 before TLS 1.2 for DNS-over-TLS support, otherwise
servers compliant with RFC 8446 might end up agreeing TLS 1.2 plus a
downgrade signal which is not expected by GnuTLS clients. This manifests
in the following error:
Failed to invoke gnutls_handshake: An illegal parameter has been received.
Fixes: #13528
Fixes: v242-962-g9c0624dcdb ("resolved: support TLS 1.3 when using GnuTLS for DNS-over-TLS")
---
src/resolve/resolved-dnstls-gnutls.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c
index 06d635fcc4..7ad9662073 100644
--- a/src/resolve/resolved-dnstls-gnutls.c
+++ b/src/resolve/resolved-dnstls-gnutls.c
@@ -10,7 +10,7 @@
#include "resolved-dnstls.h"
#if GNUTLS_VERSION_NUMBER >= 0x030600
-#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3"
+#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2"
#else
#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.2"
#endif
--
2.26.2

View File

@ -0,0 +1,58 @@
From 38e053c58fa139e0f546f327b5d8ce3db7cf1647 Mon Sep 17 00:00:00 2001
From: Iwan Timmer <irtimmer@gmail.com>
Date: Tue, 29 Oct 2019 20:26:05 +0100
Subject: [PATCH] resolved: require at least version 3.6.0 of GnuTLS for
DNS-over-TLS
Increase the required version to ensure TLS 1.3 is always supported when using GnuTLS for DNS-over-TLS and allow further changes to use recent API additions.
---
README | 2 +-
meson.build | 2 +-
src/resolve/resolved-dnstls-gnutls.c | 4 ----
3 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/README b/README
index 8aa16fe8c9..8dbf94b49c 100644
--- a/README
+++ b/README
@@ -155,7 +155,7 @@ REQUIREMENTS:
libmicrohttpd (optional)
libpython (optional)
libidn2 or libidn (optional)
- gnutls >= 3.1.4 (optional, >= 3.5.3 is required to support DNS-over-TLS with gnutls)
+ gnutls >= 3.1.4 (optional, >= 3.6.0 is required to support DNS-over-TLS with gnutls)
openssl >= 1.1.0 (optional, required to support DNS-over-TLS with openssl)
elfutils >= 158 (optional)
polkit (optional)
diff --git a/meson.build b/meson.build
index 0001504d53..a7a9222582 100644
--- a/meson.build
+++ b/meson.build
@@ -1199,7 +1199,7 @@ if dns_over_tls != 'false'
if dns_over_tls == 'openssl'
have_gnutls = false
else
- have_gnutls = (conf.get('HAVE_GNUTLS') == 1 and libgnutls.version().version_compare('>= 3.5.3'))
+ have_gnutls = (conf.get('HAVE_GNUTLS') == 1 and libgnutls.version().version_compare('>= 3.6.0'))
if dns_over_tls == 'gnutls' and not have_gnutls
error('DNS-over-TLS support was requested with gnutls, but dependencies are not available')
endif
diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c
index 7ad9662073..ea276d2c20 100644
--- a/src/resolve/resolved-dnstls-gnutls.c
+++ b/src/resolve/resolved-dnstls-gnutls.c
@@ -9,11 +9,7 @@
#include "resolved-dns-stream.h"
#include "resolved-dnstls.h"
-#if GNUTLS_VERSION_NUMBER >= 0x030600
#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2"
-#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) {
--
2.26.2

View File

@ -0,0 +1,124 @@
From eec394f10bbfcc3d2fc8504ad8ff5be44231abd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
Date: Tue, 3 Mar 2020 23:31:25 +0000
Subject: [PATCH] systemd-resolved: use hostname for certificate validation in
DoT
Widely accepted certificates for IP addresses are expensive and only
affordable for larger organizations. Therefore if the user provides
the hostname in the DNS= option, we should use it instead of the IP
address.
---
man/resolved.conf.xml | 19 +++++++++++--------
src/resolve/resolved-dnstls-gnutls.c | 20 ++++++++++++--------
src/resolve/resolved-dnstls-openssl.c | 15 +++++++++++----
3 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
index 0f70ced5b5..37161ebcbc 100644
--- a/man/resolved.conf.xml
+++ b/man/resolved.conf.xml
@@ -193,11 +193,17 @@
<varlistentry>
<term><varname>DNSOverTLS=</varname></term>
<listitem>
- <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>
+ <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. If the hostname was specified in <varname>DNS=</varname>
+ by using the format format <literal>address#server_name</literal> it
+ is used to validate its certificate and also to enable Server Name
+ Indication (SNI) when opening a TLS connection. Otherwise
+ the certificate is checked against the server's IP.
+ If the DNS server does not support DNS-over-TLS all DNS requests will fail.</para>
+
+ <para>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"
@@ -214,9 +220,6 @@
resolver is not capable of authenticating the server, so it is
vulnerable to "man-in-the-middle" attacks.</para>
- <para>Server Name Indication (SNI) can be used when opening a TLS connection.
- Entries in <varname>DNS=</varname> should be in format <literal>address#server_name</literal>.</para>
-
<para>In addition to this global DNSOverTLS setting
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
also maintains per-link DNSOverTLS settings. For system DNS
diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c
index aad3bb4481..ef90a7d5ae 100644
--- a/src/resolve/resolved-dnstls-gnutls.c
+++ b/src/resolve/resolved-dnstls-gnutls.c
@@ -56,15 +56,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
}
if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) {
- stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS;
- if (server->family == AF_INET) {
- stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr;
- stream->dnstls_data.validation.size = 4;
- } else {
- stream->dnstls_data.validation.data = server->address.in6.s6_addr;
- stream->dnstls_data.validation.size = 16;
+ if (server->server_name)
+ gnutls_session_set_verify_cert(gs, server->server_name, 0);
+ else {
+ stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS;
+ if (server->family == AF_INET) {
+ stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr;
+ stream->dnstls_data.validation.size = 4;
+ } else {
+ stream->dnstls_data.validation.data = server->address.in6.s6_addr;
+ stream->dnstls_data.validation.size = 16;
+ }
+ gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0);
}
- gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0);
}
if (server->server_name) {
diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c
index 8f58efacbd..7763cbcb5a 100644
--- a/src/resolve/resolved-dnstls-openssl.c
+++ b/src/resolve/resolved-dnstls-openssl.c
@@ -6,6 +6,7 @@
#include <openssl/bio.h>
#include <openssl/err.h>
+#include <openssl/x509v3.h>
#include "io-util.h"
#include "resolved-dns-stream.h"
@@ -80,13 +81,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
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)) == 0)
- return -ECONNREFUSED;
+ if (server->server_name) {
+ X509_VERIFY_PARAM_set_hostflags(v, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ if (X509_VERIFY_PARAM_set1_host(v, server->server_name, 0) == 0)
+ return -ECONNREFUSED;
+ } else {
+ const unsigned char *ip;
+ 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)) == 0)
+ return -ECONNREFUSED;
+ }
}
if (server->server_name) {
--
2.26.2

View File

@ -16,7 +16,7 @@
Name: systemd
Url: https://www.freedesktop.org/wiki/Software/systemd
Version: 243
Release: 31
Release: 32
License: MIT and LGPLv2+ and GPLv2+
Summary: System and Service Manager
@ -114,6 +114,15 @@ Patch0064: core-fix-re-realization-of-cgroup-siblings.patch
Patch0065: basic-string-table-avoid-crash-when-table-is-sparse.patch
Patch0066: journal-fix-buffer-overrun-when-urlifying.patch
Patch0071: backport-CVE-2018-21029-resolved-check-for-IP-in-certificate-when-using-DoT-.patch
Patch0072: backport-CVE-2018-21029-resolved-fix-connection-failures-with-TLS-1.3-and-Gn.patch
Patch0073: backport-CVE-2018-21029-resolved-require-at-least-version-3.6.0-of-GnuTLS-fo.patch
Patch0074: backport-CVE-2018-21029-Be-more-specific-in-resolved.conf-man-page-with-rega.patch
Patch0075: backport-CVE-2018-21029-Implement-SNI-when-using-DNS-over-TLS.patch
Patch0076: backport-CVE-2018-21029-resolve-error-handling-improvements.patch
Patch0077: backport-CVE-2018-21029-systemd-resolved-use-hostname-for-certificate-valida.patch
#openEuler
Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch
Patch9003: 1602-activation-service-must-be-restarted-when-reactivated.patch
@ -1498,6 +1507,12 @@ fi
%exclude /usr/share/man/man3/*
%changelog
* Fri Jan 29 2021 overweight <hexiaowen@huawei.com> - 246-32
- Type:cve
- ID:CVE-2018-21029
- SUG:NA
- DESC:fix cve-2018-21029
* Fri Dec 18 2020 overweight <hexiaowen@huawei.com> - 243-31
- Type:bugfix
- ID:NA