30 use File::Temp; |
30 use File::Temp; |
31 use IO::File; |
31 use IO::File; |
32 use POSIX qw(strftime); |
32 use POSIX qw(strftime); |
33 use if $ENV{DEBUG} => "Smart::Comments"; |
33 use if $ENV{DEBUG} => "Smart::Comments"; |
34 |
34 |
35 |
|
36 BEGIN { |
35 BEGIN { |
37 |
36 |
38 our ($VERSION, @ISA, @EXPORT); |
37 our ($VERSION, @ISA, @EXPORT); |
39 use Exporter; |
38 use Exporter; |
40 |
39 |
41 # set the version for version checking |
40 # set the version for version checking |
42 $VERSION = 1.00; |
41 $VERSION = 1.00; |
|
42 |
43 # if using RCS/CVS, this may be preferred |
43 # if using RCS/CVS, this may be preferred |
44 $VERSION = sprintf "%d.%03d", q$Revision: 1.1 $ =~ /(\d+)/g; |
44 $VERSION = sprintf "%d.%03d", q$Revision: 1.1 $ =~ /(\d+)/g; |
45 |
45 |
46 @ISA = qw(Exporter); |
46 @ISA = qw(Exporter); |
47 @EXPORT = qw(&uniq &zones &changed_zones &update_index |
47 @EXPORT = qw(&uniq &zones &changed_zones &update_index |
48 &signature_expired &need_rollover &done_rollover &begin_rollover |
48 &signature_expired &need_rollover &done_rollover &begin_rollover |
49 &end_rollover &unlink_unused_keys &include_keys &sign &update_serial |
49 &end_rollover &unlink_unused_keys &include_keys &sign &update_serial |
50 &mk_zone_conf &file_entry &server_reload &dnssec_enabled %config); |
50 &mk_zone_conf &file_entry &server_reload &dnssec_enabled %config); |
51 } |
51 } |
52 |
52 |
53 our %config; |
53 our %config; |
54 |
54 |
55 sub uniq(@); |
55 sub uniq(@); |
109 say " * $zone: no .stamp file found"; # NOCH IN NEW_SERIAL PUSHEN |
109 say " * $zone: no .stamp file found"; # NOCH IN NEW_SERIAL PUSHEN |
110 push @r, $zone; |
110 push @r, $zone; |
111 next; |
111 next; |
112 } |
112 } |
113 |
113 |
114 my $stamp_mtime = (stat _)[9]; |
114 my $stamp_mtime = (stat _)[9]; |
115 my $zone_file_mtime = (stat "$_/$zone")[9] or die "Can't stat '$_/$zone': $!"; |
115 my $zone_file_mtime = (stat "$_/$zone")[9] |
|
116 or die "Can't stat '$_/$zone': $!"; |
116 |
117 |
117 # stamp age 'wins' if mtimes are equal because update_serial will both |
118 # stamp age 'wins' if mtimes are equal because update_serial will both |
118 # modify the zonefile and update the stamp which both is likely to |
119 # modify the zonefile and update the stamp which both is likely to |
119 # happen at the 'same' time unless you have very very high precision |
120 # happen at the 'same' time unless you have very very high precision |
120 # mtimes |
121 # mtimes |
180 } |
181 } |
181 |
182 |
182 sub update_serial($) { |
183 sub update_serial($) { |
183 |
184 |
184 my $zone = shift; |
185 my $zone = shift; |
185 # say "XXX: $zone: updating serial number"; |
186 |
|
187 # say "XXX: $zone: updating serial number"; |
186 |
188 |
187 my $file = "$config{master_dir}/$zone/$zone"; |
189 my $file = "$config{master_dir}/$zone/$zone"; |
188 my $in = IO::File->new($file) or die "Can't open $file: $!\n"; |
190 my $in = IO::File->new($file) or die "Can't open $file: $!\n"; |
189 my $out = File::Temp->new(DIR => dirname $file) |
191 my $out = File::Temp->new(DIR => dirname $file) |
190 or die "Can't open tmpfile: $!\n"; |
192 or die "Can't open tmpfile: $!\n"; |
201 |
203 |
202 rename($out->filename => $file) |
204 rename($out->filename => $file) |
203 or die "Can't rename tmp to $file: $!\n"; |
205 or die "Can't rename tmp to $file: $!\n"; |
204 |
206 |
205 my $perms = (stat $file)[2] & 07777 | 040 |
207 my $perms = (stat $file)[2] & 07777 | 040 |
206 or die "Can't stat '$file': $!"; |
208 or die "Can't stat '$file': $!"; |
207 chmod $perms, $file |
209 chmod $perms, $file |
208 or die "Can't 'chmod $perms, $file': $!"; |
210 or die "Can't 'chmod $perms, $file': $!"; |
209 |
211 |
210 $serial =~ s/\s*//g; |
212 $serial =~ s/\s*//g; |
211 say " * $zone: serial incremented to $serial"; |
213 say " * $zone: serial incremented to $serial"; |
212 |
214 |
213 open(my $stamp, ">", dirname($file) . "/.stamp"); |
215 open(my $stamp, ">", dirname($file) . "/.stamp"); |
214 |
216 |
215 say " * $zone: stamp aktualisiert"; |
217 say " * $zone: stamp aktualisiert"; |
216 # say " XXX $zone: stamp '$s' aktualisiert"; |
218 |
|
219 # say " XXX $zone: stamp '$s' aktualisiert"; |
217 } |
220 } |
218 |
221 |
219 sub new_serial($) { |
222 sub new_serial($) { |
220 |
223 |
221 my ($date, $cnt) = $_[0] =~ /(\d{8})(\d\d)/; |
224 my ($date, $cnt) = $_[0] =~ /(\d{8})(\d\d)/; |
272 or die "Can't rename ", $fh->filename, " to $izf: $!\n"; |
275 or die "Can't rename ", $fh->filename, " to $izf: $!\n"; |
273 $fh->unlink_on_destroy(0); |
276 $fh->unlink_on_destroy(0); |
274 } |
277 } |
275 |
278 |
276 my $perms = (stat _)[2] & 07777 | 040 |
279 my $perms = (stat _)[2] & 07777 | 040 |
277 or die "Can't stat '$izf': $!"; |
280 or die "Can't stat '$izf': $!"; |
278 chmod $perms, $izf |
281 chmod $perms, $izf |
279 or die "Can't 'chmod $perms, $izf': $!"; |
282 or die "Can't 'chmod $perms, $izf': $!"; |
280 |
283 |
281 say "** index-zone aktualisiert"; |
284 say "** index-zone aktualisiert"; |
282 return $indexzone; |
285 return $indexzone; |
283 } |
286 } |
284 |
287 |
294 m#($md/)(.*)#; |
297 m#($md/)(.*)#; |
295 my $z = $2; |
298 my $z = $2; |
296 my $cf = "$cd/$z"; |
299 my $cf = "$cd/$z"; |
297 my $de = dnssec_enabled $z, "$md/$config{indexzone}/$config{indexzone}"; |
300 my $de = dnssec_enabled $z, "$md/$config{indexzone}/$config{indexzone}"; |
298 my $suf = $de ? '.signed' : ''; |
301 my $suf = $de ? '.signed' : ''; |
299 # TODO: assuming that paths in $md and in zone config snippets match somehow |
302 |
|
303 # TODO: assuming that paths in $md and in zone config snippets match somehow |
300 my $zr = qr{\Q$z/$z$suf\E$}; |
304 my $zr = qr{\Q$z/$z$suf\E$}; |
301 my $zf = "$md/$z/$z$suf"; |
305 my $zf = "$md/$z/$z$suf"; |
302 |
306 |
303 my ($files, $changed) = (0, 0); |
307 my ($files, $changed) = (0, 0); |
304 my $czf; |
308 my $czf; |
305 open C, "+<$cf" or die "Cant't open '$cf': $!"; |
309 open C, "+<$cf" or die "Cant't open '$cf': $!"; |
306 my @lines = <C>; # TODO: deal with race condition? |
310 my @lines = <C>; # TODO: deal with race condition? |
307 my @oldlines; |
311 my @oldlines; |
308 my ($mode, $uid, $gid, $atime, $mtime) = (stat C)[2, 4, 5, 8, 9] or die "Can't stat: $!"; |
312 my ($mode, $uid, $gid, $atime, $mtime) = (stat C)[2, 4, 5, 8, 9] |
|
313 or die "Can't stat: $!"; |
309 $mode &= 07777; |
314 $mode &= 07777; |
310 for (@lines) { |
315 for (@lines) { |
311 next unless /^\s*file\s+"([^"]*)"\s*;\s*$/; |
316 next unless /^\s*file\s+"([^"]*)"\s*;\s*$/; |
312 $czf = $1; |
317 $czf = $1; |
313 $files++; |
318 $files++; |
316 @oldlines or @oldlines = @lines; |
321 @oldlines or @oldlines = @lines; |
317 $_ = qq(\tfile "$zf";\n); |
322 $_ = qq(\tfile "$zf";\n); |
318 } |
323 } |
319 } |
324 } |
320 |
325 |
321 die "Multiple file statements found in '$cf' (maybe inside multiline comments)" if $files > 1; |
326 die |
|
327 "Multiple file statements found in '$cf' (maybe inside multiline comments)" |
|
328 if $files > 1; |
322 next unless $changed; |
329 next unless $changed; |
323 |
330 |
324 # file statement in config snippet doesnt match, so we make a backup first and write a new config |
331 # file statement in config snippet doesnt match, so we make a backup first and write a new config |
325 my $cb = "$cf.bak"; |
332 my $cb = "$cf.bak"; |
326 open B, ">$cb" or die "Can't open '$cb': $!"; |
333 open B, ">$cb" or die "Can't open '$cb': $!"; |
327 print B @oldlines; |
334 print B @oldlines; |
328 close B; |
335 close B; |
329 chown $uid, $gid, $cb or die "Can't 'chown $uid, $gid, $cb': $!"; |
336 chown $uid, $gid, $cb or die "Can't 'chown $uid, $gid, $cb': $!"; |
330 chmod $mode, $cb or die "Can't 'chmod $mode, $cb': $!"; |
337 chmod $mode, $cb or die "Can't 'chmod $mode, $cb': $!"; |
331 utime $atime, $mtime, $cb or die "Can't 'utime $atime, $mtime, $cb': $!"; |
338 utime $atime, $mtime, $cb |
|
339 or die "Can't 'utime $atime, $mtime, $cb': $!"; |
332 |
340 |
333 truncate C, 0 or die "Can't truncate C, 0: $!"; |
341 truncate C, 0 or die "Can't truncate C, 0: $!"; |
334 seek C, 0, 0 or die "Can't seek C, 0, 0: $!"; |
342 seek C, 0, 0 or die "Can't seek C, 0, 0: $!"; |
|
343 |
335 # write back @lines we modified earlier |
344 # write back @lines we modified earlier |
336 print C @lines; |
345 print C @lines; |
337 close C; |
346 close C; |
338 |
347 |
339 print " * zonekonfiguration aktualisiert ($czf ==> $zf)\n"; |
348 print " * zonekonfiguration aktualisiert ($czf ==> $zf)\n"; |
366 return @r; |
375 return @r; |
367 } |
376 } |
368 |
377 |
369 sub done_rollover() { |
378 sub done_rollover() { |
370 |
379 |
371 # funktion ueberprueft ob ein keyrollover fertig ist |
380 # funktion ueberprueft ob ein keyrollover fertig ist |
372 # die bedingung dafuer ist das: |
381 # die bedingung dafuer ist das: |
373 # - eine datei .index.zsk vorhanden ist |
382 # - eine datei .index.zsk vorhanden ist |
374 # - die letzte änderung an der datei .index.zsk länger her ist als die abl_zeit |
383 # - die letzte änderung an der datei .index.zsk länger her ist als die abl_zeit |
375 # - die datei .index.zsk ueber mehr als eine zeile gross ist |
384 # - die datei .index.zsk ueber mehr als eine zeile gross ist |
376 # (also mehr als einen Schlüssel enthält) |
385 # (also mehr als einen Schlüssel enthält) |
377 my @r; |
386 my @r; |
378 my $now = time; |
387 my $now = time; |
379 |
388 |
380 while (my $dir = glob "$config{master_dir}/*") { |
389 while (my $dir = glob "$config{master_dir}/*") { |
381 my $zone = basename $dir; |
390 my $zone = basename $dir; |