mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch 'artem-backport-tls-related-fixes-from-loopmgr-branch-v9-18' into 'v9_18'
[Backport to 9.18] Backport TLS-related fixes from the loopmgr-branch See merge request isc-projects/bind9!6550
This commit is contained in:
commit
3d98312a7b
5 changed files with 154 additions and 49 deletions
|
|
@ -1787,6 +1787,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -572,8 +572,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
|
||||
|
|
|
|||
|
|
@ -1061,38 +1061,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)) {
|
||||
|
|
|
|||
|
|
@ -324,7 +324,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;
|
||||
|
||||
|
|
@ -342,18 +342,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) {
|
||||
|
|
@ -380,7 +402,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;
|
||||
|
|
@ -403,7 +425,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);
|
||||
|
|
@ -431,7 +467,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);
|
||||
|
|
@ -450,9 +486,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;
|
||||
|
|
@ -494,6 +530,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) {
|
||||
|
|
@ -505,8 +542,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;
|
||||
|
|
@ -652,6 +698,9 @@ isc_nm_listentls(isc_nm_t *mgr, 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));
|
||||
|
||||
|
|
@ -812,6 +861,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -909,6 +962,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->extrahandlesize = extrahandlesize;
|
||||
|
|
@ -935,13 +993,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)) {
|
||||
|
|
@ -1051,8 +1110,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);
|
||||
|
|
@ -1125,6 +1184,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;
|
||||
|
|
|
|||
|
|
@ -386,9 +386,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);
|
||||
}
|
||||
|
||||
|
|
@ -1209,7 +1212,7 @@ stream_noresponse(void **state __attribute__((unused))) {
|
|||
stream_connect(connect_connect_cb, NULL, T_CONNECT, 0);
|
||||
|
||||
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);
|
||||
|
|
@ -1223,7 +1226,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);
|
||||
|
|
@ -1728,7 +1731,7 @@ ISC_RUN_TEST_IMPL(tcpdns_noresponse) {
|
|||
connect_connect_cb, NULL, T_CONNECT, 0);
|
||||
|
||||
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);
|
||||
|
|
@ -1742,7 +1745,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);
|
||||
|
|
@ -2279,7 +2282,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);
|
||||
|
|
@ -2293,7 +2296,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);
|
||||
|
|
@ -2743,7 +2746,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);
|
||||
|
|
@ -2758,7 +2760,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