/src/bind9/lib/isc/netmgr/tlsstream.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
5 | | * |
6 | | * This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
9 | | * |
10 | | * See the COPYRIGHT file distributed with this work for additional |
11 | | * information regarding copyright ownership. |
12 | | */ |
13 | | |
14 | | #include <errno.h> |
15 | | #include <libgen.h> |
16 | | #include <unistd.h> |
17 | | |
18 | | #include <openssl/err.h> |
19 | | #include <openssl/ssl.h> |
20 | | |
21 | | #include <isc/async.h> |
22 | | #include <isc/atomic.h> |
23 | | #include <isc/buffer.h> |
24 | | #include <isc/log.h> |
25 | | #include <isc/magic.h> |
26 | | #include <isc/mem.h> |
27 | | #include <isc/netmgr.h> |
28 | | #include <isc/once.h> |
29 | | #include <isc/quota.h> |
30 | | #include <isc/random.h> |
31 | | #include <isc/refcount.h> |
32 | | #include <isc/region.h> |
33 | | #include <isc/result.h> |
34 | | #include <isc/sockaddr.h> |
35 | | #include <isc/stdtime.h> |
36 | | #include <isc/thread.h> |
37 | | #include <isc/util.h> |
38 | | #include <isc/uv.h> |
39 | | |
40 | | #include "../openssl_shim.h" |
41 | | #include "netmgr-int.h" |
42 | | |
43 | 0 | #define TLS_BUF_SIZE (UINT16_MAX) |
44 | | |
45 | 0 | #define TLS_MAX_SEND_BUF_SIZE (UINT16_MAX + UINT16_MAX / 2) |
46 | | |
47 | | #define MAX_DNS_MESSAGE_SIZE (UINT16_MAX) |
48 | | |
49 | | #ifdef ISC_NETMGR_TRACE |
50 | | ISC_ATTR_UNUSED static const char * |
51 | | tls_status2str(int tls_status) { |
52 | | switch (tls_status) { |
53 | | case SSL_ERROR_NONE: |
54 | | return "SSL_ERROR_NONE"; |
55 | | case SSL_ERROR_ZERO_RETURN: |
56 | | return "SSL_ERROR_ZERO_RETURN"; |
57 | | case SSL_ERROR_WANT_WRITE: |
58 | | return "SSL_ERROR_WANT_WRITE"; |
59 | | case SSL_ERROR_WANT_READ: |
60 | | return "SSL_ERROR_WANT_READ"; |
61 | | case SSL_ERROR_SSL: |
62 | | return "SSL_ERROR_SSL"; |
63 | | default: |
64 | | UNREACHABLE(); |
65 | | } |
66 | | } |
67 | | |
68 | | ISC_ATTR_UNUSED static const char * |
69 | | state2str(int state) { |
70 | | switch (state) { |
71 | | case TLS_INIT: |
72 | | return "TLS_INIT"; |
73 | | case TLS_HANDSHAKE: |
74 | | return "TLS_HANDSHAKE"; |
75 | | case TLS_IO: |
76 | | return "TLS_IO"; |
77 | | case TLS_CLOSED: |
78 | | return "TLS_CLOSED"; |
79 | | default: |
80 | | UNREACHABLE(); |
81 | | } |
82 | | } |
83 | | #endif /* ISC_NETMGR_TRACE */ |
84 | | |
85 | | static isc_result_t |
86 | 0 | tls_error_to_result(const int tls_err, const int tls_state, isc_tls_t *tls) { |
87 | 0 | switch (tls_err) { |
88 | 0 | case SSL_ERROR_ZERO_RETURN: |
89 | 0 | return ISC_R_EOF; |
90 | 0 | case SSL_ERROR_SSL: |
91 | 0 | if (tls != NULL && tls_state < TLS_IO && |
92 | 0 | SSL_get_verify_result(tls) != X509_V_OK) |
93 | 0 | { |
94 | 0 | return ISC_R_TLSBADPEERCERT; |
95 | 0 | } |
96 | 0 | return ISC_R_TLSERROR; |
97 | 0 | default: |
98 | 0 | return ISC_R_UNEXPECTED; |
99 | 0 | } |
100 | 0 | } |
101 | | |
102 | | static void |
103 | | tls_read_start(isc_nmsocket_t *restrict sock); |
104 | | |
105 | | static void |
106 | | tls_read_stop(isc_nmsocket_t *sock); |
107 | | |
108 | | static void |
109 | | tls_failed_read_cb(isc_nmsocket_t *sock, const isc_result_t result); |
110 | | |
111 | | static void |
112 | | tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data, |
113 | | isc__nm_uvreq_t *send_data, bool finish); |
114 | | |
115 | | static void |
116 | | tls_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region, |
117 | | void *cbarg); |
118 | | |
119 | | static void |
120 | | async_tls_do_bio(isc_nmsocket_t *sock); |
121 | | |
122 | | static void |
123 | | tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx); |
124 | | |
125 | | static void |
126 | | tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener); |
127 | | |
128 | | static isc_tlsctx_t * |
129 | | tls_get_listener_tlsctx(isc_nmsocket_t *listener, const isc_tid_t tid); |
130 | | |
131 | | static void |
132 | | tls_keep_client_tls_session(isc_nmsocket_t *sock); |
133 | | |
134 | | static void |
135 | | tls_try_shutdown(isc_tls_t *tls, const bool quite); |
136 | | |
137 | | static void |
138 | | tls_try_to_enable_tcp_nodelay(isc_nmsocket_t *tlssock); |
139 | | |
140 | | /* |
141 | | * The socket is closing, outerhandle has been detached, listener is |
142 | | * inactive, or the netmgr is closing: any operation on it should abort |
143 | | * with ISC_R_CANCELED. |
144 | | */ |
145 | | static bool |
146 | 0 | inactive(isc_nmsocket_t *sock) { |
147 | 0 | return !isc__nmsocket_active(sock) || sock->closing || |
148 | 0 | sock->outerhandle == NULL || |
149 | 0 | !isc__nmsocket_active(sock->outerhandle->sock) || |
150 | 0 | sock->outerhandle->sock->closing || |
151 | 0 | isc__nm_closing(sock->worker); |
152 | 0 | } |
153 | | |
154 | | static void |
155 | | tls_call_connect_cb(isc_nmsocket_t *sock, isc_nmhandle_t *handle, |
156 | 0 | const isc_result_t result) { |
157 | 0 | INSIST(sock->connect_cb != NULL); |
158 | 0 | sock->connect_cb(handle, result, sock->connect_cbarg); |
159 | 0 | if (result != ISC_R_SUCCESS) { |
160 | 0 | isc__nmsocket_clearcb(handle->sock); |
161 | 0 | } |
162 | 0 | } |
163 | | |
164 | | static void |
165 | 0 | tls_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { |
166 | 0 | isc_nmsocket_tls_send_req_t *send_req = |
167 | 0 | (isc_nmsocket_tls_send_req_t *)cbarg; |
168 | 0 | isc_nmsocket_t *tlssock = NULL; |
169 | 0 | bool finish = send_req->finish; |
170 | 0 | isc_nm_cb_t send_cb = NULL; |
171 | 0 | void *send_cbarg = NULL; |
172 | 0 | isc_nmhandle_t *send_handle = NULL; |
173 | |
|
174 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
175 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
176 | 0 | REQUIRE(VALID_NMSOCK(send_req->tlssock)); |
177 | |
|
178 | 0 | tlssock = send_req->tlssock; |
179 | 0 | send_req->tlssock = NULL; |
180 | 0 | send_cb = send_req->cb; |
181 | 0 | send_req->cb = NULL; |
182 | 0 | send_cbarg = send_req->cbarg; |
183 | 0 | send_req->cbarg = NULL; |
184 | 0 | send_handle = send_req->handle; |
185 | 0 | send_req->handle = NULL; |
186 | |
|
187 | 0 | if (finish) { |
188 | 0 | tls_try_shutdown(tlssock->tlsstream.tls, true); |
189 | 0 | } |
190 | | |
191 | | /* Try to keep the object to be reused later - to avoid an allocation */ |
192 | 0 | if (tlssock->tlsstream.send_req == NULL) { |
193 | 0 | tlssock->tlsstream.send_req = send_req; |
194 | | /* |
195 | | * We need to ensure that the buffer is not going to grow too |
196 | | * large uncontrollably. We try to keep its size to be no more |
197 | | * than TLS_MAX_SEND_BUF_SIZE. The constant should be larger |
198 | | * than 64 KB for this to work efficiently when combined with |
199 | | * DNS transports. |
200 | | */ |
201 | 0 | if (isc_buffer_length(&send_req->data) > TLS_MAX_SEND_BUF_SIZE) |
202 | 0 | { |
203 | | /* free the underlying buffer */ |
204 | 0 | isc_buffer_clearmctx(&send_req->data); |
205 | 0 | isc_buffer_invalidate(&send_req->data); |
206 | 0 | isc_buffer_init(&send_req->data, send_req->smallbuf, |
207 | 0 | sizeof(send_req->smallbuf)); |
208 | 0 | isc_buffer_setmctx(&send_req->data, |
209 | 0 | handle->sock->worker->mctx); |
210 | 0 | } else { |
211 | 0 | isc_buffer_clear(&send_req->data); |
212 | 0 | } |
213 | 0 | } else { |
214 | 0 | isc_buffer_clearmctx(&send_req->data); |
215 | 0 | isc_buffer_invalidate(&send_req->data); |
216 | 0 | isc_mem_put(handle->sock->worker->mctx, send_req, |
217 | 0 | sizeof(*send_req)); |
218 | 0 | } |
219 | 0 | tlssock->tlsstream.nsending--; |
220 | |
|
221 | 0 | if (send_cb != NULL) { |
222 | 0 | INSIST(VALID_NMHANDLE(tlssock->statichandle)); |
223 | 0 | send_cb(send_handle, eresult, send_cbarg); |
224 | 0 | isc_nmhandle_detach(&send_handle); |
225 | | /* The last handle has been just detached: close the underlying |
226 | | * socket. */ |
227 | 0 | if (tlssock->statichandle == NULL) { |
228 | 0 | finish = true; |
229 | 0 | } |
230 | 0 | } |
231 | |
|
232 | 0 | if (finish) { |
233 | | /* |
234 | | * If wrapping up, call tls_failed_read() - it will care of |
235 | | * socket de-initialisation and calling the read callback, if |
236 | | * necessary. |
237 | | */ |
238 | 0 | tls_failed_read_cb(tlssock, ISC_R_EOF); |
239 | 0 | } else if (eresult == ISC_R_SUCCESS) { |
240 | 0 | tls_do_bio(tlssock, NULL, NULL, false); |
241 | 0 | } else if (eresult != ISC_R_SUCCESS && |
242 | 0 | tlssock->tlsstream.state <= TLS_HANDSHAKE && |
243 | 0 | !tlssock->tlsstream.server) |
244 | 0 | { |
245 | | /* |
246 | | * We are still waiting for the handshake to complete, but |
247 | | * it isn't going to happen. Call the connect callback, |
248 | | * passing the error code there. |
249 | | * |
250 | | * (Note: tls_failed_read_cb() calls the connect |
251 | | * rather than the read callback in this case. |
252 | | * XXX: clarify?) |
253 | | */ |
254 | 0 | tls_failed_read_cb(tlssock, eresult); |
255 | 0 | } |
256 | |
|
257 | 0 | isc__nmsocket_detach(&tlssock); |
258 | 0 | } |
259 | | |
260 | | static void |
261 | 0 | tls_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) { |
262 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
263 | 0 | REQUIRE(result != ISC_R_SUCCESS); |
264 | | |
265 | | /* This is TLS counterpart of isc__nm_failed_connect_cb() */ |
266 | 0 | if (!sock->tlsstream.server && |
267 | 0 | (sock->tlsstream.state == TLS_INIT || |
268 | 0 | sock->tlsstream.state == TLS_HANDSHAKE) && |
269 | 0 | sock->connect_cb != NULL) |
270 | 0 | { |
271 | 0 | isc_nmhandle_t *handle = NULL; |
272 | 0 | INSIST(sock->statichandle == NULL); |
273 | 0 | handle = isc__nmhandle_get(sock, &sock->peer, &sock->iface); |
274 | 0 | tls_call_connect_cb(sock, handle, result); |
275 | 0 | isc__nmsocket_clearcb(sock); |
276 | 0 | isc_nmhandle_detach(&handle); |
277 | 0 | goto destroy; |
278 | 0 | } |
279 | | |
280 | 0 | isc__nmsocket_timer_stop(sock); |
281 | | |
282 | | /* Nobody is reading from the socket yet */ |
283 | 0 | if (sock->statichandle == NULL) { |
284 | 0 | goto destroy; |
285 | 0 | } |
286 | | |
287 | | /* This is TLS counterpart of isc__nmsocket_readtimeout_cb() */ |
288 | 0 | if (sock->client && result == ISC_R_TIMEDOUT) { |
289 | 0 | INSIST(sock->statichandle != NULL); |
290 | |
|
291 | 0 | if (sock->recv_cb != NULL) { |
292 | 0 | isc__nm_uvreq_t *req = isc__nm_get_read_req(sock, NULL); |
293 | 0 | isc__nm_readcb(sock, req, ISC_R_TIMEDOUT, false); |
294 | 0 | } |
295 | |
|
296 | 0 | if (isc__nmsocket_timer_running(sock)) { |
297 | | /* Timer was restarted, bail-out */ |
298 | 0 | return; |
299 | 0 | } |
300 | | |
301 | 0 | isc__nmsocket_clearcb(sock); |
302 | |
|
303 | 0 | goto destroy; |
304 | 0 | } |
305 | | |
306 | | /* |
307 | | * We don't need to check for .nsending, as the callbacks will be |
308 | | * cleared at the time the tls_senddone() tries to call it for the |
309 | | * second time. |
310 | | */ |
311 | | |
312 | 0 | if (sock->recv_cb != NULL) { |
313 | 0 | isc__nm_uvreq_t *req = isc__nm_get_read_req(sock, NULL); |
314 | 0 | isc__nmsocket_clearcb(sock); |
315 | 0 | isc__nm_readcb(sock, req, result, false); |
316 | 0 | } |
317 | |
|
318 | 0 | destroy: |
319 | 0 | isc__nmsocket_prep_destroy(sock); |
320 | 0 | } |
321 | | |
322 | | void |
323 | | isc__nm_tls_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result, |
324 | 0 | bool async ISC_ATTR_UNUSED) { |
325 | 0 | if (!inactive(sock) && sock->tlsstream.state == TLS_IO) { |
326 | 0 | tls_do_bio(sock, NULL, NULL, true); |
327 | 0 | return; |
328 | 0 | } |
329 | | |
330 | 0 | tls_failed_read_cb(sock, result); |
331 | 0 | } |
332 | | |
333 | | static void |
334 | 0 | tls_do_bio_cb(void *arg) { |
335 | 0 | isc_nmsocket_t *sock = arg; |
336 | |
|
337 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
338 | |
|
339 | 0 | tls_do_bio(sock, NULL, NULL, false); |
340 | |
|
341 | 0 | isc__nmsocket_detach(&sock); |
342 | 0 | } |
343 | | |
344 | | static void |
345 | 0 | async_tls_do_bio(isc_nmsocket_t *sock) { |
346 | 0 | isc__nmsocket_attach(sock, &(isc_nmsocket_t *){ NULL }); |
347 | 0 | isc_async_run(sock->worker->loop, tls_do_bio_cb, sock); |
348 | 0 | } |
349 | | |
350 | | static int |
351 | | tls_send_outgoing(isc_nmsocket_t *sock, bool finish, isc_nmhandle_t *tlshandle, |
352 | 0 | isc_nm_cb_t cb, void *cbarg) { |
353 | 0 | isc_nmsocket_tls_send_req_t *send_req = NULL; |
354 | 0 | int pending; |
355 | 0 | int rv; |
356 | 0 | size_t len = 0; |
357 | 0 | bool new_send_req = false; |
358 | 0 | isc_region_t used_region = { 0 }; |
359 | 0 | bool shutting_down = isc__nm_closing(sock->worker); |
360 | |
|
361 | 0 | if (shutting_down || inactive(sock)) { |
362 | 0 | if (cb != NULL) { |
363 | 0 | isc_result_t result = shutting_down ? ISC_R_SHUTTINGDOWN |
364 | 0 | : ISC_R_CANCELED; |
365 | 0 | INSIST(VALID_NMHANDLE(tlshandle)); |
366 | 0 | cb(tlshandle, result, cbarg); |
367 | 0 | } |
368 | 0 | return 0; |
369 | 0 | } |
370 | | |
371 | 0 | if (finish) { |
372 | 0 | tls_try_shutdown(sock->tlsstream.tls, false); |
373 | 0 | tls_keep_client_tls_session(sock); |
374 | 0 | } |
375 | |
|
376 | 0 | pending = BIO_pending(sock->tlsstream.bio_out); |
377 | 0 | if (pending <= 0) { |
378 | 0 | return pending; |
379 | 0 | } |
380 | | |
381 | | /* Try to reuse previously allocated object */ |
382 | 0 | if (sock->tlsstream.send_req != NULL) { |
383 | 0 | send_req = sock->tlsstream.send_req; |
384 | 0 | send_req->finish = finish; |
385 | 0 | sock->tlsstream.send_req = NULL; |
386 | 0 | } else { |
387 | 0 | send_req = isc_mem_get(sock->worker->mctx, sizeof(*send_req)); |
388 | 0 | *send_req = (isc_nmsocket_tls_send_req_t){ .finish = finish }; |
389 | 0 | new_send_req = true; |
390 | 0 | } |
391 | |
|
392 | 0 | if (new_send_req) { |
393 | 0 | isc_buffer_init(&send_req->data, &send_req->smallbuf, |
394 | 0 | sizeof(send_req->smallbuf)); |
395 | 0 | isc_buffer_setmctx(&send_req->data, sock->worker->mctx); |
396 | 0 | } |
397 | 0 | INSIST(isc_buffer_remaininglength(&send_req->data) == 0); |
398 | |
|
399 | 0 | isc__nmsocket_attach(sock, &send_req->tlssock); |
400 | 0 | if (cb != NULL) { |
401 | 0 | send_req->cb = cb; |
402 | 0 | send_req->cbarg = cbarg; |
403 | 0 | isc_nmhandle_attach(tlshandle, &send_req->handle); |
404 | 0 | } |
405 | |
|
406 | 0 | RUNTIME_CHECK(isc_buffer_reserve(&send_req->data, pending) == |
407 | 0 | ISC_R_SUCCESS); |
408 | 0 | isc_buffer_add(&send_req->data, pending); |
409 | 0 | rv = BIO_read_ex(sock->tlsstream.bio_out, |
410 | 0 | isc_buffer_base(&send_req->data), pending, &len); |
411 | | /* There's something pending, read must succeed */ |
412 | 0 | RUNTIME_CHECK(rv == 1 && len == (size_t)pending); |
413 | |
|
414 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
415 | |
|
416 | 0 | sock->tlsstream.nsending++; |
417 | 0 | isc_buffer_remainingregion(&send_req->data, &used_region); |
418 | 0 | isc_nm_send(sock->outerhandle, &used_region, tls_senddone, send_req); |
419 | |
|
420 | 0 | return pending; |
421 | 0 | } |
422 | | |
423 | | static int |
424 | | tls_process_outgoing(isc_nmsocket_t *sock, bool finish, |
425 | 0 | isc__nm_uvreq_t *send_data) { |
426 | 0 | int pending; |
427 | |
|
428 | 0 | bool received_shutdown = ((SSL_get_shutdown(sock->tlsstream.tls) & |
429 | 0 | SSL_RECEIVED_SHUTDOWN) != 0); |
430 | 0 | bool sent_shutdown = ((SSL_get_shutdown(sock->tlsstream.tls) & |
431 | 0 | SSL_SENT_SHUTDOWN) != 0); |
432 | |
|
433 | 0 | if (received_shutdown && !sent_shutdown) { |
434 | 0 | finish = true; |
435 | 0 | } |
436 | | |
437 | | /* Data from TLS to network */ |
438 | 0 | if (send_data != NULL) { |
439 | 0 | pending = tls_send_outgoing(sock, finish, send_data->handle, |
440 | 0 | send_data->cb.send, |
441 | 0 | send_data->cbarg); |
442 | 0 | } else { |
443 | 0 | pending = tls_send_outgoing(sock, finish, NULL, NULL, NULL); |
444 | 0 | } |
445 | |
|
446 | 0 | return pending; |
447 | 0 | } |
448 | | |
449 | | static int |
450 | 0 | tls_try_handshake(isc_nmsocket_t *sock, isc_result_t *presult) { |
451 | 0 | REQUIRE(sock->tlsstream.state == TLS_HANDSHAKE); |
452 | |
|
453 | 0 | if (SSL_is_init_finished(sock->tlsstream.tls) == 1) { |
454 | 0 | return 0; |
455 | 0 | } |
456 | | |
457 | 0 | int rv = SSL_do_handshake(sock->tlsstream.tls); |
458 | 0 | if (rv == 1) { |
459 | 0 | isc_nmhandle_t *tlshandle = NULL; |
460 | 0 | isc_result_t result = ISC_R_SUCCESS; |
461 | |
|
462 | 0 | REQUIRE(sock->statichandle == NULL); |
463 | 0 | INSIST(SSL_is_init_finished(sock->tlsstream.tls) == 1); |
464 | |
|
465 | 0 | isc__nmsocket_log_tls_session_reuse(sock, sock->tlsstream.tls); |
466 | 0 | tlshandle = isc__nmhandle_get(sock, &sock->peer, &sock->iface); |
467 | 0 | isc__nmsocket_timer_stop(sock); |
468 | 0 | tls_read_stop(sock); |
469 | |
|
470 | 0 | if (isc__nm_closing(sock->worker)) { |
471 | 0 | result = ISC_R_SHUTTINGDOWN; |
472 | 0 | } |
473 | |
|
474 | 0 | if (sock->tlsstream.server) { |
475 | | /* |
476 | | * The listening sockets are now closed from outer |
477 | | * to inner order, which means that this function |
478 | | * will never be called when the outer socket has |
479 | | * stopped listening. |
480 | | * |
481 | | * Also see 'isc__nmsocket_stop()' - the function used |
482 | | * to shut down the listening TLS socket - for more |
483 | | * details. |
484 | | */ |
485 | 0 | if (result == ISC_R_SUCCESS) { |
486 | 0 | result = sock->accept_cb(tlshandle, result, |
487 | 0 | sock->accept_cbarg); |
488 | 0 | } |
489 | 0 | } else { |
490 | 0 | tls_call_connect_cb(sock, tlshandle, result); |
491 | 0 | } |
492 | 0 | isc_nmhandle_detach(&tlshandle); |
493 | 0 | sock->tlsstream.state = TLS_IO; |
494 | |
|
495 | 0 | SET_IF_NOT_NULL(presult, result); |
496 | 0 | } |
497 | |
|
498 | 0 | return rv; |
499 | 0 | } |
500 | | |
501 | | static bool |
502 | 0 | tls_try_to_close_unused_socket(isc_nmsocket_t *sock) { |
503 | 0 | if (sock->tlsstream.state > TLS_HANDSHAKE && |
504 | 0 | sock->statichandle == NULL && sock->tlsstream.nsending == 0) |
505 | 0 | { |
506 | | /* |
507 | | * It seems that no action on the socket has been |
508 | | * scheduled on some point after the handshake, let's |
509 | | * close the connection. |
510 | | */ |
511 | 0 | isc__nmsocket_prep_destroy(sock); |
512 | 0 | return true; |
513 | 0 | } |
514 | | |
515 | 0 | return false; |
516 | 0 | } |
517 | | |
518 | | static void |
519 | | tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data, |
520 | 0 | isc__nm_uvreq_t *send_data, bool finish) { |
521 | 0 | isc_result_t result = ISC_R_SUCCESS; |
522 | 0 | int pending, tls_status = SSL_ERROR_NONE; |
523 | 0 | int rv = 0; |
524 | 0 | size_t len = 0; |
525 | 0 | int saved_errno = 0; |
526 | |
|
527 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
528 | 0 | REQUIRE(sock->tid == isc_tid()); |
529 | | |
530 | | /* |
531 | | * Clear the TLS error queue so that SSL_get_error() and SSL I/O |
532 | | * routine calls will not get affected by prior error statuses. |
533 | | * |
534 | | * See here: |
535 | | * https://www.openssl.org/docs/man3.0/man3/SSL_get_error.html |
536 | | * |
537 | | * In particular, it mentions the following: |
538 | | * |
539 | | * The current thread's error queue must be empty before the |
540 | | * TLS/SSL I/O operation is attempted, or SSL_get_error() will not |
541 | | * work reliably. |
542 | | * |
543 | | * As we use the result of SSL_get_error() to decide on I/O |
544 | | * operations, we need to ensure that it works reliably by |
545 | | * cleaning the error queue. |
546 | | * |
547 | | * The sum of details: https://stackoverflow.com/a/37980911 |
548 | | */ |
549 | 0 | ERR_clear_error(); |
550 | |
|
551 | 0 | if (sock->tlsstream.state == TLS_INIT) { |
552 | 0 | INSIST(received_data == NULL && send_data == NULL); |
553 | 0 | if (sock->tlsstream.server) { |
554 | 0 | SSL_set_accept_state(sock->tlsstream.tls); |
555 | 0 | } else { |
556 | 0 | SSL_set_connect_state(sock->tlsstream.tls); |
557 | 0 | } |
558 | 0 | sock->tlsstream.state = TLS_HANDSHAKE; |
559 | 0 | rv = tls_try_handshake(sock, NULL); |
560 | 0 | INSIST(SSL_is_init_finished(sock->tlsstream.tls) == 0); |
561 | 0 | isc__nmsocket_timer_restart(sock); |
562 | 0 | } else if (sock->tlsstream.state == TLS_CLOSED) { |
563 | 0 | return; |
564 | 0 | } else { /* initialised and doing I/O */ |
565 | 0 | if (received_data != NULL) { |
566 | 0 | INSIST(send_data == NULL); |
567 | 0 | rv = BIO_write_ex(sock->tlsstream.bio_in, |
568 | 0 | received_data->base, |
569 | 0 | received_data->length, &len); |
570 | 0 | if (rv <= 0 || len != received_data->length) { |
571 | 0 | result = ISC_R_TLSERROR; |
572 | | #if ISC_NETMGR_TRACE |
573 | | saved_errno = errno; |
574 | | #endif |
575 | 0 | goto error; |
576 | 0 | } |
577 | | |
578 | | /* |
579 | | * Only after doing the IO we can check whether SSL |
580 | | * handshake is done. |
581 | | */ |
582 | 0 | if (sock->tlsstream.state == TLS_HANDSHAKE) { |
583 | 0 | isc_result_t hs_result = ISC_R_UNSET; |
584 | 0 | rv = tls_try_handshake(sock, &hs_result); |
585 | 0 | if (sock->tlsstream.state == TLS_IO && |
586 | 0 | hs_result != ISC_R_SUCCESS) |
587 | 0 | { |
588 | | /* |
589 | | * The accept/connect callback has been |
590 | | * called unsuccessfully. Let's try to |
591 | | * shut down the TLS connection |
592 | | * gracefully. |
593 | | */ |
594 | 0 | INSIST(SSL_is_init_finished( |
595 | 0 | sock->tlsstream.tls) == |
596 | 0 | 1); |
597 | 0 | finish = true; |
598 | 0 | } |
599 | 0 | } |
600 | 0 | } else if (send_data != NULL) { |
601 | 0 | INSIST(received_data == NULL); |
602 | 0 | INSIST(sock->tlsstream.state > TLS_HANDSHAKE); |
603 | 0 | bool received_shutdown = |
604 | 0 | ((SSL_get_shutdown(sock->tlsstream.tls) & |
605 | 0 | SSL_RECEIVED_SHUTDOWN) != 0); |
606 | 0 | bool sent_shutdown = |
607 | 0 | ((SSL_get_shutdown(sock->tlsstream.tls) & |
608 | 0 | SSL_SENT_SHUTDOWN) != 0); |
609 | 0 | bool write_failed = false; |
610 | 0 | if (*(uint16_t *)send_data->tcplen != 0) { |
611 | 0 | size_t sendlen = 0; |
612 | 0 | uint8_t sendbuf[MAX_DNS_MESSAGE_SIZE + |
613 | 0 | sizeof(uint16_t)]; |
614 | | /* |
615 | | * There is a DNS message length to write - do |
616 | | * it. |
617 | | */ |
618 | | |
619 | | /* |
620 | | * There's no SSL_writev(), so we need to use a |
621 | | * local buffer to assemble the whole message |
622 | | */ |
623 | 0 | INSIST(send_data->uvbuf.len <= |
624 | 0 | MAX_DNS_MESSAGE_SIZE); |
625 | |
|
626 | 0 | sendlen = send_data->uvbuf.len + |
627 | 0 | sizeof(uint16_t); |
628 | 0 | memmove(sendbuf, send_data->tcplen, |
629 | 0 | sizeof(uint16_t)); |
630 | 0 | memmove(sendbuf + sizeof(uint16_t), |
631 | 0 | send_data->uvbuf.base, |
632 | 0 | send_data->uvbuf.len); |
633 | | |
634 | | /* Write data */ |
635 | 0 | rv = SSL_write_ex(sock->tlsstream.tls, sendbuf, |
636 | 0 | sendlen, &len); |
637 | 0 | if (rv != 1 || len != sendlen) { |
638 | 0 | write_failed = true; |
639 | 0 | } |
640 | 0 | } else { |
641 | | /* Write data only */ |
642 | 0 | rv = SSL_write_ex(sock->tlsstream.tls, |
643 | 0 | send_data->uvbuf.base, |
644 | 0 | send_data->uvbuf.len, &len); |
645 | 0 | if (rv != 1 || len != send_data->uvbuf.len) { |
646 | 0 | write_failed = true; |
647 | 0 | } |
648 | 0 | } |
649 | |
|
650 | 0 | if (write_failed) { |
651 | 0 | result = received_shutdown || sent_shutdown |
652 | 0 | ? ISC_R_CANCELED |
653 | 0 | : ISC_R_TLSERROR; |
654 | 0 | send_data->cb.send(send_data->handle, result, |
655 | 0 | send_data->cbarg); |
656 | 0 | send_data = NULL; |
657 | 0 | return; |
658 | 0 | } |
659 | 0 | } |
660 | | |
661 | | /* Decrypt and pass data from network to client */ |
662 | 0 | if (sock->tlsstream.state >= TLS_IO && sock->recv_cb != NULL && |
663 | 0 | sock->statichandle != NULL && sock->reading && !finish) |
664 | 0 | { |
665 | 0 | bool was_new_data = false; |
666 | 0 | uint8_t recv_buf[TLS_BUF_SIZE]; |
667 | 0 | INSIST(sock->tlsstream.state > TLS_HANDSHAKE); |
668 | 0 | while ((rv = SSL_read_ex(sock->tlsstream.tls, recv_buf, |
669 | 0 | TLS_BUF_SIZE, &len)) == 1) |
670 | 0 | { |
671 | 0 | isc_region_t region; |
672 | 0 | region = (isc_region_t){ .base = &recv_buf[0], |
673 | 0 | .length = len }; |
674 | |
|
675 | 0 | was_new_data = true; |
676 | 0 | INSIST(VALID_NMHANDLE(sock->statichandle)); |
677 | 0 | sock->recv_cb(sock->statichandle, ISC_R_SUCCESS, |
678 | 0 | ®ion, sock->recv_cbarg); |
679 | | /* The handle could have been detached in |
680 | | * sock->recv_cb, making the sock->statichandle |
681 | | * nullified (it happens in netmgr.c). If it is |
682 | | * the case, then it means that we are not |
683 | | * interested in keeping the connection alive |
684 | | * anymore. Let's shut down the SSL session, |
685 | | * send what we have in the SSL buffers, |
686 | | * and close the connection. |
687 | | */ |
688 | 0 | if (sock->statichandle == NULL) { |
689 | 0 | finish = true; |
690 | 0 | break; |
691 | 0 | } else if (sock->recv_cb == NULL) { |
692 | | /* |
693 | | * The 'sock->recv_cb' might have been |
694 | | * nullified during the call to |
695 | | * 'sock->recv_cb'. That could happen, |
696 | | * e.g. by an indirect call to |
697 | | * 'isc_nmhandle_close()' from within |
698 | | * the callback when wrapping up. |
699 | | * |
700 | | * In this case, let's close the TLS |
701 | | * connection. |
702 | | */ |
703 | 0 | finish = true; |
704 | 0 | break; |
705 | 0 | } else if (!sock->reading) { |
706 | | /* |
707 | | * Reading has been paused from withing |
708 | | * the context of read callback - stop |
709 | | * processing incoming data. |
710 | | */ |
711 | 0 | break; |
712 | 0 | } |
713 | 0 | } |
714 | |
|
715 | 0 | if (was_new_data && !sock->manual_read_timer) { |
716 | | /* |
717 | | * Some data has been decrypted, it is the right |
718 | | * time to stop the read timer as it will be |
719 | | * restarted on the next read attempt. |
720 | | */ |
721 | 0 | isc__nmsocket_timer_stop(sock); |
722 | 0 | } |
723 | 0 | } |
724 | 0 | } |
725 | | |
726 | | /* |
727 | | * Setting 'finish' to 'true' means that we are about to close the |
728 | | * TLS stream (we intend to send TLS shutdown message to the |
729 | | * remote side). After that no new data can be received, so we |
730 | | * should stop the timer regardless of the |
731 | | * 'sock->manual_read_timer' value. |
732 | | */ |
733 | 0 | if (finish) { |
734 | 0 | isc__nmsocket_timer_stop(sock); |
735 | 0 | } |
736 | |
|
737 | 0 | errno = 0; |
738 | 0 | tls_status = SSL_get_error(sock->tlsstream.tls, rv); |
739 | 0 | saved_errno = errno; |
740 | | |
741 | | /* See "BUGS" section at: |
742 | | * https://www.openssl.org/docs/man1.1.1/man3/SSL_get_error.html |
743 | | * |
744 | | * It is mentioned there that when TLS status equals |
745 | | * SSL_ERROR_SYSCALL AND errno == 0 it means that underlying |
746 | | * transport layer returned EOF prematurely. However, we are |
747 | | * managing the transport ourselves, so we should just resume |
748 | | * reading from the TCP socket. |
749 | | * |
750 | | * It seems that this case has been handled properly on modern |
751 | | * versions of OpenSSL. That being said, the situation goes in |
752 | | * line with the manual: it is briefly mentioned there that |
753 | | * SSL_ERROR_SYSCALL might be returned not only in a case of |
754 | | * low-level errors (like system call failures). |
755 | | */ |
756 | 0 | if (tls_status == SSL_ERROR_SYSCALL && saved_errno == 0 && |
757 | 0 | received_data == NULL && send_data == NULL && finish == false) |
758 | 0 | { |
759 | 0 | tls_status = SSL_ERROR_WANT_READ; |
760 | 0 | } |
761 | |
|
762 | 0 | pending = tls_process_outgoing(sock, finish, send_data); |
763 | 0 | if (pending > 0 && tls_status != SSL_ERROR_SSL) { |
764 | 0 | return; |
765 | 0 | } |
766 | | |
767 | 0 | switch (tls_status) { |
768 | 0 | case SSL_ERROR_NONE: |
769 | 0 | case SSL_ERROR_ZERO_RETURN: |
770 | 0 | (void)tls_try_to_close_unused_socket(sock); |
771 | 0 | return; |
772 | 0 | case SSL_ERROR_WANT_WRITE: |
773 | 0 | if (sock->tlsstream.nsending == 0) { |
774 | | /* |
775 | | * Launch tls_do_bio asynchronously. If we're sending |
776 | | * already the send callback will call it. |
777 | | */ |
778 | 0 | async_tls_do_bio(sock); |
779 | 0 | } |
780 | 0 | return; |
781 | 0 | case SSL_ERROR_WANT_READ: |
782 | 0 | if (tls_try_to_close_unused_socket(sock) || |
783 | 0 | sock->outerhandle == NULL) |
784 | 0 | { |
785 | 0 | return; |
786 | 0 | } else if (sock->reading == false && |
787 | 0 | sock->tlsstream.state == TLS_HANDSHAKE) |
788 | 0 | { |
789 | | /* |
790 | | * We need to read data when doing handshake even if |
791 | | * 'sock->reading == false'. It will be stopped when |
792 | | * handshake is completed. |
793 | | */ |
794 | 0 | tls_read_start(sock); |
795 | 0 | return; |
796 | 0 | } else if (sock->reading == false) { |
797 | 0 | return; |
798 | 0 | } |
799 | | |
800 | 0 | tls_read_start(sock); |
801 | 0 | return; |
802 | 0 | default: |
803 | 0 | result = tls_error_to_result(tls_status, sock->tlsstream.state, |
804 | 0 | sock->tlsstream.tls); |
805 | 0 | break; |
806 | 0 | } |
807 | | |
808 | 0 | error: |
809 | | #if ISC_NETMGR_TRACE |
810 | | isc__nmsocket_log(sock, ISC_LOG_NOTICE, |
811 | | "SSL error in BIO: %d %s (errno: %d). Arguments: " |
812 | | "received_data: %p, " |
813 | | "send_data: %p, finish: %s", |
814 | | tls_status, isc_result_totext(result), saved_errno, |
815 | | received_data, send_data, finish ? "true" : "false"); |
816 | | #endif |
817 | 0 | tls_failed_read_cb(sock, result); |
818 | 0 | } |
819 | | |
820 | | static void |
821 | | tls_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region, |
822 | 0 | void *cbarg) { |
823 | 0 | isc_nmsocket_t *tlssock = (isc_nmsocket_t *)cbarg; |
824 | |
|
825 | 0 | REQUIRE(VALID_NMSOCK(tlssock)); |
826 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
827 | 0 | REQUIRE(tlssock->tid == isc_tid()); |
828 | |
|
829 | 0 | if (result != ISC_R_SUCCESS) { |
830 | 0 | tls_failed_read_cb(tlssock, result); |
831 | 0 | return; |
832 | 0 | } else if (isc__nmsocket_closing(handle->sock)) { |
833 | 0 | tls_failed_read_cb(tlssock, ISC_R_CANCELED); |
834 | 0 | return; |
835 | 0 | } |
836 | | |
837 | 0 | REQUIRE(handle == tlssock->outerhandle); |
838 | 0 | tls_do_bio(tlssock, region, NULL, false); |
839 | 0 | } |
840 | | |
841 | | static isc_result_t |
842 | 0 | initialize_tls(isc_nmsocket_t *sock, bool server) { |
843 | 0 | REQUIRE(sock->tid == isc_tid()); |
844 | |
|
845 | 0 | sock->tlsstream.bio_in = BIO_new(BIO_s_mem()); |
846 | 0 | if (sock->tlsstream.bio_in == NULL) { |
847 | 0 | isc_tls_free(&sock->tlsstream.tls); |
848 | 0 | return ISC_R_TLSERROR; |
849 | 0 | } |
850 | 0 | sock->tlsstream.bio_out = BIO_new(BIO_s_mem()); |
851 | 0 | if (sock->tlsstream.bio_out == NULL) { |
852 | 0 | BIO_free_all(sock->tlsstream.bio_in); |
853 | 0 | sock->tlsstream.bio_in = NULL; |
854 | 0 | isc_tls_free(&sock->tlsstream.tls); |
855 | 0 | return ISC_R_TLSERROR; |
856 | 0 | } |
857 | | |
858 | 0 | if (BIO_set_mem_eof_return(sock->tlsstream.bio_in, EOF) != 1 || |
859 | 0 | BIO_set_mem_eof_return(sock->tlsstream.bio_out, EOF) != 1) |
860 | 0 | { |
861 | 0 | goto error; |
862 | 0 | } |
863 | | |
864 | 0 | SSL_set_bio(sock->tlsstream.tls, sock->tlsstream.bio_in, |
865 | 0 | sock->tlsstream.bio_out); |
866 | 0 | sock->tlsstream.server = server; |
867 | 0 | sock->tlsstream.nsending = 0; |
868 | 0 | sock->tlsstream.state = TLS_INIT; |
869 | 0 | if (sock->tlsstream.sni_hostname != NULL) { |
870 | 0 | INSIST(sock->client); |
871 | 0 | const int ret = SSL_set_tlsext_host_name( |
872 | 0 | sock->tlsstream.tls, sock->tlsstream.sni_hostname); |
873 | 0 | if (ret != 1) { |
874 | 0 | goto error; |
875 | 0 | } |
876 | 0 | } |
877 | 0 | return ISC_R_SUCCESS; |
878 | 0 | error: |
879 | 0 | isc_tls_free(&sock->tlsstream.tls); |
880 | 0 | sock->tlsstream.bio_out = sock->tlsstream.bio_in = NULL; |
881 | 0 | return ISC_R_TLSERROR; |
882 | 0 | } |
883 | | |
884 | | static void |
885 | 0 | tls_try_to_enable_tcp_nodelay(isc_nmsocket_t *tlssock) { |
886 | | /* |
887 | | * Try to enable TCP_NODELAY for TLS connections by default to speed up |
888 | | * the handshakes, just like other software (e.g. NGINX) does. |
889 | | */ |
890 | 0 | isc_result_t result = isc_nmhandle_set_tcp_nodelay(tlssock->outerhandle, |
891 | 0 | true); |
892 | 0 | tlssock->tlsstream.tcp_nodelay_value = (result == ISC_R_SUCCESS); |
893 | 0 | } |
894 | | |
895 | | static isc_result_t |
896 | 0 | tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { |
897 | 0 | isc_nmsocket_t *tlslistensock = (isc_nmsocket_t *)cbarg; |
898 | 0 | isc_nmsocket_t *tlssock = NULL; |
899 | 0 | isc_tlsctx_t *tlsctx = NULL; |
900 | 0 | isc_sockaddr_t local; |
901 | | |
902 | | /* If accept() was unsuccessful we can't do anything */ |
903 | 0 | if (result != ISC_R_SUCCESS) { |
904 | 0 | return result; |
905 | 0 | } |
906 | | |
907 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
908 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
909 | 0 | REQUIRE(VALID_NMSOCK(tlslistensock)); |
910 | 0 | REQUIRE(tlslistensock->type == isc_nm_tlslistener); |
911 | |
|
912 | 0 | if (isc__nm_closing(handle->sock->worker)) { |
913 | 0 | return ISC_R_SHUTTINGDOWN; |
914 | 0 | } else if (isc__nmsocket_closing(handle->sock)) { |
915 | 0 | return ISC_R_CANCELED; |
916 | 0 | } |
917 | | |
918 | 0 | local = isc_nmhandle_localaddr(handle); |
919 | | /* |
920 | | * We need to create a 'wrapper' tlssocket for this connection. |
921 | | */ |
922 | 0 | tlssock = isc_mempool_get(handle->sock->worker->nmsocket_pool); |
923 | 0 | isc__nmsocket_init(tlssock, handle->sock->worker, isc_nm_tlssocket, |
924 | 0 | &local, NULL); |
925 | 0 | isc__nmsocket_attach(tlslistensock, &tlssock->server); |
926 | | |
927 | | /* We need to initialize SSL now to reference SSL_CTX properly */ |
928 | 0 | tlsctx = tls_get_listener_tlsctx(tlslistensock, isc_tid()); |
929 | 0 | RUNTIME_CHECK(tlsctx != NULL); |
930 | 0 | isc_tlsctx_attach(tlsctx, &tlssock->tlsstream.ctx); |
931 | 0 | tlssock->tlsstream.tls = isc_tls_create(tlssock->tlsstream.ctx); |
932 | 0 | if (tlssock->tlsstream.tls == NULL) { |
933 | 0 | tlssock->closed = true; |
934 | 0 | isc_tlsctx_free(&tlssock->tlsstream.ctx); |
935 | 0 | isc__nmsocket_detach(&tlssock->server); |
936 | 0 | isc__nmsocket_detach(&tlssock); |
937 | 0 | return ISC_R_TLSERROR; |
938 | 0 | } |
939 | | |
940 | 0 | tlssock->accept_cb = tlslistensock->accept_cb; |
941 | 0 | tlssock->accept_cbarg = tlslistensock->accept_cbarg; |
942 | 0 | isc__nmsocket_attach(handle->sock, &tlssock->listener); |
943 | 0 | isc_nmhandle_attach(handle, &tlssock->outerhandle); |
944 | 0 | tlssock->peer = isc_nmhandle_peeraddr(handle); |
945 | 0 | tlssock->read_timeout = atomic_load_relaxed(&isc__netmgr->init); |
946 | | |
947 | | /* |
948 | | * Hold a reference to tlssock in the TCP socket: it will |
949 | | * detached in isc__nm_tls_cleanup_data(). |
950 | | */ |
951 | 0 | handle->sock->tlsstream.tlssocket = tlssock; |
952 | |
|
953 | 0 | result = initialize_tls(tlssock, true); |
954 | 0 | if (result != ISC_R_SUCCESS) { |
955 | 0 | isc__nmsocket_log(tlssock, ISC_LOG_ERROR, |
956 | 0 | "TLS initialization failed: %s", |
957 | 0 | isc_result_totext(result)); |
958 | 0 | handle->sock->tlsstream.tlssocket = NULL; |
959 | 0 | isc_nmhandle_detach(&tlssock->outerhandle); |
960 | 0 | tlssock->closed = true; |
961 | 0 | isc_tlsctx_free(&tlssock->tlsstream.ctx); |
962 | 0 | isc__nmsocket_detach(&tlssock->listener); |
963 | 0 | isc__nmsocket_detach(&tlssock->server); |
964 | 0 | isc__nmsocket_detach(&tlssock); |
965 | 0 | return result; |
966 | 0 | } |
967 | | |
968 | 0 | tls_try_to_enable_tcp_nodelay(tlssock); |
969 | |
|
970 | 0 | isc__nmhandle_set_manual_timer(tlssock->outerhandle, true); |
971 | 0 | tls_do_bio(tlssock, NULL, NULL, false); |
972 | 0 | return result; |
973 | 0 | } |
974 | | |
975 | | isc_result_t |
976 | | isc_nm_listentls(uint32_t workers, isc_sockaddr_t *iface, |
977 | | isc_nm_accept_cb_t accept_cb, void *accept_cbarg, int backlog, |
978 | | isc_quota_t *quota, SSL_CTX *sslctx, bool proxy, |
979 | 0 | isc_nmsocket_t **sockp) { |
980 | 0 | isc_result_t result; |
981 | 0 | isc_nmsocket_t *tlssock = NULL; |
982 | 0 | isc_nmsocket_t *tsock = NULL; |
983 | 0 | isc__networker_t *worker = isc__networker_current(); |
984 | |
|
985 | 0 | REQUIRE(isc_tid() == 0); |
986 | |
|
987 | 0 | if (isc__nm_closing(worker)) { |
988 | 0 | return ISC_R_SHUTTINGDOWN; |
989 | 0 | } |
990 | | |
991 | 0 | if (workers == 0) { |
992 | 0 | workers = isc__netmgr->nloops; |
993 | 0 | } |
994 | 0 | REQUIRE(workers <= isc__netmgr->nloops); |
995 | |
|
996 | 0 | tlssock = isc_mempool_get(worker->nmsocket_pool); |
997 | 0 | isc__nmsocket_init(tlssock, worker, isc_nm_tlslistener, iface, NULL); |
998 | 0 | tlssock->accept_cb = accept_cb; |
999 | 0 | tlssock->accept_cbarg = accept_cbarg; |
1000 | 0 | tls_init_listener_tlsctx(tlssock, sslctx); |
1001 | 0 | tlssock->tlsstream.tls = NULL; |
1002 | | |
1003 | | /* |
1004 | | * tlssock will be a TLS 'wrapper' around an unencrypted stream. |
1005 | | * We set tlssock->outer to a socket listening for a TCP connection. |
1006 | | */ |
1007 | 0 | if (proxy) { |
1008 | 0 | result = isc_nm_listenproxystream( |
1009 | 0 | workers, iface, tlslisten_acceptcb, tlssock, backlog, |
1010 | 0 | quota, NULL, &tlssock->outer); |
1011 | 0 | } else { |
1012 | 0 | result = isc_nm_listentcp(workers, iface, tlslisten_acceptcb, |
1013 | 0 | tlssock, backlog, quota, |
1014 | 0 | &tlssock->outer); |
1015 | 0 | } |
1016 | 0 | if (result != ISC_R_SUCCESS) { |
1017 | 0 | tlssock->closed = true; |
1018 | 0 | isc__nmsocket_detach(&tlssock); |
1019 | 0 | return result; |
1020 | 0 | } |
1021 | | |
1022 | | /* copy the actual port we're listening on into sock->iface */ |
1023 | 0 | if (isc_sockaddr_getport(iface) == 0) { |
1024 | 0 | tlssock->iface = tlssock->outer->iface; |
1025 | 0 | } |
1026 | | |
1027 | | /* wait for listen result */ |
1028 | 0 | isc__nmsocket_attach(tlssock->outer, &tsock); |
1029 | 0 | tlssock->result = result; |
1030 | 0 | tlssock->active = true; |
1031 | 0 | INSIST(tlssock->outer->tlsstream.tlslistener == NULL); |
1032 | 0 | isc__nmsocket_attach(tlssock, &tlssock->outer->tlsstream.tlslistener); |
1033 | 0 | isc__nmsocket_detach(&tsock); |
1034 | 0 | INSIST(result != ISC_R_UNSET); |
1035 | 0 | tlssock->nchildren = tlssock->outer->nchildren; |
1036 | |
|
1037 | 0 | if (result == ISC_R_SUCCESS) { |
1038 | 0 | *sockp = tlssock; |
1039 | 0 | } |
1040 | |
|
1041 | 0 | return result; |
1042 | 0 | } |
1043 | | |
1044 | | static void |
1045 | 0 | tls_send_direct(void *arg) { |
1046 | 0 | isc__nm_uvreq_t *req = arg; |
1047 | |
|
1048 | 0 | REQUIRE(VALID_UVREQ(req)); |
1049 | |
|
1050 | 0 | isc_nmsocket_t *sock = req->sock; |
1051 | |
|
1052 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1053 | 0 | REQUIRE(sock->tid == isc_tid()); |
1054 | |
|
1055 | 0 | if (isc__nm_closing(sock->worker)) { |
1056 | 0 | req->cb.send(req->handle, ISC_R_SHUTTINGDOWN, req->cbarg); |
1057 | 0 | goto done; |
1058 | 0 | } else if (inactive(sock)) { |
1059 | 0 | req->cb.send(req->handle, ISC_R_CANCELED, req->cbarg); |
1060 | 0 | goto done; |
1061 | 0 | } |
1062 | | |
1063 | 0 | tls_do_bio(sock, NULL, req, false); |
1064 | 0 | done: |
1065 | 0 | isc__nm_uvreq_put(&req); |
1066 | 0 | return; |
1067 | 0 | } |
1068 | | |
1069 | | static void |
1070 | | tls_send(isc_nmhandle_t *handle, const isc_region_t *region, isc_nm_cb_t cb, |
1071 | 0 | void *cbarg, const bool dnsmsg) { |
1072 | 0 | isc__nm_uvreq_t *uvreq = NULL; |
1073 | 0 | isc_nmsocket_t *sock = NULL; |
1074 | |
|
1075 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1076 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
1077 | |
|
1078 | 0 | sock = handle->sock; |
1079 | |
|
1080 | 0 | REQUIRE(sock->type == isc_nm_tlssocket); |
1081 | |
|
1082 | 0 | uvreq = isc__nm_uvreq_get(sock); |
1083 | 0 | isc_nmhandle_attach(handle, &uvreq->handle); |
1084 | 0 | uvreq->cb.send = cb; |
1085 | 0 | uvreq->cbarg = cbarg; |
1086 | 0 | uvreq->uvbuf.base = (char *)region->base; |
1087 | 0 | uvreq->uvbuf.len = region->length; |
1088 | 0 | if (dnsmsg) { |
1089 | 0 | *(uint16_t *)uvreq->tcplen = htons(region->length); |
1090 | 0 | } |
1091 | |
|
1092 | 0 | isc_job_run(sock->worker->loop, &uvreq->job, tls_send_direct, uvreq); |
1093 | 0 | } |
1094 | | |
1095 | | void |
1096 | | isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region, |
1097 | 0 | isc_nm_cb_t cb, void *cbarg) { |
1098 | 0 | tls_send(handle, region, cb, cbarg, false); |
1099 | 0 | } |
1100 | | |
1101 | | void |
1102 | | isc__nm_tls_senddns(isc_nmhandle_t *handle, const isc_region_t *region, |
1103 | 0 | isc_nm_cb_t cb, void *cbarg) { |
1104 | 0 | tls_send(handle, region, cb, cbarg, true); |
1105 | 0 | } |
1106 | | |
1107 | | void |
1108 | 0 | isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { |
1109 | 0 | isc_nmsocket_t *sock = NULL; |
1110 | |
|
1111 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1112 | |
|
1113 | 0 | sock = handle->sock; |
1114 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1115 | 0 | REQUIRE(sock->statichandle == handle); |
1116 | 0 | REQUIRE(sock->tid == isc_tid()); |
1117 | |
|
1118 | 0 | if (isc__nm_closing(sock->worker)) { |
1119 | 0 | cb(handle, ISC_R_SHUTTINGDOWN, NULL, cbarg); |
1120 | 0 | return; |
1121 | 0 | } else if (inactive(sock)) { |
1122 | 0 | cb(handle, ISC_R_CANCELED, NULL, cbarg); |
1123 | 0 | return; |
1124 | 0 | } |
1125 | | |
1126 | 0 | sock->recv_cb = cb; |
1127 | 0 | sock->recv_cbarg = cbarg; |
1128 | 0 | sock->reading = true; |
1129 | |
|
1130 | 0 | async_tls_do_bio(sock); |
1131 | 0 | } |
1132 | | |
1133 | | static void |
1134 | 0 | tls_read_start(isc_nmsocket_t *restrict sock) { |
1135 | 0 | if (sock->tlsstream.reading) { |
1136 | 0 | return; |
1137 | 0 | } |
1138 | 0 | sock->tlsstream.reading = true; |
1139 | |
|
1140 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1141 | |
|
1142 | 0 | isc_nm_read(sock->outerhandle, tls_readcb, sock); |
1143 | 0 | if (!sock->manual_read_timer) { |
1144 | 0 | isc__nmsocket_timer_start(sock); |
1145 | 0 | } |
1146 | 0 | } |
1147 | | |
1148 | | static void |
1149 | 0 | tls_read_stop(isc_nmsocket_t *sock) { |
1150 | 0 | sock->tlsstream.reading = false; |
1151 | 0 | if (sock->outerhandle != NULL) { |
1152 | 0 | isc_nm_read_stop(sock->outerhandle); |
1153 | 0 | } |
1154 | 0 | } |
1155 | | |
1156 | | void |
1157 | 0 | isc__nm_tls_read_stop(isc_nmhandle_t *handle) { |
1158 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1159 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
1160 | |
|
1161 | 0 | handle->sock->reading = false; |
1162 | |
|
1163 | 0 | if (!handle->sock->manual_read_timer) { |
1164 | 0 | isc__nmsocket_timer_stop(handle->sock); |
1165 | 0 | } |
1166 | |
|
1167 | 0 | tls_read_stop(handle->sock); |
1168 | 0 | } |
1169 | | |
1170 | | void |
1171 | 0 | isc__nm_tls_close(isc_nmsocket_t *sock) { |
1172 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1173 | 0 | REQUIRE(sock->type == isc_nm_tlssocket); |
1174 | 0 | REQUIRE(!sock->closing); |
1175 | 0 | REQUIRE(sock->tid == isc_tid()); |
1176 | 0 | REQUIRE(!sock->closed); |
1177 | 0 | REQUIRE(!sock->closing); |
1178 | |
|
1179 | 0 | sock->closing = true; |
1180 | | |
1181 | | /* |
1182 | | * At this point we're certain that there are no |
1183 | | * external references, we can close everything. |
1184 | | */ |
1185 | 0 | tls_read_stop(sock); |
1186 | 0 | if (sock->outerhandle != NULL) { |
1187 | 0 | isc__nmsocket_timer_stop(sock); |
1188 | 0 | isc_nm_read_stop(sock->outerhandle); |
1189 | 0 | isc_nmhandle_close(sock->outerhandle); |
1190 | 0 | isc_nmhandle_detach(&sock->outerhandle); |
1191 | 0 | } |
1192 | |
|
1193 | 0 | if (sock->listener != NULL) { |
1194 | 0 | isc__nmsocket_detach(&sock->listener); |
1195 | 0 | } |
1196 | |
|
1197 | 0 | if (sock->server != NULL) { |
1198 | 0 | isc__nmsocket_detach(&sock->server); |
1199 | 0 | } |
1200 | | |
1201 | | /* Further cleanup performed in isc__nm_tls_cleanup_data() */ |
1202 | 0 | sock->closed = true; |
1203 | 0 | sock->active = false; |
1204 | 0 | sock->tlsstream.state = TLS_CLOSED; |
1205 | 0 | } |
1206 | | |
1207 | | void |
1208 | 0 | isc__nm_tls_stoplistening(isc_nmsocket_t *sock) { |
1209 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1210 | 0 | REQUIRE(sock->type == isc_nm_tlslistener); |
1211 | 0 | REQUIRE(sock->tlsstream.tls == NULL); |
1212 | 0 | REQUIRE(sock->tlsstream.ctx == NULL); |
1213 | |
|
1214 | 0 | isc__nmsocket_stop(sock); |
1215 | 0 | } |
1216 | | |
1217 | | static void |
1218 | | tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg); |
1219 | | |
1220 | | void |
1221 | | isc_nm_tlsconnect(isc_sockaddr_t *local, isc_sockaddr_t *peer, |
1222 | | isc_nm_cb_t connect_cb, void *connect_cbarg, |
1223 | | isc_tlsctx_t *ctx, const char *sni_hostname, |
1224 | | isc_tlsctx_client_session_cache_t *client_sess_cache, |
1225 | | unsigned int timeout, bool proxy, |
1226 | 0 | isc_nm_proxyheader_info_t *proxy_info) { |
1227 | 0 | isc_nmsocket_t *sock = NULL; |
1228 | 0 | isc__networker_t *worker = isc__networker_current(); |
1229 | |
|
1230 | 0 | if (isc__nm_closing(worker)) { |
1231 | 0 | connect_cb(NULL, ISC_R_SHUTTINGDOWN, connect_cbarg); |
1232 | 0 | return; |
1233 | 0 | } |
1234 | | |
1235 | 0 | sock = isc_mempool_get(worker->nmsocket_pool); |
1236 | 0 | isc__nmsocket_init(sock, worker, isc_nm_tlssocket, local, NULL); |
1237 | 0 | sock->connect_cb = connect_cb; |
1238 | 0 | sock->connect_cbarg = connect_cbarg; |
1239 | 0 | sock->connect_timeout = timeout; |
1240 | 0 | isc_tlsctx_attach(ctx, &sock->tlsstream.ctx); |
1241 | 0 | if (sni_hostname != NULL) { |
1242 | 0 | sock->tlsstream.sni_hostname = |
1243 | 0 | isc_mem_strdup(sock->worker->mctx, sni_hostname); |
1244 | 0 | } |
1245 | 0 | sock->client = true; |
1246 | 0 | if (client_sess_cache != NULL) { |
1247 | 0 | INSIST(isc_tlsctx_client_session_cache_getctx( |
1248 | 0 | client_sess_cache) == ctx); |
1249 | 0 | isc_tlsctx_client_session_cache_attach( |
1250 | 0 | client_sess_cache, &sock->tlsstream.client_sess_cache); |
1251 | 0 | } |
1252 | |
|
1253 | 0 | if (proxy) { |
1254 | 0 | isc_nm_proxystreamconnect(local, peer, tcp_connected, sock, |
1255 | 0 | sock->connect_timeout, NULL, NULL, |
1256 | 0 | NULL, proxy_info); |
1257 | 0 | } else { |
1258 | 0 | isc_nm_tcpconnect(local, peer, tcp_connected, sock, |
1259 | 0 | sock->connect_timeout); |
1260 | 0 | } |
1261 | 0 | } |
1262 | | |
1263 | | static void |
1264 | 0 | tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { |
1265 | 0 | isc_nmsocket_t *tlssock = (isc_nmsocket_t *)cbarg; |
1266 | 0 | isc_nmhandle_t *tlshandle = NULL; |
1267 | 0 | isc__networker_t *worker = NULL; |
1268 | |
|
1269 | 0 | REQUIRE(VALID_NMSOCK(tlssock)); |
1270 | |
|
1271 | 0 | worker = tlssock->worker; |
1272 | |
|
1273 | 0 | if (result != ISC_R_SUCCESS) { |
1274 | 0 | goto error; |
1275 | 0 | } |
1276 | | |
1277 | 0 | INSIST(VALID_NMHANDLE(handle)); |
1278 | |
|
1279 | 0 | tlssock->iface = isc_nmhandle_localaddr(handle); |
1280 | 0 | tlssock->peer = isc_nmhandle_peeraddr(handle); |
1281 | 0 | if (isc__nm_closing(worker)) { |
1282 | 0 | result = ISC_R_SHUTTINGDOWN; |
1283 | 0 | goto error; |
1284 | 0 | } else if (isc__nmsocket_closing(handle->sock)) { |
1285 | 0 | result = ISC_R_CANCELED; |
1286 | 0 | goto error; |
1287 | 0 | } |
1288 | | |
1289 | | /* |
1290 | | * We need to initialize SSL now to reference SSL_CTX properly. |
1291 | | */ |
1292 | 0 | tlssock->tlsstream.tls = isc_tls_create(tlssock->tlsstream.ctx); |
1293 | 0 | if (tlssock->tlsstream.tls == NULL) { |
1294 | 0 | result = ISC_R_TLSERROR; |
1295 | 0 | goto error; |
1296 | 0 | } |
1297 | | |
1298 | 0 | result = initialize_tls(tlssock, false); |
1299 | 0 | if (result != ISC_R_SUCCESS) { |
1300 | 0 | goto error; |
1301 | 0 | } |
1302 | 0 | tlssock->peer = isc_nmhandle_peeraddr(handle); |
1303 | 0 | isc_nmhandle_attach(handle, &tlssock->outerhandle); |
1304 | 0 | tlssock->active = true; |
1305 | |
|
1306 | 0 | if (tlssock->tlsstream.client_sess_cache != NULL) { |
1307 | 0 | isc_tlsctx_client_session_cache_reuse_sockaddr( |
1308 | 0 | tlssock->tlsstream.client_sess_cache, &tlssock->peer, |
1309 | 0 | tlssock->tlsstream.tls); |
1310 | 0 | } |
1311 | | |
1312 | | /* |
1313 | | * Hold a reference to tlssock in the TCP socket: it will |
1314 | | * detached in isc__nm_tls_cleanup_data(). |
1315 | | */ |
1316 | 0 | handle->sock->tlsstream.tlssocket = tlssock; |
1317 | |
|
1318 | 0 | tls_try_to_enable_tcp_nodelay(tlssock); |
1319 | |
|
1320 | 0 | isc__nmhandle_set_manual_timer(tlssock->outerhandle, true); |
1321 | 0 | tls_do_bio(tlssock, NULL, NULL, false); |
1322 | 0 | return; |
1323 | 0 | error: |
1324 | 0 | tlshandle = isc__nmhandle_get(tlssock, NULL, NULL); |
1325 | 0 | tlssock->closed = true; |
1326 | 0 | tls_call_connect_cb(tlssock, tlshandle, result); |
1327 | 0 | isc_nmhandle_detach(&tlshandle); |
1328 | 0 | isc__nmsocket_detach(&tlssock); |
1329 | 0 | } |
1330 | | |
1331 | | void |
1332 | 0 | isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) { |
1333 | 0 | if ((sock->type == isc_nm_tcplistener || |
1334 | 0 | sock->type == isc_nm_proxystreamlistener) && |
1335 | 0 | sock->tlsstream.tlslistener != NULL) |
1336 | 0 | { |
1337 | 0 | isc__nmsocket_detach(&sock->tlsstream.tlslistener); |
1338 | 0 | } else if (sock->type == isc_nm_tlslistener) { |
1339 | 0 | tls_cleanup_listener_tlsctx(sock); |
1340 | 0 | } else if (sock->type == isc_nm_tlssocket) { |
1341 | 0 | if (sock->tlsstream.tls != NULL) { |
1342 | | /* |
1343 | | * Let's shut down the TLS session properly so that |
1344 | | * the session will remain resumable, if required. |
1345 | | */ |
1346 | 0 | tls_try_shutdown(sock->tlsstream.tls, true); |
1347 | 0 | tls_keep_client_tls_session(sock); |
1348 | 0 | isc_tls_free(&sock->tlsstream.tls); |
1349 | | /* These are destroyed when we free SSL */ |
1350 | 0 | sock->tlsstream.bio_out = NULL; |
1351 | 0 | sock->tlsstream.bio_in = NULL; |
1352 | 0 | } |
1353 | 0 | if (sock->tlsstream.ctx != NULL) { |
1354 | 0 | isc_tlsctx_free(&sock->tlsstream.ctx); |
1355 | 0 | } |
1356 | 0 | if (sock->tlsstream.sni_hostname != NULL) { |
1357 | 0 | isc_mem_free(sock->worker->mctx, |
1358 | 0 | sock->tlsstream.sni_hostname); |
1359 | 0 | } |
1360 | 0 | if (sock->tlsstream.client_sess_cache != NULL) { |
1361 | 0 | INSIST(sock->client); |
1362 | 0 | isc_tlsctx_client_session_cache_detach( |
1363 | 0 | &sock->tlsstream.client_sess_cache); |
1364 | 0 | } |
1365 | |
|
1366 | 0 | if (sock->tlsstream.send_req != NULL) { |
1367 | 0 | isc_buffer_clearmctx(&sock->tlsstream.send_req->data); |
1368 | 0 | isc_buffer_invalidate(&sock->tlsstream.send_req->data); |
1369 | 0 | isc_mem_put(sock->worker->mctx, |
1370 | 0 | sock->tlsstream.send_req, |
1371 | 0 | sizeof(*sock->tlsstream.send_req)); |
1372 | 0 | } |
1373 | 0 | } else if ((sock->type == isc_nm_tcpsocket || |
1374 | 0 | sock->type == isc_nm_proxystreamsocket) && |
1375 | 0 | sock->tlsstream.tlssocket != NULL) |
1376 | 0 | { |
1377 | | /* |
1378 | | * The TLS socket can't be destroyed until its underlying TCP |
1379 | | * socket is, to avoid possible use-after-free errors. |
1380 | | */ |
1381 | 0 | isc__nmsocket_detach(&sock->tlsstream.tlssocket); |
1382 | 0 | } |
1383 | 0 | } |
1384 | | |
1385 | | void |
1386 | 0 | isc__nm_tls_cleartimeout(isc_nmhandle_t *handle) { |
1387 | 0 | isc_nmsocket_t *sock = NULL; |
1388 | |
|
1389 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1390 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
1391 | 0 | REQUIRE(handle->sock->type == isc_nm_tlssocket); |
1392 | |
|
1393 | 0 | sock = handle->sock; |
1394 | 0 | if (sock->outerhandle != NULL) { |
1395 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1396 | 0 | isc_nmhandle_cleartimeout(sock->outerhandle); |
1397 | 0 | } |
1398 | 0 | } |
1399 | | |
1400 | | void |
1401 | 0 | isc__nm_tls_settimeout(isc_nmhandle_t *handle, uint32_t timeout) { |
1402 | 0 | isc_nmsocket_t *sock = NULL; |
1403 | |
|
1404 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1405 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
1406 | 0 | REQUIRE(handle->sock->type == isc_nm_tlssocket); |
1407 | |
|
1408 | 0 | sock = handle->sock; |
1409 | 0 | if (sock->outerhandle != NULL) { |
1410 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1411 | 0 | isc_nmhandle_settimeout(sock->outerhandle, timeout); |
1412 | 0 | } |
1413 | 0 | } |
1414 | | |
1415 | | void |
1416 | 0 | isc__nmhandle_tls_keepalive(isc_nmhandle_t *handle, bool value) { |
1417 | 0 | isc_nmsocket_t *sock = NULL; |
1418 | |
|
1419 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1420 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
1421 | 0 | REQUIRE(handle->sock->type == isc_nm_tlssocket); |
1422 | |
|
1423 | 0 | sock = handle->sock; |
1424 | 0 | if (sock->outerhandle != NULL) { |
1425 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1426 | |
|
1427 | 0 | isc_nmhandle_keepalive(sock->outerhandle, value); |
1428 | 0 | } |
1429 | 0 | } |
1430 | | |
1431 | | void |
1432 | | isc__nmhandle_tls_setwritetimeout(isc_nmhandle_t *handle, |
1433 | 0 | uint64_t write_timeout) { |
1434 | 0 | isc_nmsocket_t *sock = NULL; |
1435 | |
|
1436 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1437 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
1438 | 0 | REQUIRE(handle->sock->type == isc_nm_tlssocket); |
1439 | |
|
1440 | 0 | sock = handle->sock; |
1441 | 0 | if (sock->outerhandle != NULL) { |
1442 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1443 | |
|
1444 | 0 | isc_nmhandle_setwritetimeout(sock->outerhandle, write_timeout); |
1445 | 0 | } |
1446 | 0 | } |
1447 | | |
1448 | | void |
1449 | 0 | isc__nmsocket_tls_reset(isc_nmsocket_t *sock) { |
1450 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1451 | 0 | REQUIRE(sock->type == isc_nm_tlssocket); |
1452 | |
|
1453 | 0 | if (sock->outerhandle != NULL) { |
1454 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1455 | 0 | REQUIRE(VALID_NMSOCK(sock->outerhandle->sock)); |
1456 | 0 | isc__nmsocket_reset(sock->outerhandle->sock); |
1457 | 0 | } |
1458 | 0 | } |
1459 | | |
1460 | | bool |
1461 | 0 | isc__nmsocket_tls_timer_running(isc_nmsocket_t *sock) { |
1462 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1463 | 0 | REQUIRE(sock->type == isc_nm_tlssocket); |
1464 | |
|
1465 | 0 | if (sock->outerhandle != NULL) { |
1466 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1467 | 0 | REQUIRE(VALID_NMSOCK(sock->outerhandle->sock)); |
1468 | 0 | return isc__nmsocket_timer_running(sock->outerhandle->sock); |
1469 | 0 | } |
1470 | | |
1471 | 0 | return false; |
1472 | 0 | } |
1473 | | |
1474 | | void |
1475 | 0 | isc__nmsocket_tls_timer_restart(isc_nmsocket_t *sock) { |
1476 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1477 | 0 | REQUIRE(sock->type == isc_nm_tlssocket); |
1478 | |
|
1479 | 0 | if (sock->outerhandle != NULL) { |
1480 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1481 | 0 | REQUIRE(VALID_NMSOCK(sock->outerhandle->sock)); |
1482 | 0 | isc__nmsocket_timer_restart(sock->outerhandle->sock); |
1483 | 0 | } |
1484 | 0 | } |
1485 | | |
1486 | | void |
1487 | 0 | isc__nmsocket_tls_timer_stop(isc_nmsocket_t *sock) { |
1488 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1489 | 0 | REQUIRE(sock->type == isc_nm_tlssocket); |
1490 | |
|
1491 | 0 | if (sock->outerhandle != NULL) { |
1492 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1493 | 0 | REQUIRE(VALID_NMSOCK(sock->outerhandle->sock)); |
1494 | 0 | isc__nmsocket_timer_stop(sock->outerhandle->sock); |
1495 | 0 | } |
1496 | 0 | } |
1497 | | |
1498 | | const char * |
1499 | 0 | isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle) { |
1500 | 0 | isc_nmsocket_t *sock = NULL; |
1501 | |
|
1502 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1503 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
1504 | 0 | REQUIRE(handle->sock->type == isc_nm_tlssocket); |
1505 | |
|
1506 | 0 | sock = handle->sock; |
1507 | 0 | if (sock->tlsstream.tls == NULL) { |
1508 | 0 | return NULL; |
1509 | 0 | } |
1510 | | |
1511 | 0 | return isc_tls_verify_peer_result_string(sock->tlsstream.tls); |
1512 | 0 | } |
1513 | | |
1514 | | static void |
1515 | 0 | tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) { |
1516 | 0 | size_t nworkers; |
1517 | |
|
1518 | 0 | REQUIRE(VALID_NMSOCK(listener)); |
1519 | 0 | REQUIRE(ctx != NULL); |
1520 | |
|
1521 | 0 | nworkers = (size_t)isc_loopmgr_nloops(); |
1522 | 0 | INSIST(nworkers > 0); |
1523 | |
|
1524 | 0 | listener->tlsstream.listener_tls_ctx = isc_mem_cget( |
1525 | 0 | listener->worker->mctx, nworkers, sizeof(isc_tlsctx_t *)); |
1526 | 0 | listener->tlsstream.n_listener_tls_ctx = nworkers; |
1527 | 0 | for (size_t i = 0; i < nworkers; i++) { |
1528 | 0 | listener->tlsstream.listener_tls_ctx[i] = NULL; |
1529 | 0 | isc_tlsctx_attach(ctx, |
1530 | 0 | &listener->tlsstream.listener_tls_ctx[i]); |
1531 | 0 | } |
1532 | 0 | } |
1533 | | |
1534 | | static void |
1535 | 0 | tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener) { |
1536 | 0 | REQUIRE(VALID_NMSOCK(listener)); |
1537 | |
|
1538 | 0 | if (listener->tlsstream.listener_tls_ctx == NULL) { |
1539 | 0 | return; |
1540 | 0 | } |
1541 | | |
1542 | 0 | for (size_t i = 0; i < listener->tlsstream.n_listener_tls_ctx; i++) { |
1543 | 0 | isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[i]); |
1544 | 0 | } |
1545 | 0 | isc_mem_cput( |
1546 | 0 | listener->worker->mctx, listener->tlsstream.listener_tls_ctx, |
1547 | 0 | listener->tlsstream.n_listener_tls_ctx, sizeof(isc_tlsctx_t *)); |
1548 | 0 | listener->tlsstream.n_listener_tls_ctx = 0; |
1549 | 0 | } |
1550 | | |
1551 | | static isc_tlsctx_t * |
1552 | 0 | tls_get_listener_tlsctx(isc_nmsocket_t *listener, const isc_tid_t tid) { |
1553 | 0 | REQUIRE(VALID_NMSOCK(listener)); |
1554 | 0 | REQUIRE(tid >= 0); |
1555 | |
|
1556 | 0 | if (listener->tlsstream.listener_tls_ctx == NULL) { |
1557 | 0 | return NULL; |
1558 | 0 | } |
1559 | | |
1560 | 0 | return listener->tlsstream.listener_tls_ctx[tid]; |
1561 | 0 | } |
1562 | | |
1563 | | void |
1564 | | isc__nm_async_tls_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx, |
1565 | 0 | const isc_tid_t tid) { |
1566 | 0 | REQUIRE(tid >= 0); |
1567 | |
|
1568 | 0 | isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[tid]); |
1569 | 0 | isc_tlsctx_attach(tlsctx, &listener->tlsstream.listener_tls_ctx[tid]); |
1570 | 0 | } |
1571 | | |
1572 | | static void |
1573 | 0 | tls_keep_client_tls_session(isc_nmsocket_t *sock) { |
1574 | | /* |
1575 | | * Ensure that the isc_tls_t is being accessed from |
1576 | | * within the worker thread the socket is bound to. |
1577 | | */ |
1578 | 0 | REQUIRE(sock->tid == isc_tid()); |
1579 | 0 | if (sock->tlsstream.client_sess_cache != NULL && |
1580 | 0 | sock->tlsstream.client_session_saved == false) |
1581 | 0 | { |
1582 | 0 | INSIST(sock->client); |
1583 | 0 | isc_tlsctx_client_session_cache_keep_sockaddr( |
1584 | 0 | sock->tlsstream.client_sess_cache, &sock->peer, |
1585 | 0 | sock->tlsstream.tls); |
1586 | 0 | sock->tlsstream.client_session_saved = true; |
1587 | 0 | } |
1588 | 0 | } |
1589 | | |
1590 | | static void |
1591 | 0 | tls_try_shutdown(isc_tls_t *tls, const bool force) { |
1592 | 0 | if (force) { |
1593 | 0 | (void)SSL_set_shutdown(tls, SSL_SENT_SHUTDOWN); |
1594 | 0 | } else if ((SSL_get_shutdown(tls) & SSL_SENT_SHUTDOWN) == 0) { |
1595 | 0 | (void)SSL_shutdown(tls); |
1596 | 0 | } |
1597 | 0 | } |
1598 | | |
1599 | | void |
1600 | 0 | isc__nmhandle_tls_set_manual_timer(isc_nmhandle_t *handle, const bool manual) { |
1601 | 0 | isc_nmsocket_t *sock; |
1602 | |
|
1603 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1604 | 0 | sock = handle->sock; |
1605 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1606 | 0 | REQUIRE(sock->type == isc_nm_tlssocket); |
1607 | 0 | REQUIRE(sock->tid == isc_tid()); |
1608 | |
|
1609 | 0 | sock->manual_read_timer = manual; |
1610 | 0 | } |
1611 | | |
1612 | | void |
1613 | | isc__nmhandle_tls_get_selected_alpn(isc_nmhandle_t *handle, |
1614 | | const unsigned char **alpn, |
1615 | 0 | unsigned int *alpnlen) { |
1616 | 0 | isc_nmsocket_t *sock; |
1617 | |
|
1618 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1619 | 0 | sock = handle->sock; |
1620 | 0 | REQUIRE(VALID_NMSOCK(sock)); |
1621 | 0 | REQUIRE(sock->type == isc_nm_tlssocket); |
1622 | 0 | REQUIRE(sock->tid == isc_tid()); |
1623 | |
|
1624 | 0 | isc_tls_get_selected_alpn(sock->tlsstream.tls, alpn, alpnlen); |
1625 | 0 | } |
1626 | | |
1627 | | isc_result_t |
1628 | 0 | isc__nmhandle_tls_set_tcp_nodelay(isc_nmhandle_t *handle, const bool value) { |
1629 | 0 | isc_nmsocket_t *sock = NULL; |
1630 | 0 | isc_result_t result = ISC_R_FAILURE; |
1631 | |
|
1632 | 0 | REQUIRE(VALID_NMHANDLE(handle)); |
1633 | 0 | REQUIRE(VALID_NMSOCK(handle->sock)); |
1634 | 0 | REQUIRE(handle->sock->type == isc_nm_tlssocket); |
1635 | |
|
1636 | 0 | sock = handle->sock; |
1637 | 0 | if (sock->outerhandle != NULL) { |
1638 | 0 | INSIST(VALID_NMHANDLE(sock->outerhandle)); |
1639 | |
|
1640 | 0 | if (value == sock->tlsstream.tcp_nodelay_value) { |
1641 | 0 | result = ISC_R_SUCCESS; |
1642 | 0 | } else { |
1643 | 0 | result = isc_nmhandle_set_tcp_nodelay(sock->outerhandle, |
1644 | 0 | value); |
1645 | 0 | if (result == ISC_R_SUCCESS) { |
1646 | 0 | sock->tlsstream.tcp_nodelay_value = value; |
1647 | 0 | } |
1648 | 0 | } |
1649 | 0 | } |
1650 | |
|
1651 | 0 | return result; |
1652 | 0 | } |