106
106
#my @answers = ();
111
my ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
114
$packet->header->qr(1);
115
$packet->header->aa(1);
117
my @questions = $packet->question;
118
my $qname = $questions[0]->qname;
119
my $qtype = $questions[0]->qtype;
121
# get the existing signature if any, and clear the additional section
123
while (my $rr = $packet->pop("additional")) {
124
if ($rr->type eq "TSIG") {
130
foreach $r (@rules) {
131
my $pattern = $r->{pattern};
111
my ($request, $err) = new Net::DNS::Packet(\$buf, 0);
114
my @questions = $request->question;
115
my $qname = $questions[0]->qname;
116
my $qtype = $questions[0]->qtype;
117
my $qclass = $questions[0]->qclass;
118
my $id = $request->header->id;
120
my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
121
$packet->header->qr(1);
122
$packet->header->aa(1);
123
$packet->header->id($id);
125
# get the existing signature if any, and clear the additional section
127
while (my $rr = $request->pop("additional")) {
128
if ($rr->type eq "TSIG") {
134
foreach $r (@rules) {
135
my $pattern = $r->{pattern};
132
136
my($dbtype, $key_name, $key_data) = split(/ /,$pattern);
133
137
print "[handleUDP] $dbtype, $key_name, $key_data \n";
134
if ("$qname $qtype" =~ /$dbtype/) {
136
foreach $a (@{$r->{answer}}) {
137
$packet->push("answer", $a);
138
if ("$qname $qtype" =~ /$dbtype/) {
140
foreach $a (@{$r->{answer}}) {
141
$packet->push("answer", $a);
139
143
if(defined($key_name) && defined($key_data)) {
140
144
# Sign the packet
141
145
print " Signing the response with " .
142
"$key_name/$key_data\n";
143
my $tsig = Net::DNS::RR->
144
new("$key_name TSIG $key_data");
146
"$key_name/$key_data\n";
147
my $tsig = Net::DNS::RR->
148
new("$key_name TSIG $key_data");
146
# These kluges are necessary because Net::DNS
147
# doesn't know how to sign responses. We
148
# clear compnames so that the TSIG key and
149
# algorithm name won't be compressed, and
150
# add one to arcount because the signing
151
# function will attempt to decrement it,
152
# which is incorrect in a response. Finally
153
# we set request_mac to the previous digest.
154
$packet->{"compnames"} = {};
155
$packet->{"header"}{"arcount"} += 1;
156
if (defined($prev_tsig)) {
157
my $rmac = pack('n H*',
158
$prev_tsig->mac_size,
160
$tsig->{"request_mac"} =
150
# These kluges are necessary because Net::DNS
151
# doesn't know how to sign responses. We
152
# clear compnames so that the TSIG key and
153
# algorithm name won't be compressed, and
154
# add one to arcount because the signing
155
# function will attempt to decrement it,
156
# which is incorrect in a response. Finally
157
# we set request_mac to the previous digest.
158
$packet->{"compnames"} = {};
159
$packet->{"header"}{"arcount"} += 1;
160
if (defined($prev_tsig)) {
161
my $rmac = pack('n H*',
162
$prev_tsig->mac_size,
164
$tsig->{"request_mac"} =
164
168
$packet->sign_tsig($tsig);
171
return $packet->data;
175
return $packet->data;
175
179
# given a stream of data, reads a DNS-formatted name and returns its
176
180
# total length, thus making it possible to skip past it.
182
$label_len = unpack("c", $data);
183
$data = substr($data, $label_len + 1);
184
$len += $label_len + 1;
185
} while ($label_len != 0);
186
$label_len = unpack("c", $data);
187
$data = substr($data, $label_len + 1);
188
$len += $label_len + 1;
189
} while ($label_len != 0);
190
194
# given a stream of data, reads a DNS wire-format packet and returns
191
195
# its total length, making it possible to skip past it.
197
my ($header, $offset) = Net::DNS::Header->parse(\$data);
198
for (1 .. $header->qdcount) {
199
($q, $offset) = Net::DNS::Question->parse(\$data, $offset);
201
for (1 .. $header->ancount) {
202
($rr, $offset) = Net::DNS::RR->parse(\$data, $offset);
204
for (1 .. $header->nscount) {
205
($rr, $offset) = Net::DNS::RR->parse(\$data, $offset);
207
for (1 .. $header->arcount) {
208
($rr, $offset) = Net::DNS::RR->parse(\$data, $offset);
204
# decode/encode were introduced in Net::DNS 0.68
205
# parse is no longer a method and calling it here makes perl croak.
208
$decode = 1 if ($Net::DNS::VERSION >= 0.68);
211
($header, $offset) = Net::DNS::Header->decode(\$data);
213
($header, $offset) = Net::DNS::Header->parse(\$data);
216
for (1 .. $header->qdcount) {
219
Net::DNS::Question->decode(\$data, $offset);
222
Net::DNS::Question->parse(\$data, $offset);
225
for (1 .. $header->ancount) {
227
($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
229
($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
232
for (1 .. $header->nscount) {
234
($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
236
($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
239
for (1 .. $header->arcount) {
241
($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
243
($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
213
249
# sign_tcp_continuation:
222
258
# the unwanted data from the digest before calling the default sign_hmac
224
260
sub sign_tcp_continuation {
225
my ($key, $data) = @_;
227
# copy out first two bytes: size of the previous MAC
228
my $rmacsize = unpack("n", $data);
229
$data = substr($data, 2);
231
# copy out previous MAC
232
my $rmac = substr($data, 0, $rmacsize);
233
$data = substr($data, $rmacsize);
235
# try parsing out the packet information
236
my $plen = packetlen($data);
237
my $pdata = substr($data, 0, $plen);
238
$data = substr($data, $plen);
240
# remove the keyname, ttl, class, and algorithm name
241
$data = substr($data, namelen($data));
242
$data = substr($data, 6);
243
$data = substr($data, namelen($data));
245
# preserve the TSIG data
246
my $tdata = substr($data, 0, 8);
248
# prepare a new digest and sign with it
249
$data = pack("n", $rmacsize) . $rmac . $pdata . $tdata;
250
return Net::DNS::RR::TSIG::sign_hmac($key, $data);
261
my ($key, $data) = @_;
263
# copy out first two bytes: size of the previous MAC
264
my $rmacsize = unpack("n", $data);
265
$data = substr($data, 2);
267
# copy out previous MAC
268
my $rmac = substr($data, 0, $rmacsize);
269
$data = substr($data, $rmacsize);
271
# try parsing out the packet information
272
my $plen = packetlen($data);
273
my $pdata = substr($data, 0, $plen);
274
$data = substr($data, $plen);
276
# remove the keyname, ttl, class, and algorithm name
277
$data = substr($data, namelen($data));
278
$data = substr($data, 6);
279
$data = substr($data, namelen($data));
281
# preserve the TSIG data
282
my $tdata = substr($data, 0, 8);
284
# prepare a new digest and sign with it
285
$data = pack("n", $rmacsize) . $rmac . $pdata . $tdata;
286
return Net::DNS::RR::TSIG::sign_hmac($key, $data);
256
my ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
292
my ($request, $err) = new Net::DNS::Packet(\$buf, 0);
257
293
$err and die $err;
295
my @questions = $request->question;
296
my $qname = $questions[0]->qname;
297
my $qtype = $questions[0]->qtype;
298
my $qclass = $questions[0]->qclass;
299
my $id = $request->header->id;
301
my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
259
302
$packet->header->qr(1);
260
303
$packet->header->aa(1);
262
my @questions = $packet->question;
263
my $qname = $questions[0]->qname;
264
my $qtype = $questions[0]->qtype;
304
$packet->header->id($id);
266
# get the existing signature if any, and clear the additional section
269
while (my $rr = $packet->pop("additional")) {
270
if ($rr->type eq "TSIG") {
306
# get the existing signature if any, and clear the additional section
309
while (my $rr = $request->pop("additional")) {
310
if ($rr->type eq "TSIG") {
275
315
my @results = ();
276
316
my $count_these = 0;
289
329
if(defined($key_name) && defined($key_data)) {
290
330
# sign the packet
291
331
print " Signing the data with " .
292
"$key_name/$key_data\n";
294
my $tsig = Net::DNS::RR->
295
new("$key_name TSIG $key_data");
297
# These kluges are necessary because Net::DNS
298
# doesn't know how to sign responses. We
299
# clear compnames so that the TSIG key and
300
# algorithm name won't be compressed, and
301
# add one to arcount because the signing
302
# function will attempt to decrement it,
303
# which is incorrect in a response. Finally
304
# we set request_mac to the previous digest.
305
$packet->{"compnames"} = {};
306
$packet->{"header"}{"arcount"} += 1;
307
if (defined($prev_tsig)) {
308
my $rmac = pack('n H*',
309
$prev_tsig->mac_size,
311
$tsig->{"request_mac"} =
315
$tsig->sign_func($signer) if defined($signer);
332
"$key_name/$key_data\n";
334
my $tsig = Net::DNS::RR->
335
new("$key_name TSIG $key_data");
337
# These kluges are necessary because Net::DNS
338
# doesn't know how to sign responses. We
339
# clear compnames so that the TSIG key and
340
# algorithm name won't be compressed, and
341
# add one to arcount because the signing
342
# function will attempt to decrement it,
343
# which is incorrect in a response. Finally
344
# we set request_mac to the previous digest.
345
$packet->{"compnames"} = {};
346
$packet->{"header"}{"arcount"} += 1;
347
if (defined($prev_tsig)) {
348
my $rmac = pack('n H*',
349
$prev_tsig->mac_size,
351
$tsig->{"request_mac"} =
355
$tsig->sign_func($signer) if defined($signer);
316
356
$packet->sign_tsig($tsig);
317
$signer = \&sign_tcp_continuation;
357
$signer = \&sign_tcp_continuation;
320
Net::DNS::Packet->new(\($packet->data));
321
$prev_tsig = $copy->pop("additional");
360
Net::DNS::Packet->new(\($packet->data));
361
$prev_tsig = $copy->pop("additional");
324
364
push(@results,$packet->data);
325
$packet = new Net::DNS::Packet(\$buf, 0);
365
$packet = new Net::DNS::Packet($qname, $qtype, $qclass);
326
366
$packet->header->qr(1);
327
367
$packet->header->aa(1);
368
$packet->header->id($id);
330
371
print " A total of $count_these patterns matched\n";