1*00b67f09SDavid van Moolenbroek#!/usr/bin/perl 2*00b67f09SDavid van Moolenbroek 3*00b67f09SDavid van Moolenbroekuse warnings; 4*00b67f09SDavid van Moolenbroekuse strict; 5*00b67f09SDavid van Moolenbroek 6*00b67f09SDavid van Moolenbroekuse POSIX qw(strftime); 7*00b67f09SDavid van Moolenbroekmy $now = strftime "%Y%m%d%H%M%S", gmtime; 8*00b67f09SDavid van Moolenbroek 9*00b67f09SDavid van Moolenbroeksub ext8601 ($) { 10*00b67f09SDavid van Moolenbroek my $d = shift; 11*00b67f09SDavid van Moolenbroek $d =~ s{(....)(..)(..)(..)(..)(..)} 12*00b67f09SDavid van Moolenbroek {$1-$2-$3.$4:$5:$6+0000}; 13*00b67f09SDavid van Moolenbroek return $d; 14*00b67f09SDavid van Moolenbroek} 15*00b67f09SDavid van Moolenbroek 16*00b67f09SDavid van Moolenbroeksub getkey ($$) { 17*00b67f09SDavid van Moolenbroek my $h = shift; 18*00b67f09SDavid van Moolenbroek my $k = shift; 19*00b67f09SDavid van Moolenbroek m{\s+(\d+)\s+(\d+)\s+(\d+)\s+[(]\s*$}; 20*00b67f09SDavid van Moolenbroek $k->{flags} = $1; 21*00b67f09SDavid van Moolenbroek $k->{protocol} = $2; 22*00b67f09SDavid van Moolenbroek $k->{algorithm} = $3; 23*00b67f09SDavid van Moolenbroek my $data = "("; 24*00b67f09SDavid van Moolenbroek while (<$h>) { 25*00b67f09SDavid van Moolenbroek s{^\s+}{}; 26*00b67f09SDavid van Moolenbroek s{\s+$}{}; 27*00b67f09SDavid van Moolenbroek last if m{^[)]}; 28*00b67f09SDavid van Moolenbroek $data .= $_; 29*00b67f09SDavid van Moolenbroek } 30*00b67f09SDavid van Moolenbroek m{ alg = (\S+); key id = (\d+)}; 31*00b67f09SDavid van Moolenbroek $k->{alg} = $1; 32*00b67f09SDavid van Moolenbroek $k->{id} = $2; 33*00b67f09SDavid van Moolenbroek $k->{data} = $data; 34*00b67f09SDavid van Moolenbroek return $k; 35*00b67f09SDavid van Moolenbroek} 36*00b67f09SDavid van Moolenbroek 37*00b67f09SDavid van Moolenbroeksub fmtkey ($) { 38*00b67f09SDavid van Moolenbroek my $k = shift; 39*00b67f09SDavid van Moolenbroek return sprintf "%16s tag %s", $k->{name}, $k->{id}; 40*00b67f09SDavid van Moolenbroek} 41*00b67f09SDavid van Moolenbroek 42*00b67f09SDavid van Moolenbroeksub printstatus ($) { 43*00b67f09SDavid van Moolenbroek my $a = shift; 44*00b67f09SDavid van Moolenbroek if ($a->{removehd} ne "19700101000000") { 45*00b67f09SDavid van Moolenbroek printf " untrusted and to be removed at %s\n", ext8601 $a->{removehd}; 46*00b67f09SDavid van Moolenbroek } elsif ($a->{addhd} lt $now) { 47*00b67f09SDavid van Moolenbroek printf " trusted\n"; 48*00b67f09SDavid van Moolenbroek } else { 49*00b67f09SDavid van Moolenbroek printf " waiting for %s\n", ext8601 $a->{addhd}; 50*00b67f09SDavid van Moolenbroek } 51*00b67f09SDavid van Moolenbroek} 52*00b67f09SDavid van Moolenbroek 53*00b67f09SDavid van Moolenbroeksub digkeys ($) { 54*00b67f09SDavid van Moolenbroek my $name = shift; 55*00b67f09SDavid van Moolenbroek my $keys; 56*00b67f09SDavid van Moolenbroek open my $d, "-|", qw{dig +multiline DNSKEY}, $name; 57*00b67f09SDavid van Moolenbroek while (<$d>) { 58*00b67f09SDavid van Moolenbroek next unless m{^([a-z0-9.-]*)\s+\d+\s+IN\s+DNSKEY\s+}; 59*00b67f09SDavid van Moolenbroek next unless $name eq $1; 60*00b67f09SDavid van Moolenbroek push @$keys, getkey $d, { name => $name }; 61*00b67f09SDavid van Moolenbroek } 62*00b67f09SDavid van Moolenbroek return $keys; 63*00b67f09SDavid van Moolenbroek} 64*00b67f09SDavid van Moolenbroek 65*00b67f09SDavid van Moolenbroekmy $anchor; 66*00b67f09SDavid van Moolenbroekmy $owner = "."; 67*00b67f09SDavid van Moolenbroekwhile (<>) { 68*00b67f09SDavid van Moolenbroek next unless m{^([a-z0-9.-]*)\s+KEYDATA\s+(\d+)\s+(\d+)\s+(\d+)\s+}; 69*00b67f09SDavid van Moolenbroek my $k = getkey *ARGV, { 70*00b67f09SDavid van Moolenbroek name => $1, 71*00b67f09SDavid van Moolenbroek refresh => $2, 72*00b67f09SDavid van Moolenbroek addhd => $3, 73*00b67f09SDavid van Moolenbroek removehd => $4, 74*00b67f09SDavid van Moolenbroek }; 75*00b67f09SDavid van Moolenbroek if ($k->{name} eq "") { 76*00b67f09SDavid van Moolenbroek $k->{name} = $owner; 77*00b67f09SDavid van Moolenbroek } else { 78*00b67f09SDavid van Moolenbroek $owner = $k->{name}; 79*00b67f09SDavid van Moolenbroek } 80*00b67f09SDavid van Moolenbroek $k->{name} =~ s{[.]*$}{.}; 81*00b67f09SDavid van Moolenbroek push @{$anchor->{$k->{name}}}, $k; 82*00b67f09SDavid van Moolenbroek} 83*00b67f09SDavid van Moolenbroek 84*00b67f09SDavid van Moolenbroekfor my $name (keys %$anchor) { 85*00b67f09SDavid van Moolenbroek my $keys = digkeys $name; 86*00b67f09SDavid van Moolenbroek my $anchors = $anchor->{$name}; 87*00b67f09SDavid van Moolenbroek for my $k (@$keys) { 88*00b67f09SDavid van Moolenbroek if ($k->{flags} & 1) { 89*00b67f09SDavid van Moolenbroek printf "%s %s", fmtkey $k, $k->{alg}; 90*00b67f09SDavid van Moolenbroek } else { 91*00b67f09SDavid van Moolenbroek # ZSK - skipping 92*00b67f09SDavid van Moolenbroek next; 93*00b67f09SDavid van Moolenbroek } 94*00b67f09SDavid van Moolenbroek if ($k->{flags} & 512) { 95*00b67f09SDavid van Moolenbroek print " revoked;"; 96*00b67f09SDavid van Moolenbroek } 97*00b67f09SDavid van Moolenbroek my $a; 98*00b67f09SDavid van Moolenbroek for my $t (@$anchors) { 99*00b67f09SDavid van Moolenbroek if ($t->{data} eq $k->{data} and 100*00b67f09SDavid van Moolenbroek $t->{protocol} eq $k->{protocol} and 101*00b67f09SDavid van Moolenbroek $t->{algorithm} eq $k->{algorithm}) { 102*00b67f09SDavid van Moolenbroek $t->{matched} = 1; 103*00b67f09SDavid van Moolenbroek $a = $t; 104*00b67f09SDavid van Moolenbroek last; 105*00b67f09SDavid van Moolenbroek } 106*00b67f09SDavid van Moolenbroek } 107*00b67f09SDavid van Moolenbroek if (not defined $a) { 108*00b67f09SDavid van Moolenbroek print " no trust anchor\n"; 109*00b67f09SDavid van Moolenbroek next; 110*00b67f09SDavid van Moolenbroek } 111*00b67f09SDavid van Moolenbroek printstatus $a; 112*00b67f09SDavid van Moolenbroek } 113*00b67f09SDavid van Moolenbroek for my $a (@$anchors) { 114*00b67f09SDavid van Moolenbroek next if $a->{matched}; 115*00b67f09SDavid van Moolenbroek printf "%s %s missing;", fmtkey $a, $a->{alg}; 116*00b67f09SDavid van Moolenbroek printstatus $a; 117*00b67f09SDavid van Moolenbroek } 118*00b67f09SDavid van Moolenbroek} 119*00b67f09SDavid van Moolenbroek 120*00b67f09SDavid van Moolenbroekexit; 121*00b67f09SDavid van Moolenbroek 122*00b67f09SDavid van Moolenbroek__END__ 123*00b67f09SDavid van Moolenbroek 124*00b67f09SDavid van Moolenbroek=head1 NAME 125*00b67f09SDavid van Moolenbroek 126*00b67f09SDavid van Moolenbroekcheck5011 - summarize DNSSEC trust anchor status 127*00b67f09SDavid van Moolenbroek 128*00b67f09SDavid van Moolenbroek=head1 SYNOPSIS 129*00b67f09SDavid van Moolenbroek 130*00b67f09SDavid van Moolenbroekcheck5011 <I<managed-keys.bind>> 131*00b67f09SDavid van Moolenbroek 132*00b67f09SDavid van Moolenbroek=head1 DESCRIPTION 133*00b67f09SDavid van Moolenbroek 134*00b67f09SDavid van MoolenbroekThe BIND managed-keys file contains DNSSEC trust anchors 135*00b67f09SDavid van Moolenbroekthat can be automatically updated according to RFC 5011. The 136*00b67f09SDavid van MoolenbroekB<check5011> program reads this file and prints a summary of the 137*00b67f09SDavid van Moolenbroekstatus of the trust anchors. It fetches the corresponding 138*00b67f09SDavid van MoolenbroekDNSKEY records using B<dig> and compares them to the trust anchors. 139*00b67f09SDavid van Moolenbroek 140*00b67f09SDavid van MoolenbroekEach key is printed on a line with its name, its tag, and its 141*00b67f09SDavid van Moolenbroekalgorithm, followed by a summary of its status. 142*00b67f09SDavid van Moolenbroek 143*00b67f09SDavid van Moolenbroek=over 144*00b67f09SDavid van Moolenbroek 145*00b67f09SDavid van Moolenbroek=item C<trusted> 146*00b67f09SDavid van Moolenbroek 147*00b67f09SDavid van MoolenbroekThe key is currently trusted. 148*00b67f09SDavid van Moolenbroek 149*00b67f09SDavid van Moolenbroek=item C<waiting for ...> 150*00b67f09SDavid van Moolenbroek 151*00b67f09SDavid van MoolenbroekThe key is new, and B<named> is waiting for the "add hold-down" period 152*00b67f09SDavid van Moolenbroekto pass before the key will be trusted. 153*00b67f09SDavid van Moolenbroek 154*00b67f09SDavid van Moolenbroek=item C<untrusted and to be removed at ...> 155*00b67f09SDavid van Moolenbroek 156*00b67f09SDavid van MoolenbroekThe key was revoked and will be removed at the stated time. 157*00b67f09SDavid van Moolenbroek 158*00b67f09SDavid van Moolenbroek=item C<no trust anchor> 159*00b67f09SDavid van Moolenbroek 160*00b67f09SDavid van MoolenbroekThe key is present in the DNS but not in the managed-keys file. 161*00b67f09SDavid van Moolenbroek 162*00b67f09SDavid van Moolenbroek=item C<revoked> 163*00b67f09SDavid van Moolenbroek 164*00b67f09SDavid van MoolenbroekThe key has its revoked flag set. This is printed before the key's 165*00b67f09SDavid van Moolenbroektrust anchor status which should normally be C<untrusted...> if 166*00b67f09SDavid van MoolenbroekB<named> has observed the revocation. 167*00b67f09SDavid van Moolenbroek 168*00b67f09SDavid van Moolenbroek=item C<missing> 169*00b67f09SDavid van Moolenbroek 170*00b67f09SDavid van MoolenbroekThere is no DNSKEY record for this trust anchor. This is printed 171*00b67f09SDavid van Moolenbroekbefore the key's trust anchor status. 172*00b67f09SDavid van Moolenbroek 173*00b67f09SDavid van Moolenbroek=back 174*00b67f09SDavid van Moolenbroek 175*00b67f09SDavid van MoolenbroekBy default the managed keys are stored in a file called 176*00b67f09SDavid van MoolenbroekF<managed-keys.bind> in B<named>'s working directory. This location 177*00b67f09SDavid van Moolenbroekcan be changed with B<named>'s B<managed-keys-directory> option. If 178*00b67f09SDavid van Moolenbroekyou are using views the file may be named with the SHA256 hash of a 179*00b67f09SDavid van Moolenbroekview name with a F<.mkeys> extension added. 180*00b67f09SDavid van Moolenbroek 181*00b67f09SDavid van Moolenbroek=head1 AUTHOR 182*00b67f09SDavid van Moolenbroek 183*00b67f09SDavid van Moolenbroek=over 184*00b67f09SDavid van Moolenbroek 185*00b67f09SDavid van Moolenbroek=item Written by Tony Finch <fanf2@cam.ac.uk> <dot@dotat.at> 186*00b67f09SDavid van Moolenbroek 187*00b67f09SDavid van Moolenbroek=item at the University of Cambridge Computing Service. 188*00b67f09SDavid van Moolenbroek 189*00b67f09SDavid van Moolenbroek=item You may do anything with this. It has no warranty. 190*00b67f09SDavid van Moolenbroek 191*00b67f09SDavid van Moolenbroek=item L<http://creativecommons.org/publicdomain/zero/1.0/> 192*00b67f09SDavid van Moolenbroek 193*00b67f09SDavid van Moolenbroek=back 194*00b67f09SDavid van Moolenbroek 195*00b67f09SDavid van Moolenbroek=head1 SEE ALSO 196*00b67f09SDavid van Moolenbroek 197*00b67f09SDavid van Moolenbroekdig(1), named(8) 198*00b67f09SDavid van Moolenbroek 199*00b67f09SDavid van Moolenbroek=cut 200