summaryrefslogtreecommitdiffstats
path: root/contrib/scripts
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:59:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:59:48 +0000
commit3b9b6d0b8e7f798023c9d109c490449d528fde80 (patch)
tree2e1c188dd7b8d7475cd163de9ae02c428343669b /contrib/scripts
parentInitial commit. (diff)
downloadbind9-3b9b6d0b8e7f798023c9d109c490449d528fde80.tar.xz
bind9-3b9b6d0b8e7f798023c9d109c490449d528fde80.zip
Adding upstream version 1:9.18.19.upstream/1%9.18.19upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'contrib/scripts')
-rw-r--r--contrib/scripts/catzhash.py34
-rw-r--r--contrib/scripts/check-secure-delegation.pl.in116
-rw-r--r--contrib/scripts/check5011.pl210
-rw-r--r--contrib/scripts/nanny.pl49
-rw-r--r--contrib/scripts/zone-edit.sh.in152
5 files changed, 561 insertions, 0 deletions
diff --git a/contrib/scripts/catzhash.py b/contrib/scripts/catzhash.py
new file mode 100644
index 0000000..fa0b69b
--- /dev/null
+++ b/contrib/scripts/catzhash.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# catzhash.py: generate the SHA-1 hash of a domain name in wire format.
+#
+# This can be used to determine the label to use in a catalog zone to
+# represent the specified zone. For example, the zone
+# "domain.example" can be represented in a catalog zone called
+# "catalog.example" by adding the following record:
+#
+# 5960775ba382e7a4e09263fc06e7c00569b6a05c.zones.catalog.example. \
+# IN PTR domain.example.
+#
+# The label "5960775ba382e7a4e09263fc06e7c00569b6a05c" is the output of
+# this script when run with the argument "domain.example".
+
+import sys
+import hashlib
+import dns.name
+
+if len(sys.argv) < 2:
+ print("Usage: %s name" % sys.argv[0])
+
+NAME = dns.name.from_text(sys.argv[1]).to_wire()
+print(hashlib.sha1(NAME).hexdigest())
diff --git a/contrib/scripts/check-secure-delegation.pl.in b/contrib/scripts/check-secure-delegation.pl.in
new file mode 100644
index 0000000..0f38c08
--- /dev/null
+++ b/contrib/scripts/check-secure-delegation.pl.in
@@ -0,0 +1,116 @@
+#!@PERL@
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use warnings;
+use FileHandle;
+use IPC::Open2;
+use POSIX qw/strftime/;
+
+#
+# We only compare keyid / DNSSEC algorithm pairs. If this succeeds then
+# the crypto will likely succeed. If it fails then the crypto will definitely
+# fail.
+#
+$prefix = "@prefix@";
+$dig = "$prefix/bin/dig +cd +dnssec +noall +answer";
+$dsfromkey = "$prefix/sbin/dnssec-dsfromkey -1 -A -f /dev/stdin";
+
+# Get "now" in a RRSIG datestamp format.
+$now = strftime "%Y%m%d%H%M%S", gmtime;
+
+foreach $zone (@ARGV) {
+ my %algorithms = ();
+ my %dnskeygood = ();
+ my %dnskeyalg = ();
+ my %dnskey = ();
+ my %dsgood = ();
+ my %ds = ();
+
+ # Read the DS records and extract the key id, algorithm pairs
+ open(DS, "$dig -t DS -q $zone|") || die("dig DS failed");
+ while(<DS>) {
+ @words = split;
+ if ($words[3] eq "RRSIG" && $words[4] eq "DS") {
+ next if ($words[8] >= $now && $words[9] <= $now);
+ print "BAD SIG DATES: $_";
+ }
+ next if ($words[3] ne "DS");
+ $ds{"$words[4] $words[5]"} = 1;
+ $algorithms{"$words[5]"} = 1;
+ }
+ close(DS);
+
+ # Read the RRSIG(DNSKEY) records and extract the key id,
+ # algorithm pairs. Set good if we have a match against the DS
+ # records. DNSKEY records should be before the RRSIG records.
+ open(DNSKEY, "$dig -t DNSKEY -q $zone|") || die("dig DNSKEY failed");
+ while (<DNSKEY>) {
+ @words = split;
+ if ($words[3] eq "DNSKEY") {
+ $dnskeyalg{"$words[6]"} = 1;
+ next if (! -e "/dev/stdin");
+ # get the key id ($dswords[3]).
+ $pid = open2(*Reader, *Writer, "$dsfromkey $zone");
+ die("dsfromkey failed") if ($pid == -1);
+ print Writer "$_";
+ close(Writer);
+ $line = <Reader>;
+ close(Reader);
+ @dswords = split /\s/, $line;
+ $dnskey{"$dswords[3] $dswords[4]"} = 1;
+ next;
+ }
+ next if ($words[3] ne "RRSIG" || $words[4] ne "DNSKEY");
+ if ($words[8] >= $now && $words[9] <= $now) {
+ # If we don't have /dev/stdin then just check for the
+ # RRSIG otherwise check for both the DNSKEY and
+ # RRSIG.
+ $dsgood{"$words[5]"} = 1
+ if (! -e "/dev/stdin" &&
+ exists($ds{"$words[10] $words[5]"}));
+ $dsgood{"$words[5]"} = 1
+ if (exists($ds{"$words[10] $words[5]"}) &&
+ exists($dnskey{"$words[10] $words[5]"}));
+ $dnskeygood{"$words[5]"} = 1
+ if (! -e "/dev/stdin");
+ $dnskeygood{"$words[5]"} = 1
+ if (exists($dnskey{"$words[10] $words[5]"}));
+ } else {
+ $dnskeygood{"$words[5]"} = 1;
+ print "BAD SIG DATES: $_";
+ }
+ }
+ close(DNSKEY);
+
+ # Do we have signatures for all DNSKEY algorithms?
+ foreach $alg ( keys %dnskeyalg ) {
+ print "Missing $zone DNSKEY RRSIG for algorithm $alg\n"
+ if (!exists($dnskeygood{$alg}));
+ }
+
+ # Do we have a matching self signed DNSKEY for all DNSSEC algorithms
+ # in the DS records.
+ $count = 0;
+ foreach $alg ( keys %algorithms ) {
+ if (exists($dsgood{$alg})) {
+ print "$zone algorithm $alg good " .
+ "(found DS / self signed DNSKEY pair)\n";
+ } else {
+ print "$zone algorithm $alg bad " .
+ "(no DS / self signed DNSKEY pair found)\n";
+ }
+ $count++;
+ }
+ print "$zone has no secure delegation records\n"
+ if (! $count);
+}
diff --git a/contrib/scripts/check5011.pl b/contrib/scripts/check5011.pl
new file mode 100644
index 0000000..814295a
--- /dev/null
+++ b/contrib/scripts/check5011.pl
@@ -0,0 +1,210 @@
+#!/usr/bin/perl
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use warnings;
+use strict;
+
+use POSIX qw(strftime);
+my $now = strftime "%Y%m%d%H%M%S", gmtime;
+
+sub ext8601 ($) {
+ my $d = shift;
+ $d =~ s{(....)(..)(..)(..)(..)(..)}
+ {$1-$2-$3.$4:$5:$6+0000};
+ return $d;
+}
+
+sub getkey ($$) {
+ my $h = shift;
+ my $k = shift;
+ m{\s+(\d+)\s+(\d+)\s+(\d+)\s+[(]\s*$};
+ $k->{flags} = $1;
+ $k->{protocol} = $2;
+ $k->{algorithm} = $3;
+ my $data = "(";
+ while (<$h>) {
+ s{^\s+}{};
+ s{\s+$}{};
+ last if m{^[)]};
+ $data .= $_;
+ }
+ m{ alg = (\S+)\s*; key id = (\d+)};
+ $k->{alg} = $1;
+ $k->{id} = $2;
+ $k->{data} = $data;
+ return $k;
+}
+
+sub fmtkey ($) {
+ my $k = shift;
+ return sprintf "%16s tag %s", $k->{name}, $k->{id};
+}
+
+sub printstatus ($) {
+ my $a = shift;
+ if ($a->{removehd} ne "19700101000000") {
+ printf " untrusted and to be removed at %s\n", ext8601 $a->{removehd};
+ } elsif ($a->{addhd} le $now) {
+ printf " trusted\n";
+ } else {
+ printf " waiting for %s\n", ext8601 $a->{addhd};
+ }
+}
+
+sub digkeys ($) {
+ my $name = shift;
+ my $keys;
+ open my $d, "-|", qw{dig +multiline DNSKEY}, $name;
+ while (<$d>) {
+ next unless m{^([a-z0-9.-]*)\s+\d+\s+IN\s+DNSKEY\s+};
+ next unless $name eq $1;
+ push @$keys, getkey $d, { name => $name };
+ }
+ return $keys;
+}
+
+my $anchor;
+my $owner = ".";
+while (<>) {
+ next unless m{^([a-z0-9.-]*)\s+KEYDATA\s+(\d+)\s+(\d+)\s+(\d+)\s+};
+ my $k = getkey *ARGV, {
+ name => $1,
+ refresh => $2,
+ addhd => $3,
+ removehd => $4,
+ };
+ if ($k->{name} eq "") {
+ $k->{name} = $owner;
+ } else {
+ $owner = $k->{name};
+ }
+ $k->{name} =~ s{[.]*$}{.};
+ push @{$anchor->{$k->{name}}}, $k;
+}
+
+for my $name (keys %$anchor) {
+ my $keys = digkeys $name;
+ my $anchors = $anchor->{$name};
+ for my $k (@$keys) {
+ if ($k->{flags} & 1) {
+ printf "%s %s", fmtkey $k, $k->{alg};
+ } else {
+ # ZSK - skipping
+ next;
+ }
+ if ($k->{flags} & 512) {
+ print " revoked;";
+ }
+ my $a;
+ for my $t (@$anchors) {
+ if ($t->{data} eq $k->{data} and
+ $t->{protocol} eq $k->{protocol} and
+ $t->{algorithm} eq $k->{algorithm}) {
+ $t->{matched} = 1;
+ $a = $t;
+ last;
+ }
+ }
+ if (not defined $a) {
+ print " no trust anchor\n";
+ next;
+ }
+ printstatus $a;
+ }
+ for my $a (@$anchors) {
+ next if $a->{matched};
+ printf "%s %s missing;", fmtkey $a, $a->{alg};
+ printstatus $a;
+ }
+}
+
+exit;
+
+__END__
+
+=head1 NAME
+
+check5011 - summarize DNSSEC trust anchor status
+
+=head1 SYNOPSIS
+
+check5011 <I<managed-keys.bind>>
+
+=head1 DESCRIPTION
+
+The BIND managed-keys file contains DNSSEC trust anchors
+that can be automatically updated according to RFC 5011. The
+B<check5011> program reads this file and prints a summary of the
+status of the trust anchors. It fetches the corresponding
+DNSKEY records using B<dig> and compares them to the trust anchors.
+
+Each key is printed on a line with its name, its tag, and its
+algorithm, followed by a summary of its status.
+
+=over
+
+=item C<trusted>
+
+The key is currently trusted.
+
+=item C<waiting for ...>
+
+The key is new, and B<named> is waiting for the "add hold-down" period
+to pass before the key will be trusted.
+
+=item C<untrusted and to be removed at ...>
+
+The key was revoked and will be removed at the stated time.
+
+=item C<no trust anchor>
+
+The key is present in the DNS but not in the managed-keys file.
+
+=item C<revoked>
+
+The key has its revoked flag set. This is printed before the key's
+trust anchor status which should normally be C<untrusted...> if
+B<named> has observed the revocation.
+
+=item C<missing>
+
+There is no DNSKEY record for this trust anchor. This is printed
+before the key's trust anchor status.
+
+=back
+
+By default the managed keys are stored in a file called
+F<managed-keys.bind> in B<named>'s working directory. This location
+can be changed with B<named>'s B<managed-keys-directory> option. If
+you are using views the file may be named with the SHA256 hash of a
+view name with a F<.mkeys> extension added.
+
+=head1 AUTHOR
+
+=over
+
+=item Written by Tony Finch <fanf2@cam.ac.uk> <dot@dotat.at>
+
+=item at the University of Cambridge Computing Service.
+
+=item You may do anything with this. It has no warranty.
+
+=item L<http://creativecommons.org/publicdomain/zero/1.0/>
+
+=back
+
+=head1 SEE ALSO
+
+dig(1), named(8)
+
+=cut
diff --git a/contrib/scripts/nanny.pl b/contrib/scripts/nanny.pl
new file mode 100644
index 0000000..02e7ed1
--- /dev/null
+++ b/contrib/scripts/nanny.pl
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# A simple nanny to make sure named stays running.
+
+$pid_file_location = '/var/run/named.pid';
+$nameserver_location = 'localhost';
+$dig_program = 'dig';
+$named_program = 'named';
+
+fork() && exit();
+
+for (;;) {
+ $pid = 0;
+ open(FILE, $pid_file_location) || goto restart;
+ $pid = <FILE>;
+ close(FILE);
+ chomp($pid);
+
+ $res = kill 0, $pid;
+
+ goto restart if ($res == 0);
+
+ $dig_command =
+ "$dig_program +short . \@$nameserver_location > /dev/null";
+ $return = system($dig_command);
+ goto restart if ($return == 9);
+
+ sleep 30;
+ next;
+
+ restart:
+ if ($pid != 0) {
+ kill 15, $pid;
+ sleep 30;
+ }
+ system ($named_program);
+ sleep 120;
+}
diff --git a/contrib/scripts/zone-edit.sh.in b/contrib/scripts/zone-edit.sh.in
new file mode 100644
index 0000000..2596ef8
--- /dev/null
+++ b/contrib/scripts/zone-edit.sh.in
@@ -0,0 +1,152 @@
+#!/bin/sh
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+dir=/tmp/zone-edit.$$
+mkdir ${dir} || exit 1
+trap "/bin/rm -rf ${dir}" 0
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+
+dig=${bindir}/dig
+checkzone=${bindir}/named-checkzone
+nsupdate=${bindir}/nsupdate
+
+case $# in
+0) echo "Usage: zone-edit <zone> [dig options] [ -- nsupdate options ]"; exit 0 ;;
+esac
+
+# What kind of echo are we using?
+try=`echo -n ""`
+if test "X$try" = "X-n "
+then
+ echo_arg=""
+ bsc="\\c"
+else
+ echo_arg="-n"
+ bsc=""
+fi
+
+zone="${1}"
+shift
+digopts=
+while test $# -ne 0
+do
+ case "${1}" in
+ --)
+ shift
+ break
+ ;;
+ *)
+ digopts="$digopts $1"
+ shift
+ ;;
+ esac
+done
+
+${dig} axfr "$zone" $digopts |
+awk '$4 == "RRSIG" || $4 == "NSEC" || $4 == "NSEC3" || $4 == "NSEC3PARAM" { next; } { print; }' > ${dir}/old
+
+if test -s ${dir}/old
+then
+ ${checkzone} -q -D "$zone" ${dir}/old > ${dir}/ooo
+fi
+
+if test -s ${dir}/ooo
+then
+ cp ${dir}/ooo ${dir}/new
+ while :
+ do
+ if ${VISUAL:-${EDITOR:-/bin/ed}} ${dir}/new
+ then
+ if ${checkzone} -q -D "$zone" ${dir}/new > ${dir}/nnn
+ then
+ sort ${dir}/ooo > ${dir}/s1
+ sort ${dir}/nnn > ${dir}/s2
+ comm -23 ${dir}/s1 ${dir}/s2 |
+ sed 's/^/update delete /' > ${dir}/ccc
+ comm -13 ${dir}/s1 ${dir}/s2 |
+ sed 's/^/update add /' >> ${dir}/ccc
+ if test -s ${dir}/ccc
+ then
+ cat ${dir}/ccc | more
+ while :
+ do
+ echo ${echo_arg} "Update (u), Abort (a), Redo (r), Modify (m), Display (d) : $bsc"
+ read ans
+ case "$ans" in
+ u)
+ (
+ echo zone "$zone"
+ cat ${dir}/ccc
+ echo send
+ ) | ${nsupdate} "$@"
+ break 2
+ ;;
+ a)
+ break 2
+ ;;
+ d)
+ cat ${dir}/ccc | more
+ ;;
+ r)
+ cp ${dir}/ooo ${dir}/new
+ break
+ ;;
+ m)
+ break
+ ;;
+ esac
+ done
+ else
+ while :
+ do
+ echo ${echo_arg} "Abort (a), Redo (r), Modify (m) : $bsc"
+ read ans
+ case "$ans" in
+ a)
+ break 2
+ ;;
+ r)
+ cp ${dir}/ooo ${dir}/new
+ break
+ ;;
+ m)
+ break
+ ;;
+ esac
+ done
+ fi
+ else
+ while :
+ do
+ echo ${echo_arg} "Abort (a), Redo (r), Modify (m) : $bsc"
+ read ans
+ case "$ans" in
+ a)
+ break 2
+ ;;
+ r)
+ cp ${dir}/ooo ${dir}/new
+ break
+ ;;
+ m)
+ break
+ ;;
+ esac
+ done
+ fi
+ fi
+ done
+fi