From 6863f325eaf2ee7c0a9e184ef3809d4a9e472630 Mon Sep 17 00:00:00 2001
From: Till Brehm <tbrehm@ispconfig.org>
Date: Mon, 10 Aug 2020 18:00:39 +0200
Subject: [PATCH] Reimplemented DNSSEC signing.

---
 .../sql/incremental/upd_dev_collection.sql    |  6 +++---
 install/sql/ispconfig3.sql                    |  2 +-
 interface/web/dns/dns_soa_edit.php            |  2 ++
 interface/web/dns/dns_wizard.php              |  2 +-
 interface/web/dns/form/dns_soa.tform.php      |  7 ++++---
 server/plugins-available/bind_plugin.inc.php  | 19 ++++++++++++++-----
 6 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/install/sql/incremental/upd_dev_collection.sql b/install/sql/incremental/upd_dev_collection.sql
index 3f03599e95..d42874095b 100644
--- a/install/sql/incremental/upd_dev_collection.sql
+++ b/install/sql/incremental/upd_dev_collection.sql
@@ -66,6 +66,6 @@ ALTER TABLE `client` CHANGE `id_rsa` `id_rsa` TEXT CHARACTER SET utf8 COLLATE ut
 ALTER TABLE `directive_snippets` ADD `update_sites` ENUM('y','n') NOT NULL DEFAULT 'n' ;
 
 -- Add DNSSEC Algorithm setting
