mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 16:15:27 +00:00
TLS: add manual read timer control mode
This commit adds manual read timer control mode, similarly to TCP. This way the read timer can be controlled manually using: * isc__nmsocket_timer_start(); * isc__nmsocket_timer_stop(); * isc__nmsocket_timer_restart(). The change is required to make it possible to implement more sophisticated read timer control policies in DNS transports, built on top of TLS.
This commit is contained in:
@@ -1570,6 +1570,9 @@ isc__nm_tls_cleartimeout(isc_nmhandle_t *handle);
|
|||||||
void
|
void
|
||||||
isc__nmsocket_tls_reset(isc_nmsocket_t *sock);
|
isc__nmsocket_tls_reset(isc_nmsocket_t *sock);
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nmhandle_tls_set_manual_timer(isc_nmhandle_t *handle, const bool manual);
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle);
|
isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle);
|
||||||
|
|
||||||
|
@@ -2910,6 +2910,11 @@ isc__nmhandle_set_manual_timer(isc_nmhandle_t *handle, const bool manual) {
|
|||||||
case isc_nm_tcpsocket:
|
case isc_nm_tcpsocket:
|
||||||
isc__nmhandle_tcp_set_manual_timer(handle, manual);
|
isc__nmhandle_tcp_set_manual_timer(handle, manual);
|
||||||
return;
|
return;
|
||||||
|
#if HAVE_LIBNGHTTP2
|
||||||
|
case isc_nm_tlssocket:
|
||||||
|
isc__nmhandle_tls_set_manual_timer(handle, manual);
|
||||||
|
return;
|
||||||
|
#endif /* HAVE_LIBNGHTTP2 */
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@@ -458,6 +458,7 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||||||
sock->tlsstream.state = TLS_HANDSHAKE;
|
sock->tlsstream.state = TLS_HANDSHAKE;
|
||||||
rv = tls_try_handshake(sock, NULL);
|
rv = tls_try_handshake(sock, NULL);
|
||||||
INSIST(SSL_is_init_finished(sock->tlsstream.tls) == 0);
|
INSIST(SSL_is_init_finished(sock->tlsstream.tls) == 0);
|
||||||
|
isc__nmsocket_timer_restart(sock);
|
||||||
} else if (sock->tlsstream.state == TLS_CLOSED) {
|
} else if (sock->tlsstream.state == TLS_CLOSED) {
|
||||||
return;
|
return;
|
||||||
} else { /* initialised and doing I/O */
|
} else { /* initialised and doing I/O */
|
||||||
@@ -494,6 +495,11 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||||||
1);
|
1);
|
||||||
INSIST(!atomic_load(&sock->client));
|
INSIST(!atomic_load(&sock->client));
|
||||||
finish = true;
|
finish = true;
|
||||||
|
} else if (sock->tlsstream.state == TLS_IO &&
|
||||||
|
hs_result == ISC_R_SUCCESS &&
|
||||||
|
!sock->tlsstream.server)
|
||||||
|
{
|
||||||
|
INSIST(atomic_load(&sock->client));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (send_data != NULL) {
|
} else if (send_data != NULL) {
|
||||||
@@ -523,6 +529,7 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||||||
if (sock->tlsstream.state >= TLS_IO && sock->recv_cb != NULL &&
|
if (sock->tlsstream.state >= TLS_IO && sock->recv_cb != NULL &&
|
||||||
was_reading && sock->statichandle != NULL && !finish)
|
was_reading && sock->statichandle != NULL && !finish)
|
||||||
{
|
{
|
||||||
|
bool was_new_data = false;
|
||||||
uint8_t recv_buf[TLS_BUF_SIZE];
|
uint8_t recv_buf[TLS_BUF_SIZE];
|
||||||
INSIST(sock->tlsstream.state > TLS_HANDSHAKE);
|
INSIST(sock->tlsstream.state > TLS_HANDSHAKE);
|
||||||
while ((rv = SSL_read_ex(sock->tlsstream.tls, recv_buf,
|
while ((rv = SSL_read_ex(sock->tlsstream.tls, recv_buf,
|
||||||
@@ -532,6 +539,7 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||||||
region = (isc_region_t){ .base = &recv_buf[0],
|
region = (isc_region_t){ .base = &recv_buf[0],
|
||||||
.length = len };
|
.length = len };
|
||||||
|
|
||||||
|
was_new_data = true;
|
||||||
INSIST(VALID_NMHANDLE(sock->statichandle));
|
INSIST(VALID_NMHANDLE(sock->statichandle));
|
||||||
sock->recv_cb(sock->statichandle, ISC_R_SUCCESS,
|
sock->recv_cb(sock->statichandle, ISC_R_SUCCESS,
|
||||||
®ion, sock->recv_cbarg);
|
®ion, sock->recv_cbarg);
|
||||||
@@ -570,8 +578,29 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (was_new_data && !sock->manual_read_timer) {
|
||||||
|
/*
|
||||||
|
* Some data has been decrypted, it is the right
|
||||||
|
* time to stop the read timer as it will be
|
||||||
|
* restarted on the next read attempt.
|
||||||
|
*/
|
||||||
|
isc__nmsocket_timer_stop(sock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setting 'finish' to 'true' means that we are about to close the
|
||||||
|
* TLS stream (we intend to send TLS shutdown message to the
|
||||||
|
* remote side). After that no new data can be received, so we
|
||||||
|
* should stop the timer regardless of the
|
||||||
|
* 'sock->manual_read_timer' value.
|
||||||
|
*/
|
||||||
|
if (finish) {
|
||||||
|
isc__nmsocket_timer_stop(sock);
|
||||||
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
tls_status = SSL_get_error(sock->tlsstream.tls, rv);
|
tls_status = SSL_get_error(sock->tlsstream.tls, rv);
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
@@ -633,6 +662,9 @@ tls_do_bio(isc_nmsocket_t *sock, isc_region_t *received_data,
|
|||||||
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
INSIST(VALID_NMHANDLE(sock->outerhandle));
|
||||||
|
|
||||||
isc_nm_read(sock->outerhandle, tls_readcb, sock);
|
isc_nm_read(sock->outerhandle, tls_readcb, sock);
|
||||||
|
if (!sock->manual_read_timer) {
|
||||||
|
isc__nmsocket_timer_start(sock);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
result = tls_error_to_result(tls_status, sock->tlsstream.state,
|
result = tls_error_to_result(tls_status, sock->tlsstream.state,
|
||||||
@@ -764,6 +796,7 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
/* TODO: catch failure code, detach tlssock, and log the error */
|
/* TODO: catch failure code, detach tlssock, and log the error */
|
||||||
|
|
||||||
|
isc__nmhandle_set_manual_timer(tlssock->outerhandle, true);
|
||||||
tls_do_bio(tlssock, NULL, NULL, false);
|
tls_do_bio(tlssock, NULL, NULL, false);
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@@ -1081,6 +1114,7 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||||||
*/
|
*/
|
||||||
handle->sock->tlsstream.tlssocket = tlssock;
|
handle->sock->tlsstream.tlssocket = tlssock;
|
||||||
|
|
||||||
|
isc__nmhandle_set_manual_timer(tlssock->outerhandle, true);
|
||||||
tls_do_bio(tlssock, NULL, NULL, false);
|
tls_do_bio(tlssock, NULL, NULL, false);
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
@@ -1355,3 +1389,16 @@ tls_try_shutdown(isc_tls_t *tls, const bool force) {
|
|||||||
(void)SSL_shutdown(tls);
|
(void)SSL_shutdown(tls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nmhandle_tls_set_manual_timer(isc_nmhandle_t *handle, const bool manual) {
|
||||||
|
isc_nmsocket_t *sock;
|
||||||
|
|
||||||
|
REQUIRE(VALID_NMHANDLE(handle));
|
||||||
|
sock = handle->sock;
|
||||||
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
|
REQUIRE(sock->type == isc_nm_tlssocket);
|
||||||
|
REQUIRE(sock->tid == isc_tid());
|
||||||
|
|
||||||
|
sock->manual_read_timer = manual;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user