mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch 'artem-tls-ctx-refcount-backport-v9_18' into 'v9_18'
Implement reference counting for TLS contexts, Resolve #3122 DoT stops working after "rndc reconfigure" when running named as non-root (backport to v9.18) See merge request isc-projects/bind9!6204
This commit is contained in:
commit
24655a4704
14 changed files with 369 additions and 82 deletions
5
CHANGES
5
CHANGES
|
|
@ -30,6 +30,11 @@
|
|||
5858. [bug] Don't remove CDS/CDNSKEY DELETE records on zone sign
|
||||
when using 'auto-dnssec maintain;'. [GL #2931]
|
||||
|
||||
5854. [func] Implement reference counting for TLS contexts and
|
||||
allow reloading of TLS certificates on reconfiguration
|
||||
without destroying the underlying TCP listener sockets
|
||||
for TLS-based DNS transports. [GL #3122]
|
||||
|
||||
5849. [cleanup] Remove use of exclusive mode in ns_interfacemgr in
|
||||
favor of rwlocked access to localhost and localnets
|
||||
members of dns_aclenv_t structure. [GL #3229]
|
||||
|
|
|
|||
|
|
@ -451,10 +451,17 @@ grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
|
|||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
wait_for_tlsctx_update_ns4 () {
|
||||
grep "updating TLS context on 10.53.0.4#${HTTPSPORT}" ns4/named.run > /dev/null || return 1
|
||||
grep "updating TLS context on 10.53.0.4#${TLSPORT}" ns4/named.run > /dev/null || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "doing rndc reconfig to see that queries keep being served after that ($n)"
|
||||
ret=0
|
||||
rndc_reconfig ns4 10.53.0.4 60
|
||||
retry_quiet 15 wait_for_tlsctx_update_ns4 || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
|
|
|
|||
|
|
@ -650,6 +650,7 @@ AC_CHECK_FUNCS([SSL_CTX_set_keylog_callback])
|
|||
AC_CHECK_FUNCS([SSL_CTX_set_min_proto_version])
|
||||
AC_CHECK_FUNCS([SSL_CTX_up_ref])
|
||||
AC_CHECK_FUNCS([SSL_read_ex SSL_peek_ex SSL_write_ex])
|
||||
AC_CHECK_FUNCS([SSL_CTX_up_ref])
|
||||
|
||||
#
|
||||
# Check for algorithm support in OpenSSL
|
||||
|
|
|
|||
|
|
@ -109,6 +109,18 @@ isc_nmsocket_close(isc_nmsocket_t **sockp);
|
|||
* 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
|
||||
#define isc_nmhandle_attach(handle, dest) \
|
||||
isc__nmhandle_attach(handle, dest, __FILE__, __LINE__, __func__)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,17 @@ isc_tlsctx_free(isc_tlsctx_t **ctpx);
|
|||
*\li 'ctxp' != NULL and '*ctxp' != NULL.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_tlsctx_attach(isc_tlsctx_t *src, isc_tlsctx_t **ptarget);
|
||||
/*%<
|
||||
* Attach to the TLS context.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'src' != NULL;
|
||||
*\li 'ptarget' != NULL;
|
||||
*\li '*ptarget' == NULL.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_tlsctx_createserver(const char *keyfile, const char *certfile,
|
||||
isc_tlsctx_t **ctxp);
|
||||
|
|
|
|||
|
|
@ -2909,6 +2909,14 @@ isc__nm_http_has_encryption(const isc_nmhandle_t *handle) {
|
|||
return (isc_nm_socket_type(session->handle) == isc_nm_tlssocket);
|
||||
}
|
||||
|
||||
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] = {
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false,
|
||||
|
|
|
|||
|
|
@ -331,6 +331,8 @@ typedef enum isc__netievent_type {
|
|||
netievent_task,
|
||||
netievent_privilegedtask,
|
||||
|
||||
netievent_settlsctx,
|
||||
|
||||
/*
|
||||
* event type values higher than this will be treated
|
||||
* as high-priority events, which can be processed
|
||||
|
|
@ -668,6 +670,38 @@ typedef struct isc__netievent {
|
|||
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 {
|
||||
isc__netievent_t ni;
|
||||
isc__netievent__socket_t nis;
|
||||
|
|
@ -675,6 +709,7 @@ typedef union {
|
|||
isc__netievent_udpsend_t nius;
|
||||
isc__netievent__socket_quota_t nisq;
|
||||
isc__netievent_tlsconnect_t nitc;
|
||||
isc__netievent__tlsctx_t nitls;
|
||||
} isc__netievent_storage_t;
|
||||
|
||||
/*
|
||||
|
|
@ -932,6 +967,9 @@ struct isc_nmsocket {
|
|||
BIO *bio_out;
|
||||
isc_tls_t *tls;
|
||||
isc_tlsctx_t *ctx;
|
||||
isc_tlsctx_t **listener_tls_ctx; /*%< A context reference per
|
||||
worker */
|
||||
size_t n_listener_tls_ctx;
|
||||
isc_nmsocket_t *tlslistener;
|
||||
atomic_bool result_updated;
|
||||
enum {
|
||||
|
|
@ -1615,6 +1653,9 @@ void
|
|||
isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
void
|
||||
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.
|
||||
*/
|
||||
|
|
@ -1629,6 +1670,9 @@ isc__nm_tlsdns_xfr_allowed(isc_nmsocket_t *sock);
|
|||
* \li 'sock' is a valid TLSDNS socket.
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_tlsdns_cleanup_data(isc_nmsocket_t *sock);
|
||||
|
||||
#if HAVE_LIBNGHTTP2
|
||||
void
|
||||
isc__nm_tls_send(isc_nmhandle_t *handle, const isc_region_t *region,
|
||||
|
|
@ -1685,6 +1729,10 @@ isc__nmhandle_tls_keepalive(isc_nmhandle_t *handle, bool value);
|
|||
* 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
|
||||
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
|
||||
|
||||
|
|
@ -1767,8 +1815,14 @@ isc__nm_httpsession_attach(isc_nm_http_session_t *source,
|
|||
void
|
||||
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
|
||||
|
||||
void
|
||||
isc__nm_async_settlsctx(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||
|
||||
#define isc__nm_uverr2result(x) \
|
||||
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
|
||||
isc_result_t
|
||||
|
|
@ -1962,6 +2016,8 @@ NETIEVENT_TYPE(stop);
|
|||
NETIEVENT_TASK_TYPE(task);
|
||||
NETIEVENT_TASK_TYPE(privilegedtask);
|
||||
|
||||
NETIEVENT_SOCKET_TLSCTX_TYPE(settlsctx);
|
||||
|
||||
/* Now declared the helper functions */
|
||||
|
||||
NETIEVENT_SOCKET_DECL(close);
|
||||
|
|
@ -2030,6 +2086,8 @@ NETIEVENT_DECL(stop);
|
|||
NETIEVENT_TASK_DECL(task);
|
||||
NETIEVENT_TASK_DECL(privilegedtask);
|
||||
|
||||
NETIEVENT_SOCKET_TLSCTX_DECL(settlsctx);
|
||||
|
||||
void
|
||||
isc__nm_udp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
|
||||
void
|
||||
|
|
|
|||
|
|
@ -956,6 +956,7 @@ process_netievent(isc__networker_t *worker, isc__netievent_t *ievent) {
|
|||
NETIEVENT_CASE(httpsend);
|
||||
NETIEVENT_CASE(httpclose);
|
||||
#endif
|
||||
NETIEVENT_CASE(settlsctx);
|
||||
|
||||
NETIEVENT_CASE(connectcb);
|
||||
NETIEVENT_CASE(readcb);
|
||||
|
|
@ -1095,6 +1096,8 @@ NETIEVENT_DEF(stop);
|
|||
NETIEVENT_TASK_DEF(task);
|
||||
NETIEVENT_TASK_DEF(privilegedtask);
|
||||
|
||||
NETIEVENT_SOCKET_TLSCTX_DEF(settlsctx);
|
||||
|
||||
void
|
||||
isc__nm_maybe_enqueue_ievent(isc__networker_t *worker,
|
||||
isc__netievent_t *event) {
|
||||
|
|
@ -1276,6 +1279,7 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
|
|||
isc_condition_destroy(&sock->scond);
|
||||
isc_condition_destroy(&sock->cond);
|
||||
isc_mutex_destroy(&sock->lock);
|
||||
isc__nm_tlsdns_cleanup_data(sock);
|
||||
#if HAVE_LIBNGHTTP2
|
||||
isc__nm_tls_cleanup_data(sock);
|
||||
isc__nm_http_cleanup_data(sock);
|
||||
|
|
@ -3625,6 +3629,71 @@ isc_nm_has_encryption(const isc_nmhandle_t *handle) {
|
|||
return (false);
|
||||
}
|
||||
|
||||
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 < (size_t)listener->mgr->nworkers; 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
|
||||
/*
|
||||
* Dump all active sockets in netmgr. We output to stderr
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
|||
sock->extrahandlesize = extrahandlesize;
|
||||
sock->connect_timeout = timeout;
|
||||
sock->result = ISC_R_UNSET;
|
||||
sock->tls.ctx = sslctx;
|
||||
isc_tlsctx_attach(sslctx, &sock->tls.ctx);
|
||||
atomic_init(&sock->client, true);
|
||||
atomic_init(&sock->connecting, true);
|
||||
|
||||
|
|
@ -432,7 +432,7 @@ start_tlsdns_child(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nmsocket_t *sock,
|
|||
csock->extrahandlesize = sock->extrahandlesize;
|
||||
csock->backlog = sock->backlog;
|
||||
csock->tid = tid;
|
||||
csock->tls.ctx = sock->tls.ctx;
|
||||
isc_tlsctx_attach(sock->tls.ctx, &csock->tls.ctx);
|
||||
|
||||
/*
|
||||
* We don't attach to quota, just assign - to avoid
|
||||
|
|
@ -494,7 +494,7 @@ isc_nm_listentlsdns(isc_nm_t *mgr, isc_sockaddr_t *iface,
|
|||
sock->backlog = backlog;
|
||||
sock->pquota = quota;
|
||||
|
||||
sock->tls.ctx = sslctx;
|
||||
isc_tlsctx_attach(sslctx, &sock->tls.ctx);
|
||||
|
||||
sock->tid = 0;
|
||||
sock->fd = -1;
|
||||
|
|
@ -1795,7 +1795,9 @@ tlsdns_stop_cb(uv_handle_t *handle) {
|
|||
BIO_free_all(sock->tls.app_rbio);
|
||||
BIO_free_all(sock->tls.app_wbio);
|
||||
|
||||
sock->tls.ctx = NULL;
|
||||
if (sock->tls.ctx != NULL) {
|
||||
isc_tlsctx_free(&sock->tls.ctx);
|
||||
}
|
||||
|
||||
isc__nmsocket_detach(&sock);
|
||||
}
|
||||
|
|
@ -1826,7 +1828,9 @@ tlsdns_close_sock(isc_nmsocket_t *sock) {
|
|||
BIO_free_all(sock->tls.app_rbio);
|
||||
BIO_free_all(sock->tls.app_wbio);
|
||||
|
||||
sock->tls.ctx = NULL;
|
||||
if (sock->tls.ctx != NULL) {
|
||||
isc_tlsctx_free(&sock->tls.ctx);
|
||||
}
|
||||
|
||||
isc__nmsocket_prep_destroy(sock);
|
||||
}
|
||||
|
|
@ -2098,3 +2102,22 @@ isc__nm_tlsdns_xfr_allowed(isc_nmsocket_t *sock) {
|
|||
|
||||
return (sock->tls.alpn_negotiated);
|
||||
}
|
||||
|
||||
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
|
||||
isc__nm_tlsdns_cleanup_data(isc_nmsocket_t *sock) {
|
||||
if ((sock->type == isc_nm_tlsdnslistener ||
|
||||
sock->type == isc_nm_tlsdnssocket) &&
|
||||
sock->tls.ctx != NULL)
|
||||
{
|
||||
isc_tlsctx_free(&sock->tls.ctx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,15 @@ tls_close_direct(isc_nmsocket_t *sock);
|
|||
static void
|
||||
async_tls_do_bio(isc_nmsocket_t *sock);
|
||||
|
||||
static void
|
||||
tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx);
|
||||
|
||||
static void
|
||||
tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener);
|
||||
|
||||
static isc_tlsctx_t *
|
||||
tls_get_listener_tlsctx(isc_nmsocket_t *listener, const int tid);
|
||||
|
||||
/*
|
||||
* The socket is closing, outerhandle has been detached, listener is
|
||||
* inactive, or the netmgr is closing: any operation on it should abort
|
||||
|
|
@ -578,6 +587,8 @@ static isc_result_t
|
|||
tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
||||
isc_nmsocket_t *tlslistensock = (isc_nmsocket_t *)cbarg;
|
||||
isc_nmsocket_t *tlssock = NULL;
|
||||
isc_tlsctx_t *tlsctx = NULL;
|
||||
int tid;
|
||||
|
||||
/* If accept() was unsuccessful we can't do anything */
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -596,11 +607,15 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||
isc__nmsocket_init(tlssock, handle->sock->mgr, isc_nm_tlssocket,
|
||||
&handle->sock->iface);
|
||||
|
||||
tid = isc_nm_tid();
|
||||
/* We need to initialize SSL now to reference SSL_CTX properly */
|
||||
tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx;
|
||||
tlsctx = tls_get_listener_tlsctx(tlslistensock, tid);
|
||||
RUNTIME_CHECK(tlsctx != NULL);
|
||||
isc_tlsctx_attach(tlsctx, &tlssock->tlsstream.ctx);
|
||||
tlssock->tlsstream.tls = isc_tls_create(tlssock->tlsstream.ctx);
|
||||
if (tlssock->tlsstream.tls == NULL) {
|
||||
atomic_store(&tlssock->closed, true);
|
||||
isc_tlsctx_free(&tlssock->tlsstream.ctx);
|
||||
isc__nmsocket_detach(&tlssock);
|
||||
return (ISC_R_TLSERROR);
|
||||
}
|
||||
|
|
@ -610,9 +625,7 @@ tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||
isc_nmhandle_attach(handle, &tlssock->outerhandle);
|
||||
tlssock->peer = handle->sock->peer;
|
||||
tlssock->read_timeout = atomic_load(&handle->sock->mgr->init);
|
||||
tlssock->tid = isc_nm_tid();
|
||||
|
||||
tlssock->tlsstream.ctx = tlslistensock->tlsstream.ctx;
|
||||
tlssock->tid = tid;
|
||||
|
||||
result = initialize_tls(tlssock, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
|
@ -640,7 +653,7 @@ isc_nm_listentls(isc_nm_t *mgr, isc_sockaddr_t *iface,
|
|||
tlssock->accept_cb = accept_cb;
|
||||
tlssock->accept_cbarg = accept_cbarg;
|
||||
tlssock->extrahandlesize = extrahandlesize;
|
||||
tlssock->tlsstream.ctx = sslctx;
|
||||
tls_init_listener_tlsctx(tlssock, sslctx);
|
||||
tlssock->tlsstream.tls = NULL;
|
||||
|
||||
/*
|
||||
|
|
@ -863,10 +876,9 @@ isc__nm_tls_stoplistening(isc_nmsocket_t *sock) {
|
|||
atomic_store(&sock->closed, true);
|
||||
sock->recv_cb = NULL;
|
||||
sock->recv_cbarg = NULL;
|
||||
if (sock->tlsstream.tls != NULL) {
|
||||
isc_tls_free(&sock->tlsstream.tls);
|
||||
sock->tlsstream.ctx = NULL;
|
||||
}
|
||||
|
||||
INSIST(sock->tlsstream.tls == NULL);
|
||||
INSIST(sock->tlsstream.ctx == NULL);
|
||||
|
||||
if (sock->outer != NULL) {
|
||||
isc_nm_stoplistening(sock->outer);
|
||||
|
|
@ -896,7 +908,7 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
|||
nsock->connect_cb = cb;
|
||||
nsock->connect_cbarg = cbarg;
|
||||
nsock->connect_timeout = timeout;
|
||||
nsock->tlsstream.ctx = ctx;
|
||||
isc_tlsctx_attach(ctx, &nsock->tlsstream.ctx);
|
||||
|
||||
isc_nm_tcpconnect(mgr, local, peer, tcp_connected, nsock,
|
||||
nsock->connect_timeout, 0);
|
||||
|
|
@ -1009,13 +1021,17 @@ isc__nm_tls_cleanup_data(isc_nmsocket_t *sock) {
|
|||
REQUIRE(VALID_NMSOCK(sock->tlsstream.tlslistener));
|
||||
isc__nmsocket_detach(&sock->tlsstream.tlslistener);
|
||||
} else if (sock->type == isc_nm_tlssocket) {
|
||||
if (sock->tlsstream.ctx != NULL) {
|
||||
isc_tlsctx_free(&sock->tlsstream.ctx);
|
||||
}
|
||||
if (sock->tlsstream.tls != NULL) {
|
||||
isc_tls_free(&sock->tlsstream.tls);
|
||||
/* These are destroyed when we free SSL */
|
||||
sock->tlsstream.ctx = NULL;
|
||||
sock->tlsstream.bio_out = NULL;
|
||||
sock->tlsstream.bio_in = NULL;
|
||||
}
|
||||
} else if (sock->type == isc_nm_tlslistener) {
|
||||
tls_cleanup_listener_tlsctx(sock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1064,3 +1080,61 @@ isc__nmhandle_tls_keepalive(isc_nmhandle_t *handle, bool value) {
|
|||
isc_nmhandle_keepalive(sock->outerhandle, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) {
|
||||
size_t nworkers;
|
||||
|
||||
REQUIRE(VALID_NM(listener->mgr));
|
||||
REQUIRE(ctx != NULL);
|
||||
|
||||
nworkers = (size_t)listener->mgr->nworkers;
|
||||
INSIST(nworkers > 0);
|
||||
|
||||
listener->tlsstream.listener_tls_ctx = isc_mem_get(
|
||||
listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers);
|
||||
listener->tlsstream.n_listener_tls_ctx = nworkers;
|
||||
for (size_t i = 0; i < nworkers; i++) {
|
||||
listener->tlsstream.listener_tls_ctx[i] = NULL;
|
||||
isc_tlsctx_attach(ctx,
|
||||
&listener->tlsstream.listener_tls_ctx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener) {
|
||||
REQUIRE(VALID_NM(listener->mgr));
|
||||
|
||||
if (listener->tlsstream.listener_tls_ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < listener->tlsstream.n_listener_tls_ctx; i++) {
|
||||
isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[i]);
|
||||
}
|
||||
isc_mem_put(listener->mgr->mctx, listener->tlsstream.listener_tls_ctx,
|
||||
sizeof(isc_tlsctx_t *) *
|
||||
listener->tlsstream.n_listener_tls_ctx);
|
||||
listener->tlsstream.n_listener_tls_ctx = 0;
|
||||
}
|
||||
|
||||
static isc_tlsctx_t *
|
||||
tls_get_listener_tlsctx(isc_nmsocket_t *listener, const int tid) {
|
||||
REQUIRE(VALID_NM(listener->mgr));
|
||||
REQUIRE(tid >= 0);
|
||||
|
||||
if (listener->tlsstream.listener_tls_ctx == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,3 +169,10 @@ OPENSSL_cleanup(void) {
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !HAVE_SSL_CTX_UP_REF
|
||||
int
|
||||
SSL_CTX_up_ref(SSL_CTX *ctx) {
|
||||
return (CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX) > 0);
|
||||
}
|
||||
#endif /* !HAVE_SSL_CTX_UP_REF */
|
||||
|
|
|
|||
|
|
@ -120,3 +120,8 @@ OPENSSL_cleanup(void);
|
|||
#if !HAVE_TLS_CLIENT_METHOD
|
||||
#define TLS_client_method SSLv23_client_method
|
||||
#endif
|
||||
|
||||
#if !HAVE_SSL_CTX_UP_REF
|
||||
int
|
||||
SSL_CTX_up_ref(SSL_CTX *store);
|
||||
#endif /* !HAVE_SSL_CTX_UP_REF */
|
||||
|
|
|
|||
|
|
@ -184,6 +184,16 @@ isc_tlsctx_free(isc_tlsctx_t **ctxp) {
|
|||
SSL_CTX_free(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
isc_tlsctx_attach(isc_tlsctx_t *src, isc_tlsctx_t **ptarget) {
|
||||
REQUIRE(src != NULL);
|
||||
REQUIRE(ptarget != NULL && *ptarget == NULL);
|
||||
|
||||
RUNTIME_CHECK(SSL_CTX_up_ref(src) == 1);
|
||||
|
||||
*ptarget = src;
|
||||
}
|
||||
|
||||
#if HAVE_SSL_CTX_SET_KEYLOG_CALLBACK
|
||||
/*
|
||||
* Callback invoked by the SSL library whenever a new TLS pre-master secret
|
||||
|
|
|
|||
|
|
@ -901,6 +901,25 @@ clearlistenon(ns_interfacemgr_t *mgr) {
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
replace_listener_tlsctx(ns_interfacemgr_t *mgr, ns_interface_t *ifp,
|
||||
isc_tlsctx_t *newctx) {
|
||||
char sabuf[ISC_SOCKADDR_FORMATSIZE];
|
||||
REQUIRE(NS_INTERFACE_VALID(ifp));
|
||||
|
||||
LOCK(&mgr->lock);
|
||||
isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
|
||||
"updating TLS context on %s", sabuf);
|
||||
if (ifp->tcplistensocket != NULL) {
|
||||
/* 'tcplistensocket' is used for DoT */
|
||||
isc_nmsocket_set_tlsctx(ifp->tcplistensocket, newctx);
|
||||
} else if (ifp->http_secure_listensocket != NULL) {
|
||||
isc_nmsocket_set_tlsctx(ifp->http_secure_listensocket, newctx);
|
||||
}
|
||||
UNLOCK(&mgr->lock);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) {
|
||||
isc_interfaceiter_t *iter = NULL;
|
||||
|
|
@ -968,42 +987,30 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) {
|
|||
|
||||
ifp = find_matching_interface(mgr, &listen_addr);
|
||||
if (ifp != NULL) {
|
||||
/*
|
||||
* We need to recreate the TLS/HTTPS listeners
|
||||
* during reconfiguration because the
|
||||
* certificates could have been changed.
|
||||
*/
|
||||
if (config && LISTENING(ifp) &&
|
||||
le->sslctx != NULL) {
|
||||
INSIST(NS_INTERFACE_VALID(ifp));
|
||||
LOCK(&mgr->lock);
|
||||
isc_sockaddr_format(&ifp->addr, sabuf,
|
||||
ifp->generation = mgr->generation;
|
||||
if (le->dscp != -1 && ifp->dscp == -1) {
|
||||
ifp->dscp = le->dscp;
|
||||
} else if (le->dscp != ifp->dscp) {
|
||||
isc_sockaddr_format(&listen_addr, sabuf,
|
||||
sizeof(sabuf));
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS,
|
||||
ISC_LOG_INFO,
|
||||
"no longer listening on "
|
||||
"%s",
|
||||
sabuf);
|
||||
interface_destroy(&ifp);
|
||||
UNLOCK(&mgr->lock);
|
||||
} else {
|
||||
ifp->generation = mgr->generation;
|
||||
if (le->dscp != -1 && ifp->dscp == -1) {
|
||||
ifp->dscp = le->dscp;
|
||||
} else if (le->dscp != ifp->dscp) {
|
||||
isc_sockaddr_format(
|
||||
&listen_addr, sabuf,
|
||||
sizeof(sabuf));
|
||||
isc_log_write(
|
||||
IFMGR_COMMON_LOGARGS,
|
||||
ISC_LOG_WARNING,
|
||||
"%s: conflicting DSCP "
|
||||
"values, using %d",
|
||||
sabuf, ifp->dscp);
|
||||
}
|
||||
if (LISTENING(ifp)) {
|
||||
continue;
|
||||
ISC_LOG_WARNING,
|
||||
"%s: conflicting DSCP "
|
||||
"values, using %d",
|
||||
sabuf, ifp->dscp);
|
||||
}
|
||||
if (LISTENING(ifp)) {
|
||||
/*
|
||||
* We need to update the TLS contexts
|
||||
* inside the TLS/HTTPS listeners during
|
||||
* a reconfiguration because the
|
||||
* certificates could have been changed.
|
||||
*/
|
||||
if (config && le->sslctx != NULL) {
|
||||
replace_listener_tlsctx(
|
||||
mgr, ifp, le->sslctx);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1144,42 +1151,32 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) {
|
|||
|
||||
ifp = find_matching_interface(mgr, &listen_sockaddr);
|
||||
if (ifp != NULL) {
|
||||
/*
|
||||
* We need to recreate the TLS/HTTPS listeners
|
||||
* during a reconfiguration because the
|
||||
* certificates could have been changed.
|
||||
*/
|
||||
if (config && LISTENING(ifp) &&
|
||||
le->sslctx != NULL) {
|
||||
INSIST(NS_INTERFACE_VALID(ifp));
|
||||
LOCK(&mgr->lock);
|
||||
isc_sockaddr_format(&ifp->addr, sabuf,
|
||||
ifp->generation = mgr->generation;
|
||||
if (le->dscp != -1 && ifp->dscp == -1) {
|
||||
ifp->dscp = le->dscp;
|
||||
} else if (le->dscp != ifp->dscp) {
|
||||
isc_sockaddr_format(&listen_sockaddr,
|
||||
sabuf,
|
||||
sizeof(sabuf));
|
||||
isc_log_write(IFMGR_COMMON_LOGARGS,
|
||||
ISC_LOG_INFO,
|
||||
"no longer listening on "
|
||||
"%s",
|
||||
sabuf);
|
||||
interface_destroy(&ifp);
|
||||
UNLOCK(&mgr->lock);
|
||||
} else {
|
||||
ifp->generation = mgr->generation;
|
||||
if (le->dscp != -1 && ifp->dscp == -1) {
|
||||
ifp->dscp = le->dscp;
|
||||
} else if (le->dscp != ifp->dscp) {
|
||||
isc_sockaddr_format(
|
||||
&listen_sockaddr, sabuf,
|
||||
sizeof(sabuf));
|
||||
isc_log_write(
|
||||
IFMGR_COMMON_LOGARGS,
|
||||
ISC_LOG_WARNING,
|
||||
"%s: conflicting DSCP "
|
||||
"values, using %d",
|
||||
sabuf, ifp->dscp);
|
||||
}
|
||||
if (LISTENING(ifp)) {
|
||||
continue;
|
||||
ISC_LOG_WARNING,
|
||||
"%s: conflicting DSCP "
|
||||
"values, using %d",
|
||||
sabuf, ifp->dscp);
|
||||
}
|
||||
if (LISTENING(ifp)) {
|
||||
/*
|
||||
* We need to update the TLS contexts
|
||||
* inside the TLS/HTTPS listeners during
|
||||
* a reconfiguration because the
|
||||
* certificates could have been changed.
|
||||
*/
|
||||
if (config && le->sslctx != NULL) {
|
||||
replace_listener_tlsctx(
|
||||
mgr, ifp, le->sslctx);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue