From 6b43c981b88b27ad244af16b8d9bdbb339bb5193 Mon Sep 17 00:00:00 2001 From: Jamie Cameron Date: Sat, 23 Apr 2022 18:23:17 -0700 Subject: [PATCH] Preserve key files when disabling DNSSEC --- bind8/bind8-lib.pl | 87 ++++++++++++++++++++++++++------------- bind8/delete_zone.cgi | 2 +- bind8/disable_zonekey.cgi | 2 +- bind8/enable_zonekey.cgi | 2 +- bind8/mass_delete.cgi | 2 +- 5 files changed, 62 insertions(+), 33 deletions(-) diff --git a/bind8/bind8-lib.pl b/bind8/bind8-lib.pl index 7f8845912..845a195c9 100755 --- a/bind8/bind8-lib.pl +++ b/bind8/bind8-lib.pl @@ -2843,7 +2843,7 @@ foreach my $slave (@slaves) { if ($config{'extra_slaves'}) { push(@otherslaves, grep { $_ ne '' } - map { &to_ipaddress($_) + map { &to_ipaddress($_) } split(/\s+/, $config{'extra_slaves'})); } if ($moreslaves) { @@ -3330,29 +3330,48 @@ else { $zonesize = $size; } -# Create the zone key -my $out = &backquote_logged( - "cd ".quotemeta($fn)." && ". - "$config{'keygen'} -a ".quotemeta($alg)." -b ".quotemeta($zonesize). - " -n ZONE $rand_flag $dom 2>&1"); -if ($?) { - kill('KILL', $pid) if ($pid); - return $out; - } - -# Create the key signing key, if needed -if (!$single) { - $out = &backquote_logged( - "cd ".quotemeta($fn)." && ". - "$config{'keygen'} -a ".quotemeta($alg)." -b ".quotemeta($size). - " -n ZONE -f KSK $rand_flag $dom 2>&1"); - kill('KILL', $pid) if ($pid); - if ($?) { - return $out; +# Check if there are saved keys, and if so use them +my @savedkeys = grep { $_->{'saved'} } &get_dnssec_key($z, 1); +my $out; +if (@savedkeys) { + # Rename back the saved key files + foreach my $key (@savedkeys) { + foreach my $f ('publicfile', 'privatefile') { + if (ref($key) && $key->{$f} && $key->{'saved'}) { + my $origfile = $key->{$f}; + $origfile =~ s/\.saved$//; + &rename_file($key->{$f}, $origfile); + } + } } } else { - kill('KILL', $pid) if ($pid); + # Create the zone key + $out = &backquote_logged( + "cd ".quotemeta($fn)." && ". + "$config{'keygen'} -a ".quotemeta($alg). + " -b ".quotemeta($zonesize). + " -n ZONE $rand_flag $dom 2>&1"); + if ($?) { + kill('KILL', $pid) if ($pid); + return $out; + } + + # Create the key signing key, if needed + if (!$single) { + $out = &backquote_logged( + "cd ".quotemeta($fn)." && ". + "$config{'keygen'} -a ".quotemeta($alg). + " -b ".quotemeta($size). + " -n ZONE -f KSK $rand_flag $dom 2>&1"); + kill('KILL', $pid) if ($pid); + if ($?) { + return $out; + } + } + else { + kill('KILL', $pid) if ($pid); + } } # Get the new keys @@ -3458,20 +3477,27 @@ return "Re-signing failed : $err" if ($err); return undef; } -# delete_dnssec_key(&zone|&zone-name) +# delete_dnssec_key(&zone|&zone-name, [save-key]) # Deletes the key for a zone, and all DNSSEC records sub delete_dnssec_key { -my ($z) = @_; +my ($z, $savekey) = @_; my $fn = &get_zone_file($z); $fn || return "Could not work out records file!"; my $dom = $z->{'members'} ? $z->{'values'}->[0] : $z->{'name'}; # Remove the key -my @keys = &get_dnssec_key($z); +my @keys = &get_dnssec_key($z, 1); foreach my $key (@keys) { foreach my $f ('publicfile', 'privatefile') { - &unlink_file($key->{$f}) if (ref($key) && $key->{$f}); + if (ref($key) && $key->{$f}) { + if ($savekey && !$key->{'saved'}) { + &rename_file($key->{$f}, $key->{$f}.".saved"); + } + else { + &unlink_file($key->{$f}); + } + } } } @@ -3616,19 +3642,20 @@ if ($keyrec) { } } -# get_dnssec_key(&zone|&zone-name) +# get_dnssec_key(&zone|&zone-name, [include-saved]) # Returns a list of hashes containing details of a zone's keys, or an error # message. The KSK is always returned first. sub get_dnssec_key { -my ($z) = @_; +my ($z, $saved) = @_; my $dir = &get_keys_dir($z); my $dom = $z->{'members'} ? $z->{'values'}->[0] : $z->{'name'}; my %keymap; opendir(ZONEDIR, $dir); foreach my $f (readdir(ZONEDIR)) { - if ($f =~ /^K\Q$dom\E\.\+(\d+)\+(\d+)\.key$/) { + if ($f =~ /^K\Q$dom\E\.\+(\d+)\+(\d+)\.key(\.saved)?$/) { # Found the public key file .. read it + next if ($3 && !$saved); $keymap{$2} ||= { }; my $rv = $keymap{$2}; $rv->{'publicfile'} = "$dir/$f"; @@ -3649,9 +3676,11 @@ foreach my $f (readdir(ZONEDIR)) { $rv->{'publictext'} = &read_file_contents("$dir/$f"); while($rv->{'publictext'} =~ s/^;.*\r?\n//) { }; $rv->{'publictext'} = format_dnssec_public_key($rv->{'publictext'}); + $rv->{'saved'} = $3 ? 1 : 0; } - elsif ($f =~ /^K\Q$dom\E\.\+(\d+)\+(\d+)\.private$/) { + elsif ($f =~ /^K\Q$dom\E\.\+(\d+)\+(\d+)\.private(\.saved)?$/) { # Found the private key file + next if ($3 && !$saved); $keymap{$2} ||= { }; my $rv = $keymap{$2}; $rv->{'privatefile'} = "$dir/$f"; diff --git a/bind8/delete_zone.cgi b/bind8/delete_zone.cgi index 44416a9f9..6ec0fd5ce 100755 --- a/bind8/delete_zone.cgi +++ b/bind8/delete_zone.cgi @@ -126,7 +126,7 @@ if ($f && $type ne 'hint') { } # delete any keys -&delete_dnssec_key($zconf); +&delete_dnssec_key($zconf, 0); # delete all dnssec-tools related state &dt_delete_dnssec_state($zconf); diff --git a/bind8/disable_zonekey.cgi b/bind8/disable_zonekey.cgi index 920b81222..3509ed583 100755 --- a/bind8/disable_zonekey.cgi +++ b/bind8/disable_zonekey.cgi @@ -22,7 +22,7 @@ if ($key) { foreach my $k (@keyfiles) { &lock_file($k); } -&delete_dnssec_key($zone); +&delete_dnssec_key($zone, 1); foreach my $k (@keyfiles) { &unlock_file($k); } diff --git a/bind8/enable_zonekey.cgi b/bind8/enable_zonekey.cgi index f15bd5fab..d07437dfd 100755 --- a/bind8/enable_zonekey.cgi +++ b/bind8/enable_zonekey.cgi @@ -15,7 +15,7 @@ my $desc = &ip6int_to_net(&arpa_to_ip($dom)); # Validate inputs and compute size my ($ok, $size) = &compute_dnssec_key_size($in{'alg'}, $in{'size_def'}, - $in{'size'}); + $in{'size'}); &error($size) if (!$ok); &ui_print_unbuffered_header($desc, $text{'zonekey_title'}, "", diff --git a/bind8/mass_delete.cgi b/bind8/mass_delete.cgi index d00646333..dc6595daa 100755 --- a/bind8/mass_delete.cgi +++ b/bind8/mass_delete.cgi @@ -93,7 +93,7 @@ else { } # delete any keys - &delete_dnssec_key($zconf); + &delete_dnssec_key($zconf, 0); # remove the zone directive &lock_file(&make_chroot($zconf->{'file'}));