mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
Add isc_nmsocket_set_tlsctx()
This commit adds isc_nmsocket_set_tlsctx() - an asynchronous function that replaces the TLS context within a given TLS-enabled listener socket object. It is based on the newly added reference counting functionality. The intention of adding this function is to add functionality to replace a TLS context without recreating the whole socket object, including the underlying TCP listener socket, as a BIND process might not have enough permissions to re-create it fully on reconfiguration.
This commit is contained in:
@@ -109,6 +109,18 @@ isc_nmsocket_close(isc_nmsocket_t **sockp);
|
|||||||
* sockets with active handles, the socket will be closed.
|
* sockets with active handles, the socket will be closed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx);
|
||||||
|
/*%<
|
||||||
|
* Asynchronously replace the TLS context within the listener socket object.
|
||||||
|
* The function is intended to be used during reconfiguration.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* \li 'listener' is a pointer to a valid network manager listener socket
|
||||||
|
object with TLS support;
|
||||||
|
* \li 'tlsctx' is a valid pointer to a TLS context object.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef NETMGR_TRACE
|
#ifdef NETMGR_TRACE
|
||||||
#define isc_nmhandle_attach(handle, dest) \
|
#define isc_nmhandle_attach(handle, dest) \
|
||||||
isc__nmhandle_attach(handle, dest, __FILE__, __LINE__, __func__)
|
isc__nmhandle_attach(handle, dest, __FILE__, __LINE__, __func__)
|
||||||
|
@@ -2936,6 +2936,14 @@ isc__nm_http_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
|
|||||||
return (isc_nm_verify_tls_peer_result_string(session->handle));
|
return (isc_nm_verify_tls_peer_result_string(session->handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_http_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
|
||||||
|
REQUIRE(VALID_NMSOCK(listener));
|
||||||
|
REQUIRE(listener->type == isc_nm_httplistener);
|
||||||
|
|
||||||
|
isc_nmsocket_set_tlsctx(listener->outer, tlsctx);
|
||||||
|
}
|
||||||
|
|
||||||
static const bool base64url_validation_table[256] = {
|
static const bool base64url_validation_table[256] = {
|
||||||
false, false, false, false, false, false, false, false, false, false,
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
false, false, false, false, false, false, false, false, false, false,
|
false, false, false, false, false, false, false, false, false, false,
|
||||||
|
@@ -328,6 +328,8 @@ typedef enum isc__netievent_type {
|
|||||||
|
|
||||||
netievent_task,
|
netievent_task,
|
||||||
|
|
||||||
|
netievent_settlsctx,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* event type values higher than this will be treated
|
* event type values higher than this will be treated
|
||||||
* as high-priority events, which can be processed
|
* as high-priority events, which can be processed
|
||||||
@@ -665,6 +667,38 @@ typedef struct isc__netievent {
|
|||||||
isc__nm_put_netievent(nm, ievent); \
|
isc__nm_put_netievent(nm, ievent); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct isc__netievent__tlsctx {
|
||||||
|
NETIEVENT__SOCKET;
|
||||||
|
isc_tlsctx_t *tlsctx;
|
||||||
|
} isc__netievent__tlsctx_t;
|
||||||
|
|
||||||
|
#define NETIEVENT_SOCKET_TLSCTX_TYPE(type) \
|
||||||
|
typedef isc__netievent__tlsctx_t isc__netievent_##type##_t;
|
||||||
|
|
||||||
|
#define NETIEVENT_SOCKET_TLSCTX_DECL(type) \
|
||||||
|
isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
|
||||||
|
isc_nm_t *nm, isc_nmsocket_t *sock, isc_tlsctx_t *tlsctx); \
|
||||||
|
void isc__nm_put_netievent_##type(isc_nm_t *nm, \
|
||||||
|
isc__netievent_##type##_t *ievent);
|
||||||
|
|
||||||
|
#define NETIEVENT_SOCKET_TLSCTX_DEF(type) \
|
||||||
|
isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
|
||||||
|
isc_nm_t *nm, isc_nmsocket_t *sock, isc_tlsctx_t *tlsctx) { \
|
||||||
|
isc__netievent_##type##_t *ievent = \
|
||||||
|
isc__nm_get_netievent(nm, netievent_##type); \
|
||||||
|
isc__nmsocket_attach(sock, &ievent->sock); \
|
||||||
|
isc_tlsctx_attach(tlsctx, &ievent->tlsctx); \
|
||||||
|
\
|
||||||
|
return (ievent); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void isc__nm_put_netievent_##type(isc_nm_t *nm, \
|
||||||
|
isc__netievent_##type##_t *ievent) { \
|
||||||
|
isc_tlsctx_free(&ievent->tlsctx); \
|
||||||
|
isc__nmsocket_detach(&ievent->sock); \
|
||||||
|
isc__nm_put_netievent(nm, ievent); \
|
||||||
|
}
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
isc__netievent_t ni;
|
isc__netievent_t ni;
|
||||||
isc__netievent__socket_t nis;
|
isc__netievent__socket_t nis;
|
||||||
@@ -672,6 +706,7 @@ typedef union {
|
|||||||
isc__netievent_udpsend_t nius;
|
isc__netievent_udpsend_t nius;
|
||||||
isc__netievent__socket_quota_t nisq;
|
isc__netievent__socket_quota_t nisq;
|
||||||
isc__netievent_tlsconnect_t nitc;
|
isc__netievent_tlsconnect_t nitc;
|
||||||
|
isc__netievent__tlsctx_t nitls;
|
||||||
} isc__netievent_storage_t;
|
} isc__netievent_storage_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -930,6 +965,7 @@ struct isc_nmsocket {
|
|||||||
isc_tlsctx_t *ctx;
|
isc_tlsctx_t *ctx;
|
||||||
isc_tlsctx_t **listener_tls_ctx; /*%< A context reference per
|
isc_tlsctx_t **listener_tls_ctx; /*%< A context reference per
|
||||||
worker */
|
worker */
|
||||||
|
size_t n_listener_tls_ctx;
|
||||||
isc_nmsocket_t *tlslistener;
|
isc_nmsocket_t *tlslistener;
|
||||||
atomic_bool result_updated;
|
atomic_bool result_updated;
|
||||||
enum {
|
enum {
|
||||||
@@ -1608,6 +1644,9 @@ void
|
|||||||
isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0);
|
isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||||
void
|
void
|
||||||
isc__nm_async_tlsdnsread(isc__networker_t *worker, isc__netievent_t *ev0);
|
isc__nm_async_tlsdnsread(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||||
|
void
|
||||||
|
isc__nm_async_tlsdns_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
|
||||||
|
const int tid);
|
||||||
/*%<
|
/*%<
|
||||||
* Callback handlers for asynchronous TLSDNS events.
|
* Callback handlers for asynchronous TLSDNS events.
|
||||||
*/
|
*/
|
||||||
@@ -1684,6 +1723,10 @@ isc__nmhandle_tls_keepalive(isc_nmhandle_t *handle, bool value);
|
|||||||
* Set the keepalive value on the underlying TCP handle.
|
* Set the keepalive value on the underlying TCP handle.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_async_tls_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
|
||||||
|
const int tid);
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
||||||
|
|
||||||
@@ -1769,8 +1812,14 @@ isc__nm_httpsession_attach(isc_nm_http_session_t *source,
|
|||||||
void
|
void
|
||||||
isc__nm_httpsession_detach(isc_nm_http_session_t **sessionp);
|
isc__nm_httpsession_detach(isc_nm_http_session_t **sessionp);
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_http_set_tlsctx(isc_nmsocket_t *sock, isc_tlsctx_t *tlsctx);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_async_settlsctx(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||||
|
|
||||||
#define isc__nm_uverr2result(x) \
|
#define isc__nm_uverr2result(x) \
|
||||||
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
|
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@@ -1963,6 +2012,8 @@ NETIEVENT_TYPE(stop);
|
|||||||
|
|
||||||
NETIEVENT_TASK_TYPE(task);
|
NETIEVENT_TASK_TYPE(task);
|
||||||
|
|
||||||
|
NETIEVENT_SOCKET_TLSCTX_TYPE(settlsctx);
|
||||||
|
|
||||||
/* Now declared the helper functions */
|
/* Now declared the helper functions */
|
||||||
|
|
||||||
NETIEVENT_SOCKET_DECL(close);
|
NETIEVENT_SOCKET_DECL(close);
|
||||||
@@ -2030,6 +2081,8 @@ NETIEVENT_DECL(stop);
|
|||||||
|
|
||||||
NETIEVENT_TASK_DECL(task);
|
NETIEVENT_TASK_DECL(task);
|
||||||
|
|
||||||
|
NETIEVENT_SOCKET_TLSCTX_DECL(settlsctx);
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_udp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
|
isc__nm_udp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
|
||||||
void
|
void
|
||||||
|
@@ -903,6 +903,7 @@ process_netievent(isc__networker_t *worker, isc__netievent_t *ievent) {
|
|||||||
NETIEVENT_CASE(httpsend);
|
NETIEVENT_CASE(httpsend);
|
||||||
NETIEVENT_CASE(httpclose);
|
NETIEVENT_CASE(httpclose);
|
||||||
#endif
|
#endif
|
||||||
|
NETIEVENT_CASE(settlsctx);
|
||||||
|
|
||||||
NETIEVENT_CASE(connectcb);
|
NETIEVENT_CASE(connectcb);
|
||||||
NETIEVENT_CASE(readcb);
|
NETIEVENT_CASE(readcb);
|
||||||
@@ -1041,6 +1042,8 @@ NETIEVENT_DEF(stop);
|
|||||||
|
|
||||||
NETIEVENT_TASK_DEF(task);
|
NETIEVENT_TASK_DEF(task);
|
||||||
|
|
||||||
|
NETIEVENT_SOCKET_TLSCTX_DEF(settlsctx);
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_maybe_enqueue_ievent(isc__networker_t *worker,
|
isc__nm_maybe_enqueue_ievent(isc__networker_t *worker,
|
||||||
isc__netievent_t *event) {
|
isc__netievent_t *event) {
|
||||||
@@ -3554,6 +3557,71 @@ isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_async_settlsctx(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||||
|
isc__netievent__tlsctx_t *ev_tlsctx = (isc__netievent__tlsctx_t *)ev0;
|
||||||
|
const int tid = isc_nm_tid();
|
||||||
|
isc_nmsocket_t *listener = ev_tlsctx->sock;
|
||||||
|
isc_tlsctx_t *tlsctx = ev_tlsctx->tlsctx;
|
||||||
|
|
||||||
|
UNUSED(worker);
|
||||||
|
|
||||||
|
switch (listener->type) {
|
||||||
|
case isc_nm_tlsdnslistener:
|
||||||
|
isc__nm_async_tlsdns_set_tlsctx(listener, tlsctx, tid);
|
||||||
|
break;
|
||||||
|
#if HAVE_LIBNGHTTP2
|
||||||
|
case isc_nm_tlslistener:
|
||||||
|
isc__nm_async_tls_set_tlsctx(listener, tlsctx, tid);
|
||||||
|
break;
|
||||||
|
#endif /* HAVE_LIBNGHTTP2 */
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_tlsctx_workers(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
|
||||||
|
/* Update the TLS context reference for every worker thread. */
|
||||||
|
for (size_t i = 0; i < isc_nm_getnworkers(listener->mgr); i++) {
|
||||||
|
isc__netievent__tlsctx_t *ievent =
|
||||||
|
isc__nm_get_netievent_settlsctx(listener->mgr, listener,
|
||||||
|
tlsctx);
|
||||||
|
isc__nm_enqueue_ievent(&listener->mgr->workers[i],
|
||||||
|
(isc__netievent_t *)ievent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
|
||||||
|
REQUIRE(VALID_NMSOCK(listener));
|
||||||
|
REQUIRE(tlsctx != NULL);
|
||||||
|
|
||||||
|
switch (listener->type) {
|
||||||
|
#if HAVE_LIBNGHTTP2
|
||||||
|
case isc_nm_httplistener:
|
||||||
|
/*
|
||||||
|
* We handle HTTP listener sockets differently, as they rely
|
||||||
|
* on underlying TLS sockets for networking. The TLS context
|
||||||
|
* will get passed to these underlying sockets via the call to
|
||||||
|
* isc__nm_http_set_tlsctx().
|
||||||
|
*/
|
||||||
|
isc__nm_http_set_tlsctx(listener, tlsctx);
|
||||||
|
break;
|
||||||
|
case isc_nm_tlslistener:
|
||||||
|
set_tlsctx_workers(listener, tlsctx);
|
||||||
|
break;
|
||||||
|
#endif /* HAVE_LIBNGHTTP2 */
|
||||||
|
case isc_nm_tlsdnslistener:
|
||||||
|
set_tlsctx_workers(listener, tlsctx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef NETMGR_TRACE
|
#ifdef NETMGR_TRACE
|
||||||
/*
|
/*
|
||||||
* Dump all active sockets in netmgr. We output to stderr
|
* Dump all active sockets in netmgr. We output to stderr
|
||||||
|
@@ -2115,6 +2115,14 @@ isc__nm_tlsdns_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
|
|||||||
return (isc_tls_verify_peer_result_string(sock->tls.tls));
|
return (isc_tls_verify_peer_result_string(sock->tls.tls));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_async_tlsdns_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
|
||||||
|
const int tid) {
|
||||||
|
REQUIRE(tid >= 0);
|
||||||
|
|
||||||
|
isc_tlsctx_free(&listener->children[tid].tls.ctx);
|
||||||
|
isc_tlsctx_attach(tlsctx, &listener->children[tid].tls.ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_tlsdns_cleanup_data(isc_nmsocket_t *sock) {
|
isc__nm_tlsdns_cleanup_data(isc_nmsocket_t *sock) {
|
||||||
@@ -2124,4 +2132,4 @@ isc__nm_tlsdns_cleanup_data(isc_nmsocket_t *sock) {
|
|||||||
{
|
{
|
||||||
isc_tlsctx_free(&sock->tls.ctx);
|
isc_tlsctx_free(&sock->tls.ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1101,17 +1101,17 @@ isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) {
|
tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) {
|
||||||
uint32_t nworkers;
|
size_t nworkers;
|
||||||
|
|
||||||
REQUIRE(VALID_NM(listener->mgr));
|
REQUIRE(VALID_NM(listener->mgr));
|
||||||
|
|
||||||
nworkers = isc_nm_getnworkers(listener->mgr);
|
|
||||||
|
|
||||||
REQUIRE(nworkers > 0);
|
|
||||||
REQUIRE(ctx != NULL);
|
REQUIRE(ctx != NULL);
|
||||||
|
|
||||||
|
nworkers = (size_t)isc_nm_getnworkers(listener->mgr);
|
||||||
|
INSIST(nworkers > 0);
|
||||||
|
|
||||||
listener->tlsstream.listener_tls_ctx = isc_mem_get(
|
listener->tlsstream.listener_tls_ctx = isc_mem_get(
|
||||||
listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers);
|
listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers);
|
||||||
|
listener->tlsstream.n_listener_tls_ctx = nworkers;
|
||||||
for (size_t i = 0; i < nworkers; i++) {
|
for (size_t i = 0; i < nworkers; i++) {
|
||||||
listener->tlsstream.listener_tls_ctx[i] = NULL;
|
listener->tlsstream.listener_tls_ctx[i] = NULL;
|
||||||
isc_tlsctx_attach(ctx,
|
isc_tlsctx_attach(ctx,
|
||||||
@@ -1121,22 +1121,19 @@ tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener) {
|
tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener) {
|
||||||
uint32_t nworkers;
|
|
||||||
|
|
||||||
REQUIRE(VALID_NM(listener->mgr));
|
REQUIRE(VALID_NM(listener->mgr));
|
||||||
|
|
||||||
nworkers = isc_nm_getnworkers(listener->mgr);
|
|
||||||
|
|
||||||
REQUIRE(nworkers > 0);
|
|
||||||
if (listener->tlsstream.listener_tls_ctx == NULL) {
|
if (listener->tlsstream.listener_tls_ctx == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < nworkers; i++) {
|
for (size_t i = 0; i < listener->tlsstream.n_listener_tls_ctx; i++) {
|
||||||
isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[i]);
|
isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[i]);
|
||||||
}
|
}
|
||||||
isc_mem_put(listener->mgr->mctx, listener->tlsstream.listener_tls_ctx,
|
isc_mem_put(listener->mgr->mctx, listener->tlsstream.listener_tls_ctx,
|
||||||
sizeof(isc_tlsctx_t *) * nworkers);
|
sizeof(isc_tlsctx_t *) *
|
||||||
|
listener->tlsstream.n_listener_tls_ctx);
|
||||||
|
listener->tlsstream.n_listener_tls_ctx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_tlsctx_t *
|
static isc_tlsctx_t *
|
||||||
@@ -1150,3 +1147,12 @@ tls_get_listener_tlsctx(isc_nmsocket_t *listener, const int tid) {
|
|||||||
|
|
||||||
return (listener->tlsstream.listener_tls_ctx[tid]);
|
return (listener->tlsstream.listener_tls_ctx[tid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nm_async_tls_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
|
||||||
|
const int tid) {
|
||||||
|
REQUIRE(tid >= 0);
|
||||||
|
|
||||||
|
isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[tid]);
|
||||||
|
isc_tlsctx_attach(tlsctx, &listener->tlsstream.listener_tls_ctx[tid]);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user