-ALTER TABLE `dns_soa` ADD `dnssec_algo` ENUM('sha1','sha256') NULL DEFAULT NULL AFTER `dnssec_wanted`;
-UPDATE `dns_soa` SET `dnssec_algo` = 'sha1' WHERE `dnssec_algo` IS NULL;
-ALTER TABLE `dns_soa` CHANGE `dnssec_algo` `dnssec_algo` ENUM('sha1','sha256') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'sha256';
+ALTER TABLE `dns_soa` ADD `dnssec_algo` SET('NSEC3RSASHA1','ECDSAP256SHA256') NULL DEFAULT NULL AFTER `dnssec_wanted`;
+UPDATE `dns_soa` SET `dnssec_algo` = 'NSEC3RSASHA1' WHERE `dnssec_algo` IS NULL;
+ALTER TABLE `dns_soa` CHANGE `dnssec_algo` `dnssec_algo` SET('NSEC3RSASHA1','ECDSAP256SHA256') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'ECDSAP256SHA256';
diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql
index 76e9f152bd..aac7f1b784 100644
--- a/install/sql/ispconfig3.sql
+++ b/install/sql/ispconfig3.sql
@@ -626,7 +626,7 @@ CREATE TABLE `dns_soa` (
   `update_acl` varchar(255) default NULL,
   `dnssec_initialized` ENUM('Y','N') NOT NULL DEFAULT 'N',
   `dnssec_wanted` ENUM('Y','N') NOT NULL DEFAULT 'N',
-  `dnssec_algo` ENUM('sha1','sha256') NOT NULL DEFAULT 'sha256',
+  `dnssec_algo` SET('NSEC3RSASHA1','ECDSAP256SHA256') NOT NULL DEFAULT 'ECDSAP256SHA256',
   `dnssec_last_signed` BIGINT NOT NULL DEFAULT '0',
   `dnssec_info` TEXT NULL,
   PRIMARY KEY  (`id`),
diff --git a/interface/web/dns/dns_soa_edit.php b/interface/web/dns/dns_soa_edit.php
index ec5ba67c79..f5e716ca5d 100644
--- a/interface/web/dns/dns_soa_edit.php
+++ b/interface/web/dns/dns_soa_edit.php
@@ -296,6 +296,8 @@ function onSubmit() {
 
 		$this->dataRecord["xfer"] = preg_replace('/\s+/', '', $this->dataRecord["xfer"]);
 		$this->dataRecord["also_notify"] = preg_replace('/\s+/', '', $this->dataRecord["also_notify"]);
+		
+		if(isset($this->dataRecord['dnssec_wanted']) && $this->dataRecord['dnssec_wanted'] == 'Y' && $this->dataRecord['dnssec_algo'] == '') $this->dataRecord['dnssec_algo'] = 'ECDSAP256SHA256';
 
 		//* Check if a secondary zone with the same name already exists
 		$tmp = $app->db->queryOneRecord("SELECT count(id) as number FROM dns_slave WHERE origin = ? AND server_id = ?", $this->dataRecord["origin"], $this->dataRecord["server_id"]);
diff --git a/interface/web/dns/dns_wizard.php b/interface/web/dns/dns_wizard.php
index 121d3c81c3..b2320dc6bf 100644
--- a/interface/web/dns/dns_wizard.php
+++ b/interface/web/dns/dns_wizard.php
@@ -339,7 +339,7 @@ if($_POST['create'] == 1) {
 	$section = '';
 	$vars = array();
 	$vars['xfer']='';
-	$vars['dnssec_algo']='sha256';
+	$vars['dnssec_algo']='ECDSAP256SHA256';
 	$dns_rr = array();
 	foreach($tpl_rows as $row) {
 		$row = trim($row);
diff --git a/interface/web/dns/form/dns_soa.tform.php b/interface/web/dns/form/dns_soa.tform.php
index 3d86e07f37..81389c4553 100644
--- a/interface/web/dns/form/dns_soa.tform.php
+++ b/interface/web/dns/form/dns_soa.tform.php
@@ -278,9 +278,10 @@ $form["tabs"]['dns_soa'] = array (
 		),
 		'dnssec_algo' => array (
 			'datatype' => 'VARCHAR',
-			'formtype' => 'SELECT',
-			'default' => 'sha256',
-			'value'  => array('sha1' => 'SHA1','sha256' => 'SHA256'),
+			'formtype' => 'CHECKBOXARRAY',
+			'separator' => ',',
+			'default' => 'ECDSAP256SHA256',
+			'value'  => array('NSEC3RSASHA1' => '7 (NSEC3RSASHA1)','ECDSAP256SHA256' => '13 (ECDSAP256SHA256)'),
 			'width'  => '30',
 			'maxlength' => '255'
 		),
diff --git a/server/plugins-available/bind_plugin.inc.php b/server/plugins-available/bind_plugin.inc.php
index 20eeb28ad7..a0668e4f1c 100644
--- a/server/plugins-available/bind_plugin.inc.php
+++ b/server/plugins-available/bind_plugin.inc.php
@@ -110,10 +110,14 @@ class bind_plugin {
 			}
 		}
 		
+		// Get DNSSEC Algorithms
+		$dnssec_algo = explode(',',$data['new']['dnssec_algo']);
+		
 		//Do some magic...
-		if($data['new']['dnssec_algo'] == 'sha256') {
+		if(in_array('ECDSAP256SHA256',$dnssec_algo)) {
 			$app->system->exec_safe('cd ?; dnssec-keygen -3 -a ECDSAP256SHA256 -n ZONE ?; dnssec-keygen -f KSK -3 -a ECDSAP256SHA256 -n ZONE ?', $dns_config['bind_zonefiles_dir'], $domain, $domain);
-		} else {
+		}
+		if(in_array('NSEC3RSASHA1',$dnssec_algo)) {
 			$app->system->exec_safe('cd ?; dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE ?; dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE ?', $dns_config['bind_zonefiles_dir'], $domain, $domain);
 		}
 
@@ -141,7 +145,10 @@ class bind_plugin {
 			if (!preg_match('@'.preg_quote($includeline).'@', $zonefile)) $zonefile .= "\n".$includeline."\n";
 			$keycount++;
 		}
-		if ($keycount != 2) $app->log('DNSSEC Warning: There are more or less than 2 keyfiles for zone '.$domain, LOGLEVEL_WARN);
+		
+		$keycount_wanted = count(explode(',',$data['new']['dnssec_algo']))*2;
+		
+		if ($keycount != $keycount_wanted) $app->log('DNSSEC Warning: There are more or less than 2 keyfiles for each algorithm for zone '.$domain, LOGLEVEL_WARN);
 		file_put_contents($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain, $zonefile);
 		
 		//Sign the zone and set it valid for max. 16 days
@@ -309,9 +316,11 @@ class bind_plugin {
 		}
 		
 		//* DNSSEC-Implementation
-		if($data['old']['origin'] != $data['new']['origin'] || $data['old']['dnssec_algo'] != $data['new']['dnssec_algo']) {			
+		if($data['old']['origin'] != $data['new']['origin']) {			
 			if (@$data['old']['dnssec_initialized'] == 'Y' && strlen(@$data['old']['origin']) > 3) $this->soa_dnssec_delete($data); //delete old keys
-			if ($data['new']['dnssec_wanted'] == 'Y') $this->soa_dnssec_create($data);	
+			if ($data['new']['dnssec_wanted'] == 'Y') $this->soa_dnssec_create($data);
+		} elseif($data['old']['dnssec_algo'] != $data['new']['dnssec_algo']) {
+			if ($data['new']['dnssec_wanted'] == 'Y') $this->soa_dnssec_create($data);
 		} elseif ($data['new']['dnssec_wanted'] == 'Y' && $data['old']['dnssec_initialized'] == 'N') {
 			$this->soa_dnssec_create($data);
 		} elseif ($data['new']['dnssec_wanted'] == 'N' && $data['old']['dnssec_initialized'] == 'Y') {	//delete old signed file if dnssec is no longer wanted
-- 
GitLab