mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 19:20:00 -04:00
Merge branch 'artem-backport-tls-related-fixes-from-loopmgr-branch' into 'main'
Backport TLS-related fixes from the loopmgr-branch See merge request isc-projects/bind9!6501
This commit is contained in:
commit
0b221bf326
5 changed files with 154 additions and 49 deletions
|
|
@ -1771,6 +1771,10 @@ void
|
|||
isc__nm_async_tls_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
|
||||
const int tid);
|
||||
|
||||
void
|
||||
isc__nmhandle_tls_setwritetimeout(isc_nmhandle_t *handle,
|
||||
uint64_t write_timeout);
|
||||
|
||||
void
|
||||
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
|
|
|
|||
|
|
@ -569,8 +569,24 @@ void
|
|||
isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout) {
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
REQUIRE(handle->sock->tid == isc_nm_tid());
|
||||
|
||||
handle->sock->write_timeout = write_timeout;
|
||||
switch (handle->sock->type) {
|
||||
case isc_nm_tcpsocket:
|
||||
case isc_nm_udpsocket:
|
||||
case isc_nm_tcpdnssocket:
|
||||
case isc_nm_tlsdnssocket:
|
||||
handle->sock->write_timeout = write_timeout;
|
||||
break;
|
||||
#ifdef HAVE_LIBNGHTTP2
|
||||
case isc_nm_tlssocket:
|
||||
isc__nmhandle_tls_setwritetimeout(handle, write_timeout);
|
||||
break;
|
||||
#endif /* HAVE_LIBNGHTTP2 */
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1059,38 +1059,46 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
|||
pending = (int)ISC_NETMGR_TCP_RECVBUF_SIZE;
|
||||
}
|
||||
|
||||
if ((sock->buf_len + pending) > sock->buf_size) {
|
||||
isc__nm_alloc_dnsbuf(sock,
|
||||
sock->buf_len + pending);
|
||||
}
|
||||
|
||||
len = 0;
|
||||
rv = SSL_read_ex(sock->tls.tls,
|
||||
sock->buf + sock->buf_len,
|
||||
sock->buf_size - sock->buf_len, &len);
|
||||
if (rv != 1) {
|
||||
/*
|
||||
* Process what's in the buffer so far
|
||||
*/
|
||||
result = isc__nm_process_sock_buffer(sock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
if (pending != 0) {
|
||||
if ((sock->buf_len + pending) > sock->buf_size)
|
||||
{
|
||||
isc__nm_alloc_dnsbuf(
|
||||
sock, sock->buf_len + pending);
|
||||
}
|
||||
/*
|
||||
* FIXME: Should we call
|
||||
* isc__nm_failed_read_cb()?
|
||||
*/
|
||||
break;
|
||||
|
||||
len = 0;
|
||||
rv = SSL_read_ex(sock->tls.tls,
|
||||
sock->buf + sock->buf_len,
|
||||
sock->buf_size - sock->buf_len,
|
||||
&len);
|
||||
if (rv != 1) {
|
||||
/*
|
||||
* Process what's in the buffer so far
|
||||
*/
|
||||
result = isc__nm_process_sock_buffer(
|
||||
sock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
}
|
||||
/*
|
||||
* FIXME: Should we call
|
||||
* isc__nm_failed_read_cb()?
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
INSIST((size_t)pending == len);
|
||||
|
||||
sock->buf_len += len;
|
||||
}
|
||||
|
||||
INSIST((size_t)pending == len);
|
||||
|
||||
sock->buf_len += len;
|
||||
|
||||
result = isc__nm_process_sock_buffer(sock);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (pending == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!SSL_is_init_finished(sock->tls.tls)) {
|
||||
if (SSL_is_server(sock->tls.tls)) {
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ tls_process_outgoing(isc_nmsocket_t *sock, bool finish,
|
|||
}
|
||||
|
||||
static int
|
||||
tls_try_handshake(isc_nmsocket_t *sock) {
|
||||
tls_try_handshake(isc_nmsocket_t *sock, isc_result_t *presult) {
|
||||
int rv = 0;
|
||||
isc_nmhandle_t *tlshandle = NULL;
|
||||
|
||||
|
|
@ -341,18 +341,40 @@ tls_try_handshake(isc_nmsocket_t *sock) {
|
|||
isc__nmsocket_log_tls_session_reuse(sock, sock->tlsstream.tls);
|
||||
tlshandle = isc__nmhandle_get(sock, &sock->peer, &sock->iface);
|
||||
if (sock->tlsstream.server) {
|
||||
sock->listener->accept_cb(tlshandle, result,
|
||||
sock->listener->accept_cbarg);
|
||||
result = sock->listener->accept_cb(
|
||||
tlshandle, result,
|
||||
sock->listener->accept_cbarg);
|
||||
} else {
|
||||
tls_call_connect_cb(sock, tlshandle, result);
|
||||
}
|
||||
isc_nmhandle_detach(&tlshandle);
|
||||
sock->tlsstream.state = TLS_IO;
|
||||
|
||||
if (presult != NULL) {
|
||||
*presult = result;
|
||||
}
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static bool
|
||||
tls_try_to_close_unused_socket(isc_nmsocket_t *sock) {
|
||||
if (sock->tlsstream.state > TLS_HANDSHAKE &&
|
||||
sock->statichandle == NULL && sock->tlsstream.nsending == 0)
|
||||
{
|
||||
/*
|
||||
* It seems that no action on the socket has been
|
||||
* scheduled on some point after the handshake, let's
|
||||
* close the connection.
|
||||
*/
|
||||
isc__nmsocket_prep_destroy(sock);
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
static void
|
||||
tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
||||
isc__nm_uvreq_t *send_data, bool finish) {
|
||||
|
|
@ -379,7 +401,7 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||
SSL_set_connect_state(sock->tlsstream.tls);
|
||||
}
|
||||
sock->tlsstream.state = TLS_HANDSHAKE;
|
||||
rv = tls_try_handshake(sock);
|
||||
rv = tls_try_handshake(sock, NULL);
|
||||
INSIST(SSL_is_init_finished(sock->tlsstream.tls) == 0);
|
||||
} else if (sock->tlsstream.state == TLS_CLOSED) {
|
||||
return;
|
||||
|
|
@ -402,7 +424,21 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||
* handshake is done.
|
||||
*/
|
||||
if (sock->tlsstream.state == TLS_HANDSHAKE) {
|
||||
rv = tls_try_handshake(sock);
|
||||
isc_result_t hs_result = ISC_R_UNSET;
|
||||
rv = tls_try_handshake(sock, &hs_result);
|
||||
if (sock->tlsstream.state == TLS_IO &&
|
||||
hs_result != ISC_R_SUCCESS) {
|
||||
/*
|
||||
* The accept callback has been called
|
||||
* unsuccessfully. Let's try to shut
|
||||
* down the TLS connection gracefully.
|
||||
*/
|
||||
INSIST(SSL_is_init_finished(
|
||||
sock->tlsstream.tls) ==
|
||||
1);
|
||||
INSIST(!atomic_load(&sock->client));
|
||||
finish = true;
|
||||
}
|
||||
}
|
||||
} else if (send_data != NULL) {
|
||||
INSIST(received_data == NULL);
|
||||
|
|
@ -430,7 +466,7 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||
/* Decrypt and pass data from network to client */
|
||||
if (sock->tlsstream.state >= TLS_IO && sock->recv_cb != NULL &&
|
||||
!atomic_load(&sock->readpaused) &&
|
||||
sock->statichandle != NULL)
|
||||
sock->statichandle != NULL && !finish)
|
||||
{
|
||||
uint8_t recv_buf[TLS_BUF_SIZE];
|
||||
INSIST(sock->tlsstream.state > TLS_HANDSHAKE);
|
||||
|
|
@ -449,9 +485,9 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||
* nullified (it happens in netmgr.c). If it is
|
||||
* the case, then it means that we are not
|
||||
* interested in keeping the connection alive
|
||||
* anymore. Let's shutdown the SSL session, send
|
||||
* what we have in the SSL buffers, and close
|
||||
* the connection.
|
||||
* anymore. Let's shut down the SSL session,
|
||||
* send what we have in the SSL buffers,
|
||||
* and close the connection.
|
||||
*/
|
||||
if (sock->statichandle == NULL) {
|
||||
finish = true;
|
||||
|
|
@ -493,6 +529,7 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||
switch (tls_status) {
|
||||
case SSL_ERROR_NONE:
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
(void)tls_try_to_close_unused_socket(sock);
|
||||
return;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
if (sock->tlsstream.nsending == 0) {
|
||||
|
|
@ -504,8 +541,17 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||
}
|
||||
return;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
if (tls_try_to_close_unused_socket(sock)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sock->outerhandle == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||
|
||||
if (sock->tlsstream.reading) {
|
||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||
isc_nm_resumeread(sock->outerhandle);
|
||||
} else if (sock->tlsstream.state == TLS_HANDSHAKE) {
|
||||
sock->tlsstream.reading = true;
|
||||
|
|
@ -649,6 +695,9 @@ isc_nm_listentls(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
|
|||
isc_nmsocket_t *tsock = NULL;
|
||||
|
||||
REQUIRE(VALID_NM(mgr));
|
||||
if (atomic_load(&mgr->closing)) {
|
||||
return (ISC_R_SHUTTINGDOWN);
|
||||
}
|
||||
|
||||
tlssock = isc_mem_get(mgr->mctx, sizeof(*tlssock));
|
||||
|
||||
|
|
@ -807,6 +856,10 @@ isc__nm_tls_resumeread(isc_nmhandle_t *handle) {
|
|||
if (!atomic_compare_exchange_strong(&handle->sock->readpaused,
|
||||
&(bool){ false }, false))
|
||||
{
|
||||
if (inactive(handle->sock)) {
|
||||
return;
|
||||
}
|
||||
|
||||
async_tls_do_bio(handle->sock);
|
||||
}
|
||||
}
|
||||
|
|
@ -904,6 +957,11 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
|||
|
||||
REQUIRE(VALID_NM(mgr));
|
||||
|
||||
if (atomic_load(&mgr->closing)) {
|
||||
cb(NULL, ISC_R_SHUTTINGDOWN, cbarg);
|
||||
return;
|
||||
}
|
||||
|
||||
nsock = isc_mem_get(mgr->mctx, sizeof(*nsock));
|
||||
isc__nmsocket_init(nsock, mgr, isc_nm_tlssocket, local);
|
||||
nsock->result = ISC_R_UNSET;
|
||||
|
|
@ -929,13 +987,14 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||
isc_nmhandle_t *tlshandle = NULL;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(tlssock));
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
|
||||
tlssock->tid = isc_nm_tid();
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
INSIST(VALID_NMHANDLE(handle));
|
||||
|
||||
tlssock->iface = handle->sock->iface;
|
||||
tlssock->peer = handle->sock->peer;
|
||||
if (isc__nm_closing(tlssock)) {
|
||||
|
|
@ -1045,8 +1104,8 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
|
|||
} else if (sock->type == isc_nm_tlssocket) {
|
||||
if (sock->tlsstream.tls != NULL) {
|
||||
/*
|
||||
* Let's shutdown the TLS session properly so that the
|
||||
* session will remain resumable, if required.
|
||||
* Let's shut down the TLS session properly so that
|
||||
* the session will remain resumable, if required.
|
||||
*/
|
||||
tls_try_shutdown(sock->tlsstream.tls, true);
|
||||
tls_keep_client_tls_session(sock);
|
||||
|
|
@ -1119,6 +1178,23 @@ isc__nmhandle_tls_keepalive(isc_nmhandle_t *handle, bool value) {
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nmhandle_tls_setwritetimeout(isc_nmhandle_t *handle,
|
||||
uint64_t write_timeout) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
||||
REQUIRE(VALID_NMHANDLE(handle));
|
||||
REQUIRE(VALID_NMSOCK(handle->sock));
|
||||
REQUIRE(handle->sock->type == isc_nm_tlssocket);
|
||||
|
||||
sock = handle->sock;
|
||||
if (sock->outerhandle != NULL) {
|
||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||
|
||||
isc_nmhandle_setwritetimeout(sock->outerhandle, write_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
|
|
|
|||
|
|
@ -384,9 +384,12 @@ noop_recv_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
|
|||
static unsigned int
|
||||
noop_accept_cb(isc_nmhandle_t *handle, unsigned int result, void *cbarg) {
|
||||
UNUSED(handle);
|
||||
UNUSED(result);
|
||||
UNUSED(cbarg);
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
(void)atomic_fetch_add(&saccepts, 1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -1217,7 +1220,7 @@ stream_noresponse(void **state __attribute__((unused))) {
|
|||
stream_connect(connect_connect_cb, NULL, T_CONNECT);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
WAIT_FOR_EQ(csends, 1);
|
||||
WAIT_FOR_EQ(saccepts, 1);
|
||||
|
||||
isc_nm_stoplistening(listen_sock);
|
||||
isc_nmsocket_close(&listen_sock);
|
||||
|
|
@ -1231,7 +1234,7 @@ stream_noresponse(void **state __attribute__((unused))) {
|
|||
X(ssends);
|
||||
|
||||
atomic_assert_int_eq(cconnects, 1);
|
||||
atomic_assert_int_eq(csends, 1);
|
||||
atomic_assert_int_eq(saccepts, 1);
|
||||
atomic_assert_int_eq(creads, 0);
|
||||
atomic_assert_int_eq(sreads, 0);
|
||||
atomic_assert_int_eq(ssends, 0);
|
||||
|
|
@ -1729,7 +1732,7 @@ ISC_RUN_TEST_IMPL(tcpdns_noresponse) {
|
|||
connect_connect_cb, NULL, T_CONNECT);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
WAIT_FOR_EQ(csends, 1);
|
||||
WAIT_FOR_EQ(saccepts, 1);
|
||||
|
||||
isc_nm_stoplistening(listen_sock);
|
||||
isc_nmsocket_close(&listen_sock);
|
||||
|
|
@ -1743,7 +1746,7 @@ ISC_RUN_TEST_IMPL(tcpdns_noresponse) {
|
|||
X(ssends);
|
||||
|
||||
atomic_assert_int_eq(cconnects, 1);
|
||||
atomic_assert_int_eq(csends, 1);
|
||||
atomic_assert_int_eq(saccepts, 1);
|
||||
atomic_assert_int_eq(creads, 0);
|
||||
atomic_assert_int_eq(sreads, 0);
|
||||
atomic_assert_int_eq(ssends, 0);
|
||||
|
|
@ -2282,7 +2285,7 @@ ISC_RUN_TEST_IMPL(tlsdns_noresponse) {
|
|||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
WAIT_FOR_EQ(csends, 1);
|
||||
WAIT_FOR_EQ(saccepts, 1);
|
||||
|
||||
isc_nm_stoplistening(listen_sock);
|
||||
isc_nmsocket_close(&listen_sock);
|
||||
|
|
@ -2296,7 +2299,7 @@ ISC_RUN_TEST_IMPL(tlsdns_noresponse) {
|
|||
X(ssends);
|
||||
|
||||
atomic_assert_int_eq(cconnects, 1);
|
||||
atomic_assert_int_eq(csends, 1);
|
||||
atomic_assert_int_eq(saccepts, 1);
|
||||
atomic_assert_int_eq(creads, 0);
|
||||
atomic_assert_int_eq(sreads, 0);
|
||||
atomic_assert_int_eq(ssends, 0);
|
||||
|
|
@ -2747,7 +2750,6 @@ ISC_RUN_TEST_IMPL(tlsdns_listen_noalpn) {
|
|||
|
||||
WAIT_FOR_EQ(saccepts, 1);
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
WAIT_FOR_EQ(csends, 1);
|
||||
|
||||
isc_nm_stoplistening(listen_sock);
|
||||
isc_nmsocket_close(&listen_sock);
|
||||
|
|
@ -2762,7 +2764,6 @@ ISC_RUN_TEST_IMPL(tlsdns_listen_noalpn) {
|
|||
|
||||
atomic_assert_int_eq(saccepts, 1);
|
||||
atomic_assert_int_eq(cconnects, 1);
|
||||
atomic_assert_int_eq(csends, 1);
|
||||
atomic_assert_int_eq(creads, 0);
|
||||
atomic_assert_int_eq(sreads, 0);
|
||||
atomic_assert_int_eq(ssends, 0);
|
||||
|
|
|
|||
Loading…
Reference in a new issue