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 };
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
}
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();
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'.
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;
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 &&
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;
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;
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;
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);
}
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,
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);
}
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)) {
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)
+ 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(ISC_LIST_EMPTY(sock->tls.sendreqs));
- isc_tlsctx_free(&sock->tls.ctx);
+ 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;
}
}
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
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);
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);
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);
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);
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);
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);
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);