1 #! /usr/bin/perl |
|
2 # (c) 1998 Heiko Schlittermann <heiko@datom.de> |
|
3 # |
|
4 # … work in progress do integrate dnssec (branch suess) |
|
5 # |
|
6 # Update the serial numbers in zone files |
|
7 # The serial number needs to match a specified pattern (see |
|
8 # the line marked w/ PATTERN. |
|
9 # |
|
10 # ToDo: |
|
11 # . test against an md5 sum, not just the date of the stamp file |
|
12 # . FIXME: handle `/' in file names (currently only working in |
|
13 # the current directory) |
|
14 # . optionally reload the named |
|
15 |
|
16 use strict; |
|
17 use warnings; |
|
18 |
|
19 use File::Basename; |
|
20 use File::Copy; |
|
21 use FindBin; |
|
22 |
|
23 my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" ); |
|
24 my @dnssec_killkeys |
|
25 = ( "$FindBin::Bin/dnssec-killkey", "/usr/bin/dnstools/dnssec-killkey" ); |
|
26 my $dnssec_killkey; |
|
27 my @dnssec_creatkeys |
|
28 = ( "$FindBin::Bin/dnssec-creatkey", "/usr/bin/dnstools/dnssec-creatkey" ); |
|
29 my $dnssec_creatkey; |
|
30 my @dnssec_signs |
|
31 = ( "$FindBin::Bin/dnssec-sign", "/usr/bin/dnstools/dnssec-sign" ); |
|
32 my %config; |
|
33 my $dnssec_sign; |
|
34 my @change_names = (); |
|
35 |
|
36 foreach ( grep {-f} @configs ) { |
|
37 open( CONFIG, $_ ) or die "Can't open $_: $!\n"; |
|
38 } |
|
39 |
|
40 unless ( seek( CONFIG, 0, 0 ) ) { |
|
41 die "Can't open config (searched: @configs)\n"; |
|
42 } |
|
43 foreach ( grep {-f} @dnssec_killkeys ) { |
|
44 if ( -x $_ ) { |
|
45 $dnssec_killkey = $_; |
|
46 } |
|
47 else { |
|
48 die "Can't run $_\n"; |
|
49 } |
|
50 } |
|
51 foreach ( grep {-f} @dnssec_creatkeys ) { |
|
52 if ( -x $_ ) { |
|
53 $dnssec_creatkey = $_; |
|
54 } |
|
55 else { |
|
56 die "Can't run $_\n"; |
|
57 } |
|
58 } |
|
59 foreach ( grep {-f} @dnssec_signs ) { |
|
60 if ( -x $_ ) { |
|
61 $dnssec_sign = $_; |
|
62 } |
|
63 else { |
|
64 die "Can't run $_\n"; |
|
65 } |
|
66 } |
|
67 |
|
68 while (<CONFIG>) { |
|
69 chomp; |
|
70 s/#.*//; |
|
71 s/\t//g; |
|
72 s/\s//g; |
|
73 next unless length; |
|
74 my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 ); |
|
75 $config{$cname} = $ccont; |
|
76 } |
|
77 close(CONFIG); |
|
78 |
|
79 my $bind_dir = $config{bind_dir}; |
|
80 my $conf_dir = $config{zone_conf_dir}; |
|
81 my $master_dir = $config{master_dir}; |
|
82 |
|
83 my $ME = basename $0; |
|
84 my @tmpfiles; |
|
85 my $verbose = 0; |
|
86 my $opt_yes = 0; |
|
87 my @Zones; |
|
88 my $file; |
|
89 |
|
90 |
|
91 sub cleanup() { unlink @tmpfiles; } |
|
92 END { cleanup(); } |
|
93 |
|
94 for (@ARGV) { |
|
95 if ( $_ eq "-y" ) { |
|
96 $opt_yes = 1; |
|
97 shift @ARGV; |
|
98 } |
|
99 } |
|
100 |
|
101 @Zones = @ARGV ? @ARGV : glob("$master_dir/*"); |
|
102 |
|
103 MAIN: { |
|
104 my $changed = 0; |
|
105 my ( $dd, $mm, $yy ) = ( localtime() )[ 3 .. 5 ]; |
|
106 my $date; |
|
107 $mm++; |
|
108 |
|
109 # prueft jede domain, die ein verzeichnis in $master_dir hat, ob sie |
|
110 # dnssec nutzt. |
|
111 # passt die eintraege in $config_file falls noetig an. |
|
112 while (<$master_dir/*>) { |
|
113 s#($master_dir/)(.*)#$2#; |
|
114 my $zone = $_; |
|
115 |
|
116 my $zone_file = "$master_dir/$zone/$zone"; |
|
117 my $conf_file = "$conf_dir/$zone"; |
|
118 my @c_content; |
|
119 |
|
120 unless ( -f "$conf_file" ) { |
|
121 die "$conf_file: $! \n"; |
|
122 } |
|
123 |
|
124 if ( -e "$master_dir/$zone/.keycounter" ) { |
|
125 |
|
126 open( FILE, "<$conf_file" ) or die "$conf_file: $!\n"; |
|
127 @c_content = <FILE>; |
|
128 close(FILE); |
|
129 |
|
130 for (@c_content) { |
|
131 if (m{(.*)($zone_file)(";)}) { |
|
132 print "$2 ==> $2.signed\n"; |
|
133 $_ = "$1$2.signed$3\n"; |
|
134 } |
|
135 } |
|
136 |
|
137 open( FILE, ">$conf_file" ) or die "$conf_file: $!\n"; |
|
138 print FILE @c_content; |
|
139 close(FILE); |
|
140 |
|
141 } |
|
142 else { |
|
143 |
|
144 open( FILE, "<$conf_file" ) or die "$conf_file: $!\n"; |
|
145 @c_content = <FILE>; |
|
146 close(FILE); |
|
147 |
|
148 for (@c_content) { |
|
149 if (m{(.*)($zone_file)\.signed(.*)}) { |
|
150 print "$2.signed ==> $2\n"; |
|
151 $_ = "$1$2$3\n"; |
|
152 } |
|
153 } |
|
154 |
|
155 open( FILE, ">$conf_file" ) or die "$conf_file: $!\n"; |
|
156 print FILE @c_content; |
|
157 close(FILE); |
|
158 } |
|
159 } |
|
160 |
|
161 # erzeugt eine named.conf-datei aus den entsprechenden vorlagen. |
|
162 print "** creat named.conf.zones **\n"; |
|
163 open( TO, ">$bind_dir/named.conf.zones" ) |
|
164 or die "$bind_dir/named.conf.zones: $!\n"; |
|
165 while (<$conf_dir/*>) { |
|
166 open( FROM, "$_" ) or die "$_: $! \n"; |
|
167 print TO <FROM>; |
|
168 close(FROM); |
|
169 } |
|
170 close(TO); |
|
171 |
|
172 # aufruf von dnssec-killkey |
|
173 print "** execute dnssec-killkey for keyrollover **\n"; |
|
174 system "$dnssec_killkey"; |
|
175 die "$dnssec_killkey not found ($!)" if $? == -1; |
|
176 exit 1 if $?; |
|
177 |
|
178 # aufruf von dnssec-creatkey |
|
179 print "** execute dnssec-creatkey for keyrollover **\n"; |
|
180 system "$dnssec_creatkey"; |
|
181 die "$dnssec_creatkey not found ($!)" if $? == -1; |
|
182 exit 1 if $?; |
|
183 |
|
184 # aufruf von dnssec-sign |
|
185 print "** execute dnssec-sign for sign-update **\n"; |
|
186 system "$dnssec_sign"; |
|
187 die "$dnssec_sign not found ($!)" if $? == -1; |
|
188 exit 1 if $?; |
|
189 |
|
190 # update-serial |
|
191 print "** update serial **\n"; |
|
192 foreach ( $dd, $mm ) { s/^\d$/0$&/; } |
|
193 $yy += 1900; |
|
194 $date = "$yy$mm$dd"; |
|
195 |
|
196 while ( my $file = shift @Zones ) { |
|
197 |
|
198 my $file_basename = basename($file); |
|
199 |
|
200 $file =~ s#($master_dir)(/.*)#$1$2$2#; |
|
201 local ( *I, *O ); |
|
202 my $done = 0; |
|
203 |
|
204 my $new = "$file.$$.tmp"; |
|
205 my $bak = "$file.bak"; |
|
206 my $stamp = $master_dir . "/.stamp/" . basename($file); |
|
207 |
|
208 $file =~ /(\.bak|~)$/ and next; |
|
209 $file !~ /\./ and next; |
|
210 |
|
211 $verbose && print "$file:"; |
|
212 |
|
213 if ( -f $stamp && ( ( stat($stamp) )[9] >= ( stat($file) )[9] ) ) { |
|
214 $verbose && print " fresh, skipping.\n"; |
|
215 next; |
|
216 } |
|
217 |
|
218 $done = 0; |
|
219 push @tmpfiles, $new; |
|
220 open( *I, "<$file" ) or die("Can't open < $file: $!\n"); |
|
221 open( *O, ">$new" ) or die("Can't open > $new: $!\n"); |
|
222 |
|
223 while (<I>) { |
|
224 /^\s+((\d+)(\d{2}))\s*;\s*serial/i and do { # PATTERN |
|
225 my ( $sdate, $scount, $serial ) = ( $2, $3, $1 ); |
|
226 $done = 1; |
|
227 print " [$file] serial $sdate$scount"; |
|
228 |
|
229 if ( $date eq $sdate ) { $scount++; } |
|
230 else { $sdate = $date; $scount = "00"; } |
|
231 |
|
232 print " bumping to $sdate$scount"; |
|
233 s/$serial/$sdate$scount/; |
|
234 |
|
235 }; |
|
236 print O; |
|
237 } |
|
238 |
|
239 close(O); |
|
240 close(I); |
|
241 |
|
242 if ($done) { |
|
243 |
|
244 open( I, "<$new" ) or die("Can't open <$new: $!\n"); |
|
245 open( O, ">$file" ) or die("Can't open >$file: $!\n"); |
|
246 while (<I>) { print O or die("Can't write to $file: $!\n"); } |
|
247 close(I) or die("Can't close $new: $!\n"); |
|
248 close(O) or die("Can't close $file: $!\n"); |
|
249 |
|
250 unlink $new; |
|
251 |
|
252 open( O, ">$stamp" ) or die("Can't open >$stamp: $!\n"); |
|
253 close(O); |
|
254 $changed++; |
|
255 |
|
256 push @change_names, $file_basename; |
|
257 |
|
258 } |
|
259 else { |
|
260 print " $file: no serial number found: no zone file?"; |
|
261 } |
|
262 print "\n"; |
|
263 } |
|
264 |
|
265 my $pidfile; |
|
266 |
|
267 unless ($changed == 0) { |
|
268 print "Changed $changed files.\n"; |
|
269 } |
|
270 |
|
271 foreach ( |
|
272 qw(/var/run/bind/run/named.pid /var/run/named.pid /etc/named.pid)) |
|
273 { |
|
274 -f $_ and $pidfile = $_ and last; |
|
275 } |
|
276 |
|
277 # dnssec-sign aufruf fuer geanderten domains |
|
278 print "** execute dnssec-sign **\n"; |
|
279 system "$dnssec_sign @change_names"; |
|
280 die "$dnssec_sign not found ($!)" if $? == -1; |
|
281 exit 1 if $?; |
|
282 |
|
283 if ($pidfile) { |
|
284 if ($opt_yes) { |
|
285 $_ = "y"; |
|
286 print "** Nameserver will be reloaded\n"; |
|
287 } |
|
288 else { print "** Reload now? [Y/n]: "; $_ = <STDIN>; } |
|
289 /^y|^$/i and system "rndc reload"; |
|
290 } |
|
291 else { |
|
292 print |
|
293 "** No PID of a running named found. Please reload manually.\n"; |
|
294 |
|
295 } |
|
296 |
|
297 } |
|
298 |
|