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>
11 #include "resolved-dns-stream.h"
12 #include "resolved-dnstls.h"
14 DEFINE_TRIVIAL_CLEANUP_FUNC(SSL
*, SSL_free
);
15 DEFINE_TRIVIAL_CLEANUP_FUNC(BIO
*, BIO_free
);
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 SSL_set_session(s
, server
->dnstls_data
.session
);
77 SSL_set_bio(s
, TAKE_PTR(rb
), TAKE_PTR(wb
));
79 if (server
->manager
->dns_over_tls_mode
== DNS_OVER_TLS_YES
) {
81 const unsigned char *ip
;
83 SSL_set_verify(s
, SSL_VERIFY_PEER
, NULL
);
84 v
= SSL_get0_param(s
);
85 ip
= server
->family
== AF_INET
? (const unsigned char*) &server
->address
.in
.s_addr
: server
->address
.in6
.s6_addr
;
86 if (!X509_VERIFY_PARAM_set1_ip(v
, ip
, FAMILY_ADDRESS_SIZE(server
->family
)))
91 stream
->dnstls_data
.handshake
= SSL_do_handshake(s
);
92 if (stream
->dnstls_data
.handshake
<= 0) {
93 error
= SSL_get_error(s
, stream
->dnstls_data
.handshake
);
94 if (!IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
97 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
98 log_debug("Failed to invoke SSL_do_handshake: %s", errbuf
);
103 stream
->encrypted
= true;
104 stream
->dnstls_data
.ssl
= TAKE_PTR(s
);
106 r
= dnstls_flush_write_buffer(stream
);
107 if (r
< 0 && r
!= -EAGAIN
) {
108 SSL_free(TAKE_PTR(stream
->dnstls_data
.ssl
));
115 void dnstls_stream_free(DnsStream
*stream
) {
117 assert(stream
->encrypted
);
119 if (stream
->dnstls_data
.ssl
)
120 SSL_free(stream
->dnstls_data
.ssl
);
123 int dnstls_stream_on_io(DnsStream
*stream
, uint32_t revents
) {
127 assert(stream
->encrypted
);
128 assert(stream
->dnstls_data
.ssl
);
130 /* Flush write buffer when requested by OpenSSL */
131 if ((revents
& EPOLLOUT
) && (stream
->dnstls_events
& EPOLLOUT
)) {
132 r
= dnstls_flush_write_buffer(stream
);
137 if (stream
->dnstls_data
.shutdown
) {
139 r
= SSL_shutdown(stream
->dnstls_data
.ssl
);
141 stream
->dnstls_events
= 0;
143 r
= dnstls_flush_write_buffer(stream
);
149 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
150 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
151 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
153 r
= dnstls_flush_write_buffer(stream
);
158 } else if (error
== SSL_ERROR_SYSCALL
) {
160 log_debug_errno(errno
, "Failed to invoke SSL_shutdown, ignoring: %m");
164 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
165 log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf
);
169 stream
->dnstls_events
= 0;
170 stream
->dnstls_data
.shutdown
= false;
172 r
= dnstls_flush_write_buffer(stream
);
176 dns_stream_unref(stream
);
177 return DNSTLS_STREAM_CLOSED
;
178 } else if (stream
->dnstls_data
.handshake
<= 0) {
180 stream
->dnstls_data
.handshake
= SSL_do_handshake(stream
->dnstls_data
.ssl
);
181 if (stream
->dnstls_data
.handshake
<= 0) {
182 error
= SSL_get_error(stream
->dnstls_data
.ssl
, stream
->dnstls_data
.handshake
);
183 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
184 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
185 r
= dnstls_flush_write_buffer(stream
);
193 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
194 return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED
),
195 "Failed to invoke SSL_do_handshake: %s",
200 stream
->dnstls_events
= 0;
201 r
= dnstls_flush_write_buffer(stream
);
209 int dnstls_stream_shutdown(DnsStream
*stream
, int error
) {
214 assert(stream
->encrypted
);
215 assert(stream
->dnstls_data
.ssl
);
217 if (stream
->server
) {
218 s
= SSL_get1_session(stream
->dnstls_data
.ssl
);
220 if (stream
->server
->dnstls_data
.session
)
221 SSL_SESSION_free(stream
->server
->dnstls_data
.session
);
223 stream
->server
->dnstls_data
.session
= s
;
227 if (error
== ETIMEDOUT
) {
229 r
= SSL_shutdown(stream
->dnstls_data
.ssl
);
231 if (!stream
->dnstls_data
.shutdown
) {
232 stream
->dnstls_data
.shutdown
= true;
233 dns_stream_ref(stream
);
236 stream
->dnstls_events
= 0;
238 r
= dnstls_flush_write_buffer(stream
);
244 ssl_error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
245 if (IN_SET(ssl_error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
246 stream
->dnstls_events
= ssl_error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
247 r
= dnstls_flush_write_buffer(stream
);
248 if (r
< 0 && r
!= -EAGAIN
)
251 if (!stream
->dnstls_data
.shutdown
) {
252 stream
->dnstls_data
.shutdown
= true;
253 dns_stream_ref(stream
);
256 } else if (ssl_error
== SSL_ERROR_SYSCALL
) {
258 log_debug_errno(errno
, "Failed to invoke SSL_shutdown, ignoring: %m");
262 ERR_error_string_n(ssl_error
, errbuf
, sizeof(errbuf
));
263 log_debug("Failed to invoke SSL_shutdown, ignoring: %s", errbuf
);
267 stream
->dnstls_events
= 0;
268 r
= dnstls_flush_write_buffer(stream
);
276 ssize_t
dnstls_stream_write(DnsStream
*stream
, const char *buf
, size_t count
) {
281 assert(stream
->encrypted
);
282 assert(stream
->dnstls_data
.ssl
);
286 ss
= r
= SSL_write(stream
->dnstls_data
.ssl
, buf
, count
);
288 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
289 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
290 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
292 } else if (error
== SSL_ERROR_ZERO_RETURN
) {
293 stream
->dnstls_events
= 0;
298 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
299 log_debug("Failed to invoke SSL_write: %s", errbuf
);
300 stream
->dnstls_events
= 0;
304 stream
->dnstls_events
= 0;
306 r
= dnstls_flush_write_buffer(stream
);
313 ssize_t
dnstls_stream_read(DnsStream
*stream
, void *buf
, size_t count
) {
318 assert(stream
->encrypted
);
319 assert(stream
->dnstls_data
.ssl
);
323 ss
= r
= SSL_read(stream
->dnstls_data
.ssl
, buf
, count
);
325 error
= SSL_get_error(stream
->dnstls_data
.ssl
, r
);
326 if (IN_SET(error
, SSL_ERROR_WANT_READ
, SSL_ERROR_WANT_WRITE
)) {
327 stream
->dnstls_events
= error
== SSL_ERROR_WANT_READ
? EPOLLIN
: EPOLLOUT
;
329 } else if (error
== SSL_ERROR_ZERO_RETURN
) {
330 stream
->dnstls_events
= 0;
335 ERR_error_string_n(error
, errbuf
, sizeof(errbuf
));
336 log_debug("Failed to invoke SSL_read: %s", errbuf
);
337 stream
->dnstls_events
= 0;
341 stream
->dnstls_events
= 0;
343 /* flush write buffer in cache of renegotiation */
344 r
= dnstls_flush_write_buffer(stream
);
351 void dnstls_server_free(DnsServer
*server
) {
354 if (server
->dnstls_data
.session
)
355 SSL_SESSION_free(server
->dnstls_data
.session
);
358 int dnstls_manager_init(Manager
*manager
) {
362 ERR_load_crypto_strings();
363 SSL_load_error_strings();
364 manager
->dnstls_data
.ctx
= SSL_CTX_new(TLS_client_method());
366 if (!manager
->dnstls_data
.ctx
)
369 SSL_CTX_set_min_proto_version(manager
->dnstls_data
.ctx
, TLS1_2_VERSION
);
370 SSL_CTX_set_options(manager
->dnstls_data
.ctx
, SSL_OP_NO_COMPRESSION
);
371 r
= SSL_CTX_set_default_verify_paths(manager
->dnstls_data
.ctx
);
373 log_warning("Failed to load system trust store: %s", ERR_error_string(ERR_get_error(), NULL
));
378 void dnstls_manager_free(Manager
*manager
) {
381 if (manager
->dnstls_data
.ctx
)
382 SSL_CTX_free(manager
->dnstls_data
.ctx
);