From: Evan Hunt Date: Wed, 17 Jun 2020 19:09:10 +0000 (-0700) Subject: restore "blackhole" functionality X-Git-Tag: v9.16.5~14^2~1 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=952461b6afc06375433506b28cf369bfff8db9cf;p=thirdparty%2Fbind9.git restore "blackhole" functionality 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) --- diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index 0c3f3adc7fb..73938d9d0c0 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -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 diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 5c598ae295c..cb3da7fc71f 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -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; diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 15cabce4904..c572777662d 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -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; diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index cfd9b3f873e..93f97d2e341 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -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)); diff --git a/lib/ns/client.c b/lib/ns/client.c index 8bcbb231157..ce6059af69e 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -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 diff --git a/lib/ns/include/ns/client.h b/lib/ns/include/ns/client.h index 74c435b0c61..7fa285745b0 100644 --- a/lib/ns/include/ns/client.h +++ b/lib/ns/include/ns/client.h @@ -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); /*%< diff --git a/lib/ns/include/ns/interfacemgr.h b/lib/ns/include/ns/interfacemgr.h index e60dc9d412b..d55bd1b82f6 100644 --- a/lib/ns/include/ns/interfacemgr.h +++ b/lib/ns/include/ns/interfacemgr.h @@ -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 * diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 633485f6478..9aba9d5c071 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -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; diff --git a/lib/ns/win32/libns.def b/lib/ns/win32/libns.def index d2b9ad652f5..1680e4982d6 100644 --- a/lib/ns/win32/libns.def +++ b/lib/ns/win32/libns.def @@ -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