diff --git a/api.php b/api.php index db419d30..39d67786 100644 --- a/api.php +++ b/api.php @@ -61,7 +61,7 @@ function json_response($status, $status_message = '', $data = null) } header($resheader); } - + $response = array(); $response['status'] = $status; $response['status_message'] = $status_message; $response['data'] = $data; diff --git a/lib/classes/api/commands/class.Domains.php b/lib/classes/api/commands/class.Domains.php index 7ae01cca..a925d9b0 100644 --- a/lib/classes/api/commands/class.Domains.php +++ b/lib/classes/api/commands/class.Domains.php @@ -1038,9 +1038,13 @@ class Domains extends ApiCommand implements ResourceEntity $speciallogfile = $result['speciallogfile']; } - if ($isbinddomain != $result['isbinddomain'] || $zonefile != $result['zonefile'] || $dkim != $result['dkim']) { + if ($isbinddomain != $result['isbinddomain'] || $zonefile != $result['zonefile'] || $dkim != $result['dkim'] || $isemaildomain != $result['isemaildomain']) { inserttask('4'); } + // check whether nameserver has been disabled, #581 + if ($isbinddomain != $result['isbinddomain'] && $isbinddomain == 0) { + inserttask('11', $result['domain']); + } if ($isemaildomain == '0' && $result['isemaildomain'] == '1') { $del_stmt = Database::prepare(" @@ -1499,6 +1503,9 @@ class Domains extends ApiCommand implements ResourceEntity triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $this->logger()); + // remove domains DNS from powerDNS if used, #581 + inserttask('11', $result['domain']); + $this->logger()->logAction(ADM_ACTION, LOG_INFO, "[API] deleted domain/subdomains (#" . $result['id'] . ")"); updateCounters(); inserttask('1'); diff --git a/lib/classes/dns/class.PowerDNS.php b/lib/classes/dns/class.PowerDNS.php new file mode 100644 index 00000000..525b366a --- /dev/null +++ b/lib/classes/dns/class.PowerDNS.php @@ -0,0 +1,127 @@ + (2016-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Cron + * + */ +class PowerDNS +{ + + private static $pdns_db = null; + + private static function connectToPdnsDb() + { + // get froxlor pdns config + $cf = Settings::Get('system.bindconf_directory') . '/froxlor/pdns_froxlor.conf'; + $config = makeCorrectFile($cf); + + if (! file_exists($config)) { + die('PowerDNS configuration file (' . $config . ') not found. Did you go through the configuration templates?' . PHP_EOL); + } + $lines = file($config); + $mysql_data = array(); + foreach ($lines as $line) { + $line = trim($line); + if (strtolower(substr($line, 0, 6)) == 'gmysql') { + $namevalue = explode("=", $line); + $mysql_data[$namevalue[0]] = $namevalue[1]; + } + } + + // build up connection string + $driver = 'mysql'; + $dsn = $driver . ":"; + $options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET names utf8,sql_mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"' + ); + $attributes = array( + 'ATTR_ERRMODE' => 'ERRMODE_EXCEPTION' + ); + $dbconf = array(); + + $dbconf["dsn"] = array( + 'dbname' => $mysql_data["gmysql-dbname"], + 'charset' => 'utf8' + ); + + if (isset($mysql_data['gmysql-socket']) && ! empty($mysql_data['gmysql-socket'])) { + $dbconf["dsn"]['unix_socket'] = makeCorrectFile($mysql_data['gmysql-socket']); + } else { + $dbconf["dsn"]['host'] = $mysql_data['gmysql-host']; + $dbconf["dsn"]['port'] = $mysql_data['gmysql-port']; + } + + // add options to dsn-string + foreach ($dbconf["dsn"] as $k => $v) { + $dsn .= $k . "=" . $v . ";"; + } + + // clean up + unset($dbconf); + + // try to connect + try { + self::$pdns_db = new PDO($dsn, $mysql_data['gmysql-user'], $mysql_data['gmysql-password'], $options); + } catch (PDOException $e) { + die($e->getMessage()); + } + + // set attributes + foreach ($attributes as $k => $v) { + self::$pdns_db->setAttribute(constant("PDO::" . $k), constant("PDO::" . $v)); + } + } + + /** + * get pdo database connection to powerdns database + * + * @return PDO + */ + public static function getDB() + { + if (! isset(self::$pdns_db) || (self::$pdns_db instanceof PDO) == false) { + self::connectToPdnsDb(); + } + return self::$pdns_db; + } + + /** + * remove all records and entries of a given domain + * + * @param array $domain + */ + public static function cleanDomainZone($domain = null) + { + if (is_array($domain) && isset($domain['domain'])) { + $pdns_domains_stmt = self::getDB()->prepare("SELECT `id`, `name` FROM `domains` WHERE `name` = :domain"); + $del_rec_stmt = self::getDB()->prepare("DELETE FROM `records` WHERE `domain_id` = :did"); + $del_meta_stmt = self::getDB()->prepare("DELETE FROM `domainmetadata` WHERE `domain_id` = :did"); + $del_dom_stmt = self::getDB()->prepare("DELETE FROM `domains` WHERE `id` = :did"); + + $pdns_domains_stmt->execute(array( + 'domain' => $domain['domain'] + )); + $pdns_domain = $pdns_domains_stmt->fetch(\PDO::FETCH_ASSOC); + + $del_rec_stmt->execute(array( + 'did' => $pdns_domain['id'] + )); + $del_meta_stmt->execute(array( + 'did' => $pdns_domain['id'] + )); + $del_dom_stmt->execute(array( + 'did' => $pdns_domain['id'] + )); + } + } +} \ No newline at end of file diff --git a/lib/functions/froxlor/function.inserttask.php b/lib/functions/froxlor/function.inserttask.php index 705bf77e..06b06e6d 100644 --- a/lib/functions/froxlor/function.inserttask.php +++ b/lib/functions/froxlor/function.inserttask.php @@ -20,27 +20,26 @@ /** * Inserts a task into the PANEL_TASKS-Table * - * @param int Type of task - * @param string Parameter 1 - * @param string Parameter 2 - * @param string Parameter 3 + * @param + * int Type of task + * @param + * string Parameter 1 + * @param + * string Parameter 2 + * @param + * string Parameter 3 * @author Florian Lippert * @author Froxlor team */ -function inserttask($type, $param1 = '', $param2 = '', $param3 = '', $param4 = '') { +function inserttask($type, $param1 = '', $param2 = '', $param3 = '', $param4 = '') +{ // prepare the insert-statement $ins_stmt = Database::prepare(" INSERT INTO `" . TABLE_PANEL_TASKS . "` SET `type` = :type, `data` = :data "); - if ($type == '1' - || $type == '3' - || $type == '4' - || $type == '5' - || $type == '10' - || $type == '99' - ) { + if ($type == '1' || $type == '3' || $type == '4' || $type == '5' || $type == '10' || $type == '99') { // 4 = bind -> if bind disabled -> no task if ($type == '4' && Settings::Get('system.bind_enable') == '0') { return; @@ -54,57 +53,65 @@ function inserttask($type, $param1 = '', $param2 = '', $param3 = '', $param4 = ' $del_stmt = Database::prepare(" DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = :type "); - Database::pexecute($del_stmt, array('type' => $type)); + Database::pexecute($del_stmt, array( + 'type' => $type + )); // insert the new task - Database::pexecute($ins_stmt, array('type' => $type, 'data' => '')); - - } elseif ($type == '2' - && $param1 != '' - && $param2 != '' - && $param3 != '' - && ($param4 == 0 || $param4 == 1) - ) { + Database::pexecute($ins_stmt, array( + 'type' => $type, + 'data' => '' + )); + } elseif ($type == '2' && $param1 != '' && $param2 != '' && $param3 != '' && ($param4 == 0 || $param4 == 1)) { $data = array(); $data['loginname'] = $param1; $data['uid'] = $param2; $data['gid'] = $param3; $data['store_defaultindex'] = $param4; $data = json_encode($data); - Database::pexecute($ins_stmt, array('type' => '2', 'data' => $data)); - - } elseif ($type == '6' - && $param1 != '' - ) { + Database::pexecute($ins_stmt, array( + 'type' => '2', + 'data' => $data + )); + } elseif ($type == '6' && $param1 != '') { $data = array(); $data['loginname'] = $param1; $data = json_encode($data); - Database::pexecute($ins_stmt, array('type' => '6', 'data' => $data)); - - } elseif ($type == '7' - && $param1 != '' - && $param2 != '' - ) { + Database::pexecute($ins_stmt, array( + 'type' => '6', + 'data' => $data + )); + } elseif ($type == '7' && $param1 != '' && $param2 != '') { $data = array(); $data['loginname'] = $param1; $data['email'] = $param2; $data = json_encode($data); - Database::pexecute($ins_stmt, array('type' => '7', 'data' => $data)); - - } elseif ($type == '8' - && $param1 != '' - && $param2 != '' - ) { + Database::pexecute($ins_stmt, array( + 'type' => '7', + 'data' => $data + )); + } elseif ($type == '8' && $param1 != '' && $param2 != '') { $data = array(); $data['loginname'] = $param1; $data['homedir'] = $param2; $data = json_encode($data); - Database::pexecute($ins_stmt, array('type' => '8', 'data' => $data)); - - } elseif ($type == '20' - && is_array($param1) - ) { + Database::pexecute($ins_stmt, array( + 'type' => '8', + 'data' => $data + )); + } elseif ($type == '11' && $param1 != '') { + $data = array(); + $data['domain'] = $param1; + $data = json_encode($data); + Database::pexecute($ins_stmt, array( + 'type' => '11', + 'data' => $data + )); + } elseif ($type == '20' && is_array($param1)) { $data = json_encode($param1); - Database::pexecute($ins_stmt, array('type' => '20', 'data' => $data)); + Database::pexecute($ins_stmt, array( + 'type' => '20', + 'data' => $data + )); } } diff --git a/scripts/jobs/cron_tasks.inc.dns.20.pdns.php b/scripts/jobs/cron_tasks.inc.dns.20.pdns.php index cb70417a..afa82ea5 100644 --- a/scripts/jobs/cron_tasks.inc.dns.20.pdns.php +++ b/scripts/jobs/cron_tasks.inc.dns.20.pdns.php @@ -14,21 +14,16 @@ if (! defined('MASTER_CRONJOB')) * @author Froxlor team (2016-) * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt * @package Cron - * + * */ class pdns extends DnsBase { - private $pdns_db = null; - public function writeConfigs() { // tell the world what we are doing $this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Task4 started - Refreshing DNS database'); - // connect to db - $this->_connectToPdnsDb(); - $domains = $this->getDomainList(); // clean up @@ -62,17 +57,14 @@ class pdns extends DnsBase } if ($domain['zonefile'] == '') { - // check for system-hostname + // check for system-hostname $isFroxlorHostname = false; if (isset($domain['froxlorhost']) && $domain['froxlorhost'] == 1) { $isFroxlorHostname = true; } if ($domain['ismainbutsubto'] == 0) { - $zoneContent = createDomainZone(($domain['id'] == 'none') ? - $domain : - $domain['id'], - $isFroxlorHostname); + $zoneContent = createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname); if (count($subzones)) { foreach ($subzones as $subzone) { $zoneContent->records[] = $subzone; @@ -83,16 +75,10 @@ class pdns extends DnsBase $this->_insertAllowedTransfers($pdnsDomId); $this->_logger->logAction(CRON_ACTION, LOG_INFO, 'DB entries stored for zone `' . $domain['domain'] . '`'); } else { - return createDomainZone(($domain['id'] == 'none') ? - $domain : - $domain['id'], - $isFroxlorHostname, - true); + return createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname, true); } } else { - $this->_logger->logAction(CRON_ACTION, LOG_ERROR, - 'Custom zonefiles are NOT supported when PowerDNS is selected as DNS daemon (triggered by: ' . - $domain['domain'] . ')'); + $this->_logger->logAction(CRON_ACTION, LOG_ERROR, 'Custom zonefiles are NOT supported when PowerDNS is selected as DNS daemon (triggered by: ' . $domain['domain'] . ')'); } } @@ -100,30 +86,40 @@ class pdns extends DnsBase { $this->_logger->logAction(CRON_ACTION, LOG_INFO, 'Cleaning dns zone entries from database'); - $pdns_domains_stmt = $this->pdns_db->prepare("SELECT `id`, `name` FROM `domains` WHERE `name` = :domain"); + $pdns_domains_stmt = PowerDNS::getDB()->prepare("SELECT `id`, `name` FROM `domains` WHERE `name` = :domain"); - $del_rec_stmt = $this->pdns_db->prepare("DELETE FROM `records` WHERE `domain_id` = :did"); - $del_meta_stmt = $this->pdns_db->prepare("DELETE FROM `domainmetadata` WHERE `domain_id` = :did"); - $del_dom_stmt = $this->pdns_db->prepare("DELETE FROM `domains` WHERE `id` = :did"); + $del_rec_stmt = PowerDNS::getDB()->prepare("DELETE FROM `records` WHERE `domain_id` = :did"); + $del_meta_stmt = PowerDNS::getDB()->prepare("DELETE FROM `domainmetadata` WHERE `domain_id` = :did"); + $del_dom_stmt = PowerDNS::getDB()->prepare("DELETE FROM `domains` WHERE `id` = :did"); - foreach ($domains as $domain) - { - $pdns_domains_stmt->execute(array('domain' => $domain['domain'])); + foreach ($domains as $domain) { + $pdns_domains_stmt->execute(array( + 'domain' => $domain['domain'] + )); $pdns_domain = $pdns_domains_stmt->fetch(\PDO::FETCH_ASSOC); - $del_rec_stmt->execute(array('did' => $pdns_domain['id'])); - $del_meta_stmt->execute(array('did' => $pdns_domain['id'])); - $del_dom_stmt->execute(array('did' => $pdns_domain['id'])); + $del_rec_stmt->execute(array( + 'did' => $pdns_domain['id'] + )); + $del_meta_stmt->execute(array( + 'did' => $pdns_domain['id'] + )); + $del_dom_stmt->execute(array( + 'did' => $pdns_domain['id'] + )); } } private function _insertZone($domainname, $serial = 0) { - $ins_stmt = $this->pdns_db->prepare(" + $ins_stmt = PowerDNS::getDB()->prepare(" INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = 'NATIVE' "); - $ins_stmt->execute(array('domainname' => $domainname, 'serial' => $serial)); - $lastid = $this->pdns_db->lastInsertId(); + $ins_stmt->execute(array( + 'domainname' => $domainname, + 'serial' => $serial + )); + $lastid = PowerDNS::getDB()->lastInsertId(); return $lastid; } @@ -131,7 +127,7 @@ class pdns extends DnsBase { $changedate = date('Ymds', time()); - $ins_stmt = $this->pdns_db->prepare(" + $ins_stmt = PowerDNS::getDB()->prepare(" INSERT INTO records set `domain_id` = :did, `name` = :rec, @@ -143,8 +139,7 @@ class pdns extends DnsBase `change_date` = :changedate "); - foreach ($records as $record) - { + foreach ($records as $record) { if ($record instanceof DnsZone) { $this->_insertRecords($domainid, $record->records, $record->origin); continue; @@ -152,10 +147,8 @@ class pdns extends DnsBase if ($record->record == '@') { $_record = $origin; - } - else - { - $_record = $record->record.".".$origin; + } else { + $_record = $record->record . "." . $origin; } $ins_data = array( @@ -173,7 +166,7 @@ class pdns extends DnsBase private function _insertAllowedTransfers($domainid) { - $ins_stmt = $this->pdns_db->prepare(" + $ins_stmt = PowerDNS::getDB()->prepare(" INSERT INTO domainmetadata set `domain_id` = :did, `kind` = 'ALLOW-AXFR-FROM', `content` = :value "); @@ -200,67 +193,4 @@ class pdns extends DnsBase } } } - - private function _connectToPdnsDb() - { - // get froxlor pdns config - $cf = Settings::Get('system.bindconf_directory').'/froxlor/pdns_froxlor.conf'; - $config = makeCorrectFile($cf); - - if (!file_exists($config)) - { - $this->_logger->logAction(CRON_ACTION, LOG_ERROR, 'PowerDNS configuration file ('.$config.') not found. Did you go through the configuration templates?'); - die('PowerDNS configuration file ('.$config.') not found. Did you go through the configuration templates?'.PHP_EOL); - } - $lines = file($config); - $mysql_data = array(); - foreach ($lines as $line) - { - $line = trim($line); - if (strtolower(substr($line, 0, 6)) == 'gmysql') - { - $namevalue = explode("=", $line); - $mysql_data[$namevalue[0]] = $namevalue[1]; - } - } - - // build up connection string - $driver = 'mysql'; - $dsn = $driver.":"; - $options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET names utf8,sql_mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"'); - $attributes = array('ATTR_ERRMODE' => 'ERRMODE_EXCEPTION'); - $dbconf = array(); - - $dbconf["dsn"] = array( - 'dbname' => $mysql_data["gmysql-dbname"], - 'charset' => 'utf8' - ); - - if (isset($mysql_data['gmysql-socket']) && !empty($mysql_data['gmysql-socket'])) { - $dbconf["dsn"]['unix_socket'] = makeCorrectFile($mysql_data['gmysql-socket']); - } else { - $dbconf["dsn"]['host'] = $mysql_data['gmysql-host']; - $dbconf["dsn"]['port'] = $mysql_data['gmysql-port']; - } - - // add options to dsn-string - foreach ($dbconf["dsn"] as $k => $v) { - $dsn .= $k."=".$v.";"; - } - - // clean up - unset($dbconf); - - // try to connect - try { - $this->pdns_db = new PDO($dsn, $mysql_data['gmysql-user'], $mysql_data['gmysql-password'], $options); - } catch (PDOException $e) { - die($e->getMessage()); - } - - // set attributes - foreach ($attributes as $k => $v) { - $this->pdns_db->setAttribute(constant("PDO::".$k), constant("PDO::".$v)); - } - } } diff --git a/scripts/jobs/cron_tasks.php b/scripts/jobs/cron_tasks.php index 48cbbb66..8ac0c811 100644 --- a/scripts/jobs/cron_tasks.php +++ b/scripts/jobs/cron_tasks.php @@ -417,6 +417,15 @@ while ($row = $result_tasks_stmt->fetch(PDO::FETCH_ASSOC)) { } } } + + /** + * TYPE=11 domain has been deleted, remove from pdns database if used + */ + if ($row['type'] == '11' && Settings::Get('system.dns_server') == 'pdns') + { + $cronlog->logAction(CRON_ACTION, LOG_NOTICE, "Removing PowerDNS entries for domain " . $row['data']['domain']); + PowerDNS::cleanDomainZone($row['data']['domain']); + } } if ($num_results != 0) {