diff --git a/install/sql/incremental/upd_dev_collection.sql b/install/sql/incremental/upd_dev_collection.sql index 71f702ebf81c68ad349e7ba993aa312c8d8f08f3..f0254216d538d2b02d8ee8f056e5c102d2a7cc75 100644 --- a/install/sql/incremental/upd_dev_collection.sql +++ b/install/sql/incremental/upd_dev_collection.sql @@ -108,3 +108,5 @@ ALTER TABLE `web_database` CHANGE `database_quota` `database_quota` INT(11) NULL ALTER TABLE `web_domain` ADD `log_retention` INT NOT NULL DEFAULT '30' ; ALTER TABLE spamfilter_policy CHANGE spam_tag_level spam_tag_level DECIMAL(5,2) NULL DEFAULT NULL, CHANGE spam_tag2_level spam_tag2_level DECIMAL(5,2) NULL DEFAULT NULL, CHANGE spam_kill_level spam_kill_level DECIMAL(5,2) NULL DEFAULT NULL, CHANGE spam_dsn_cutoff_level spam_dsn_cutoff_level DECIMAL(5,2) NULL DEFAULT NULL, CHANGE spam_quarantine_cutoff_level spam_quarantine_cutoff_level DECIMAL(5,2) NULL DEFAULT NULL; UPDATE `web_database` as d LEFT JOIN `web_domain` as w ON (w.domain_id = d.parent_domain_id) SET d.parent_domain_id = 0 WHERE w.domain_id IS NULL AND d.parent_domain_id != 0; + +ALTER TABLE `dns_soa` ADD COLUMN `zonefile_unsigned` LONGTEXT NULL AFTER `dnssec_info`, ADD COLUMN `zonefile_signed` LONGTEXT NULL AFTER `zonefile_unsigned`, ADD COLUMN `datalog_only_replication` TINYINT(1) NOT NULL DEFAULT '0' AFTER `zonefile_signed`; diff --git a/server/lib/classes/cron.d/400-bind_replication.inc.php b/server/lib/classes/cron.d/400-bind_replication.inc.php new file mode 100644 index 0000000000000000000000000000000000000000..1014fab2cbeb1ec159a1264e7f86e72e39632c0e --- /dev/null +++ b/server/lib/classes/cron.d/400-bind_replication.inc.php @@ -0,0 +1,85 @@ +db->dbHost != $app->dbmaster->dbHost) return; + + //* Load libraries + $app->uses("getconf,tpl"); + + $soas = $app->db->queryAllRecords("SELECT id,zonefile_signed,zonefile_unsigned FROM dns_soa WHERE active= 'Y' AND datalog_only_replication=0"); + + foreach ($soas as $data) { + $app->log('DNS-Replication: Adding DataLog-Entry for SOA ID '.$data['id'], LOGLEVEL_DEBUG); + $app->db->datalogUpdate('dns_soa', array("zonefile_signed" => $data['zonefile_signed'], "zonefile_unsigned" => $data['zonefile_unsigned'], "datalog_only_replication" => 1), 'id', $data['id']); + } + + parent::onRunJob(); + } + + /* this function is optional if it contains no custom code */ + public function onAfterRun() { + global $app; + + parent::onAfterRun(); + } + +} + +?> diff --git a/server/plugins-available/bind_plugin.inc.php b/server/plugins-available/bind_plugin.inc.php index edf7b93d9f1ea62f8b314a62b73c77f15e5ca678..3e47e0f0f87fdf84c3b836fc8c2137c711f0f3bf 100644 --- a/server/plugins-available/bind_plugin.inc.php +++ b/server/plugins-available/bind_plugin.inc.php @@ -158,6 +158,9 @@ class bind_plugin { $dnssecdata .= file_get_contents($keyfile)."\n\n"; } + //Update signed Zonefile in DB for mirrors (it is intended to write unsigend data twice as signing might fail and then at least the unsigned data is in DB from soa_update) + $app->dbmaster->query('UPDATE dns_soa SET zonefile_unsigned=?, zonefile_signed=?, datalog_only_replication=1 WHERE id=?', $zonefile_unsigned, file_get_contents($dns_config['bind_zonefiles_dir'].'/'.$filespre.$domain.'.signed'), $data['new']['id']); + if ($app->dbmaster !== $app->db) $app->dbmaster->query('UPDATE dns_soa SET dnssec_info=?, dnssec_initialized=\'Y\', dnssec_last_signed=? WHERE id=?', $dnssecdata, intval(time()), intval($data['new']['id'])); $app->db->query('UPDATE dns_soa SET dnssec_info=?, dnssec_initialized=\'Y\', dnssec_last_signed=? WHERE id=?', $dnssecdata, intval(time()), intval($data['new']['id'])); } @@ -229,7 +232,7 @@ class bind_plugin { function soa_update($event_name, $data) { global $app, $conf; - + //* Load libraries $app->uses("getconf,tpl"); @@ -246,6 +249,64 @@ class bind_plugin { unset($tmp); } unset($bind); + + if ($conf['mirror_server_id'] > 0) { + //We are a mirroring DNS Server thus will take our zone from DB + $this->soa_update_mirror($event_name, $data, $dns_config); + } else if ($data['new']['datalog_only_replication'] != 1) { + //We are the master server and will create (as well as probably sign and store) the zone on our own + $this->soa_update_master($event_name, $data, $dns_config, $bind_caa); + } + + //This shall ALWAYS BE 0 after these actions. This flag is made to stop datalog-recursion when replicating to mirrors. + $data['new']['datalog_only_replication'] = 0; + $app->db->query('UPDATE dns_soa SET datalog_only_replication=0 WHERE id=?', intval($data['new']['id'])); //Do not put this to datalog. + + //* rebuild the named.conf file if the origin has changed or when the origin is inserted. + //if($this->action == 'insert' || $data['old']['origin'] != $data['new']['origin']) { + $this->write_named_conf($data, $dns_config); + //} + + //* Delete old domain file, if domain name has been changed + if($data['old']['origin'] != $data['new']['origin']) { + //TODO : change this when distribution information has been integrated into server record + if (file_exists('/etc/gentoo-release')) { + $filename = $dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1)); + } + else { + $filename = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1)); + } + + if(is_file($filename)) unlink($filename); + if(is_file($filename.'.err')) unlink($filename.'.err'); + if(is_file($filename.'.signed')) unlink($filename.'.signed'); + } + + //* Restart bind nameserver if update_acl is not empty, otherwise reload it + if($data['new']['update_acl'] != '') { + $app->services->restartServiceDelayed('bind', 'restart'); + } else { + $app->services->restartServiceDelayed('bind', 'reload'); + } + } + + function soa_update_mirror($event_name, $data, $dns_config) { + global $app, $conf; + + //* Write the domain files to file system (replicating from master via datalog/DB) + //TODO : change this when distribution information has been integrated into server record + if (file_exists('/etc/gentoo-release')) { + $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($data['new']['origin'], 0, -1))); + } + else { + $filename = escapeshellcmd($dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['new']['origin'], 0, -1))); + } + if ($data['new']['zonefile_unsigned'] != null) file_put_contents($filename, $data['new']['zonefile_unsigned']); + if ($data['new']['zonefile_signed'] != null) file_put_contents($filename.'.signed', $data['new']['zonefile_signed']); + } + + function soa_update_master($event_name, $data, $dns_config, $bind_caa) { + global $app, $conf; //* Write the domain file if(!empty($data['new']['id'])) { @@ -291,6 +352,7 @@ class bind_plugin { $old_zonefile = @file_get_contents($filename); file_put_contents($filename, $tpl->grab()); + $db_zone_unsigned = $tpl->grab(); chown($filename, escapeshellcmd($dns_config['bind_user'])); chgrp($filename, escapeshellcmd($dns_config['bind_group'])); @@ -309,12 +371,17 @@ class bind_plugin { if ($old_zonefile != '') { rename($filename, $filename.'.err'); file_put_contents($filename, $old_zonefile); + $db_zone_unsigned = $old_zonefile; chown($filename, escapeshellcmd($dns_config['bind_user'])); chgrp($filename, escapeshellcmd($dns_config['bind_group'])); } else { rename($filename, $filename.'.err'); } } + + //Update Zonefile in DB for mirrors + $app->dbmaster->query('UPDATE dns_soa SET zonefile_unsigned=?, datalog_only_replication=0 WHERE id=?', $zonefile_unsigned, $data['new']['id']); + unset($tpl); unset($records); unset($records_out); @@ -335,39 +402,13 @@ class bind_plugin { else { $filename = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1)); } - if(is_file($filename.'.signed')) unlink($filename.'.signed'); + if(is_file($filename.'.signed')) { + unlink($filename.'.signed'); + } } else if ($data['new']['dnssec_wanted'] == 'Y') $this->soa_dnssec_update($data); // END DNSSEC - - //* rebuild the named.conf file if the origin has changed or when the origin is inserted. - //if($this->action == 'insert' || $data['old']['origin'] != $data['new']['origin']) { - $this->write_named_conf($data, $dns_config); - //} - - //* Delete old domain file, if domain name has been changed - if($data['old']['origin'] != $data['new']['origin']) { - //TODO : change this when distribution information has been integrated into server record - if (file_exists('/etc/gentoo-release')) { - $filename = $dns_config['bind_zonefiles_dir'].'/pri/'.str_replace("/", "_", substr($data['old']['origin'], 0, -1)); - } - else { - $filename = $dns_config['bind_zonefiles_dir'].'/pri.'.str_replace("/", "_", substr($data['old']['origin'], 0, -1)); - } - - if(is_file($filename)) unlink($filename); - if(is_file($filename.'.err')) unlink($filename.'.err'); - if(is_file($filename.'.signed')) unlink($filename.'.signed'); - } - - //* Restart bind nameserver if update_acl is not empty, otherwise reload it - if($data['new']['update_acl'] != '') { - $app->services->restartServiceDelayed('bind', 'restart'); - } else { - $app->services->restartServiceDelayed('bind', 'reload'); - } - } - + function soa_delete($event_name, $data) { global $app, $conf;