1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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 "openssl-util.h"
13 #include "resolved-dns-stream.h"
14 #include "resolved-dnstls.h"
15 #include "resolved-manager.h"
17 static int dnstls_flush_write_buffer(DnsStream
*stream
) {
21 assert(stream
->encrypted
);
23 if (stream
->dnstls_data
.buffer_offset
< stream
->dnstls_data
.write_buffer
->length
) {
24 assert(stream
->dnstls_data
.write_buffer
->data
);
27 iov
[0] = IOVEC_MAKE(stream
->dnstls_data
.write_buffer
->data
+ stream
->dnstls_data
.buffer_offset
,
28 stream
->dnstls_data
.write_buffer
->length
- stream
->dnstls_data
.buffer_offset
);
29 ss
= dns_stream_writev(stream
, iov
, 1, DNS_STREAM_WRITE_TLS_DATA
);
32 stream
->dnstls_events
|= EPOLLOUT
;
36 stream
->dnstls_data
.buffer_offset
+= ss
;
38 if (stream
->dnstls_data
.buffer_offset
< stream
->dnstls_data
.write_buffer
->length
) {
39 stream
->dnstls_events
|= EPOLLOUT
;
42 BIO_reset(SSL_get_wbio(stream
->dnstls_data
.ssl
));
43 stream
->dnstls_data
.buffer_offset
= 0;
51 int dnstls_stream_connect_tls(DnsStream
*stream
, DnsServer
*server
) {
52 _cleanup_(BIO_freep
) BIO
*rb
= NULL
, *wb
= NULL
;
53 _cleanup_(SSL_freep
) SSL
*s
= NULL
;
57 assert(stream
->manager
);
60 rb
= BIO_new_socket(stream
->fd
, 0);
64 wb
= BIO_new(BIO_s_mem());
68 BIO_get_mem_ptr(wb
, &stream
->dnstls_data
.write_buffer
);
69 stream
->dnstls_data
.buffer_offset
= 0;
71 s
= SSL_new(stream
->manager
->dnstls_data
.ctx
);
75 SSL_set_connect_state(s
);
76 r
= SSL_set_session(s
, server
->dnstls_data
.session
);
79 SSL_set_bio(s
, TAKE_PTR(rb
), TAKE_PTR(wb
));
81 if (server
->manager
->dns_over_tls_mode
== DNS_OVER_TLS_YES
) {
84 SSL_set_verify(s
, SSL_VERIFY_PEER
, NULL
);
85 v
= SSL_get0_param(s
);
86 if (server
->server_name
) {
87 X509_VERIFY_PARAM_set_hostflags(v
, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
);
88 if (X509_VERIFY_PARAM_set1_host(v
, server
->server_name
, 0) == 0)
91 const unsigned char *ip
;
92 ip
= server
->family
== AF_INET
? (const unsigned char*) &server
->address
.in
.s_addr
: server
->address
.in6
.s6_addr
;
93 if (X509_VERIFY_PARAM_set1_ip(v
, ip
, FAMILY_ADDRESS_SIZE(server
->family
)) == 0)
98 if (server
->server_name
) {
99 r
= SSL_set_tlsext_host_name(s
, server
->server_name
);
103 error
= ERR_get_error();
104 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
105 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL
), "Failed to set server name: %s", errbuf
);
110 stream
->dnstls_data
.handshake
= SSL_do_handshake(s
);
111 if (stream
->dnstls_data
.handshake
<= 0) {
112 error
= SSL_get_error(s
, stream
->dnstls_data
.handshake
);
113 if (!IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
116 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
117 return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED
),
118 "Failed to invoke SSL_do_handshake: %s", errbuf
);
122 stream
->encrypted
= true;
123 stream
->dnstls_data
.ssl
= TAKE_PTR(s
);
125 r
= dnstls_flush_write_buffer(stream
);
126 if (r
< 0 && r
!= -EAGAIN
) {
127 SSL_free(TAKE_PTR(stream
->dnstls_data
.ssl
));
134 void dnstls_stream_free(DnsStream
*stream
) {
136 assert(stream
->encrypted
);
138 if (stream
->dnstls_data
.ssl
)
139 SSL_free(stream
->dnstls_data
.ssl
);
142 int dnstls_stream_on_io(DnsStream
*stream
, uint32_t revents
) {
146 assert(stream
->encrypted
);
147 assert(stream
->dnstls_data
.ssl
);
149 /* Flush write buffer when requested by OpenSSL */
150 if ((revents
& EPOLLOUT
) && (stream
->dnstls_events
& EPOLLOUT
)) {
151 r
= dnstls_flush_write_buffer(stream
);
156 if (stream
->dnstls_data
.shutdown
) {
158 r
= SSL_shutdown(stream
->dnstls_data
.ssl
);
160 stream
->dnstls_events
= 0;
162 r
= dnstls_flush_write_buffer(stream
);
168 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
169 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
170 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
172 r
= dnstls_flush_write_buffer(stream
);
177 } else if (error
== SSL_ERROR_SYSCALL
) {
179 log_debug_errno(errno
, "Failed to invoke SSL_shutdown, ignoring: %m");
183 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
184 log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf
);
188 stream
->dnstls_events
= 0;
189 stream
->dnstls_data
.shutdown
= false;
191 r
= dnstls_flush_write_buffer(stream
);
195 dns_stream_unref(stream
);
196 return DNSTLS_STREAM_CLOSED
;
197 } else if (stream
->dnstls_data
.handshake
<= 0) {
199 stream
->dnstls_data
.handshake
= SSL_do_handshake(stream
->dnstls_data
.ssl
);
200 if (stream
->dnstls_data
.handshake
<= 0) {
201 error
= SSL_get_error(stream
->dnstls_data
.ssl
, stream
->dnstls_data
.handshake
);
202 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
203 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
204 r
= dnstls_flush_write_buffer(stream
);
212 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
213 return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED
),
214 "Failed to invoke SSL_do_handshake: %s",
219 stream
->dnstls_events
= 0;
220 r
= dnstls_flush_write_buffer(stream
);
228 int dnstls_stream_shutdown(DnsStream
*stream
, int error
) {
233 assert(stream
->encrypted
);
234 assert(stream
->dnstls_data
.ssl
);
236 if (stream
->server
) {
237 s
= SSL_get1_session(stream
->dnstls_data
.ssl
);
239 if (stream
->server
->dnstls_data
.session
)
240 SSL_SESSION_free(stream
->server
->dnstls_data
.session
);
242 stream
->server
->dnstls_data
.session
= s
;
246 if (error
== ETIMEDOUT
) {
248 r
= SSL_shutdown(stream
->dnstls_data
.ssl
);
250 if (!stream
->dnstls_data
.shutdown
) {
251 stream
->dnstls_data
.shutdown
= true;
252 dns_stream_ref(stream
);
255 stream
->dnstls_events
= 0;
257 r
= dnstls_flush_write_buffer(stream
);
263 ssl_error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
264 if (IN_SET(ssl_error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
265 stream
->dnstls_events
= ssl_error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
266 r
= dnstls_flush_write_buffer(stream
);
267 if (r
< 0 && r
!= -EAGAIN
)
270 if (!stream
->dnstls_data
.shutdown
) {
271 stream
->dnstls_data
.shutdown
= true;
272 dns_stream_ref(stream
);
275 } else if (ssl_error
== SSL_ERROR_SYSCALL
) {
277 log_debug_errno(errno
, "Failed to invoke SSL_shutdown, ignoring: %m");
281 ERR_error_string_n(ssl_error
, errbuf
, sizeof(errbuf
));
282 log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf
);
286 stream
->dnstls_events
= 0;
287 r
= dnstls_flush_write_buffer(stream
);
295 ssize_t
dnstls_stream_write(DnsStream
*stream
, const char *buf
, size_t count
) {
300 assert(stream
->encrypted
);
301 assert(stream
->dnstls_data
.ssl
);
305 ss
= r
= SSL_write(stream
->dnstls_data
.ssl
, buf
, count
);
307 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
308 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
309 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
311 } else if (error
== SSL_ERROR_ZERO_RETURN
) {
312 stream
->dnstls_events
= 0;
317 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
318 log_debug("Failed to invoke SSL_write: %s", errbuf
);
319 stream
->dnstls_events
= 0;
323 stream
->dnstls_events
= 0;
325 r
= dnstls_flush_write_buffer(stream
);
332 ssize_t
dnstls_stream_read(DnsStream
*stream
, void *buf
, size_t count
) {
337 assert(stream
->encrypted
);
338 assert(stream
->dnstls_data
.ssl
);
342 ss
= r
= SSL_read(stream
->dnstls_data
.ssl
, buf
, count
);
344 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
345 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
346 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
348 } else if (error
== SSL_ERROR_ZERO_RETURN
) {
349 stream
->dnstls_events
= 0;
354 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
355 log_debug("Failed to invoke SSL_read: %s", errbuf
);
356 stream
->dnstls_events
= 0;
360 stream
->dnstls_events
= 0;
362 /* flush write buffer in cache of renegotiation */
363 r
= dnstls_flush_write_buffer(stream
);
370 bool dnstls_stream_has_buffered_data(DnsStream
*stream
) {
372 assert(stream
->encrypted
);
373 assert(stream
->dnstls_data
.ssl
);
375 return SSL_has_pending(stream
->dnstls_data
.ssl
) > 0;
378 void dnstls_server_free(DnsServer
*server
) {
381 if (server
->dnstls_data
.session
)
382 SSL_SESSION_free(server
->dnstls_data
.session
);
385 int dnstls_manager_init(Manager
*manager
) {
390 ERR_load_crypto_strings();
391 SSL_load_error_strings();
393 manager
->dnstls_data
.ctx
= SSL_CTX_new(TLS_client_method());
394 if (!manager
->dnstls_data
.ctx
)
397 r
= SSL_CTX_set_min_proto_version(manager
->dnstls_data
.ctx
, TLS1_2_VERSION
);
401 (void) SSL_CTX_set_options(manager
->dnstls_data
.ctx
, SSL_OP_NO_COMPRESSION
);
403 r
= SSL_CTX_set_default_verify_paths(manager
->dnstls_data
.ctx
);
405 return log_warning_errno(SYNTHETIC_ERRNO(EIO
),
406 "Failed to load system trust store: %s",
407 ERR_error_string(ERR_get_error(), NULL
));
412 void dnstls_manager_free(Manager
*manager
) {
415 if (manager
->dnstls_data
.ctx
)
416 SSL_CTX_free(manager
->dnstls_data
.ctx
);