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