]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
restore "blackhole" functionality
authorEvan Hunt <each@isc.org>
Wed, 17 Jun 2020 19:09:10 +0000 (12:09 -0700)
committerEvan Hunt <each@isc.org>
Wed, 1 Jul 2020 04:10:31 +0000 (21:10 -0700)
the blackhole ACL was accidentally disabled with respect to client
queries during the netmgr conversion.

in order to make this work for TCP, it was necessary to add a return
code to the accept callback functions passed to isc_nm_listentcp() and
isc_nm_listentcpdns().

(cherry picked from commit 23c7373d68d2b5aca838aab2ebb16e1c9156ed60)

lib/isc/include/isc/netmgr.h
lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/tcp.c
lib/isc/netmgr/tcpdns.c
lib/ns/client.c
lib/ns/include/ns/client.h
lib/ns/include/ns/interfacemgr.h
lib/ns/interfacemgr.c
lib/ns/win32/libns.def

index 0c3f3adc7fb936ae39357a55fbbbc783d60f85b6..73938d9d0c0ca8a6d4fc1ce28dd1b9b27aef99dc 100644 (file)
@@ -24,6 +24,47 @@ typedef enum {
        NMEV_SHUTDOWN
 } isc_nm_eventtype;
 
+typedef void (*isc_nm_recv_cb_t)(isc_nmhandle_t *handle, isc_region_t *region,
+                                void *cbarg);
+/*%<
+ * Callback function to be used when receiving a packet.
+ *
+ * 'handle' the handle that can be used to send back the answer.
+ * 'region' contains the received data. It will be freed after
+ *          return by caller.
+ * 'cbarg'  the callback argument passed to isc_nm_listenudp(),
+ *          isc_nm_listentcpdns(), or isc_nm_read().
+ */
+
+typedef isc_result_t (*isc_nm_accept_cb_t)(isc_nmhandle_t *handle,
+                                          isc_result_t result, void *cbarg);
+/*%<
+ * Callback function to be used when accepting a connection. (This differs
+ * from isc_nm_cb_t below in that it returns a result code.)
+ *
+ * 'handle' the handle that can be used to send back the answer.
+ * 'eresult' the result of the event.
+ * 'cbarg'  the callback argument passed to isc_nm_listentcp() or
+ * isc_nm_listentcpdns().
+ */
+
+typedef void (*isc_nm_cb_t)(isc_nmhandle_t *handle, isc_result_t result,
+                           void *cbarg);
+/*%<
+ * Callback function for other network completion events (send, connect).
+ *
+ * 'handle' the handle on which the event took place.
+ * 'eresult' the result of the event.
+ * 'cbarg'  the callback argument passed to isc_nm_send(),
+ *          isc_nm_tcp_connect(), or isc_nm_listentcp()
+ */
+
+typedef void (*isc_nm_opaquecb_t)(void *arg);
+/*%<
+ * Opaque callback function, used for isc_nmhandle 'reset' and 'free'
+ * callbacks.
+ */
+
 isc_nm_t *
 isc_nm_start(isc_mem_t *mctx, uint32_t workers);
 /*%<
@@ -102,8 +143,6 @@ isc_nmhandle_getdata(isc_nmhandle_t *handle);
 void *
 isc_nmhandle_getextra(isc_nmhandle_t *handle);
 
-typedef void (*isc_nm_opaquecb_t)(void *arg);
-
 bool
 isc_nmhandle_is_stream(isc_nmhandle_t *handle);
 
@@ -135,30 +174,6 @@ isc_nmhandle_netmgr(isc_nmhandle_t *handle);
  * Return a pointer to the netmgr object for the given handle.
  */
 
-typedef void (*isc_nm_recv_cb_t)(isc_nmhandle_t *handle, isc_region_t *region,
-                                void *cbarg);
-/*%<
- * Callback function to be used when receiving a packet.
- *
- * 'handle' the handle that can be used to send back the answer.
- * 'region' contains the received data. It will be freed after
- *          return by caller.
- * 'cbarg'  the callback argument passed to isc_nm_listenudp(),
- *          isc_nm_listentcpdns(), or isc_nm_read().
- */
-
-typedef void (*isc_nm_cb_t)(isc_nmhandle_t *handle, isc_result_t result,
-                           void *cbarg);
-/*%<
- * Callback function for other network completion events (send, connect,
- * accept).
- *
- * 'handle' the handle on which the event took place.
- * 'result' the result of the event.
- * 'cbarg'  the callback argument passed to isc_nm_send(),
- *          isc_nm_tcp_connect(), or isc_nm_listentcp()
- */
-
 isc_result_t
 isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
                 void *cbarg, size_t extrasize, isc_nmsocket_t **sockp);
