From: Mark Andrews Date: Thu, 5 Jan 2006 03:26:01 +0000 (+0000) Subject: 1961. [bug] Check the port and address of responses forwarded X-Git-Tag: v9.2.7b1~91^2~35 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=a295fbb55cfed38bcf2853c60410cce52ab6cebb;p=thirdparty%2Fbind9.git 1961. [bug] Check the port and address of responses forwarded to dispatch. [RT #15474] --- diff --git a/CHANGES b/CHANGES index 563958e06d2..020bbbc75c2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +1961. [bug] Check the port and address of responses forwarded + to dispatch. [RT #15474] + 1960. [bug] Update code should set NSEC ttls from SOA MINIMUM. [RT #15465] diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 72bf1058a20..e7da8f1bd1a 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.124 2005/07/12 01:00:14 marka Exp $ */ +/* $Id: dispatch.c,v 1.125 2006/01/05 03:26:01 marka Exp $ */ /*! \file */ @@ -643,6 +643,50 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) { free_buffer(disp, ev->region.base, ev->region.length); goto unlock; } + + /* + * Now that we have the original dispatch the query was sent + * from check that the address and port the response was + * sent to make sense. + */ + if (disp != resp->disp) { + isc_sockaddr_t a1; + isc_sockaddr_t a2; + + /* + * Check that the socket types and ports match. + */ + if (disp->socktype != resp->disp->socktype || + isc_sockaddr_getport(&disp->local) != + isc_sockaddr_getport(&resp->disp->local)) { + free_buffer(disp, ev->region.base, ev->region.length); + goto unlock; + } + + /* + * If both dispatches are bound to an address then fail as + * the addresses can't be equal (enforced by the IP stack). + * + * Note under Linux a packet can be sent out via IPv4 socket + * and the response be received via a IPv6 socket. + * + * Requests sent out via IPv6 should always come back in + * via IPv6. + */ + if (isc_sockaddr_pf(&resp->disp->local) == PF_INET6 && + isc_sockaddr_pf(&disp->local) != PF_INET6) { + free_buffer(disp, ev->region.base, ev->region.length); + goto unlock; + } + isc_sockaddr_anyofpf(&a1, isc_sockaddr_pf(&resp->disp->local)); + isc_sockaddr_anyofpf(&a2, isc_sockaddr_pf(&disp->local)); + if (!isc_sockaddr_eqaddr(&a1, &resp->disp->local) && + !isc_sockaddr_eqaddr(&a2, &disp->local)) { + free_buffer(disp, ev->region.base, ev->region.length); + goto unlock; + } + } + queue_response = resp->item_out; rev = allocate_event(resp->disp); if (rev == NULL) {