1#!/usr/bin/env perl
2#
3# Copyright (C) 2015  Internet Systems Consortium, Inc. ("ISC")
4#
5# Permission to use, copy, modify, and/or distribute this software for any
6# purpose with or without fee is hereby granted, provided that the above
7# copyright notice and this permission notice appear in all copies.
8#
9# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15# PERFORMANCE OF THIS SOFTWARE.
16
17use strict;
18use warnings;
19
20my $boilerplate_header = <<'EOB';
21# common configuration
22include "named.conf.header";
23
24view "recursive" {
25    zone "." {
26        type hint;
27        file "root.hint";
28    };
29
30    # policy configuration to be tested
31    response-policy {
32EOB
33
34my $no_option = <<'EOB';
35    };
36
37    # policy zones to be tested
38EOB
39
40my $qname_wait_recurse = <<'EOB';
41    } qname-wait-recurse no;
42
43    # policy zones to be tested
44EOB
45
46my $boilerplate_end = <<'EOB';
47};
48EOB
49
50my $policy_option = $qname_wait_recurse;
51
52my $serialnum = "1";
53my $policy_zone_header = <<'EOH';
54$TTL 60
55@ IN SOA root.ns ns SERIAL 3600 1800 86400 60
56     NS ns
57ns A 127.0.0.1
58EOH
59
60sub policy_client_ip {
61    return "32.1.0.0.127.rpz-client-ip CNAME .\n";
62}
63
64sub policy_qname {
65    my $query_nbr = shift;
66    return sprintf "q%02d.l2.l1.l0 CNAME .\n", $query_nbr;
67}
68
69sub policy_ip {
70    return "32.255.255.255.255.rpz-ip CNAME .\n";
71}
72
73sub policy_nsdname {
74    return "ns.example.org.rpz-nsdname CNAME .\n";
75}
76
77sub policy_nsip {
78    return "32.255.255.255.255.rpz-ip CNAME .\n";
79}
80
81my %static_triggers = (
82    'client-ip' => \&policy_client_ip,
83    'ip'        => \&policy_ip,
84    'nsdname'   => \&policy_nsdname,
85    'nsip'      => \&policy_nsip,
86);
87
88sub mkconf {
89    my $case_id = shift;
90    my $n_queries = shift;
91
92    { # generate the query list
93        my $query_list_filename = "ns2/$case_id.queries";
94        my $query_list_fh;
95
96        open $query_list_fh, ">$query_list_filename" or die;
97
98        for( my $i = 1; $i <= $n_queries; $i++ ) {
99            print $query_list_fh sprintf "q%02d.l2.l1.l0\n", $i;
100        }
101    }
102
103    my @zones;
104
105    { # generate the conf file
106        my $conf_filename = "ns2/named.$case_id.conf";
107
108        my $conf_fh;
109
110        open $conf_fh, ">$conf_filename" or die;
111
112        print $conf_fh $boilerplate_header;
113
114        my $zone_seq = 0;
115
116        @zones = map {
117            [
118                sprintf( "$case_id.%02d.policy.local", $zone_seq++ ),
119                $_,
120            ];
121        } @_;
122
123        print $conf_fh map { qq{        zone "$_->[0]";\n} } @zones;
124
125        print $conf_fh $policy_option;
126
127        print $conf_fh map { qq{    zone "$_->[0]" { type master; file "db.$_->[0]"; };\n} } @zones;
128
129        print $conf_fh $boilerplate_end;
130    }
131
132    # generate the policy zone contents
133    foreach my $policy_zone_info( @zones ) {
134        my $policy_zone_name = $policy_zone_info->[0];
135        my $policy_zone_contents = $policy_zone_info->[1];
136
137        my $policy_zone_filename = "ns2/db.$policy_zone_name";
138        my $policy_zone_fh;
139
140        open $policy_zone_fh, ">$policy_zone_filename" or die;
141
142        my $header = $policy_zone_header;
143        $header =~ s/SERIAL/$serialnum/;
144        print $policy_zone_fh $header;
145
146        foreach my $trigger( @$policy_zone_contents ) {
147            if( exists $static_triggers{$trigger} ) {
148                # matches a trigger type with a static value
149                print $policy_zone_fh $static_triggers{$trigger}->();
150            }
151            else {
152                # a qname trigger, where what was specified is the query number it should match
153                print $policy_zone_fh policy_qname( $trigger );
154            }
155        }
156    }
157}
158
159mkconf(
160    '1a',
161    1,
162    [ 'client-ip' ],
163);
164
165mkconf(
166    '1b',
167    2,
168    [ 1 ],
169);
170
171mkconf(
172    '1c',
173    1,
174    [ 'client-ip', 2 ],
175);
176
177mkconf(
178    '2a',
179    33,
180    map { [ $_ ]; }  1 .. 32
181);
182
183mkconf(
184    '3a',
185    1,
186    [ 'ip' ],
187);
188
189mkconf(
190    '3b',
191    1,
192    [ 'nsdname' ],
193);
194
195mkconf(
196    '3c',
197    1,
198    [ 'nsip' ],
199);
200
201mkconf(
202    '3d',
203    2,
204    [ 'ip', 1 ]
205);
206
207mkconf(
208    '3e',
209    2,
210    [ 'nsdname', 1 ]
211);
212
213mkconf(
214    '3f',
215    2,
216    [ 'nsip', 1 ]
217);
218
219{
220    my $seq_code = 'aa';
221    my $seq_nbr = 0;
222
223    while( $seq_nbr < 32 ) {
224
225        mkconf(
226            "4$seq_code",
227            33,
228            ( map { [ $_ ]; } 1 .. $seq_nbr ),
229            [ 'ip', $seq_nbr + 2 ],
230            ( map { [ $_ + 2 ]; } ($seq_nbr + 1) .. 31 ),
231        );
232
233        $seq_code++;
234        $seq_nbr++;
235    }
236}
237
238mkconf(
239    '5a',
240    6,
241    [ 1 ],
242    [ 2, 'ip' ],
243    [ 4 ],
244    [ 5, 'ip' ],
245    [ 6 ],
246);
247
248$policy_option = $no_option;
249
250mkconf(
251    '6a',
252    0,
253    [ ],
254);
255
256$serialnum = "2";
257mkconf(
258    '6b',
259    0,
260    [ 'nsdname' ],
261);
262
263$serialnum = "3";
264mkconf(
265    '6c',
266    0,
267    [ ],
268);
269
270__END__
271
2720x01 - has client-ip
273    32.1.0.0.127.rpz-client-ip CNAME .
2740x02 - has qname
275    qX.l2.l1.l0 CNAME .
2760x10 - has ip
277    32.255.255.255.255.rpz-ip CNAME .
2780x20 - has nsdname
279    ns.example.org.rpz-nsdname CNAME .
2800x40 - has nsip
281    32.255.255.255.255.rpz-nsip CNAME .
282
283$case.$seq.policy.local
284
285case 1a = 0x01
286    .q01 = (00,0x01)=-r
287case 1b = 0x02
288    .q01 = (00,0x02)=-r
289    .q02 = (--,----)=+r
290case 1c = 0x03
291    .q01 = (00,0x01)=-r
292
293case 2a = 0x03{32}
294    .q01 = (00,0x02)=-r
295    .q02 = (01,0x02)=-r
296     ...
297    .q31 = (30,0x02)=-r
298    .q32 = (31,0x02)=-r
299    .q33 = (--,----)=+r
300
301case 3a = 0x10
302    .q01 = (00,0x10)=+r
303case 3b = 0x20
304    .q01 = (00,0x20)=+r
305case 3c = 0x40
306    .q01 = (00,0x40)=+r
307case 3d = 0x12
308    .q01 = (00,0x10)=+r
309    .q02 = (00,0x02)=-r
310case 3e = 0x22
311    .q01 = (00,0x20)=+r
312    .q02 = (00,0x02)=-r
313case 3f = 0x42
314    .q01 = (00,0x40)=+r
315    .q02 = (00,0x02)=-r
316
317case 4aa = 0x12,0x02{31}
318    .q01 = (00,0x10)=+r
319    .q02 = (00,0x02)=-r
320    .q03 = (01,0x02)=+r
321     ...
322    .q32 = (30,0x02)=+r
323    .q33 = (31,0x02)=+r
324case 4__ = 0x02{n(1->30)},0x12,0x02{31-n}
325    .q01 = (00,0x02)=-r
326     ...
327    .q(n+1) = (n,0x10)=+r
328    .q(n+2) = (n,0x02)=-r
329     ...
330    .q33 = (31,0x02)=+r
331case 4bf = 0x02{31},0x12
332    .q01 = (00,0x02)=-r
333    .q02 = (01,0x02)=-r
334     ...
335    .q31 = (30,0x02)=-r
336    .q32 = (31,0x10)=+r
337    .q33 = (31,0x02)=-r
338
339case 5a = 0x02,0x12,0x02,0x12,0x02
340    .q01 = (00,0x02)=-r
341    .q02 = (01,0x02)=-r
342    .q03 = (01,0x10)=+r
343    .q04 = (02,0x02)=+r
344    .q05 = (03,0x02)=+r
345    .q06 = (04,0x02)=+r
346
347