Merge branch '3053-tls-listeners-recreate-on-reconfiguration' into 'main'

Recreate TLS interfaces during reconfiguration

Closes #3053

See merge request isc-projects/bind9!5634
This commit is contained in:
Arаm Sаrgsyаn
2021-12-13 11:06:09 +00:00
3 changed files with 155 additions and 85 deletions

View File

@@ -1,3 +1,7 @@
5778. [bug] Destroyed TLS contexts could have been used after a
reconfiguration, making BIND unable to serve queries
over TLS and HTTPS. [GL #3053]
5777. [bug] TCP connections could hang after receiving
non-matching responses. [GL #3042]

View File

@@ -35,6 +35,10 @@ dig_with_opts() {
"$DIG" $common_dig_options -p "${PORT}" "$@"
}
rndccmd() (
"$RNDC" -c ../common/rndc.conf -p "${CONTROLPORT}" -s "$@"
)
wait_for_tls_xfer() (
srv_number="$1"
shift
@@ -435,6 +439,29 @@ grep "ANSWER: 2500" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "doing rndc reconfig to see that queries keep being served after that ($n)"
ret=0
rndccmd 10.53.0.1 reconfig
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoT query (ephemeral key) after a reconfiguration ($n)"
ret=0
dig_with_tls_opts @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "checking DoH query (POST) after a reconfiguration ($n)"
ret=0
dig_with_https_opts @10.53.0.1 . SOA > dig.out.test$n
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
test_opcodes() {
EXPECT_STATUS="$1"
shift

View File

@@ -917,37 +917,60 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose) {
ifp = find_matching_interface(mgr, &listen_addr);
if (ifp != NULL) {
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,
/*
* We need to recreate the TLS/HTTPS listeners
* because the certificates could have been
* changed on reconfiguration.
*/
if (le->sslctx != NULL) {
INSIST(NS_INTERFACE_VALID(ifp));
LOCK(&mgr->lock);
ISC_LIST_UNLINK(ifp->mgr->interfaces,
ifp, link);
isc_sockaddr_format(&ifp->addr, sabuf,
sizeof(sabuf));
isc_log_write(IFMGR_COMMON_LOGARGS,
ISC_LOG_WARNING,
"%s: conflicting DSCP "
"values, using %d",
sabuf, ifp->dscp);
ISC_LOG_INFO,
"no longer listening on "
"%s",
sabuf);
ns_interface_shutdown(ifp);
ns_interface_detach(&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);
}
continue;
}
}
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
"listening on IPv6 "
"interfaces, port %u",
le->port);
result = ns_interface_setup(mgr, &listen_addr, "<any>",
&ifp, le, NULL);
if (result == ISC_R_SUCCESS) {
ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
} else {
isc_log_write(IFMGR_COMMON_LOGARGS,
ISC_LOG_INFO,
"listening on IPv6 "
"interfaces, port %u",
le->port);
result = ns_interface_setup(mgr, &listen_addr,
"<any>", &ifp, le,
NULL);
if (result == ISC_R_SUCCESS) {
ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
} else {
isc_log_write(IFMGR_COMMON_LOGARGS,
ISC_LOG_ERROR,
"listening on all IPv6 "
"interfaces failed");
}
/* Continue. */
ISC_LOG_ERROR,
"listening on all IPv6 "
"interfaces failed");
}
/* Continue. */
}
}
@@ -1031,6 +1054,7 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose) {
for (le = ISC_LIST_HEAD(ll->elts); le != NULL;
le = ISC_LIST_NEXT(le, link)) {
int match;
bool addr_in_use = false;
bool ipv6_wildcard = false;
isc_netaddr_t listen_netaddr;
isc_sockaddr_t listen_sockaddr;
@@ -1078,71 +1102,86 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose) {
ifp = find_matching_interface(mgr, &listen_sockaddr);
if (ifp != NULL) {
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,
/*
* We need to recreate the TLS/HTTPS listeners
* because the certificates could have been
* changed on reconfiguration.
*/
if (le->sslctx != NULL) {
INSIST(NS_INTERFACE_VALID(ifp));
LOCK(&mgr->lock);
ISC_LIST_UNLINK(ifp->mgr->interfaces,
ifp, link);
isc_sockaddr_format(&ifp->addr, sabuf,
sizeof(sabuf));
isc_log_write(IFMGR_COMMON_LOGARGS,
ISC_LOG_WARNING,
"%s: conflicting DSCP "
"values, using %d",
sabuf, ifp->dscp);
}
} else {
bool addr_in_use = false;
if (ipv6_wildcard) {
ISC_LOG_INFO,
"no longer listening on "
"%s",
sabuf);
ns_interface_shutdown(ifp);
ns_interface_detach(&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);
}
continue;
}
if (log_explicit && family == AF_INET6 &&
listenon_is_ip6_any(le)) {
isc_log_write(
IFMGR_COMMON_LOGARGS,
verbose ? ISC_LOG_INFO
: ISC_LOG_DEBUG(1),
"IPv6 socket API is "
"incomplete; explicitly "
"binding to each IPv6 "
"address separately");
log_explicit = false;
}
isc_sockaddr_format(&listen_sockaddr, sabuf,
sizeof(sabuf));
isc_log_write(
IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
"listening on %s interface "
"%s, %s",
(family == AF_INET) ? "IPv4" : "IPv6",
interface.name, sabuf);
result = ns_interface_setup(
mgr, &listen_sockaddr, interface.name,
&ifp, le, &addr_in_use);
tried_listening = true;
if (!addr_in_use) {
all_addresses_in_use = false;
}
if (result != ISC_R_SUCCESS) {
isc_log_write(IFMGR_COMMON_LOGARGS,
ISC_LOG_ERROR,
"creating %s interface "
"%s failed; interface "
"ignored",
(family == AF_INET) ? "IP"
"v4"
: "IP"
"v"
"6",
interface.name);
}
/* Continue. */
}
if (ipv6_wildcard) {
continue;
}
if (log_explicit && family == AF_INET6 &&
listenon_is_ip6_any(le)) {
isc_log_write(IFMGR_COMMON_LOGARGS,
verbose ? ISC_LOG_INFO
: ISC_LOG_DEBUG(1),
"IPv6 socket API is "
"incomplete; explicitly "
"binding to each IPv6 "
"address separately");
log_explicit = false;
}
isc_sockaddr_format(&listen_sockaddr, sabuf,
sizeof(sabuf));
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO,
"listening on %s interface "
"%s, %s",
(family == AF_INET) ? "IPv4" : "IPv6",
interface.name, sabuf);
result = ns_interface_setup(mgr, &listen_sockaddr,
interface.name, &ifp, le,
&addr_in_use);
tried_listening = true;
if (!addr_in_use) {
all_addresses_in_use = false;
}
if (result != ISC_R_SUCCESS) {
isc_log_write(
IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
"creating %s interface "
"%s failed; interface ignored",
(family == AF_INET) ? "IPv4" : "IPv6",
interface.name);
}
/* Continue. */
}
continue;