# HG changeset patch # User Heiko Schlittermann # Date 1293546215 -3600 # Node ID 6af96ec29ada91681ed0d7a111a07e5558c054d2 # Parent ee22798cf2c373d25afadbf49c4c67b4dec8db03 sign_expired diff -r ee22798cf2c3 -r 6af96ec29ada update-serial.pl --- a/update-serial.pl Fri Dec 24 00:15:54 2010 +0100 +++ b/update-serial.pl Tue Dec 28 15:23:35 2010 +0100 @@ -7,16 +7,20 @@ use File::Basename; use Pod::Usage; use Getopt::Long; +use Smart::Comments; +use File::Temp; +use POSIX qw(strftime); sub uniq(@); sub read_conf(@); -sub add_argv; -sub changed_zone; -sub sign_end; +sub zones(@); +sub changed_zones(); +sub update_index($); +sub sign_expired($); + sub sign_zone; sub update_serial; sub mk_zone_conf; -sub update_index; sub file_entry; sub server_reload; sub to_begin_ro; @@ -27,12 +31,14 @@ sub end_ro; my %config; +my %opt; MAIN: { GetOptions( - "h|help" => sub { pod2usage(-exit 0, -verbose => 1) }, - "m|man" => sub { + "sign-alert-time=i" => \$opt{sign_alert_time}, + "h|help" => sub { pod2usage(-exit 0, -verbose => 1) }, + "m|man" => sub { pod2usage( -exit 0, -verbose => 2, @@ -41,38 +47,42 @@ }, ) or pod2usage; - %config = read_conf("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf"); + # merge the config and the defined options from commandline + %config = ( + read_conf("$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf"), + map { $_ => $opt{$_} } grep { defined $opt{$_} } keys %opt + ); - our @new_serial; # liste fuer neuen serial + our @new_serial; # DO NOT USE our @begin_ro_list; # liste mit zonen deren key-rollover beginnt our @end_ro_list; # liste mit zonen deren key-rollover fertig ist our $bind_dir = $config{bind_dir}; our $conf_dir = $config{zone_conf_dir}; - our $sign_alert_time = $config{sign_alert_time}; - our $indexzone = $config{indexzone}; our $key_counter_end = $config{key_counter_end}; our $ablauf_zeit = $config{abl_zeit}; - add_argv; + my @candidates = @ARGV ? zones(@ARGV) : changed_zones; + push @candidates, update_index($config{indexzone}); + push @candidates, sign_expired($config{sign_alert_time}); + ### @candidates + exit; - changed_zone; - sign_end; - - to_begin_ro; # prueft nach beginnenden rollover-verfahren - to_end_ro; # prueft nach endenden rollover-verfahren + to_begin_ro; # prueft nach beginnenden rollover-verfahren + to_end_ro; # prueft nach endenden rollover-verfahren if (@begin_ro_list) { - begin_ro; # eine rollover-beginn-sequenz + begin_ro; # eine rollover-beginn-sequenz } if (@end_ro_list) { - end_ro; # eine rollover-end-squenz + end_ro; # eine rollover-end-squenz } if (@new_serial) { - update_index; # index zone aktuallisieren - update_serial; # serial aktuallisieren - sign_zone; # zone signieren + + #--update_index; # index zone aktuallisieren + update_serial; # serial aktuallisieren + sign_zone; # zone signieren } file_entry; # bearbeitet die file-eintraege der konfigurations-datei @@ -82,6 +92,7 @@ } sub uniq(@) { + # remove duplicate entries my %all; @all{@_} = (); @@ -108,74 +119,72 @@ return %config; } -sub add_argv { - # checked whether the zones in argv are managed zones and - #inserted them into the list new_serial - our @new_serial; - my $zone; +sub zones(@) { + + # check whether the zones in argv are managed zones and + # insert them into the list new_serial + + my @r; - for (@ARGV) { - chomp($zone = `idn --quiet "$_"`); - if (-e "$config{master_dir}/$zone/$zone") { - push @new_serial, $zone; - } + foreach (@_) { + chomp(my $zone = `idn --quiet "$_"`); + die "$zone is not managed\n" + if not -e "$config{master_dir}/$zone/$zone"; + push @r, $zone; } + + return @r; } -sub changed_zone { - our @new_serial; +sub changed_zones() { + + # find candidates in our master dir + my @r; while (glob "$config{master_dir}/*") { my $zone = basename($_); - if (-e "$config{master_dir}/$zone/.stamp") { - my $stamptime = (-M "$config{master_dir}/$zone/.stamp"); - my $filetime = (-M "$config{master_dir}/$zone/$zone"); - if ($stamptime > $filetime) { - push @new_serial, $zone; - print " * $zone: zonedatei wurde geaendert\n"; - } + if (not -e "$_/.stamp") { + say " * $zone: no .stamp file found"; # NOCH IN NEW_SERIAL PUSHEN + push @r, $zone; + next; } - else { - print " * $zone: keine .stamp-datei gefunden\n" - ; # NOCH IN NEW_SERIAL PUSHEN - push @new_serial, $zone; - } + + my $stamp_age = -M _; + my $file_age = -M "$_/$zone"; + + next if $stamp_age <= $file_age; # should be only < + + push @r, $zone; + say " * $zone: zone file modified"; } - + return @r; } -sub sign_end { - our $sign_alert_time; # the time between the end and the new signing - # (see external configuration) - our @new_serial; +sub sign_expired($) { + my $sign_alert_time = shift; # the time between the end and the new signing + # (see external configuration) + my @r; # erzeugt $time (die zeit ab der neu signiert werden soll) - my $unixtime = time + (3600 * $sign_alert_time); - my $time = `date -d \@$unixtime +%Y%m%d%H`; + # ... warum eigentlich nur bis zu den Stunden und nicht auch Minuten und Sekunden? + my $time = strftime("%Y%m%d%H" => localtime time + 3600 * $sign_alert_time); ## vergleicht fuer alle zonen im ordner $config{master_dir} mit einer ## .signed-datei den zeitpunkt in $time mit dem ablaufdatum der ## signatur, welcher aus der datei .signed ausgelesen wird. - while (glob "$config{master_dir}/*") { - s#($config{master_dir}/)(.*)#$2#; - my $zone = $_; + ZONE: while (my $dir = glob "$config{master_dir}/*") { + my $zone = basename $dir; - if (-e "$config{master_dir}/$zone/$zone.signed") { - open(ZONE, "$config{master_dir}/$zone/$zone.signed"); - my @zone_sig_content = ; - close(ZONE); + next if not -e "$dir/$zone.signed"; - for (@zone_sig_content) { - if (m#SOA.*[0-9]{14}#) { - s#.*([0-9]{10})([0-9]{4}).*#$1#; - if ($_ < $time) { - push @new_serial, $zone; - } - } - } - } + open(my $fh, "$dir/$zone.signed") or die "Can't open $dir/$zone.signed: $!\n"; + push @r, $zone if + /RRSIG\s+SOA[\d ]+(\d{10})\d{4}\s+\(/ ~~ [<$fh>] + and $1 < $time; } + + return @r; } sub sign_zone { @@ -279,47 +288,35 @@ print "** zonekonfiguration erzeugt\n"; } -sub update_index { +sub update_index($) { + my $indexzone = shift; - # aktualisiert die indexzone; - our @new_serial; - our $indexzone; - my @iz_content_old; - my @iz_content_new; + my @iz; - open(INDEXZONE, "$config{master_dir}/$indexzone/$indexzone") - or die "$config{master_dir}/$indexzone/$indexzone: $!\n"; - @iz_content_old = ; - close(INDEXZONE); - - for (@iz_content_old) { - unless (m#ZONE::#) { - push @iz_content_new, $_; - } + { + open(my $fh, "$config{master_dir}/$indexzone/$indexzone") + or die "$config{master_dir}/$indexzone/$indexzone: $!\n"; + chomp(@iz = grep !/ZONE::/ => <$fh>); } for my $dir (glob "$config{master_dir}/*") { - my $zone = basename($dir); - my $info_end = "::sec-off"; - - if (-e "$dir/.keycounter") { - $info_end = "::sec-on"; - } - - my $iz_line = "\t\tIN TXT\t\t\"ZONE::$zone$info_end\"\n"; - - push @iz_content_new, $iz_line; + my $zone = basename($dir); + my $info = -e ("$dir/.keycounter") ? "sec-on" : "sec-off"; + push @iz, join "::", "\t\tIN TXT\t\t\"ZONE", $zone, $info; } - open(INDEXZONE, ">$config{master_dir}/$indexzone/$indexzone") - or die "$config{master_dir}/$indexzone/$indexzone: $!\n"; - print INDEXZONE @iz_content_new; - close(INDEXZONE); + { + my $fh = File::Temp->new(DIR => "$config{master_dir}/$indexzone") + or die "Can't create tmpdir: $!\n"; + print $fh join "\n" => @iz, ""; + rename($fh->filename => "$config{master_dir}/$indexzone/$indexzone") + or die "Can't rename " + . $fh->filename + . " to $config{master_dir}/$indexzone/$indexzone: $!\n"; + } - # fuegt die index-zone in die liste damit der serial erhoet wird - push @new_serial, $indexzone; - - print "** index-zone aktualisiert \n"; + say "** index-zone aktualisiert"; + return $indexzone; } sub file_entry { @@ -589,7 +586,7 @@ =head1 SYNOPSIS - update-serial [zone...] + update-serial [options] [zone...] =head1 DESCRIPTION @@ -598,6 +595,13 @@ =head1 OPTIONS +=over + +=item B<--sign-alert-time> I + + +=back + The common options B<-h>|B<--help>|B<-m>|B<--man> are supported. =head1 AUTHOR