mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
Fix a bug in RPZ that could cause unwanted recursion (#39229)
Conflicts: doc/arm/notes.xml
This commit is contained in:
parent
012142bbe0
commit
b947e1a521
6
CHANGES
6
CHANGES
@ -1,3 +1,9 @@
|
||||
4116. [bug] Fix a bug in RPZ that could cause some policy
|
||||
zones that did not specifically require
|
||||
recursion to be treated as if they did;
|
||||
consequently, setting qname-wait-recurse no; was
|
||||
sometimes ineffective. [RT #39229]
|
||||
|
||||
4115. [func] "rndc -r" now prints the result code (e.g.,
|
||||
ISC_R_SUCCESS, ISC_R_TIMEOUT, etc) after
|
||||
running the requested command. [RT #38913]
|
||||
|
@ -19,6 +19,7 @@ involving a different DNS setup. They are:
|
||||
(not a complete resolver test suite)
|
||||
rrl/ query rate limiting
|
||||
rpz/ Tests of response policy zone (RPZ) rewriting
|
||||
rpzrecurse/ Another set of RPZ tests to check recursion behavior
|
||||
stub/ Tests of stub zone functionality
|
||||
unknown/ Unknown type and class tests
|
||||
upforwd/ Update forwarding tests
|
||||
|
@ -72,8 +72,9 @@ SUBDIRS="acl additional allow_query addzone autosign builtin
|
||||
legacy limits logfileconfig lwresd
|
||||
masterfile masterformat metadata mkeys
|
||||
notify nslookup nsupdate pending pipelined @PKCS11_TEST@
|
||||
reclimit redirect resolver rndc rpz rrl rrchecker rrsetorder
|
||||
rsabigexponent runtime sit sfcache smartsign sortlist spf
|
||||
reclimit redirect resolver rndc rpz rpzrecurse
|
||||
rrl rrchecker rrsetorder rsabigexponent runtime
|
||||
sit sfcache smartsign sortlist spf
|
||||
staticstub statistics stub tcp tkey tsig tsiggss unknown
|
||||
upforwd verify views wildcard xfer xferquota zero zonechecks"
|
||||
|
||||
|
@ -635,7 +635,7 @@ for i in 1 2 3 4 5; do
|
||||
nsd $ns5 delete '*.example.com.policy1.' example.com.policy1.
|
||||
done
|
||||
|
||||
echo "I:checking checking that going from a empty policy zone works"
|
||||
echo "I:checking that going from a empty policy zone works"
|
||||
nsd $ns5 add '*.x.servfail.policy2.' x.servfail.policy2.
|
||||
sleep 1
|
||||
$RNDCCMD $ns7 reload policy2
|
||||
|
2
bin/tests/system/rpzrecurse/.gitignore
vendored
Normal file
2
bin/tests/system/rpzrecurse/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/rpz
|
||||
/rpz.o
|
113
bin/tests/system/rpzrecurse/README
Normal file
113
bin/tests/system/rpzrecurse/README
Normal file
@ -0,0 +1,113 @@
|
||||
These tests check RPZ recursion behavior (including skipping
|
||||
recursion when appropriate).
|
||||
|
||||
The general structure of the tests is:
|
||||
|
||||
* The resolver (ns2) with an unqualified view containing the policy
|
||||
zones, the response-policy statement, and a root hint zone
|
||||
|
||||
* The auth server that contains two authoritative zones, l1.l0 and
|
||||
l2.l1.l0, both delegated to itself. l2.l1.l0 specifies a non-existent
|
||||
zone data file and so will generate SERVFAILs for any queries to it.
|
||||
|
||||
The l2.l1.l0 zone was chosen to generate SERVFAIL responses because RPZ
|
||||
evaluation will use that error response whenever it encounters it during
|
||||
processing, thus making it a binary indicator for whether or not
|
||||
recursion was attempted. This also allows us to not worry about having
|
||||
to craft 'ip', 'nsdname', and 'nsip' rules that matched the queries.
|
||||
|
||||
Each test is intended to be fed a number of queries constructed as
|
||||
qXX.l2.l1.l0, where XX is the 1-based query sequence number (e.g. the
|
||||
first query of each test is q01.l2.l1.l0).
|
||||
|
||||
For all the tests the triggers are constructed as follows:
|
||||
client-ip - match 127.0.0.1/32
|
||||
ip - match 255.255.255.255/32 (does not matter due to SERVFAIL)
|
||||
nsdname - match does.not.matter (and it doesn't)
|
||||
nsip - match 255.255.255.255/32 (also does not matter)
|
||||
qname - match qXX.l2.l1.l0, where XX is the query sequence number that
|
||||
is intended to be matched by this qname rule.
|
||||
|
||||
Here's the detail on the test cases:
|
||||
|
||||
Group 1 - testing skipping recursion for a single policy zone with only
|
||||
records that allow recursion to be skipped
|
||||
|
||||
Test 1a:
|
||||
1 policy zone containing 1 'client-ip' trigger
|
||||
1 query, expected to skip recursion
|
||||
|
||||
Test 1b:
|
||||
1 policy zone containing 1 'qname' trigger (q01)
|
||||
2 queries, q01 is expected to skip recursion, q02 is expected to
|
||||
recurse
|
||||
|
||||
Test 1c:
|
||||
1 policy zone containing both a 'client-ip' and 'qname' trigger (q02)
|
||||
1 query, expected to skip recursion
|
||||
|
||||
Group 2 - testing skipping recursion with multiple policy zones when all
|
||||
zones have only trigger types eligible to skip recursion with
|
||||
|
||||
Test 2a:
|
||||
32 policy zones, each containing 1 'qname' trigger (qNN, where NN is
|
||||
the zone's sequence 1-based sequence number formatted to 2 digits,
|
||||
so each of the first 32 queries should match a different zone)
|
||||
33 queries, the first 32 of which are expected to skip recursion
|
||||
while the 33rd is expected to recurse
|
||||
|
||||
Group 3 - Testing interaction of triggers that require recursion when in
|
||||
a single zone, both alone and with triggers that allow recursion to be
|
||||
skipped
|
||||
|
||||
Test 3a:
|
||||
1 policy zone containing 1 'ip' trigger
|
||||
1 query, expected to recurse
|
||||
|
||||
Test 3b:
|
||||
1 policy zone containing 1 'nsdname' trigger
|
||||
1 query, expected to recurse
|
||||
|
||||
Test 3c:
|
||||
1 policy zone containing 1 'nsip' trigger
|
||||
1 query, expected to recurse
|
||||
|
||||
Test 3d:
|
||||
1 policy zone containing 1 'ip' trigger and 1 'qname' trigger (q02)
|
||||
2 queries, the first should not recurse and the second should recurse
|
||||
|
||||
Test 3e:
|
||||
1 policy zone containing 1 'nsdname' trigger and 1 'qname' trigger
|
||||
(q02)
|
||||
2 queries, the first should not recurse and the second should recurse
|
||||
|
||||
Test 3f:
|
||||
1 policy zone containing 1 'nsip' trigger and 1 'qname' trigger (q02)
|
||||
2 queries, the first should not recurse and the second should recurse
|
||||
|
||||
Group 4 - contains 32 subtests designed to verify that recursion is
|
||||
skippable for only the appropriate zones based on the order specified in
|
||||
the 'response-policy' statement
|
||||
|
||||
Tests 4aa to 4bf:
|
||||
32 policy zones per test, one of which is configured with 1 'ip'
|
||||
trigger and one 'qname' trigger while the others are configured
|
||||
only with 1 'qname' trigger. The zone with both triggers starts
|
||||
listed first and is moved backwards by one position with each
|
||||
test. The 'qname' triggers in the zones are structured so that
|
||||
the zones are tested starting with the first zone and the 'ip'
|
||||
trigger is tested before the 'qname' trigger for that zone.
|
||||
33 queries per test, where the number expected to skip recursion
|
||||
matches the test sequence number: e.g. 1 skip for 4aa, 26 skips
|
||||
for 4az, and 32 skips for 4bf
|
||||
|
||||
Group 5 - This test verifies that the "pivot" policy zone for whether or
|
||||
not recursion can be skipped is the first listed zone with applicable
|
||||
trigger types rather than a later listed zone.
|
||||
|
||||
Test 5a:
|
||||
5 policy zones, the 1st, 3rd, and 5th configured with 1 'qname'
|
||||
trigger each (q01, q04, and q06, respectively), the 2nd and 4th
|
||||
each configured with an 'ip' and 'qname' trigger (q02 and q05,
|
||||
respectively for the 'qname' triggers
|
||||
6 queries, of which only q01 and q02 are expected to skip recursion
|
24
bin/tests/system/rpzrecurse/clean.sh
Normal file
24
bin/tests/system/rpzrecurse/clean.sh
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (C) 2015 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.
|
||||
|
||||
# Clean up after rpz tests.
|
||||
|
||||
rm -f dig.out.*
|
||||
rm -f ns2/named.conf
|
||||
rm -f ns2/*.local
|
||||
rm -f ns2/*.queries
|
||||
rm -f ns2/named.*.conf
|
||||
rm -f ns*/named.lock
|
||||
rm -f ns*/named.memstats
|
||||
rm -f ns*/named.run
|
6
bin/tests/system/rpzrecurse/ns1/db.l0
Normal file
6
bin/tests/system/rpzrecurse/ns1/db.l0
Normal file
@ -0,0 +1,6 @@
|
||||
$TTL 60
|
||||
@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
|
||||
NS ns
|
||||
ns A 10.53.0.1
|
||||
l1 NS ns.l1
|
||||
ns.l1 A 10.53.0.1
|
6
bin/tests/system/rpzrecurse/ns1/db.l1.l0
Normal file
6
bin/tests/system/rpzrecurse/ns1/db.l1.l0
Normal file
@ -0,0 +1,6 @@
|
||||
$TTL 60
|
||||
@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
|
||||
NS ns
|
||||
ns A 10.53.0.1
|
||||
l2 NS ns.l2
|
||||
ns.l2 A 10.53.0.1
|
46
bin/tests/system/rpzrecurse/ns1/named.conf
Normal file
46
bin/tests/system/rpzrecurse/ns1/named.conf
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type master;
|
||||
file "root.db";
|
||||
};
|
||||
|
||||
zone "l0" {
|
||||
type master;
|
||||
file "db.l0";
|
||||
};
|
||||
|
||||
zone "l1.l0" {
|
||||
type master;
|
||||
file "db.l1.l0";
|
||||
};
|
||||
|
||||
zone "l2.l1.l0" {
|
||||
type master;
|
||||
file "does-not-exist";
|
||||
};
|
27
bin/tests/system/rpzrecurse/ns1/root.db
Normal file
27
bin/tests/system/rpzrecurse/ns1/root.db
Normal file
@ -0,0 +1,27 @@
|
||||
; Copyright (C) 2015 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.
|
||||
|
||||
$TTL 300
|
||||
. IN SOA muks.isc.org. a.root.servers.nil. (
|
||||
2010 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
. NS a.root-servers.nil.
|
||||
a.root-servers.nil. A 10.53.0.1
|
||||
|
||||
l0. NS ns.l0.
|
||||
ns.l0. A 10.53.0.1
|
3
bin/tests/system/rpzrecurse/ns2/.gitignore
vendored
Normal file
3
bin/tests/system/rpzrecurse/ns2/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/*.local
|
||||
/*.queries
|
||||
/*.conf
|
9
bin/tests/system/rpzrecurse/ns2/named.conf.default
Normal file
9
bin/tests/system/rpzrecurse/ns2/named.conf.default
Normal file
@ -0,0 +1,9 @@
|
||||
# common configuration
|
||||
include "named.conf.header";
|
||||
|
||||
view "recursive" {
|
||||
zone "." {
|
||||
type hint;
|
||||
file "root.hint";
|
||||
};
|
||||
};
|
29
bin/tests/system/rpzrecurse/ns2/named.conf.header
Normal file
29
bin/tests/system/rpzrecurse/ns2/named.conf.header
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 yes;
|
||||
querylog yes;
|
||||
};
|
17
bin/tests/system/rpzrecurse/ns2/root.hint
Normal file
17
bin/tests/system/rpzrecurse/ns2/root.hint
Normal file
@ -0,0 +1,17 @@
|
||||
; Copyright (C) 2015 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.
|
||||
|
||||
$TTL 999999
|
||||
. IN NS a.root-servers.nil.
|
||||
a.root-servers.nil. IN A 10.53.0.1
|
29
bin/tests/system/rpzrecurse/prereq.sh
Normal file
29
bin/tests/system/rpzrecurse/prereq.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2015 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
|
||||
|
||||
ret=0
|
||||
../rpz/rpz nsdname || ret=1
|
||||
../rpz/rpz nsip || ret=1
|
||||
|
||||
if [ $ret != 0 ]; then
|
||||
echo "I:This test requires NSIP AND NSDNAME support in RPZ." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec $SHELL ../testcrypto.sh
|
21
bin/tests/system/rpzrecurse/setup.sh
Normal file
21
bin/tests/system/rpzrecurse/setup.sh
Normal file
@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2015 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
|
||||
|
||||
perl testgen.pl
|
||||
cp -f ns2/named.conf.default ns2/named.conf
|
299
bin/tests/system/rpzrecurse/testgen.pl
Executable file
299
bin/tests/system/rpzrecurse/testgen.pl
Executable file
@ -0,0 +1,299 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $boilerplate_header = <<'EOB';
|
||||
# common configuration
|
||||
include "named.conf.header";
|
||||
|
||||
view "recursive" {
|
||||
zone "." {
|
||||
type hint;
|
||||
file "root.hint";
|
||||
};
|
||||
|
||||
# policy configuration to be tested
|
||||
response-policy {
|
||||
EOB
|
||||
|
||||
my $boilerplate_middle = <<'EOB';
|
||||
} qname-wait-recurse no;
|
||||
|
||||
# policy zones to be tested
|
||||
EOB
|
||||
|
||||
my $boilerplate_end = <<'EOB';
|
||||
};
|
||||
EOB
|
||||
|
||||
my $policy_zone_header = <<'EOH';
|
||||
$TTL 60
|
||||
@ IN SOA root.ns ns 1996072700 3600 1800 86400 60
|
||||
NS ns
|
||||
ns A 127.0.0.1
|
||||
EOH
|
||||
|
||||
sub policy_client_ip {
|
||||
return "32.1.0.0.127.rpz-client-ip CNAME .\n";
|
||||
}
|
||||
|
||||
sub policy_qname {
|
||||
my $query_nbr = shift;
|
||||
return sprintf "q%02d.l2.l1.l0 CNAME .\n", $query_nbr;
|
||||
}
|
||||
|
||||
sub policy_ip {
|
||||
return "32.255.255.255.255.rpz-ip CNAME .\n";
|
||||
}
|
||||
|
||||
sub policy_nsdname {
|
||||
return "does.not.matter.rpz-nsdname CNAME .\n";
|
||||
}
|
||||
|
||||
sub policy_nsip {
|
||||
return "32.255.255.255.255.rpz-ip CNAME .\n";
|
||||
}
|
||||
|
||||
my %static_triggers = (
|
||||
'client-ip' => \&policy_client_ip,
|
||||
'ip' => \&policy_ip,
|
||||
'nsdname' => \&policy_nsdname,
|
||||
'nsip' => \&policy_nsip,
|
||||
);
|
||||
|
||||
sub mkconf {
|
||||
my $case_id = shift;
|
||||
my $n_queries = shift;
|
||||
|
||||
{ # generate the query list
|
||||
my $query_list_filename = "ns2/$case_id.queries";
|
||||
my $query_list_fh;
|
||||
|
||||
open $query_list_fh, ">$query_list_filename" or die;
|
||||
|
||||
for( my $i = 1; $i <= $n_queries; $i++ ) {
|
||||
print $query_list_fh sprintf "q%02d.l2.l1.l0\n", $i;
|
||||
}
|
||||
}
|
||||
|
||||
my @zones;
|
||||
|
||||
{ # generate the conf file
|
||||
my $conf_filename = "ns2/named.$case_id.conf";
|
||||
|
||||
my $conf_fh;
|
||||
|
||||
open $conf_fh, ">$conf_filename" or die;
|
||||
|
||||
print $conf_fh $boilerplate_header;
|
||||
|
||||
my $zone_seq = 0;
|
||||
|
||||
@zones = map {
|
||||
[
|
||||
sprintf( "$case_id.%02d.policy.local", $zone_seq++ ),
|
||||
$_,
|
||||
];
|
||||
} @_;
|
||||
|
||||
print $conf_fh map { qq{ zone "$_->[0]";\n} } @zones;
|
||||
|
||||
print $conf_fh $boilerplate_middle;
|
||||
|
||||
print $conf_fh map { qq{ zone "$_->[0]" { type master; file "db.$_->[0]"; };\n} } @zones;
|
||||
|
||||
print $conf_fh $boilerplate_end;
|
||||
}
|
||||
|
||||
# generate the policy zone contents
|
||||
foreach my $policy_zone_info( @zones ) {
|
||||
my $policy_zone_name = $policy_zone_info->[0];
|
||||
my $policy_zone_contents = $policy_zone_info->[1];
|
||||
|
||||
my $policy_zone_filename = "ns2/db.$policy_zone_name";
|
||||
my $policy_zone_fh;
|
||||
|
||||
open $policy_zone_fh, ">$policy_zone_filename" or die;
|
||||
|
||||
print $policy_zone_fh $policy_zone_header;
|
||||
|
||||
foreach my $trigger( @$policy_zone_contents ) {
|
||||
if( exists $static_triggers{$trigger} ) {
|
||||
# matches a trigger type with a static value
|
||||
print $policy_zone_fh $static_triggers{$trigger}->();
|
||||
}
|
||||
else {
|
||||
# a qname trigger, where what was specified is the query number it should match
|
||||
print $policy_zone_fh policy_qname( $trigger );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mkconf(
|
||||
'1a',
|
||||
1,
|
||||
[ 'client-ip' ],
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'1b',
|
||||
2,
|
||||
[ 1 ],
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'1c',
|
||||
1,
|
||||
[ 'client-ip', 2 ],
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'2a',
|
||||
33,
|
||||
map { [ $_ ]; } 1 .. 32
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'3a',
|
||||
1,
|
||||
[ 'ip' ],
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'3b',
|
||||
1,
|
||||
[ 'nsdname' ],
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'3c',
|
||||
1,
|
||||
[ 'nsip' ],
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'3d',
|
||||
2,
|
||||
[ 'ip', 1 ]
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'3e',
|
||||
2,
|
||||
[ 'nsdname', 1 ]
|
||||
);
|
||||
|
||||
mkconf(
|
||||
'3f',
|
||||
2,
|
||||
[ 'nsip', 1 ]
|
||||
);
|
||||
|
||||
{
|
||||
my $seq_code = 'aa';
|
||||
my $seq_nbr = 0;
|
||||
|
||||
while( $seq_nbr < 32 ) {
|
||||
|
||||
mkconf(
|
||||
"4$seq_code",
|
||||
33,
|
||||
( map { [ $_ ]; } 1 .. $seq_nbr ),
|
||||
[ 'ip', $seq_nbr + 2 ],
|
||||
( map { [ $_ + 2 ]; } ($seq_nbr + 1) .. 31 ),
|
||||
);
|
||||
|
||||
$seq_code++;
|
||||
$seq_nbr++;
|
||||
}
|
||||
}
|
||||
|
||||
mkconf(
|
||||
'5a',
|
||||
6,
|
||||
[ 1 ],
|
||||
[ 2, 'ip' ],
|
||||
[ 4 ],
|
||||
[ 5, 'ip' ],
|
||||
[ 6 ],
|
||||
);
|
||||
|
||||
__END__
|
||||
|
||||
0x01 - has client-ip
|
||||
32.1.0.0.127.rpz-client-ip CNAME .
|
||||
0x02 - has qname
|
||||
qX.l2.l1.l0 CNAME .
|
||||
0x10 - has ip
|
||||
32.255.255.255.255.rpz-ip CNAME .
|
||||
0x20 - has nsdname
|
||||
does.not.matter.rpz-nsdname CNAME .
|
||||
0x40 - has nsip
|
||||
32.255.255.255.255.rpz-nsip CNAME .
|
||||
|
||||
$case.$seq.policy.local
|
||||
|
||||
case 1a = 0x01
|
||||
.q01 = (00,0x01)=-r
|
||||
case 1b = 0x02
|
||||
.q01 = (00,0x02)=-r
|
||||
.q02 = (--,----)=+r
|
||||
case 1c = 0x03
|
||||
.q01 = (00,0x01)=-r
|
||||
|
||||
case 2a = 0x03{32}
|
||||
.q01 = (00,0x02)=-r
|
||||
.q02 = (01,0x02)=-r
|
||||
...
|
||||
.q31 = (30,0x02)=-r
|
||||
.q32 = (31,0x02)=-r
|
||||
.q33 = (--,----)=+r
|
||||
|
||||
case 3a = 0x10
|
||||
.q01 = (00,0x10)=+r
|
||||
case 3b = 0x20
|
||||
.q01 = (00,0x20)=+r
|
||||
case 3c = 0x40
|
||||
.q01 = (00,0x40)=+r
|
||||
case 3d = 0x12
|
||||
.q01 = (00,0x10)=+r
|
||||
.q02 = (00,0x02)=-r
|
||||
case 3e = 0x22
|
||||
.q01 = (00,0x20)=+r
|
||||
.q02 = (00,0x02)=-r
|
||||
case 3f = 0x42
|
||||
.q01 = (00,0x40)=+r
|
||||
.q02 = (00,0x02)=-r
|
||||
|
||||
case 4aa = 0x12,0x02{31}
|
||||
.q01 = (00,0x10)=+r
|
||||
.q02 = (00,0x02)=-r
|
||||
.q03 = (01,0x02)=+r
|
||||
...
|
||||
.q32 = (30,0x02)=+r
|
||||
.q33 = (31,0x02)=+r
|
||||
case 4__ = 0x02{n(1->30)},0x12,0x02{31-n}
|
||||
.q01 = (00,0x02)=-r
|
||||
...
|
||||
.q(n+1) = (n,0x10)=+r
|
||||
.q(n+2) = (n,0x02)=-r
|
||||
...
|
||||
.q33 = (31,0x02)=+r
|
||||
case 4bf = 0x02{31},0x12
|
||||
.q01 = (00,0x02)=-r
|
||||
.q02 = (01,0x02)=-r
|
||||
...
|
||||
.q31 = (30,0x02)=-r
|
||||
.q32 = (31,0x10)=+r
|
||||
.q33 = (31,0x02)=-r
|
||||
|
||||
case 5a = 0x02,0x12,0x02,0x12,0x02
|
||||
.q01 = (00,0x02)=-r
|
||||
.q02 = (01,0x02)=-r
|
||||
.q03 = (01,0x10)=+r
|
||||
.q04 = (02,0x02)=+r
|
||||
.q05 = (03,0x02)=+r
|
||||
.q06 = (04,0x02)=+r
|
||||
|
168
bin/tests/system/rpzrecurse/tests.sh
Normal file
168
bin/tests/system/rpzrecurse/tests.sh
Normal file
@ -0,0 +1,168 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2015 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
|
||||
t=0
|
||||
|
||||
# $1 = test name (such as 1a, 1b, etc. for which named.$1.conf exists)
|
||||
run_server() {
|
||||
TESTNAME=$1
|
||||
|
||||
echo "I:stopping resolver"
|
||||
$PERL $SYSTEMTESTTOP/stop.pl . ns2
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "I:starting resolver using named.$TESTNAME.conf"
|
||||
cp -f ns2/named.$TESTNAME.conf ns2/named.conf
|
||||
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns2
|
||||
}
|
||||
|
||||
run_query() {
|
||||
TESTNAME=$1
|
||||
LINE=$2
|
||||
|
||||
NAME=`tail -n +"$LINE" ns2/$TESTNAME.queries | head -n 1`
|
||||
$DIG $DIGOPTS $NAME a @10.53.0.2 -p 5300 -b 127.0.0.1 > dig.out.${t}
|
||||
grep "status: SERVFAIL" dig.out.${t} > /dev/null 2>&1 && return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists)
|
||||
# $2 = line number in query file to test (the name to query is taken from this line)
|
||||
expect_norecurse() {
|
||||
TESTNAME=$1
|
||||
LINE=$2
|
||||
|
||||
NAME=`tail -n +"$LINE" ns2/$TESTNAME.queries | head -n 1`
|
||||
t=`expr $t + 1`
|
||||
echo "I:testing $NAME doesn't recurse (${t})"
|
||||
run_query $TESTNAME $LINE || {
|
||||
echo "I:test ${t} failed"
|
||||
status=1
|
||||
}
|
||||
}
|
||||
|
||||
# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists)
|
||||
# $2 = line number in query file to test (the name to query is taken from this line)
|
||||
expect_recurse() {
|
||||
TESTNAME=$1
|
||||
LINE=$2
|
||||
|
||||
NAME=`tail -n +"$LINE" ns2/$TESTNAME.queries | head -n 1`
|
||||
t=`expr $t + 1`
|
||||
echo "I:testing $NAME recurses (${t})"
|
||||
run_query $TESTNAME $LINE && {
|
||||
echo "I:test $t failed"
|
||||
status=1
|
||||
}
|
||||
}
|
||||
|
||||
t=`expr $t + 1`
|
||||
echo "I:testing that l1.l0 exists without RPZ (${t})"
|
||||
$DIG $DIGOPTS l1.l0 ns @10.53.0.2 -p 5300 > dig.out.${t}
|
||||
grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || {
|
||||
echo "I:test $t failed"
|
||||
status=1
|
||||
}
|
||||
|
||||
t=`expr $t + 1`
|
||||
echo "I:testing that l2.l1.l0 returns SERVFAIL without RPZ (${t})"
|
||||
$DIG $DIGOPTS l2.l1.l0 ns @10.53.0.2 -p 5300 > dig.out.${t}
|
||||
grep "status: SERVFAIL" dig.out.${t} > /dev/null 2>&1 || {
|
||||
echo "I:test $t failed"
|
||||
status=1
|
||||
}
|
||||
|
||||
# Group 1
|
||||
run_server 1a
|
||||
expect_norecurse 1a 1
|
||||
run_server 1b
|
||||
expect_norecurse 1b 1
|
||||
expect_recurse 1b 2
|
||||
run_server 1c
|
||||
expect_norecurse 1c 1
|
||||
|
||||
# Group 2
|
||||
run_server 2a
|
||||
for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
||||
do
|
||||
expect_norecurse 2a $n
|
||||
done
|
||||
expect_recurse 2a 33
|
||||
|
||||
# Group 3
|
||||
run_server 3a
|
||||
expect_recurse 3a 1
|
||||
run_server 3b
|
||||
expect_recurse 3b 1
|
||||
run_server 3c
|
||||
expect_recurse 3c 1
|
||||
run_server 3d
|
||||
expect_norecurse 3d 1
|
||||
expect_recurse 3d 2
|
||||
run_server 3e
|
||||
expect_norecurse 3e 1
|
||||
expect_recurse 3e 2
|
||||
run_server 3f
|
||||
expect_norecurse 3f 1
|
||||
expect_recurse 3f 2
|
||||
|
||||
# Group 4
|
||||
testlist="aa ap bf"
|
||||
values="1 16 32"
|
||||
# Uncomment the following to test every skip value instead of
|
||||
# only a sample of values
|
||||
#
|
||||
#testlist="aa ab ac ad ae af ag ah ai aj ak al am an ao ap \
|
||||
# aq ar as at au av aw ax ay az ba bb bc bd be bf"
|
||||
#values="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
|
||||
# 21 22 23 24 25 26 27 28 29 30 31 32"
|
||||
set -- $values
|
||||
for n in $testlist; do
|
||||
run_server 4$n
|
||||
ni=$1
|
||||
t=`expr $t + 1`
|
||||
echo "I:testing that ${ni} of 33 queries skip recursion (${t})"
|
||||
c=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \
|
||||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
||||
do
|
||||
run_query 4$n $i
|
||||
c=`expr $c + $?`
|
||||
done
|
||||
skipped=`expr 33 - $c`
|
||||
if [ $skipped != $ni ]; then
|
||||
echo "I:test $t failed (actual=$skipped, expected=$ni)"
|
||||
status=1
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
# Group 5
|
||||
run_server 5a
|
||||
expect_norecurse 5a 1
|
||||
expect_norecurse 5a 2
|
||||
expect_recurse 5a 3
|
||||
expect_recurse 5a 4
|
||||
expect_recurse 5a 5
|
||||
expect_recurse 5a 6
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
@ -9950,7 +9950,7 @@ deny-answer-aliases { "example.net"; };
|
||||
<command>DISABLED</command> actions) must be chosen.
|
||||
Triggers or the records that encode them are chosen for the
|
||||
rewriting in the following order:
|
||||
<itemizedlist>
|
||||
<orderedlist>
|
||||
<listitem>Choose the triggered record in the zone that appears
|
||||
first in the <command>response-policy</command> option.
|
||||
</listitem>
|
||||
@ -9967,7 +9967,7 @@ deny-answer-aliases { "example.net"; };
|
||||
prefer the IP or NSIP trigger that matches
|
||||
the smallest IP address.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -620,6 +620,17 @@
|
||||
<command>dig +short</command>. [RT #39291]
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
A bug in the RPZ implementation could cause some policy
|
||||
zones that did not specifically require recursion to be
|
||||
treated as if they did; consequently, setting
|
||||
<command>qname-wait-recurse no;</command> was
|
||||
sometimes ineffective. This has been corrected.
|
||||
In most configurations, behavioral changes due to this
|
||||
fix will not be noticeable. [RT #39229]
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</sect2>
|
||||
<sect2 id="end_of_life">
|
||||
|
190
lib/dns/rpz.c
190
lib/dns/rpz.c
@ -55,7 +55,7 @@
|
||||
*
|
||||
* Each leaf indicates that an IP address is listed in the IP address or the
|
||||
* name server IP address policy sub-zone (or both) of the corresponding
|
||||
* response response zone. The policy data such as a CNAME or an A record
|
||||
* response policy zone. The policy data such as a CNAME or an A record
|
||||
* is kept in the policy zone. After an IP address has been found in a radix
|
||||
* tree, the node in the policy zone's database is found by converting
|
||||
* the IP address to a domain name in a canonical form.
|
||||
@ -133,11 +133,6 @@ struct dns_rpz_cidr_node {
|
||||
dns_rpz_addr_zbits_t sum;
|
||||
};
|
||||
|
||||
/*
|
||||
* The data in a RBT node has two pairs of bits for policy zones.
|
||||
* One pair is for the corresponding name of the node such as example.com
|
||||
* and the other pair is for a wildcard child such as *.example.com.
|
||||
*/
|
||||
/*
|
||||
* A pair of arrays of bits flagging the existence of
|
||||
* QNAME and NSDNAME policy triggers.
|
||||
@ -148,6 +143,11 @@ struct dns_rpz_nm_zbits {
|
||||
dns_rpz_zbits_t ns;
|
||||
};
|
||||
|
||||
/*
|
||||
* The data in a RBT node has two pairs of bits for policy zones.
|
||||
* One pair is for the corresponding name of the node such as example.com
|
||||
* and the other pair is for a wildcard child such as *.example.com.
|
||||
*/
|
||||
typedef struct dns_rpz_nm_data dns_rpz_nm_data_t;
|
||||
struct dns_rpz_nm_data {
|
||||
dns_rpz_nm_zbits_t set;
|
||||
@ -259,11 +259,15 @@ dns_rpz_policy2str(dns_rpz_policy_t policy) {
|
||||
return (str);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the bit number of the highest set bit in 'zbit'.
|
||||
* (for example, 0x01 returns 0, 0xFF returns 7, etc.)
|
||||
*/
|
||||
static int
|
||||
zbit_to_num(dns_rpz_zbits_t zbit) {
|
||||
dns_rpz_num_t rpz_num;
|
||||
|
||||
INSIST(zbit != 0);
|
||||
REQUIRE(zbit != 0);
|
||||
rpz_num = 0;
|
||||
#if DNS_RPZ_MAX_ZONES > 32
|
||||
if ((zbit & 0xffffffff00000000L) != 0) {
|
||||
@ -376,30 +380,172 @@ set_sum_pair(dns_rpz_cidr_node_t *cnode) {
|
||||
|
||||
static void
|
||||
fix_qname_skip_recurse(dns_rpz_zones_t *rpzs) {
|
||||
dns_rpz_zbits_t zbits;
|
||||
dns_rpz_zbits_t mask;
|
||||
|
||||
/* qname_wait_recurse and qname_skip_recurse are used to
|
||||
* implement the "qname-wait-recurse" config option.
|
||||
*
|
||||
* By default, "qname-wait-recurse" is yes, so no
|
||||
* processing happens without recursion. In this case,
|
||||
* qname_wait_recurse is true, and qname_skip_recurse
|
||||
* (a bit field indicating which policy zones can be
|
||||
* processed without recursion) is set to all 0's by
|
||||
* fix_qname_skip_recurse().
|
||||
*
|
||||
* When "qname-wait-recurse" is no, qname_skip_recurse may be
|
||||
* set to a non-zero value by fix_qname_skip_recurse(). The mask
|
||||
* has to have bits set for for the policy zones for which
|
||||
* processing may continue without recursion, and bits cleared
|
||||
* for the rest.
|
||||
*
|
||||
* (1) The ARM says:
|
||||
*
|
||||
* The "qname-wait-recurse no" option overrides that default
|
||||
* behavior when recursion cannot change a non-error
|
||||
* response. The option does not affect QNAME or client-IP
|
||||
* triggers in policy zones listed after other zones
|
||||
* containing IP, NSIP and NSDNAME triggers, because those may
|
||||
* depend on the A, AAAA, and NS records that would be found
|
||||
* during recursive resolution.
|
||||
*
|
||||
* Let's consider the following:
|
||||
*
|
||||
* zbits_req = (rpzs->have.ipv4 | rpzs->have.ipv6 |
|
||||
* rpzs->have.nsdname |
|
||||
* rpzs->have.nsipv4 | rpzs->have.nsipv6);
|
||||
*
|
||||
* zbits_req now contains bits set for zones which require
|
||||
* recursion.
|
||||
*
|
||||
* But going by the description in the ARM, if the first policy
|
||||
* zone requires recursion, then all zones after that (higher
|
||||
* order bits) have to wait as well. If the Nth zone requires
|
||||
* recursion, then (N+1)th zone onwards all need to wait.
|
||||
*
|
||||
* So mapping this, examples:
|
||||
*
|
||||
* zbits_req = 0b000 mask = 0xffffffff (no zones have to wait for
|
||||
* recursion)
|
||||
* zbits_req = 0b001 mask = 0x00000000 (all zones have to wait)
|
||||
* zbits_req = 0b010 mask = 0x00000001 (the first zone doesn't have to
|
||||
* wait, second zone onwards need
|
||||
* to wait)
|
||||
* zbits_req = 0b011 mask = 0x00000000 (all zones have to wait)
|
||||
* zbits_req = 0b100 mask = 0x00000011 (the 1st and 2nd zones don't
|
||||
* have to wait, third zone
|
||||
* onwards need to wait)
|
||||
*
|
||||
* More generally, we have to count the number of trailing 0
|
||||
* bits in zbits_req and only these can be processed without
|
||||
* recursion. All the rest need to wait.
|
||||
*
|
||||
* (2) The ARM says that "qname-wait-recurse no" option
|
||||
* overrides the default behavior when recursion cannot change a
|
||||
* non-error response. So, in the order of listing of policy
|
||||
* zones, within the first policy zone where recursion may be
|
||||
* required, we should first allow CLIENT-IP and QNAME policy
|
||||
* records to be attempted without recursion.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get a mask covering all policy zones that are not subordinate to
|
||||
* other policy zones containing triggers that require that the
|
||||
* qname be resolved before they can be checked.
|
||||
*/
|
||||
if (rpzs->p.qname_wait_recurse) {
|
||||
zbits = 0;
|
||||
} else {
|
||||
zbits = (rpzs->have.ipv4 || rpzs->have.ipv6 ||
|
||||
rpzs->have.nsdname ||
|
||||
rpzs->have.nsipv4 || rpzs->have.nsipv6);
|
||||
if (zbits == 0) {
|
||||
zbits = DNS_RPZ_ALL_ZBITS;
|
||||
} else {
|
||||
zbits = DNS_RPZ_ZMASK(zbit_to_num(zbits));
|
||||
}
|
||||
}
|
||||
rpzs->have.qname_skip_recurse = zbits;
|
||||
|
||||
rpzs->have.client_ip = rpzs->have.client_ipv4 | rpzs->have.client_ipv6;
|
||||
rpzs->have.ip = rpzs->have.ipv4 | rpzs->have.ipv6;
|
||||
rpzs->have.nsip = rpzs->have.nsipv4 | rpzs->have.nsipv6;
|
||||
|
||||
if (rpzs->p.qname_wait_recurse) {
|
||||
mask = 0;
|
||||
} else {
|
||||
dns_rpz_zbits_t zbits_req;
|
||||
dns_rpz_zbits_t zbits_notreq;
|
||||
dns_rpz_zbits_t mask2;
|
||||
dns_rpz_zbits_t req_mask;
|
||||
|
||||
/*
|
||||
* Get the masks of zones with policies that
|
||||
* do/don't require recursion
|
||||
*/
|
||||
|
||||
zbits_req = (rpzs->have.ipv4 | rpzs->have.ipv6 |
|
||||
rpzs->have.nsdname |
|
||||
rpzs->have.nsipv4 | rpzs->have.nsipv6);
|
||||
zbits_notreq = (rpzs->have.client_ip | rpzs->have.qname);
|
||||
|
||||
if (zbits_req == 0) {
|
||||
mask = DNS_RPZ_ALL_ZBITS;
|
||||
goto set;
|
||||
}
|
||||
|
||||
/*
|
||||
* req_mask is a mask covering used bits in
|
||||
* zbits_req. (For instance, 0b1 => 0b1, 0b101 => 0b111,
|
||||
* 0b11010101 => 0b11111111).
|
||||
*/
|
||||
req_mask = zbits_req;
|
||||
req_mask |= req_mask >> 1;
|
||||
req_mask |= req_mask >> 2;
|
||||
req_mask |= req_mask >> 4;
|
||||
req_mask |= req_mask >> 8;
|
||||
req_mask |= req_mask >> 16;
|
||||
#if DNS_RPZ_MAX_ZONES > 32
|
||||
req_mask |= req_mask >> 32;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* There's no point in skipping recursion for a later
|
||||
* zone if it is required in a previous zone.
|
||||
*/
|
||||
if ((zbits_notreq & req_mask) == 0) {
|
||||
mask = 0;
|
||||
goto set;
|
||||
}
|
||||
|
||||
/*
|
||||
* This bit arithmetic creates a mask of zones in which
|
||||
* it is okay to skip recursion. After the first zone
|
||||
* that has to wait for recursion, all the others have
|
||||
* to wait as well, so we want to create a mask in which
|
||||
* all the trailing zeroes in zbits_req are are 1, and
|
||||
* more significant bits are 0. (For instance,
|
||||
* 0x0700 => 0x00ff, 0x0007 => 0x0000)
|
||||
*/
|
||||
mask = ~(zbits_req | -zbits_req);
|
||||
|
||||
/*
|
||||
* As mentioned in (2) above, the zone corresponding to
|
||||
* the least significant zero could have its CLIENT-IP
|
||||
* and QNAME policies checked before recursion, if it
|
||||
* has any of those policies. So if it does, we
|
||||
* can set its 0 to 1.
|
||||
*
|
||||
* Locate the least significant 0 bit in the mask (for
|
||||
* instance, 0xff => 0x100)...
|
||||
*/
|
||||
mask2 = (mask << 1) & ~mask;
|
||||
|
||||
/*
|
||||
* Also set the bit for zone 0, because if it's in
|
||||
* zbits_notreq then it's definitely okay to attempt to
|
||||
* skip recursion for zone 0...
|
||||
*/
|
||||
mask2 |= 1;
|
||||
|
||||
/* Clear any bits *not* in zbits_notreq... */
|
||||
mask2 &= zbits_notreq;
|
||||
|
||||
/* And merge the result into the skip-recursion mask */
|
||||
mask |= mask2;
|
||||
}
|
||||
|
||||
set:
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
|
||||
DNS_RPZ_DEBUG_QUIET,
|
||||
"computed RPZ qname_skip_recurse mask=0x%llx",
|
||||
(isc_uint64_t) mask);
|
||||
rpzs->have.qname_skip_recurse = mask;
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
x
Reference in New Issue
Block a user