--- a/update-serial.pl Tue Dec 21 17:00:11 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,583 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-use FindBin;
-use File::Basename;
-
-sub del_double {
-
- # remove duplicate entries
- my %all;
- grep { $all{$_} = 0 } @_;
- return (keys %all);
-}
-
-sub read_conf {
-
- # read the configuration
- 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 (<CONFIG>) {
- 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 {
- # checked whether the zones in argv are managed zones and
- #inserted them into the list new_serial
- 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; # the time between the end and the new signing
- # (see external configuration)
- 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
- ## <zone>.signed-datei den zeitpunkt in $time mit dem ablaufdatum der
- ## signatur, welcher aus der datei <zone>.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 = <ZONE>;
- 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 = <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 (<SER>) {
- 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 <FROM>;
- 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 = <INDEXZONE>;
- 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 = <FILE>;
- 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 = <FILE>;
- 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 = <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>;
- $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 = <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 = <ZONEFILE>;
- 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 = <INDEX>;
- close(INDEX);
- open(INDEX, "<$zpf/.index.ksk") or die "$zpf/.index.ksk: $!\n";
- push @keylist, <INDEX>;
-
- # 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 = <INDEX>;
- 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
-
-
-
-__END__
-
-=pod
-
-=head1 TITLE
-
-update-serial
-
-=head1 SYNTAX
-
-update-serial
-
-=head1 BESCHREIBUNG
-
-=cut