diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:59:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:59:48 +0000 |
commit | 3b9b6d0b8e7f798023c9d109c490449d528fde80 (patch) | |
tree | 2e1c188dd7b8d7475cd163de9ae02c428343669b /contrib/scripts | |
parent | Initial commit. (diff) | |
download | bind9-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.py | 34 | ||||
-rw-r--r-- | contrib/scripts/check-secure-delegation.pl.in | 116 | ||||
-rw-r--r-- | contrib/scripts/check5011.pl | 210 | ||||
-rw-r--r-- | contrib/scripts/nanny.pl | 49 | ||||
-rw-r--r-- | contrib/scripts/zone-edit.sh.in | 152 |
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 |