xref: /netbsd-src/external/mpl/bind/dist/contrib/scripts/check-secure-delegation.pl.in (revision 8aaca124c0ad52af9550477f296b63debc7b4c98)
1#!@PERL@
2#
3# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
4#
5# SPDX-License-Identifier: MPL-2.0
6#
7# This Source Code Form is subject to the terms of the Mozilla Public
8# License, v. 2.0. If a copy of the MPL was not distributed with this
9# file, you can obtain one at https://mozilla.org/MPL/2.0/.
10#
11# See the COPYRIGHT file distributed with this work for additional
12# information regarding copyright ownership.
13
14use warnings;
15use FileHandle;
16use IPC::Open2;
17use POSIX qw/strftime/;
18
19#
20# We only compare keyid / DNSSEC algorithm pairs.  If this succeeds then
21# the crypto will likely succeed.  If it fails then the crypto will definitely
22# fail.
23#
24$prefix = "@prefix@";
25$dig = "$prefix/bin/dig +cd +dnssec +noall +answer";
26$dsfromkey = "$prefix/sbin/dnssec-dsfromkey -1 -A -f /dev/stdin";
27
28# Get "now" in a RRSIG datestamp format.
29$now = strftime "%Y%m%d%H%M%S", gmtime;
30
31foreach $zone (@ARGV) {
32	my %algorithms = ();
33	my %dnskeygood = ();
34	my %dnskeyalg = ();
35	my %dnskey = ();
36	my %dsgood = ();
37	my %ds = ();
38
39	# Read the DS records and extract the key id, algorithm pairs
40	open(DS, "$dig -t DS -q $zone|") || die("dig DS failed");
41	while(<DS>) {
42		@words = split;
43		if ($words[3] eq "RRSIG" && $words[4] eq "DS") {
44			next if ($words[8] >= $now && $words[9] <= $now);
45			print "BAD SIG DATES: $_";
46		}
47		next if ($words[3] ne "DS");
48		$ds{"$words[4] $words[5]"} = 1;
49		$algorithms{"$words[5]"} = 1;
50	}
51	close(DS);
52
53	# Read the RRSIG(DNSKEY) records and extract the key id,
54	# algorithm pairs.  Set good if we have a match against the DS
55	# records.  DNSKEY records should be before the RRSIG records.
56	open(DNSKEY, "$dig -t DNSKEY -q $zone|") || die("dig DNSKEY failed");
57	while (<DNSKEY>) {
58		@words = split;
59		if ($words[3] eq "DNSKEY") {
60			$dnskeyalg{"$words[6]"} = 1;
61			next if (! -e "/dev/stdin");
62			# get the key id ($dswords[3]).
63			$pid = open2(*Reader, *Writer, "$dsfromkey $zone");
64			die("dsfromkey failed") if ($pid == -1);
65			print Writer "$_";
66			close(Writer);
67			$line = <Reader>;
68			close(Reader);
69			@dswords = split /\s/, $line;
70			$dnskey{"$dswords[3] $dswords[4]"} = 1;
71			next;
72		}
73		next if ($words[3] ne "RRSIG" || $words[4] ne "DNSKEY");
74		if ($words[8] >= $now && $words[9] <= $now) {
75			# If we don't have /dev/stdin then just check for the
76			# RRSIG otherwise check for both the DNSKEY and
77			# RRSIG.
78			$dsgood{"$words[5]"} = 1
79				if (! -e "/dev/stdin" &&
80				    exists($ds{"$words[10] $words[5]"}));
81			$dsgood{"$words[5]"} = 1
82				if (exists($ds{"$words[10] $words[5]"}) &&
83				    exists($dnskey{"$words[10] $words[5]"}));
84			$dnskeygood{"$words[5]"} = 1
85				if (! -e "/dev/stdin");
86			$dnskeygood{"$words[5]"} = 1
87				if (exists($dnskey{"$words[10] $words[5]"}));
88		} else {
89			$dnskeygood{"$words[5]"} = 1;
90			print "BAD SIG DATES: $_";
91		}
92	}
93	close(DNSKEY);
94
95	# Do we have signatures for all DNSKEY algorithms?
96	foreach $alg ( keys %dnskeyalg ) {
97		print "Missing $zone DNSKEY RRSIG for algorithm $alg\n"
98			if (!exists($dnskeygood{$alg}));
99	}
100
101	# Do we have a matching self signed DNSKEY for all DNSSEC algorithms
102	# in the DS records.
103	$count = 0;
104	foreach $alg ( keys %algorithms ) {
105		if (exists($dsgood{$alg})) {
106			print "$zone algorithm $alg good " .
107			      "(found DS / self signed DNSKEY pair)\n";
108		} else {
109			print "$zone algorithm $alg bad " .
110			      "(no DS / self signed DNSKEY pair found)\n";
111		}
112		$count++;
113	}
114	print "$zone has no secure delegation records\n"
115		if (! $count);
116}
117