diff -r d50f6874b7ab -r 7e472c559b36 update-serial --- a/update-serial Fri Dec 03 16:42:12 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,549 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; -use FindBin; -use File::Basename; - -sub del_double { - # entfernt doppelte eintraege in einer liste - my %all; - grep { $all{$_} = 0 } @_; - return ( keys %all ); -} - -sub read_conf { - # liest die Konfiguration ein - my @configs = ( "$FindBin::Bin/dnstools.conf", "/etc/dnstools.conf" ); - our %config; - - for ( grep {-f} @configs ) { - open( CONFIG, $_ ) or die "Can't open $_: $!\n"; - } - unless ( seek( CONFIG, 0, 0 ) ) { - die "Can't open config (searched: @configs)\n"; - } - while () { - chomp; - s/#.*//; - s/\t//g; - s/\s//g; - - next unless length; - my ( $cname, $ccont ) = split( /\s*=\s*/, $_, 2 ); - $config{$cname} = $ccont; - } - close(CONFIG); -} - -sub add_argv { - # prueft ob zonen aus ARGV verwaltete zonen sind - # und fuegt sie, falls ja in die liste @new_serial ein - our @new_serial; - our $master_dir; - my $zone; - - for (@ARGV) { - chomp( $zone = `idn --quiet "$_"` ); - if ( -e "$master_dir/$zone/$zone" ) { - push @new_serial, $zone; - } - } -} - -sub changed_zone { - our $master_dir; - our @new_serial; - - for (<$master_dir/*>) { - my $zone = basename($_); - - if (-e "$master_dir/$zone/.stamp") { - my $stamptime = (-M "$master_dir/$zone/.stamp"); - my $filetime = (-M "$master_dir/$zone/$zone"); - if ($stamptime > $filetime) { - push @new_serial, $zone; - print " * $zone: zonedatei wurde geaendert\n"; - } - } - else { - print " * $zone: keine .stamp-datei gefunden\n"; # NOCH IN NEW_SERIAL PUSHEN - push @new_serial, $zone; - } - } - -} - -sub sign_end { - our $sign_alert_time; # die zeit zwischen dem ende und der neuen - # signierung (siehe externe konfiguration) - our $master_dir; - our @new_serial; - - # erzeugt $time (die zeit ab der neu signiert werden soll) - chomp( my $unixtime = `date +%s` ); - $unixtime = $unixtime + ( 3600 * $sign_alert_time ); - my $time = `date -d \@$unixtime +%Y%m%d%H`; - - ## vergleicht fuer alle zonen im ordner $master_dir mit einer - ## .signed-datei den zeitpunkt in $time mit dem ablaufdatum der - ## signatur, welcher aus der datei .signed ausgelesen wird. - for (<$master_dir/*>) { - s#($master_dir/)(.*)#$2#; - my $zone = $_; - - if ( -e "$master_dir/$zone/$zone.signed" ) { - open( ZONE, "$master_dir/$zone/$zone.signed" ); - my @zone_sig_content = ; - close(ZONE); - - for (@zone_sig_content) { - if (m#SOA.*[0-9]{14}#) { - s#.*([0-9]{10})([0-9]{4}).*#$1#; - if ( $_ < $time ) { - push @new_serial, $zone; - } - } - } - } - } -} - -sub sign_zone { - # signiert die zonen und erhoeht den wert in der keycounter-datei - our @new_serial; - our $master_dir; - my $zone; - my $kc; - - for ( &del_double( @new_serial ) ) { - $zone = $_; - - unless (-e "$master_dir/$zone/.index.zsk") { - next; - } - - chdir "$master_dir/$zone"; - if (`dnssec-signzone $zone 2>/dev/null`) { - print " * $zone neu signiert \n"; - - # erhoeht den keycounter - if ("$master_dir/$zone/.keycounter") { - open( KC, "$master_dir/$zone/.keycounter" ); - $kc = ; - close(KC); - $kc += 1; - } - else { - $kc = 1; - } - open( KC, ">$master_dir/$zone/.keycounter" ); - print KC $kc; - close(KC); - } - else { print "$zone konnte nicht signiert werden \n"; } - } -} - -sub update_serial { - our $master_dir; - our @new_serial; - chomp (my $date = `date +%Y%m%d`); - my @new_content; - my $sdate; - my $scount; - my $serial; - - for ( &del_double( @new_serial ) ) { - # erhoeht den serial - my $zone = $_; - my $file = "$master_dir/$zone/$zone"; - my @new_content = (); - - open (SER, "<$file") or die "$file: $!\n"; - for () { - if (/^\s+(\d+)(\d{2})\s*;\s*serial/i) { - $sdate = $1; - $scount = $2; - $serial = "$sdate$scount"; - if ( $date eq $sdate ) { - $scount++; - } - else { - $sdate = $date; - $scount = "00"; - } - } - if ($serial) { - s/$serial/$sdate$scount/; - } - push @new_content, $_; - } - close (SER); - - open (RES, ">$file") or die "$file: $!\n"; - print RES @new_content; - close (RES); - print " * $zone: serial erhoeht \n"; - - open(STAMP, ">$master_dir/$zone/.stamp") or die "$master_dir/$zone/.stamp: $!\n"; - close(STAMP); - print " * $zone: stamp aktualisiert \n"; - } -} - -sub mk_zone_conf { - # erzeugt eine named.conf-datei aus den entsprechenden vorlagen. - our $bind_dir; - our $conf_dir; - - open( TO, ">$bind_dir/named.conf.zones" ) - or die "$bind_dir/named.conf.zones: $!\n"; - while (<$conf_dir/*>) { - open( FROM, "$_" ) or die "$_: $! \n"; - print TO ; - close(FROM); - } - close(TO); - print "** zonekonfiguration erzeugt\n"; -} - -sub update_index { - # aktualisiert die indexzone; - our @new_serial; - our $indexzone; - our $master_dir; - my @iz_content_old; - my @iz_content_new; - - open (INDEXZONE, "$master_dir/$indexzone/$indexzone") - or die "$master_dir/$indexzone/$indexzone: $!\n"; - @iz_content_old = ; - close (INDEXZONE); - - for (@iz_content_old) { - unless (m#ZONE::#) { - push @iz_content_new, $_; - } - } - - for my $dir ( glob "$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; - } - - open (INDEXZONE, ">$master_dir/$indexzone/$indexzone") - or die "$master_dir/$indexzone/$indexzone: $!\n"; - print INDEXZONE @iz_content_new; - close (INDEXZONE); - - # fuegt die index-zone in die liste damit der serial erhoet wird - push @new_serial, $indexzone; - - print "** index-zone aktualisiert \n"; -} - -sub file_entry { - # prueft jede domain, die ein verzeichnis in $master_dir hat, ob sie - # dnssec nutzt. - # passt die eintraege in $config_file falls noetig an. - our $master_dir; - our $conf_dir; - - while (<$master_dir/*>) { - s#($master_dir/)(.*)#$2#; - my $zone = $_; - my $zone_file = "$master_dir/$zone/$zone"; - my $conf_file = "$conf_dir/$zone"; - my @c_content; - - unless ( -f "$conf_file" ) { - die "$conf_file: $! \n"; - } - - if ( -e "$master_dir/$zone/.keycounter" ) { - open( FILE, "<$conf_file" ) or die "$conf_file: $!\n"; - @c_content = ; - close(FILE); - for (@c_content) { - if (m{(.*)($zone_file)(";)}) { - print " * zonekonfiguration aktualisiert ($2 ==> $2.signed)\n"; - $_ = "$1$2.signed$3\n"; - } - } - open( FILE, ">$conf_file" ) or die "$conf_file: $!\n"; - print FILE @c_content; - close(FILE); - } - else { - open( FILE, "<$conf_file" ) or die "$conf_file: $!\n"; - @c_content = ; - close(FILE); - for (@c_content) { - if (m{(.*)($zone_file)\.signed(.*)}) { - print " * zonekonfiguration aktualisiert ($2.signed ==> $2)\n"; - $_ = "$1$2$3\n"; - } - } - open( FILE, ">$conf_file" ) or die "$conf_file: $!\n"; - print FILE @c_content; - close(FILE); - } - } -} - -sub server_reload { - if (`rndc reload`) {print "** reload dns-server \n"}; -} - -sub to_begin_ro { - # gibt alle zonen mit abgelaufenen keycounter in die liste @begin_ro_list - our @begin_ro_list; - our $master_dir; - our $key_counter_end; - our @new_serial; - my $zone; - - while (<$master_dir/*>) { - chomp( $zone = $_ ); - my $key; - - unless (-f "$zone/.keycounter" ) {next;} - - open( KEY, "$zone/.keycounter" ) or die "$zone/.keycounter: $!\n"; - $key = ; - close(KEY); - - # vergleicht den wert aus der keycount-datei mit dem wert aus der - #dnstools.conf (key_counter_end) - if ( $key_counter_end <= $key ) { - $zone =~ s#($master_dir/)(.*)#$2#; - push @begin_ro_list, $zone; - } - } -} - -sub to_end_ro { - # funktion ueberprueft ob ein keyrollover fertig ist - # die bedingung dafuer ist das: - # - eine datei .index.zsk vorhanden ist - # - die datei .index.zsk vor mehr x stunden geaendert wurde - # - die datei .index.zsk ueber mehr als zwei zeilen gross ist - our $master_dir; - our @end_ro_list; - our $ablauf_zeit; - chomp( my $now_time = `date +%s` ); - - for (<$master_dir/*>) { - my $zone = $_; - $zone =~ s#($master_dir/)(.*)#$2#; - - my @index = (); - my $index_wc; - my @status; - - # prueft nach der ".index.zsk"-datei und erstellt den zeitpunkt - # an dem das key-rollover endet. - $status[9] - if ( -e "$master_dir/$zone/.index.zsk" ) { - @status = stat("$master_dir/$zone/.index.zsk"); - $status[9] += ( 3600 * $ablauf_zeit ); - } - else { next; } - - # $status[9] ist der zeitpunkt an dem der key-rollover endet - # prueft ob das key-rollover-ende erreicht ist - unless ( $status[9] < $now_time ) { next;} - - # prueft die anzahl der schluessel in der .index.zsk - open( INDEX, "$master_dir/$zone/.index.zsk" ) - or die "$master_dir/$zone/.index.zsk: $!\n"; - @index = ; - $index_wc = @index; - close(INDEX); - if ( $index_wc > 1 ) {push @end_ro_list, $zone;} - } -} - -sub begin_ro { - # anfang des key-rollovers - our @begin_ro_list; - our $master_dir; - our @new_serial; - - for ( &del_double( @begin_ro_list ) ) { - #erzeugt zsks - my $zone = $_; - my $zpf = "$master_dir/$zone"; - my @index; - - chdir "$zpf" or die "$zpf: $!\n"; - my $keyname = `dnssec-keygen -a RSASHA1 -b 512 -n ZONE $zone`; - - open( INDEX, ".index.zsk" ) or die "$zpf/.index.zsk: $!\n"; - @index = ; - close(INDEX); - - push @index, $keyname; - if ( @index > 2 ) { shift(@index); } - - open( INDEX, ">.index.zsk" ) or die "$zpf/.index.zsk: $!\n"; - print INDEX @index; - close(INDEX); - - chomp($keyname); - print " * $zone: neuer ZSK $keyname erstellt\n"; - - open( KC, ">.keycounter" ) or die "$zpf/keycounter: $!\n"; - print KC "0"; - close(KC); - - &kill_useless_keys($zone); - &key_to_zonefile($zone); - push @new_serial, $zone; - } -} - -sub key_to_zonefile { - # die funktion fugt alle schluessel in eine zonedatei - our $master_dir; - my $zone = $_[0]; - my $zpf = "$master_dir/$zone"; - my @old_content; - my @new_content = (); - - open(ZONEFILE, "<$zpf/$zone"); - @old_content = ; - close(ZONEFILE); - - for (@old_content) { - unless (m#INCLUDE.*key#) { push @new_content, $_; } - } - - for (<$zpf/*>) { - if (m#(.*\/)(K.*\.key)#) { - push @new_content, "\$INCLUDE \"$2\"\n"; - } - } - open( ZONEFILE, ">$zpf/$zone" ) or die "$zpf/$zone: $!\n"; - print ZONEFILE @new_content; - close(ZONEFILE); -} - -sub kill_useless_keys { - # die funktion loescht alle schluessel die nicht in der index.zsk - # der uebergebenen zone stehen - our $master_dir; - my $zone = $_[0]; - my @keylist = (); - my $zpf = "$master_dir/$zone"; - - open (INDEX, "<$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n"; - @keylist = ; - close(INDEX); - open (INDEX, "<$zpf/.index.ksk") or die "$zpf/.index.ksk: $!\n"; - push @keylist, ; - - # kuerzt die schluessel-bezeichnung aus der indexdatei auf die id um sie - # besser vergleichen zu koennen. - for ( @keylist ) { - chomp; - s#K.*\+.*\+(.*)#$1#; - } - - # prueft alle schluesseldateien (ksk, zsk) ob sie in der jeweiligen - # indexdatei beschrieben sind. wenn nicht werden sie geloescht. - for (`ls $master_dir/$zone/K*[key,private]`) { - chomp; - my $file = $_; - my $rm_count = 1; - my $keyname; - for (@keylist) { - if ( $file =~ /$_/ ) { $rm_count = 0;} - } - if ($rm_count == 1) { - unlink "$file"; - if ($file =~ /$zpf\/(.*\.key)/ ) { - print " * $zone: Schluessel $1 entfernt \n"; - } - } - } -} - -sub end_ro { - our @end_ro_list; - our $master_dir; - our @new_serial; - my @content; - - for (@end_ro_list) { - my $zone = $_; - my $count = 0; - my @content; - my $last_key; - - open (INDEX, "<$master_dir/$zone/.index.zsk"); - @content = ; - close(INDEX); - - for (@content) { - $count++; - $last_key = $_; - } - if ($count > 1) { - open (INDEX, ">$master_dir/$zone/.index.zsk"); - print INDEX $last_key; - close (INDEX); - } - &kill_useless_keys($zone); - &key_to_zonefile($zone); - push @new_serial, $zone; - } -} - - -&read_conf; - -our %config; -our @new_serial; # liste fuer neuen serial -our @begin_ro_list; # liste mit zonen deren key-rollover beginnt -our @end_ro_list; # liste mit zonen deren key-rollover fertig ist -our $master_dir = $config{master_dir}; -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; -&changed_zone; -&sign_end; - -&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 -} - -if (@end_ro_list) { - &end_ro; # eine rollover-end-squenz -} - -if (@new_serial) { - &update_index; # index zone aktuallisieren - &update_serial; # serial aktuallisieren - &sign_zone; # zone signieren -} - -&file_entry; # bearbeitet die file-eintraege der konfigurations-datei -&mk_zone_conf; # konfiguration zusammenfuegen -&server_reload; # server neu laden