diff --git a/server/plugins-available/bind_dlz_plugin.inc.php b/server/plugins-available/bind_dlz_plugin.inc.php new file mode 100644 index 0000000000000000000000000000000000000000..e1af9553b405c6c4df89ce24c5b829ad98567f52 --- /dev/null +++ b/server/plugins-available/bind_dlz_plugin.inc.php @@ -0,0 +1,347 @@ +<?php + +/* +Copyright (c) 2009, Falko Timme, Till Brehm, projektfarm Gmbh +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of ISPConfig nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* +TABLE STRUCTURE of the "named" database: + +CREATE TABLE IF NOT EXISTS `records` ( + `id` int(10) unsigned NOT NULL auto_increment, + `zone` varchar(255) NOT NULL, + `ttl` int(11) NOT NULL default '86400', + `type` varchar(255) NOT NULL, + `host` varchar(255) NOT NULL default '@', + `mx_priority` int(11) default NULL, + `data` text, + `primary_ns` varchar(255) default NULL, + `resp_contact` varchar(255) default NULL, + `serial` bigint(20) default NULL, + `refresh` int(11) default NULL, + `retry` int(11) default NULL, + `expire` int(11) default NULL, + `minimum` int(11) default NULL, + `ispconfig_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + KEY `type` (`type`), + KEY `host` (`host`), + KEY `zone` (`zone`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `xfr` ( + `id` int(11) NOT NULL auto_increment, + `zone` varchar(255) NOT NULL, + `client` varchar(255) NOT NULL, + `ispconfig_id` int(11) NOT NULL, + PRIMARY KEY (`id`), + KEY `zone` (`zone`), + KEY `client` (`client`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +*/ + +class bind_dlz_plugin { + + var $plugin_name = 'bind_dlz_plugin'; + var $class_name = 'bind_dlz_plugin'; + + //* This function is called during ispconfig installation to determine + // if a symlink shall be created for this plugin. + function onInstall() + { + global $conf; + + if(isset($conf['bind']['installed']) && $conf['bind']['installed'] == true) { + return true; + } else { + return false; + } + + } + + /* + This function is called when the plugin is loaded + */ + + function onLoad() + { + global $app; + + /* + Register for the events + */ + + //* SOA + $app->plugins->registerEvent('dns_soa_insert',$this->plugin_name,'soa_insert'); + $app->plugins->registerEvent('dns_soa_update',$this->plugin_name,'soa_update'); + $app->plugins->registerEvent('dns_soa_delete',$this->plugin_name,'soa_delete'); + + //* RR + $app->plugins->registerEvent('dns_rr_insert',$this->plugin_name,'rr_insert'); + $app->plugins->registerEvent('dns_rr_update',$this->plugin_name,'rr_update'); + $app->plugins->registerEvent('dns_rr_delete',$this->plugin_name,'rr_delete'); + } + + + function soa_insert($event_name,$data) + { + global $app, $conf; + + if($data["new"]["active"] != 'Y') return; + + $origin = substr($data["new"]["origin"], 0, -1); + $ispconfig_id = $data["new"]["id"]; + $serial = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$ispconfig_id); + + $ttl = $data["new"]["ttl"]; + + $_db = clone $app->db; + $_db->dbName = 'named'; + + $_db->query("INSERT INTO records (zone, ttl, type, primary_ns, resp_contact, serial, refresh, retry, expire, minimum, ispconfig_id) VALUES ". + "('$origin', $ttl, 'SOA', '{$data["new"]["ns"]}', '{$data["new"]["mbox"]}', '{$serial["serial"]}', '{$serial["refresh"]}'," . + "'{$serial["retry"]}', '{$serial["expire"]}', '{$serial["minimum"]}', $ispconfig_id)"); + unset($_db); + } + + function soa_update($event_name,$data) + { + global $app, $conf; + + if($data["new"]["active"] != 'Y') + { + if($data["old"]["active"] != 'Y') return; + $this->soa_delete($event_name,$data); + } + else + { + if($data["old"]["active"] == 'Y') + { + $origin = substr($data["new"]["origin"], 0, -1); + $ispconfig_id = $data["new"]["id"]; + $serial = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$ispconfig_id); + + $ttl = $data["new"]["ttl"]; + + $_db = clone $app->db; + $_db->dbName = 'named'; + + $_db->query("UPDATE records SET zone = '$origin', ttl = $ttl, primary_ns = '{$data["new"]["ns"]}', resp_contact = '{$data["new"]["mbox"]}', ". + "serial = '{$serial["serial"]}', refresh = '{$serial["refresh"]}', retry = '{$serial["retry"]}', expire = '{$serial["expire"]}', ". + "minimum = '{$serial["minimum"]}' WHERE ispconfig_id = ".$data["new"]["id"]." AND type = 'SOA'"); + unset($_db); + } + else + { + $this->soa_insert($event_name,$data); + $ispconfig_id = $data["new"]["id"]; + + if ($records = $app->db->queryAllRecords("SELECT * FROM dns_rr WHERE zone = $ispconfig_id AND active = 'Y'")) + { + foreach($records as $record) + { + foreach ($record as $key => $val) { + $data["new"][$key] = $val; + } + $this->rr_insert("dns_rr_insert", $data); + } + } + } + } + + } + + function soa_delete($event_name,$data) + { + global $app, $conf; + + $_db = clone $app->db; + $_db->dbName = 'named'; + + $_db->query("DELETE FROM records WHERE ispconfig_id = {$data["old"]["id"]}"); + unset($_db); + } + + function rr_insert($event_name,$data) + { + global $app, $conf; + if($data["new"]["active"] != 'Y') return; + + $zone = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data["new"]["zone"]); + $origin = substr($zone["origin"], 0, -1); + $ispconfig_id = $data["new"]["id"]; + + $type = $data["new"]["type"]; + + if (substr($data["new"]["name"], -1) == '.') { + $name = substr($data["new"]["name"], 0, -1); + } else { + $name = ($data["new"]["name"] == "") ? $name = '@' : $data["new"]["name"]; + } + + if ($name == $origin || $name == '') { + $name = '@'; + } + + switch ($type) + { + case "CNAME": + case "MX": + case "NS": + case "ALIAS": + case "PTR": + case "SRV": + if(substr($data["new"]["data"], -1) != '.'){ + $content = $data["new"]["data"] . '.'; + } else { + $content = $data["new"]["data"]; + } + break; + case "HINFO": + $content = $data["new"]["data"]; + $quote1 = strpos($content, '"'); + + if($quote1 !== FALSE) { + $quote2 = strpos(substr($content, ($quote1 + 1)), '"'); + } + + if ($quote1 !== FALSE && $quote2 !== FALSE) { + $text_between_quotes = str_replace(' ', '_', substr($content, ($quote1 + 1), (($quote2 - $quote1)))); + $content = $text_between_quotes.substr($content, ($quote2 + 2)); + } + break; + default: + $content = $data["new"]["data"]; + } + + $ttl = $data["new"]["ttl"]; + + $_db = clone $app->db; + $_db->dbName = 'named'; + + if ($type == 'MX') { + $_db->query("INSERT INTO records (zone, ttl, type, host, mx_priority, data, ispconfig_id)". + " VALUES ('$origin', $ttl, '$type', '$name', {$data["new"]["aux"]}, '$content', $ispconfig_id)"); + } else { + $_db->query("INSERT INTO records (zone, ttl, type, host, data, ispconfig_id)". + " VALUES ('$origin', $ttl, '$type', '$name', '$content', $ispconfig_id)"); + } + + unset($_db); + } + + function rr_update($event_name,$data) + { + global $app, $conf; + + if ($data["new"]["active"] != 'Y') + { + if($data["old"]["active"] != 'Y') return; + $this->rr_delete($event_name,$data); + } + else + { + if ($data["old"]["active"] == 'Y') + { + $zone = $app->db->queryOneRecord("SELECT * FROM dns_soa WHERE id = ".$data["new"]["zone"]); + $origin = substr($zone["origin"], 0, -1); + $ispconfig_id = $data["new"]["id"]; + + $type = $data["new"]["type"]; + + if (substr($data["new"]["name"], -1) == '.') { + $name = substr($data["new"]["name"], 0, -1); + } else { + $name = ($data["new"]["name"] == "") ? $name = '@' : $data["new"]["name"]; + } + + if ($name == $origin || $name == '') { + $name = '@'; + } + + switch ($type) + { + case "CNAME": + case "MX": + case "NS": + case "ALIAS": + case "PTR": + case "SRV": + if(substr($data["new"]["data"], -1) != '.'){ + $content = $data["new"]["data"] . '.'; + } else { + $content = $data["new"]["data"]; + } + break; + case "HINFO": + $content = $data["new"]["data"]; + $quote1 = strpos($content, '"'); + if($quote1 !== FALSE){ + $quote2 = strpos(substr($content, ($quote1 + 1)), '"'); + } + if($quote1 !== FALSE && $quote2 !== FALSE){ + $text_between_quotes = str_replace(' ', '_', substr($content, ($quote1 + 1), (($quote2 - $quote1)))); + $content = $text_between_quotes.substr($content, ($quote2 + 2)); + } + break; + default: + $content = $data["new"]["data"]; + } + + $ttl = $data["new"]["ttl"]; + $prio = (int)$data["new"]["aux"]; + + $_db = clone $app->db; + $_db->dbName = 'named'; + + if ($type == 'MX') { + $_db->query("UPDATE records SET zone = '$origin', ttl = $ttl, type = '$type', host = '$name', mx_priority = $prio, ". + "data = '$content' WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'"); + } else { + $_db->query("UPDATE records SET zone = '$origin', ttl = $ttl, type = '$type', host = '$name', ". + "data = '$content' WHERE ispconfig_id = $ispconfig_id AND type != 'SOA'"); + } + + unset($_db); + } else { + $this->rr_insert($event_name,$data); + } + } + } + + function rr_delete($event_name,$data) { + global $app, $conf; + + $_db = clone $app->db; + $_db->dbName = 'named'; + + $_db->query("DELETE FROM named.records WHERE ispconfig_id = {$data["old"]["id"]} AND type != 'SOA'"); + unset($_db); + } +} // end class +?> \ No newline at end of file