diff --git a/install/tpl/server.ini.master b/install/tpl/server.ini.master index 7c371a217168daccacdedd378f76b4b532367bb6..521e418f6c6be9f635b5954f291ae79cf97e9699 100644 --- a/install/tpl/server.ini.master +++ b/install/tpl/server.ini.master @@ -140,6 +140,7 @@ php_fpm_default_chroot=n bind_user=root bind_group=bind bind_zonefiles_dir=/etc/bind +bind_keyfiles_dir=/etc/bind named_conf_path=/etc/bind/named.conf named_conf_local_path=/etc/bind/named.conf.local disable_bind_log=n diff --git a/interface/web/admin/form/server_config.tform.php b/interface/web/admin/form/server_config.tform.php index bede61a3ddde653c85f7581940b2cb19a31c25ff..679ebb2b7fae5ddcff4706d56bd391b3142f7bb3 100644 --- a/interface/web/admin/form/server_config.tform.php +++ b/interface/web/admin/form/server_config.tform.php @@ -1652,6 +1652,20 @@ $form["tabs"]['dns'] = array( 'width' => '40', 'maxlength' => '255' ), + 'bind_keyfiles_dir' => array( + 'datatype' => 'VARCHAR', + 'formtype' => 'TEXT', + 'default' => '', + 'validators' => array( 0 => array('type' => 'NOTEMPTY', + 'errmsg' => 'bind_keyfiles_dir_error_empty'), + 1 => array ( 'type' => 'REGEX', + 'regex' => '/^\/[a-zA-Z0-9\.\-\_\/]{1,128}$/', + 'errmsg'=> 'bind_keyfiles_dir_error_regex'), + ), + 'value' => '', + 'width' => '40', + 'maxlength' => '255' + ), 'named_conf_path' => array( 'datatype' => 'VARCHAR', 'formtype' => 'TEXT', diff --git a/interface/web/admin/lib/lang/en_server_config.lng b/interface/web/admin/lib/lang/en_server_config.lng index 748e4c6d581bd9c9533e5c7d00fe4bcad3ec75c7..363f528fba2d713e819e112578797a15b7c1b782 100644 --- a/interface/web/admin/lib/lang/en_server_config.lng +++ b/interface/web/admin/lib/lang/en_server_config.lng @@ -91,10 +91,12 @@ $wb['apps_vhost_servername_txt'] = 'Apps-vhost Domain'; $wb['bind_user_txt'] = 'BIND User'; $wb['bind_group_txt'] = 'BIND Group'; $wb['bind_zonefiles_dir_txt'] = 'BIND zonefiles directory'; +$wb['bind_keyfiles_dir_txt'] = 'BIND keyfiles directory'; $wb['named_conf_path_txt'] = 'BIND named.conf path'; $wb['bind_user_error_empty'] = 'BIND user is empty.'; $wb['bind_group_error_empty'] = 'BIND group is empty.'; $wb['bind_zonefiles_dir_error_empty'] = 'BIND zonefiles directory is empty.'; +$wb['bind_keyfiles_dir_error_empty'] = 'BIND keyfiles directory is empty.'; $wb['named_conf_path_error_empty'] = 'BIND named.conf path is empty.'; $wb['named_conf_local_path_error_empty'] = 'BIND named.conf.local path is empty.'; $wb['mail_filter_syntax_txt'] = 'Mailfilter Syntax'; @@ -281,6 +283,7 @@ $wb['awstats_buildstaticpages_pl_error_regex'] = 'Invalid awstats_buildstaticpag $wb['invalid_bind_user_txt'] = 'Invalid BIND user.'; $wb['invalid_bind_group_txt'] = 'Invalid BIND group.'; $wb['bind_zonefiles_dir_error_regex'] = 'Invalid BIND zonefiles directory.'; +$wb['bind_keyfiles_dir_error_regex'] = 'Invalid BIND keyfiles directory.'; $wb['named_conf_path_error_regex'] = 'Invalid named.conf path.'; $wb['named_conf_local_path_error_regex'] = 'Invalid named.conf.local path.'; $wb['fastcgi_starter_path_error_regex'] = 'Invalid fastcgi starter path.'; diff --git a/interface/web/admin/templates/server_config_dns_edit.htm b/interface/web/admin/templates/server_config_dns_edit.htm index 995acbf98651c2557ff0f2fb055a420f3f11aaf5..dcc7328e2c10cb4241ac8ff55a046ffbf3c3a6c2 100644 --- a/interface/web/admin/templates/server_config_dns_edit.htm +++ b/interface/web/admin/templates/server_config_dns_edit.htm @@ -11,6 +11,9 @@ <div class="form-group"> <label for="bind_zonefiles_dir" class="col-sm-3 control-label">{tmpl_var name='bind_zonefiles_dir_txt'}</label> <div class="col-sm-9"><input type="text" name="bind_zonefiles_dir" id="bind_zonefiles_dir" value="{tmpl_var name='bind_zonefiles_dir'}" class="form-control" /></div></div> + <div class="form-group"> + <label for="bind_keyfiles_dir" class="col-sm-3 control-label">{tmpl_var name='bind_keyfiles_dir_txt'}</label> + <div class="col-sm-9"><input type="text" name="bind_keyfiles_dir" id="bind_keyfiles_dir" value="{tmpl_var name='bind_keyfiles_dir'}" class="form-control" /></div></div> <div class="form-group"> <label for="named_conf_path" class="col-sm-3 control-label">{tmpl_var name='named_conf_path_txt'}</label> <div class="col-sm-9"><input type="text" name="named_conf_path" id="named_conf_path" value="{tmpl_var name='named_conf_path'}" class="form-control" /></div></div> diff --git a/server/plugins-available/bind_plugin.inc.php b/server/plugins-available/bind_plugin.inc.php index 2deabc7e23a71f29f7747b313f72a70f529d1d7c..d341ff2e3b8d83f1b35cb5cca2d389cec52a0217 100644 --- a/server/plugins-available/bind_plugin.inc.php +++ b/server/plugins-available/bind_plugin.inc.php @@ -98,11 +98,11 @@ class bind_plugin { //* Verify that we do not already have keys (overwriting-protection) if($data['old']['dnssec_algo'] == $data['new']['dnssec_algo']) { - if (file_exists($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.')) { + if (file_exists($dns_config['bind_keyfiles_dir'].'/dsset-'.$domain.'.')) { return $this->soa_dnssec_update($data); } else if ($data['new']['dnssec_initialized'] == 'Y') { //In case that we generated keys but the dsset-file was not generated $keycount=0; - foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'*.key') as $keyfile) { + foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'*.key') as $keyfile) { $keycount++; } if ($keycount > 0) { @@ -116,11 +116,11 @@ class bind_plugin { $dnssec_algo = explode(',',$data['new']['dnssec_algo']); //* Create the Zone Signing and Key Signing Keys - if(in_array('ECDSAP256SHA256',$dnssec_algo) && count(glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+013*.key')) == 0) { - $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); + if(in_array('ECDSAP256SHA256',$dnssec_algo) && count(glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+013*.key')) == 0) { + $app->system->exec_safe('cd ?; dnssec-keygen -3 -a ECDSAP256SHA256 -n ZONE ?; dnssec-keygen -f KSK -3 -a ECDSAP256SHA256 -n ZONE ?', $dns_config['bind_keyfiles_dir'], $domain, $domain); } - if(in_array('NSEC3RSASHA1',$dnssec_algo) && count(glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+007*.key')) == 0) { - $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); + if(in_array('NSEC3RSASHA1',$dnssec_algo) && count(glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+007*.key')) == 0) { + $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_keyfiles_dir'], $domain, $domain); } $this->soa_dnssec_sign($data); //Now sign the zone for the first time @@ -149,8 +149,8 @@ class bind_plugin { //* Include ECDSAP256SHA256 keys in zone if(in_array('ECDSAP256SHA256',$dnssec_algo)) { - foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+013*.key') as $keyfile) { - $includeline = '$INCLUDE '.basename($keyfile); + foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+013*.key') as $keyfile) { + $includeline = '$INCLUDE ' . $keyfile; if (!preg_match('@'.preg_quote($includeline).'@', $zonefile)) $zonefile .= "\n".$includeline."\n"; $keycount++; } @@ -158,8 +158,8 @@ class bind_plugin { //* Include NSEC3RSASHA1 keys in zone if(in_array('NSEC3RSASHA1',$dnssec_algo)) { - foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+007*.key') as $keyfile) { - $includeline = '$INCLUDE '.basename($keyfile); + foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+007*.key') as $keyfile) { + $includeline = '$INCLUDE ' . $keyfile; if (!preg_match('@'.preg_quote($includeline).'@', $zonefile)) $zonefile .= "\n".$includeline."\n"; $keycount++; } @@ -171,20 +171,20 @@ class bind_plugin { file_put_contents($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain, $zonefile); //* Sign the zone and set it valid for max. 16 days - $app->system->exec_safe('cd ?; dnssec-signzone -A -e +1382400 -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N increment -o ? -t ?', $dns_config['bind_zonefiles_dir'], $domain, $filespre.$domain); + $app->system->exec_safe('cd ?; dnssec-signzone -A -e +1382400 -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N increment -o ? -K ? -t ?', $dns_config['bind_zonefiles_dir'], $domain, $dns_config['bind_keyfiles_dir'], $dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain); //* Write Data back ino DB - $dnssecdata = "DS-Records:\n".file_get_contents($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.'); + $dnssecdata = "DS-Records:\n".file_get_contents($dns_config['bind_keyfiles_dir'].'/dsset-'.$domain.'.'); $dnssecdata .= "\n------------------------------------\n\nDNSKEY-Records:\n"; if(in_array('ECDSAP256SHA256',$dnssec_algo)) { - foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+013*.key') as $keyfile) { + foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+013*.key') as $keyfile) { $dnssecdata .= file_get_contents($keyfile)."\n\n"; } } if(in_array('NSEC3RSASHA1',$dnssec_algo)) { - foreach (glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+007*.key') as $keyfile) { + foreach (glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+007*.key') as $keyfile) { $dnssecdata .= file_get_contents($keyfile)."\n\n"; } } @@ -213,7 +213,7 @@ class bind_plugin { return false; } - if (!$new && !file_exists($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.')) $this->soa_dnssec_create($data); + if (!$new && !file_exists($dns_config['bind_keyfiles_dir'].'/dsset-'.$domain.'.')) $this->soa_dnssec_create($data); $dbdata = $app->db->queryOneRecord('SELECT id,serial FROM dns_soa WHERE id=?', intval($data['new']['id'])); $app->system->exec_safe('cd ?; named-checkzone ? ? | egrep -ho \'[0-9]{10}\'', $dns_config['bind_zonefiles_dir'], $domain, $dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain); @@ -237,12 +237,12 @@ class bind_plugin { $domain = substr($data['new']['origin'], 0, strlen($data['new']['origin'])-1); - $key_files = glob($dns_config['bind_zonefiles_dir'].'/K'.$domain.'.+*'); + $key_files = glob($dns_config['bind_keyfiles_dir'].'/K'.$domain.'.+*'); foreach($key_files as $file) { unlink($file); } unlink($dns_config['bind_zonefiles_dir'].'/'.$this->zone_file_prefix().$domain.'.signed'); - unlink($dns_config['bind_zonefiles_dir'].'/dsset-'.$domain.'.'); + unlink($dns_config['bind_keyfiles_dir'].'/dsset-'.$domain.'.'); if ($app->dbmaster !== $app->db) $app->dbmaster->query('UPDATE dns_soa SET dnssec_info=\'\', dnssec_initialized=\'N\' WHERE id=?', intval($data['new']['id'])); $app->db->query('UPDATE dns_soa SET dnssec_info=\'\', dnssec_initialized=\'N\' WHERE id=?', intval($data['new']['id']));