mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
DoT: implement TLS client session resumption
This commit extends DoT code with TLS client session resumption support implemented on top of the TLS client session cache.
This commit is contained in:
parent
90bc13a5d5
commit
86465c1dac
7 changed files with 85 additions and 23 deletions
|
|
@ -3000,7 +3000,7 @@ start_tcp(dig_query_t *query) {
|
|||
isc_nm_tlsdnsconnect(netmgr, &localaddr,
|
||||
&query->sockaddr, tcp_connected,
|
||||
connectquery, local_timeout,
|
||||
tlsctx);
|
||||
tlsctx, sess_cache);
|
||||
#if HAVE_LIBNGHTTP2
|
||||
} else if (query->lookup->https_mode) {
|
||||
char uri[4096] = { 0 };
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ run(void) {
|
|||
isc_tlsctx_createclient(&tls_ctx);
|
||||
|
||||
isc_nm_tlsdnsconnect(netmgr, &sockaddr_local, &sockaddr_remote,
|
||||
connect_cb, NULL, timeout, tls_ctx);
|
||||
connect_cb, NULL, timeout, tls_ctx, NULL);
|
||||
break;
|
||||
}
|
||||
#if HAVE_LIBNGHTTP2
|
||||
|
|
|
|||
|
|
@ -1118,7 +1118,7 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
|
|||
}
|
||||
isc_nm_tlsdnsconnect(xfr->netmgr, &xfr->sourceaddr,
|
||||
&xfr->primaryaddr, xfrin_connect_done,
|
||||
connect_xfr, 30000, tlsctx);
|
||||
connect_xfr, 30000, tlsctx, sess_cache);
|
||||
} break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
|
|
|||
|
|
@ -484,7 +484,8 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
|||
void
|
||||
isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
isc_nm_cb_t cb, void *cbarg, unsigned int timeout,
|
||||
isc_tlsctx_t *sslctx);
|
||||
isc_tlsctx_t *sslctx,
|
||||
isc_tlsctx_client_session_cache_t *client_sess_cache);
|
||||
/*%<
|
||||
* Establish a DNS client connection via a TCP or TLS connection, bound to
|
||||
* the address 'local' and connected to the address 'peer'.
|
||||
|
|
|
|||
|
|
@ -932,6 +932,8 @@ struct isc_nmsocket {
|
|||
struct tls {
|
||||
isc_tls_t *tls;
|
||||
isc_tlsctx_t *ctx;
|
||||
isc_tlsctx_client_session_cache_t *client_sess_cache;
|
||||
bool client_session_saved;
|
||||
BIO *app_rbio;
|
||||
BIO *app_wbio;
|
||||
BIO *ssl_rbio;
|
||||
|
|
|
|||
|
|
@ -79,6 +79,14 @@ tls_cycle(isc_nmsocket_t *sock);
|
|||
static void
|
||||
call_pending_send_callbacks(isc_nmsocket_t *sock, const isc_result_t result);
|
||||
|
||||
static void
|
||||
tlsdns_keep_client_tls_session(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
tlsdns_set_tls_shutdown(isc_tls_t *tls) {
|
||||
(void)SSL_set_shutdown(tls, SSL_SENT_SHUTDOWN);
|
||||
}
|
||||
|
||||
static bool
|
||||
peer_verification_has_failed(isc_nmsocket_t *sock) {
|
||||
if (sock->tls.tls != NULL && sock->tls.state == TLS_STATE_HANDSHAKE &&
|
||||
|
|
@ -294,11 +302,17 @@ tlsdns_connect_cb(uv_connect_t *uvreq, int status) {
|
|||
SSL_set_bio(sock->tls.tls, sock->tls.ssl_rbio, sock->tls.ssl_wbio);
|
||||
#endif
|
||||
|
||||
SSL_set_connect_state(sock->tls.tls);
|
||||
|
||||
result = isc_sockaddr_fromsockaddr(&sock->peer, (struct sockaddr *)&ss);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
if (sock->tls.client_sess_cache != NULL) {
|
||||
isc_tlsctx_client_session_cache_reuse_sockaddr(
|
||||
sock->tls.client_sess_cache, &sock->peer,
|
||||
sock->tls.tls);
|
||||
}
|
||||
|
||||
SSL_set_connect_state(sock->tls.tls);
|
||||
|
||||
/* Setting pending req */
|
||||
sock->tls.pending_req = req;
|
||||
|
||||
|
|
@ -319,7 +333,8 @@ error:
|
|||
void
|
||||
isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
isc_nm_cb_t cb, void *cbarg, unsigned int timeout,
|
||||
isc_tlsctx_t *sslctx) {
|
||||
isc_tlsctx_t *sslctx,
|
||||
isc_tlsctx_client_session_cache_t *client_sess_cache) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_nmsocket_t *sock = NULL;
|
||||
isc__netievent_tlsdnsconnect_t *ievent = NULL;
|
||||
|
|
@ -349,6 +364,13 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
|||
req->local = *local;
|
||||
req->handle = isc__nmhandle_get(sock, &req->peer, &sock->iface);
|
||||
|
||||
if (client_sess_cache != NULL) {
|
||||
INSIST(isc_tlsctx_client_session_cache_getctx(
|
||||
client_sess_cache) == sslctx);
|
||||
isc_tlsctx_client_session_cache_attach(
|
||||
client_sess_cache, &sock->tls.client_sess_cache);
|
||||
}
|
||||
|
||||
result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock->fd);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
|
|
@ -1008,6 +1030,11 @@ isc__nm_tlsdns_processbuffer(isc_nmsocket_t *sock) {
|
|||
|
||||
isc_nmhandle_detach(&handle);
|
||||
|
||||
if (isc__nmsocket_closing(sock)) {
|
||||
tlsdns_set_tls_shutdown(sock->tls.tls);
|
||||
tlsdns_keep_client_tls_session(sock);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
@ -1102,6 +1129,8 @@ tls_cycle_input(isc_nmsocket_t *sock) {
|
|||
const unsigned char *alpn = NULL;
|
||||
unsigned int alpnlen = 0;
|
||||
|
||||
isc__nmsocket_log_tls_session_reuse(sock, sock->tls.tls);
|
||||
|
||||
isc_tls_get_selected_alpn(sock->tls.tls, &alpn, &alpnlen);
|
||||
if (alpn != NULL && alpnlen == ISC_TLS_DOT_PROTO_ALPN_ID_LEN &&
|
||||
memcmp(ISC_TLS_DOT_PROTO_ALPN_ID, alpn,
|
||||
|
|
@ -1835,6 +1864,12 @@ tlsdns_close_sock(isc_nmsocket_t *sock) {
|
|||
atomic_store(&sock->connected, false);
|
||||
|
||||
if (sock->tls.tls != NULL) {
|
||||
/*
|
||||
* Let's shutdown the TLS session properly so that the session
|
||||
* will remain resumable, if required.
|
||||
*/
|
||||
tlsdns_set_tls_shutdown(sock->tls.tls);
|
||||
tlsdns_keep_client_tls_session(sock);
|
||||
isc_tls_free(&sock->tls.tls);
|
||||
}
|
||||
|
||||
|
|
@ -2015,7 +2050,7 @@ isc__nm_tlsdns_shutdown(isc_nmsocket_t *sock) {
|
|||
|
||||
if (sock->tls.tls) {
|
||||
/* Shutdown any active TLS connections */
|
||||
(void)SSL_shutdown(sock->tls.tls);
|
||||
tlsdns_set_tls_shutdown(sock->tls.tls);
|
||||
}
|
||||
|
||||
if (atomic_load(&sock->accepting)) {
|
||||
|
|
@ -2146,11 +2181,35 @@ isc__nm_async_tlsdns_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
|
|||
|
||||
void
|
||||
isc__nm_tlsdns_cleanup_data(isc_nmsocket_t *sock) {
|
||||
if ((sock->type == isc_nm_tlsdnslistener ||
|
||||
sock->type == isc_nm_tlsdnssocket) &&
|
||||
sock->tls.ctx != NULL)
|
||||
{
|
||||
INSIST(ISC_LIST_EMPTY(sock->tls.sendreqs));
|
||||
isc_tlsctx_free(&sock->tls.ctx);
|
||||
if (sock->type == isc_nm_tlsdnslistener ||
|
||||
sock->type == isc_nm_tlsdnssocket) {
|
||||
if (sock->tls.client_sess_cache != NULL) {
|
||||
INSIST(atomic_load(&sock->client));
|
||||
INSIST(sock->type == isc_nm_tlsdnssocket);
|
||||
isc_tlsctx_client_session_cache_detach(
|
||||
&sock->tls.client_sess_cache);
|
||||
}
|
||||
if (sock->tls.ctx != NULL) {
|
||||
INSIST(ISC_LIST_EMPTY(sock->tls.sendreqs));
|
||||
isc_tlsctx_free(&sock->tls.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tlsdns_keep_client_tls_session(isc_nmsocket_t *sock) {
|
||||
/*
|
||||
* Ensure that the isc_tls_t is being accessed from
|
||||
* within the worker thread the socket is bound to.
|
||||
*/
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
if (sock->tls.client_sess_cache != NULL &&
|
||||
sock->tls.client_session_saved == false)
|
||||
{
|
||||
INSIST(atomic_load(&sock->client));
|
||||
isc_tlsctx_client_session_cache_keep_sockaddr(
|
||||
sock->tls.client_sess_cache, &sock->peer,
|
||||
sock->tls.tls);
|
||||
sock->tls.client_session_saved = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2331,7 +2331,7 @@ static void
|
|||
tlsdns_connect(isc_nm_t *nm) {
|
||||
isc_nm_tlsdnsconnect(nm, &tcp_connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_CONNECT,
|
||||
tcp_connect_tlsctx);
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2353,7 +2353,7 @@ tlsdns_noop(void **state __attribute__((unused))) {
|
|||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_CONNECT,
|
||||
tcp_connect_tlsctx);
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
isc__netmgr_shutdown(connect_nm);
|
||||
|
||||
|
|
@ -2382,7 +2382,7 @@ tlsdns_noresponse(void **state __attribute__((unused))) {
|
|||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_CONNECT,
|
||||
tcp_connect_tlsctx);
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
WAIT_FOR_EQ(csends, 1);
|
||||
|
|
@ -2437,7 +2437,7 @@ tlsdns_timeout_recovery(void **state __attribute__((unused))) {
|
|||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_SOFT,
|
||||
tcp_connect_tlsctx);
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
WAIT_FOR_GE(csends, 1);
|
||||
|
|
@ -2469,7 +2469,7 @@ tlsdns_recv_one(void **state __attribute__((unused))) {
|
|||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_CONNECT,
|
||||
tcp_connect_tlsctx);
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
WAIT_FOR_LE(nsends, 0);
|
||||
|
|
@ -2512,14 +2512,14 @@ tlsdns_recv_two(void **state __attribute__((unused))) {
|
|||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_CONNECT,
|
||||
tcp_connect_tlsctx);
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
|
||||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_CONNECT,
|
||||
tcp_connect_tlsctx);
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 2);
|
||||
|
||||
|
|
@ -2788,7 +2788,7 @@ tlsdns_connect_noalpn(void **state __attribute__((unused))) {
|
|||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr,
|
||||
tlsdns_connect_connect_noalpn, NULL, T_CONNECT,
|
||||
connect_tlsctx_noalpn);
|
||||
connect_tlsctx_noalpn, NULL);
|
||||
|
||||
WAIT_FOR_EQ(active_cconnects, 0);
|
||||
|
||||
|
|
@ -2855,7 +2855,7 @@ tlsdns_listen_noalpn(void **state __attribute__((unused))) {
|
|||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_CONNECT,
|
||||
tcp_connect_tlsctx);
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
WAIT_FOR_EQ(saccepts, 1);
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
|
|
|
|||
Loading…
Reference in a new issue