]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Recreate TLS interfaces during reconfiguration
authorAram Sargsyan <aram@isc.org>
Thu, 9 Dec 2021 14:49:51 +0000 (14:49 +0000)
committerAram Sargsyan <aram@isc.org>
Mon, 13 Dec 2021 10:19:57 +0000 (10:19 +0000)
For DoH and DoT listeners, a reconfiguration event triggers a creation
of a new 'SSL_CTX' TLS context, and a destruction of the old one.

The network manager, though, keeps using the old context which causes
errors.

During interface scanning, when a matching existing interface is found,
reuse it only when it doesn't have a TLS context, otherwise shut it down
and recreate with a new TLS context.

lib/ns/interfacemgr.c

index 1bca46768ada7bf0738411880399df312f74cc25..38de7cfe23ff2f6aa1d7154245fb0f57d4564c82 100644 (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);
+                       if (ipv6_wildcard) {
+                               continue;
+                       }
 
-                               tried_listening = true;
-                               if (!addr_in_use) {
-                                       all_addresses_in_use = false;
-                               }
+                       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 (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;