@@ -227,9 +242,10 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
  */
 
 isc_result_t
-isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
-                void *cbarg, size_t extrahandlesize, int backlog,
-                isc_quota_t *quota, isc_nmsocket_t **sockp);
+isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
+                isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
+                size_t extrahandlesize, int backlog, isc_quota_t *quota,
+                isc_nmsocket_t **sockp);
 /*%<
  * Start listening for raw messages over the TCP interface 'iface', using
  * net manager 'mgr'.
@@ -237,8 +253,8 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
  * On success, 'sockp' will be updated to contain a new listening TCP
  * socket.
  *
- * When a message is received on the socket, 'cb' will be called with 'cbarg'
- * as its argument.
+ * When connection is accepted on the socket, 'accept_cb' will be called with
+ * 'accept_cbarg' as its argument. The callback is expected to start a read.
  *
  * When handles are allocated for the socket, 'extrasize' additional bytes
  * will be allocated along with the handle for an associated object.
@@ -253,9 +269,9 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
 
 isc_result_t
 isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
-                   void *cbarg, isc_nm_cb_t accept_cb, void *accept_cbarg,
-                   size_t extrahandlesize, int backlog, isc_quota_t *quota,
-                   isc_nmsocket_t **sockp);
+                   void *cbarg, isc_nm_accept_cb_t accept_cb,
+                   void *accept_cbarg, size_t extrahandlesize, int backlog,
+                   isc_quota_t *quota, isc_nmsocket_t **sockp);
 /*%<
  * Start listening for DNS messages over the TCP interface 'iface', using
  * net manager 'mgr'.
@@ -269,7 +285,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
  * When a complete DNS message is received on the socket, 'cb' will be
  * called with 'cbarg' as its argument.
  *
- * When a new TCP connection is accepted, 'accept_cb' will be called
+ * When a new TCPDNS connection is accepted, 'accept_cb' will be called
  * with 'accept_cbarg' as its argument.
  *
  * When handles are allocated for the socket, 'extrasize' additional bytes
index 5c598ae295cc93c670bb14b2042681e5824187b7..cb3da7fc71f2ea0c5a42a2abc83a8bbb6820932a 100644 (file)
@@ -158,7 +158,7 @@ typedef enum isc__netievent_type {
  */
 typedef union {
        isc_nm_recv_cb_t recv;
-       isc_nm_cb_t accept;
+       isc_nm_accept_cb_t accept;
 } isc__nm_readcb_t;
 
 typedef union {
@@ -168,7 +168,7 @@ typedef union {
 
 typedef union {
        isc_nm_recv_cb_t recv;
-       isc_nm_cb_t accept;
+       isc_nm_accept_cb_t accept;
        isc_nm_cb_t send;
        isc_nm_cb_t connect;
 } isc__nm_cb_t;
index 15cabce49044d02bd0815313f77c4e455d7ecd1b..c572777662dd66e040b3f161d8baab8aa0a6de2d 100644 (file)
@@ -160,9 +160,10 @@ tcp_connect_cb(uv_connect_t *uvreq, int status) {
 }
 
 isc_result_t
-isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
-                void *cbarg, size_t extrahandlesize, int backlog,
-                isc_quota_t *quota, isc_nmsocket_t **sockp) {
+isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface,
+                isc_nm_accept_cb_t accept_cb, void *accept_cbarg,
+                size_t extrahandlesize, int backlog, isc_quota_t *quota,
+                isc_nmsocket_t **sockp) {
        isc_nmsocket_t *nsock = NULL;
        isc__netievent_tcplisten_t *ievent = NULL;
 
@@ -170,8 +171,8 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t cb,
 
        nsock = isc_mem_get(mgr->mctx, sizeof(*nsock));
        isc__nmsocket_init(nsock, mgr, isc_nm_tcplistener, iface);
-       nsock->rcb.accept = cb;
-       nsock->rcbarg = cbarg;
+       nsock->accept_cb.accept = accept_cb;
+       nsock->accept_cbarg = accept_cbarg;
        nsock->extrahandlesize = extrahandlesize;
        nsock->backlog = backlog;
        nsock->result = ISC_R_SUCCESS;
@@ -383,9 +384,9 @@ isc__nm_async_tcpchildaccept(isc__networker_t *worker, isc__netievent_t *ev0) {
 
        handle = isc__nmhandle_get(csock, NULL, &local);
 
-       INSIST(ssock->rcb.accept != NULL);
+       INSIST(ssock->accept_cb.accept != NULL);
        csock->read_timeout = ssock->mgr->init;
-       ssock->rcb.accept(handle, ISC_R_SUCCESS, ssock->rcbarg);
+       ssock->accept_cb.accept(handle, ISC_R_SUCCESS, ssock->accept_cbarg);
        isc_nmsocket_detach(&csock);
        return;
 
index cfd9b3f873e125e67ddbeda856d99600be1293d5..93f97d2e341e3b82a7514ac133517b1616ad5dc6 100644 (file)
@@ -98,7 +98,7 @@ dnstcp_readtimeout(uv_timer_t *timer) {
 /*
  * Accept callback for TCP-DNS connection.
  */
-static void
+static isc_result_t
 dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
        isc_nmsocket_t *dnslistensock = (isc_nmsocket_t *)cbarg;
        isc_nmsocket_t *dnssock = NULL;
@@ -106,14 +106,16 @@ dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
        REQUIRE(VALID_NMSOCK(dnslistensock));
        REQUIRE(dnslistensock->type == isc_nm_tcpdnslistener);
 
-       /* If accept() was unnsuccessful we can't do anything */
        if (result != ISC_R_SUCCESS) {
-               return;
+               return (result);
        }
 
        if (dnslistensock->accept_cb.accept != NULL) {
-               dnslistensock->accept_cb.accept(handle, ISC_R_SUCCESS,
-                                               dnslistensock->accept_cbarg);
+               result = dnslistensock->accept_cb.accept(
+                       handle, ISC_R_SUCCESS, dnslistensock->accept_cbarg);
+               if (result != ISC_R_SUCCESS) {
+                       return (result);
+               }
        }
 
        /* We need to create a 'wrapper' dnssocket for this connection */
@@ -137,6 +139,8 @@ dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
                       dnssock->read_timeout, 0);
 
        isc_nm_read(handle, dnslisten_readcb, dnssock);
+
+       return (ISC_R_SUCCESS);
 }
 
 /*
@@ -283,9 +287,9 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
  */
 isc_result_t
 isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
-                   void *cbarg, isc_nm_cb_t accept_cb, void *accept_cbarg,
-                   size_t extrahandlesize, int backlog, isc_quota_t *quota,
-                   isc_nmsocket_t **sockp) {
+                   void *cbarg, isc_nm_accept_cb_t accept_cb,
+                   void *accept_cbarg, size_t extrahandlesize, int backlog,
+                   isc_quota_t *quota, isc_nmsocket_t **sockp) {
        /* A 'wrapper' socket object with outer set to true TCP socket */
        isc_nmsocket_t *dnslistensock = isc_mem_get(mgr->mctx,
                                                    sizeof(*dnslistensock));
index 8bcbb2311571313d737482850ae06a397a965e26..ce6059af69e99910fda29f6cf3e86629122bd1db 100644 (file)
@@ -1617,7 +1617,6 @@ ns__client_put_cb(void *client0) {
 void
 ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
        ns_client_t *client;
-       bool newclient = false;
        ns_clientmgr_t *mgr;
        ns_interface_t *ifp;
        isc_result_t result;
@@ -1714,29 +1713,23 @@ ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
        }
 #endif /* if NS_CLIENT_DROPPORT */
 
+       env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
+       if (client->sctx->blackholeacl != NULL &&
+           (dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl, env,
+                          &match, NULL) == ISC_R_SUCCESS) &&
+           match > 0)
+       {
+               ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+                             NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+                             "dropped request: blackholed peer");
+               isc_task_unpause(client->task);
+               return;
+       }
+
        ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
                      ISC_LOG_DEBUG(3), "%s request",
                      TCP_CLIENT(client) ? "TCP" : "UDP");
 
