fix cve-2018-21029
This commit is contained in:
parent
de0482fab0
commit
d11b24bbe4
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
@ -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
|
||||||
|
|
||||||
17
systemd.spec
17
systemd.spec
@ -16,7 +16,7 @@
|
|||||||
Name: systemd
|
Name: systemd
|
||||||
Url: https://www.freedesktop.org/wiki/Software/systemd
|
Url: https://www.freedesktop.org/wiki/Software/systemd
|
||||||
Version: 243
|
Version: 243
|
||||||
Release: 31
|
Release: 32
|
||||||
License: MIT and LGPLv2+ and GPLv2+
|
License: MIT and LGPLv2+ and GPLv2+
|
||||||
Summary: System and Service Manager
|
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
|
Patch0065: basic-string-table-avoid-crash-when-table-is-sparse.patch
|
||||||
Patch0066: journal-fix-buffer-overrun-when-urlifying.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
|
#openEuler
|
||||||
Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch
|
Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch
|
||||||
Patch9003: 1602-activation-service-must-be-restarted-when-reactivated.patch
|
Patch9003: 1602-activation-service-must-be-restarted-when-reactivated.patch
|
||||||
@ -1498,6 +1507,12 @@ fi
|
|||||||
%exclude /usr/share/man/man3/*
|
%exclude /usr/share/man/man3/*
|
||||||
|
|
||||||
%changelog
|
%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
|
* Fri Dec 18 2020 overweight <hexiaowen@huawei.com> - 243-31
|
||||||
- Type:bugfix
|
- Type:bugfix
|
||||||
- ID:NA
|
- ID:NA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user