1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #if !ENABLE_DNS_OVER_TLS || !DNS_OVER_TLS_USE_OPENSSL
4 #error This source file requires DNS-over-TLS to be enabled and OpenSSL to be available.
7 #include <openssl/bio.h>
8 #include <openssl/err.h>
9 #include <openssl/x509v3.h>
12 #include "resolved-dns-stream.h"
13 #include "resolved-dnstls.h"
14 #include "resolved-manager.h"
16 DEFINE_TRIVIAL_CLEANUP_FUNC(SSL
*, SSL_free
);
17 DEFINE_TRIVIAL_CLEANUP_FUNC(BIO
*, BIO_free
);
19 static int dnstls_flush_write_buffer(DnsStream
*stream
) {
23 assert(stream
->encrypted
);
25 if (stream
->dnstls_data
.buffer_offset
< stream
->dnstls_data
.write_buffer
->length
) {
26 assert(stream
->dnstls_data
.write_buffer
->data
);
29 iov
[0] = IOVEC_MAKE(stream
->dnstls_data
.write_buffer
->data
+ stream
->dnstls_data
.buffer_offset
,
30 stream
->dnstls_data
.write_buffer
->length
- stream
->dnstls_data
.buffer_offset
);
31 ss
= dns_stream_writev(stream
, iov
, 1, DNS_STREAM_WRITE_TLS_DATA
);
34 stream
->dnstls_events
|= EPOLLOUT
;
38 stream
->dnstls_data
.buffer_offset
+= ss
;
40 if (stream
->dnstls_data
.buffer_offset
< stream
->dnstls_data
.write_buffer
->length
) {
41 stream
->dnstls_events
|= EPOLLOUT
;
44 BIO_reset(SSL_get_wbio(stream
->dnstls_data
.ssl
));
45 stream
->dnstls_data
.buffer_offset
= 0;
53 int dnstls_stream_connect_tls(DnsStream
*stream
, DnsServer
*server
) {
54 _cleanup_(BIO_freep
) BIO
*rb
= NULL
, *wb
= NULL
;
55 _cleanup_(SSL_freep
) SSL
*s
= NULL
;
59 assert(stream
->manager
);
62 rb
= BIO_new_socket(stream
->fd
, 0);
66 wb
= BIO_new(BIO_s_mem());
70 BIO_get_mem_ptr(wb
, &stream
->dnstls_data
.write_buffer
);
71 stream
->dnstls_data
.buffer_offset
= 0;
73 s
= SSL_new(stream
->manager
->dnstls_data
.ctx
);
77 SSL_set_connect_state(s
);
78 r
= SSL_set_session(s
, server
->dnstls_data
.session
);
81 SSL_set_bio(s
, TAKE_PTR(rb
), TAKE_PTR(wb
));
83 if (server
->manager
->dns_over_tls_mode
== DNS_OVER_TLS_YES
) {
86 SSL_set_verify(s
, SSL_VERIFY_PEER
, NULL
);
87 v
= SSL_get0_param(s
);
88 if (server
->server_name
) {
89 X509_VERIFY_PARAM_set_hostflags(v
, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
);
90 if (X509_VERIFY_PARAM_set1_host(v
, server
->server_name
, 0) == 0)
93 const unsigned char *ip
;
94 ip
= server
->family
== AF_INET
? (const unsigned char*) &server
->address
.in
.s_addr
: server
->address
.in6
.s6_addr
;
95 if (X509_VERIFY_PARAM_set1_ip(v
, ip
, FAMILY_ADDRESS_SIZE(server
->family
)) == 0)
100 if (server
->server_name
) {
101 r
= SSL_set_tlsext_host_name(s
, server
->server_name
);
105 error
= ERR_get_error();
106 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
107 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to set server name: %s", errbuf
);
112 stream
->dnstls_data
.handshake
= SSL_do_handshake(s
);
113 if (stream
->dnstls_data
.handshake
<= 0) {
114 error
= SSL_get_error(s
, stream
->dnstls_data
.handshake
);
115 if (!IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
118 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
119 return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED
),
120 "Failed to invoke SSL_do_handshake: %s", errbuf
);
124 stream
->encrypted
= true;
125 stream
->dnstls_data
.ssl
= TAKE_PTR(s
);
127 r
= dnstls_flush_write_buffer(stream
);
128 if (r
< 0 && r
!= -EAGAIN
) {
129 SSL_free(TAKE_PTR(stream
->dnstls_data
.ssl
));
136 void dnstls_stream_free(DnsStream
*stream
) {
138 assert(stream
->encrypted
);
140 if (stream
->dnstls_data
.ssl
)
141 SSL_free(stream
->dnstls_data
.ssl
);
144 int dnstls_stream_on_io(DnsStream
*stream
, uint32_t revents
) {
148 assert(stream
->encrypted
);
149 assert(stream
->dnstls_data
.ssl
);
151 /* Flush write buffer when requested by OpenSSL */
152 if ((revents
& EPOLLOUT
) && (stream
->dnstls_events
& EPOLLOUT
)) {
153 r
= dnstls_flush_write_buffer(stream
);
158 if (stream
->dnstls_data
.shutdown
) {
160 r
= SSL_shutdown(stream
->dnstls_data
.ssl
);
162 stream
->dnstls_events
= 0;
164 r
= dnstls_flush_write_buffer(stream
);
170 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
171 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
172 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
174 r
= dnstls_flush_write_buffer(stream
);
179 } else if (error
== SSL_ERROR_SYSCALL
) {
181 log_debug_errno(errno
, "Failed to invoke SSL_shutdown, ignoring: %m");
185 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
186 log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf
);
190 stream
->dnstls_events
= 0;
191 stream
->dnstls_data
.shutdown
= false;
193 r
= dnstls_flush_write_buffer(stream
);
197 dns_stream_unref(stream
);
198 return DNSTLS_STREAM_CLOSED
;
199 } else if (stream
->dnstls_data
.handshake
<= 0) {
201 stream
->dnstls_data
.handshake
= SSL_do_handshake(stream
->dnstls_data
.ssl
);
202 if (stream
->dnstls_data
.handshake
<= 0) {
203 error
= SSL_get_error(stream
->dnstls_data
.ssl
, stream
->dnstls_data
.handshake
);
204 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
205 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
206 r
= dnstls_flush_write_buffer(stream
);
214 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
215 return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED
),
216 "Failed to invoke SSL_do_handshake: %s",
221 stream
->dnstls_events
= 0;
222 r
= dnstls_flush_write_buffer(stream
);
230 int dnstls_stream_shutdown(DnsStream
*stream
, int error
) {
235 assert(stream
->encrypted
);
236 assert(stream
->dnstls_data
.ssl
);
238 if (stream
->server
) {
239 s
= SSL_get1_session(stream
->dnstls_data
.ssl
);
241 if (stream
->server
->dnstls_data
.session
)
242 SSL_SESSION_free(stream
->server
->dnstls_data
.session
);
244 stream
->server
->dnstls_data
.session
= s
;
248 if (error
== ETIMEDOUT
) {
250 r
= SSL_shutdown(stream
->dnstls_data
.ssl
);
252 if (!stream
->dnstls_data
.shutdown
) {
253 stream
->dnstls_data
.shutdown
= true;
254 dns_stream_ref(stream
);
257 stream
->dnstls_events
= 0;
259 r
= dnstls_flush_write_buffer(stream
);
265 ssl_error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
266 if (IN_SET(ssl_error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
267 stream
->dnstls_events
= ssl_error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
268 r
= dnstls_flush_write_buffer(stream
);
269 if (r
< 0 && r
!= -EAGAIN
)
272 if (!stream
->dnstls_data
.shutdown
) {
273 stream
->dnstls_data
.shutdown
= true;
274 dns_stream_ref(stream
);
277 } else if (ssl_error
== SSL_ERROR_SYSCALL
) {
279 log_debug_errno(errno
, "Failed to invoke SSL_shutdown, ignoring: %m");
283 ERR_error_string_n(ssl_error
, errbuf
, sizeof(errbuf
));
284 log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf
);
288 stream
->dnstls_events
= 0;
289 r
= dnstls_flush_write_buffer(stream
);
297 ssize_t
dnstls_stream_write(DnsStream
*stream
, const char *buf
, size_t count
) {
302 assert(stream
->encrypted
);
303 assert(stream
->dnstls_data
.ssl
);
307 ss
= r
= SSL_write(stream
->dnstls_data
.ssl
, buf
, count
);
309 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
310 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
311 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
313 } else if (error
== SSL_ERROR_ZERO_RETURN
) {
314 stream
->dnstls_events
= 0;
319 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
320 log_debug("Failed to invoke SSL_write: %s", errbuf
);
321 stream
->dnstls_events
= 0;
325 stream
->dnstls_events
= 0;
327 r
= dnstls_flush_write_buffer(stream
);
334 ssize_t
dnstls_stream_read(DnsStream
*stream
, void *buf
, size_t count
) {
339 assert(stream
->encrypted
);
340 assert(stream
->dnstls_data
.ssl
);
344 ss
= r
= SSL_read(stream
->dnstls_data
.ssl
, buf
, count
);
346 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
347 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
348 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
350 } else if (error
== SSL_ERROR_ZERO_RETURN
) {
351 stream
->dnstls_events
= 0;
356 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
357 log_debug("Failed to invoke SSL_read: %s", errbuf
);
358 stream
->dnstls_events
= 0;
362 stream
->dnstls_events
= 0;
364 /* flush write buffer in cache of renegotiation */
365 r
= dnstls_flush_write_buffer(stream
);
372 void dnstls_server_free(DnsServer
*server
) {
375 if (server
->dnstls_data
.session
)
376 SSL_SESSION_free(server
->dnstls_data
.session
);
379 int dnstls_manager_init(Manager
*manager
) {
384 ERR_load_crypto_strings();
385 SSL_load_error_strings();
387 manager
->dnstls_data
.ctx
= SSL_CTX_new(TLS_client_method());
388 if (!manager
->dnstls_data
.ctx
)
391 r
= SSL_CTX_set_min_proto_version(manager
->dnstls_data
.ctx
, TLS1_2_VERSION
);
395 (void) SSL_CTX_set_options(manager
->dnstls_data
.ctx
, SSL_OP_NO_COMPRESSION
);
397 r
= SSL_CTX_set_default_verify_paths(manager
->dnstls_data
.ctx
);
399 return log_warning_errno(SYNTHETIC_ERRNO(EIO
),
400 "Failed to load system trust store: %s",
401 ERR_error_string(ERR_get_error(), NULL
));
406 void dnstls_manager_free(Manager
*manager
) {
409 if (manager
->dnstls_data
.ctx
)
410 SSL_CTX_free(manager
->dnstls_data
.ctx
);