-       /*
-        * Check the blackhole ACL for UDP only, since TCP is done in
-        * client_newconn.
-        */
-       env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
-       if (newclient) {
-               if (client->sctx->blackholeacl != NULL &&
-                   (dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl,
-                                  env, &match, NULL) == ISC_R_SUCCESS) &&
-                   match > 0)
-               {
-                       ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
-                                     NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
-                                     "blackholed UDP datagram");
-                       isc_task_unpause(client->task);
-                       return;
-               }
-       }
-
        result = dns_message_peekheader(buffer, &id, &flags);
        if (result != ISC_R_SUCCESS) {
                /*
@@ -2197,17 +2190,36 @@ ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
        isc_task_unpause(client->task);
 }
 
-void
+isc_result_t
 ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
-       ns_server_t *sctx = (ns_server_t *)arg;
+       ns_interface_t *ifp = (ns_interface_t *)arg;
+       dns_aclenv_t *env = ns_interfacemgr_getaclenv(ifp->mgr);
+       ns_server_t *sctx = ns_interfacemgr_getserver(ifp->mgr);
        unsigned int tcpquota;
+       isc_sockaddr_t peeraddr;
+       isc_netaddr_t netaddr;
+       int match;
 
-       UNUSED(handle);
        UNUSED(result);
 
+       if (handle != NULL) {
+               peeraddr = isc_nmhandle_peeraddr(handle);
+               isc_netaddr_fromsockaddr(&netaddr, &peeraddr);
+
+               if (sctx->blackholeacl != NULL &&
+                   (dns_acl_match(&netaddr, NULL, sctx->blackholeacl, env,
+                                  &match, NULL) == ISC_R_SUCCESS) &&
+                   match > 0)
+               {
+                       return (ISC_R_CONNREFUSED);
+               }
+       }
+
        tcpquota = isc_quota_getused(&sctx->tcpquota);
        ns_stats_update_if_greater(sctx->nsstats, ns_statscounter_tcphighwater,
                                   tcpquota);
+
+       return (ISC_R_SUCCESS);
 }
 
 static void
index 74c435b0c61d0f213983a6135c791178b6870f51..7fa285745b0728da4676103d29809cfdf9a2435b 100644 (file)
@@ -475,7 +475,7 @@ ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg);
  * (Not intended for use outside this module and associated tests.)
  */
 
-void
+isc_result_t
 ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg);
 
 /*%<
index e60dc9d412b525967183ad269a77d3051f8a4c34..d55bd1b82f62e3e85b5ecd18f6999e27652cb5b7 100644 (file)
@@ -197,6 +197,12 @@ ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr);
 bool
 ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, const isc_sockaddr_t *addr);
 
+ns_server_t *
+ns_interfacemgr_getserver(ns_interfacemgr_t *mgr);
+/*%<
+ * Returns the ns_server object associated with the interface manager.
+ */
+
 ns_interface_t *
 ns__interfacemgr_getif(ns_interfacemgr_t *mgr);
 ns_interface_t *
