dnssec-keytool.pl
changeset 46 de6761ce0d5b
parent 45 5dc44dc86f61
parent 41 3c10c45c6a59
child 51 d4e31a2d4b5c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dnssec-keytool.pl	Tue Dec 21 15:59:05 2010 +0100
@@ -0,0 +1,371 @@
+#! /usr/bin/perl
+
+use warnings;
+use strict;
+use FindBin;
+
+sub del_double {
+    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 (<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 read_argv {
+
+    # wertet argv aus oder gibt die hilfe aus
+    my $arg = shift @ARGV;
+    my $zone;
+    our $do;
+    our @zones;
+    our $master_dir;
+
+    if (!defined $arg) {
+        print " usage: dnssec-keytool <option> zone\n";
+        print "   -z  erstellt einen neuen ZSK\n";
+        print "   -k  erstellt je einen neuen ZSK und KSK\n";
+        print "   -rm loescht das Schluesselmaterial einer Zone\n";
+        print "   -c  erstellt bei existierenden ksk konfigurationsdateien\n";
+        print "       fuer die dnstools, sowie einen neuen zsk\n";
+        print "\n";
+
+        exit;
+    }
+    elsif ($arg eq "-k")  { $do = "ksk"; }
+    elsif ($arg eq "-rm") { $do = "rm"; }
+    elsif ($arg eq "-c")  { $do = "ck"; }
+    elsif ($arg eq "-z")  { $do = "zsk"; }
+    else {
+        print "keine gueltige Option.\n";
+        exit;
+    }
+
+    # prueft die zonen in argv ob es verwaltete zonen sind
+    for (@ARGV) {
+        chomp($zone = `idn --quiet "$_"`);
+        if (-e "$master_dir/$zone/$zone") {
+            push @zones, $zone;
+        }
+    }
+}
+
+sub rm_keys {
+    # loescht alle schluessel wenn -rm uebergeben wurde
+    our @zones;
+    our $master_dir;
+    my $zone;
+    my @new_zone_content;
+    my @old_zone_content;
+
+    for (@zones) {
+        $zone = $_;
+
+        my $zpf = "$master_dir/$zone";
+        my $ep  = 0;
+
+        if (-e "$zpf/$zone.signed") {
+            unlink "$zpf/$zone.signed" and $ep = 1;
+        }
+        if (-e "$zpf/.keycounter") {
+            unlink "$zpf/.keycounter" and $ep = 1;
+        }
+        if (-e "$zpf/.index.ksk") {
+            unlink "$zpf/.index.ksk" and $ep = 1;
+        }
+        if (-e "$zpf/.index.zsk") {
+            unlink "$zpf/.index.zsk" and $ep = 1;
+        }
+        if (-e "$zpf/dsset-$zone.") {
+            unlink "$zpf/dsset-$zone." and $ep = 1;
+        }
+        if (-e "$zpf/keyset-$zone.") {
+            unlink "$zpf/keyset-$zone." and $ep = 1;
+        }
+
+        for (glob("$zpf/K$zone*")) { 
+            chomp($_);
+            unlink ("$_");
+        }
+
+        if ($ep == 1) {
+            print " * $zone: schluesselmaterial entfernt\n";
+        }
+
+        open(ZONE, "$zpf/$zone")
+          or die "$zpf/$zone: $!\n";
+        @old_zone_content = <ZONE>;
+        close(ZONE);
+
+        for (@old_zone_content) {
+            unless (m#\$INCLUDE.*\"K$zone.*\.key\"#) {
+                push @new_zone_content, $_;
+            }
+        }
+
+        open(ZONE, ">$zpf/$zone") or die "$zpf/$zone: $!\n";
+        print ZONE @new_zone_content;
+        close(ZONE);
+    }
+}
+
+sub creat_ksk {
+    our @zones;
+    our $master_dir;
+    my @index;
+    my $zone;
+    my $keyname;
+    my $zpf;
+
+    for (@zones) {
+        $zone = $_;
+        $zpf  = "$master_dir/$zone";
+
+        chdir "$zpf" or die "$zpf: $!\n";
+        $keyname = `dnssec-keygen -a RSASHA1 -b 2048 -f KSK -n ZONE $zone`;
+
+        unless (-f ".index.ksk") { @index = (); }
+        else {
+            open(INDEX, ".index.ksk") or die "$zpf/.index.ksk: $!\n";
+            @index = <INDEX>;
+            close(INDEX);
+        }
+
+        push @index, $keyname;
+        if (@index > 2) { shift(@index); }
+
+        open(INDEX, ">.index.ksk") or die "$zpf/.index.ksk: $!\n";
+        print INDEX @index;
+        close(INDEX);
+
+        chomp($keyname);
+        print " * $zone: neuer KSK $keyname\n";
+
+        print "!! DER KSK muss veroeffentlicht werden !! \n";
+
+    }
+}
+
+sub creat_zsk {
+    our @zones;
+    our $master_dir;
+    my @index;
+    my $zone;
+    my $keyname;
+    my $zpf;
+
+    for (@zones) {
+        $zone = $_;
+        $zpf  = "$master_dir/$zone";
+
+        chdir "$zpf" or die "$zpf: $!\n";
+        $keyname = `dnssec-keygen -a RSASHA1 -b 512 -n ZONE $zone`;
+
+        unless (-f ".index.zsk") { @index = (); }
+        else {
+            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\n";
+
+        open(KC, ">.keycounter") or die "$zpf/keycounter: $!\n";
+        print KC "0";
+        close(KC);
+
+    }
+}
+
+sub ck_zone {
+    our @zones;
+    our $master_dir;
+    my $zone;
+
+    for (@zones) {
+        $zone = $_;
+        my $zpf = "$master_dir/$zone";
+        my $keyfile;
+        my @content;
+        my @keylist;
+
+        for (<$zpf/*>) {
+            if (m#(K$zone.*\.key)#) {
+                $keyfile = $1;
+                open(KEYFILE, "<$zpf/$keyfile");
+                @content = <KEYFILE>;
+                close(KEYFILE);
+                for (@content) {
+                    if (m#DNSKEY.257#) {
+                        push @keylist, $keyfile;
+                    }
+                }
+            }
+        }
+
+        open(INDEX, ">.index.ksk") or die "$zpf/.index.ksk: $!\n";
+        for (@keylist) {
+            s#\.key##;
+            print INDEX "$_\n";
+        }
+        close(INDEX);
+
+        print " * $zone: neue .index.ksk erzeugt\n";
+
+        if (-f "$zpf/.index.zsk") {
+            unlink("$zpf/.index.zsk") or die "$zpf/.index.zsk: $!\n";
+        }
+    }
+}
+
+sub post_creat {
+    our @zones;
+    our $master_dir;
+
+    for (@zones) {
+        my $zone = $_;
+        `touch $master_dir/$zone/$zone`;
+
+        &kill_useless_keys($zone);
+        &key_to_zonefile($zone);
+    }
+
+}
+
+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 ( glob("$master_dir/$zone/K*") {
+        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 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);
+}
+
+&read_conf;
+
+our %config;
+our $do;       # arbeitsschritte aus argv
+our @zones;    # liste der zonen in argv
+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};
+
+&read_argv;
+
+unless (@zones) { exit; }    # beendet das programm, wurden keine
+                             # gueltigen zonen uebergeben
+
+if ($do eq "rm") { &rm_keys; exit; }
+if ($do eq "ck") { &ck_zone; }
+if ($do eq "ksk") { &creat_ksk; }
+
+&creat_zsk;
+&post_creat;
+
+__END__
+
+=pod
+
+=head1 TITLE
+
+dnssec-keytool
+
+=head1 SYNTAX
+
+dnssec-keytool <option> zone
+
+=head1 BESCHREIBUNG