--ksk should work now
authorMatthias Förste <foerste@schlittermann.de>
Mon, 27 Jun 2011 15:06:30 +0200
changeset 137 69856eb1e826
parent 136 43e9d618af43
child 138 046d8e631700
--ksk should work now
sbin/dnssec-keytool
--- a/sbin/dnssec-keytool	Fri Jun 10 09:12:18 2011 +0200
+++ b/sbin/dnssec-keytool	Mon Jun 27 15:06:30 2011 +0200
@@ -15,7 +15,8 @@
 
 sub rm_keys($@);
 sub check_zone($@);
-sub create_ksk($@);
+sub create_key($@);
+sub create_ksk(@);
 sub create_zsk(@);
 sub post_create($@);
 
@@ -65,9 +66,9 @@
 
     given ($cmd) {
         when ("zsk")   { exit create_zsk(@zones) };
-        #when ("ksk")   { return create_ksk(@zones) };
-        #when ("check") { return check_zone(@zones) };
-        #when ("rm")    { return rm_keys(@zones) };
+        when ("ksk")   { exit create_ksk(@zones) };
+        #when ("check") { exit check_zone(@zones) };
+        #when ("rm")    { exit rm_keys(@zones) };
 	default		{ die "not implemented\n" };
     };
 }
@@ -120,74 +121,62 @@
     }
 }
 
-sub create_ksk ($@) {
-    my ($master_dir, @zone) = @_;
-    my @index;
-    my $keyname;
+sub create_key ($@) {
 
-    for (@zone) {
-        my $zone = $_;
-        my $zpf  = "$master_dir/$zone";
-
-        $keyname =
-          `cd $zpf && dnssec-keygen -a RSASHA1 -b 2048 -f KSK -n ZONE $zone`;
+    my ($type, @zones) = @_;
+    my $master_dir = "$cf{master_dir}";
 
-        unless (-f "$zpf/.index.ksk") { @index = (); }
-        else {
-            open(INDEX, "$zpf/.index.ksk") or die "$zpf/.index.ksk: $!\n";
-            @index = <INDEX>;
-            close(INDEX);
-        }
+    my $args = {
 
-        push @index, $keyname;
-        if (@index > 2) { shift(@index); }
-
-        {
-            my $fh = File::Temp->new(DIR => "$zpf")
-              or die "Can't create tmpdir: $!\n";
-            print $fh join "" => @index, "";
-            rename($fh->filename => "$zpf/.index.ksk")
-              or die "Can't rename "
-              . $fh->filename
-              . " to $zpf/.index.ksk: $!\n";
+        ksk => {
+            cmd => 'cd %s && dnssec-keygen -a RSASHA1 -b 2048 -f KSK -n ZONE %s'
+        },
+        zsk => {
+            cmd => 'cd %s && dnssec-keygen -a RSASHA1 -b 512 -n ZONE %s'
         }
 
-        chomp($keyname);
-        print " * $zone: new KSK $keyname\n";
-        print "!! THE KSK must be published !! \n";
+    };
+
+    die "Invalid type $type" unless defined $args->{$type};
+
+    for my $zone (@zones) {
+
+        my (@index, $keyname, $idx);
+        my $dir = "$master_dir/$zone";
+        my $cmd = sprintf $args->{$type}->{cmd}, $dir, $zone;
+
+        chomp($keyname = qx/$cmd/);
+        die "Key generation failed! (output was: '$keyname')" unless $keyname =~ /^K\Q$zone\E\.?\+\d{3}\+\d{5}$/;
+
+        open $idx, '+>>', "$dir/.index.$type" or die "Can't open $dir/.index.$type: $!\n";
+        seek $idx, 0 ,0 or die "Cant' seek: $!";
+        chomp (@index = <$idx>);
+
+        push @index, $keyname;
+        # TODO: this should be part of the key removal procedure, no?
+        # shift @index if @index > 2;
+
+        seek $idx, 0 ,0 or die "Cant' seek: $!";
+        truncate $idx, 0 or die "Can't truncate: $!";
+        print $idx join "\n" => @index, '';
+        close $idx;
+
+        say "$zone: new ", uc $type, " $keyname";
+
+        key_to_zonefile($keyname);
+
+        if (lc $type eq 'zsk') {
+            open my $kc, '>', "$dir/.keycounter" or die "Can't open $dir/.keycounter: $!\n";
+            print $kc "0\n";
+            close $kc;
+        }
 
     }
+
 }
 
-sub create_zsk (@) {
-    my @zones = @_;
-
-    my $keyname;
-
-    foreach my $zone (@zones) {
-        my $dir  = "$cf{master_dir}/$zone";
-
-        chomp($keyname = `cd $dir && dnssec-keygen -a RSASHA1 -b 512 -n ZONE $zone`);
-
-	my @index;
-	open(my $idx, "+>>", "$dir/.index.zsk") or die "Can't open $dir/.index.zsk: $!\n";
-	seek($idx, 0, 0);
-	chomp(@index = <$idx>);
-
-        push @index, $keyname;
-	shift @index if @index > 2;
-
-	truncate($idx, 0);
-	print $idx join "\n" => @index, "";
-	close($idx);
-
-        say "$zone: new ZSK $keyname";
-
-        open(my $kc, ">", "$dir/.keycounter") or die "$dir/.keycounter: $!\n";
-        print $kc "0\n";
-        close($kc);
-    }
-}
+sub create_ksk (@) { return create_key 'ksk', @_; }
+sub create_zsk (@) { return create_key 'zsk', @_; }
 
 sub check_zone ($@) {
     my ($master_dir, @zone) = @_;
@@ -279,31 +268,26 @@
     }
 }
 
-sub key_to_zonefile ($@) {
+sub key_to_zonefile (@) {
 
-    # the function added all keys to the indexfile
-    my $zone       = $_[0];
-    my $master_dir = $_[1];
-    my $zpf        = "$master_dir/$zone";
-    my @old_content;
-    my @new_content = ();
-
-    open(ZONEFILE, "<$zpf/$zone");
-    @old_content = <ZONEFILE>;
-    close(ZONEFILE);
+    (my ($keyname) = @_);
+    $keyname =~ /^K(.*)\.\+\d{3}\+\d{5}$/;
+    my $zone = $1 or die "Can't determine zone from key name '$keyname'\n";
+    my $zf = "$cf{master_dir}/$zone/$zone";
+    my (@lines, $tmp);
 
-    for (@old_content) {
-        unless (m#INCLUDE.*key#) { push @new_content, $_; }
-    }
+    open OLD, '<', $zf or die "Can't open $zf: $!\n";
+    chomp (@lines = <OLD>);
+    close OLD;
+
+    return if grep /^\s*\$include\s+("?)\Q$keyname\E\.key\1$/i, @lines;
 
-    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);
+    $tmp = File::Temp->new(UNLINK => 0) or die "Can't create temporary file\n";
+    print $tmp join "\n", @lines, qq(\$INCLUDE "$keyname.key"\n);
+    close $tmp;
+
+    rename $tmp => $zf or die "Can't rename '$tmp' => '$zf': $!";
+
 }
 
 __END__
@@ -328,11 +312,11 @@
 
 =item B<--zsk> 
 
-Create a new ZSK for the zones.
+Create a new ZSK for the zones and include the DNSKEY record for it in the respective zone.
 
 =item B<--ksk>
 
-Create a new KSK for the zones.
+Create a new KSK for the zones and include the DNSKEY record for it in the respective zone.
 
 =item B<--rm>