check5011.pl revision 1.1.1.1
126168Sfsmp#!/usr/bin/perl
226168Sfsmp
335393Steggeuse warnings;
426168Sfsmpuse strict;
526168Sfsmp
626168Sfsmpuse POSIX qw(strftime);
728043Sfsmpmy $now = strftime "%Y%m%d%H%M%S", gmtime;
827728Sfsmp
928043Sfsmpsub ext8601 ($) {
1027517Sfsmp	my $d = shift;
1127007Sfsmp	$d =~ s{(....)(..)(..)(..)(..)(..)}
1228043Sfsmp	       {$1-$2-$3.$4:$5:$6+0000};
1328442Sfsmp	return $d;
1428442Sfsmp}
1528442Sfsmp
1628442Sfsmpsub getkey ($$) {
1728442Sfsmp	my $h = shift;
1828442Sfsmp	my $k = shift;
1928442Sfsmp	m{\s+(\d+)\s+(\d+)\s+(\d+)\s+[(]\s*$};
2028442Sfsmp	$k->{flags}     = $1;
2128442Sfsmp	$k->{protocol}  = $2;
2228442Sfsmp	$k->{algorithm} = $3;
2328442Sfsmp	my $data = "(";
2428442Sfsmp	while (<$h>) {
2528442Sfsmp		s{^\s+}{};
2628442Sfsmp		s{\s+$}{};
2728442Sfsmp		last if m{^[)]};
2828442Sfsmp		$data .= $_;
2928487Sfsmp	}
3028442Sfsmp	m{ alg = (\S+)\s*; key id = (\d+)};
3128442Sfsmp	$k->{alg}  = $1;
3228442Sfsmp	$k->{id}   = $2;
3328442Sfsmp	$k->{data} = $data;
3428442Sfsmp	return $k;
3528442Sfsmp}
3628442Sfsmp
3726168Sfsmpsub fmtkey ($) {
3826168Sfsmp	my $k = shift;
3926168Sfsmp	return sprintf "%16s tag %s", $k->{name}, $k->{id};
4026168Sfsmp}
4126168Sfsmp
4226168Sfsmpsub printstatus ($) {
4328442Sfsmp	my $a = shift;
4426168Sfsmp	if ($a->{removehd} ne "19700101000000") {
4528487Sfsmp		printf " untrusted and to be removed at %s\n", ext8601 $a->{removehd};
4626168Sfsmp	} elsif ($a->{addhd} le $now) {
4727696Sfsmp		printf " trusted\n";
4828487Sfsmp	} else {
4927696Sfsmp		printf " waiting for %s\n", ext8601 $a->{addhd};
5027728Sfsmp	}
5127728Sfsmp}
5226168Sfsmp
5326168Sfsmpsub digkeys ($) {
5426168Sfsmp	my $name = shift;
5526168Sfsmp	my $keys;
5626168Sfsmp	open my $d, "-|", qw{dig +multiline DNSKEY}, $name;
5726168Sfsmp	while (<$d>) {
5826168Sfsmp		next unless m{^([a-z0-9.-]*)\s+\d+\s+IN\s+DNSKEY\s+};
5926168Sfsmp		next unless $name eq $1;
6026168Sfsmp		push @$keys, getkey $d, { name => $name };
6126168Sfsmp	}
6226168Sfsmp	return $keys;
6326168Sfsmp}
6426168Sfsmp
6528921Sfsmpmy $anchor;
6628442Sfsmpmy $owner = ".";
6726168Sfsmpwhile (<>) {
6828921Sfsmp	next unless m{^([a-z0-9.-]*)\s+KEYDATA\s+(\d+)\s+(\d+)\s+(\d+)\s+};
6928442Sfsmp	my $k = getkey *ARGV, {
7027406Sfsmp		name     => $1,
7128442Sfsmp		refresh  => $2,
7228442Sfsmp		addhd    => $3,
7328442Sfsmp		removehd => $4,
7428442Sfsmp	};
7528442Sfsmp	if ($k->{name} eq "") {
7628442Sfsmp		$k->{name} = $owner;
7728442Sfsmp	} else {
7828442Sfsmp		$owner = $k->{name};
7928442Sfsmp	}
8028442Sfsmp	$k->{name} =~ s{[.]*$}{.};
8128442Sfsmp	push @{$anchor->{$k->{name}}}, $k;
8228442Sfsmp}
8328442Sfsmp
8428641Sfsmpfor my $name (keys %$anchor) {
8528442Sfsmp	my $keys = digkeys $name;
8628442Sfsmp	my $anchors = $anchor->{$name};
8728442Sfsmp	for my $k (@$keys) {
8828442Sfsmp		if ($k->{flags} & 1) {
8928442Sfsmp			printf "%s %s", fmtkey $k, $k->{alg};
9028442Sfsmp		} else {
9128442Sfsmp			# ZSK - skipping
9228442Sfsmp			next;
9328442Sfsmp		}
9428442Sfsmp		if ($k->{flags} & 512) {
9528641Sfsmp			print " revoked;";
9628641Sfsmp		}
9728442Sfsmp		my $a;
9828442Sfsmp		for my $t (@$anchors) {
9928442Sfsmp			if ($t->{data} eq $k->{data} and
10028442Sfsmp			    $t->{protocol} eq $k->{protocol} and
10128442Sfsmp			    $t->{algorithm} eq $k->{algorithm}) {
10228641Sfsmp				$t->{matched} = 1;
10328442Sfsmp				$a = $t;
10428641Sfsmp				last;
10526168Sfsmp			}
10626168Sfsmp		}
10728641Sfsmp		if (not defined $a) {
10826168Sfsmp			print " no trust anchor\n";
10928641Sfsmp			next;
11026168Sfsmp		}
11128641Sfsmp		printstatus $a;
11226168Sfsmp	}
11326168Sfsmp	for my $a (@$anchors) {
11426168Sfsmp		next if $a->{matched};
11528442Sfsmp		printf "%s %s missing;", fmtkey $a, $a->{alg};
11626168Sfsmp		printstatus $a;
11726168Sfsmp	}
11826168Sfsmp}
11926168Sfsmp
12026168Sfsmpexit;
12126168Sfsmp
12226168Sfsmp__END__
12326168Sfsmp
12426168Sfsmp=head1 NAME
12528641Sfsmp
12626168Sfsmpcheck5011 - summarize DNSSEC trust anchor status
12728641Sfsmp
12826168Sfsmp=head1 SYNOPSIS
12928641Sfsmp
13028641Sfsmpcheck5011 <I<managed-keys.bind>>
13126168Sfsmp
13226168Sfsmp=head1 DESCRIPTION
13326168Sfsmp
13426168SfsmpThe BIND managed-keys file contains DNSSEC trust anchors
13526168Sfsmpthat can be automatically updated according to RFC 5011. The
13628641SfsmpB<check5011> program reads this file and prints a summary of the
13726168Sfsmpstatus of the trust anchors. It fetches the corresponding
13826168SfsmpDNSKEY records using B<dig> and compares them to the trust anchors.
13926168Sfsmp
14028641SfsmpEach key is printed on a line with its name, its tag, and its
14128641Sfsmpalgorithm, followed by a summary of its status.
14228641Sfsmp
14328641Sfsmp=over
14428641Sfsmp
14526168Sfsmp=item C<trusted>
14628641Sfsmp
14726168SfsmpThe key is currently trusted.
14826168Sfsmp
14926168Sfsmp=item C<waiting for ...>
15028442Sfsmp
15128442SfsmpThe key is new, and B<named> is waiting for the "add hold-down" period
15228442Sfsmpto pass before the key will be trusted.
15328487Sfsmp
15428487Sfsmp=item C<untrusted and to be removed at ...>
15528487Sfsmp
15628487SfsmpThe key was revoked and will be removed at the stated time.
15728487Sfsmp
15828487Sfsmp=item C<no trust anchor>
15928487Sfsmp
16028487SfsmpThe key is present in the DNS but not in the managed-keys file.
16128487Sfsmp
16228487Sfsmp=item C<revoked>
16328487Sfsmp
16428487SfsmpThe key has its revoked flag set. This is printed before the key's
16528487Sfsmptrust anchor status which should normally be C<untrusted...> if
16628487SfsmpB<named> has observed the revocation.
16728487Sfsmp
16828487Sfsmp=item C<missing>
16934021Stegge
17034021SteggeThere is no DNSKEY record for this trust anchor. This is printed
17134021Steggebefore the key's trust anchor status.
17234021Stegge
17334021Stegge=back
17434021Stegge
17534021SteggeBy default the managed keys are stored in a file called
17634021SteggeF<managed-keys.bind> in B<named>'s working directory. This location
17734021Steggecan be changed with B<named>'s B<managed-keys-directory> option. If
17834021Steggeyou are using views the file may be named with the SHA256 hash of a
17934021Steggeview name with a F<.mkeys> extension added.
18034021Stegge
18128487Sfsmp=head1 AUTHOR
18228487Sfsmp
18328487Sfsmp=over
18428487Sfsmp
18528487Sfsmp=item Written by Tony Finch <fanf2@cam.ac.uk> <dot@dotat.at>
18628487Sfsmp
18728487Sfsmp=item at the University of Cambridge Computing Service.
18834021Stegge
18934021Stegge=item You may do anything with this. It has no warranty.
19034021Stegge
19128487Sfsmp=item L<http://creativecommons.org/publicdomain/zero/1.0/>
19234021Stegge
19334021Stegge=back
19434021Stegge
19534021Stegge=head1 SEE ALSO
19634021Stegge
19734021Steggedig(1), named(8)
19834021Stegge
19934021Stegge=cut
20034021Stegge