From e22c5b20641e3ce6cd029cb40e3f4ed1330493bf Mon Sep 17 00:00:00 2001 From: Iwan Timmer Date: Sat, 15 Jun 2019 22:54:41 +0200 Subject: [PATCH] resolved: move TLS data shared by all servers to manager Instead of having a context and/or trusted CA list per server this is now moved to the server. Ensures future TLS configuration options are global instead of per server. --- src/resolve/resolved-dns-server.c | 4 ---- src/resolve/resolved-dnstls-gnutls.c | 27 +++++++++++++-------- src/resolve/resolved-dnstls-gnutls.h | 5 +++- src/resolve/resolved-dnstls-openssl.c | 34 +++++++++++++++++---------- src/resolve/resolved-dnstls-openssl.h | 5 +++- src/resolve/resolved-dnstls.h | 5 +++- src/resolve/resolved-manager.c | 8 +++++++ src/resolve/resolved-manager.h | 5 ++++ 8 files changed, 63 insertions(+), 30 deletions(-) diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index cd6e42e5945..0033de73b4f 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 */ diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c index 4da5121e625..7defd119a4b 100644 --- a/src/resolve/resolved-dnstls-gnutls.c +++ b/src/resolve/resolved-dnstls-gnutls.c @@ -41,7 +41,7 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { 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; @@ -187,19 +187,26 @@ 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); +void dnstls_manager_init(Manager *manager) { + int r; + assert(manager); - if (server->dnstls_data.cert_cred) - gnutls_certificate_free_credentials(server->dnstls_data.cert_cred); + gnutls_certificate_allocate_credentials(&manager->dnstls_data.cert_cred); + r = gnutls_certificate_set_x509_trust_file(manager->dnstls_data.cert_cred, manager->trusted_certificate_file, GNUTLS_X509_FMT_PEM); + if (r < 0) + log_error("Failed to load trusted certificate file %s: %s", manager->trusted_certificate_file, gnutls_strerror(r)); +} - if (server->dnstls_data.session_data.data) - gnutls_free(server->dnstls_data.session_data.data); +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 41c89f27375..af52f04fdf2 100644 --- a/src/resolve/resolved-dnstls-gnutls.h +++ b/src/resolve/resolved-dnstls-gnutls.h @@ -8,8 +8,11 @@ #include #include -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 1a21b9224b4..6b2e1b218f8 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; @@ -336,22 +337,29 @@ 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); +void 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 (manager->dnstls_data.ctx) { + 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); + } +} - if (server->dnstls_data.session) - SSL_SESSION_free(server->dnstls_data.session); +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 0fe72afd0ae..8100d2ba6b0 100644 --- a/src/resolve/resolved-dnstls-openssl.h +++ b/src/resolve/resolved-dnstls-openssl.h @@ -8,8 +8,11 @@ #include #include -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 fdd85eece6a..b01de2d9d20 100644 --- a/src/resolve/resolved-dnstls.h +++ b/src/resolve/resolved-dnstls.h @@ -5,6 +5,7 @@ #error This source file requires DNS-over-TLS to be enabled #endif +typedef struct DnsTlsManagerData DnsTlsManagerData; typedef struct DnsTlsServerData DnsTlsServerData; typedef struct DnsTlsStreamData DnsTlsStreamData; @@ -28,5 +29,7 @@ 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); + +void dnstls_manager_init(Manager *manager); +void dnstls_manager_free(Manager *manager); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 5f63a21e01d..433d50cc2b5 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -597,6 +597,10 @@ int manager_new(Manager **ret) { if (r < 0) log_warning_errno(r, "Failed to parse configuration file: %m"); +#if ENABLE_DNS_OVER_TLS + dnstls_manager_init(m); +#endif + r = sd_event_default(&m->event); if (r < 0) return r; @@ -677,6 +681,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 72171f8c975..0f7d8ee5ee1 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; -- 2.39.2