diff options
Diffstat (limited to 'config/bind/bind.inc')
-rw-r--r-- | config/bind/bind.inc | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/config/bind/bind.inc b/config/bind/bind.inc new file mode 100644 index 00000000..65d3c4f7 --- /dev/null +++ b/config/bind/bind.inc @@ -0,0 +1,605 @@ +<?PHP +/* $Id$ */ +/* + bind.inc + part of the Bind package for pfSense + Copyright (C) 2013 Juliano Oliveira/Adriano Brancher + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. 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. + + THIS SOFTWARE IS PROVIDED ``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 + AUTHOR 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. + +*/ +$shortcut_section = "bind"; +require_once('globals.inc'); +require_once('config.inc'); +require_once('util.inc'); +require_once('pfsense-utils.inc'); +require_once('pkg-utils.inc'); +require_once('service-utils.inc'); +if(!function_exists("filter_configure")) + require_once("filter.inc"); + +function bind_sync(){ + + global $config; + + $bind = $config["installedpackages"]["bind"]["config"][0]; + $bind_enable = $bind['enable_bind']; + $bind_forwarder = $bind['bind_forwarder']; + $forwader_ips = $bind['bind_forwader_ips']; + $ram_limite = $bind['bind_ram_limite']; + $hide_version = $bind['bind_hide_version']; + $bind_notify = $bind['bind_notify']; + $custom_options = base64_decode($bind['bind_custom_options']); + $bind_logging = $bind['bind_logging']; + + + $bind_conf ="#Bind pfsense configuration\n"; + $bind_conf .="#Do not edit this file!!!\n"; +$bind_conf .= <<<EOD + + options { + directory "/etc/namedb"; + pid-file "/var/run/named/pid"; + statistics-file "/var/log/named.stats"; + + max-cache-size $ram_limite;\n +EOD; + + //check ips to listen on + if (preg_match("/All/",$bind['listenon'])){ + $bind_listenonv6="Any;"; + $bind_listenon="Any;"; + } + else{ + $bind_listenonv6=""; + $bind_listenon =""; + foreach (explode(',',$bind['listenon']) as $listenon){ + if (is_ipaddrv6($listenon)) + $bind_listenonv6 .= $listenon."; "; + elseif (is_ipaddr($listenon)) + $bind_listenon .= $listenon."; "; + else{ + $listenon=(pfSense_get_interface_addresses(convert_friendly_interface_to_real_interface_name($listenon))); + if (is_ipaddr($listenon['ipaddr'])) + $bind_listenon .= $listenon['ipaddr']."; "; + elseif(is_ipaddrv6($listenon['ipaddr'])) + $bind_listenonv6 .= $listenon['ipaddr']."; "; + } + } + } + $bind_listenonv6=($bind_listenonv6==""?"none;":$bind_listenonv6); + $bind_listenon=($bind_listenon==""?"none;":$bind_listenon); + print "<PRE>$bind_listenonv6 $bind_listenon"; + if (key_exists("ipv6allow",$config['system'])){ + $bind_conf .="\t\tlisten-on-v6 { $bind_listenonv6 };\n"; + } + $bind_conf .="\t\tlisten-on { $bind_listenon };\n"; + + #forwarder config + if ($bind_forwarder == on) + $bind_conf .="\t\tforwarders { $forwader_ips };\n"; + if ($bind_notify == on) + $bind_conf .="\t\tnotify yes;\n"; + if ($hide_version == on) + $bind_conf .="\t\tversion \"N/A\";\n"; + + $bind_conf .="\t\t$custom_options\n"; + $bind_conf .= "\t};\n\n"; + + if ($bind_logging == on){ +$bind_conf .= <<<EOD + + logging { + channel custom { + file "/var/log/named.log"; + print-time yes; + print-category yes; + }; + + category config {custom;}; + category notify {custom;}; + category dnssec {custom;}; + category general {custom;}; + category security {custom;}; + category xfer-out {custom;}; + category lame-servers {custom;}; + }; + +EOD; + } + + + #Config Zone domain + if(is_array($config["installedpackages"]["bindacls"])) + $bindacls = $config["installedpackages"]["bindacls"]["config"]; + else + $bindacls =array(); + + for ($i=0; $i<sizeof($bindacls); $i++) + { + $aclname = $bindacls[$i]['name']; + $aclhost = $bindacls[$i]['row']; + if($aclname != "any"){ + $bind_conf .= "acl \"$aclname\" {\n"; + for ($u=0; $u<sizeof($aclhost); $u++) + { + $aclhostvalue = $aclhost[$u]['value']; + $bind_conf .= "\t$aclhostvalue;\n"; + } + $bind_conf .= "};\n\n"; + } + } + + if(is_array($config["installedpackages"]["bindviews"])) + $bindview = $config["installedpackages"]["bindviews"]["config"]; + else + $bindview =array(); + + for ($i=0; $i<sizeof($bindview); $i++) + { + $views = $config["installedpackages"]["bindviews"]["config"][$i]; + $viewname = $views['name']; + $viewrecursion = $views['recursion']; + if($views['match-clients'] == '') + $viewmatchclients = "none"; + else + $viewmatchclients = str_replace(',','; ',$views['match-clients']); + if($views['allow-recursion'] == '') + $viewallowrecursion = "none"; + else + $viewallowrecursion = str_replace(',','; ',$views['allow-recursion']); + $viewcustomoptions = $views['bind_custom_options']; + + $bind_conf .= "view \"$viewname\" { \n\n"; + $bind_conf .= "\trecursion $viewrecursion;\n"; + $bind_conf .= "\tmatch-clients { $viewmatchclients;};\n"; + $bind_conf .= "\tallow-recursion { $viewallowrecursion;};\n"; + $bind_conf .= "\t$viewcustomoptions\n\n"; + + $bind_conf .="\tzone \".\" {\n"; + $bind_conf .="\t\ttype hint;\n"; + $bind_conf .="\t\tfile \"/etc/namedb/named.root\";\n"; + $bind_conf .= "\t};\n\n"; + + for ($x=0; $x<sizeof($config["installedpackages"]["bindzone"]["config"]); $x++) + { + $zone = $config["installedpackages"]["bindzone"]["config"][$x]; + + $zonename = $zone['name']; + $zonetype = $zone['type']; + $zoneview = $zone['view']; + $zonecuston = $zone['custon']; + $zoneipslave = $zone['slaveip']; + $zonereverso = $zone['reverso']; + if($zone['allowupdate'] == '') + $zoneallowupdate = "none"; + else + $zoneallowupdate = str_replace(',','; ',$zone['allowupdate']); + if($zone['allowquery'] == '') + $zoneallowquery = "none"; + else + $zoneallowquery = str_replace(',','; ',$zone['allowquery']); + if($zone['allowtransfer'] == '') + $zoneallowtransfer = "none"; + else + $zoneallowtransfer = str_replace(',','; ',$zone['allowtransfer']); + + if ($zoneview == $viewname) + { + if($zonereverso == "on") + $bind_conf .= "\tzone \"$zonename.in-addr.arpa\" {\n"; + else + $bind_conf .= "\tzone \"$zonename\" {\n"; + + $bind_conf .= "\t\ttype $zonetype;\n"; + $bind_conf .= "\t\tfile \"/etc/namedb/$zonetype/$zoneview/$zonename.DB\";\n"; + if ($zonetype == "slave") + $bind_conf .= "\t\tmasters { $zoneipslave };\n"; + if ($zonetype != "slave") + $bind_conf .= "\t\tallow-update { $zoneallowupdate;};\n"; + if ($zonetype != "slave") + $bind_conf .= "\t\tallow-query { $zoneallowquery;};\n"; + if ($zonetype != "slave") + $bind_conf .= "\t\tallow-transfer { $zoneallowtransfer;};\n"; + if ($zonecuston != '') + $bind_conf .= "\t\t$zonecuston\n"; + $bind_conf .= "\t};\n\n"; + + if (!(file_exists("/etc/namedb/$zonetype"))) { + mwexec("mkdir /etc/namedb/$zonetype"); + } + + if (!(file_exists("/etc/namedb/$zonetype/$zoneview"))) { + mwexec("mkdir /etc/namedb/$zonetype/$zoneview"); + } + + if ($zonetype == "master"){ + $zonetll = $zone['tll']; + $zonemail = $zone['mail']; + $zoneserial = $zone['serial']; + $zonerefresh = $zone['refresh']; + $zoneretry = $zone['retry']; + $zoneexpire = $zone['expire']; + $zoneminimum = $zone['minimum']; + $zonenameserver = $zone['nameserver']; + $zoneipns = $zone['ipns']; + $zonereverso = $zone['reverso']; + if($zone['allowupdate'] == '') + $zoneallowupdate = "none"; + else + $zoneallowupdate = str_replace(',','; ',$zone['allowupdate']); + if($zone['allowquery'] == '') + $zoneallowquery = "none"; + else + $zoneallowquery = str_replace(',','; ',$zone['allowquery']); + if($zone['allowtransfer'] == '') + $zoneallowtransfer = "none"; + else + $zoneallowtransfer = str_replace(',','; ',$zone['allowtransfer']); + $zone_conf = ";$zonename\n"; + $zone_conf .= "\$TTL $zonetll\n\n"; + + if($zonereverso == "on") + $zone_conf .= "@\t IN SOA $zonenameserver. \t $zonemail. (\n"; + else + $zone_conf .= "$zonename.\t IN SOA $zonenameserver. \t $zonemail. (\n"; + + $zone_conf .= "\t$zoneserial\n"; + $zone_conf .= "\t$zonerefresh\n"; + $zone_conf .= "\t$zoneretry\n"; + $zone_conf .= "\t$zoneexpire\n"; + $zone_conf .= "\t$zoneminimum)\n\n"; + + if($zonereverso == "on") + $zone_conf .= "\t IN NS \t\t$zonenameserver.\n"; + else{ + $zone_conf .= "@ \t IN NS \t\t$zonenameserver.\n"; + $zone_conf .= "@ \t IN A \t\t$zoneipns\n"; + } + for ($y=0; $y<sizeof($zone['row']); $y++) + { + $hostname = $zone['row'][$y]['hostname']; + $hosttype = $zone['row'][$y]['hosttype']; + $hostdst = $zone['row'][$y]['hostdst']; + $hostvalue = $zone['row'][$y]['hostvalue']; + + $zone_conf .= "$hostname \t IN $hosttype $hostvalue \t$hostdst\n"; + } + file_put_contents("/etc/namedb/$zonetype/$zoneview/$zonename.DB", $zone_conf); + + #reader file domain zone + #reader file host definition + } + } + } + + $bind_conf .= "};\n"; + } + if (!is_dir("/etc/namedb")) + mkdir("/etc/namedb",0755); + file_put_contents('/etc/namedb/named.conf', $bind_conf); + + + if($bind_enable == "on") + mwexec("/usr/local/etc/rc.d/named.sh restart"); + else + mwexec("/usr/local/etc/rc.d/named.sh stop"); +} + +function bind_print_javascript_type_zone(){ +?> + <script language="JavaScript"> + <!-- + function on_type_zone_changed() { + + var field = document.iform.type; + var tipo = field.options[field.selectedIndex].value; + if (tipo == 'master') { + + document.iform.slaveip.disabled = 1; + document.iform.tll.disabled = 0; + document.iform.nameserver.disabled = 0; + document.iform.ipns.disabled = 0; + document.iform.mail.disabled = 0; + document.iform.serial.disabled = 0; + document.iform.refresh.disabled = 0; + document.iform.retry.disabled = 0; + document.iform.expire.disabled = 0; + document.iform.minimum.disabled = 0; + + } + else { + document.iform.slaveip.disabled = 0; + document.iform.tll.disabled = 1; + document.iform.nameserver.disabled = 1; + document.iform.ipns.disabled = 1; + document.iform.mail.disabled = 1; + document.iform.serial.disabled = 1; + document.iform.refresh.disabled = 1; + document.iform.retry.disabled = 1; + document.iform.expire.disabled = 1; + document.iform.minimum.disabled = 1; + } + } + --> + </script> +<?php +} + +function bind_print_javascript_type_zone2(){ + print("<script language=\"JavaScript\">on_type_zone_changed()</script>\n"); +} + +# Carregar o campo com os dados da views +# ----------------------------------------------------------------------------- + +function get_bind_conf_items_list($data_group, $fieldname) { + global $config; + $res = ''; + if (is_array($config["installedpackages"][$data_group])){ + $conf = $config["installedpackages"][$data_group]["config"]; + if (is_array($conf)) + foreach($conf as $cf) $res[] = $cf[$fieldname]; + } + return $res; +} + +# Carregar o campo com os dados da views +# ----------------------------------------------------------------------------- + +function bind_views_before_form_dest($pkg,$data_group,$fieldname,$dest) { + + $destination_items = get_bind_conf_items_list($data_group,$fieldname); + $i=0; + if (is_array($pkg['fields']['field'])) + foreach($pkg['fields']['field'] as $field) { + # + if ($field['fieldname'] == $dest) { + $fld = &$pkg['fields']['field'][$i]; + if (is_array($destination_items)) + foreach($destination_items as $nmkey => $nm) + $fld['options']['option'][] = array('name'=>ucfirst(strtolower($nm)), 'value'=>strtolower($nm)); + } + $i++; + } +} + +# Analizador do serial da zona de dns +# ----------------------------------------------------------------------------- + +function get_bind_conf_serial($data_group, $fieldname) { + global $config; + $res = ''; + if (is_array($config["installedpackages"][$data_group])){ + $conf = $config["installedpackages"][$data_group]["config"]; + if (is_array($conf)) + foreach($conf as $cf) $res[] = $cf[$fieldname]; + } + return $res; +} + +# Carregar o campo com os dados da views +# ----------------------------------------------------------------------------- + +function bind_zona_before_form_dest($pkg,$data_group,$fieldname,$dest) { + + $destination_items = get_bind_conf_serial($data_group,$fieldname); + $i=0; + if (is_array($pkg['fields']['field'])) + foreach($pkg['fields']['field'] as $field) { + # + if ($field['fieldname'] == $dest) { + $fld = &$pkg['fields']['field'][$i]; + $fld['default_value'] = date("Y")."000000"; + #$fld['value'] = date("Ymdhms")."boa"; + } + $i++; + } +} +function bind_write_rcfile() { + $rc = array(); + $BIND_LOCALBASE = "/usr/local"; + $rc['file'] = 'named.sh'; + $rc['start'] = <<<EOD +if [ -z "`ps auxw | grep "[n]amed -c /etc/namedb/named.conf"|awk '{print $2}'`" ];then + {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind +fi + +EOD; + $rc['stop'] = <<<EOD +killall -9 named 2>/dev/null +sleep 2 +EOD; + $rc['restart'] = <<<EOD +if [ -z "`ps auxw | grep "[n]amed -c /etc/namedb/named.conf"|awk '{print $2}'`" ];then + {$BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind + else + killall -9 named 2>/dev/null + sleep 3 + $BIND_LOCALBASE}/sbin/named -c /etc/namedb/named.conf -u bind + fi + +EOD; + conf_mount_rw(); + write_rcfile($rc); + conf_mount_ro(); +} + +function create_log_file(){ + mwexec("touch /var/log/named.log"); + mwexec("chown bind:bind /var/log/named.log"); + mwexec("chmod 755 /var/log/named.log"); +} + +function delete_log_file(){ + mwexec("rm /var/log/named.log"); +} +/* Uses XMLRPC to synchronize the changes to a remote node */ +function bind_sync_on_changes() { + global $config, $g; + if (is_array($config['installedpackages']['bind']['config'])){ + $bind_sync=$config['installedpackages']['bind']['config'][0]; + $synconchanges = $bind_sync['synconchanges']; + $synctimeout = $bind_sync['synctimeout']; + switch ($synconchanges){ + case "manual": + if (is_array($bind_sync[row])){ + $rs=$bind_sync[row]; + } + else{ + log_error("[bind] xmlrpc sync is enabled but there is no hosts to push on bind config."); + return; + } + break; + case "auto": + if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){ + $system_carp=$config['installedpackages']['carpsettings']['config'][0]; + $rs[0]['ipaddress']=$system_carp['synchronizetoip']; + $rs[0]['username']=$system_carp['username']; + $rs[0]['password']=$system_carp['password']; + } + else{ + log_error("[bind] xmlrpc sync is enabled but there is no system backup hosts to push bind config."); + return; + } + break; + default: + return; + break; + } + if (is_array($rs)){ + log_error("[bind] xmlrpc sync is starting."); + foreach($rs as $sh){ + $sync_to_ip = $sh['ipaddress']; + $password = $sh['password']; + if($sh['username']) + $username = $sh['username']; + else + $username = 'admin'; + if($password && $sync_to_ip) + bind_do_xmlrpc_sync($sync_to_ip, $username, $password,$synctimeout); + } + log_error("[bind] xmlrpc sync is ending."); + } + } +} +/* Do the actual XMLRPC sync */ +function bind_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout) { + global $config, $g; + + if(!$username) + return; + + if(!$password) + return; + + if(!$sync_to_ip) + return; + + if(!$synctimeout) + $synctimeout=25; + + + $xmlrpc_sync_neighbor = $sync_to_ip; + if($config['system']['webgui']['protocol'] != "") { + $synchronizetoip = $config['system']['webgui']['protocol']; + $synchronizetoip .= "://"; + } + $port = $config['system']['webgui']['port']; + /* if port is empty lets rely on the protocol selection */ + if($port == "") { + if($config['system']['webgui']['protocol'] == "http") + $port = "80"; + else + $port = "443"; + } + $synchronizetoip .= $sync_to_ip; + + /* xml will hold the sections to sync */ + $xml = array(); + $xml['bind'] = $config['installedpackages']['bind']; + $xml['bindacls'] = $config['installedpackages']['bindacls']; + $xml['bindviews'] = $config['installedpackages']['bindviews']; + $xml['bindzone'] = $config['installedpackages']['bindzone']; + /* assemble xmlrpc payload */ + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($xml) + ); + + /* set a few variables needed for sync code borrowed from filter.inc */ + $url = $synchronizetoip; + log_error("[bind] Beginning bind XMLRPC sync to {$url}:{$port}."); + $method = 'pfsense.merge_installedpackages_section_xmlrpc'; + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials($username, $password); + if($g['debug']) + $cli->setDebug(1); + /* send our XMLRPC message and timeout after defined sync timeout value*/ + $resp = $cli->send($msg, $synctimeout); + if(!$resp) { + $error = "A communications error occurred while attempting bind XMLRPC sync with {$url}:{$port}."; + log_error($error); + file_notice("sync_settings", $error, "bind Settings Sync", ""); + } elseif($resp->faultCode()) { + $cli->setDebug(1); + $resp = $cli->send($msg, $synctimeout); + $error = "An error code was received while attempting bind XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "bind Settings Sync", ""); + } else { + log_error("[bind] XMLRPC sync successfully completed with {$url}:{$port}."); + } + + /* tell bind to reload our settings on the destination sync host. */ + $method = 'pfsense.exec_php'; + $execcmd = "require_once('/usr/local/pkg/bind.inc');\n"; + $execcmd .= "bind_sync('yes');"; + /* assemble xmlrpc payload */ + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($execcmd) + ); + + log_error("[bind] XMLRPC reload data {$url}:{$port}."); + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials($username, $password); + $resp = $cli->send($msg, $synctimeout); + if(!$resp) { + $error = "A communications error occurred while attempting bind XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; + log_error($error); + file_notice("sync_settings", $error, "Bind Settings Sync", ""); + } elseif($resp->faultCode()) { + $cli->setDebug(1); + $resp = $cli->send($msg, $synctimeout); + $error = "[Bind] An error code was received while attempting bind XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "bind Settings Sync", ""); + } else { + log_error("Bind XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); + } + +} +?> |