index 633485f6478ee9b5503d06b011198bdaa206dac0..9aba9d5c0715f25642f867b8f12dda0961f964ef 100644 (file)
@@ -467,7 +467,7 @@ ns_interface_listentcp(ns_interface_t *ifp) {
 
        result = isc_nm_listentcpdns(
                ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, ns__client_request,
-               ifp, ns__client_tcpconn, ifp->mgr->sctx, sizeof(ns_client_t),
+               ifp, ns__client_tcpconn, ifp, sizeof(ns_client_t),
                ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota,
                &ifp->tcplistensocket);
        if (result != ISC_R_SUCCESS) {
@@ -481,7 +481,12 @@ ns_interface_listentcp(ns_interface_t *ifp) {
         * this is necessary because we are adding to the TCP quota just
         * by listening.
         */
-       ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp->mgr->sctx);
+       result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp);
+       if (result != ISC_R_SUCCESS) {
+               isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+                             "connecting TCP socket: %s",
+                             isc_result_totext(result));
+       }
 
 #if 0
 #ifndef ISC_ALLOW_MAPPED
@@ -1267,6 +1272,13 @@ ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr,
        return (result);
 }
 
+ns_server_t *
+ns_interfacemgr_getserver(ns_interfacemgr_t *mgr) {
+       REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+
+       return (mgr->sctx);
+}
+
 ns_interface_t *
 ns__interfacemgr_getif(ns_interfacemgr_t *mgr) {
        ns_interface_t *head;
index d2b9ad652f547555397081d6867211546e3d59db..1680e4982d68a81351cb5efd4efe372bfdc71da9 100644 (file)
@@ -55,6 +55,7 @@ ns_interfacemgr_create
 ns_interfacemgr_detach
 ns_interfacemgr_dumprecursing
 ns_interfacemgr_getaclenv
+ns_interfacemgr_getserver
 ns_interfacemgr_islistening
 ns_interfacemgr_listeningon
 ns_interfacemgr_scan