diff --git a/CHANGES b/CHANGES index 4d8e876894..826bad4e13 100644 --- a/CHANGES +++ b/CHANGES @@ -7,7 +7,8 @@ query (CVE-2014-8500). The recursion depth limit is configured via the - "max-recursion-depth" option. [RT #37580] + "max-recursion-depth" option, and the query limit + via the "max-recursion-queries" option. [RT #37580] 4004. [bug] When delegations had AAAA glue but not A, a reference could be leaked causing an assertion diff --git a/bin/named/config.c b/bin/named/config.c index 5ee8c4ee66..ebc48cfc46 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -159,6 +159,7 @@ options {\n\ clients-per-query 10;\n\ max-clients-per-query 100;\n\ max-recursion-depth 7;\n\ + max-recursion-queries 50;\n\ zero-no-soa-ttl-cache no;\n\ nsec3-test-zone no;\n\ allow-new-zones no;\n\ diff --git a/bin/named/server.c b/bin/named/server.c index 0559977f63..76542b9a87 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -3166,6 +3166,11 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, INSIST(result == ISC_R_SUCCESS); dns_resolver_setmaxdepth(view->resolver, cfg_obj_asuint32(obj)); + obj = NULL; + result = ns_config_get(maps, "max-recursion-queries", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_resolver_setmaxqueries(view->resolver, cfg_obj_asuint32(obj)); + #ifdef ALLOW_FILTER_AAAA_ON_V4 obj = NULL; result = ns_config_get(maps, "filter-aaaa-on-v4", &obj); diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in index 06c212b291..2745c1f46e 100644 --- a/bin/tests/system/conf.sh.in +++ b/bin/tests/system/conf.sh.in @@ -67,8 +67,8 @@ SUBDIRS="acl additional allow_query addzone autosign builtin @COVERAGE@ database dlv dlvauto dlz dlzexternal dname dns64 dnssec ecdsa emptyzones filter-aaaa formerr forward glue gost ixfr inline limits logfileconfig lwresd masterfile - masterformat metadata notify nslookup nsupdate pending - pkcs11 redirect resolver rndc rpz rrl rrsetorder rsabigexponent + masterformat metadata notify nslookup nsupdate pending pkcs11 + reclimit redirect resolver rndc rpz rrl rrsetorder rsabigexponent smartsign sortlist spf staticstub stub tkey tsig tsiggss unknown upforwd verify views wildcard xfer xferquota zero zonechecks" diff --git a/bin/tests/system/many/ns2/named.conf b/bin/tests/system/many/ns2/named.conf deleted file mode 100644 index 16266e225a..0000000000 --- a/bin/tests/system/many/ns2/named.conf +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -controls { /* empty */ }; - -options { - query-source address 10.53.0.2; - notify-source 10.53.0.2; - transfer-source 10.53.0.2; - port 5300; - pid-file "named.pid"; - listen-on { 10.53.0.2; }; - listen-on-v6 { none; }; - recursion no; -}; - -include "zones.conf"; diff --git a/bin/tests/system/many/setup.sh b/bin/tests/system/many/setup.sh deleted file mode 100644 index ee59f928b1..0000000000 --- a/bin/tests/system/many/setup.sh +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -i=1 - -cat > ns3/root.db << EOF -. 60 in soa ns.nil. hostmaster.ns.nil. 1 0 0 0 0 -. 60 in ns ns.nil. -ns.nil. 60 in a 10.53.0.3 -tld1. 60 in ns ns.tld1. -ns.tld1. 60 in a 10.53.0.3 -tld2. 60 in ns ns.tld2. -ns.tld2. 60 in a 10.53.0.4 -EOF - -cat > ns3/tld1.db << EOF -tld1. 60 in soa ns.tld1. hostmaster.ns.tld1. 1 0 0 0 0 -tld1. 60 in ns ns.tld1. -ns.tld1. 60 in a 10.53.0.1 -EOF - -cat > ns4/tld2.db << EOF -tld2. 60 in soa ns.tld2. hostmaster.ns.tld4. 1 0 0 0 0 -tld2. 60 in ns ns.tld2. -ns.tld2. 60 in a 10.53.0.1 -EOF - -: > ns1/zones.conf -: > ns2/zones.conf - -while [ $i -lt 1000 ] -do -j=`expr $i + 1` -s=`expr $j % 2 + 1` -n=`expr $i % 2 + 1` -t=`expr $s + 2` - -# i=1 j=2 s=1 n=2 -# i=2 j=3 s=1 n=2 -# i=3 j=4 s=1 n=2 - -cat > ns1/${i}example.tld${s}.db << EOF -${i}example.tld${s}. 60 in soa ns.${j}example.tld${n}. hostmaster 1 0 0 0 0 -${i}example.tld${s}. 60 in ns ns.${j}example.tld${n}. -ns.${i}example.tld${s}. 60 in a 10.53.0.1 -EOF - -cat >> ns1/zones.conf << EOF -zone "${i}example.tld${s}" { type master; file "${i}example.tld${s}.db"; }; -EOF - -cat >> ns${t}/tld${s}.db << EOF -${i}example.tld${s}. 60 in ns ns.${j}example.tld${n}. -EOF - -i=$j - -done - -j=`expr $i + 1` -s=`expr $j % 2 + 1` -n=`expr $s % 2 + 1` -t=`expr $s + 2` - -cat > ns1/${i}example.tld${s}.db << EOF -${i}example.tld${s}. 60 in soa ns.${i}example.tld${s}. hostmaster 1 0 0 0 0 -${i}example.tld${s}. 60 in ns ns.${i}example.tld${s}. -ns.${i}example.tld${s}. 60 in a 10.53.0.1 -EOF - -cat >> ns1/zones.conf << EOF -zone "${i}example.tld${s}" { type master; file "${i}example.tld${s}.db"; }; -EOF - -cat >> ns${t}/tld${s}.db << EOF -${i}example.tld${s}. 60 in ns ns.${i}example.tld${s}. -ns.${i}example.tld${s}. 60 in a 10.53.0.1 -EOF diff --git a/bin/tests/system/many/tests.sh b/bin/tests/system/many/tests.sh deleted file mode 100644 index 37964e2635..0000000000 --- a/bin/tests/system/many/tests.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -SYSTEMTESTTOP=.. -. $SYSTEMTESTTOP/conf.sh - -status=0 -n=0 - -n=`expr $n + 1` -echo "I: attempt lookup 1example.tld2 soa ($n)" -ret=0 -$DIG +tcp 1example.tld1 soa @10.53.0.5 -p 5300 > dig.out.test$n -grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 -if [ $ret != 0 ]; then echo "I:failed"; fi -status=`expr $status + $ret` - -n=`expr $n + 1` -echo "I: attempt lookup 992example.tld2 soa ($n)" -ret=0 -$DIG +tcp 992example.tld2 soa @10.53.0.5 -p 5300 > dig.out.test$n -grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 -if [ $ret != 0 ]; then echo "I:failed"; fi -status=`expr $status + $ret` - -n=`expr $n + 1` -echo "I: attempt lookup 993example.tld1 soa ($n)" -ret=0 -$DIG +tcp 993example.tld1 soa @10.53.0.5 -p 5300 > dig.out.test$n -grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 -if [ $ret != 0 ]; then echo "I:failed"; fi -status=`expr $status + $ret` - -echo "I:exit status: $status" -exit $status diff --git a/bin/tests/system/reclimit/README b/bin/tests/system/reclimit/README new file mode 100644 index 0000000000..b802a057ef --- /dev/null +++ b/bin/tests/system/reclimit/README @@ -0,0 +1,6 @@ +system test for recursion limits + +ns1 -- root server +ans2 -- delegate to ns1.(n+1).example.com for all n, up to + the value specified in ans.limit +ns3 -- resolver under test diff --git a/bin/tests/system/reclimit/ans2/ans.pl b/bin/tests/system/reclimit/ans2/ans.pl new file mode 100644 index 0000000000..a6e39a6a94 --- /dev/null +++ b/bin/tests/system/reclimit/ans2/ans.pl @@ -0,0 +1,115 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use IO::File; +use Getopt::Long; +use Net::DNS::Nameserver; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +my $count = 0; +my $send_response = 0; + +sub getlimit { + if ( -e "ans.limit") { + open(FH, "<", "ans.limit"); + my $line = ; + chomp $line; + close FH; + if ($line =~ /^\d+$/) { + return $line; + } + } + + return 0; +} + +my $localaddr = "10.53.0.2"; +my $localport = 5300; +my $verbose = 0; +my $limit = getlimit(); + +sub reply_handler { + my ($qname, $qclass, $qtype, $peerhost, $query, $conn) = @_; + my ($rcode, @ans, @auth, @add); + + print ("request: $qname/$qtype\n"); + STDOUT->flush(); + + $count += 1; + + if ($qname eq "count" ) { + if ($qtype eq "TXT") { + my ($ttl, $rdata) = (0, "$count"); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + print ("\tcount: $count\n"); + } + $rcode = "NOERROR"; + } elsif ($qname eq "reset" ) { + $count = 0; + $send_response = 0; + $limit = getlimit(); + $rcode = "NOERROR"; + print ("\tlimit: $limit\n"); + } elsif ($qname eq "direct.example.org" ) { + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname eq "indirect.example.org") { + if (! $send_response) { + my $rr = new Net::DNS::RR("indirect.example.org 86400 $qclass NS ns1.1.example.org"); + push @auth, $rr; + } elsif ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); + push @ans, $rr; + } + $rcode = "NOERROR"; + } elsif ($qname =~ /^ns1\.(\d+)\.example\.org$/) { + my $next = $1 + 1; + if ($limit == 0 || (! $send_response && $next <= $limit)) { + my $rr = new Net::DNS::RR("$1.example.org 86400 $qclass NS ns1.$next.example.org"); + push @auth, $rr; + } else { + $send_response = 1; + if ($qtype eq "A") { + my ($ttl, $rdata) = (3600, $localaddr); + my $rr = new Net::DNS::RR("$qname $ttl $qclass $qtype $rdata"); +print("\tresponse: $qname $ttl $qclass $qtype $rdata\n"); + push @ans, $rr; + } + } + $rcode = "NOERROR"; + } else { + $rcode = "NXDOMAIN"; + } + + # mark the answer as authoritive (by setting the 'aa' flag + return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); +} + +GetOptions( + 'port=i' => \$localport, + 'verbose!' => \$verbose, +); + +my $ns = Net::DNS::Nameserver->new( + LocalAddr => $localaddr, + LocalPort => $localport, + ReplyHandler => \&reply_handler, + Verbose => $verbose, +); + +$ns->main_loop; diff --git a/bin/tests/system/many/clean.sh b/bin/tests/system/reclimit/clean.sh similarity index 83% rename from bin/tests/system/many/clean.sh rename to bin/tests/system/reclimit/clean.sh index d9e08fb675..b48874ae74 100644 --- a/bin/tests/system/many/clean.sh +++ b/bin/tests/system/reclimit/clean.sh @@ -1,3 +1,5 @@ +#!/bin/sh +# # Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") # # Permission to use, copy, modify, and/or distribute this software for any @@ -12,10 +14,6 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -rm -f ns1/[1-9]*example.tld?.db -rm -f ns2/[1-9]*example.tld?.db -rm -f ns1/zones.conf -rm -f ns2/zones.conf -rm -f */root.db -rm -f ns3/tld1.db -rm -f ns4/tld2.db +rm -f dig.out* +rm -f ans2/ans.limit +rm -f ns3/named.conf diff --git a/bin/tests/system/many/ns1/named.conf b/bin/tests/system/reclimit/ns1/named.conf similarity index 89% rename from bin/tests/system/many/ns1/named.conf rename to bin/tests/system/reclimit/ns1/named.conf index abc9dca4bc..5e1c947d10 100644 --- a/bin/tests/system/many/ns1/named.conf +++ b/bin/tests/system/reclimit/ns1/named.conf @@ -17,6 +17,7 @@ controls { /* empty */ }; options { + directory "."; query-source address 10.53.0.1; notify-source 10.53.0.1; transfer-source 10.53.0.1; @@ -27,7 +28,4 @@ options { recursion no; }; -include "zones.conf"; - -// zone "tld1" { type master; file "tld1.db"; }; -// zone "tld2" { type master; file "tld2.db"; }; +zone "." { type master; file "root.db"; }; diff --git a/bin/tests/system/reclimit/ns1/root.db b/bin/tests/system/reclimit/ns1/root.db new file mode 100644 index 0000000000..8e706b2bde --- /dev/null +++ b/bin/tests/system/reclimit/ns1/root.db @@ -0,0 +1,20 @@ +; Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +. 60 IN SOA ns.nil. hostmaster.ns.nil. 1 0 0 0 0 +. 60 IN NS ns.nil. +ns.nil. 60 IN A 10.53.0.1 +ns.tld1. 60 IN A 10.53.0.1 +example.org. 60 IN NS direct.example.org. +direct.example.org. 60 IN A 10.53.0.2 diff --git a/bin/tests/system/reclimit/ns3/.gitignore b/bin/tests/system/reclimit/ns3/.gitignore new file mode 100644 index 0000000000..58e5c9282d --- /dev/null +++ b/bin/tests/system/reclimit/ns3/.gitignore @@ -0,0 +1 @@ +named.conf diff --git a/bin/tests/system/many/ns5/hints.db b/bin/tests/system/reclimit/ns3/hints.db similarity index 94% rename from bin/tests/system/many/ns5/hints.db rename to bin/tests/system/reclimit/ns3/hints.db index 6b7041a021..2ea27ca54f 100644 --- a/bin/tests/system/many/ns5/hints.db +++ b/bin/tests/system/reclimit/ns3/hints.db @@ -12,5 +12,5 @@ ; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ; PERFORMANCE OF THIS SOFTWARE. -. 60 in ns ns.nil. -ns.nil. 60 in A 10.53.0.3 +. 60 IN NS ns.nil. +ns.nil. 60 IN A 10.53.0.1 diff --git a/bin/tests/system/many/ns5/named.conf b/bin/tests/system/reclimit/ns3/named1.conf similarity index 73% rename from bin/tests/system/many/ns5/named.conf rename to bin/tests/system/reclimit/ns3/named1.conf index fce7d5925f..558c230a5c 100644 --- a/bin/tests/system/many/ns5/named.conf +++ b/bin/tests/system/reclimit/ns3/named1.conf @@ -17,13 +17,25 @@ controls { /* empty */ }; options { - query-source address 10.53.0.5; - notify-source 10.53.0.5; - transfer-source 10.53.0.5; + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; port 5300; pid-file "named.pid"; - listen-on { 10.53.0.5; }; + listen-on { 10.53.0.3; }; listen-on-v6 { none; }; + servfail-ttl 0; + max-recursion-depth 12; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; }; }; zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/many/ns3/named.conf b/bin/tests/system/reclimit/ns3/named2.conf similarity index 79% rename from bin/tests/system/many/ns3/named.conf rename to bin/tests/system/reclimit/ns3/named2.conf index b950afe9c7..eb1fa09f63 100644 --- a/bin/tests/system/many/ns3/named.conf +++ b/bin/tests/system/reclimit/ns3/named2.conf @@ -17,6 +17,7 @@ controls { /* empty */ }; options { + directory "."; query-source address 10.53.0.3; notify-source 10.53.0.3; transfer-source 10.53.0.3; @@ -24,9 +25,17 @@ options { pid-file "named.pid"; listen-on { 10.53.0.3; }; listen-on-v6 { none; }; - recursion no; + servfail-ttl 0; + max-recursion-depth 5; }; -zone "." { type master; file "root.db"; }; +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; -zone "tld1" { type master; file "tld1.db"; }; +controls { + inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/many/ns4/named.conf b/bin/tests/system/reclimit/ns3/named3.conf similarity index 70% rename from bin/tests/system/many/ns4/named.conf rename to bin/tests/system/reclimit/ns3/named3.conf index ca9aa6a7ee..1c3679a89e 100644 --- a/bin/tests/system/many/ns4/named.conf +++ b/bin/tests/system/reclimit/ns3/named3.conf @@ -17,14 +17,25 @@ controls { /* empty */ }; options { - query-source address 10.53.0.4; - notify-source 10.53.0.4; - transfer-source 10.53.0.4; + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; port 5300; pid-file "named.pid"; - listen-on { 10.53.0.4; }; + listen-on { 10.53.0.3; }; listen-on-v6 { none; }; - recursion no; + servfail-ttl 0; + max-recursion-depth 100; }; -zone "tld2" { type master; file "tld2.db"; }; +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/reclimit/ns3/named4.conf b/bin/tests/system/reclimit/ns3/named4.conf new file mode 100644 index 0000000000..46da44803c --- /dev/null +++ b/bin/tests/system/reclimit/ns3/named4.conf @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +controls { /* empty */ }; + +options { + directory "."; + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + servfail-ttl 0; + max-recursion-depth 100; + max-recursion-queries 40; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; }; +}; + +zone "." { type hint; file "hints.db"; }; diff --git a/bin/tests/system/reclimit/setup.sh b/bin/tests/system/reclimit/setup.sh new file mode 100644 index 0000000000..f4adda2123 --- /dev/null +++ b/bin/tests/system/reclimit/setup.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# +# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +cp -f ns3/named1.conf ns3/named.conf diff --git a/bin/tests/system/reclimit/tests.sh b/bin/tests/system/reclimit/tests.sh new file mode 100644 index 0000000000..f67da3e3dc --- /dev/null +++ b/bin/tests/system/reclimit/tests.sh @@ -0,0 +1,154 @@ +#!/bin/sh +# +# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +DIGOPTS="-p 5300" + +status=0 +n=0 + +n=`expr $n + 1` +echo "I: attempt excessive-depth lookup ($n)" +ret=0 +echo "1000" > ans2/ans.limit +$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1 +grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1 +$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1 +eval count=`cat dig.out.2.test$n` +[ $count -eq 26 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: attempt permissible lookup ($n)" +ret=0 +echo "12" > ans2/ans.limit +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /' +$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1 +$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1 +eval count=`cat dig.out.2.test$n` +[ $count -eq 49 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:reset max-recursion-depth" +cp ns3/named2.conf ns3/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reconfig 2>&1 | sed 's/^/I:ns1 /' +sleep 2 + +n=`expr $n + 1` +echo "I: attempt excessive-depth lookup ($n)" +ret=0 +echo "12" > ans2/ans.limit +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /' +$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1 +grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1 +$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1 +eval count=`cat dig.out.2.test$n` +[ $count -eq 12 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: attempt permissible lookup ($n)" +ret=0 +echo "5" > ans2/ans.limit +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /' +$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1 +$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1 +eval count=`cat dig.out.2.test$n` +[ $count -eq 21 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:reset max-recursion-depth" +cp ns3/named3.conf ns3/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reconfig 2>&1 | sed 's/^/I:ns1 /' +sleep 2 + +n=`expr $n + 1` +echo "I: attempt excessive-queries lookup ($n)" +ret=0 +echo "25" > ans2/ans.limit +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /' +$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1 +grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1 +grep "exceeded max queries resolving 'indirect.example.org/A'" ns3/named.run > /dev/null || ret=1 +$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1 +eval count=`cat dig.out.2.test$n` +[ $count -eq 100 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: attempt permissible lookup ($n)" +ret=0 +echo "24" > ans2/ans.limit +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /' +$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1 +$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1 +eval count=`cat dig.out.2.test$n` +[ $count -eq 97 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:reset max-recursion-queries" +cp ns3/named4.conf ns3/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reconfig 2>&1 | sed 's/^/I:ns1 /' +sleep 2 + +n=`expr $n + 1` +echo "I: attempt excessive-queries lookup ($n)" +ret=0 +echo "21" > ans2/ans.limit +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /' +$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1 +grep "status: SERVFAIL" dig.out.1.test$n > /dev/null || ret=1 +grep "exceeded max queries resolving 'indirect.example.org/A'" ns3/named.run > /dev/null || ret=1 +$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1 +eval count=`cat dig.out.2.test$n` +[ $count -eq 84 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I: attempt permissible lookup ($n)" +ret=0 +echo "19" > ans2/ans.limit +$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 flush 2>&1 | sed 's/^/I:ns1 /' +$DIG $DIGOPTS @10.53.0.2 reset > /dev/null || ret=1 +$DIG $DIGOPTS @10.53.0.3 indirect.example.org > dig.out.1.test$n || ret=1 +grep "status: NOERROR" dig.out.1.test$n > /dev/null || ret=1 +$DIG $DIGOPTS +short @10.53.0.2 count txt > dig.out.2.test$n || ret=1 +eval count=`cat dig.out.2.test$n` +[ $count -eq 77 ] || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:exit status: $status" +exit $status diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index fff4249773..957ccbf875 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -8686,8 +8686,26 @@ avoid-v6-udp-ports { 40000; range 50000 60000; }; Sets the maximum number of levels of recursion - permitted at any one time while resolving a name. - The default is 7. + that are permitted at any one time while servicing + a recursive query. Resolving a name may require + looking up a name server address, which in turn + requires resolving another name, etc; if the number + of indirections exceeds this value, the recursive + query is terminated and returns SERVFAIL. The + default is 7. + + + + + + max-recursion-queries + + + Sets the maximum number of iterative queries that + may be sent while servicing a recursive query. + If more queries are sent, the recursive query + is terminated and returns SERVFAIL. The default + is 50. diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index c2560493ec..8a8200a7ec 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -601,6 +601,18 @@ dns_resolver_getmaxdepth(dns_resolver_t *resolver); * \li resolver to be valid. */ +void +dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries); +unsigned int +dns_resolver_getmaxqueries(dns_resolver_t *resolver); +/*% + * Get and set how many iterative queries will be allowed before + * terminating a recursive query. + * + * Requires: + * \li resolver to be valid. + */ + ISC_LANG_ENDDECLS #endif /* DNS_RESOLVER_H */ diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 6a635b2737..30dfdc9d30 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -432,6 +432,7 @@ struct dns_resolver { isc_boolean_t zero_no_soa_ttl; unsigned int query_timeout; unsigned int maxdepth; + unsigned int maxqueries; /* Locked by lock. */ unsigned int references; @@ -2210,9 +2211,9 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) { */ INSIST(!SHUTTINGDOWN(fctx)); fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; + fctx->totalqueries += find->qtotal; if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { want_try = ISC_TRUE; - fctx->totalqueries += find->qtotal; } else { fctx->findfail++; if (fctx->pending == 0) { @@ -2242,7 +2243,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) { else if (want_done) fctx_done(fctx, ISC_R_FAILURE, __LINE__); else if (destroy) { - fctx_destroy(fctx); + fctx_destroy(fctx); if (bucket_empty) empty_bucket(res); } @@ -2611,7 +2612,10 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) { res = fctx->res; if (fctx->depth > res->maxdepth) { - FCTXTRACE("too much NS indirection"); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), + "too much NS indirection resolving '%s'", + fctx->info); return (DNS_R_SERVFAIL); } @@ -3053,8 +3057,14 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) { REQUIRE(!ADDRWAIT(fctx)); - if (fctx->totalqueries > DEFAULT_MAX_QUERIES) + if (fctx->totalqueries > fctx->res->maxqueries) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), + "exceeded max queries resolving '%s'", + fctx->info); fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); + return; + } addrinfo = fctx_nextaddress(fctx); if (addrinfo == NULL) { @@ -5708,7 +5718,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, char qbuf[DNS_NAME_FORMATSIZE]; char nbuf[DNS_NAME_FORMATSIZE]; char tbuf[DNS_RDATATYPE_FORMATSIZE]; - dns_rdatatype_format(fctx->type, tbuf, + dns_rdatatype_format(type, tbuf, sizeof(tbuf)); dns_name_format(name, nbuf, sizeof(nbuf)); @@ -5717,7 +5727,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, log_formerr(fctx, "unrelated %s %s in " "%s authority section", - tbuf, qbuf, nbuf); + tbuf, nbuf, qbuf); goto nextname; } if (type == dns_rdatatype_ns) { @@ -7813,6 +7823,7 @@ dns_resolver_create(dns_view_t *view, res->zero_no_soa_ttl = ISC_FALSE; res->query_timeout = DEFAULT_QUERY_TIMEOUT; res->maxdepth = DEFAULT_RECURSION_DEPTH; + res->maxqueries = DEFAULT_MAX_QUERIES; res->nbuckets = ntasks; res->activebuckets = ntasks; res->buckets = isc_mem_get(view->mctx, @@ -9165,3 +9176,15 @@ dns_resolver_getmaxdepth(dns_resolver_t *resolver) { REQUIRE(VALID_RESOLVER(resolver)); return (resolver->maxdepth); } + +void +dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) { + REQUIRE(VALID_RESOLVER(resolver)); + resolver->maxqueries = queries; +} + +unsigned int +dns_resolver_getmaxqueries(dns_resolver_t *resolver) { + REQUIRE(VALID_RESOLVER(resolver)); + return (resolver->maxqueries); +} diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 5f8b037064..1c82f9bfd0 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - /*! \file */ #include @@ -1394,6 +1392,7 @@ view_clauses[] = { { "max-clients-per-query", &cfg_type_uint32, 0 }, { "max-ncache-ttl", &cfg_type_uint32, 0 }, { "max-recursion-depth", &cfg_type_uint32, 0 }, + { "max-recursion-queries", &cfg_type_uint32, 0 }, { "max-udp-size", &cfg_type_uint32, 0 }, { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP }, { "minimal-responses", &cfg_type_boolean, 0 },