diff options
120 files changed, 7984 insertions, 5359 deletions
diff --git a/config/apache_mod_security-dev/apache_mod_security.inc b/config/apache_mod_security-dev/apache_mod_security.inc index ed5596d6..4ec13bd0 100644 --- a/config/apache_mod_security-dev/apache_mod_security.inc +++ b/config/apache_mod_security-dev/apache_mod_security.inc @@ -1,19 +1,20 @@ <?php /* apache_mod_security.inc - part of apache_mod_security package (http://www.pfSense.com) + part of pfSense (https://www.pfSense.org/) Copyright (C) 2009, 2010 Scott Ullrich Copyright (C) 2012-2013 Marcello Coutinho Copyright (C) 2013 Stephane Lapie <stephane.lapie@asahinet.com> + Copyright (C) 2015 ESF, LLC 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, + 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 + 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. @@ -28,7 +29,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - require_once("service-utils.inc"); $shortcut_section = "apache"; @@ -157,27 +157,38 @@ function apache_mod_security_resync() { if (is_array($config['installedpackages']['apachesync']['config'])){ $apache_sync = $config['installedpackages']['apachesync']['config'][0]; $synconchanges = $apache_sync['synconchanges']; - $synctimeout = $apache_sync['synctimeout']; - switch ($synconchanges){ + $synctimeout = $apache_sync['synctimeout'] ?: '250'; + switch ($synconchanges) { case "manual": - if (is_array($apache_sync[row])){ - $rs = $apache_sync[row]; + if (is_array($apache_sync['row'])) { + $rs = $apache_sync['row']; } else { - log_error("apache_mod_security_package: XMLRPC sync is enabled, but there is no local host to push on apache config."); + log_error("apache_mod_security_package: XMLRPC sync is enabled but there are no hosts configured as replication targets."); return; } break; case "auto": - if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){ // pfSense 2.0.x - $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 if (is_array($config['hasync'])) { // pfSense 2.1 + if (is_array($config['hasync'])) { $system_carp = $config['hasync']; $rs[0]['ipaddress'] = $system_carp['synchronizetoip']; $rs[0]['username'] = $system_carp['username']; $rs[0]['password'] = $system_carp['password']; + $rs[0]['syncdestinenable'] = FALSE; + + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['syncprotocol'] = "http"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['syncprotocol'] = "https"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '443'; + } + if ($system_carp['synchronizetoip'] == "") { + log_error("apache_mod_security_package: XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } else { + $rs[0]['syncdestinenable'] = TRUE; + } } else { log_error("apache_mod_security_package: XMLRPC sync is enabled, but there is no global backup host to push apache config."); return; @@ -185,55 +196,63 @@ function apache_mod_security_resync() { break; default: return; - break; + break; } - } - if (is_array($rs)){ - 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) - apache_mod_security_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout); + if (is_array($rs)) { + log_error("apache_mod_security_package: XMLRPC sync is starting."); + foreach ($rs as $sh) { + // Only sync enabled replication targets + if ($sh['syncdestinenable']) { + $sync_to_ip = $sh['ipaddress']; + $port = $sh['syncport']; + $username = $sh['username'] ?: 'admin'; + $password = $sh['password']; + $protocol = $sh['syncprotocol']; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + apache_mod_security_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout); + } else { + log_error("apache_mod_security_package: XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } + } + } + log_error("apache_mod_security_package: XMLRPC sync completed."); } } } // Do the actual XMLRPC Sync -function apache_mod_security_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout) { +function apache_mod_security_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) { global $config, $g; - if(!$username) - return; - - if(!$password) - return; - - if(!$sync_to_ip) + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("apache_mod_security_package: A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); 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"; + + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; } - $synchronizetoip .= $sync_to_ip; - /* xml will hold the sections to sync */ + $url = "{$protocol}://{$sync_to_ip}"; + + /* XML will hold the sections to sync. */ $xml = array(); $xml['apachesettings'] = $config['installedpackages']['apachesettings']; $xml['apachemodsecurity'] = $config['installedpackages']['apachemodsecurity']; @@ -243,67 +262,58 @@ function apache_mod_security_do_xmlrpc_sync($sync_to_ip, $username, $password, $ $xml['apachevirtualhost'] = $config['installedpackages']['apachevirtualhost']; $xml['apachelisten'] = $config['installedpackages']['apachelisten']; - /* assemble xmlrpc payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($xml) - ); + /* 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("apache_mod_security_package: Beginning apache_mod_security XMLRPC sync to {$url}:{$port}."); + /* Set a few variables needed for sync code */ $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']) + if ($g['debug']) { $cli->setDebug(1); - /* send our XMLRPC message and timeout after defined sync timeout value*/ + } + /* 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 apache_mod_security XMLRPC sync with {$url}:{$port}."; - log_error($error); + if (!$resp) { + $error = "A communications error occurred while attempting XMLRPC sync with {$url}:{$port}."; + log_error("apache_mod_security_package: {$error}"); file_notice("sync_settings", $error, "apache_mod_security Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - $error = "An error code was received while attempting apache_mod_security XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("apache_mod_security_package: {$error}"); file_notice("sync_settings", $error, "apache_mod_security Settings Sync", ""); } else { log_error("apache_mod_security_package: XMLRPC sync successfully completed with {$url}:{$port}."); } - /* tell apache_mod_security to reload our settings on the destination sync host. */ + /* Tell apache_mod_security to reload our settings on the destination sync host. */ $method = 'pfsense.exec_php'; $execcmd = "require_once('/usr/local/pkg/apache_mod_security.inc');\n"; $execcmd .= "apache_mod_security_resync();"; - /* assemble xmlrpc payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($execcmd) - ); + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); - log_error("apache_mod_security_package: 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 apache_mod_security XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; - log_error($error); + if (!$resp) { + $error = "A communications error occurred while attempting XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; + log_error("apache_mod_security_package: {$error}"); file_notice("sync_settings", $error, "apache_mod_security Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - $error = "An error code was received while attempting apache_mod_security XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("apache_mod_security_package: {$error}"); file_notice("sync_settings", $error, "apache_mod_security Settings Sync", ""); } else { - log_error("apache_mod_security XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); + log_error("apache_mod_security_package: XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); } - } function apache_mod_security_checkconfig() { diff --git a/config/apache_mod_security-dev/apache_mod_security_sync.xml b/config/apache_mod_security-dev/apache_mod_security_sync.xml index 7ecfb68e..425069b6 100755 --- a/config/apache_mod_security-dev/apache_mod_security_sync.xml +++ b/config/apache_mod_security-dev/apache_mod_security_sync.xml @@ -1,46 +1,46 @@ <?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd"> -<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> +<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> <copyright> <![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* - apache_sync.xml - part of the sarg package for pfSense - Copyright (C) 2012 Marcello Coutinho - All rights reserved. - */ -/* ========================================================================== */ + apache_sync.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2012 Marcello Coutinho + Copyright (C) 2015 ESF, LLC + All rights reserved. +*/ +/* ====================================================================================== */ /* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + 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. + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. - 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. - */ -/* ========================================================================== */ + 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. +*/ +/* ====================================================================================== */ ]]> </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> <name>apachesync</name> <version>1.0</version> <title>Proxy server: XMLRPC Sync</title> @@ -66,9 +66,15 @@ <type>listtopic</type> </field> <field> - <fielddescr>Automatically sync apache configuration changes</fielddescr> + <fielddescr>Enable Sync</fielddescr> <fieldname>synconchanges</fieldname> - <description>Select a sync method for Apache + ModSecurity.</description> + <description> + <![CDATA[ + Select a sync method for Apache + ModSecurity.<br/><br/> + <strong>Important:</strong> While using "Sync to host(s) defined below", only sync from host A to B, A to C but <strong>do not</strong> enable XMLRPC sync <b>to</b> A. + This will result in a loop! + ]]> + </description> <type>select</type> <required/> <default_value>auto</default_value> @@ -79,39 +85,70 @@ </options> </field> <field> - <fielddescr>Sync timeout</fielddescr> + <fielddescr>Sync Timeout</fielddescr> <fieldname>synctimeout</fieldname> - <description>Select sync max wait time</description> + <description>XMLRPC timeout in seconds.</description> <type>select</type> <required/> <default_value>250</default_value> <options> - <option><name>30 seconds(Default)</name><value>30</value></option> - <option><name>60 seconds</name><value>60</value></option> - <option><name>90 seconds</name><value>90</value></option> + <option><name>250 seconds (Default)</name><value>250</value></option> <option><name>120 seconds</name><value>120</value></option> - <option><name>250 seconds</name><value>250</value></option> + <option><name>90 seconds</name><value>90</value></option> + <option><name>60 seconds</name><value>60</value></option> + <option><name>30 seconds</name><value>30</value></option> </options> </field> <field> - <fielddescr>Remote Server</fielddescr> + <fielddescr>Replication Targets</fielddescr> <fieldname>none</fieldname> <type>rowhelper</type> <rowhelper> - <rowhelperfield> - <fielddescr>IP Address</fielddescr> - <fieldname>ipaddress</fieldname> - <description>IP Address of remote server</description> - <type>input</type> - <size>20</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Password</fielddescr> - <fieldname>password</fieldname> - <description>Password for remote server.</description> - <type>password</type> - <size>20</size> - </rowhelperfield> + <rowhelperfield> + <fielddescr>Enable</fielddescr> + <fieldname>syncdestinenable</fieldname> + <description><![CDATA[Enable this host as a replication target]]></description> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>syncprotocol</fieldname> + <description><![CDATA[Choose the protocol used to sync with the destination host (HTTP or HTTPS).]]></description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>IP Address/Hostname</fielddescr> + <fieldname>ipaddress</fieldname> + <description><![CDATA[IP address or hostname of the destination host.]]></description> + <type>input</type> + <size>40</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>syncport</fieldname> + <description><![CDATA[Choose the sync port of the destination host.]]></description> + <type>input</type> + <size>3</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Username (admin)</fielddescr> + <fieldname>username</fieldname> + <description><![CDATA[Enter the username account for administration.]]></description> + <type>input</type> + <size>20</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Admin Password</fielddescr> + <fieldname>password</fieldname> + <description><![CDATA[Password of the user "admin" on the destination host.]]></description> + <type>password</type> + <size>20</size> + </rowhelperfield> </rowhelper> </field> </fields> diff --git a/config/avahi/avahi.inc b/config/avahi/avahi.inc index ba89676f..04f3b343 100644 --- a/config/avahi/avahi.inc +++ b/config/avahi/avahi.inc @@ -82,8 +82,8 @@ function avahi_write_config() { // Wide Area $widearea = ($avahi_config['enable_wide_area']) ? "yes" : "no"; // Publishing Options - $publish = ($avahi_config['disable_publishing']) ? "no" : "yes"; - $userpublish = ($avahi_config['disable_user_service_publishing']) ? "no" : "yes"; + $publish = ($avahi_config['disable_publishing']) ? "yes" : "no"; + $userpublish = ($avahi_config['disable_user_service_publishing']) ? "yes" : "no"; $addresspublish = ($avahi_config['publish_addresses']) ? "yes" : "no"; $cookie = ($avahi_config['add_service_cookie']) ? "yes" : "no"; $hinfopublish = ($avahi_config['publish_hinfo']) ? "yes" : "no"; diff --git a/config/filer/filer.inc b/config/filer/filer.inc index 7b795acb..63cdb302 100644 --- a/config/filer/filer.inc +++ b/config/filer/filer.inc @@ -103,75 +103,113 @@ function filer_validate_input($post, &$input_errors) { /* Uses XMLRPC to synchronize the changes to a remote node. */ function filer_sync_on_changes() { - global $config, $g; + global $config; - log_error("[filer] filer_xmlrpc_sync.php is starting."); - $synconchanges = $config['installedpackages']['filersync']['config'][0]['synconchanges']; - if (!$synconchanges) { - return; - } - foreach ($config['installedpackages']['filersync']['config'] as $rs) { - foreach ($rs['row'] as $sh) { - $sync_to_ip = $sh['ipaddress']; - $password = $sh['password']; - if ($sh['username']) { - $username = $sh['username']; - } else { - $username = 'admin'; - } - if ($password && $sync_to_ip) { - filer_do_xmlrpc_sync($sync_to_ip, $username, $password); + if (is_array($config['installedpackages']['filersync']['config'])) { + $filer_sync = $config['installedpackages']['filersync']['config'][0]; + $synconchanges = $filer_sync['synconchanges']; + $synctimeout = $filer_sync['synctimeout'] ?: '250'; + switch ($synconchanges) { + case "manual": + if (is_array($filer_sync['row'])) { + $rs = $filer_sync['row']; + } else { + log_error("[filer] XMLRPC sync is enabled but there are no hosts configured as replication targets."); + return; + } + break; + case "auto": + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; + $rs[0]['ipaddress'] = $system_carp['synchronizetoip']; + $rs[0]['username'] = $system_carp['username']; + $rs[0]['password'] = $system_carp['password']; + $rs[0]['syncdestinenable'] = FALSE; + + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['syncprotocol'] = "http"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['syncprotocol'] = "https"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '443'; + } + if ($system_carp['synchronizetoip'] == "") { + log_error("[filer] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } else { + $rs[0]['syncdestinenable'] = TRUE; + } + } else { + log_error("[filer] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } + break; + default: + return; + break; + } + if (is_array($rs)) { + log_error("[filer] XMLRPC sync is starting."); + foreach ($rs as $sh) { + // Only sync enabled replication targets + if ($sh['syncdestinenable']) { + $sync_to_ip = $sh['ipaddress']; + $port = $sh['syncport']; + $username = $sh['username'] ?: 'admin'; + $password = $sh['password']; + $protocol = $sh['syncprotocol']; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + filer_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout); + } else { + log_error("[filer] XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } + } } + log_error("[filer] XMLRPC sync completed."); } - } - log_error("[filer] filer_xmlrpc_sync.php is ending."); + } } /* Do the actual XMLRPC sync. */ -function filer_do_xmlrpc_sync($sync_to_ip, $username, $password) { +function filer_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) { global $config, $g; - if (!$username) { + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("[filer] A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; } - if (!$password) { - return; + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; } - if (!$sync_to_ip) { - return; - } + $url = "{$protocol}://{$sync_to_ip}"; - $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, let's 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 will hold the sections to sync. */ $xml = array(); $xml['filer'] = $config['installedpackages']['filer']; - /* 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("Beginning Filer XMLRPC sync to {$url}:{$port}."); + $params = array(XML_RPC_encode($password), XML_RPC_encode($xml)); + + /* Set a few variables needed for sync code */ $method = 'pfsense.merge_installedpackages_section_xmlrpc'; $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); @@ -180,19 +218,19 @@ function filer_do_xmlrpc_sync($sync_to_ip, $username, $password) { $cli->setDebug(1); } /* Send our XMLRPC message and timeout after 250 seconds. */ - $resp = $cli->send($msg, "250"); + $resp = $cli->send($msg, $synctimeout); if (!$resp) { - $error = "A communications error occurred while attempting filer XMLRPC sync with {$url}:{$port}."; - log_error($error); + $error = "A communications error occurred while attempting XMLRPC sync with {$url}:{$port}."; + log_error("[filer] {$error}"); file_notice("sync_settings", $error, "filer Settings Sync", ""); } elseif ($resp->faultCode()) { $cli->setDebug(1); - $resp = $cli->send($msg, "250"); - $error = "An error code was received while attempting filer XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $resp = $cli->send($msg, $synctimeout); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[filer] {$error}"); file_notice("sync_settings", $error, "filer Settings Sync", ""); } else { - log_error("filer XMLRPC sync successfully completed with {$url}:{$port}."); + log_error("[filer] XMLRPC sync successfully completed with {$url}:{$port}."); } /* Tell filer to reload our settings on the destination sync host. */ @@ -200,28 +238,25 @@ function filer_do_xmlrpc_sync($sync_to_ip, $username, $password) { $execcmd = "require_once('/usr/local/pkg/filer.inc');\n"; $execcmd .= "sync_package_filer();"; /* Assemble XMLRPC payload. */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($execcmd) - ); + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); - log_error("filer XMLRPC reload data {$url}:{$port}."); + log_error("[filer] 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, "250"); + $resp = $cli->send($msg, $synctimeout); if (!$resp) { - $error = "A communications error occurred while attempting filer XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; - log_error($error); + $error = "A communications error occurred while attempting XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; + log_error("[filer] {$error}"); file_notice("sync_settings", $error, "filer Settings Sync", ""); } elseif ($resp->faultCode()) { $cli->setDebug(1); - $resp = $cli->send($msg, "250"); - $error = "An error code was received while attempting filer XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $resp = $cli->send($msg, $synctimeout); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[filer] {$error}"); file_notice("sync_settings", $error, "filer Settings Sync", ""); } else { - log_error("filer XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); + log_error("[filer] XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); } } diff --git a/config/filer/filer_sync.xml b/config/filer/filer_sync.xml index 0b4124ce..1e3614d0 100644 --- a/config/filer/filer_sync.xml +++ b/config/filer/filer_sync.xml @@ -44,7 +44,7 @@ ]]> </copyright> <name>filersync</name> - <version>1.2</version> + <version>0.60.6</version> <title>Filer: Sync</title> <include_file>/usr/local/pkg/filer.inc</include_file> <tabs> @@ -61,50 +61,96 @@ <fields> <field> <type>listtopic</type> - <fieldname>temp</fieldname> - <name>Enable Filer configuration sync</name> + <name>XMLRPC Sync</name> </field> <field> - <fielddescr>Automatically sync Filer configuration changes.</fielddescr> + <fielddescr>Enable Sync</fielddescr> <fieldname>synconchanges</fieldname> - <description>pfSense will automatically sync changes to the hosts defined below. (Leave blank to use 'admin'.)</description> - <type>checkbox</type> + <description> + <![CDATA[ + Select a sync method for Filer.<br/><br/> + <strong>Important:</strong> While using "Sync to host(s) defined below", only sync from host A to B, A to C but <strong>do not</strong> enable XMLRPC sync <b>to</b> A. + This will result in a loop! + ]]> + </description> + <type>select</type> + <required/> + <default_value>disabled</default_value> + <options> + <option><name>Sync to configured system backup server</name><value>auto</value></option> + <option><name>Sync to host(s) defined below</name><value>manual</value></option> + <option><name>Do not sync this package configuration</name><value>disabled</value></option> + </options> </field> <field> - <fielddescr>Remote Servers</fielddescr> + <fielddescr>Sync Timeout</fielddescr> + <fieldname>synctimeout</fieldname> + <description>XMLRPC timeout in seconds.</description> + <type>select</type> + <required/> + <default_value>250</default_value> + <options> + <option><name>250 seconds (Default)</name><value>250</value></option> + <option><name>120 seconds</name><value>120</value></option> + <option><name>90 seconds</name><value>90</value></option> + <option><name>60 seconds</name><value>60</value></option> + <option><name>30 seconds</name><value>30</value></option> + </options> + </field> + <field> + <fielddescr>Replication Targets</fielddescr> <fieldname>none</fieldname> <type>rowhelper</type> <rowhelper> - <rowhelperfield> - <fielddescr>IP Address</fielddescr> - <fieldname>ipaddress</fieldname> - <description>IP Address of remote server.</description> - <type>input</type> - <size>20</size> - <required/> - </rowhelperfield> - <rowhelperfield> - <fielddescr>User Name</fielddescr> - <fieldname>username</fieldname> - <description>user name of remote server.</description> - <type>input</type> - <size>20</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Password</fielddescr> - <fieldname>password</fieldname> - <description>Password for remote server.</description> - <type>password</type> - <size>20</size> - <required/> - </rowhelperfield> + <rowhelperfield> + <fielddescr>Enable</fielddescr> + <fieldname>syncdestinenable</fieldname> + <description><![CDATA[Enable this host as a replication target]]></description> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>syncprotocol</fieldname> + <description><![CDATA[Choose the protocol used to sync with the destination host (HTTP or HTTPS).]]></description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>IP Address/Hostname</fielddescr> + <fieldname>ipaddress</fieldname> + <description><![CDATA[IP address or hostname of the destination host.]]></description> + <type>input</type> + <size>40</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>syncport</fieldname> + <description><![CDATA[Choose the sync port of the destination host.]]></description> + <type>input</type> + <size>3</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Username (admin)</fielddescr> + <fieldname>username</fieldname> + <description><![CDATA[Enter the username account for administration.]]></description> + <type>input</type> + <size>20</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Admin Password</fielddescr> + <fieldname>password</fieldname> + <description><![CDATA[Password of the user "admin" on the destination host.]]></description> + <type>password</type> + <size>20</size> + </rowhelperfield> </rowhelper> </field> </fields> <custom_php_resync_config_command> filer_sync_on_changes(); </custom_php_resync_config_command> - <custom_php_command_before_form> - unset($_POST['temp']); - </custom_php_command_before_form> </packagegui> diff --git a/config/freeradius2/freeradius.inc b/config/freeradius2/freeradius.inc index 6d626e3a..005a193a 100644 --- a/config/freeradius2/freeradius.inc +++ b/config/freeradius2/freeradius.inc @@ -1,19 +1,12 @@ <?php -/* copyright */ -/* ========================================================================== */ /* freeradius.inc - part of pfSense (http://www.pfSense.com) + part of pfSense (https://www.pfSense.org/) Copyright (C) 2013 Alexander Wilke <nachtfalkeaw@web.de> Copyright (C) 2013 Marcello Coutinho + Copyright (C) 2015 ESF, LLC All rights reserved. - Based on m0n0wall (http://m0n0.ch/wall) - Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>. - All rights reserved. - */ -/* ========================================================================== */ -/* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -34,9 +27,7 @@ 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. - */ -/* ========================================================================== */ - +*/ require_once('config.inc'); require_once('service-utils.inc'); require_once("util.inc"); @@ -630,7 +621,7 @@ if (is_array($arrusers) && !empty($arrusers)) { // If an octet limit is NOT set we delete the files for the limit and the counter. else { if (file_exists("/var/log/radacct/datacounter/$varusersmaxtotaloctetstimerange/max-octets-$varusersusername")) { unlink("/var/log/radacct/datacounter/$varusersmaxtotaloctetstimerange/max-octets-$varusersusername"); } - if (file_exists("/var/log/radacct/datacounter/$varusersmaxtotaloctetstimerange/used-octets-$varusersusername")) { unlink("/var/log/radacct/datacounter/$varusersmaxtotaloctetstimerange/used-octets-$varusersusername"); } + if (file_exists("/var/log/radacct/datacounter/$varusersmaxtotaloctetstimerange/used-octets-$varusersusername")) { unlink("/var/log/radacct/datacounter/$varusersmaxtotaloctetstimerange/used-octets-$varusersusername*"); } } if ($varusersadditionaloptionsreplyitems != '') { if ($varusersreplyitem != '') { $varusersreplyitem .=","; } @@ -824,7 +815,7 @@ if (is_array($arrmacs) && !empty($arrmacs)) { // If an octet limit is NOT set we delete the files for the limit and the counter. else { if (file_exists("/var/log/radacct/datacounter/$varmacsmaxtotaloctetstimerange/max-octets-$varmacsaddress")) { unlink("/var/log/radacct/datacounter/$varmacsmaxtotaloctetstimerange/max-octets-$varmacsaddress"); } - if (file_exists("/var/log/radacct/datacounter/$varmacsmaxtotaloctetstimerange/used-octets-$varmacsaddress")) { unlink("/var/log/radacct/datacounter/$varmacsmaxtotaloctetstimerange/used-octets-$varmacsaddress"); } + if (file_exists("/var/log/radacct/datacounter/$varmacsmaxtotaloctetstimerange/used-octets-$varmacsaddress")) { unlink("/var/log/radacct/datacounter/$varmacsmaxtotaloctetstimerange/used-octets-$varmacsaddress*"); } } if ($varmacsadditionaloptionsreplyitems != '') { if ($varmacsreplyitem != '') { $varmacsreplyitem .=","; } @@ -2571,163 +2562,181 @@ conf_mount_ro(); /* Uses XMLRPC to synchronize the changes to a remote node */ function freeradius_sync_on_changes() { - global $config, $g; - if (is_array($config['installedpackages']['freeradiussync'])){ + global $config; + + if (is_array($config['installedpackages']['freeradiussync'])) { $synconchanges = $config['installedpackages']['freeradiussync']['config'][0]['varsyncenablexmlrpc']; - $varsynctimeout = $config['installedpackages']['freeradiussync']['config'][0]['varsynctimeout']; - } - else - { + $varsynctimeout = $config['installedpackages']['freeradiussync']['config'][0]['varsynctimeout'] ?: '150'; + } else { return; } // if checkbox is NOT checked do nothing - switch ($synconchanges){ + switch ($synconchanges) { case "manual": - if (is_array($config['installedpackages']['freeradiussync']['config'][0]['row'])){ - $rs=$config['installedpackages']['freeradiussync']['config'][0]['row']; - } - else{ - log_error("[FreeRADIUS]: xmlrpc sync is enabled but there is no hosts to push on FreeRADIUS config."); + if (is_array($config['installedpackages']['freeradiussync']['config'][0]['row'])) { + $rs = $config['installedpackages']['freeradiussync']['config'][0]['row']; + } else { + log_error("[FreeRADIUS]: XMLRPC sync is enabled but there are no hosts configured as replication targets."); 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]['varsyncdestinenable']="on"; - $rs[0]['varsyncprotocol']=($config['system']['webgui']['protocol']!=""?$config['system']['webgui']['protocol']:"https"); - $rs[0]['varsyncipaddress']=$system_carp['synchronizetoip']; - $rs[0]['varsyncpassword']=$system_carp['password']; - $rs[0]['varsyncport']=($config['system']['webgui']['port']!=""?$config['system']['webgui']['port']:"443"); - if (! is_ipaddr($system_carp['synchronizetoip'])){ - log_error("[FreeRADIUS]: xmlrpc sync is enabled but there is no system backup hosts to push FreeRADIUS config."); - return; - } + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; + $rs[0]['varsyncipaddress'] = $system_carp['synchronizetoip']; + $rs[0]['varsyncusername'] = $system_carp['username']; + $rs[0]['varsyncpassword'] = $system_carp['password']; + $rs[0]['varsyncdestinenable'] = FALSE; + + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['varsyncprotocol'] = "http"; + $rs[0]['varsyncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['varsyncprotocol'] = "https"; + $rs[0]['varsyncport'] = $config['system']['webgui']['port'] ?: '443'; } - else{ - log_error("[FreeRADIUS]: xmlrpc sync is enabled but there is no system backup hosts to push FreeRADIUS config."); + if ($system_carp['synchronizetoip'] == "") { + log_error("[FreeRADIUS]: XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); return; + } else { + $rs[0]['varsyncdestinenable'] = TRUE; } + } else { + log_error("[FreeRADIUS]: XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } break; default: return; - break; - } - if (is_array($rs)){ - log_error("[FreeRADIUS]: xmlrpc sync is starting with timeout {$varsynctimeout} seconds."); - foreach($rs as $sh){ - if($sh['varsyncdestinenable']){ - $varsyncprotocol = $sh['varsyncprotocol']; - $sync_to_ip = $sh['varsyncipaddress']; - $password = $sh['varsyncpassword']; - $varsyncport = $sh['varsyncport']; - if($password && $sync_to_ip) - freeradius_do_xmlrpc_sync($sync_to_ip, $password, $varsyncport, $varsyncprotocol,$varsynctimeout); - else - log_error("[FreeRADIUS]: XMLRPC Sync with {$sh['varsyncipaddress']} has incomplete credentials. No XMLRPC Sync done!"); + break; + } + if (is_array($rs)) { + log_error("[FreeRADIUS]: XMLRPC sync is starting with timeout {$varsynctimeout} seconds."); + foreach ($rs as $sh) { + if ($sh['varsyncdestinenable']) { + $sync_to_ip = $sh['varsyncipaddress']; + $varsyncport = $sh['varsyncport']; + $varsyncprotocol = $sh['varsyncprotocol']; + $username = $sh['varsyncusername'] ?: 'admin'; + $password = $sh['varsyncpassword']; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; } - else { - log_error("[FreeRADIUS]: XMLRPC Sync with {$sh['varsyncipaddress']} is disabled"); + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; } + if (!is_port($varsyncport)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + freeradius_do_xmlrpc_sync($sync_to_ip, $username, $password, $varsyncport, $varsyncprotocol, $varsynctimeout); + } else { + log_error("[FreeRADIUS]: XMLRPC Sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } + } else { + log_error("[FreeRADIUS]: XMLRPC Sync with {$sh['varsyncipaddress']} is disabled"); } - log_error("[FreeRADIUS]: xmlrpc sync is ending."); - } + } + log_error("[FreeRADIUS]: XMLRPC sync is ending."); + } } /* Do the actual XMLRPC sync */ -function freeradius_do_xmlrpc_sync($sync_to_ip, $password, $varsyncport, $varsyncprotocol,$varsynctimeout) { +function freeradius_do_xmlrpc_sync($sync_to_ip, $username, $password, $varsyncport, $varsyncprotocol, $varsynctimeout) { global $config, $g; - if($varsynctimeout == '' || $varsynctimeout == 0) - $varsynctimeout = 150; - - if(!$password) + /* Detect boot process, do nothing during boot. */ + if (function_exists("platform_booting")) { + if (platform_booting()) { + return; + } + } elseif ($g['booting']) { return; + } - if(!$sync_to_ip) - return; - - if(!$varsyncport) + if ($username == "" || $password == "" || $sync_to_ip == "" || $varsyncport == "" || $varsyncprotocol == "") { + log_error("[FreeRADIUS]: A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; + } - if(!$varsyncprotocol) - return; - - // Check and choose correct protocol type, port number and IP address - $synchronizetoip .= "$varsyncprotocol" . '://'; - $port = "$varsyncport"; + /* Take care of IPv6 literal address */ + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; + } - $synchronizetoip .= $sync_to_ip; + $url = "{$varsyncprotocol}://{$sync_to_ip}"; + $port = $varsyncport; - /* xml will hold the sections to sync */ + /* XML will hold the sections to sync. */ $xml = array(); $xml['freeradius'] = $config['installedpackages']['freeradius']; $xml['freeradiusauthorizedmacs'] = $config['installedpackages']['freeradiusauthorizedmacs']; $xml['freeradiusclients'] = $config['installedpackages']['freeradiusclients']; - /* assemble xmlrpc payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($xml) - ); + /* 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; + /* Set a few variables needed for sync code */ log_error("[FreeRADIUS]: Beginning FreeRADIUS XMLRPC sync with {$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('admin', $password); - if($g['debug']) - $cli->setDebug(1); - /* send our XMLRPC message and timeout after $varsynctimeout seconds */ + $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, $varsynctimeout); + if (!$resp) { + $error = "A communications error occurred while FreeRADIUS was attempting XMLRPC sync with {$url}:{$port}."; + log_error("[FreeRADIUS]: {$error}"); + file_notice("sync_settings", $error, "FreeRADIUS Settings Sync", ""); + } elseif ($resp->faultCode()) { + $cli->setDebug(1); $resp = $cli->send($msg, $varsynctimeout); - if(!$resp) { - $error = "A communications error occurred while FreeRADIUS was attempting XMLRPC sync with {$url}:{$port}."; - log_error("[FreeRADIUS]: $error"); - file_notice("sync_settings", $error, "FreeRADIUS Settings Sync", ""); - } elseif($resp->faultCode()) { - $cli->setDebug(1); - $resp = $cli->send($msg, $varsynctimeout); - $error = "An error code was received while FreeRADIUS XMLRPC was attempting to sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error("[FreeRADIUS]: $error"); - file_notice("sync_settings", $error, "FreeRADIUS Settings Sync", ""); - } else { - log_error("[FreeRADIUS]: XMLRPC has synced data successfully with {$url}:{$port}."); - } + $error = "An error code was received while FreeRADIUS XMLRPC was attempting to sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[FreeRADIUS]: {$error}"); + file_notice("sync_settings", $error, "FreeRADIUS Settings Sync", ""); + } else { + log_error("[FreeRADIUS]: XMLRPC has synced data successfully with {$url}:{$port}."); + } - /* tell FreeRADIUS to reload our settings on the destionation sync host. */ + /* Tell FreeRADIUS to reload our settings on the destionation sync host. */ $method = 'pfsense.exec_php'; $execcmd = "require_once('/usr/local/pkg/freeradius.inc');\n"; - // pfblocker just needed one fuction to reload after XMLRPC. FreeRADIUS needs more so we point to a fuction below which contains all fuctions + /* pfblocker just needed one fuction to reload after XMLRPC. FreeRADIUS needs more so we point to a fuction below which contains all fuctions */ $execcmd .= "freeradius_all_after_XMLRPC_resync();"; - /* assemble xmlrpc payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($execcmd) - ); + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); log_error("[FreeRADIUS]: XMLRPC is reloading data on {$url}:{$port}."); $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); - $cli->setCredentials('admin', $password); + $cli->setCredentials($username, $password); + $resp = $cli->send($msg, $varsynctimeout); + if (!$resp) { + $error = "A communications error occurred while FreeRADIUS was attempting XMLRPC sync with {$url}:{$port} (exec_php)."; + log_error("[FreeRADIUS]: {$error}"); + file_notice("sync_settings", $error, "FreeRADIUS Settings Sync", ""); + } elseif ($resp->faultCode()) { + $cli->setDebug(1); $resp = $cli->send($msg, $varsynctimeout); - if(!$resp) { - $error = "A communications error occurred while FreeRADIUS was attempting XMLRPC sync with {$url}:{$port} (exec_php)."; - log_error($error); - file_notice("sync_settings", $error, "FreeRADIUS Settings Sync", ""); - } elseif($resp->faultCode()) { - $cli->setDebug(1); - $resp = $cli->send($msg, $varsynctimeout); - $error = "An error code was received while FreeRADIUS XMLRPC was attempting to sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); - file_notice("sync_settings", $error, "FreeRADIUS Settings Sync", ""); - } else { - log_error("[FreeRADIUS]: XMLRPC has reloaded data successfully on {$url}:{$port} (exec_php)."); - } - + $error = "An error code was received while FreeRADIUS XMLRPC was attempting to sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[FreeRADIUS]: {$error}"); + file_notice("sync_settings", $error, "FreeRADIUS Settings Sync", ""); + } else { + log_error("[FreeRADIUS]: XMLRPC has reloaded data successfully on {$url}:{$port} (exec_php)."); + } } // This function restarts all other needed functions after XMLRPC so that the content of .XML + .INC will be written in the files (clients.conf, users) @@ -2738,7 +2747,7 @@ function freeradius_all_after_XMLRPC_resync() { freeradius_authorizedmacs_resync(); freeradius_clients_resync(); - log_error("FreeRADIUS: Finished XMLRPC process. It should be OK. For more information look at the host which started sync."); + log_error("[FreeRADIUS]: Finished XMLRPC process. It should be OK. For more information look at the host which started sync."); exec(FREERADIUS_ETC . "/rc.d/radiusd onerestart"); } @@ -4123,20 +4132,20 @@ function freeradius_modulesdatacounter_resync() { $conf .= <<<EOD exec datacounterdaily { wait = yes - program = "/bin/sh {$varFREERADIUS_ETC}/raddb/scripts/datacounter_acct.sh %{request:User-Name} daily %{request:Acct-Input-Octets} %{request:Acct-Output-Octets}" + program = "/bin/sh {$varFREERADIUS_ETC}/raddb/scripts/datacounter_acct.sh %{request:User-Name} daily %{request:Acct-Input-Octets} %{request:Acct-Output-Octets} %{request:Acct-Status-Type} %{request:Acct-Session-Id}" } exec datacounterweekly { wait = yes - program = "/bin/sh {$varFREERADIUS_ETC}/raddb/scripts/datacounter_acct.sh %{request:User-Name} weekly %{request:Acct-Input-Octets} %{request:Acct-Output-Octets}" + program = "/bin/sh {$varFREERADIUS_ETC}/raddb/scripts/datacounter_acct.sh %{request:User-Name} weekly %{request:Acct-Input-Octets} %{request:Acct-Output-Octets} %{request:Acct-Status-Type} %{request:Acct-Session-Id}" } exec datacountermonthly { wait = yes - program = "/bin/sh {$varFREERADIUS_ETC}/raddb/scripts/datacounter_acct.sh %{request:User-Name} monthly %{request:Acct-Input-Octets} %{request:Acct-Output-Octets}" + program = "/bin/sh {$varFREERADIUS_ETC}/raddb/scripts/datacounter_acct.sh %{request:User-Name} monthly %{request:Acct-Input-Octets} %{request:Acct-Output-Octets} %{request:Acct-Status-Type} %{request:Acct-Session-Id}" } exec datacounterforever { wait = yes - program = "/bin/sh {$varFREERADIUS_ETC}/raddb/scripts/datacounter_acct.sh %{request:User-Name} forever %{request:Acct-Input-Octets} %{request:Acct-Output-Octets}" - } + program = "/bin/sh {$varFREERADIUS_ETC}/raddb/scripts/datacounter_acct.sh %{request:User-Name} forever %{request:Acct-Input-Octets} %{request:Acct-Output-Octets} %{request:Acct-Status-Type} %{request:Acct-Session-Id}" + } EOD; $filename = FREERADIUS_ETC . '/raddb/modules/datacounter_acct'; @@ -4162,18 +4171,19 @@ TIMERANGE=`echo -n "\\$2" | sed 's/[^a-z]//g' ` ### This is to make sure there is a used-octets file after the cronjob resetted the counter if [ -e "/var/log/radacct/datacounter/\$TIMERANGE/max-octets-\$USERNAME" ] && [ ! -e "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME" ]; then echo 0 > "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME" + rm "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME-"* fi ### The next two lines are just for getting values for logging output -MAXOCTETSUSERNAMEMB=$((`cat "/var/log/radacct/datacounter/\$TIMERANGE/max-octets-\$USERNAME"`/1024/1024)) -USEDOCTETSUSERNAMEMB=$((`cat "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME"`/1024/1024)) - +MAXOCTETSUSERNAMEMB=$((`/bin/cat "/var/log/radacct/datacounter/\$TIMERANGE/max-octets-\$USERNAME"`/1024/1024)) +USEDOCTETSUSERNAMEMB=`/bin/cat "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\${USERNAME}"* | /usr/bin/awk '{ SUM += \$1; } END { print int(SUM/1024/1024); }'` + ### We check if MAX-OCTETS-USERNAME is greater than USED-OCTETS-USERNAME and accept or reject the user -if [ `cat "/var/log/radacct/datacounter/\$TIMERANGE/max-octets-\$USERNAME"` -gt `cat "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME"` ]; then - logger -f /var/log/system.log "FreeRADIUS: Used amount of \$TIMERANGE traffic by \$USERNAME is \$USEDOCTETSUSERNAMEMB MB of \$MAXOCTETSUSERNAMEMB MB! The user was accepted!!!" +if [ \$MAXOCTETSUSERNAMEMB -gt \$USEDOCTETSUSERNAMEMB ]; then + logger -f /var/log/system.log "FreeRADIUS: User \$USERNAME has used \$USEDOCTETSUSERNAMEMB MB of \$MAXOCTETSUSERNAMEMB MB \$TIMERANGE allotted traffic. The login request was accepted." exit 0 else - logger -f /var/log/system.log "FreeRADIUS: Credentials are probably correct but the user \$USERNAME has reached the \$TIMERANGE Amount of Upload and Download Traffic which is \$USEDOCTETSUSERNAMEMB MB of \$MAXOCTETSUSERNAMEMB MB! The user was rejected!!!" + logger -f /var/log/system.log "FreeRADIUS: User \$USERNAME has reached the \$TIMERANGE amount of upload and download traffic (\$USEDOCTETSUSERNAMEMB MB of \$MAXOCTETSUSERNAMEMB MB). The login request was denied." exit 99 fi EOD; @@ -4198,6 +4208,8 @@ USERNAME=`echo -n "\\$1" | sed 's/[^0-9a-zA-Z.:_-]/X/g' ` TIMERANGE=`echo -n "\\$2" | sed 's/[^a-z]//g' ` ACCTINPUTOCTETS=`echo -n "\\$3" | sed 's/[^0-9]/0/g' ` ACCTOUTPUTOCTETS=`echo -n "\\$4" | sed 's/[^0-9]/0/g' ` +UPDATETYPE=\$5 +SESSIONID=\$6 ### If we do not get Octets we set some default values if [ ! \$ACCTINPUTOCTETS ]; then @@ -4216,11 +4228,23 @@ else if [ ! -e "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME" ]; then echo 0 > "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME" fi -### The following two lines (chose the one or the other) are a bad workaround to make accounting accurate with stop/start accounting on pfsense 2.0.1 - it only works if the session will not be interrupted (host disconnects) -### USEDOCTETS=\$((\$ACCTINPUTOCTETS+\$ACCTOUTPUTOCTETS)) - USEDOCTETS=\$((\$ACCTINPUTOCTETS+\$ACCTOUTPUTOCTETS+`cat "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME"`)) - - echo "\$USEDOCTETS" > "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME" + + USEDOCTETS=\$((\$ACCTINPUTOCTETS+\$ACCTOUTPUTOCTETS)) + + # If this is an interim update, track it in a separate session file + # since the incoming data is a gauge not a counter. + if [ \$UPDATETYPE = "Interim-Update" ]; then + echo \$USEDOCTETS > "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME-\$SESSIONID" + else + USEDOCTETS=\$((\$USEDOCTETS+`cat "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME"`)) + + # If there was a session file for this session (from interim updates) clear it since the equivalent + # value was just added to the total. + if [ -e "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME-\$SESSIONID" ]; then + rm "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME-\$SESSIONID" + fi + echo "\$USEDOCTETS" > "/var/log/radacct/datacounter/\$TIMERANGE/used-octets-\$USERNAME" + fi exit 0 fi diff --git a/config/freeradius2/freeradius.xml b/config/freeradius2/freeradius.xml index 4563ef62..eab6b09a 100644 --- a/config/freeradius2/freeradius.xml +++ b/config/freeradius2/freeradius.xml @@ -45,7 +45,7 @@ <requirements>Describe your package requirements here</requirements> <faq>Currently there are no FAQ items provided.</faq> <name>freeradius</name> - <version>1.6.13</version> + <version>1.6.17</version> <title>FreeRADIUS: Users</title> <include_file>/usr/local/pkg/freeradius.inc</include_file> <menu> diff --git a/config/freeradius2/freeradiussync.xml b/config/freeradius2/freeradiussync.xml index 61c7eecb..d36c8b3f 100644 --- a/config/freeradius2/freeradiussync.xml +++ b/config/freeradius2/freeradiussync.xml @@ -1,51 +1,47 @@ <?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd"> -<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> +<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> <copyright> -<![CDATA[ + <![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* -freeradiussync.xml -part of pfSense (http://www.pfSense.com) -Copyright (C) 2013 Alexander Wilke <nachtfalkeaw@web.de> -Copyright (C) 2013 Marcello Coutinho <marcellocoutinho@gmail.com> -based on pfblocker_sync.xml -All rights reserved. - -Based on m0n0wall (http://m0n0.ch/wall) -Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>. -All rights reserved. + freeradiussync.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2013 Alexander Wilke <nachtfalkeaw@web.de> + Copyright (C) 2013 Marcello Coutinho <marcellocoutinho@gmail.com> + Copyright (C) 2015 ESF, LLC + All rights reserved. */ -/* ========================================================================== */ +/* ====================================================================================== */ /* -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + 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. -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. -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. + 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. */ -/* ========================================================================== */ -]]></copyright> - <description><![CDATA[Describe your package here]]></description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> +/* ====================================================================================== */ + ]]> + </copyright> <name>freeradiussync</name> <version>2.2.0</version> <title>FreeRADIUS: XMLRPC Sync</title> @@ -111,8 +107,13 @@ POSSIBILITY OF SUCH DAMAGE. <field> <fielddescr>Enable Sync</fielddescr> <fieldname>varsyncenablexmlrpc</fieldname> - <description><![CDATA[All changes will be synced immediately to the IPs listed below if this option is checked.<br> - <b>Important:</b> While using "Sync to hosts defined below", only sync from host A to B, A to C but <b>do not</B> enable XMLRPC sync <b>to</b> A. This will result in a loop!]]></description> + <description> + <![CDATA[ + Select a sync method for FreeRADIUS.<br /> + <b>Important:</b> While using "Sync to host(s) defined below", only sync from host A to B, A to C but <b>do not</B> enable XMLRPC sync <b>to</b> A. + This will result in a loop! + ]]> + </description> <type>select</type> <required/> <default_value>auto</default_value> @@ -127,7 +128,7 @@ POSSIBILITY OF SUCH DAMAGE. <fieldname>varsynctimeout</fieldname> <description><![CDATA[Timeout in seconds for the XMLRPC timeout. Default: 150]]></description> <type>input</type> - <default_value>150</default_value> + <default_value>150</default_value> <size>5</size> </field> @@ -144,7 +145,7 @@ POSSIBILITY OF SUCH DAMAGE. <rowhelperfield> <fielddescr>GUI Protocol</fielddescr> <fieldname>varsyncprotocol</fieldname> - <description><![CDATA[Choose the protocol of the destination host. Probably <b>http</b> or <b>https</b>]]></description> + <description><![CDATA[Choose the protocol of the destination host (HTTP or HTTPS).]]></description> <type>select</type> <default_value>HTTP</default_value> <options> @@ -153,9 +154,9 @@ POSSIBILITY OF SUCH DAMAGE. </options> </rowhelperfield> <rowhelperfield> - <fielddescr>GUI IP-Address</fielddescr> + <fielddescr>GUI IP Address/Hostname</fielddescr> <fieldname>varsyncipaddress</fieldname> - <description><![CDATA[IP Address of the destination host.]]></description> + <description><![CDATA[IP Address or hostname of the destination host.]]></description> <type>input</type> <size>15</size> </rowhelperfield> @@ -178,7 +179,7 @@ POSSIBILITY OF SUCH DAMAGE. </fields> <custom_delete_php_command> freeradius_sync_on_changes(); - </custom_delete_php_command> + </custom_delete_php_command> <custom_php_resync_config_command> freeradius_sync_on_changes(); </custom_php_resync_config_command> diff --git a/config/haproxy-devel/haproxy.priv.inc b/config/haproxy-devel/haproxy.priv.inc new file mode 100644 index 00000000..e4914db8 --- /dev/null +++ b/config/haproxy-devel/haproxy.priv.inc @@ -0,0 +1,50 @@ +<?php +/* + haproxy.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-service-haproxy'] = array(); +$priv_list['page-service-haproxy']['name'] = "WebCfg - Services: HAProxy package"; +$priv_list['page-service-haproxy']['descr'] = "Allow access to HAProxy package GUI"; +$priv_list['page-service-haproxy']['match'] = array(); + +$priv_list['page-service-haproxy']['match'][] = "haproxy_files.php*"; +$priv_list['page-service-haproxy']['match'][] = "haproxy_global.php*"; +$priv_list['page-service-haproxy']['match'][] = "haproxy_listeners.php*"; +$priv_list['page-service-haproxy']['match'][] = "haproxy_listeners_edit.php*"; +$priv_list['page-service-haproxy']['match'][] = "haproxy_pool_edit.php*"; +$priv_list['page-service-haproxy']['match'][] = "haproxy_pools.php*"; +$priv_list['page-service-haproxy']['match'][] = "haproxy_templates.php*"; + +$priv_list['page-service-haproxy-stats'] = array(); +$priv_list['page-service-haproxy-stats']['name'] = "WebCfg - Services: HAProxy package stats"; +$priv_list['page-service-haproxy-stats']['descr'] = "Allow access to HAProxy package GUI stats"; +$priv_list['page-service-haproxy-stats']['match'] = array(); +$priv_list['page-service-haproxy-stats']['match'][] = "haproxy_stats.php*"; + +?>
\ No newline at end of file diff --git a/config/haproxy-devel/haproxy.xml b/config/haproxy-devel/haproxy.xml index 429b6c9f..19b6b577 100644 --- a/config/haproxy-devel/haproxy.xml +++ b/config/haproxy-devel/haproxy.xml @@ -42,7 +42,7 @@ ]]> </copyright> <name>haproxy</name> - <version>0.29</version> + <version>0.33</version> <title>HAProxy</title> <aftersaveredirect>/pkg_edit.php?xml=haproxy_pools.php</aftersaveredirect> <include_file>/usr/local/pkg/haproxy.inc</include_file> @@ -146,6 +146,10 @@ <prefix>/usr/local/www/javascript/</prefix> <item>https://packages.pfsense.org/packages/config/haproxy-devel/www/javascript/haproxy_geturl.js</item> </additional_files_needed> + <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy.priv.inc</item> + </additional_files_needed> <custom_php_install_command> haproxy_custom_php_install_command(); </custom_php_install_command> diff --git a/config/haproxy-devel/pkg/haproxy.inc b/config/haproxy-devel/pkg/haproxy.inc index 1bc62cb9..3d614fe0 100644 --- a/config/haproxy-devel/pkg/haproxy.inc +++ b/config/haproxy-devel/pkg/haproxy.inc @@ -37,7 +37,7 @@ require_once("haproxy_utils.inc"); require_once("haproxy_xmlrpcsyncclient.inc"); $d_haproxyconfdirty_path = $g['varrun_path'] . "/haproxy.conf.dirty"; - +#region Global haproxy array item definitions.. global $a_frontendmode; $a_frontendmode = array(); $a_frontendmode['http'] = array('name' => "http / https(offloading)", 'shortname' => "http/https"); @@ -66,7 +66,12 @@ $a_acltypes["path_matches"] = array('name' => 'Path matches:', $a_acltypes["path_regex"] = array('name' => 'Path regex:', 'mode' => 'http', 'syntax' => 'path_reg -i %1$s'); $a_acltypes["path_contains"] = array('name' => 'Path contains:', - 'mode' => 'http', 'syntax' => 'path_dir -i %1$s'); + 'mode' => 'http', 'syntax' => 'path_sub -i %1$s'); +$a_acltypes["url_parameter"] = array('name' => 'Url parameter contains:', + 'mode' => 'http', 'syntax' => 'url_param({parameter}) -i %1$s', + 'fields' => array( + array('name'=>"parameter",'columnheader'=>"Parameter name",'type'=>"textbox",'size'=>"50",'mask'=>'urlparameter') + )); $a_acltypes["ssl_c_verify_code"] = array('name' => 'SSL Client certificate verify error result:', 'mode' => 'http', 'syntax' => 'ssl_c_verify %1$s', 'require_client_cert' => '1'); // ssl_c_verify result codes: https://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS @@ -77,7 +82,10 @@ $a_acltypes["ssl_c_ca_commonname"] = array('name' => 'SSL Client issued by CA co $a_acltypes["source_ip"] = array('name' => 'Source IP matches IP or Alias:', 'mode' => '', 'syntax' => 'src %1$s'); $a_acltypes["backendservercount"] = array('name' => 'Minimum count usable servers:', - 'mode' => '', 'syntax' => 'nbsrv(%2$s) ge %1$d', 'parameters' => 'value,backendname'); + 'mode' => '', 'syntax' => 'nbsrv({backend}) ge %1$d', 'parameters' => 'value,backendname', + 'fields' => array( + 'backend' => array('name'=>"backend",'columnheader'=>"Backend",'type'=>"select",'size'=>"50",'mask'=>'backend') + )); $a_acltypes["traffic_is_http"] = array('name' => 'Traffic is http (no value needed):', 'inspect-delay' => '5', 'mode' => 'tcp', 'syntax' => 'req.proto_http', 'advancedoptions' => "tcp-request content accept if { req.proto_http }"); $a_acltypes["traffic_is_ssl"] = array('name' => 'Traffic is ssl (no value needed):', 'inspect-delay' => '5', @@ -224,7 +232,144 @@ $a_sysloglevel['notice'] = array('name' => "Notice"); $a_sysloglevel['info'] = array('name' => "Informational"); $a_sysloglevel['debug'] = array('name' => "Debugging"); -if(!function_exists('group_ports')){ +global $a_filestype; +$a_filestype = array(); +$a_filestype[''] = array('name' => "Errorfile"); +$a_filestype['luascript'] = array('name' => "Lua script"); +$a_filestype['writetodisk'] = array('name' => "Write to disk"); + +global $a_action; +$a_action = array(); +// +$a_action["use_backend"] = array('name' => "Use Backend", 'mode' => '', 'syntax' => 'use_backend {backend}', 'usage' => 'frontend', + 'fields' => array( + 'backend' => array('name'=>"backend",'columnheader'=>"Backend",'type'=>"select",'size'=>"50",'mask'=>'backend') + )); +$a_action["use_server"] = array('name' => "Use Server", 'mode' => '', 'syntax' => 'use-server {server}', 'usage' => 'backend', + 'fields' => array( + 'server' => array('name'=>"server",'columnheader'=>"Server",'type'=>"select",'size'=>"50",'mask'=>'server') + )); +// +$a_action["custom"] = array('name' => "Custom", 'mode' => '', + 'fields' => array( + array('name'=>"customaction",'columnheader'=>"Custom action",'type'=>"textbox",'size'=>"50",'mask'=>'freetext') + )); +// +$a_action["http-request_allow"] = array('name' => "http-request allow", 'mode'=> 'http', 'syntax' => 'http-request allow'); +$a_action["http-request_deny"] = array('name' => "http-request deny", 'mode'=> 'http', 'syntax' => 'http-request deny'); +$a_action["http-request_tarpit"] = array('name' => "http-request tarpit", 'mode'=> 'http', 'syntax' => 'http-request tarpit'); +$a_action["http-request_auth"] = array('name' => "http-request auth", 'mode'=> 'http', 'syntax' => 'http-request auth {realm}', + 'fields' => array( + array('name'=>"realm",'columnheader'=>"Realm",'type'=>"textbox",'size'=>"50",'mask'=>'freetext') + ) +); +$a_action["http-request_redirect"] = array('name' => "http-request redirect", 'mode'=> 'http', 'syntax' => 'http-request redirect {rule}', + 'fields' => array( + array('name'=>"rule",'columnheader'=>"Rule",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + ) +); +if (haproxy_version() >= '1.6') { + $a_action["http-request_lua"] = array('name' => "http-request lua action", 'mode'=> 'http', 'syntax' => 'http-request lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); + $a_action["http-request_use-service"] = array('name' => "http-request lua service", 'mode'=> 'http', 'syntax' => 'http-request use-service lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); +} +$a_action["http-request_add-header"] = array('name' => "http-request header add", 'mode'=> 'http', 'syntax' => 'http-request add-header {name} {fmt}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"fmt",'columnheader'=>"New logformat value",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + )); +$a_action["http-request_set-header"] = array('name' => "http-request header set", 'mode'=> 'http', 'syntax' => 'http-request set-header {name} {fmt}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"fmt",'columnheader'=>"New logformat value",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + )); +$a_action["http-request_del-header"] = array('name' => "http-request header delete", 'mode'=> 'http', 'syntax' => 'http-request del-header {name}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername') + )); +$a_action["http-request_replace-header"] = array('name' => "http-request header replace", 'mode'=> 'http', 'syntax' => 'http-request replace-header {name} {find} {replace}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"find",'columnheader'=>"Find regex",'type'=>"textbox",'size'=>"50",'mask'=>'match-regex'), + array('name'=>"replace",'columnheader'=>"Replace by",'type'=>"textbox",'size'=>"50",'mask'=>'replace-fmt') + )); +$a_action["http-request_replace-value"] = array('name' => "http-request header replace value", 'mode'=> 'http', 'syntax' => 'http-request replace-value {name} {find} {replace}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"find",'columnheader'=>"Find regex",'type'=>"textbox",'size'=>"50",'mask'=>'match-regex'), + array('name'=>"replace",'columnheader'=>"Replace by",'type'=>"textbox",'size'=>"50",'mask'=>'replace-fmt') + )); +// +$a_action["http-response_allow"] = array('name' => "http-response allow", 'mode'=> 'http', 'syntax' => 'http-response allow'); +$a_action["http-response_deny"] = array('name' => "http-response deny", 'mode'=> 'http', 'syntax' => 'http-response deny'); +if (haproxy_version() >= '1.6') { + $a_action["http-response_lua"] = array('name' => "http-response lua script", 'mode'=> 'http', 'syntax' => 'http-response lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); +} +$a_action["http-response_add-header"] = array('name' => "http-response header add", 'mode'=> 'http', 'syntax' => 'http-response add-header {name} {fmt}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"fmt",'columnheader'=>"New logformat value",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + )); +$a_action["http-response_set-header"] = array('name' => "http-response header set", 'mode'=> 'http', 'syntax' => 'http-response set-header {name} {fmt}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"fmt",'columnheader'=>"New logformat value",'type'=>"textbox",'size'=>"50",'mask'=>'logformat') + )); +$a_action["http-response_del-header"] = array('name' => "http-response header delete", 'mode'=> 'http', 'syntax' => 'http-response del-header {name}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername') + )); +$a_action["http-response_replace-header"] = array('name' => "http-response header replace", 'mode'=> 'http', 'syntax' => 'http-response replace-header {name} {find} {replace}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"find",'columnheader'=>"Find regex",'type'=>"textbox",'size'=>"50",'mask'=>'match-regex'), + array('name'=>"replace",'columnheader'=>"Replace by",'type'=>"textbox",'size'=>"50",'mask'=>'replace-fmt') + )); +$a_action["http-response_replace-value"] = array('name' => "http-response header replace value", 'mode'=> 'http', 'syntax' => 'http-response replace-value {name} {find} {replace}', + 'fields' => array( + array('name'=>"name",'columnheader'=>"Headername",'type'=>"textbox",'size'=>"50",'mask'=>'headername'), + array('name'=>"find",'columnheader'=>"Find regex",'type'=>"textbox",'size'=>"50",'mask'=>'match-regex'), + array('name'=>"replace",'columnheader'=>"Replace by",'type'=>"textbox",'size'=>"50",'mask'=>'replace-fmt') + )); +// +$a_action["tcp-request_connection_accept"] = array('name' => "tcp-request connection accept", 'mode'=> '', 'syntax' => 'tcp-request connection accept'); +$a_action["tcp-request_connection_reject"] = array('name' => "tcp-request connection reject", 'mode'=> '', 'syntax' => 'tcp-request connection reject'); +// +$a_action["tcp-request_content_accept"] = array('name' => "tcp-request content accept", 'mode'=> '', 'syntax' => 'tcp-request content accept'); +$a_action["tcp-request_content_reject"] = array('name' => "tcp-request content reject", 'mode'=> '', 'syntax' => 'tcp-request content reject'); +if (haproxy_version() >= '1.6') { + $a_action["tcp-request_content_lua"] = array('name' => "tcp-request content lua script", 'mode'=> '', 'syntax' => 'tcp-request content lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); + $a_action["tcp-request_content_use-service"] = array('name' => "tcp-request content use-service", 'mode'=> '', 'syntax' => 'tcp-request content use-service lua.{lua-function}', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); +} +// +$a_action["tcp-response_content_accept"] = array('name' => "tcp-response content accept", 'mode'=> '', 'syntax' => 'tcp-response content accept'); +$a_action["tcp-response_content_close"] = array('name' => "tcp-response content close", 'mode'=> '', 'syntax' => 'tcp-response content close'); +$a_action["tcp-response_content_reject"] = array('name' => "tcp-response content reject", 'mode'=> '', 'syntax' => 'tcp-response content reject'); +if (haproxy_version() >= '1.6') { + $a_action["tcp-response_content_lua"] = array('name' => "tcp-response content lua script", 'mode'=> '', 'syntax' => 'tcp-response content lua.{lua-function}', 'usage' => 'backend', + 'fields' => array( + 'lua-function' => array('name'=>"lua-function",'columnheader'=>"lua function",'type'=>"textbox",'size'=>"50",'mask'=>'lua-function') + )); +} + +#end + + +if (!function_exists('group_ports')) { // function group_ports() is present in pfSense 2.2 in util.inc /* create ranges of sequential port numbers (200:215) and remove duplicates */ function group_ports($ports) { @@ -243,7 +388,7 @@ function group_ports($ports) { for ($i = $begin; $i <= $end; $i++) if (!in_array($i, $uniq)) $uniq[] = $i; - } else if (is_port($port)) { + } elseif (is_port($port)) { if (!in_array($port, $uniq)) $uniq[] = $port; } @@ -276,7 +421,7 @@ function group_ports($ports) { } global $haproxy_version; -function haproxy_verion() { +function haproxy_version() { global $haproxy_version; if (empty($haproxy_version)) { $haproxy_version = shell_exec("haproxy -v | head -n 1 | awk '{ print $3 }'"); @@ -284,6 +429,89 @@ function haproxy_verion() { return $haproxy_version; } +function haproxy_css() { + if (!file_exists("/usr/local/www/bootstrap")) + return; + // quick fix to look a bit decent on bootstrapped pfSense.. + echo <<<EOD +<style type="text/css"> +.listtopic { + border-right: 1px solid #999999; + font-size: 11px; + background-color: #990000; + padding-right: 16px; + padding-left: 6px; + color: #FFFFFF; + font-weight: bold; + padding-top: 5px; + padding-bottom: 5px; +} +.tabcont { + background-color: #DDDDDD; + padding-right: 12px; + padding-left: 12px; + padding-top: 12px; + padding-bottom: 12px; +} +.vtable { + border-bottom: 1px solid #999999; +} +.vncell { + background-color: #DDDDDD; + padding-right: 20px; + padding-left: 8px; + border-bottom: 1px solid #999999; +} +.vncellreq { + background-color: #DDDDDD; + padding-right: 20px; + padding-left: 8px; + font-weight: bold; + border-bottom: 1px solid #999999; +} +.listhdrr { + background-color: #BBBBBB; + padding-right: 6px; + padding-left: 6px; + font-weight: bold; + border-right: 1px solid #999999; + border-bottom: 1px solid #999999; + font-size: 11px; + padding-top: 5px; + padding-bottom: 5px; +} +.listr { + background-color: #FFFFFF; + border-right: 1px solid #999999; + border-bottom: 1px solid #999999; + font-size: 11px; + padding-right: 6px; + padding-left: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +.listlr { + background-color: #FFFFFF; + border-right: 1px solid #999999; + border-bottom: 1px solid #999999; + border-left: 1px solid #999999; + font-size: 11px; + padding-right: 6px; + padding-left: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +.tabcont { + background-color: #DDDDDD; + padding-right: 12px; + padding-left: 12px; + padding-top: 12px; + padding-bottom: 12px; +} +</style> +EOD; +} + function haproxy_portoralias_to_list($port_or_alias) { // input: a port or aliasname: 80 https MyPortAlias // returns: a array of ports and portranges 80 443 8000:8010 @@ -298,7 +526,7 @@ function haproxy_portoralias_to_list($port_or_alias) { $portresult = array_merge($portresult, $portresults); } return $portresult; - } else if (is_portrange($port_or_alias)) { + } elseif (is_portrange($port_or_alias)) { return (array)$port_or_alias; } else { $ports = explode(",", $port_or_alias); @@ -420,7 +648,7 @@ haproxy_start () { require_once("haproxy.inc"); haproxy_configure(); ?> -ENDOFF +ENDOFF } haproxy_check () { @@ -504,10 +732,11 @@ function haproxy_find_backend($backendname) { function haproxy_find_acl($name) { global $a_acltypes; - if($a_acltypes) { + if ($a_acltypes) { foreach ($a_acltypes as $key => $acl) { - if ($key == $name) + if ($key == $name) { return $acl; + } } } } @@ -517,25 +746,30 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { $frontend = $backendsettings['frontend']; $ipversion = $backendsettings['ipversion']; $a_global = &$config['installedpackages']['haproxy']; - $a_mailers = &$config['installedpackages']['haproxy']['email_mailers']['items']; + $a_mailers = &$config['installedpackages']['haproxy']['email_mailers']['item']; + $a_resolvers = $config['installedpackages']['haproxy']['dns_resolvers']['item']; - if(!is_array($pool['ha_servers']['item']) && !$pool['stats_enabled']=='yes') + if (!is_array($pool['ha_servers']['item']) && !$pool['stats_enabled']=='yes') { return; + } global $a_checktypes, $a_cookiemode, $a_files_cache, $a_error; - + + $server_options = ""; $a_servers = &$pool['ha_servers']['item']; $frontendtype = $frontend['type']; fwrite ($fd, "backend " . $name . "\n"); // https is an alias for tcp for clarity purposes - if($frontendtype == "https") { + if ($frontendtype == "https") { $backend_mode = "tcp"; } else { $backend_mode = $frontendtype; } fwrite ($fd, "\tmode\t\t\t" . $backend_mode . "\n"); - - if (haproxy_verion() >= '1.6') { + fwrite ($fd, "\tlog\t\t\tglobal\n"); + + $use_haproxyresolvers = false; + if (haproxy_version() >= '1.6') { $use_mailers = is_array($a_mailers) && count($a_mailers) > 0; if ($use_mailers) { fwrite ($fd, "\t# use mailers\n"); @@ -562,6 +796,14 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } } } + + $use_resolvers = is_array($a_resolvers) && count($a_resolvers) > 0; + if ($use_resolvers) { + $use_haproxyresolvers = true; + //server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6 + $resolverprefer = ($ipversion == "ipv4" || $ipversion == "ipv6") ? $resolverprefer = " resolve-prefer {$ipversion}" : ""; + $server_options .= " resolvers globalresolvers" . $resolverprefer; + } } if ($pool['log-health-checks'] == 'yes') @@ -586,39 +828,46 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { fwrite ($fd, "\trspirep ^(Set-Cookie:((?!;\\ secure).)*)$ \\1;\ secure if { ssl_fc }\n"); } - if($pool['stats_enabled']=='yes') { + if ($pool['stats_enabled'] == 'yes') { fwrite ($fd, "\tstats\t\t\tenable\n"); - if($pool['stats_uri']) + if ($pool['stats_uri']) { fwrite ($fd, "\tstats\t\t\turi ".$pool['stats_uri']."\n"); - if($pool['stats_realm']) + } + if ($pool['stats_realm']) { fwrite ($fd, "\tstats\t\t\trealm " . haproxy_escapestring($pool['stats_realm']) . "\n"); - else + } else { fwrite ($fd, "\tstats\t\t\trealm .\n"); + } - if ($pool['stats_username'] && $pool['stats_password']) + if ($pool['stats_username'] && $pool['stats_password']) { fwrite ($fd, "\tstats\t\t\tauth " . haproxy_escapestring($pool['stats_username']).":". haproxy_escapestring($pool['stats_password'])."\n"); - - if($pool['stats_admin']=='yes') + } + if ($pool['stats_admin'] == 'yes') { fwrite ($fd, "\tstats\t\t\tadmin if TRUE" . "\n"); - - if($pool['stats_node']) + } + if ($pool['stats_node']) { fwrite ($fd, "\tstats\t\t\tshow-node " . $pool['stats_node'] . "\n"); - if($pool['stats_desc']) + } + if ($pool['stats_desc']) { fwrite ($fd, "\tstats\t\t\tshow-desc " . haproxy_escapestring($pool['stats_desc']) . "\n"); - if($pool['stats_refresh']) + } + if ($pool['stats_refresh']) { fwrite ($fd, "\tstats\t\t\trefresh " . $pool['stats_refresh'] . "\n"); + } if ($pool['stats_scope']) { $scope_items = explode(",", $pool['stats_scope']); - foreach($scope_items as $scope_item) + foreach($scope_items as $scope_item) { fwrite ($fd, "\tstats\t\t\tscope " . $scope_item . "\n"); + } } } if (is_arrayset($pool,'errorfiles','item')) { foreach($pool['errorfiles']['item'] as $errorfile) { - if (!is_array($a_files_cache))// load only once + if (!is_array($a_files_cache)) {// load only once $a_files_cache = haproxy_get_fileslist(); + } $file = $errorfile['errorfile']; $errorcodes = explode(",",$errorfile['errorcode']); foreach($errorcodes as $errorcode) { @@ -688,19 +937,35 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } } - if($pool['balance']) - fwrite ($fd, "\tbalance\t\t\t" . $pool['balance'] . "\n"); - - if(!$pool['connection_timeout']) + if ($pool['balance']) { + $parameters = ""; + if ($pool['balance'] == 'uri') { + if (!empty($pool['balance_urilen'])) { + $parameters .= " len {$pool['balance_urilen']}"; + } + if (!empty($pool['balance_uridepth'])) { + $parameters .= " depth {$pool['balance_uridepth']}"; + } + if ($pool['balance_uriwhole'] == 'yes') { + $parameters .= " whole"; + } + + } + fwrite ($fd, "\tbalance\t\t\t{$pool['balance']}{$parameters}\n"); + } + if (!$pool['connection_timeout']) { $pool['connection_timeout'] = 30000; + } fwrite ($fd, "\ttimeout connect\t\t" . $pool['connection_timeout'] . "\n"); - if(!$pool['server_timeout']) + if (!$pool['server_timeout']) { $pool['server_timeout'] = 30000; + } fwrite ($fd, "\ttimeout server\t\t" . $pool['server_timeout'] . "\n"); - if(!$pool['retries']) + if (!$pool['retries']) { $pool['retries'] = 3; + } fwrite ($fd, "\tretries\t\t\t" . $pool['retries'] . "\n"); $addrprefix = ""; @@ -718,13 +983,15 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } $uri = $pool['monitor_uri']; - if ($pool['monitor_uri']) + if ($pool['monitor_uri']) { $uri = $pool['monitor_uri']; - else + } else { $uri = "/"; - - if ($optioncheck) + } + + if ($optioncheck) { fwrite ($fd, "\toption\t\t\t{$optioncheck}\n"); + } if ($pool['advanced_backend']) { $adv_be = explode("\n", base64_decode($pool['advanced_backend'])); @@ -735,7 +1002,143 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } } - if($pool['advanced']) { + global $a_action; + $config_acls = array(); + + $cert_acls = ""; + $aclcrt_name = ""; + $a_acl = get_backend_acls($pool, $frontendtype); + if (!is_array($a_acl)) { + $a_acl = array(); + } + // ACL's + foreach ($a_acl as $entry) { + $aclitem = $entry['ref']; + $expression = $aclitem['expression']; + + $aclname = $aclitem['name']; + $acltype = haproxy_find_acl($expression); + if (!isset($acltype)) + continue; + + // Filter out acls for different modes + if ($acltype['mode'] != '' && $acltype['mode'] != strtolower($frontendtype)) { + continue; + } + if ($acltype['inspect-delay'] != '') { + $inspectdelay = $acltype['inspect-delay']; + } + if ($acltype['advancedoptions'] != '') { + $advancedextra[$acltype['syntax']] = $acltype['advancedoptions']."\n"; + } + if ($acltype['require_client_cert']) { + $needs_clientcert[$aclname] = true; + } + if ($aclitem['certacl']) { + $aclname = "aclcrt_{$frontend['name']}"; + $aclcrt_name = $aclname; + } + + if (($expression == "source_ip") && is_alias($aclitem['value'])) { + $filename = "$configpath/ipalias_{$aclitem['value']}.lst"; + $listitems = haproxy_hostoralias_to_list($aclitem['value']); + $fd_alias = fopen("$filename", "w"); + foreach($listitems as $item) { + fwrite($fd_alias, $item."\r\n"); + } + fclose($fd_alias); + $expr = "src -f $filename"; + } else { + $expr = sprintf($acltype['syntax'], $aclitem['value']); + if (is_array($acltype['fields'])) { + foreach ($acltype['fields'] as $field) { + $fieldname = $field['name']; + $parameter = $aclitem[$expression . $fieldname]; + if ($fieldname == "backend") { + $backendname = $parameter . "_" . strtolower($bind['type'])."_".$ipversion; + $parameter = $backendname; + } + $expr = str_replace("{{$fieldname}}", $parameter, $expr); + } + } + } + $config_acls ["\tacl\t\t\t" . $aclname . "\t" . $expr . "\n"] = 1; + } + // Write acl's first, so they may be used by advanced text options written by user. + foreach($config_acls as $acl => $dummy) { + fwrite ($fd, $acl); + } + + $a_actionitems = $pool['a_actionitems']['item']; + if (!is_array($a_actionitems)) { + $a_actionitems = array(); + } + foreach ($a_actionitems as $actionitem) { + $actionid = $actionitem['action']; + $action = $a_action[$actionid]; + + $action_cfg = $action['syntax']; + + if (is_array($action['fields'])) { + foreach ($action['fields'] as $field) { + $fieldname = $field['name']; + $parameter = $actionitem[$actionid . $field['name']]; + + if ($fieldname == "backend") { + $backend = $parameter; + $backendname = $parameter . "_" . strtolower($bind['type'])."_".$ipversion; + if (!isset($a_pendingpl[$backendname])) { + $a_pendingpl[$backendname] = array(); + $a_pendingpl[$backendname]['name'] = $backendname; + $a_pendingpl[$backendname]['backend'] = $backend; + $a_pendingpl[$backendname]['frontend'] = $bind; + $a_pendingpl[$backendname]['ipversion'] = $ipversion; + } + $parameter = $backendname; + } + $action_cfg = str_replace("{{$fieldname}}", $parameter, $action_cfg); + } + } + $condition = ""; + if (!empty($actionitem['acl']) || !empty($systemacl)) { + $useclientcert = ""; + $useracls = ""; + $aclnames = explode(' ', $actionitem['acl']); + foreach($aclnames as $aclname) { + if ($needs_clientcert[$aclname]) { + $useclientcert = " aclsystem_ssl_c_used"; + } + $not = ""; + foreach ($a_acl as $entry) { + if ($entry['ref']['name'] == $aclname && $entry['ref']['not'] == 'yes') { + $not = "!"; + } + } + $useracls .= " {$not}{$aclname}"; + } + $condition = " if {$useracls}{$useclientcert} {$systemacl}"; + } + + $action = "\t{$action_cfg} {$condition}\n"; + + if ($actionid == "use_backend") { + if (empty($condition)) { + $config_usedefaultbackends .= "\tdefault_backend {$parameter}{$condition}\n"; + } else { + if (!empty($actionitem['acl'])){ + $config_usebackends .= $action; + } else { + // add use_backend if ipv4/6 before default_backend if any exists.. + $config_usedefaultbackends .= $action; + } + } + } else { + $config_actions .= $action; + } + } + fwrite ($fd, $config_actions); + + if ($pool['advanced']) { $advanced = base64_decode($pool['advanced']); $advanced_txt = " " . $advanced; } else { @@ -743,28 +1146,33 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { } if ($check_type != 'none') { - if($pool['checkinter']) + if ($pool['checkinter']) { $checkinter = " check inter {$pool['checkinter']}"; - else + } else { $checkinter = " check inter 1000"; + } } //agent-check requires at least haproxy v1.5dev20 - if ($pool['agent_check']) + if ($pool['agent_check']) { $agentcheck = " agent-check agent-inter {$pool['agent_inter']} agent-port {$pool['agent_port']}"; + } if (is_array($a_servers)) { foreach($a_servers as $be) { - if ($be['status'] == "inactive") + if ($be['status'] == "inactive") { continue; - if($be['cookie'] && $frontendtype == "http") + } + if ($be['cookie'] && $frontendtype == "http") { $cookie = " cookie {$be['cookie']}"; - else + } else { $cookie = ""; + } - if (!$be['name']) + if (!$be['name']) { $be['name'] = $be['address']; - if(!$be['status'] || $be['status'] != 'active') { + } + if (!$be['status'] || $be['status'] != 'active') { $isbackup = $be['status']; } else { $isbackup = ""; @@ -775,8 +1183,7 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { $crtfile = ""; $verifynone = ""; $verifyhost = ""; - if ($be['ssl'] == 'yes') - { + if ($be['ssl'] == 'yes') { $ssl = $frontendtype == "http" ? ' ssl' : ' check-ssl'; if ($be['sslserververify'] != 'yes') { @@ -803,24 +1210,25 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { haproxy_write_certificate_crt($filename, $server_clientcert, true); $crtfile = " crt $filename"; } - } $weight = ""; - if (is_numeric($be['weight'])){ + if (is_numeric($be['weight'])) { $weight = " weight " . $be['weight']; } $maxconn = ""; - if (is_numeric($be['maxconn'])){ + if (is_numeric($be['maxconn'])) { $maxconn = " maxconn " . $be['maxconn']; } + $unix_socket = false; $servers = array(); if ($be['forwardto'] && $be['forwardto'] != "") { + $unix_socket = true; $servers[] = "/{$be['forwardto']}.socket send-proxy-v2-ssl-cn"; } else { - if (is_ipaddr($be['address'])) { + if (is_ipaddr($be['address']) || $use_haproxyresolvers) { $servers[] = $be['address']; - } else if (is_hostname($be['address'])) { + } elseif (is_hostname($be['address'])) { $dnsresult_servers = haproxy_utils::query_dns($be['address'], $dnsquerytype); foreach($dnsresult_servers as $dnsresult_server){ $servers[] = $dnsresult_server['data']; @@ -831,18 +1239,26 @@ function write_backend($configpath, $fd, $name, $pool, $backendsettings) { foreach($servers as $server) { if (is_ipaddr($server)) { // skip ipv4 servers when using transparent client ip with ipv6 backend servers, and vice versa - if ($ipversion == "ipv4" && !is_ipaddrv4($server)) + if ($ipversion == "ipv4" && !is_ipaddrv4($server)) { continue; - if ($ipversion == "ipv6" && !is_ipaddrv6($server)) + } + if ($ipversion == "ipv6" && !is_ipaddrv6($server)) { continue; - if (isset($be['port'])) - $server = $server . ":" . $be['port']; + } + } else { + if (!$unix_socket) { + // place the ipv4@ or ipv6@ before the address, but not when using a unix socket + $server = $addrprefix . $server; + } + } + if (!empty($be['port'])) { + $server = $server . ":" . $be['port']; } $servername = $be['name']; if (count($servers) > 1) { $servername .= "_" . $counter; } - fwrite ($fd, "\tserver\t\t\t" . $servername . " " . $server . "$ssl$cookie$checkinter$checkport$agentcheck $isbackup$weight$maxconn$cafile$crlfile$verifynone$verifyhost$crtfile{$advanced_txt} {$be['advanced']}\n"); + fwrite ($fd, "\tserver\t\t\t" . $servername . " " . $server . "$ssl$cookie$checkinter$checkport$agentcheck $isbackup$weight$maxconn$cafile$crlfile$verifynone$verifyhost$crtfile$server_options{$advanced_txt} {$be['advanced']}\n"); $counter++; } } @@ -862,15 +1278,20 @@ function haproxy_check_and_run(&$messages, $reload) { haproxy_writeconf($testpath); $retval = exec("haproxy -c -V -f $testpath/haproxy.cfg 2>&1", $output, $err); $messages = ""; - if ($err > 1) + if ($err > 1) { $messages = "<h2><strong>FATAL ERROR CODE: $err while starting haproxy</strong></h2>"; - elseif ($err == 1) + } elseif ($err == 1) { $messages = "Errors found while starting haproxy"; + } if ((count($output) > 1) && $output[0] != "Configuration file is valid") { - foreach($output as $line) + $syslogmessage = ""; + foreach($output as $line) { $messages .= "<br/>" . htmlspecialchars($line) . "\n"; + $syslogmessage .= str_replace("\n"," ", $line) . " "; + } + syslog(LOG_NOTICE, "haproxy: check error output: {$syslogmessage}"); } $ok = strstr($retval, "Configuration file is valid"); if ($ok && $reload) { @@ -884,16 +1305,18 @@ function haproxy_check_and_run(&$messages, $reload) { function haproxy_lookup_cert($certid) { $res = lookup_ca($certid); - if (!$res) + if (!$res) { $res = lookup_cert($certid); + } return $res; } function haproxy_write_certificate_crt($filename, $certid, $include_psk = false, $append = false) { $cert = haproxy_lookup_cert($certid); $certcontent = base64_decode($cert['crt']); - if ($include_psk && isset($cert['prv'])) + if ($include_psk && isset($cert['prv'])) { $certcontent .= "\r\n".base64_decode($cert['prv']); + } $flags = $append ? FILE_APPEND : 0; file_put_contents($filename, $certcontent, $flags); unset($certcontent); @@ -902,6 +1325,7 @@ function haproxy_write_certificate_crt($filename, $certid, $include_psk = false, function haproxy_write_certificate_crl($filename, $crlid, $append = false) { $crl = lookup_crl($crlid); + crl_update($crl); $content = base64_decode($crl['text']); $flags = $append ? FILE_APPEND : 0; file_put_contents($filename, $content, $flags); @@ -913,18 +1337,21 @@ function haproxy_write_certificate_fullchain($filename, $certid, $append = false $cert = haproxy_lookup_cert($certid); $certcontent = base64_decode($cert['crt']); - if (isset($cert['prv'])) + if (isset($cert['prv'])) { $certcontent .= "\r\n".base64_decode($cert['prv']); + } $ca = $cert; while(!empty($ca['caref'])) { $ca = lookup_ca($ca['caref']); if ($ca) { - if ($skiproot && (cert_get_subject($ca['crt']) == cert_get_issuer($ca['crt']))) + if ($skiproot && (cert_get_subject($ca['crt']) == cert_get_issuer($ca['crt']))) { break; + } $certcontent .= "\r\n" . base64_decode($ca['crt']); - } else + } else { break; + } } $flags = $append ? FILE_APPEND : 0; file_put_contents($filename, $certcontent, $flags); @@ -947,8 +1374,9 @@ function haproxy_write_certificate_issuer($filename, $certid) { function haproxy_uses_ocsp() { global $config; $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; - if (!is_array($a_frontends)) + if (!is_array($a_frontends)) { return false; + } $configpath = "{$g['varetc_path']}/haproxy"; foreach ($a_frontends as $frontend) { @@ -977,9 +1405,9 @@ function haproxy_updateocsp_one($socketupdate, $filename, $name) { if ($socketupdate) { $ocspresponse = base64_encode(file_get_contents("{$filename}.ocsp")); $r = haproxy_socket_command("set ssl ocsp-response $ocspresponse"); - if ($r[0] == "OCSP Response updated!\n") + if ($r[0] == "OCSP Response updated!\n") { syslog(LOG_NOTICE, "HAProxy OCSP socket update successful for frontend {$name}..result: ".$retval); - else { + } else { syslog(LOG_ERR, "HAProxy OCSP ERROR while performing haproxy socket update OCSP response for: {$name}"); } } else { @@ -992,8 +1420,9 @@ function haproxy_updateocsp_one($socketupdate, $filename, $name) { function haproxy_updateocsp($socketupdate = true) { global $config, $g; $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; - if (!is_array($a_frontends)) + if (!is_array($a_frontends)) { return true; + } $configpath = "{$g['varetc_path']}/haproxy"; foreach ($a_frontends as $frontend) { @@ -1012,10 +1441,12 @@ function haproxy_updateocsp($socketupdate = true) { } function haproxy_writeconf($configpath) { - global $config; + global $config, $a_files_cache; global $aliastable; - if (!isset($aliastable)) + global $a_action; + if (!isset($aliastable)) { alias_make_table($config); + } $chroot_dir = "/tmp/haproxy_chroot"; // can contain socket to forward connection from backend to frontend. "/var/empty" @mkdir($chroot_dir, 0755, true); @@ -1027,38 +1458,64 @@ function haproxy_writeconf($configpath) { $a_global = &$config['installedpackages']['haproxy']; $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; - $a_mailers = &$config['installedpackages']['haproxy']['email_mailers']['items']; + $a_mailers = &$config['installedpackages']['haproxy']['email_mailers']['item']; + $a_resolvers = &$config['installedpackages']['haproxy']['dns_resolvers']['item']; + $a_files = &$config['installedpackages']['haproxy']['files']['item']; + if (!is_array($a_frontends)) { + $a_frontends = array(); + } + if (!is_array($a_backends)) { + $a_backends = array(); + } + if (!is_array($a_mailers)) { + $a_mailers = array(); + } + if (!is_array($a_resolvers)) { + $a_resolvers = array(); + } $fd = fopen($configfile, "w"); - if(is_array($a_global)) { + if (is_array($a_global)) { fwrite ($fd, "global\n"); - if ($a_global['maxconn']) + if ($a_global['maxconn']) { fwrite ($fd, "\tmaxconn\t\t\t".$a_global['maxconn']."\n"); - if($a_global['remotesyslog']) + } + if ($a_global['remotesyslog']) { fwrite ($fd, "\tlog\t\t\t{$a_global['remotesyslog']}\t{$a_global['logfacility']}\t{$a_global['loglevel']}\n"); + } fwrite ($fd, "\tstats socket /tmp/haproxy.socket level admin\n"); - if(!use_transparent_clientip_proxying()) + if(!use_transparent_clientip_proxying()) { fwrite ($fd, "\tuid\t\t\t80\n"); - + } + fwrite ($fd, "\tgid\t\t\t80\n"); // Set numprocs if defined or use system default (#cores) - if($a_global['nbproc']) - $numprocs = $a_global['nbproc']; - else - $numprocs ="1"; + $numprocs = $a_global['nbproc'] ? $a_global['nbproc'] : "1"; fwrite ($fd, "\tnbproc\t\t\t$numprocs\n"); fwrite ($fd, "\tchroot\t\t\t$chroot_dir\n"); fwrite ($fd, "\tdaemon\n"); - //fwrite ($fd, "\tssl-server-verify none\n"); - if($a_global['ssldefaultdhparam']) + if ($a_global['ssldefaultdhparam']) { fwrite ($fd, "\ttune.ssl.default-dh-param\t{$a_global['ssldefaultdhparam']}\n"); - if($a_global['log-send-hostname']) + } + if ($a_global['log-send-hostname']) { fwrite ($fd, "\tlog-send-hostname\t\t{$a_global['log-send-hostname']}\n"); + } + + // lua-load + if (is_array($a_files)) { + foreach($a_files as $file) { + if ($file['type'] == "luascript") { + $luafile = $configpath . "/luascript_" . $file['name']; + file_put_contents($luafile, base64_decode($file['content']), 0); + fwrite ($fd, "\tlua-load\t\t{$luafile}\n"); + } + } + } // Keep the advanced options on the bottom of the global settings, to allow additional sections to be easely added - if($a_global['advanced']) { + if ($a_global['advanced']) { $adv = explode("\n", base64_decode($a_global['advanced'])); foreach($adv as $adv_line) { fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); @@ -1073,8 +1530,9 @@ function haproxy_writeconf($configpath) { fwrite ($fd, "\tbind 127.0.0.1:$localstatsport name localstats\n"); fwrite ($fd, "\tmode http\n"); fwrite ($fd, "\tstats enable\n"); - if (is_numeric($a_global['localstats_refreshtime'])) + if (is_numeric($a_global['localstats_refreshtime'])) { fwrite ($fd, "\tstats refresh {$a_global['localstats_refreshtime']}\n"); + } fwrite ($fd, "\tstats admin if TRUE\n"); fwrite ($fd, "\tstats uri /haproxy_stats.php?haproxystats=1\n"); fwrite ($fd, "\ttimeout client 5000\n"); @@ -1084,7 +1542,7 @@ function haproxy_writeconf($configpath) { } } - if (haproxy_verion() >= '1.6') { + if (haproxy_version() >= '1.6') { $use_mailers = is_array($a_mailers) && count($a_mailers) > 0; if ($use_mailers) { fwrite ($fd, "mailers globalmailers\n"); @@ -1093,16 +1551,26 @@ function haproxy_writeconf($configpath) { } fwrite ($fd, "\n"); } + $use_resolvers = is_array($a_resolvers) && count($a_resolvers) > 0; + if ($use_resolvers) { + fwrite ($fd, "resolvers globalresolvers\n"); + foreach($a_resolvers as $resolver) { + fwrite ($fd, "\tnameserver {$resolver['name']} {$resolver['server']}:{$resolver['port']}\n"); + } + fwrite ($fd, "\tresolve_retries {$a_global['resolver_retries']}\n"); + fwrite ($fd, "\ttimeout retry {$a_global['resolver_timeoutretry']}\n"); + fwrite ($fd, "\thold valid {$a_global['resolver_holdvalid']}\n"); + fwrite ($fd, "\n"); + } } // Try and get a unique array for address:port as frontends can duplicate $a_bind = array(); - if(is_array($a_frontends)) { + if (is_array($a_frontends)) { foreach ($a_frontends as $frontend) { - if($frontend['status'] != 'active') - continue; - if(!$frontend['backend_serverpool']) + if ($frontend['status'] != 'active') { continue; + } $primaryfrontend = get_primaryfrontend($frontend); $bname = $primaryfrontend['name']; @@ -1131,8 +1599,8 @@ function haproxy_writeconf($configpath) { $subfolder = "$configpath/{$frontend['name']}"; $certs = $frontend['ha_certificates']['item']; - if (is_array($certs)){ - if (count($certs) > 0){ + if (is_array($certs)) { + if (count($certs) > 0) { @mkdir($subfolder, 0755, true); foreach($certs as $cert){ $filenamefoldercert = "$subfolder/{$cert['ssl_certificate']}.pem"; @@ -1148,7 +1616,7 @@ function haproxy_writeconf($configpath) { $ssl_crt .= " crt $subfolder"; } } - }else{ + } else { $ssl_crt=""; unlink_if_exists("var/etc/{$frontend['name']}.{$frontend['port']}.crt");//cleanup for possible old haproxy package version } @@ -1161,8 +1629,9 @@ function haproxy_writeconf($configpath) { } if ($ssl_crt != "") { - if ($b['ssl_info'] == "") + if ($b['ssl_info'] == "") { $b['ssl_info'] = "ssl {$frontend['dcertadv']}"; + } $b['ssl_info'] .= $ssl_crt; } @@ -1170,26 +1639,26 @@ function haproxy_writeconf($configpath) { $b['config'][] = $frontend; } } - $a_pendingpl = array(); // Construct and write out configuration for each "frontend" - if(is_array($a_bind)) { + if (is_array($a_bind)) { foreach ($a_bind as $bind) { - if (count($bind['config']) > 1) + if (count($bind['config']) > 1) { $frontendinfo = "frontend {$bind['name']}-merged\n"; - else + } else { $frontendinfo = "frontend {$bind['name']}\n"; + } fwrite ($fd, "{$frontendinfo}"); $advancedextra = array(); $ca_file = ""; $first = true; - if (is_array($bind['clientcert_ca']['item'])){ + if (is_array($bind['clientcert_ca']['item'])) { $filename = "$configpath/clientca_{$bind['name']}.pem"; - foreach($bind['clientcert_ca']['item'] as $ca){ - if (!empty($ca['cert_ca'])){ + foreach($bind['clientcert_ca']['item'] as $ca) { + if (!empty($ca['cert_ca'])) { haproxy_write_certificate_crt($filename, $ca['cert_ca'], false, !$first); $first = false; } @@ -1199,9 +1668,9 @@ function haproxy_writeconf($configpath) { } $crl_file = ""; $first = true; - if (is_array($bind['clientcert_crl']['item'])){ + if (is_array($bind['clientcert_crl']['item'])) { $filename = "$configpath/clientcrl_{$bind['name']}.pem"; - foreach($bind['clientcert_crl']['item'] as $ca){ + foreach($bind['clientcert_crl']['item'] as $ca) { haproxy_write_certificate_crl($filename, $ca['cert_crl'], !$first); $first = false; } @@ -1210,8 +1679,9 @@ function haproxy_writeconf($configpath) { $advanced_bind = $bind['advanced_bind']; $ssl_info = $bind['ssl_info']; $ssl_info .= $ca_file . $crl_file; - if ($bind['sslclientcert-invalid']) + if ($bind['sslclientcert-invalid']) { $ssl_info .= " crt-ignore-err all"; + } $useipv4 = false; $useipv6 = false; @@ -1226,12 +1696,12 @@ function haproxy_writeconf($configpath) { } fwrite ($fd, "{$listenip}"); - if (use_frontend_as_unixsocket($bind['name'])){ + if (use_frontend_as_unixsocket($bind['name'])) { fwrite ($fd, "\tbind /tmp/haproxy_chroot/{$bind['name']}.socket name unixsocket accept-proxy {$ssl_info} {$advanced_bind}\n"); } // https is an alias for tcp for clarity purposes - if($bind['type'] == "https") { + if ($bind['type'] == "https") { $backend_type = "tcp"; } else { $backend_type = $bind['type']; @@ -1240,26 +1710,32 @@ function haproxy_writeconf($configpath) { fwrite ($fd, "\tmode\t\t\t" . $backend_type . "\n"); fwrite ($fd, "\tlog\t\t\tglobal\n"); - if ($bind['socket-stats'] == 'yes') + if ($bind['socket-stats'] == 'yes') { fwrite ($fd, "\toption\t\t\tsocket-stats\n"); - if ($bind['dontlognull'] == 'yes') + } + if ($bind['dontlognull'] == 'yes') { fwrite ($fd, "\toption\t\t\tdontlognull\n"); - if ($bind['dontlog-normal'] == 'yes') + } + if ($bind['dontlog-normal'] == 'yes') { fwrite ($fd, "\toption\t\t\tdontlog-normal\n"); - if ($bind['log-separate-errors'] == 'yes') + } + if ($bind['log-separate-errors'] == 'yes') { fwrite ($fd, "\toption\t\t\tlog-separate-errors\n"); - if ($bind['log-detailed'] == 'yes'){ - if ($backend_type == 'http') + } + if ($bind['log-detailed'] == 'yes') { + if ($backend_type == 'http') { fwrite ($fd, "\toption\t\t\thttplog\n"); - else + } else { fwrite ($fd, "\toption\t\t\ttcplog\n"); + } } if ($backend_type == 'http') { - if($bind['httpclose'] && $bind['httpclose'] != "none" ) + if ($bind['httpclose'] && $bind['httpclose'] != "none") { fwrite ($fd, "\toption\t\t\t{$bind['httpclose']}\n"); + } - if($bind['forwardfor']) { + if ($bind['forwardfor']) { fwrite ($fd, "\toption\t\t\tforwardfor\n"); fwrite ($fd, "\tacl https ssl_fc\n"); fwrite ($fd, "\treqadd X-Forwarded-Proto:\ http if !https\n"); @@ -1267,19 +1743,38 @@ function haproxy_writeconf($configpath) { } } - if($bind['max_connections']) - fwrite ($fd, "\tmaxconn\t\t\t" . $bind['max_connections'] . "\n"); + if ($bind['max_connections']) { + fwrite ($fd, "\tmaxconn\t\t\t{$bind['max_connections']}\n"); + } - if(!$bind['client_timeout']) + if (!$bind['client_timeout']) { $bind['client_timeout'] = 30000; + } - fwrite ($fd, "\ttimeout client\t\t" . $bind['client_timeout'] . "\n"); + fwrite ($fd, "\ttimeout client\t\t{$bind['client_timeout']}\n"); + + if (is_arrayset($bind,'a_errorfiles','item')) { + foreach($bind['a_errorfiles']['item'] as $errorfile) { + if (!is_array($a_files_cache)) {// load only once + $a_files_cache = haproxy_get_fileslist(); + } + $file = $errorfile['errorfile']; + $errorcodes = explode(",",$errorfile['errorcode']); + foreach($errorcodes as $errorcode) { + $filename = "$configpath/errorfile_{$name}_{$errorcode}_{$file}"; + $content = base64_decode($a_files_cache[$file]['content']); + $content = str_replace('{errormsg}', $a_error[$errorcode]['descr'], $content); + $content = str_replace('{errorcode}', $errorcode, $content); + file_put_contents($filename, $content); + fwrite ($fd, "\terrorfile\t\t\t" . $errorcode ." " . $filename . "\n"); + } + } + } - // Advanced pass thru - if($bind['advanced']) { - $advanced = explode("\n", base64_decode($bind['advanced'])); - foreach($advanced as $adv_line) { + if ($bind['advanced']) { + $advanced = explode("\n", base64_decode($bind['advanced'])); + foreach ($advanced as $adv_line) { if ($adv_line != "") { fwrite($fd, "\t" . str_replace("\r", "", $adv_line) . "\n"); } @@ -1288,176 +1783,220 @@ function haproxy_writeconf($configpath) { // Combine the rest of the frontend configs $default_backend = ""; - $config_acls = ""; + $config_acls = array(); + $config_actions = ""; $config_usebackends = ""; $config_usedefaultbackends = ""; $transparent_clientip = false; foreach ($bind['config'] as $frontend) { - $backend = haproxy_find_backend($frontend['backend_serverpool']); - if ($backend["transparent_clientip"] == 'yes') { + //todo: check also use_backend actions + if (frontend_usetransparentbackend($frontend)) { $transparent_clientip = true; break; } } if ($transparent_clientip && $useipv4 && $useipv6) { // set the src_is_ipv4 acl if needed. - $config_acls .= "\tacl\t\t\tsrc_is_ipv4\tsrc 0.0.0.0/0\n"; + $acl = "\tacl\t\t\tsrc_is_ipv4\tsrc 0.0.0.0/0\n"; + $config_acls[$acl] = 1; } $inspectdelay = 0; $i = 0; $acllist = array(); + $needs_clientcert = array(); $acl_newid = 0; foreach ($bind['config'] as $frontend) { + // loop through 'shared frontends' within one primary. + $a_acl = get_frontend_acls($frontend); - - $backend = haproxy_find_backend($frontend['backend_serverpool']); - $transparent_clientip = $backend["transparent_clientip"] == 'yes'; + + $a_actionitems = $frontend['a_actionitems']['item']; + if (!is_array($a_actionitems)) { + $a_actionitems = array(); + } + if (!empty($frontend['backend_serverpool'])) { + // insert extra use_backend action without a user-condition + $item = array(); + $item['action'] = "use_backend"; + $item['use_backendbackend'] = $frontend['backend_serverpool']; + $a_actionitems[] = $item; + } + $transparent_clientip = frontend_usetransparentbackend($frontend); $allowfordefaultbackend = true; $ipv = array(); if ($transparent_clientip) { if ($useipv4 && $useipv6) { $ipv["ipv4"]['acl'] = " src_is_ipv4 "; + $ipv["ipv4"]['aclnameadd'] = "_ipv4"; $ipv["ipv6"]['acl'] = " !src_is_ipv4 "; + $ipv["ipv6"]['aclnameadd'] = "_ipv6"; $allowfordefaultbackend = false; // transparent backend must always match client-ip which is ipv4 v.s. ipv6 specific so there cannot be a default. - } else if ($useipv6) + } elseif ($useipv6) { $ipv["ipv6"]['acl'] = " "; - else + $ipv["ipv6"]['aclnameadd'] = ""; + } else { $ipv["ipv4"]['acl'] = " "; - } else - $ipv["ipvANY"]['acl'] = " "; - - // combine acl's with same name to allow for 'combined checks' to check for example hostname and fileextension together.. - $a_acl_combine = array(); - foreach ($a_acl as $entry) { - $name = $entry['ref']['name']; - - $acl = array(); - $acl['ref'] = $entry['ref']; - $acltype = haproxy_find_acl($entry['ref']['expression']); - $acl['acltype'] = $acltype; - if (!isset($acltype)) - continue; - $a_acl_combine[$name][] = $acl; - - if (isset($acltype['require_client_cert'])){ - $acl = array(); - $acl['ref']['expression'] = "ssl_c_used"; - $acl['acltype']['syntax'] = "ssl_c_used"; - $acl['acltype']['novalue'] = 1; - $a_acl_combine[$name][] = $acl; + $ipv["ipv4"]['aclnameadd'] = ""; } + } else { + $ipv["ipvANY"]['acl'] = " "; + $ipv["ipvANY"]['aclnameadd'] = ""; } - + $certacl = ""; $y = 0; foreach($ipv as $ipversion => $ipversionoptions) { - $useracls = array(); - $poolname = $frontend['backend_serverpool'] . "_" . strtolower($bind['type'])."_".$ipversion; - if (!isset($a_pendingpl[$poolname])) { - $a_pendingpl[$poolname] = array(); - $a_pendingpl[$poolname]['name'] = $poolname; - $a_pendingpl[$poolname]['backend'] = $frontend['backend_serverpool']; - $a_pendingpl[$poolname]['frontend'] = $bind; - $a_pendingpl[$poolname]['ipversion'] = $ipversion; - } - $canbedefaultbackend = false; - // Write this out once, and must be before any backend config text - if (($default_backend == "" || $frontend['secondary'] != 'yes') && count($a_acl) == 0 ) { - $canbedefaultbackend = true; - if ($allowfordefaultbackend) - $default_backend = $poolname; + $cert_acls = ""; + $aclcrt_name = ""; + + // ACL's + foreach ($a_acl as $entry) { + $aclitem = $entry['ref']; + $expression = $aclitem['expression']; + + $aclname = $aclitem['name']; + $acltype = haproxy_find_acl($expression); + if (!isset($acltype)) + continue; + + // Filter out acls for different modes + if ($acltype['mode'] != '' && $acltype['mode'] != strtolower($bind['type'])) { + continue; + } + if ($acltype['inspect-delay'] != '') { + $inspectdelay = $acltype['inspect-delay']; + } + if ($acltype['advancedoptions'] != '') { + $advancedextra[$acltype['syntax']] = $acltype['advancedoptions']."\n"; + } + if ($acltype['require_client_cert']) { + $needs_clientcert[$aclname] = true; + } + if ($aclitem['certacl']) { + $aclname = "aclcrt_{$frontend['name']}"; + $aclcrt_name = $aclname; + } + + if (($expression == "source_ip") && is_alias($aclitem['value'])) { + $filename = "$configpath/ipalias_{$aclitem['value']}.lst"; + $listitems = haproxy_hostoralias_to_list($aclitem['value']); + $fd_alias = fopen("$filename", "w"); + foreach($listitems as $item) { + fwrite($fd_alias, $item."\r\n"); + } + fclose($fd_alias); + $expr = "src -f $filename"; + } else { + $expr = sprintf($acltype['syntax'], $aclitem['value']); + if (is_array($acltype['fields'])) { + foreach ($acltype['fields'] as $field) { + $fieldname = $field['name']; + $parameter = $aclitem[$expression . $fieldname]; + if ($fieldname == "backend") { + $backendname = $parameter . "_" . strtolower($bind['type'])."_".$ipversion; + $parameter = $backendname; + } + $expr = str_replace("{{$fieldname}}", $parameter, $expr); + } + } + } + $config_acls ["\tacl\t\t\t" . $aclname . "\t" . $expr . "\n"] = 1; } - - foreach ($a_acl_combine as $a_usebackend) { - $aclnames = ""; - foreach ($a_usebackend as $entry2) { - $entry = $entry2['ref']; - $acl = $entry2['acltype']; - - // Filter out acls for different modes - if ($acl['mode'] != '' && $acl['mode'] != strtolower($bind['type'])) - continue; - if (($entry['expression'] == "source_ip") && is_alias($entry['value'])) { - $filename = "$configpath/ipalias_{$entry['value']}.lst"; - $listitems = haproxy_hostoralias_to_list($entry['value']); - $fd_alias = fopen("$filename", "w"); - foreach($listitems as $item) - fwrite($fd_alias, $item."\r\n"); - fclose($fd_alias); - $expr = "src -f $filename"; - } else - $expr = sprintf($acl['syntax'],$entry['value'],$poolname); - - $not = $entry['not'] == "yes" ? "!" : ""; - - unset($aclkey); - foreach($acllist as $aclid => $aclitem) { - if ($aclitem['expr'] == $expr) { - $aclkey = $aclid; + + $systemacl = trim("{$aclcrt_name}{$ipversionoptions['acl']}"); + + foreach ($a_actionitems as $actionitem) { + $actionid = $actionitem['action']; + $action = $a_action[$actionid]; + + $action_cfg = $action['syntax']; + + if (is_array($action['fields'])) { + foreach ($action['fields'] as $field) { + $fieldname = $field['name']; + $parameter = $actionitem[$actionid . $field['name']]; + + if ($fieldname == "backend") { + $backend = $parameter; + $backendname = $parameter . "_" . strtolower($bind['type'])."_".$ipversion; + if (!isset($a_pendingpl[$backendname])) { + $a_pendingpl[$backendname] = array(); + $a_pendingpl[$backendname]['name'] = $backendname; + $a_pendingpl[$backendname]['backend'] = $backend; + $a_pendingpl[$backendname]['frontend'] = $bind; + $a_pendingpl[$backendname]['ipversion'] = $ipversion; + } + $parameter = $backendname; + } + $action_cfg = str_replace("{{$fieldname}}", $parameter, $action_cfg); + } + } + $condition = ""; + if (!empty($actionitem['acl']) || !empty($systemacl)) { + $useclientcert = ""; + $useracls = ""; + $aclnames = explode(' ', $actionitem['acl']); + foreach($aclnames as $aclname) { + if ($needs_clientcert[$aclname]) { + $useclientcert = " aclsystem_ssl_c_used"; } + $not = ""; + foreach ($a_acl as $entry) { + if ($entry['ref']['name'] == $aclname && $entry['ref']['not'] == 'yes') { + $not = "!"; + } + } + $useracls .= " {$not}{$aclname}"; } - if (isset($aclkey)) { - $aclname = $acllist[$aclkey]['aclname']; + $condition = " if {$useracls}{$useclientcert} {$systemacl}"; + } + + $action = "\t{$action_cfg} {$condition}\n"; + + if ($actionid == "use_backend") { + if (empty($condition)) { + $config_usedefaultbackends .= "\tdefault_backend {$parameter}{$condition}\n"; } else { - $aclkey = $acl_newid++; - if ($entry['certacl']) { - $aclname = "aclcrt_".$frontend['name']; - $certacl = $aclname; + if (!empty($actionitem['acl'])){ + $config_usebackends .= $action; } else { - $aclname = "aclusr_{$entry['expression']}"; - if (!isset($acl['novalue'])) - $aclname .= "_{$entry['value']}"; - $aclname = haproxy_escape_acl_name($aclname); - $i++; + // add use_backend if ipv4/6 before default_backend if any exists.. + $config_usedefaultbackends .= $action; } - $acllist[$aclkey]['aclname'] = $aclname; - $acllist[$aclkey]['expr'] = $expr; - $config_acls .= "\tacl\t\t\t" . $aclname . "\t" . $expr . "\n"; } - if (!isset($entry['certacl'])) - $useracls[$y] .= $not . $aclname . " "; - - if ($acl['inspect-delay'] != '') - $inspectdelay = $acl['inspect-delay']; - - if ($acl['advancedoptions'] != '') - $advancedextra[$acl['syntax']] = $acl['advancedoptions']."\n"; + } else { + $config_actions .= $action; } - $y++; - } - - $systemacl = trim("{$certacl}{$ipversionoptions['acl']}"); - if (!empty($systemacl) && count($useracls) == 0) $useracls[] = ""; // add empty item to enter foreach loop at least once when a system acl is pressent. - foreach($useracls as $useracl) { - $backendacl = ""; - $backendacl .= "|| {$useracl}{$systemacl}"; - $backendacl = substr($backendacl, 3); - if ($canbedefaultbackend) { - // makes sure these come last even though systemacl's might have been added. - $config_usedefaultbackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; - } else - $config_usebackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; } } } - if ($inspectdelay > 0) + if ($inspectdelay > 0) { fwrite ($fd, "\ttcp-request inspect-delay\t" . $inspectdelay . "s\n"); + } + if (count($needs_clientcert) > 0) { + fwrite ($fd, "\tacl\t\t\taclsystem_ssl_c_used\tssl_c_used\n"); + } // Write acl's first, so they may be used by advanced text options written by user. - fwrite ($fd, $config_acls); + foreach($config_acls as $acl => $dummy) { + fwrite ($fd, $acl); + } - foreach($advancedextra as $extra) + foreach($advancedextra as $extra) { fwrite ($fd, "\t".$extra."\n"); + } + fwrite ($fd, $config_actions); // Write backends after advanced options so custom use_backend rules can be applied first. fwrite ($fd, $config_usebackends); fwrite ($fd, $config_usedefaultbackends); - if ($default_backend) + if ($default_backend) { fwrite ($fd, "\tdefault_backend\t\t" . $default_backend . "\n"); + } fwrite ($fd, "\n"); } @@ -1477,21 +2016,20 @@ function haproxy_writeconf($configpath) { // close config file fclose($fd); - if ($input_errors) - { + if ($input_errors) { require_once("guiconfig.inc"); print_input_errors($input_errors); } else { // Only sync to xmlrpc backup machine if no errors are found in config - if(isset($config['installedpackages']['haproxy']['enablesync'])) { + if (isset($config['installedpackages']['haproxy']['enablesync'])) { haproxy_do_xmlrpc_sync(); } } } function haproxy_is_running() { - $running = (shell_exec("/bin/pgrep -x haproxy") != ''); - return $running; + $running = (shell_exec("/bin/pgrep -x haproxy") != ''); + return $running; } function haproxy_load_modules() { @@ -1513,6 +2051,24 @@ function haproxy_load_modules() { unmute_kernel_msgs(); } +function frontend_usetransparentbackend($frontend) { + $backend = haproxy_find_backend($frontend['backend_serverpool']); + if ($backend["transparent_clientip"] == 'yes') { + return true; + } + if (is_array($frontend['a_actionitems']['item'])) { + foreach($frontend['a_actionitems']['item'] as $action) { + if ($action['action'] == "use_backend") { + $backend = haproxy_find_backend($action['use_backendbackend']); + if ($backend["transparent_clientip"] == 'yes') { + return true; + } + } + } + } + return false; +} + function use_transparent_clientip_proxying() { global $config; $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; @@ -1531,17 +2087,20 @@ function haproxy_get_transparent_backends(){ global $config; $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; $transparent_backends = array(); + if (!is_array($a_backends)) { + return $transparent_backends; + } foreach ($a_backends as $backend) { - if ($backend["transparent_clientip"] != 'yes') + if ($backend["transparent_clientip"] != 'yes') { continue; + } $real_if = get_real_interface($backend["transparent_interface"]); $a_servers = &$backend['ha_servers']['item']; if (is_array($a_servers)) { foreach($a_servers as $be) { - if (!$be['status'] == "inactive") - continue; - if (!is_ipaddr($be['address'])) + if (!$be['status'] == "inactive" || !is_ipaddr($be['address'])){ continue; + } $item = array(); $item['name'] = $be['name']; $item['interface'] = $real_if; @@ -1618,9 +2177,9 @@ function load_ipfw_rules() { $rulenum = 64000; // why that high? captiveportal.inc also does it... $rules = "flush\n"; foreach($transparent_backends as $transparent_be) { - if (is_ipaddrv4($transparent_be["address"])) + if (is_ipaddrv4($transparent_be["address"])) { $rules .= "add $rulenum fwd localhost tcp from {$transparent_be["address"]} {$transparent_be["port"]} to any in recv {$transparent_be["interface"]}\n"; - else if (is_ipaddrv6($transparent_be["address"])) { + } elseif (is_ipaddrv6($transparent_be["address"])) { list ($addr, $scope) = explode("%", $transparent_be['address']); $rules .= "add $rulenum fwd ::1 tcp from {$addr} {$transparent_be["port"]} to any in recv {$transparent_be["interface"]}\n"; } @@ -1715,7 +2274,7 @@ function haproxy_check_run($reload) { } } - if(isset($a_global['enable'])) { + if (isset($a_global['enable'])) { if (isset($a_global['carpdev'])) { $status = haproxy_carpipismaster($a_global['carpdev']); if (!$status) { @@ -1726,18 +2285,18 @@ function haproxy_check_run($reload) { } unlock($haproxylock); return (0); - } else if (haproxy_is_running() && $reload == 0) { + } elseif (haproxy_is_running() && $reload == 0) { unlock($haproxylock); return (0); } log_error("Starting haproxy on CARP master."); /* fallthrough */ - } else if ($reload == 0){ + } elseif ($reload == 0) { unlock($haproxylock); return (0); } - if(use_transparent_clientip_proxying()) { + if (use_transparent_clientip_proxying()) { filter_configure(); load_ipfw_rules(); } else { @@ -1751,14 +2310,16 @@ function haproxy_check_run($reload) { if (file_exists('/var/run/haproxy.pid')){ $old_pid = file_get_contents('/var/run/haproxy.pid'); - } else + } else { $old_pid = 'none'; + } if (haproxy_is_running()) { - if (isset($a_global['terminate_on_reload'])) + if (isset($a_global['terminate_on_reload'])) { $sf_st = "-st";//terminate old process as soon as the new process is listening - else + } else { $sf_st = "-sf";//finish serving existing connections exit when done, and the new process is listening + } syslog(LOG_NOTICE, "haproxy: reload old pid:$old_pid"); exec("/usr/local/sbin/haproxy -f {$configpath}/haproxy.cfg -p /var/run/haproxy.pid $sf_st `cat /var/run/haproxy.pid` 2>&1", $output, $errcode); @@ -1768,12 +2329,20 @@ function haproxy_check_run($reload) { } if (file_exists('/var/run/haproxy.pid')){ $new_pid = file_get_contents('/var/run/haproxy.pid'); - } else + } else { $new_pid = 'none'; + } syslog(LOG_NOTICE, "haproxy: started new pid:$new_pid"); - foreach($output as $line) + $syslogmessage = ""; + foreach($output as $line) { $haproxy_run_message .= "<br/>" . htmlspecialchars($line) . "\n"; + $syslogmessage .= str_replace("\n"," ",$line); + } + if (!empty($syslogmessage)) { + syslog(LOG_NOTICE, "haproxy: startup error output!: {$syslogmessage}"); + } + } else { if ($reload && haproxy_is_running()) { //exec("/bin/pkill -F /var/run/haproxy.pid haproxy");//doesnt work for multiple pid's in a pidfile @@ -1786,10 +2355,11 @@ function haproxy_check_run($reload) { } function haproxy_kill($killimmediately = true) { - if ($killimmediately) + if ($killimmediately) { $signal = "KILL"; // stop now - else + } else { $signal = "USR1"; // stop when all connections are closed + } killprocesses("haproxy", "/var/run/haproxy.pid", $signal); } @@ -1838,7 +2408,7 @@ function haproxy_xmlrpc_sync_configure() { haproxy_configure(); // Configure HAProxy config files to use the new configuration. // sync 2nd and further nodes in the chain if applicable. - if(isset($config['installedpackages']['haproxy']['enablesync'])) { + if (isset($config['installedpackages']['haproxy']['enablesync'])) { haproxy_do_xmlrpc_sync(); } } @@ -1857,34 +2427,38 @@ function get_frontend_id($name) { } function haproxy_is_frontendname($name) { - if ($name[0] == '!') + if ($name[0] == '!') { $name = substr($name, 1); + } return get_frontend_id($name) != null; } function get_primaryfrontend($frontend) { global $config; $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; - if ($frontend['secondary'] == 'yes') + if ($frontend['secondary'] == 'yes') { $mainfrontend = $a_frontend[get_frontend_id($frontend['primary_frontend'])]; - else + } else { $mainfrontend = $frontend; + } return $mainfrontend; } function get_frontend_ipport($frontend, $userfriendly=false) { $mainfrontend = get_primaryfrontend($frontend); $result = array(); - if (!is_arrayset($mainfrontend,"a_extaddr","item")) + if (!is_arrayset($mainfrontend,"a_extaddr","item")) { return $result; + } foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { if ($extaddr['extaddr'] == 'custom'){ $addr = $extaddr['extaddr_custom']; } else { $addr = haproxy_interface_ip($extaddr['extaddr'], $userfriendly); } - if ($userfriendly and is_ipaddrv6($addr)) + if ($userfriendly and is_ipaddrv6($addr)) { $addr = "[{$addr}]"; + } $port = $extaddr['extaddr_port']; $newitem = array(); @@ -1910,10 +2484,11 @@ function get_frontend_bindips($frontend) { $iporalias = $extaddr['extaddr_custom']; $a_ip = haproxy_addressoralias_to_list($iporalias); } - if ($extaddr['extaddr_ssl'] == 'yes') + if ($extaddr['extaddr_ssl'] == 'yes') { $ssl = $ssl_info; - else + } else { $ssl = ""; + } foreach($a_ip as $ip) { $portsnumeric = group_ports(haproxy_portoralias_to_list($extaddr['extaddr_port'])); @@ -1940,46 +2515,66 @@ function haproxy_check_config() { $activefrontends = array(); $issues = array(); - foreach($a_backends as $frontend) { - if (($frontend['status'] != 'active') || ($frontend['secondary'] == 'yes')) + foreach ($a_backends as $frontend) { + if (($frontend['status'] != 'active') || ($frontend['secondary'] == 'yes')) { continue; + } $ipports = get_frontend_ipport($frontend); foreach($ipports as $ipport) { $id = "{$ipport['addr']}:{$ipport['port']}"; - if (isset($activefrontends[$id])) - $issues['P_'.$id] = "Multiple primary frontends with IP:Port \"$id\", use Shared-Frontends instead."; - else - $activefrontends[$id] = true; + if (isset($activefrontends[$id])) { + $activefrontends[$id] = $activefrontends[$id].", ".$frontend['name']; + $issues['P_'.$id] = "Multiple primary frontends ({$activefrontends[$id]}) with IP:Port \"$id\", use Shared-Frontends instead."; + } else { + $activefrontends[$id] = $frontend['name']; + } } } - foreach($a_backends as $frontend) { - if (($frontend['status'] != 'active') || ($frontend['secondary'] != 'yes')) + foreach ($a_backends as $frontend) { + if (($frontend['status'] != 'active') || ($frontend['secondary'] != 'yes')) { continue; + } $mainfrontend = get_primaryfrontend($frontend); - if (!isset($mainfrontend)) + if (!isset($mainfrontend)) { $issues['S_'.$frontend['name']] = "Secondary frontend \"{$frontend['name']}\" without active primary frontend."; + } } - foreach ($issues as $item) + foreach ($issues as $item) { $result .= ($result == false ? "" : "<br/>") . $item; + } return $result; } -function get_haproxy_frontends($excludeitem="") { +function get_haproxy_backends() { + global $config; + $a_backend = &$config['installedpackages']['haproxy']['ha_pools']['item']; + $result = array(); + if (!is_array($a_backend)) { + return $result; + } + foreach ($a_backend as &$backend) { + $result[$backend['name']]['name'] = "{$backend['name']}"; + $result[$backend['name']]['ref'] = &$backend; + } + uasort($result, haproxy_compareByName); + return $result; +} + +function get_haproxy_frontends($excludeitem = "") { global $config; $a_frontend = &$config['installedpackages']['haproxy']['ha_backends']['item']; $result = array(); - if(!is_array($a_frontend)) + if (!is_array($a_frontend)) { return $result; - foreach($a_frontend as &$frontend) - { - if ($frontend['secondary']) - continue; - if ($frontend['name'] == $excludeitem) + } + foreach ($a_frontend as &$frontend) { + if ($frontend['secondary'] || $frontend['name'] == $excludeitem) { continue; + } $serveraddress = get_frontend_ipport($frontend, true); $serveradresstext = null; - foreach($serveraddress as $addr) { + foreach ($serveraddress as $addr) { $serveradresstext .=($serveradresstext == null ? "" : ", ") . "{$addr['addr']}:{$addr['port']}"; } $result[$frontend['name']]['name'] = "{$frontend['name']} - {$frontend['type']} ({$serveradresstext})"; @@ -2009,30 +2604,44 @@ function get_frontend_uses_ssl_only($frontend) { $mainfrontend = get_primaryfrontend($frontend); if (is_arrayset($mainfrontend,'a_extaddr','item')) { foreach($mainfrontend['a_extaddr']['item'] as $extaddr) { - if ($extaddr['extaddr_ssl'] != 'yes') + if ($extaddr['extaddr_ssl'] != 'yes') { return false; + } } } return true; } -function haproxy_get_cert_acl($cert) { - $acl_item = array(); +function haproxy_get_cert_acls($cert, $usealternativenames = false) { + $result = array(); - $cert_cn = cert_get_cn($cert['crt']); + if (!$usealternativenames) { + $cert_cns = array(); + $cert_cns[] = cert_get_cn($cert['crt']); + } else { + $cert_cns = haproxy_get_certificate_subjectAltNames($cert['crt']); + } $descr = haproxy_escape_acl_name($cert['descr']); unset($cert); - $is_wildcard = substr($cert_cn, 0, 2) == "*."; - $cert_cn_regex = str_replace(".", "\.", $cert_cn); // escape '.' in regex. - $wild_regex = ""; - if ($is_wildcard) { - $cert_cn_regex = "([^\.]*)" . substr($cert_cn_regex, 1);// match only subdomains directly under the wildcard + //$i = 1; + foreach ($cert_cns as $cert_cn) { + $acl_item = array(); + $is_wildcard = substr($cert_cn, 0, 2) == "*."; + $cert_cn_regex = str_replace(".", "\.", $cert_cn); // escape '.' in regex. + $wild_regex = ""; + if ($is_wildcard) { + $cert_cn_regex = "([^\.]*)" . substr($cert_cn_regex, 1);// match only subdomains directly under the wildcard + } + $cert_cn_regex = "^{$cert_cn_regex}(:([0-9]){1,5})?$";// match both with and without port. + + $acl_item['descr'] = "Certificate ACL matches: {$cert_cn}"; + //$aclname_add = $usealternativenames ? "_{$i}" : ""; + $acl_item['ref'] = array('name' => "{$aclname}_{$descr}{$aclname_add}",'expression' => 'host_regex', 'value' => $cert_cn_regex, 'certacl' => true); + + //$i++; + $result[] = $acl_item; } - $cert_cn_regex = "^{$cert_cn_regex}(:([0-9]){1,5})?$";// match both with and without port. - - $acl_item['descr'] = "Certificate ACL matches: {$cert_cn}"; - $acl_item['ref'] = array('name' => "{$aclname}_{$descr}",'expression' => 'host_regex', 'value' => $cert_cn_regex, 'certacl' => true); - return $acl_item; + return $result; } function get_frontend_acls($frontend) { @@ -2043,12 +2652,14 @@ function get_frontend_acls($frontend) { { foreach ($a_acl as $entry) { $acl = haproxy_find_acl($entry['expression']); - if (!$acl) + if (!$acl) { continue; + } // Filter out acls for different modes - if ($acl['mode'] != '' && $acl['mode'] != strtolower($mainfrontend['type'])) + if ($acl['mode'] != '' && $acl['mode'] != strtolower($mainfrontend['type'])) { continue; + } $not = $entry['not'] == "yes" ? "not: " : ""; $acl_item = array(); $acl_item['descr'] = $acl['name'] . " " . (isset($acl['novalue']) ? "" : $not . $entry['value']); @@ -2060,22 +2671,36 @@ function get_frontend_acls($frontend) { if (get_frontend_uses_ssl($frontend)) { $a_acl = &$frontend['ha_acls']['item']; - if(!is_array($a_acl)) - $a_acl=array(); + if (!is_array($a_acl)) { + $a_acl = array(); + } - $poolname = $frontend['backend_serverpool'] . "_" . strtolower($frontend['type']); - $aclname = "SNI_" . $poolname; + //$poolname = $frontend['backend_serverpool'] . "_" . strtolower($frontend['type']); + //$aclname = "SNI_" . $poolname; - if (ifset($frontend['ssloffloadacl']) == 'yes' || ifset($frontend['ssloffloadaclnondefault']) == 'yes') { + if (ifset($frontend['ssloffloadacl']) == 'yes') { + $cert = lookup_cert($frontend['ssloffloadcert']); + $result = array_merge($result, haproxy_get_cert_acls($cert)); + } + if (ifset($frontend['ssloffloadacl_an']) == 'yes') { $cert = lookup_cert($frontend['ssloffloadcert']); - $result[] = haproxy_get_cert_acl($cert); + $result = array_merge($result, haproxy_get_cert_acls($cert, true)); } if (ifset($frontend['ssloffloadacladditional']) == 'yes') { $certs = $frontend['ha_certificates']['item']; - if (is_array($certs)){ - foreach($certs as $certref){ + if (is_array($certs)) { + foreach ($certs as $certref) { + $cert = lookup_cert($certref['ssl_certificate']); + $result = array_merge($result, haproxy_get_cert_acls($cert)); + } + } + } + if (ifset($frontend['ssloffloadacladditional_an']) == 'yes') { + $certs = $frontend['ha_certificates']['item']; + if (is_array($certs)) { + foreach ($certs as $certref) { $cert = lookup_cert($certref['ssl_certificate']); - $result[] = haproxy_get_cert_acl($cert); + $result = array_merge($result, haproxy_get_cert_acls($cert, true)); } } } @@ -2083,16 +2708,44 @@ function get_frontend_acls($frontend) { return $result; } +function get_backend_acls($backend, $type) { + $result = array(); + $a_acl = &$backend['a_acl']['item']; + if (is_array($a_acl)) + { + foreach ($a_acl as $entry) { + $acl = haproxy_find_acl($entry['expression']); + if (!$acl) { + continue; + } + + // Filter out acls for different modes + if ($acl['mode'] != '' && $acl['mode'] != $type) { + continue; + } + $not = $entry['not'] == "yes" ? "not: " : ""; + $acl_item = array(); + $acl_item['descr'] = $acl['name'] . " " . (isset($acl['novalue']) ? "" : $not . $entry['value']); + $acl_item['ref'] = $entry; + + $result[] = $acl_item; + } + } + return $result; +} + function get_backend_id($name) { global $config; $a_backend = &$config['installedpackages']['haproxy']['ha_pools']['item']; $i = 0; - if(is_array($a_backend)) - foreach($a_backend as $key => $backend) { - if ($backend['name'] == $name) + if (is_array($a_backend)) { + foreach ($a_backend as $key => $backend) { + if ($backend['name'] == $name) { return $i; + } $i++; } + } return null; } @@ -2100,8 +2753,9 @@ function get_backend($name) { global $config; $a_backend = &$config['installedpackages']['haproxy']['ha_pools']['item']; $id = get_backend_id($name); - if (is_numeric($id)) + if (is_numeric($id)) { return $a_backend[$id]; + } return null; } @@ -2112,8 +2766,9 @@ function use_frontend_as_unixsocket($name) { $a_servers = &$backend['ha_servers']['item']; if (is_array($a_servers)) { foreach($a_servers as $server) { - if ($server['forwardto'] && $server['forwardto'] == $name) + if ($server['forwardto'] && $server['forwardto'] == $name) { return true; + } } } } @@ -2133,8 +2788,9 @@ function haproxy_escape_acl_name($aclname) { function haproxy_find_create_certificate($certificatename) { global $g; $cert = lookup_cert_by_name($certificatename); - if (is_array($cert)) + if (is_array($cert)) { return $cert; + } global $config; $a_cert =& $config['cert']; $cert = array(); diff --git a/config/haproxy-devel/pkg/haproxy_htmllist.inc b/config/haproxy-devel/pkg/haproxy_htmllist.inc index 394f3ff6..7eaad023 100644 --- a/config/haproxy-devel/pkg/haproxy_htmllist.inc +++ b/config/haproxy-devel/pkg/haproxy_htmllist.inc @@ -48,100 +48,129 @@ class HaproxyHtmlList public $fields_details = null; public $keyfield = ""; - public function HaproxyHtmlList($tablename, $fields){ + public function HaproxyHtmlList($tablename, $fields) { $this->tablename = $tablename; $this->fields = $fields; } - public function Draw($data){ + public function Draw($data) { $this->haproxy_htmllist($data, $this->fields, $this->editmode, $this->fields_details); } - function haproxy_htmllist_get_values(){ + public function outputjavascript() { + $table_def = array(); + $table_def['keyfield'] = $this->keyfield; + phparray_to_javascriptarray($table_def, "tabledefinition_".$this->tablename,Array('/*','/*/*')); + phparray_to_javascriptarray($this->fields, "fields_".$this->tablename,Array('/*','/*/name','/*/type','/*/text','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + if (count($this->fields_details) != 0) { + phparray_to_javascriptarray($this->fields_details,"fields_details_".$this->tablename,Array('/*','/*/name','/*/columnheader','/*/description','/*/type','/*/text','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name','/*/items/*/*/name')); + } + } + + // function retrieves all posted values and returns an array + public function haproxy_htmllist_get_values() { $values = array(); - for($x=0; $x<99; $x++) { + for($x = 0; $x < 99; $x ++) { $value = array(); $add_item = false; - foreach($this->fields as $item){ + if (is_array($this->fields_details)) { + $fields = array_merge($this->fields, $this->fields_details); + } else { + $fields = $this->fields; + } + foreach($fields as $item) { $itemname = $item['name']; - $value[$itemname] = $_POST[$itemname.$x]; - if ($item['type'] == 'textarea') + $value[$itemname] = $_POST[$this->tablename.$itemname.$x]; + if ($item['type'] == 'textarea') { $value[$itemname] = base64_encode($value[$itemname]); - $add_item |= isset($_POST[$itemname.$x]); + } + $add_item |= isset($_POST[$this->tablename.$itemname.$x]); } if ($add_item) { if ($this->keyfield != "") { - if (isset($_POST[$this->tablename."_key".$x])) + if (isset($_POST[$this->tablename."_key".$x])) { $key = $_POST[$this->tablename."_key".$x]; - else - $key = $_POST[$this->keyfield.$x]; - - } else + } else { + $key = $_POST[$this->tablename.$this->keyfield.$x]; + } + } else { $key = ""; - - if (isset($values[$key])) + } + $index = $_POST[$this->tablename."_rowindex".$x]; + $value['_index'] = $index; + if (isset($values[$key])) { $values[] = $value; - else + } else { $values[$key] = $value; + } } } + usort($values, 'sort_index'); + return $values; } - - private function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter) { - $itemnamenr = $itemname . $counter; + + function haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter) { + $itemnamenr = $this->tablename . $itemname . $counter; $itemtype = $item['type']; if ($editable) { $itemtype = $item['type']; - if ($itemtype == "select"){ - echo_html_select($itemnamenr, $item['items'], $itemvalue,"","html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);", "width:{$item['size']}"); - } else - if ($itemtype == "checkbox"){ + if ($itemtype == "select") { + echo_html_select($itemnamenr, $item['items'], $itemvalue,"-none available-","html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);", "width:{$item['size']}"); + } elseif ($itemtype == "checkbox") { $checked = $itemvalue=='yes' ? " checked" : ""; echo "<input onclick='html_listitem_change(\"{$this->tablename}\",\"{$itemname}\",\"{$counter}\",this);' name='$itemnamenr' id='$itemnamenr' type='checkbox'$checked value='yes' size='{$item['size']}' />"; - } else - if ($itemtype == "textarea"){ + } elseif ($itemtype == "textarea") { echo "<textarea name='$itemnamenr' id='$itemnamenr' type='text' cols='{$item['size']}' rows='10'>"; echo htmlspecialchars(base64_decode($itemvalue)); echo "</textarea>"; - } else + } elseif ($itemtype == "fixedtext") { + echo $item['text']; + } else { echo "<input name='$itemnamenr' id='$itemnamenr' type='text' value='{$itemvalue}' size='{$item['size']}' />"; + } } else { - if ($itemtype == "select"){ + if ($itemtype == "select") { echo $item['items'][$itemvalue]['name']; - } else - if ($itemtype == "checkbox"){ + } elseif ($itemtype == "checkbox") { echo $itemvalue=='yes' ? gettext('yes') : gettext('no'); - } else - if ($itemtype == "textarea"){ - echo '<div style="overlow:scroll;max-height:120px;overflow-y: scroll;">'; - echo str_replace("\n","<br/>", htmlspecialchars(base64_decode($itemvalue))); + } elseif ($itemtype == "textarea") { + echo "<div style='overlow:scroll;max-height:120px;max-width:{$item['colwidth']};overflow-y: scroll;'>"; + echo str_replace(" "," ", str_replace("\n","<br/>", htmlspecialchars(base64_decode($itemvalue)))); echo '</div>'; - } else + } elseif ($itemtype == "fixedtext") { + echo $item['text']; + } else { echo htmlspecialchars($itemvalue); + } } } function haproxy_htmllist($rowvalues,$items,$editstate=false,$itemdetails=null){ $tablename = $this->tablename; global $g, $counter; - echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='$tablename'> + echo "<table class='' width='100%' cellpadding='0' cellspacing='0' id='{$tablename}'> + <thead> <tr>"; foreach($items as $item){ echo "<td width='{$item['colwidth']}' class='listhdrr'>{$item['columnheader']}</td>"; } echo "<td width='5%' class=''></td> - </tr>"; - if (is_array($rowvalues)){ - foreach($rowvalues as $keyid => $value){ - if ($this->keyfield != "") { - if (preg_match("/[^0-9]/", $keyid)) + </tr> + </thead> + <tbody>"; + if (is_array($rowvalues)) { + foreach($rowvalues as $keyid => $value) { + if (!empty($this->keyfield)) { + if (preg_match("/[^0-9]/", $keyid)) { $itemvalue = $keyid; - else + } else { $itemvalue = $value[$this->keyfield]; + } $key = "<input name='{$tablename}_key{$counter}' id='{$tablename}_key{$counter}' type='hidden' value='{$itemvalue}'>"; - } else + } else { $key = ""; + } if (!$editstate) { echo "<tr id='tr_view_$counter' ondblclick='editRow($counter); return false;' >"; @@ -152,26 +181,36 @@ class HaproxyHtmlList $itemname = $item['name']; $itemvalue = $value[$itemname]; if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, false); - } else + $item['customdrawcell']($this, $item, $itemvalue, false, $itemname, $counter); + } else { $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter); + } echo "</td>"; $leftitem = false; } echo " - <td class='list'> - <table border='0' cellspacing='0' cellpadding='1'><tr> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow($counter); return false;' /> - </td> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow($counter, \"$tablename\"); return false;' /> - </td> - <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> - </td></tr></table> - </td>"; + <td class='list'> + <table border='0' cellspacing='0' cellpadding='1'><tr> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_e.gif' title='edit entry' width='17' height='17' border='0' onclick='editRow({$counter}); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow({$counter}, \"{$tablename}\"); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow({$counter}, \"{$tablename}\"); return false;' /> + </td>"; + if (empty($this->noindex)) { + echo "<td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_up.gif' title='move row up' width='17' height='17' border='0' onclick='moveRowUp({$counter}, \"{$tablename}\"); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_down.gif' title='move row down' width='17' height='17' border='0' onclick='moveRowDown({$counter}, \"{$tablename}\"); return false;' /> + </td>"; + } + echo "</tr></table> + </td>"; echo "</tr>"; } $displaystyle = $editstate ? "" : "display: none;"; @@ -181,9 +220,10 @@ class HaproxyHtmlList $itemvalue = $value[$itemname]; echo "<td class='vtable'>".$key; if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, true, $item['name'].$counter); - } else + $item['customdrawcell']($this, $item, $itemvalue, true, $itemname, $counter); + } else { $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter); + } echo "</td>"; $key = ""; } @@ -191,11 +231,21 @@ class HaproxyHtmlList <td class='list'> <table border='0' cellspacing='0' cellpadding='1'><tr> <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='removeRow(this); return false;' /> + <input name='{$tablename}_rowindex{$counter}' id='{$tablename}_rowindex{$counter}' type='hidden' value='{$counter}' /> + <img src='/themes/{$g['theme']}/images/icons/icon_x.gif' title='delete entry' width='17' height='17' border='0' onclick='deleteRow({$counter}, \"{$tablename}\"); return false;' /> </td> <td valign='middle'> - <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow($counter, \"$tablename\"); return false;' /> - </td></tr></table> + <img src='/themes/{$g['theme']}/images/icons/icon_plus.gif' title='duplicate entry' width='17' height='17' border='0' onclick='dupRow({$counter}, \"{$tablename}\"); return false;' /> + </td>"; + if (empty($this->noindex)) { + echo "<td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_up.gif' title='move row up' width='17' height='17' border='0' onclick='moveRowUp({$counter}, \"{$tablename}\"); return false;' /> + </td> + <td valign='middle'> + <img src='/themes/{$g['theme']}/images/icons/icon_down.gif' title='move row down' width='17' height='17' border='0' onclick='moveRowDown({$counter}, \"{$tablename}\"); return false;' /> + </td>"; + } + echo "</tr></table> </td>"; echo "</tr>"; if (isset($itemdetails)) { @@ -204,7 +254,7 @@ class HaproxyHtmlList ?> <td class='vtable listlr' style='border-bottom-width: medium;vertical-align:top;'> <div style="position:relative;float:right;width:11px;height:11px;"> - <a onclick="htmltable_toggle_details('<?="htmltable_{$tablename}_{$counter}_details"?>')"> + <a onclick="htmltable_toggle_details('<?=$tablename?>','<?=$counter?>','<?="htmltable_{$tablename}_{$counter}_details"?>')"> <img id="htmltable_<?="{$tablename}_{$counter}"?>_details_off" alt="Expand advanced server settings" src="tree/plus.gif" style="clip:rect(19px 13px 30px 2px); top:-19px;position:absolute;"/> </a> @@ -215,80 +265,92 @@ class HaproxyHtmlList $itemnr = 0; echo "<div id='htmltable_{$tablename}_{$counter}_details_view'>"; $itemcount = count($itemdetails); + $leftitem = true; foreach($itemdetails as $item) { - echo "<div style='float: left;padding-right: 2px;'>"; - $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; - echo $item['columnheader'] . ": "; $itemname = $item['name']; $itemvalue = $value[$itemname]; + //TODO don't filter empty items, filter context un-related items through customizable function.. + if (empty($itemvalue)) { + continue; + } + echo "<div style='float: left;padding-right: 2px;'>"; + $tdclass = ""; + if (!$leftitem) { + echo ", "; + } + $leftitem = false; + echo $item['columnheader'] . ": "; if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, false); - } else + $item['customdrawcell']($this, $item, $itemvalue, false, $itemname, $counter); + } else { $this->haproxy_htmllist_drawcell($item, $itemvalue, false, $itemname, $counter); - $leftitem = false; + } $itemnr++; - if ($itemcount != $itemnr) - echo ", "; echo "</div>"; } echo "</div>"; echo "<div id='htmltable_{$tablename}_{$counter}_details_edit' style='display:none;'>"; echo "<table class='tabcont' style='border-collapse:collapse' border='1' cellspacing='0' >"; - $leftitem = true; foreach($itemdetails as $item) { - echo "<tr id='tr_edititemdetails_$counter' ondblclick='editRow($counter); return false;'>"; - $tdclass = "";//$leftitem ? "vtable listlr" : "vtable listr"; - echo "<td style='border-right:0' class='$tdclass'>"; + $itemname = $item['name']; + echo "<tr id='tr_edititemdetails_{$counter}_{$itemname}'>"; + echo "<td style='border-right:0'>"; echo "{$item['columnheader']}: "; echo "</td>"; - echo "<td style='border-left:0' class='$tdclass'>"; - $itemname = $item['name']; + echo "<td style='border-left:0'>"; $itemvalue = $value[$itemname]; - echo "{$item['description']}<br/>"; + + if (!empty($item['description'])) { + echo "{$item['description']}<br/>"; + } if (isset($item['customdrawcell'])) { - $item['customdrawcell']($item, $itemvalue, true, $itemname . $counter); - } else + $item['customdrawcell']($this, $item, $itemvalue, true, $itemname, $counter); + } else { $this->haproxy_htmllist_drawcell($item, $itemvalue, true, $itemname, $counter); + } echo "</td>"; - $leftitem = false; - echo "</tr>"; + echo "</tr>"; } echo "</table>"; echo "</div>"; echo "</td>"; echo "</tr>"; } - if (isset($itemdetails)) { - $colspan = count($items)-1; - echo "<tr id='htmltable_{$tablename}_{$counter}_details' style='$displaystyle' >"; - echo "<td class='vtable listlr' style='border-bottom-width: medium;'> </td>"; - echo "<td class='vtable listr' colspan='$colspan' style='border-bottom-width: medium;'>"; - echo "</td>"; - echo "</tr>"; - } - $counter++; } } - echo "</table> - <a onclick='javascript:addRowTo(\"$tablename\"); return false;' href='#'> + echo "</tbody> + </table> + <a onclick='javascript:addRowTo(\"{$tablename}\"); return false;' href='#'> <img border='0' src='/themes/{$g['theme']}/images/icons/icon_plus.gif' alt='' title='add another entry' /> </a>"; } } +function sort_index(&$a, &$b) { + // sort callback function, cannot be inside the object. + if ($a['_index'] != $b['_index']) { + return $a['_index'] > $b['_index'] ? 1 : -1; + } + return 0; +} + function haproxy_htmllist($tablename,$rowvalues,$items,$editstate=false,$itemdetails=null){ $list = new HaproxyHtmlList($tablename, $items); $list->haproxy_htmllist($rowvalues, $items, $editstate, $itemdetails); } -function haproxy_htmllist_get_values($html_list){ - $list = new HaproxyHtmlList("-", $html_list); +function haproxy_htmllist_get_values($tablename, $html_list){ + $list = new HaproxyHtmlList($tablename, $html_list); return $list->haproxy_htmllist_get_values(); } function haproxy_htmllist_js(){ + global $g; ?><script type="text/javascript"> + + var theme = "<?=$g['theme']?>"; + function html_listitem_change(tableId, fieldId, rowNr, field) { javascript_event = tableId + "_listitem_change"; var fn = window[javascript_event]; @@ -297,61 +359,73 @@ function haproxy_htmllist_js(){ } } - function htmllist_get_select_items(prefix,tableId) { + function htmllist_get_select_items(prefix, tableId) { var items; - var i = tableId.lastIndexOf('_'); - var items_name = prefix+"_"+tableId.substr(i+1); - items = eval("typeof "+items_name+" !== 'undefined' ? "+items_name+" : {}"); + var items_name = prefix+"_"+tableId; + items = eval("typeof "+items_name+" !== 'undefined' ? "+items_name+" : null"); return items; } + function createFieldHtml(tableId, field, rowId) { + var result = ""; + if(field['type'] == 'textbox') { + result="<input size='" + field['size'] + "' name='" + tableId + field['name'] + rowId + + "' id='" + tableId + field['name'] + rowId + + "'><\/input> "; + } else if(field['type'] == 'textarea') { + result="<textarea cols='" + field['size'] + "' rows='30' name='" + tableId + field['name'] + rowId + + "' id='" + tableId + field['name'] + rowId + + "'><\/textarea> "; + } else if(field['type'] == 'select') { + var seltext = ""; + var fieldid = field['name']; + var fn = window["htmllist_get_select_options"]; + fielditems = field['items']; + if (typeof fn === 'function'){ + fielditems = htmllist_get_select_options(tableId, field['name'], fielditems); + } + for (var fieldvalueid in fielditems) { + var fieldvalue = fielditems[fieldvalueid] + seltext += "<option value='"+fieldvalueid+"'>"+fieldvalue['name']+"<\/option>"; + } + + result="<select style='width:" + field['size'] + "' name='" + tableId + field['name'] + rowId + + "' id='" + tableId + field['name'] + rowId + "' "+ + "onchange='html_listitem_change(\""+tableId+"\",\""+field['name']+"\",\""+rowId+"\",this);' " + + ">" + seltext + "<\/select> "; + } else if(field['type'] == 'fixedtext') { + result=field['text']; + } else { + result="<input type='checkbox' name='" + tableId + field['name'] + rowId +"'"+ + "id='" + tableId + field['name'] + rowId + "' "+ + "onclick='html_listitem_change(\""+tableId+"\",\""+field['name']+"\",\""+rowId+"\",this);' " + + "value='yes'><\/input> "; + } + return result; + } + var addRowTo = (function() { return (function (tableId) { var d, tbody, tr, td, bgc, i, ii, j, type, seltext, items; var btable, btbody, btr, btd; d = document; - items = htmllist_get_select_items('fields',tableId); - tbody = d.getElementById(tableId).getElementsByTagName("tbody").item(0); - tr = d.createElement("tr"); totalrows++; - tr.setAttribute("id","aclrow" + totalrows); - + + // create edit row fields + items = htmllist_get_select_items('fields',tableId); + tr = d.createElement("tr"); + tr.setAttribute("id","tr_edit_" + totalrows); for (var i in items) { + fieldhtml = createFieldHtml(tableId, items[i], totalrows); td = d.createElement("td"); - if(items[i]['type'] == 'textbox') { - td.innerHTML="<input size='" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + - "'><\/input> "; - } else if(items[i]['type'] == 'textarea') { - td.innerHTML="<textarea cols='" + items[i]['size'] + "' rows='30' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + - "'><\/textarea> "; - } else if(items[i]['type'] == 'select') { - seltext = htmllist_get_select_options(tableId, items[i]['name']); - td.innerHTML="<select style='width:" + items[i]['size'] + "' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + "' "+ - "onchange='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " + - ">" + seltext + "<\/select> "; - } else { - td.innerHTML="<input type='checkbox' name='" + items[i]['name'] + totalrows +"'"+ - "id='" + items[i]['name'] + totalrows + "' "+ - "onclick='html_listitem_change(\""+tableId+"\",\""+items[i]['name']+"\",\""+totalrows+"\",this);' " + - "value='yes'><\/input> "; - } + td.innerHTML = fieldhtml; tr.appendChild(td); } td = d.createElement("td"); td.rowSpan = "1"; td.setAttribute("class","list"); - - items = htmllist_get_select_items('fields_details',tableId); - for (var i in items) { - td.innerHTML=td.innerHTML+"<input type='hidden' name='" + items[i]['name'] + totalrows + - "' id='" + items[i]['name'] + totalrows + - "'><\/input> "; - } // Recreate the button table. btable = document.createElement("table"); @@ -360,20 +434,75 @@ function haproxy_htmllist_js(){ btable.setAttribute("cellpadding", "1"); btbody = document.createElement("tbody"); btr = document.createElement("tr"); + btd = document.createElement("td"); btd.setAttribute("valign", "middle"); - btd.innerHTML = '<img src="/themes/' + theme + '/images/icons/icon_x.gif" title="delete entry" width="17" height="17" border="0" onclick="removeRow(this); return false;" />'; + btd.innerHTML = + '<input name="'+tableId+'_rowindex'+totalrows+'" id="'+tableId+'_rowindex'+totalrows+'" type="hidden" value="'+totalrows+'" />' + + '<img src="/themes/' + theme + '/images/icons/icon_x.gif" title="delete entry" width="17" height="17" border="0" onclick="deleteRow(' + totalrows + ", '" + tableId + "'); return false;\" />"; btr.appendChild(btd); + btd = document.createElement("td"); btd.setAttribute("valign", "middle"); btd.innerHTML = '<img src="/themes/' + theme + "/images/icons/icon_plus.gif\" title=\"duplicate entry\" width=\"17\" height=\"17\" border=\"0\" onclick=\"dupRow(" + totalrows + ", '" + tableId + "'); return false;\" />"; btr.appendChild(btd); + + + var tabledefinition = htmllist_get_select_items("tabledefinition", tableId); + if (tabledefinition && tabledefinition['keyfield'] == "") { + btd = document.createElement("td"); + btd.setAttribute("valign", "middle"); + btd.innerHTML = '<img src="/themes/' + theme + "/images/icons/icon_up.gif\" title=\"move entry up\" width=\"17\" height=\"17\" border=\"0\" onclick=\"moveRowUp(" + totalrows + ", '" + tableId + "'); return false;\" />"; + btr.appendChild(btd); + + btd = document.createElement("td"); + btd.setAttribute("valign", "middle"); + btd.innerHTML = '<img src="/themes/' + theme + "/images/icons/icon_down.gif\" title=\"move entry down\" width=\"17\" height=\"17\" border=\"0\" onclick=\"moveRowDown(" + totalrows + ", '" + tableId + "'); return false;\" />"; + btr.appendChild(btd); + } + btbody.appendChild(btr); btable.appendChild(btbody); td.appendChild(btable); tr.appendChild(td); - tbody.appendChild(tr); - + tbody.appendChild(tr); // add the edit row to the table + + // create viewdetail row + items = htmllist_get_select_items('fields_details',tableId); + if (items) { + tr = d.createElement("tr"); + tr.setAttribute("id","tr_viewdetail_" + totalrows); + td = d.createElement("td"); + tr.appendChild(td); + td = d.createElement("td"); + table = d.createElement("table"); + table.setAttribute("cellspacing","0"); + for (var i in items) { + field = items[i]; + fieldhtml = createFieldHtml(tableId, field, totalrows); + subtr = d.createElement("tr"); + subtr.setAttribute("id","tr_edititemdetails_" + totalrows + "_" + field['name']); + subtd = d.createElement("td"); + subtd.setAttribute("class","vncell"); + subtd.innerHTML = field['columnheader'] + ": "; + subtr.appendChild(subtd); + subtd = d.createElement("td"); + subtd.setAttribute("class","vncell"); + subtd.innerHTML = field['description'] + "<br/>" + fieldhtml; + subtr.appendChild(subtd); + table.appendChild(subtr); + } + td.appendChild(table); + tr.appendChild(td); + tbody.appendChild(tr); // add the viewdetail row to the table + } + // show/hide conditional fields if applicable using a custom function. + javascript_event = tableId + "_listitem_change"; + var fn = window[javascript_event]; + if (typeof fn === 'function'){ + fn(tableId, "toggle_details", totalrows, null); + } + javascript_row_added = tableId + "_row_added"; var fn = window[javascript_row_added]; if (typeof fn === 'function'){ @@ -387,18 +516,18 @@ function haproxy_htmllist_js(){ addRowTo(tableId); items = htmllist_get_select_items('fields',tableId); for (var i in items) { - dupEl = document.getElementById(items[i]['name'] + rowId); - newEl = document.getElementById(items[i]['name'] + totalrows); + dupEl = document.getElementById(tableId + items[i]['name'] + rowId); + newEl = document.getElementById(tableId + items[i]['name'] + totalrows); if (dupEl && newEl) if(items[i]['type'] == 'checkbox') newEl.checked = dupEl.checked; else newEl.value = dupEl.value; } - items = htmllist_get_select_items('fields_details',tableId); + items = htmllist_get_select_items('fields_details', tableId); for (var i in items) { - dupEl = document.getElementById(items[i]['name'] + rowId); - newEl = document.getElementById(items[i]['name'] + totalrows); + dupEl = document.getElementById(tableId + items[i]['name'] + rowId); + newEl = document.getElementById(tableId + items[i]['name'] + totalrows); if (dupEl && newEl) if(items[i]['type'] == 'checkbox') newEl.value = dupEl.checked ? 'yes' : ''; @@ -428,21 +557,89 @@ function haproxy_htmllist_js(){ if (edit) edit.parentNode.removeChild(edit); } - function removeRow(el) { - var cel; - // Break out of one table first - while (el && el.nodeName.toLowerCase() != "table") - el = el.parentNode; - while (el && el.nodeName.toLowerCase() != "tr") - el = el.parentNode; - if (el && el.parentNode) { - cel = el.getElementsByTagName("td").item(0); - el.parentNode.removeChild(el); + function moveRowUp(rowId, tableId) { + moveRow(rowId, tableId, true); + } + function moveRowDown(rowId, tableId) { + moveRow(rowId, tableId, false); + } + function moveRow(rowId, tableId, up) { + var rowview = document.getElementById("tr_view_" + rowId); + var rowedit = document.getElementById("tr_edit_" + rowId); + var rowviewdetail = document.getElementById("tr_viewdetail_" + rowId); + + var parent = rowedit.parentNode; + var swapid; + var swaprowedit; + if (up){ + //move current rows before the previous row + var prevtr; + if (rowview) { + prevtr = rowview.previousElementSibling; + } else { + prevtr = rowedit.previousElementSibling; + } + if (!prevtr) + return; // was already top element. + var swapid = prevtr['id']; + var i = swapid.lastIndexOf('_'); + swapid = swapid.substr(i+1); + var prevrowview = document.getElementById("tr_view_" + swapid); + swaprowedit = document.getElementById("tr_edit_" + swapid); + if (prevrowview){ + firstprevrow = prevrowview; + } else { + firstprevrow = swaprowedit; + } + // move the 3 rows + if (rowview) { + parent.insertBefore(rowview, firstprevrow); + } + parent.insertBefore(rowedit, firstprevrow); + if (rowviewdetail) { + parent.insertBefore(rowviewdetail, firstprevrow); + } + } else { + //move next row before the current row + var nexttr; + if (rowviewdetail) { + nexttr = rowviewdetail.nextElementSibling; + } else { + nexttr = rowedit.nextElementSibling; + } + if (!nexttr) { + return; // was already bottom element. + } + var swapid = nexttr['id']; + var i = swapid.lastIndexOf('_'); + swapid = swapid.substr(i+1); + var prevrowview = document.getElementById("tr_view_" + swapid); + swaprowedit = document.getElementById("tr_edit_" + swapid); + var prevrowviewdetail = document.getElementById("tr_viewdetail_" + swapid); + if (rowview){ + firstrow = rowview; + } else { + firstrow = rowedit; + } + // move the 3 rows + if (prevrowview) { + parent.insertBefore(prevrowview, firstrow); + } + parent.insertBefore(swaprowedit, firstrow); + if (prevrowviewdetail) { + parent.insertBefore(prevrowviewdetail, firstrow); + } } + + var id_a = document.getElementById(tableId+'_rowindex' + swapid); + var id_b = document.getElementById(tableId+'_rowindex' + rowId); + temp = id_a.value; + id_a.value = id_b.value; + id_b.value = temp; } - function htmltable_toggle_details(table_row_detail_id) { + function htmltable_toggle_details(tableId, rowNr, table_row_detail_id) { tredit = document.getElementById(table_row_detail_id+'_off'); trviewdetail = document.getElementById(table_row_detail_id+'_edit'); treditdetail = document.getElementById(table_row_detail_id+'_view'); @@ -450,6 +647,13 @@ function haproxy_htmllist_js(){ tredit.style.display=current_on ? '' : 'none'; trviewdetail.style.display=current_on ? 'none' : ''; treditdetail.style.display=current_on ? '' : 'none'; + + // show/hide conditional fields if applicable using a custom function. + javascript_event = tableId + "_listitem_change"; + var fn = window[javascript_event]; + if (typeof fn === 'function'){ + fn(tableId, "toggle_details", rowNr, null); + } } </script><? } diff --git a/config/haproxy-devel/pkg/haproxy_upgrade_config.inc b/config/haproxy-devel/pkg/haproxy_upgrade_config.inc index c1c951df..052f7c77 100644 --- a/config/haproxy-devel/pkg/haproxy_upgrade_config.inc +++ b/config/haproxy-devel/pkg/haproxy_upgrade_config.inc @@ -1,6 +1,6 @@ <?php /* - haproxy.inc + haproxy_upgrade_config.inc Copyright (C) 2015 PiBa-NL All rights reserved. @@ -26,7 +26,9 @@ POSSIBILITY OF SUCH DAMAGE. */ +require_once("haproxy_utils.inc"); require_once("pkg-utils.inc"); +require_once("haproxy.inc"); function haproxy_upgrade_config() { global $config, $static_output; @@ -143,16 +145,18 @@ function haproxy_upgrade_config() { } if ($configversion < "00.13") { // update config to "haproxy-devel 1.5-dev19 pkg v0.13" - foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { - if (isset($bind['extaddr'])) { - $new['extaddr'] = $bind['extaddr']; - $new['extaddr_port'] = $bind['port']; - $new['extaddr_ssl'] = $bind['ssloffload']; - $bind['a_extaddr']['item'][] = $new; + if (is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { + if (isset($bind['extaddr'])) { + $new['extaddr'] = $bind['extaddr']; + $new['extaddr_port'] = $bind['port']; + $new['extaddr_ssl'] = $bind['ssloffload']; + $bind['a_extaddr']['item'][] = $new; + } + unset($bind['extaddr']); + unset($bind['port']); + //unset($bind['ssloffload']); } - unset($bind['extaddr']); - unset($bind['port']); - //unset($bind['ssloffload']); } $configversion = "00.13"; } @@ -167,15 +171,17 @@ function haproxy_upgrade_config() { $static_output .= "HAProxy, 00.17\n"; update_output_window($static_output); // remove 'none' ca-cert, and set checkbox to allow for no certificate instead. - foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { - $list = array(); - foreach ($bind['clientcert_ca']['item'] as $ca){ - if (empty($ca['cert_ca'])) - $bind['sslclientcert-none'] = 'yes'; - else - $list[] = $ca; + if (is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$bind) { + $list = array(); + foreach ($bind['clientcert_ca']['item'] as $ca){ + if (empty($ca['cert_ca'])) + $bind['sslclientcert-none'] = 'yes'; + else + $list[] = $ca; + } + $bind['clientcert_ca']['item'] = $list; } - $bind['clientcert_ca']['item'] = $list; } $configversion = "00.17"; } @@ -193,6 +199,71 @@ function haproxy_upgrade_config() { } $configversion = "00.19"; } + if ($configversion < "00.32") { + $frontends = array(); + if (is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { + foreach ($config['installedpackages']['haproxy']['ha_backends']['item'] as &$frontend) { + $primaryfrontend = get_primaryfrontend($frontend); + $fe_name = $primaryfrontend['name']; + $frontends[$fe_name][] = &$frontend; + } + + foreach ($frontends as $primary) { + $acl_count = array(); + foreach ($primary as &$frontend){ + $acl_use = array(); + $a_actions = &$frontend['a_actionitems']['item']; + if (!is_array($a_actions)) { + $a_actions = array(); + } + + $primaryfrontend = get_primaryfrontend($frontend); + $frontendtype = $primaryfrontend['type']; + $is_default = true; + if (is_array($frontend['ha_acls']['item'])) { + $a_acl = &$frontend['ha_acls']['item']; + + foreach ($a_acl as &$aclitem) { + $aclname = $aclitem['name']; + $acltype = haproxy_find_acl($aclitem['expression']); + if ($aclitem['expression'] == "backendservercount") { + $aclitem['backendservercountbackend'] = $frontend['backend_serverpool']; + } + if (!isset($acl_count[$aclname])) { + $acl_count[$aclname] = 1; + } else { + $acl_count[$aclname] += 1; + $aclitem['name'] .= "_{$acl_count[$aclname]}"; + } + if (!isset($acltype)) + continue; + if ($acltype['mode'] != '' && $acltype['mode'] != strtolower($frontendtype)) { + continue; + } + $acl_use[$aclname][] = $aclitem['name']; + } + foreach ($acl_use as $key => $acl_x) { + $aclx = $acl_count[$key]; + $aclnames = ""; + foreach($acl_x as $aclname) { + $aclnames .= " $aclname"; + } + $aclnames = trim($aclnames); + $action['action'] = 'use_backend'; + $action['use_backendbackend'] = $frontend['backend_serverpool']; + $action['acl'] = $aclnames; + $a_actions[] = $action; + $is_default = false; + } + } + if (!$is_default) { + $frontend['backend_serverpool'] = ""; + } + } + } + } + $configversion = "00.32"; + } $writeconfigupdate = $config['installedpackages']['haproxy']['configversion'] <> $configversion; if ($writeconfigupdate) { diff --git a/config/haproxy-devel/pkg/haproxy_utils.inc b/config/haproxy-devel/pkg/haproxy_utils.inc index ec72b986..04cacb30 100644 --- a/config/haproxy-devel/pkg/haproxy_utils.inc +++ b/config/haproxy-devel/pkg/haproxy_utils.inc @@ -122,11 +122,11 @@ function haproxy_get_bindable_interfaces($ipv="ipv4,ipv6", $interfacetype="any,l // $bindable[key]['description'] can be shown to user in a selection box global $config; - $ipverions = split(',',$ipv); + $ipversions = split(',',$ipv); $interfacetypes= split(',',$interfacetype); $bindable = array(); - if (in_array("ipv4",$ipverions)){ + if (in_array("ipv4",$ipversions)){ if (in_array('any',$interfacetypes)){ $item = array(); $item[ip] = '0.0.0.0'; @@ -187,7 +187,7 @@ function haproxy_get_bindable_interfaces($ipv="ipv4,ipv6", $interfacetype="any,l if (!isset($config['system']['ipv6allow'])) return $bindable;// skip adding the IPv6 addresses if those are not 'allowed' - if (in_array("ipv6",$ipverions)){ + if (in_array("ipv6",$ipversions)){ if (in_array('any',$interfacetypes)){ $item = array(); $item[ip] = '::'; @@ -386,6 +386,27 @@ function haproxy_get_certificates($type = 'server,user', $get_includeWebCert=fal return $certificates; } +function haproxy_get_certificate_subjectAltNames($str_crt, $decode = true) { + if ($decode) { + $str_crt = base64_decode($str_crt); + } + $result = array(); + $ext = openssl_x509_parse($str_crt, false); + $subjectAltName = $ext['extensions']['subjectAltName']; + $lines = explode('\n', $subjectAltName); + foreach($lines as $line) { + $items = explode(',', $line); + foreach($items as $item) { + $item = trim($item); + if (strpos($item, "DNS:") === 0) { + $DNSitem = substr($item, 4); + $result[] = $DNSitem; + } + } + } + return $result; +} + function haproxy_get_crls() { global $config; $certificates=array(); @@ -406,7 +427,8 @@ function haproxy_get_crls() { function phparray_to_javascriptarray_recursive($nestID, $path, $items, $nodeName, $includeitems) { $offset = str_repeat(' ',$nestID); $itemName = "item$nestID"; - echo "{$offset}$nodeName = {};\n"; + //echo "{$offset}$nodeName = {};\n"; + echo "{$offset}$nodeName = Object.create(null);\n"; if (is_array($items)) foreach ($items as $key => $item) { diff --git a/config/haproxy-devel/www/haproxy_files.php b/config/haproxy-devel/www/haproxy_files.php index 12ab5a88..4fe6bf45 100644 --- a/config/haproxy-devel/www/haproxy_files.php +++ b/config/haproxy-devel/www/haproxy_files.php @@ -42,15 +42,20 @@ if (!is_array($a_pools)) $a_pools = array(); $fields_files = array(); $fields_files[0]['name']="name"; $fields_files[0]['columnheader']="Name"; -$fields_files[0]['colwidth']="30%"; +$fields_files[0]['colwidth']="20%"; $fields_files[0]['type']="textbox"; $fields_files[0]['size']="20"; - -$fields_files[1]['name']="content"; -$fields_files[1]['columnheader']="content"; -$fields_files[1]['colwidth']="70%"; -$fields_files[1]['type']="textarea"; -$fields_files[1]['size']="70"; +$fields_files[1]['name']="type"; +$fields_files[1]['columnheader']="Type"; +$fields_files[1]['colwidth']="10%"; +$fields_files[1]['type']="select"; +$fields_files[1]['size']="10"; +$fields_files[1]['items']=$a_filestype; +$fields_files[2]['name']="content"; +$fields_files[2]['columnheader']="content"; +$fields_files[2]['colwidth']="70%"; +$fields_files[2]['type']="textarea"; +$fields_files[2]['size']="70"; $fileslist = new HaproxyHtmlList("table_files", $fields_files); $fileslist->keyfield = "name"; @@ -63,7 +68,7 @@ if ($_POST) { if ($result) unlink_if_exists($d_haproxyconfdirty_path); } else { - $a_files = $fileslist->haproxy_htmllist_get_values($fields_files); + $a_files = $fileslist->haproxy_htmllist_get_values(); $filedupcheck = array(); foreach($a_files as $key => $file) { @@ -77,7 +82,7 @@ if ($_POST) { // replace references in backends to renamed 'files' foreach($a_pools as &$backend) { - if (is_arrayset($backend,'errorfiles','item')) + if (is_arrayset($backend,'errorfiles','item')) { foreach($backend['errorfiles']['item'] as &$errorfile) { $found = false; foreach($a_files as $key => $file) { @@ -86,9 +91,11 @@ if ($_POST) { $found = true; } } - if (!$found) + if (!$found) { $input_errors[] = "Errorfile marked for deletion: " . $errorfile['errorfile'] . " which is used in backend " . $backend['name']; + } } + } } if (!$input_errors) { // save config when no errors found @@ -100,10 +107,9 @@ if ($_POST) { } } -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); - $pgtitle = "Services: HAProxy: Files"; include("head.inc"); +haproxy_css(); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> @@ -165,7 +171,7 @@ include("head.inc"); <script type="text/javascript"> totalrows = <?php echo $counter; ?>; <? - phparray_to_javascriptarray($fields_files,"fields_files",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + $fileslist->outputjavascript(); ?> </script> diff --git a/config/haproxy-devel/www/haproxy_global.php b/config/haproxy-devel/www/haproxy_global.php index 2ae92256..4902b966 100644 --- a/config/haproxy-devel/www/haproxy_global.php +++ b/config/haproxy-devel/www/haproxy_global.php @@ -38,12 +38,13 @@ require_once("pkg_haproxy_tabs.inc"); require_once("haproxy_htmllist.inc"); $simplefields = array('localstats_refreshtime', 'localstats_sticktable_refreshtime', 'log-send-hostname', 'ssldefaultdhparam', - 'email_level', 'email_myhostname', 'email_from', 'email_to'); + 'email_level', 'email_myhostname', 'email_from', 'email_to', + 'resolver_retries', 'resolver_timeoutretry', 'resolver_holdvalid'); $none = array(); $none['']['name'] = "Dont log"; $a_sysloglevel = $none + $a_sysloglevel; - + $fields_mailers = array(); $fields_mailers[0]['name'] = "name"; $fields_mailers[0]['columnheader'] = "Name"; @@ -61,8 +62,27 @@ $fields_mailers[2]['colwidth'] = "10%"; $fields_mailers[2]['type'] = "textbox"; $fields_mailers[2]['size'] = "10"; +$fields_resolvers = array(); +$fields_resolvers[0]['name'] = "name"; +$fields_resolvers[0]['columnheader'] = "Name"; +$fields_resolvers[0]['colwidth'] = "30%"; +$fields_resolvers[0]['type'] = "textbox"; +$fields_resolvers[0]['size'] = "20"; +$fields_resolvers[1]['name'] = "server"; +$fields_resolvers[1]['columnheader'] = "DNSserver"; +$fields_resolvers[1]['colwidth'] = "60%"; +$fields_resolvers[1]['type'] = "textbox"; +$fields_resolvers[1]['size'] = "60"; +$fields_resolvers[2]['name'] = "port"; +$fields_resolvers[2]['columnheader'] = "DNSport"; +$fields_resolvers[2]['colwidth'] = "10%"; +$fields_resolvers[2]['type'] = "textbox"; +$fields_resolvers[2]['size'] = "10"; + $mailerslist = new HaproxyHtmlList("table_mailers", $fields_mailers); $mailerslist->keyfield = "name"; +$resolverslist = new HaproxyHtmlList("table_resolvers", $fields_resolvers); +$resolverslist->keyfield = "name"; if (!is_array($config['installedpackages']['haproxy'])) $config['installedpackages']['haproxy'] = array(); @@ -82,7 +102,7 @@ if ($_POST) { unlink_if_exists($d_haproxyconfdirty_path); } else { $a_mailers = $mailerslist->haproxy_htmllist_get_values(); - $pool['ha_servers']['item'] = $a_servers; + $a_resolvers = $resolverslist->haproxy_htmllist_get_values(); if ($_POST['carpdev'] == "disabled") unset($_POST['carpdev']); @@ -99,28 +119,18 @@ if ($_POST) { if ($_POST['localstats_sticktable_refreshtime'] && (!is_numeric($_POST['localstats_sticktable_refreshtime']))) $input_errors[] = "The local stats sticktable refresh time should be numeric or empty."; - /*if($_POST['synchost1'] && !is_ipaddr($_POST['synchost1'])) - $input_errors[] = "Synchost1 needs to be an IPAddress."; - if($_POST['synchost2'] && !is_ipaddr($_POST['synchost2'])) - $input_errors[] = "Synchost2 needs to be an IPAddress."; - if($_POST['synchost3'] && !is_ipaddr($_POST['synchost3'])) - $input_errors[] = "Synchost3 needs to be an IPAddress.";*/ - if (!$input_errors) { - $config['installedpackages']['haproxy']['email_mailers']['items'] = $a_mailers; + $config['installedpackages']['haproxy']['email_mailers']['item'] = $a_mailers; + $config['installedpackages']['haproxy']['dns_resolvers']['item'] = $a_resolvers; $config['installedpackages']['haproxy']['enable'] = $_POST['enable'] ? true : false; $config['installedpackages']['haproxy']['terminate_on_reload'] = $_POST['terminate_on_reload'] ? true : false; $config['installedpackages']['haproxy']['maxconn'] = $_POST['maxconn'] ? $_POST['maxconn'] : false; $config['installedpackages']['haproxy']['enablesync'] = $_POST['enablesync'] ? true : false; - //$config['installedpackages']['haproxy']['synchost1'] = $_POST['synchost1'] ? $_POST['synchost1'] : false; - //$config['installedpackages']['haproxy']['synchost2'] = $_POST['synchost2'] ? $_POST['synchost2'] : false; - //$config['installedpackages']['haproxy']['synchost2'] = $_POST['synchost3'] ? $_POST['synchost3'] : false; $config['installedpackages']['haproxy']['remotesyslog'] = $_POST['remotesyslog'] ? $_POST['remotesyslog'] : false; $config['installedpackages']['haproxy']['logfacility'] = $_POST['logfacility'] ? $_POST['logfacility'] : false; $config['installedpackages']['haproxy']['loglevel'] = $_POST['loglevel'] ? $_POST['loglevel'] : false; $config['installedpackages']['haproxy']['carpdev'] = $_POST['carpdev'] ? $_POST['carpdev'] : false; - //$config['installedpackages']['haproxy']['syncpassword'] = $_POST['syncpassword'] ? $_POST['syncpassword'] : false; $config['installedpackages']['haproxy']['localstatsport'] = $_POST['localstatsport'] ? $_POST['localstatsport'] : false; $config['installedpackages']['haproxy']['advanced'] = $_POST['advanced'] ? base64_encode($_POST['advanced']) : false; $config['installedpackages']['haproxy']['nbproc'] = $_POST['nbproc'] ? $_POST['nbproc'] : false; @@ -132,16 +142,19 @@ if ($_POST) { } } -$a_mailers = $config['installedpackages']['haproxy']['email_mailers']['items']; +$a_mailers = $config['installedpackages']['haproxy']['email_mailers']['item']; +if (!is_array($a_mailers)) { + $a_mailers = array(); +} +$a_resolvers = $config['installedpackages']['haproxy']['dns_resolvers']['item']; +if (!is_array($a_resolvers)) { + $a_resolvers = array(); +} $pconfig['enable'] = isset($config['installedpackages']['haproxy']['enable']); $pconfig['terminate_on_reload'] = isset($config['installedpackages']['haproxy']['terminate_on_reload']); $pconfig['maxconn'] = $config['installedpackages']['haproxy']['maxconn']; $pconfig['enablesync'] = isset($config['installedpackages']['haproxy']['enablesync']); -//$pconfig['syncpassword'] = $config['installedpackages']['haproxy']['syncpassword']; -//$pconfig['synchost1'] = $config['installedpackages']['haproxy']['synchost1']; -//$pconfig['synchost2'] = $config['installedpackages']['haproxy']['synchost2']; -//$pconfig['synchost3'] = $config['installedpackages']['haproxy']['synchost3']; $pconfig['remotesyslog'] = $config['installedpackages']['haproxy']['remotesyslog']; $pconfig['logfacility'] = $config['installedpackages']['haproxy']['logfacility']; $pconfig['loglevel'] = $config['installedpackages']['haproxy']['loglevel']; @@ -158,13 +171,9 @@ if (!$pconfig['logfacility']) if (!$pconfig['loglevel']) $pconfig['loglevel'] = 'info'; -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); -if ($pf_version < 2.0) - $one_two = true; - $pgtitle = "Services: HAProxy: Settings"; include("head.inc"); - +haproxy_css(); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <script type="text/javascript" src="javascript/scriptaculous/prototype.js"></script> @@ -179,9 +188,6 @@ function enable_change(enable_change) { } //--> </script> -<?php if($one_two): ?> -<p class="pgtitle"><?=$pgtitle?></p> -<?php endif; ?> <form action="haproxy_global.php" method="post" name="iform"> <?php if ($input_errors) print_input_errors($input_errors); ?> <?php if ($savemsg) print_info_box($savemsg); ?> @@ -210,7 +216,7 @@ function enable_change(enable_change) { <tr> <td width="22%" valign="top" class="vncell">Installed version:</td> <td width="78%" class="vtable"> - <strong><?=haproxy_verion()?></strong> + <strong><?=haproxy_version()?></strong> </td> </tr> <tr> @@ -400,9 +406,55 @@ function enable_change(enable_change) { </td> </tr> <tr><td> </td></tr> - <? if (haproxy_verion() >= '1.6' ) { ?> + <? if (haproxy_version() >= '1.6-dev4' ) { ?> <tr> - <td colspan="2" valign="top" class="listtopic">Email notifications</td> + <td colspan="2" valign="top" class="listtopic">Global DNS resolvers for haproxy</td> + </tr> + <tr> + <td valign="top" class="vncell"> + DNS servers + </td> + <td class="vtable"> + Configuring DNS servers will allow haproxy to detect when a servers IP changes to a different one in 'elastic' environments without needing to be restarted. + <br/> + <? + $counter=0; + $resolverslist->Draw($a_resolvers); + ?> + </td> + </tr> + <tr> + <td valign="top" class="vncell"> + 'resolver_retries' + </td> + <td class="vtable"> + <input name="resolver_retries" type="text" <?if(isset($pconfig['resolver_retries'])) echo "value=\"{$pconfig['resolver_retries']}\"";?> size="50"/><br/> + Email address to be used as the sender of the emails. + </td> + </tr> + <tr> + <td valign="top" class="vncell"> + 'resolver_timeoutretry' + </td> + <td class="vtable"> + <input name="resolver_timeoutretry" type="text" <?if(isset($pconfig['resolver_timeoutretry'])) echo "value=\"{$pconfig['resolver_timeoutretry']}\"";?> size="50"/><br/> + Email address to be used as the sender of the emails. + </td> + </tr> + <tr> + <td valign="top" class="vncell"> + 'resolver_holdvalid' + </td> + <td class="vtable"> + <input name="resolver_holdvalid" type="text" <?if(isset($pconfig['resolver_holdvalid'])) echo "value=\"{$pconfig['resolver_holdvalid']}\"";?> size="50"/><br/> + Email address to be used as the sender of the emails. + </td> + </tr> + <tr><td> </td></tr> + <? } + if (haproxy_version() >= '1.6' ) { ?> + <tr> + <td colspan="2" valign="top" class="listtopic">Global email notifications</td> </tr> <tr> <td valign="top" class="vncell"> @@ -412,7 +464,6 @@ function enable_change(enable_change) { It is possible to send email alerts when the state of servers changes. If configured email alerts are sent to each mailer that is configured in a mailers section. Email is sent to mailers using SMTP. <br/> <? - $counter=0; $mailerslist->Draw($a_mailers); ?> </td> @@ -582,7 +633,8 @@ haproxy_htmllist_js(); <script type="text/javascript"> totalrows = <?php echo $counter; ?>; <? - phparray_to_javascriptarray($fields_mailers,"fields_mailers",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + $mailerslist->outputjavascript(); + $resolverslist->outputjavascript(); ?> function scroll_after_fade() { diff --git a/config/haproxy-devel/www/haproxy_listeners.php b/config/haproxy-devel/www/haproxy_listeners.php index db1f3ff2..c7288e7d 100644 --- a/config/haproxy-devel/www/haproxy_listeners.php +++ b/config/haproxy-devel/www/haproxy_listeners.php @@ -93,9 +93,31 @@ if ($_GET['act'] == "del") { } } +function haproxy_userlist_backend_servers($backendname) { + //used for hint title text when hovering mouse over a backend name + global $a_servermodes; + $backend_servers = ""; + $backend = get_backend($backendname); + if ($backend && is_array($backend['ha_servers']) && is_array($backend['ha_servers']['item'])){ + $servers = $backend['ha_servers']['item']; + $backend_servers = sprintf(gettext("Servers in \"%s\" pool:"), $backendname); + if (is_array($servers)){ + foreach($servers as $server){ + $srvstatus = $server['status']; + $status = $a_servermodes[$srvstatus]['sign']; + if (isset($server['forwardto']) && $server['forwardto'] != "") + $backend_servers .= "\n{$status}[{$server['forwardto']}]"; + else + $backend_servers .= "\n{$status}{$server['address']}:{$server['port']}"; + } + } + } + return $backend_servers; +} + $pgtitle = "Services: HAProxy: Frontends"; include("head.inc"); - +haproxy_css(); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> @@ -182,7 +204,7 @@ function js_callback(req) { $first = true; $last_frontend_shared = false; foreach ($a_frontend_grouped as $a_frontend) { - usort($a_frontend,'sort_sharedfrontends'); + usort($a_frontend, 'sort_sharedfrontends'); if ((count($a_frontend) > 1 || $last_frontend_shared) && !$first) { ?> <tr class="<?=$textgray?>"><td colspan="7"> </td></tr> <? } @@ -238,24 +260,6 @@ function js_callback(req) { if ($frontend['advanced']) $isadvset .= "Advanced pass thru setting used\r\n"; if ($isadvset) echo "<img src=\"$img_adv\" title=\"" . gettext("Advanced settings set") . ": {$isadvset}\" border=\"0\" />"; - - $backend_serverpool_hint = ""; - $backend_serverpool = $frontend['backend_serverpool']; - $backend = get_backend($backend_serverpool); - if ($backend && is_array($backend['ha_servers']) && is_array($backend['ha_servers']['item'])){ - $servers = $backend['ha_servers']['item']; - $backend_serverpool_hint = gettext("Servers in pool:"); - if (is_array($servers)){ - foreach($servers as $server){ - $srvstatus = $server['status']; - $status = $a_servermodes[$srvstatus]['sign']; - if (isset($server['forwardto']) && $server['forwardto'] != "") - $backend_serverpool_hint .= "\n{$status}[{$server['forwardto']}]"; - else - $backend_serverpool_hint .= "\n{$status}{$server['address']}:{$server['port']}"; - } - } - } ?> </td> <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> @@ -296,15 +300,30 @@ function js_callback(req) { ?> </td> <td class="listr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> - <div title='<?=$backend_serverpool_hint;?>'> - <a href="haproxy_pool_edit.php?id=<?=$frontend['backend_serverpool']?>"> - <?=$frontend['backend_serverpool']?> - </a> - </div> + <? + if (is_array($frontend['a_actionitems']['item'])) { + foreach ($frontend['a_actionitems']['item'] as $actionitem) { + if ($actionitem['action'] == "use_backend") { + $backend = $actionitem['use_backendbackend']; + $hint = haproxy_userlist_backend_servers($backend); + echo "<div title='{$hint}'>"; + echo "<a href='haproxy_pool_edit.php?id={$backend}'>{$backend}</a>"; + if (!empty($actionitem['acl'])) { + echo " if({$actionitem['acl']})"; + } + echo "<br/></div>"; + } + } + } + $hint = haproxy_userlist_backend_servers($frontend['backend_serverpool']); + $backend = $frontend['backend_serverpool']; + if (!empty($backend)) { + echo "<div title='{$hint}'>"; + echo "<a href='haproxy_pool_edit.php?id={$backend}'>{$backend}</a> (default)"; + echo "<br/></div>"; + } + ?> </td> - <!--td class="listlr" ondblclick="document.location='haproxy_listeners_edit.php?id=<?=$frontendname;?>';"> - <?=$frontend['secondary'] == 'yes' ? $frontend['primary_frontend'] : "";?> - </td--> <td class="list" nowrap> <table border="0" cellspacing="0" cellpadding="1"> <tr> diff --git a/config/haproxy-devel/www/haproxy_listeners_edit.php b/config/haproxy-devel/www/haproxy_listeners_edit.php index 6998e099..8e6c1c3d 100644 --- a/config/haproxy-devel/www/haproxy_listeners_edit.php +++ b/config/haproxy-devel/www/haproxy_listeners_edit.php @@ -47,17 +47,6 @@ if (!function_exists("cert_get_purpose")) { } /**/ -function haproxy_js_acl_select($mode) { - global $a_acltypes; - - $seltext = ''; - foreach ($a_acltypes as $key => $expr) { - if ($expr['mode'] == '' || $expr['mode'] == $mode) - $seltext .= "<option value='" . $key . "'>" . $expr['name'] ."<\/option>"; - } - return $seltext; -} - if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); } @@ -71,7 +60,8 @@ uasort($a_pools, haproxy_compareByName); global $simplefields; $simplefields = array('name','desc','status','secondary','primary_frontend','type','forwardfor','httpclose','extaddr','backend_serverpool', 'max_connections','client_timeout','port','advanced_bind', - 'ssloffloadcert','dcertadv','ssloffload','ssloffloadacl','ssloffloadacladditional','sslclientcert-none','sslclientcert-invalid','sslocsp', + 'ssloffloadcert','dcertadv','ssloffload','ssloffloadacl','ssloffloadacl_an','ssloffloadacladditional','ssloffloadacladditional_an', + 'sslclientcert-none','sslclientcert-invalid','sslocsp', 'socket-stats', 'dontlognull','dontlog-normal','log-separate-errors','log-detailed'); @@ -88,7 +78,7 @@ $id = get_frontend_id($id); if (!is_numeric($id)) { //default value for new items. - $pconfig['ssloffloadacl'] = "yes"; + $pconfig['ssloffloadacl_an'] = "yes"; $new_item = array(); $new_item['extaddr'] = "wan_ipv4"; $new_item['extaddr_port'] = "80"; @@ -182,12 +172,110 @@ $fields_externalAddress[4]['colwidth']="20%"; $fields_externalAddress[4]['type']="textbox"; $fields_externalAddress[4]['size']="30"; +$fields_actions=array(); +$fields_actions[0]['name']="action"; +$fields_actions[0]['columnheader']="Action"; +$fields_actions[0]['colwidth']="30%"; +$fields_actions[0]['type']="select"; +$fields_actions[0]['size']="200px"; +$fields_actions[0]['items']=&$a_action; +$fields_actions[1]['name']="parameters"; +$fields_actions[1]['columnheader']="Parameters"; +$fields_actions[1]['colwidth']="30%"; +$fields_actions[1]['type']="fixedtext"; +$fields_actions[1]['size']="200px"; +$fields_actions[1]['text']="See below"; +$fields_actions[2]['name']="acl"; +$fields_actions[2]['columnheader']="Condition acl names"; +$fields_actions[2]['colwidth']="15%"; +$fields_actions[2]['type']="textbox"; +$fields_actions[2]['size']="40"; + +$a_files = haproxy_get_fileslist(); +$fields_errorfile = array(); +$fields_errorfile[0]['name']="errorcode"; +$fields_errorfile[0]['columnheader']="errorcode(s)"; +$fields_errorfile[0]['colwidth']="15%"; +$fields_errorfile[0]['type']="textbox"; +$fields_errorfile[0]['size']="70px"; +$fields_errorfile[1]['name']="errorfile"; +$fields_errorfile[1]['columnheader']="Error Page"; +$fields_errorfile[1]['colwidth']="30%"; +$fields_errorfile[1]['type']="select"; +$fields_errorfile[1]['size']="170px"; +$fields_errorfile[1]['items']=&$a_files; + +$backends = get_haproxy_backends(); +$a_action['use_backend']['fields']['backend']['items'] = &$backends; +//$a_action['http-request_lua']['fields']['lua-script']['items'] = &$a_files; +//$a_action['tcp-request_content_lua']['fields']['lua-script']['items'] = &$a_files; + +$fields_actions_details=array(); +foreach($a_action as $key => $action) { + if (is_array($action['fields'])) { + foreach($action['fields'] as $field) { + $item = $field; + $name = $key . $item['name']; + $item['name'] = $name; + $item['columnheader'] = $field['name']; + $item['customdrawcell'] = customdrawcell_actions; + $fields_actions_details[$name] = $item; + } + } +} + +$a_acltypes["backendservercount"]['fields']['backend']['items'] = &$backends; +$fields_acl_details=array(); +foreach($a_acltypes as $key => $action) { + if (is_array($action['fields'])) { + foreach($action['fields'] as $field) { + $item = $field; + $name = $key . $item['name']; + $item['name'] = $name; + $item['columnheader'] = $field['name']; + $item['customdrawcell'] = customdrawcell_actions; + $fields_acl_details[$name] = $item; + } + } +} + +function customdrawcell_actions($object, $item, $itemvalue, $editable, $itemname, $counter) { + if ($editable) { + $object->haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter); + } else { + //TODO hide fields not applicable.?. + echo $itemvalue; + } +} + +$htmllist_extaddr = new HaproxyHtmlList("table_extaddr", $fields_externalAddress); +$htmllist_extaddr->editmode = true; + +$htmllist_acls = new HaproxyHtmlList("table_acls", $fields_aclSelectionList); +$htmllist_acls->fields_details = $fields_acl_details; +//$htmllist_acls->editmode = true; + +$htmllist_actions = new HaproxyHtmlList("table_actions", $fields_actions); +$htmllist_actions->fields_details = $fields_actions_details; +//$htmllist_actions->keyfield = "name"; +//$htmllist_actions->editmode = true; + +$htmllist_sslCertificates = new HaproxyHtmlList("tbl_sslCerts", $fields_sslCertificates); +$htmllist_caCertificates = new HaproxyHtmlList("tbl_caCerts", $fields_caCertificates ); +$htmllist_crlCertificates = new HaproxyHtmlList("tbl_crlCerts", $fields_crlCertificates); + +$errorfileslist = new HaproxyHtmlList("table_errorfile", $fields_errorfile); +$errorfileslist->keyfield = "errorcode"; + if (isset($id) && $a_backend[$id]) { $pconfig['a_acl']=&$a_backend[$id]['ha_acls']['item']; $pconfig['a_certificates']=&$a_backend[$id]['ha_certificates']['item']; $pconfig['clientcert_ca']=&$a_backend[$id]['clientcert_ca']['item']; $pconfig['clientcert_crl']=&$a_backend[$id]['clientcert_crl']['item']; $pconfig['a_extaddr']=&$a_backend[$id]['a_extaddr']['item']; + $pconfig['a_actionitems']=&$a_backend[$id]['a_actionitems']['item']; + $pconfig['a_errorfiles']=&$a_backend[$id]['a_errorfiles']['item']; + $pconfig['advanced'] = base64_decode($a_backend[$id]['advanced']); foreach($simplefields as $stat) $pconfig[$stat] = $a_backend[$id][$stat]; @@ -195,6 +283,7 @@ if (isset($id) && $a_backend[$id]) { if (isset($_GET['dup'])) { unset($id); + $pconfig['name'] .= "-copy"; if ($pconfig['secondary'] != 'yes') $pconfig['primary_frontend'] = $pconfig['name']; } @@ -243,20 +332,23 @@ if ($_POST) { if (($_POST['name'] == $config['installedpackages']['haproxy']['ha_backends']['item'][$i]['name']) && ($i != $id)) $input_errors[] = "This frontend name has already been used. Frontend names must be unique. $i != $id"; - $a_certificates = haproxy_htmllist_get_values($fields_sslCertificates); + $a_actionitems = $htmllist_actions->haproxy_htmllist_get_values(); + $pconfig['a_actionitems'] = $a_actionitems; + $a_errorfiles = $errorfileslist->haproxy_htmllist_get_values(); + $pconfig['a_errorfiles'] = $a_errorfiles; + $a_certificates = $htmllist_sslCertificates->haproxy_htmllist_get_values(); $pconfig['a_certificates'] = $a_certificates; - $a_clientcert_ca = haproxy_htmllist_get_values($fields_caCertificates); + $a_clientcert_ca = $htmllist_caCertificates->haproxy_htmllist_get_values(); $pconfig['clientcert_ca'] = $a_clientcert_ca; - $a_clientcert_crl = haproxy_htmllist_get_values($fields_crlCertificates); + $a_clientcert_crl = $htmllist_crlCertificates->haproxy_htmllist_get_values(); $pconfig['clientcert_crl'] = $a_clientcert_crl; - $a_acl = haproxy_htmllist_get_values($fields_aclSelectionList); + $a_acl = $htmllist_acls->haproxy_htmllist_get_values(); $pconfig['a_acl'] = $a_acl; - $a_extaddr = haproxy_htmllist_get_values($fields_externalAddress); + $a_extaddr = $htmllist_extaddr->haproxy_htmllist_get_values(); $pconfig['a_extaddr'] = $a_extaddr; - foreach($a_acl as $acl) { $acl_name = $acl['name']; $acl_value = $acl['value']; @@ -311,6 +403,8 @@ if ($_POST) { $backend['clientcert_ca']['item'] = $a_clientcert_ca; $backend['clientcert_crl']['item'] = $a_clientcert_crl; $backend['a_extaddr']['item'] = $a_extaddr; + $backend['a_actionitems']['item'] = $a_actionitems; + $backend['a_errorfiles']['item'] = $a_errorfiles; if (isset($id) && $a_backend[$id]) { $a_backend[$id] = $backend; @@ -328,13 +422,10 @@ if ($_POST) { } } -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); -if ($pf_version < 2.0) - $one_two = true; - $closehead = false; $pgtitle = "HAProxy: Frontend: Edit"; include("head.inc"); +haproxy_css(); if (!isset($_GET['dup'])) $excludefrontend = $pconfig['name']; @@ -353,50 +444,28 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); </head> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> -<?php if($one_two): ?> -<script type="text/javascript" src="/javascript/scriptaculous/prototype.js"></script> -<script type="text/javascript" src="/javascript/scriptaculous/scriptaculous.js"></script> -<?php endif; ?> - <script type="text/javascript"> - function htmllist_get_select_options(tableId, fieldname) { - var seltext; - seltext = ""; - var type; - var secondary = d.getElementById("secondary"); - var primary_frontend = d.getElementById("primary_frontend"); - if ((secondary !== null) && (secondary.checked)) - type = primaryfrontends[primary_frontend.value]['ref']['type']; - else - type = d.getElementById("type").value; - - if (tableId == 'tableA_acltable'){ - if (type == 'health') - seltext = "<?php echo haproxy_js_acl_select('health');?>"; - else if (type == 'tcp') - seltext = "<?php echo haproxy_js_acl_select('tcp');?>"; - else if (type == 'https') - seltext = "<?php echo haproxy_js_acl_select('https');?>"; + function htmllist_get_select_options(tableId, fieldname, itemstable) { + if (tableId == 'table_acls' && fieldname == 'expression') { + var type; + var secondary = d.getElementById("secondary"); + var primary_frontend = d.getElementById("primary_frontend"); + if ((secondary !== null) && (secondary.checked)) + type = primaryfrontends[primary_frontend.value]['ref']['type']; else - seltext = "<?php echo haproxy_js_acl_select('http');?>"; - if (seltext == '') { - alert("No ACL types available in current frontend type"); - return; + type = d.getElementById("type").value; + + result = Object.create(null); + for (var key in itemstable) { + newitem = itemstable[key]; + if (newitem['mode'] == type || newitem['mode'] == "") { + result[key] = newitem; + result[key]['name'] = result[key]['name']; + } } + return result; } - if (tableId == 'tableA_sslCertificates'){ - seltext = "<?=haproxy_js_select_options($servercerts);?>"; - } - if (tableId == 'table_clientcert_ca'){ - seltext = "<?=haproxy_js_select_options($certs_ca);?>"; - } - if (tableId == 'table_clientcert_crl'){ - seltext = "<?=haproxy_js_select_options($certs_crl);?>"; - } - if (tableId == 'table_extaddr'){ - seltext = "<?=haproxy_js_select_options($interfaces);?>"; - } - return seltext; + return itemstable; } function setCSSdisplay(cssID, display) { @@ -430,7 +499,7 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); } else { type = d.getElementById("type").value; for (i = 0; i < 99; i++) { - customEdit = document.getElementById("extaddr_ssl"+i); + customEdit = document.getElementById("table_extaddr"+"extaddr_ssl"+i); if (customEdit && customEdit.checked) sslshow = true; } @@ -462,47 +531,31 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); d = document; for (i = 0; i < 99; i++) { - el = d.getElementById("acl_expression" + i); - row = d.getElementById("aclrow" + i); - if (!el) - continue; - for (j = 0; j < count; j++) { - if (acl[j] == el.value) { - if (mode[j] != '' && mode[j] != type) { - Effect.Fade(row,{ duration: 1.0 }); - } else { - Effect.Appear(row,{ duration: 1.0 }); - } - } - } - } - - for (i = 0; i < 99; i++) { - el = d.getElementById("expression" + i); - //row_v = d.getElementById("tr_view_" + i); + el = d.getElementById("table_acls" + "expression" + i); row_e = d.getElementById("tr_edit_" + i); - if (!el) + row_v = d.getElementById("tr_viewdetail_" + i); + if (!el || !row_e) continue; for (j = 0; j < count; j++) { if (acl[j] == el.value) { if (mode[j] != '' && mode[j] != type) { - //Effect.Fade(row_v,{ duration: 1.0 }); Effect.Fade(row_e,{ duration: 1.0 }); + if (row_v) { + Effect.Fade(row_v,{ duration: 1.0 }); + } } else { - //Effect.Appear(row_v,{ duration: 1.0 }); Effect.Appear(row_e,{ duration: 1.0 }); + if (row_v) { + Effect.Appear(row_v,{ duration: 1.0 }); + } } } } } - } </script> <?php include("fbegin.inc"); ?> <?php if ($input_errors) print_input_errors($input_errors); ?> -<?php if($one_two): ?> -<p class="pgtitle"><?=$pgtitle?></p> -<?php endif; ?> <form action="haproxy_listeners_edit.php" method="post" name="iform" id="iform"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td class="tabnavtbl"> @@ -566,21 +619,19 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); <? $counter=0; $a_extaddr = $pconfig['a_extaddr']; - $htmllist_extadd = new HaproxyHtmlList("table_extaddr", $fields_externalAddress); - $htmllist_extadd->editmode = true; - $htmllist_extadd->Draw($a_extaddr); + $htmllist_extaddr->Draw($a_extaddr); ?> <script type="text/javascript"> - function table_extaddr_row_added(tableid, rowid){ - new AutoSuggestControl(document.getElementById("extaddr_custom"+rowid), new StateSuggestions(address_array)); - new AutoSuggestControl(document.getElementById("extaddr_port"+rowid), new StateSuggestions(port_array)); - table_extaddr_listitem_change(tableid,"",rowid, null);//disables address when not set to custom. + function table_extaddr_row_added(tableId, rowId){ + new AutoSuggestControl(document.getElementById(tableId+"extaddr_custom"+rowId), new StateSuggestions(address_array)); + new AutoSuggestControl(document.getElementById(tableId+"extaddr_port"+rowId), new StateSuggestions(port_array)); + table_extaddr_listitem_change(tableId,"",rowId, null);//disables address when not set to custom. } function table_extaddr_listitem_change(tableId, fieldId, rowNr, field) { if (fieldId == "extaddr" || fieldId == "") { - field = field || document.getElementById("extaddr"+rowNr); - customEdit = document.getElementById("extaddr_custom"+rowNr); + field = field || document.getElementById(tableId+"extaddr"+rowNr); + customEdit = document.getElementById(tableId+"extaddr_custom"+rowNr); customdisabled = field.value == "custom" ? 0 : 1; customEdit.disabled = customdisabled; } @@ -607,23 +658,6 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); <input name="max_connections" type="text" <?if(isset($pconfig['max_connections'])) echo "value=\"{$pconfig['max_connections']}\"";?> size="10" maxlength="10" /> </td> </tr> - <tr> - <td width="22%" valign="top" class="vncellreq">Backend server pool</td> - <td width="78%" class="vtable"> - - <select id="backend_serverpool" name="backend_serverpool" class="formfld"> - <?php - if (is_array($a_pools)) { - foreach ($a_pools as $p) { - $selected = $p['name'] == $pconfig['backend_serverpool'] ? 'selected' : ''; - $name = htmlspecialchars("{$p['name']}"); - echo "<option value=\"{$p['name']}\" $selected>$name</option>"; - } - } else { - echo "<option value=\"-\">-</option>"; - } - ?> - </select> <tr class="haproxy_primary" align="left"> <td width="22%" valign="top" class="vncellreq">Type</td> <td width="78%" class="vtable" colspan="2"> @@ -644,11 +678,74 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); <td width="78%" class="vtable" colspan="2" valign="top"> <? $a_acl = $pconfig['a_acl']; - haproxy_htmllist("tableA_acltable", $a_acl, $fields_aclSelectionList, true); + $htmllist_acls->Draw($a_acl); ?> <br/> - acl's with the same name wil be 'combined', acl's with different names will be evaluated seperately.<br/> - For more information about ACL's please see <a href='http://haproxy.1wt.eu/download/1.5/doc/configuration.txt' target='_blank'>HAProxy Documentation</a> Section 7 - Using ACL's + Example: + <table border='1' style='border-collapse:collapse'> + <tr> + <td><b>Name</b></td> + <td><b>Expression</b></td> + <td><b>Not</b></td> + <td><b>Value</b></td> + </tr> + <tr> + <td>Backend1acl</td> + <td>Host matches</td> + <td></td> + <td>www.yourdomain.tld</td> + </tr> + <tr> + <td>addHeaderAcl</td> + <td>SSL Client certificate valid</td> + <td></td> + <td></td> + </tr> + </table> + <br/> + acl's with the same name will be 'combined' using OR criteria.<br/> + For more information about ACL's please see <a href='http://haproxy.1wt.eu/download/1.5/doc/configuration.txt' target='_blank'>HAProxy Documentation</a> Section 7 - Using ACL's<br/><br/> + <strong>NOTE Important change in behaviour, since package version 0.32</strong><br/> + -acl's are no longer combined with logical AND operators, list multiple acl's below where needed.<br/> + -acl's alone no longer implicitly generate use_backend configuration. Add 'actions' below to accomplish this behaviour. + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncellreq">Actions</td> + <td width="78%" class="vtable" colspan="2" valign="top"> + <? + $a_actionitems = $pconfig['a_actionitems']; + $htmllist_actions->Draw($a_actionitems); + ?> + <br/> + Example: + <table border='1' style='border-collapse:collapse'> + <tr> + <td><b>Action</b></td> + <td><b>Parameters</b></td> + <td><b>Condition</b></td> + </tr> + <tr> + <td>Use Backend</td> + <td>Website1Backend</td> + <td>Backend1acl</td> + </tr> + <tr> + <td>http-request header set</td> + <td>Headername: X-HEADER-ClientCertValid<br/>New logformat value: YES</td> + <td>addHeaderAcl</td> + </tr> + </table> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncellreq">Default Backend</td> + <td width="78%" class="vtable"> + <?php + $listitem_none['']['name']="None"; + $backends = $listitem_none + $backends; + echo_html_select("backend_serverpool", $backends, $pconfig['backend_serverpool'] ? $pconfig['backend_serverpool'] : "none", "", "updatevisibility();"); + ?> </td> </tr> <tr class="haproxy_primary"><td> </td></tr> @@ -704,6 +801,23 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); address and ports. In http mode also the HTTP request and captured headers and cookies will be logged.</div> </td> </tr> + <tr><td> </td></tr> + <tr> + <td colspan="2" valign="top" class="listtopic">Error files</td> + </tr> + <tr class="" align="left" id='errorfiles'> + <td colspan="2" valign="top" class="vtable"> + Use these to replace the error pages that haproxy can generate by custom pages created on the files tab. + For example haproxy will generate a 503 error page when no backend is available, you can replace that page here. + <br/> + <br/> + <? + $a_errorfiles = $pconfig['a_errorfiles']; + $errorfileslist->Draw($a_errorfiles); + ?> + </td> + </tr> + <tr><td> </td></tr> </table> <br/> <br/> <table class="haproxy_primary" width="100%" border="0" cellpadding="6" cellspacing="0"> @@ -785,6 +899,7 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); Choose the cert to use on this frontend. <br/> <input id="ssloffloadacl" name="ssloffloadacl" type="checkbox" value="yes" <?php if ($pconfig['ssloffloadacl']=='yes') echo "checked";?> onclick="updatevisibility();" />Add ACL for certificate CommonName. (host header matches the 'CN' of the certificate)<br/> + <input id="ssloffloadacl_an" name="ssloffloadacl_an" type="checkbox" value="yes" <?php if ($pconfig['ssloffloadacl_an']=='yes') echo "checked";?> onclick="updatevisibility();" />Add ACL for certificate Subject Alternative Names.<br/> </td> </tr> <tr class="haproxy_ssloffloading_enabled" align="left"> @@ -799,10 +914,12 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); Which of these certificate will be send will be determined by haproxys SNI recognition. If the browser does not send SNI this will not work properly. (IE on XP is one example, possibly also older browsers or mobile devices) <? $a_certificates = $pconfig['a_certificates']; - haproxy_htmllist("tableA_sslCertificates", $a_certificates, $fields_sslCertificates); + //haproxy_htmllist("tableA_sslCertificates", $a_certificates, $fields_sslCertificates); + $htmllist_sslCertificates->Draw($a_certificates); ?> <br/> <input id="ssloffloadacladditional" name="ssloffloadacladditional" type="checkbox" value="yes" <?php if ($pconfig['ssloffloadacladditional']=='yes') echo "checked";?> onclick="updatevisibility();" />Add ACL for certificate CommonName. (host header matches the 'CN' of the certificate)<br/> + <input id="ssloffloadacladditional_an" name="ssloffloadacladditional_an" type="checkbox" value="yes" <?php if ($pconfig['ssloffloadacladditional_an']=='yes') echo "checked";?> onclick="updatevisibility();" />Add ACL for certificate Subject Alternative Names.<br/> </td> </tr> <tr class="haproxy_ssloffloading_enabled haproxy_primary" align="left"> @@ -843,7 +960,7 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); Client certificate will be verified against these CA certificates. <? $a_certificates = $pconfig['clientcert_ca']; - haproxy_htmllist("table_clientcert_ca", $a_certificates, $fields_caCertificates); + $htmllist_caCertificates->Draw($a_certificates); ?> </td> </tr> @@ -853,7 +970,7 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); Client certificate will be verified against these CRL revocation lists. <? $a_certificates = $pconfig['clientcert_crl']; - haproxy_htmllist("table_clientcert_crl", $a_certificates, $fields_crlCertificates); + $htmllist_crlCertificates->Draw($a_certificates); ?> </td> </tr> @@ -883,15 +1000,26 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); <br/> <script type="text/javascript"> <? + // On gui descriptions when a closetype has been selected.. + phparray_to_javascriptarray($a_closetypes, "closetypes", Array('/*', '/*/name', '/*/descr')); + + // To find 'type' of frontend to show proper acl's ?? phparray_to_javascriptarray($primaryfrontends,"primaryfrontends",Array('/*', - '/*/name','/*/ref','/*/ref/type','/*/ref/a_extaddr','/*/ref/a_extaddr/item','/*/ref/a_extaddr/item/*', + '/*/name', '/*/ref', '/*/ref/type', '/*/ref/a_extaddr', '/*/ref/a_extaddr/item', '/*/ref/a_extaddr/item/*', '/*/ref/a_extaddr/item/*/extaddr_ssl')); - phparray_to_javascriptarray($a_closetypes,"closetypes",Array('/*','/*/name','/*/descr')); - phparray_to_javascriptarray($fields_sslCertificates,"fields_sslCertificates",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); - phparray_to_javascriptarray($fields_caCertificates,"fields_ca",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); - phparray_to_javascriptarray($fields_crlCertificates,"fields_crl",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); - phparray_to_javascriptarray($fields_aclSelectionList,"fields_acltable",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); - phparray_to_javascriptarray($fields_externalAddress,"fields_extaddr",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); + + phparray_to_javascriptarray($a_action, "showhide_actionfields", + Array('/*', '/*/fields', '/*/fields/*', '/*/fields/*/name')); + phparray_to_javascriptarray($a_acltypes, "showhide_aclfields", + Array('/*', '/*/fields', '/*/fields/*', '/*/fields/*/name')); + + $htmllist_extaddr->outputjavascript(); + $htmllist_acls->outputjavascript(); + $htmllist_actions->outputjavascript(); + $errorfileslist->outputjavascript(); + $htmllist_sslCertificates->outputjavascript(); + $htmllist_caCertificates->outputjavascript(); + $htmllist_crlCertificates->outputjavascript(); ?> </script> <script type="text/javascript"> @@ -902,12 +1030,64 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); for(i=0;i < <?=count($a_extaddr)?>;i++){ - new AutoSuggestControl(document.getElementById('extaddr_custom'+i), new StateSuggestions(address_array)); - new AutoSuggestControl(document.getElementById('extaddr_port'+i), new StateSuggestions(port_array)); + new AutoSuggestControl(document.getElementById('table_extaddrextaddr_custom'+i), new StateSuggestions(address_array)); + new AutoSuggestControl(document.getElementById('table_extaddrextaddr_port'+i), new StateSuggestions(port_array)); // Initially set fields disabled where needed table_extaddr_listitem_change('table_extaddr','',i,null); } + function table_acls_listitem_change(tableId, fieldId, rowNr, field) { + if (fieldId = "toggle_details") { + fieldId = "expression"; + field = d.getElementById(tableId+"expression"+rowNr); + } + if (fieldId = "expression") { + var actiontype = field.value; + + var table = d.getElementById(tableId); + + for(var actionkey in showhide_aclfields) { + var fields = showhide_aclfields[actionkey]['fields']; + for(var fieldkey in fields){ + var fieldname = fields[fieldkey]['name']; + var rowid = "tr_edititemdetails_"+rowNr+"_"+actionkey+fieldname; + var element = d.getElementById(rowid); + + if (actionkey == actiontype) + element.style.display = ''; + else + element.style.display = 'none'; + } + } + } + } + + function table_actions_listitem_change(tableId, fieldId, rowNr, field) { + if (fieldId = "toggle_details") { + fieldId = "action"; + field = d.getElementById(tableId+"action"+rowNr); + } + if (fieldId = "action") { + var actiontype = field.value; + + var table = d.getElementById(tableId); + + for(var actionkey in showhide_actionfields) { + var fields = showhide_actionfields[actionkey]['fields']; + for(var fieldkey in fields){ + var fieldname = fields[fieldkey]['name']; + var rowid = "tr_edititemdetails_"+rowNr+"_"+actionkey+fieldname; + var element = d.getElementById(rowid); + + if (actionkey == actiontype) + element.style.display = ''; + else + element.style.display = 'none'; + } + } + } + } + updatevisibility(); </script> <?php diff --git a/config/haproxy-devel/www/haproxy_pool_edit.php b/config/haproxy-devel/www/haproxy_pool_edit.php index 6cd78741..2b4787f3 100644 --- a/config/haproxy-devel/www/haproxy_pool_edit.php +++ b/config/haproxy-devel/www/haproxy_pool_edit.php @@ -48,7 +48,7 @@ if (isset($_POST['id'])) $id = $_POST['id']; else $id = $_GET['id']; - + $tmp = get_backend_id($id); if (is_numeric($tmp)) $id = $tmp; @@ -58,7 +58,9 @@ if (isset($_GET['dup'])) global $simplefields; $simplefields = array( -"name","balance","transparent_clientip","transparent_interface", +"name", +"balance","balance_urilen","balance_uridepth","balance_uriwhole", +"transparent_clientip","transparent_interface", "check_type","checkinter","log-health-checks","httpcheck_method","monitor_uri","monitor_httpversion","monitor_username","monitor_domain","monitor_agentport", "agent_check","agent_port","agent_inter", "connection_timeout","server_timeout","retries", @@ -194,21 +196,137 @@ $fields_errorfile[1]['type']="select"; $fields_errorfile[1]['size']="170px"; $fields_errorfile[1]['items']=&$a_files; +$serverslist = new HaproxyHtmlList("tableA_servers", $fields_servers); +$serverslist->keyfield = "name"; +$serverslist->fields_details = $fields_servers_details; + +$errorfileslist = new HaproxyHtmlList("table_errorfile", $fields_errorfile); +$errorfileslist->keyfield = "errorcode"; + + + +$fields_aclSelectionList=array(); +$fields_aclSelectionList[0]['name']="name"; +$fields_aclSelectionList[0]['columnheader']="Name"; +$fields_aclSelectionList[0]['colwidth']="30%"; +$fields_aclSelectionList[0]['type']="textbox"; +$fields_aclSelectionList[0]['size']="20"; + +$fields_aclSelectionList[1]['name']="expression"; +$fields_aclSelectionList[1]['columnheader']="Expression"; +$fields_aclSelectionList[1]['colwidth']="30%"; +$fields_aclSelectionList[1]['type']="select"; +$fields_aclSelectionList[1]['size']="10"; +$fields_aclSelectionList[1]['items']=&$a_acltypes; + +$fields_aclSelectionList[2]['name']="not"; +$fields_aclSelectionList[2]['columnheader']="Not"; +$fields_aclSelectionList[2]['colwidth']="5%"; +$fields_aclSelectionList[2]['type']="checkbox"; +$fields_aclSelectionList[2]['size']="5"; + +$fields_aclSelectionList[3]['name']="value"; +$fields_aclSelectionList[3]['columnheader']="Value"; +$fields_aclSelectionList[3]['colwidth']="35%"; +$fields_aclSelectionList[3]['type']="textbox"; +$fields_aclSelectionList[3]['size']="35"; + +$fields_actions=array(); +$fields_actions[0]['name']="action"; +$fields_actions[0]['columnheader']="Action"; +$fields_actions[0]['colwidth']="30%"; +$fields_actions[0]['type']="select"; +$fields_actions[0]['size']="200px"; +$fields_actions[0]['items']=&$a_action; +$fields_actions[1]['name']="parameters"; +$fields_actions[1]['columnheader']="Parameters"; +$fields_actions[1]['colwidth']="30%"; +$fields_actions[1]['type']="fixedtext"; +$fields_actions[1]['size']="200px"; +$fields_actions[1]['text']="See below"; +$fields_actions[2]['name']="acl"; +$fields_actions[2]['columnheader']="Condition acl names"; +$fields_actions[2]['colwidth']="15%"; +$fields_actions[2]['type']="textbox"; +$fields_actions[2]['size']="40"; + + +$fields_actions_details=array(); +foreach($a_action as $key => $action) { + if (is_array($action['fields'])) { + foreach($action['fields'] as $field) { + $item = $field; + $name = $key . $item['name']; + $item['name'] = $name; + $item['columnheader'] = $field['name']; + $item['customdrawcell'] = customdrawcell_actions; + $fields_actions_details[$name] = $item; + } + } +} + +$a_acltypes["backendservercount"]['fields']['backend']['items'] = &$backends; +$fields_acl_details=array(); +foreach($a_acltypes as $key => $action) { + if (is_array($action['fields'])) { + foreach($action['fields'] as $field) { + $item = $field; + $name = $key . $item['name']; + $item['name'] = $name; + $item['columnheader'] = $field['name']; + $item['customdrawcell'] = customdrawcell_actions; + $fields_acl_details[$name] = $item; + } + } +} + +function customdrawcell_actions($object, $item, $itemvalue, $editable, $itemname, $counter) { + if ($editable) { + $object->haproxy_htmllist_drawcell($item, $itemvalue, $editable, $itemname, $counter); + } else { + //TODO hide fields not applicable.?. + echo $itemvalue; + } +} + +$htmllist_acls = new HaproxyHtmlList("table_acls", $fields_aclSelectionList); +$htmllist_acls->fields_details = $fields_acl_details; +$htmllist_acls->editmode = true; + +$htmllist_actions = new HaproxyHtmlList("table_actions", $fields_actions); +$htmllist_actions->fields_details = $fields_actions_details; +$htmllist_actions->keyfield = "name"; + + if (isset($id) && $a_pools[$id]) { + $pconfig['a_acl'] = &$a_pools[$id]['a_acl']['item']; + if (!is_array($pconfig['a_acl'])) { + $pconfig['a_acl'] = array(); + } + $pconfig['a_actionitems'] = &$a_pools[$id]['a_actionitems']['item']; + if (!is_array($pconfig['a_actionitems'])) { + $pconfig['a_actionitems'] = array(); + } $pconfig['advanced'] = base64_decode($a_pools[$id]['advanced']); $pconfig['advanced_backend'] = base64_decode($a_pools[$id]['advanced_backend']); - $pconfig['a_servers']=&$a_pools[$id]['ha_servers']['item']; + + + $a_servers = &$a_pools[$id]['ha_servers']['item']; foreach($simplefields as $stat) $pconfig[$stat] = $a_pools[$id][$stat]; + $a_errorfiles = &$a_pools[$id]['errorfiles']['item']; - if (!is_array($a_errorfiles)) $a_errorfiles = array(); + if (!is_array($a_errorfiles)) { + $a_errorfiles = array(); + } } -if (isset($_GET['dup'])) +if (isset($_GET['dup'])) { unset($id); - + $pconfig['name'] .= "-copy"; +} $changedesc = "Services: HAProxy: Backend server pool: "; $changecount = 0; @@ -265,7 +383,9 @@ if ($_POST) { if (($_POST['name'] == $config['installedpackages']['haproxy']['ha_pools']['item'][$i]['name']) && ($i != $id)) $input_errors[] = "This pool name has already been used. Pool names must be unique."; - $a_servers = haproxy_htmllist_get_values(array_merge($fields_servers,$fields_servers_details)); + $pconfig['a_acl'] = $htmllist_acls->haproxy_htmllist_get_values(); + $pconfig['a_actionitems'] = $htmllist_actions->haproxy_htmllist_get_values(); + $a_servers = $serverslist->haproxy_htmllist_get_values(); foreach($a_servers as $server){ $server_name = $server['name']; $server_address = $server['address']; @@ -294,66 +414,75 @@ if ($_POST) { $input_errors[] = "The field 'Port' value is not a number."; } - $a_errorfiles = haproxy_htmllist_get_values($fields_errorfile); + $a_errorfiles = $errorfileslist->haproxy_htmllist_get_values(); if ($_POST['strict_transport_security'] !== "" && !is_numeric($_POST['strict_transport_security'])) $input_errors[] = "The field 'Strict-Transport-Security' is not empty or a number."; -// if (!$input_errors) { - $pool = array(); - if(isset($id) && $a_pools[$id]) - $pool = $a_pools[$id]; - - if ($pool['name'] != $_POST['name']) { - // name changed: - if (!is_array($config['installedpackages']['haproxy']['ha_backends']['item'])) { - $config['installedpackages']['haproxy']['ha_backends']['item'] = array(); - } - $a_backend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + $pool = array(); + if(isset($id) && $a_pools[$id]) + $pool = $a_pools[$id]; + + if (!empty($pool['name']) && ($pool['name'] != $_POST['name'])) { + //old $pool['name'] can be empty if a new or cloned item is saved, nothing should be renamed then + // name changed: + $oldvalue = $pool['name']; + $newvalue = $_POST['name']; + + $a_backend = &$config['installedpackages']['haproxy']['ha_backends']['item']; + if (!is_array($a_backend)) { + $a_backend = array(); + } - for ( $i = 0; $i < count($a_backend); $i++) { - if ($a_backend[$i]['backend_serverpool'] == $pool['name']) - $a_backend[$i]['backend_serverpool'] = $_POST['name']; + for ( $i = 0; $i < count($a_backend); $i++) { + $backend = &$a_backend[$i]; + if ($a_backend[$i]['backend_serverpool'] == $oldvalue) { + $a_backend[$i]['backend_serverpool'] = $newvalue; + } + if (is_array($backend['a_actionitems']['item'])) { + foreach($backend['a_actionitems']['item'] as &$item) { + if ($item['action'] == "use_backend") { + if ($item['use_backendbackend'] == $oldvalue) { + $item['use_backendbackend'] = $newvalue; + } + } + } } } + } - if($pool['name'] != "") - $changedesc .= " modified pool: '{$pool['name']}'"; + if($pool['name'] != "") + $changedesc .= " modified pool: '{$pool['name']}'"; + $pool['ha_servers']['item'] = $a_servers; + $pool['a_acl']['item'] = $pconfig['a_acl']; + $pool['a_actionitems']['item'] = $pconfig['a_actionitems']; - $pool['ha_servers']['item']=$a_servers; + update_if_changed("advanced", $pool['advanced'], base64_encode($_POST['advanced'])); + update_if_changed("advanced_backend", $pool['advanced_backend'], base64_encode($_POST['advanced_backend'])); - update_if_changed("advanced", $pool['advanced'], base64_encode($_POST['advanced'])); - update_if_changed("advanced_backend", $pool['advanced_backend'], base64_encode($_POST['advanced_backend'])); + global $simplefields; + foreach($simplefields as $stat) + update_if_changed($stat, $pool[$stat], $_POST[$stat]); - global $simplefields; - foreach($simplefields as $stat) - update_if_changed($stat, $pool[$stat], $_POST[$stat]); - - if (isset($id) && $a_pools[$id]) { - $a_pools[$id] = $pool; - } else { - $a_pools[] = $pool; - } + if (isset($id) && $a_pools[$id]) { + $a_pools[$id] = $pool; + } else { + $a_pools[] = $pool; + } if (!isset($input_errors)) { if ($changecount > 0) { touch($d_haproxyconfdirty_path); - write_config($changedesc); - /* - echo "<PRE>"; - print_r($config); - echo "</PRE>"; - */ + write_config($changedesc); } - header("Location: haproxy_pools.php"); exit; } - $pconfig['a_servers']=&$a_pools[$id]['ha_servers']['item']; } $closehead = false; $pgtitle = "HAProxy: Backend server pool: Edit"; include("head.inc"); +haproxy_css(); // 'processing' done, make all simple fields usable in html. foreach($simplefields as $field){ @@ -379,16 +508,6 @@ foreach($simplefields as $field){ </head> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <script type="text/javascript"> - function htmllist_get_select_options(tableId, fieldname) { - if (fieldname == 'forwardto') - return "<?=haproxy_js_select_options($primaryfrontends);?>"; - else - if (fieldname == 'errorfile') - return "<?=haproxy_js_select_options($a_files);?>"; - else - return "<?=haproxy_js_select_options($a_servermodes);?>"; - } - function clearcombo(){ for (var i=document.iform.serversSelect.options.length-1; i>=0; i--){ document.iform.serversSelect.options[i] = null; @@ -498,8 +617,7 @@ foreach($simplefields as $field){ </span> <? $counter=0; - $a_servers = $pconfig['a_servers']; - haproxy_htmllist("tableA_servers", $a_servers, $fields_servers, null, $fields_servers_details); + $serverslist->Draw($a_servers); ?> <table class="haproxy_help_serverlist" style="border:1px dashed green" cellspacing="0"> <tr><td class="vncell"> @@ -528,66 +646,104 @@ foreach($simplefields as $field){ <tr align="left"> <td width="22%" valign="top" class="vncellreq">Balance</td> <td width="78%" class="vtable" colspan="1"> - <table width="100%"> + <table width="100%" cellspacing="0"> <tr> - <td width="25%" valign="top"> + <td class="vncell" width="25%" valign="top"> + <input type="radio" name="balance" value=""<?php if(empty($pconfig['balance'])) echo " CHECKED"; ?> />None + </td> + <td class="vncell"> + This allows writing your own custom balance settings into the advanced section. + Or when you have no need for balancing with only 1 server. + </td> + </tr> + <tr> + <td class="vncell" width="25%" valign="top"> <input type="radio" name="balance" value="roundrobin"<?php if($pconfig['balance'] == "roundrobin") echo " CHECKED"; ?> />Round robin </td> - <td> - Each server is used in turns, according to their weights. - This is the smoothest and fairest algorithm when the server's - processing time remains equally distributed. This algorithm - is dynamic, which means that server weights may be adjusted - on the fly for slow starts for instance. + <td class="vncell"> + Each server is used in turns, according to their weights. + This is the smoothest and fairest algorithm when the server's + processing time remains equally distributed. This algorithm + is dynamic, which means that server weights may be adjusted + on the fly for slow starts for instance. </td> </tr> <tr> - <td width="25%" valign="top"> + <td class="vncell" width="25%" valign="top"> <input type="radio" name="balance" value="static-rr"<?php if($pconfig['balance'] == "static-rr") echo " CHECKED"; ?> />Static Round Robin </td> - <td> + <td class="vncell"> Each server is used in turns, according to their weights. - This algorithm is as similar to roundrobin except that it is - static, which means that changing a server's weight on the - fly will have no effect. On the other hand, it has no design - limitation on the number of servers, and when a server goes - up, it is always immediately reintroduced into the farm, once - the full map is recomputed. It also uses slightly less CPU to - run (around -1%). + This algorithm is as similar to roundrobin except that it is + static, which means that changing a server's weight on the + fly will have no effect. On the other hand, it has no design + limitation on the number of servers, and when a server goes + up, it is always immediately reintroduced into the farm, once + the full map is recomputed. It also uses slightly less CPU to + run (around -1%). </td> </tr> <tr> - <td width="25%" valign="top"> + <td class="vncell" width="25%" valign="top"> <input type="radio" name="balance" value="leastconn"<?php if($pconfig['balance'] == "leastconn") echo " CHECKED"; ?> />Least Connections </td> - <td> - The server with the lowest number of connections receives the - connection. Round-robin is performed within groups of servers - of the same load to ensure that all servers will be used. Use - of this algorithm is recommended where very long sessions are - expected, such as LDAP, SQL, TSE, etc... but is not very well - suited for protocols using short sessions such as HTTP. This - algorithm is dynamic, which means that server weights may be - adjusted on the fly for slow starts for instance. + <td class="vncell"> + The server with the lowest number of connections receives the + connection. Round-robin is performed within groups of servers + of the same load to ensure that all servers will be used. Use + of this algorithm is recommended where very long sessions are + expected, such as LDAP, SQL, TSE, etc... but is not very well + suited for protocols using short sessions such as HTTP. This + algorithm is dynamic, which means that server weights may be + adjusted on the fly for slow starts for instance. </td> </tr> - <tr><td valign="top"><input type="radio" name="balance" value="source"<?php if($pconfig['balance'] == "source") echo " CHECKED"; ?> />Source - </td> - <td> - The source IP address is hashed and divided by the total - weight of the running servers to designate which server will - receive the request. This ensures that the same client IP - address will always reach the same server as long as no - server goes down or up. If the hash result changes due to the - number of running servers changing, many clients will be - directed to a different server. This algorithm is generally - used in TCP mode where no cookie may be inserted. It may also - be used on the Internet to provide a best-effort stickyness - to clients which refuse session cookies. This algorithm is - static, which means that changing a server's weight on the - fly will have no effect. + <tr> + <td class="vncell" valign="top"> + <input type="radio" name="balance" value="source"<?php if($pconfig['balance'] == "source") echo " CHECKED"; ?> />Source + </td> + <td class="vncell"> + The source IP address is hashed and divided by the total + weight of the running servers to designate which server will + receive the request. This ensures that the same client IP + address will always reach the same server as long as no + server goes down or up. If the hash result changes due to the + number of running servers changing, many clients will be + directed to a different server. This algorithm is generally + used in TCP mode where no cookie may be inserted. It may also + be used on the Internet to provide a best-effort stickyness + to clients which refuse session cookies. This algorithm is + static, which means that changing a server's weight on the + fly will have no effect. + </td> + </tr> + <tr> + <td class="vncell" valign="top"> + <input type="radio" name="balance" value="uri"<?php if($pconfig['balance'] == "uri") echo " CHECKED"; ?> />Uri (HTTP backends only) + </td> + <td class="vncell"> + This algorithm hashes either the left part of the URI (before + the question mark) or the whole URI (if the "whole" parameter + is present) and divides the hash value by the total weight of + the running servers. The result designates which server will + receive the request. This ensures that the same URI will + always be directed to the same server as long as no server + goes up or down. This is used with proxy caches and + anti-virus proxies in order to maximize the cache hit rate. + Note that this algorithm may only be used in an HTTP backend.<br/> + <input name="balance_urilen" size="10" value="<?=$pconfig['balance_urilen']?>" />Len (optional) <br/> + The "len" parameter + indicates that the algorithm should only consider that many + characters at the beginning of the URI to compute the hash.<br/> + <input name="balance_uridepth" size="10" value="<?=$pconfig['balance_uridepth']?>" />Depth (optional) <br/> + The "depth" parameter indicates the maximum directory depth + to be used to compute the hash. One level is counted for each + slash in the request.<br/> + <input id="balance_uriwhole" name="balance_uriwhole" type="checkbox" value="yes" <?php if ($pconfig['balance_uriwhole']=='yes') echo "checked"; ?> /> + Allow using whole URI including url parameters behind a question mark. </td> </tr> + <!-- TODO add some other balance methods --> </table> </td> </tr> @@ -636,6 +792,71 @@ foreach($simplefields as $field){ <br/> NOTE: paste text into this box that you would like to pass thru. Applied to the backend section. </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell">Access Control lists</td> + <td width="78%" class="vtable" colspan="2" valign="top"> + <? + $a_acl = $pconfig['a_acl']; + $htmllist_acls->Draw($a_acl); + ?> + <br/> + Example: + <table border='1' style='border-collapse:collapse'> + <tr> + <td><b>Name</b></td> + <td><b>Expression</b></td> + <td><b>Not</b></td> + <td><b>Value</b></td> + </tr> + <tr> + <td>Backend1acl</td> + <td>Host matches</td> + <td></td> + <td>www.yourdomain.tld</td> + </tr> + <tr> + <td>addHeaderAcl</td> + <td>SSL Client certificate valid</td> + <td></td> + <td></td> + </tr> + </table> + <br/> + acl's with the same name will be 'combined' using OR criteria.<br/> + For more information about ACL's please see <a href='http://haproxy.1wt.eu/download/1.5/doc/configuration.txt' target='_blank'>HAProxy Documentation</a> Section 7 - Using ACL's<br/><br/> + <strong>NOTE Important change in behaviour, since package version 0.32</strong><br/> + -acl's are no longer combined with logical AND operators, list multiple acl's below where needed.<br/> + -acl's alone no longer implicitly generate use_backend configuration. Add 'actions' below to accomplish this behaviour. + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncellreq">Actions</td> + <td width="78%" class="vtable" colspan="2" valign="top"> + <? + $a_actionitems = $pconfig['a_actionitems']; + $htmllist_actions->Draw($a_actionitems); + ?> + <br/> + Example: + <table border='1' style='border-collapse:collapse'> + <tr> + <td><b>Action</b></td> + <td><b>Parameters</b></td> + <td><b>Condition</b></td> + </tr> + <tr> + <td>Use Backend</td> + <td>Website1Backend</td> + <td>Backend1acl</td> + </tr> + <tr> + <td>http-request header set</td> + <td>Headername: X-HEADER-ClientCertValid<br/>New logformat value: YES</td> + <td>addHeaderAcl</td> + </tr> + </table> + </td> </tr> <tr><td> </td></tr> <tr> @@ -868,7 +1089,7 @@ set by the 'retries' parameter.</div> </td> </tr> <tr><td> </td></tr> - <? if (haproxy_verion() >= '1.6' ) { ?> + <? if (haproxy_version() >= '1.6' ) { ?> <tr> <td colspan="2" valign="top" class="listtopic">Email notifications</td> </tr> @@ -985,7 +1206,7 @@ set by the 'retries' parameter.</div> <br/> <br/> <? - haproxy_htmllist("table_errorfile", $a_errorfiles, $fields_errorfile); + $errorfileslist->Draw($a_errorfiles); ?> </td> </tr> @@ -1030,17 +1251,78 @@ set by the 'retries' parameter.</div> <br/> <script type="text/javascript"> <? - phparray_to_javascriptarray($fields_servers,"fields_servers",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); phparray_to_javascriptarray($fields_servers_details,"fields_details_servers",Array('/*','/*/name','/*/type')); - phparray_to_javascriptarray($fields_errorfile,"fields_errorfile",Array('/*','/*/name','/*/type','/*/size','/*/items','/*/items/*','/*/items/*/*','/*/items/*/*/name')); phparray_to_javascriptarray($a_checktypes,"checktypes",Array('/*','/*/name','/*/descr')); phparray_to_javascriptarray($a_cookiemode,"cookiemode",Array('/*','/*/name','/*/descr')); phparray_to_javascriptarray($a_sticky_type,"sticky_type",Array('/*','/*/descr','/*/cookiedescr')); - phparray_to_javascriptarray($a_files,"a_files",Array('/*','/*/name','/*/descr')); + //phparray_to_javascriptarray($a_files,"a_files",Array('/*','/*/name','/*/descr')); + + phparray_to_javascriptarray($a_action, "showhide_actionfields", + Array('/*', '/*/fields', '/*/fields/*', '/*/fields/*/name')); + phparray_to_javascriptarray($a_acltypes, "showhide_aclfields", + Array('/*', '/*/fields', '/*/fields/*', '/*/fields/*/name')); + + $serverslist->outputjavascript(); + $errorfileslist->outputjavascript(); + $htmllist_acls->outputjavascript(); + $htmllist_actions->outputjavascript(); ?> browser_InnerText_support = (document.getElementsByTagName("body")[0].innerText != undefined) ? true : false; - + totalrows = <?php echo $counter; ?>; + + function table_acls_listitem_change(tableId, fieldId, rowNr, field) { + if (fieldId = "toggle_details") { + fieldId = "expression"; + field = d.getElementById(tableId+"expression"+rowNr); + } + if (fieldId = "expression") { + var actiontype = field.value; + + var table = d.getElementById(tableId); + + for(var actionkey in showhide_aclfields) { + var fields = showhide_aclfields[actionkey]['fields']; + for(var fieldkey in fields){ + var fieldname = fields[fieldkey]['name']; + var rowid = "tr_edititemdetails_"+rowNr+"_"+actionkey+fieldname; + var element = d.getElementById(rowid); + + if (actionkey == actiontype) + element.style.display = ''; + else + element.style.display = 'none'; + } + } + } + } + + function table_actions_listitem_change(tableId, fieldId, rowNr, field) { + if (fieldId = "toggle_details") { + fieldId = "action"; + field = d.getElementById(tableId+"action"+rowNr); + } + if (fieldId = "action") { + var actiontype = field.value; + + var table = d.getElementById(tableId); + + for(var actionkey in showhide_actionfields) { + var fields = showhide_actionfields[actionkey]['fields']; + for(var fieldkey in fields){ + var fieldname = fields[fieldkey]['name']; + var rowid = "tr_edititemdetails_"+rowNr+"_"+actionkey+fieldname; + var element = d.getElementById(rowid); + + if (actionkey == actiontype) + element.style.display = ''; + else + element.style.display = 'none'; + } + } + } + } + updatevisibility(); </script> <?php diff --git a/config/haproxy-devel/www/haproxy_pools.php b/config/haproxy-devel/www/haproxy_pools.php index 92235933..d98c7f41 100644 --- a/config/haproxy-devel/www/haproxy_pools.php +++ b/config/haproxy-devel/www/haproxy_pools.php @@ -65,19 +65,13 @@ if ($_GET['act'] == "del") { exit; } -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); -if ($pf_version < 2.0) - $one_two = true; - $pgtitle = "Services: HAProxy: Backend server pools"; include("head.inc"); +haproxy_css(); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> -<?php if($one_two): ?> -<p class="pgtitle"><?=$pgtitle?></p> -<?php endif; ?> <form action="haproxy_pools.php" method="post"> <?php if ($input_errors) print_input_errors($input_errors); ?> <?php if ($savemsg) print_info_box($savemsg); ?> @@ -108,18 +102,31 @@ include("head.inc"); foreach ($a_pools as $pool){ $fe_list = ""; $sep = ""; - foreach ($a_backends as $backend) { - if($backend['backend_serverpool'] == $pool['name']) { - $fe_list .= $sep . $backend['name']; - $sep = ", "; - } + foreach ($a_backends as $frontend) { + $used = false; + if($frontend['backend_serverpool'] == $pool['name']) { + $used = true; + } + $actions = $frontend['a_actionitems']['item']; + if (is_array($actions)) { + foreach($actions as $action) { + if ($action["action"] == "use_backend" && $action['use_backendbackend'] == $pool['name']) { + $used = true; + } + } + } + if ($used) { + $fe_list .= $sep . $frontend['name']; + $sep = ", "; + } } $textgray = $fe_list == "" ? " gray" : ""; - if (is_array($pool['ha_servers'])) + if (is_array($pool['ha_servers'])) { $count = count($pool['ha_servers']['item']); - else - $count = 0; + } else { + $count = 0; + } ?> <tr class="<?=$textgray?>"> <td class="listlr" ondblclick="document.location='haproxy_pool_edit.php?id=<?=$i;?>';"> diff --git a/config/haproxy-devel/www/haproxy_stats.php b/config/haproxy-devel/www/haproxy_stats.php index 302793b6..628d0e5a 100644 --- a/config/haproxy-devel/www/haproxy_stats.php +++ b/config/haproxy-devel/www/haproxy_stats.php @@ -68,7 +68,7 @@ if (isset($_GET['haproxystats']) || isset($_GET['scope']) || (isset($_POST) && i exit(0); } require_once("guiconfig.inc"); -if (isset($_GET['showsticktablecontent'])){ +if (isset($_GET['showsticktablecontent']) || isset($_GET['showstatresolvers'])) { if (is_numeric($pconfig['localstats_sticktable_refreshtime'])) header("Refresh: {$pconfig['localstats_sticktable_refreshtime']}"); } @@ -91,10 +91,6 @@ if ($_POST) { } } -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); -if ($pf_version < 2.0) - $one_two = true; - $pgtitle = "Services: HAProxy: Stats"; include("head.inc"); @@ -102,9 +98,6 @@ include("head.inc"); <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> <form action="haproxy_stats.php" method="post"> -<?php if($one_two): ?> -<p class="pgtitle"><?=$pgtitle?></p> -<?php endif; ?> <?php if ($input_errors) print_input_errors($input_errors); ?> <?php if ($savemsg) print_info_box($savemsg); ?> <?php if (file_exists($d_haproxyconfdirty_path)): ?> @@ -123,15 +116,25 @@ include("head.inc"); <table class="tabcont" width="100%" height="100%" cellspacing="0"> <tr> <? -if (isset($_GET['showsticktablecontent'])){ + +if (isset($_GET['showstatresolvers'])){ + $showstatresolversname = $_GET['showstatresolvers']; + echo "<td colspan='2'>"; + echo "Contents of the sticktable: $sticktablename<br/>"; + $res = haproxy_socket_command("show stat resolvers $showstatresolversname"); + foreach($res as $line){ + echo "<br/>".print_r($line,true); + } + echo "</td>"; +} elseif (isset($_GET['showsticktablecontent'])){ $sticktablename = $_GET['showsticktablecontent']; -echo "<td colspan='2'>"; + echo "<td colspan='2'>"; echo "Contents of the sticktable: $sticktablename<br/>"; $res = haproxy_socket_command("show table $sticktablename"); foreach($res as $line){ echo "<br/>".print_r($line,true); } -echo "</td>"; + echo "</td>"; } else { ?> <td colspan="2"> @@ -177,6 +180,15 @@ echo "</td>"; <td> </td> </tr> <tr> + <td colspan="2" valign="top" class="listtopic">HAProxy DNS</td> + </tr> + <tr> + <td colspan="2" valign="top" class="vncell"><a href="/haproxy_stats.php?showstatresolvers=globalresolvers" target="_blank">DNS statistics</a></td> + </tr> + <tr> + <td> </td> + </tr> + <tr> <td colspan="2" valign="top" class="listtopic">HAProxy stats</td> </tr> <tr> diff --git a/config/haproxy-devel/www/haproxy_templates.php b/config/haproxy-devel/www/haproxy_templates.php index 478c83a3..072df508 100644 --- a/config/haproxy-devel/www/haproxy_templates.php +++ b/config/haproxy-devel/www/haproxy_templates.php @@ -114,6 +114,7 @@ EOD; $savemsg = "File 'ExampleErrorfile' is already configured on the Files tab."; } + $changedesc = "haproxy, add template errorfile"; if ($changecount > 0) { header("Location: haproxy_files.php"); echo "touching: $d_haproxyconfdirty_path"; @@ -122,7 +123,83 @@ EOD; exit; } } + +function haproxy_template_multipledomains() { + global $config, $d_haproxyconfdirty_path; + $a_backends = &$config['installedpackages']['haproxy']['ha_pools']['item']; + $a_frontends = &$config['installedpackages']['haproxy']['ha_backends']['item']; + + $backend = array(); + $backend["name"] = "example_backend1"; + $backend["stats_enabled"] = "yes"; + $backend["stats_uri"] = "/"; + $backend["stats_refresh"] = "10"; + $backend["stats_scope"] = "."; + $backend["stats_node"] = "NODE1"; + $a_backends[] = $backend; + + $backend = array(); + $backend["name"] = "example_backend2"; + $backend["stats_enabled"] = "yes"; + $backend["stats_uri"] = "/"; + $backend["stats_refresh"] = "10"; + $backend["stats_scope"] = "."; + $backend["stats_node"] = "NODE2"; + $a_backends[] = $backend; + + $backend = array(); + $backend["name"] = "example_backend3"; + $backend["stats_enabled"] = "yes"; + $backend["stats_uri"] = "/"; + $backend["stats_refresh"] = "10"; + $backend["stats_scope"] = "."; + $backend["stats_node"] = "NODE3"; + $a_backends[] = $backend; + + $frontend = array(); + $frontend["name"] = "example_multipledomains"; + $frontend["status"] = "active"; + $frontend["type"] = "http"; + $frontend["a_extaddr"]["item"]["stats_name"]["extaddr"] = "wan_ipv4"; + $frontend["a_extaddr"]["item"]["stats_name"]["extaddr_port"] = "80"; + $frontend["backend_serverpool"] = "example_backend1"; + $acl = array(); + $acl["name"] = "mail_acl"; + $acl["expression"] = "host_matches"; + $acl["value"] = "mail.domain.tld"; + $frontend["ha_acls"]["item"][] = $acl; + $action = array(); + $action["action"] = "use_backend"; + $action["use_backendbackend"] = "example_backend2"; + $action["acl"] = "mail_acl"; + $frontend["a_actionitems"]["item"][] = $action; + $a_frontends[] = $frontend; + + $frontend = array(); + $frontend["name"] = "example_multipledomains_forum"; + $frontend["status"] = "active"; + $frontend["secondary"] = "yes"; + $frontend["primary_frontend"] = "example_multipledomains"; + $acl = array(); + $acl["name"] = "forum_acl"; + $acl["expression"] = "host_matches"; + $acl["value"] = "forum.domain.tld"; + $frontend["ha_acls"]["item"][] = $acl; + $action = array(); + $action["action"] = "use_backend"; + $action["use_backendbackend"] = "example_backend3"; + $action["acl"] = "forum_acl"; + $frontend["a_actionitems"]["item"][] = $action; + $a_frontends[] = $frontend; + $changedesc = "haproxy, add multi domain example"; + header("Location: haproxy_listeners.php"); + echo "touching: $d_haproxyconfdirty_path"; + touch($d_haproxyconfdirty_path); + write_config($changedesc); + exit; +} + if (isset($_GET['add_stats_example'])) { $templateid = $_GET['add_stats_example']; switch ($templateid) { @@ -132,6 +209,9 @@ if (isset($_GET['add_stats_example'])) { case "2": template_errorfile(); break; + case "3": + haproxy_template_multipledomains(); + break; } } @@ -145,14 +225,12 @@ if ($_POST) { $pgtitle = "Services: HAProxy: Templates"; include("head.inc"); +haproxy_css(); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> <form action="haproxy_templates.php" method="post"> -<?php if($one_two): ?> -<p class="pgtitle"><?=$pgtitle?></p> -<?php endif; ?> <?php if ($input_errors) print_input_errors($input_errors); ?> <?php if ($savemsg) print_info_box($savemsg); ?> <?php if (file_exists($d_haproxyconfdirty_path)): ?> @@ -179,6 +257,20 @@ include("head.inc"); <td> </td> </tr> <tr> + <td colspan="2" valign="top" class="listtopic">Serving multiple domains from 1 frontend.</td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"> + <a href="haproxy_templates.php?add_stats_example=3">Create configuration</a> + </td> + <td class="vtable"> + As an basic example of how to serve multiple domains on 1 listening ip:port. + </td> + </tr> + <tr> + <td> </td> + </tr> + <tr> <td colspan="2" valign="top" class="listtopic">Stats SSL frontent+backend</td> </tr> <tr> diff --git a/config/haproxy-legacy/haproxy.inc b/config/haproxy-legacy/haproxy.inc index 55b86882..9b19bbd4 100644 --- a/config/haproxy-legacy/haproxy.inc +++ b/config/haproxy-legacy/haproxy.inc @@ -345,8 +345,8 @@ function haproxy_sync_on_changes() { } break; case "auto": - if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){ - $system_carp=$config['installedpackages']['carpsettings']['config'][0]; + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; $rs[0]['ipaddress']=$system_carp['synchronizetoip']; $rs[0]['username']=$system_carp['username']; $rs[0]['password']=$system_carp['password']; diff --git a/config/lightsquid/.project b/config/lightsquid/.project deleted file mode 100644 index 7e6f47b6..00000000 --- a/config/lightsquid/.project +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>lightsquid</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - </buildSpec> - <natures> - </natures> -</projectDescription> diff --git a/config/lightsquid/.settings/org.eclipse.ltk.core.refactoring.prefs b/config/lightsquid/.settings/org.eclipse.ltk.core.refactoring.prefs deleted file mode 100644 index 123de66a..00000000 --- a/config/lightsquid/.settings/org.eclipse.ltk.core.refactoring.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Fri Jun 22 21:59:25 MSD 2007 -eclipse.preferences.version=1 -org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/config/lightsquid/lightsquid.inc b/config/lightsquid/lightsquid.inc index a5f6b77b..7decc050 100644 --- a/config/lightsquid/lightsquid.inc +++ b/config/lightsquid/lightsquid.inc @@ -1,7 +1,9 @@ <?php /* lightsquid.inc - Copyright (C) 2006 Serg Dvorianceev + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006-2012 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC All rights reserved. Redistribution and use in source and binary forms, with or without @@ -25,7 +27,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - require_once('globals.inc'); require_once('config.inc'); require_once('util.inc'); @@ -34,13 +35,14 @@ require_once('pkg-utils.inc'); require_once('filter.inc'); require_once('service-utils.inc'); -if (file_exists('squid.inc')) { - require_once('squid.inc'); +if (file_exists('/usr/local/pkg/squid.inc')) { + require_once('/usr/local/pkg/squid.inc'); +} else { + echo "No squid.inc found. You must have Squid/Squid3 package installed to use LightSquid."; } -else update_log("File 'squid.inc' not found."); global $pfs_version; -$pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); +$pfs_version = substr(trim(file_get_contents("/etc/version")), 0, 3); switch ($pfs_version) { case "2.1": define('LIGHTSQUID_BASE', '/usr/pbi/lightsquid-' . php_uname("m")); @@ -49,16 +51,10 @@ switch ($pfs_version) { define('LIGHTSQUID_BASE', '/usr/pbi/lightsquid-' . php_uname("m") . '/local'); break; default: - define('LIGHTSQUID_BASE','/usr/local'); + define('LIGHTSQUID_BASE', '/usr/local'); break; } -define ('CMD_PKGDELETE', 'pkg_delete lightsquid-1.7.1'); - -// enable GUI debug -define('LS_GUI_DEBUG', 'on'); -define('LS_LOG_FILE', '/tmp/lightsquid_gui.log'); - // configuration settings !-- CHECK THIS --! define('LS_CONFIGPATH', LIGHTSQUID_BASE . '/etc/lightsquid'); define('LS_CONFIGFILE', 'lightsquid.cfg'); @@ -69,20 +65,15 @@ define('LS_LANGPATH', LIGHTSQUID_BASE . '/share/lightsquid/lang'); define('LS_REPORTPATH', '/var/lightsquid/report'); global $config; -if (isset($config['installedpackages']['squid']['config'][0])) { - if (!empty($config['installedpackages']['squid']['config'][0]['log_dir'])) - define('LS_SQUIDLOGPATH', $config['installedpackages']['squid']['config'][0]['log_dir']); - else - define('LS_SQUIDLOGPATH', '/var/squid/logs'); +if (is_array($config['installedpackages']['squid']['config'][0]) && $config['installedpackages']['squid']['config'][0]['log_dir'] != "") { + define('LS_SQUIDLOGPATH', $config['installedpackages']['squid']['config'][0]['log_dir']); +} else { + define('LS_SQUIDLOGPATH', '/var/squid/logs'); } + define('LS_SQUIDLOG', 'access.log'); define('LS_IP2NAMEPATH', LIGHTSQUID_BASE . '/libexec/lightsquid'); - -define('CRONTAB_FILE', '/var/cron/tabs/root'); define('CRONTAB_LS_TEMPLATE', '/usr/bin/perl ' . LIGHTSQUID_BASE . '/www/lightsquid/lightparser.pl'); -define('CRONTAB_LS_JOBKEY', '/lightparser.pl'); -define('CRONTAB_SQUID_TEMPLATE', '/usr/local/sbin/squid -k rotate > /dev/null'); -define('CRONTAB_SQUID_JOBKEY', '/squid -k rotate'); // default values define('LS_DEF_IP2NAME', 'dns'); @@ -106,43 +97,27 @@ define('LS_VAR_IP2NAME', 'ip2name'); define('LS_VAR_TEMPLATE', 'templatename'); define('LS_VAR_BARCOLOR', 'barcolor'); -// xml variables +// XML GUI variables define('LS_XML_LANG', 'lightsquid_lang'); define('LS_XML_SKIPURL', 'lightsquid_skipurl'); define('LS_XML_IP2NAME', 'lightsquid_ip2name'); define('LS_XML_TEMPLATE', 'lightsquid_template'); define('LS_XML_BARCOLOR', 'lightsquid_barcolor'); define('LS_XML_SHEDULERTIME', 'lightsquid_refreshsheduler_time'); -define('LS_XML_SQUID_SHEDULERTIME', 'lightsquid_squidrotatelog_sheduler_time'); - -function lightsquid_install() { - global $pfs_version; - - update_log("lightsquid_install: started"); - // create lightsquid report catalog - if (!file_exists(LS_REPORTPATH)) { - update_log("lightsquid_install: Create report dir " . LS_REPORTPATH); - mwexec("/bin/mkdir -p " . LS_REPORTPATH); - } +/* + * Package install/uninstall + */ - if ($pfs_version == "2.1" || $pfs_version == "2.2") { - # check perl - $perl_path = '/usr/bin/perl'; +function lightsquid_install() { + // create lightsquid reports directory + lightsquid_create_reportdir(); - /* Clean up a bad perl link. */ - ls_cleanup_bad_link($perl_path); + // ugly PBI hacks + if (LIGHTSQUID_BASE != '/usr/local') { + // check and fix perl paths + lightsquid_fix_perl(); - if (!file_exists("/usr/bin/perl")) { - if (is_executable('/usr/local/bin/perl')) { - symlink('/usr/local/bin/perl', '/usr/bin/perl'); - } elseif (is_executable(LIGHTSQUID_BASE . '/bin/perl')) { - symlink(LIGHTSQUID_BASE . '/bin/perl', '/usr/bin/perl'); - } - } - if (!is_dir('/usr/local/lib/perl5') && is_dir(LIGHTSQUID_BASE . '/lib/perl5')) { - symlink(LIGHTSQUID_BASE . '/lib/perl5', '/usr/local/lib/perl5'); - } if (!is_dir('/usr/local/etc/lightsquid') && is_dir(LS_CONFIGPATH)) { symlink(LS_CONFIGPATH, '/usr/local/etc/lightsquid'); } @@ -155,332 +130,358 @@ function lightsquid_install() { } } + // template symlinks foreach (array('novopf', 'novosea') as $tpl) { - if (file_exists(LS_TEMPLATEPATH . '/' . $tpl)) + if (is_dir(LS_TEMPLATEPATH . '/' . $tpl)) { $_gc = exec('rm -rf ' . LS_TEMPLATEPATH . '/' . $tpl); + } symlink('/usr/local/share/lightsquid/tpl/' . $tpl, LS_TEMPLATEPATH . '/' . $tpl); } - - update_log("lightsquid_install: stopped"); + symlink("/usr/local/www/themes", "/usr/local/www/sqstat/themes"); } function lightsquid_deinstall() { - update_log("lightsquid_deinstall: started"); - - // delete cron task's - ls_setup_cron("lightsquid_squid_rotate", "", "", false); - ls_setup_cron("lightsquid_parser", "", "", false); + // remove cronjobs + lightsquid_setup_cron(false); + // undo PBI hacks + lightsquid_unfix_perl(); + if (is_dir("/usr/local/www/sqstat/")) { + mwexec("/bin/rm -rf /usr/local/www/sqstat/"); + } +} - update_log("lightsquid_deinstall: stopped"); +/* + * Ugly PBI hacks around perl paths; only needed for pfSense <2.3 + */ +/* Create perl links on package install */ +function lightsquid_fix_perl() { + if (LIGHTSQUID_BASE != '/usr/local') { + /* Clean up a broken perl link first if needed. */ + $perl_path = '/usr/bin/perl'; + if (file_exists($perl_path) && is_link($perl_path)) { + $target = readlink($perl_path); + if (!file_exists($target) || !is_executable($target)) { + unlink($target); + } + } + /* Find usable perl and create perl symlink to $perl_path */ + if (!file_exists($perl_path)) { + if (is_executable("/usr/local/bin/perl")) { + symlink("/usr/local/bin/perl", "{$perl_path}"); + } elseif (is_executable(LIGHTSQUID_BASE . "/bin/perl")) { + symlink(LIGHTSQUID_BASE . "/bin/perl", "{$perl_path}"); + } + } + if (!is_dir("/usr/local/lib/perl5") && is_dir(LIGHTSQUID_BASE . "/lib/perl5")) { + symlink(LIGHTSQUID_BASE . "/lib/perl5", "/usr/local/lib/perl5"); + } + } +} +/* Remove perl links on package uninstall */ +function lightsquid_unfix_perl() { + if (LIGHTSQUID_BASE != '/usr/local') { + $perl_path = '/usr/bin/perl'; + if (file_exists($perl_path) && is_link($perl_path)) { + $target = readlink($perl_path); + $ls_target = LIGHTSQUID_BASE . "/bin/perl"; + if ($target === $ls_target) { + unlink($perl_path); + } + } + $perl_libpath = "/usr/local/lib/perl5"; + if (is_dir($perl_libpath) && is_link($perl_libpath)) { + $target = readlink($perl_libpath); + $ls_target = LIGHTSQUID_BASE . "/lib/perl5"; + if ($target === $ls_target) { + unlink($perl_libpath); + } + } + } } +/* + * Package configuration routines + */ function lightsquid_resync() { global $config, $pfs_version; - $tm = ''; - $tm_squid = ''; - if ($pfs_version == "2.1" || $pfs_version == "2.2") { - # check perl - if (!file_exists("/usr/bin/perl")) - mwexec("ln -s /usr/local/bin/perl /usr/bin/perl"); + // Ugly PBI hacks + if (LIGHTSQUID_BASE != '/usr/local') { + // check perl paths + if (!file_exists("/usr/bin/perl")) { + lightsquid_fix_perl(); + } // Fixup library path so GD can find its libraries for graphs. mwexec("/sbin/ldconfig -m " . LIGHTSQUID_BASE . "/lib/"); } - // create lightsquid report catalog - if (!file_exists(LS_REPORTPATH)) { - update_log("lightsquid_install: Create report dir " . LS_REPORTPATH); - mwexec("mkdir -p " . LS_REPORTPATH); - } - + lightsquid_create_reportdir(); mwexec("/bin/chmod -R u+w " . LIGHTSQUID_BASE . "/etc/lightsquid"); - // debug - $light_test = array(); - if (($_POST['Submit'] === 'Save') or !isset($_POST['Submit'])) { - $lsconf_var = array(); + // Set up variables for configuration update + $lsconf_var = array(); + $lsconf_var[LS_VAR_CFGPATH] = "\"" . LS_CONFIGPATH . "\""; + $lsconf_var[LS_VAR_LOGPATH] = "\"" . LS_SQUIDLOGPATH . "\""; - // variables for update - $lsconf_var[LS_VAR_CFGPATH] = "\"" . LS_CONFIGPATH . "\""; - if (isset($config['installedpackages']['squid']['config'][0])) { - $lsconf_var[LS_VAR_LOGPATH] = "\"" . LS_SQUIDLOGPATH . "\""; - } - $lsconf_var[LS_VAR_TPLPATH] = "\"" . LS_TEMPLATEPATH . "\""; - $lsconf_var[LS_VAR_LANGPATH] = "\"" . LS_LANGPATH . "\""; - $lsconf_var[LS_VAR_REPORTPATH] = "\"" . LS_REPORTPATH . "\""; - $lsconf_var[LS_VAR_IP2NAMEPATH] = "\"" . LS_IP2NAMEPATH . "\""; - - $lsconf_var[LS_VAR_LANG] = "\"" . LS_DEF_LANG . "\""; - $lsconf_var[LS_VAR_TEMPLATE] = "\"" . LS_DEF_TEMPLATE . "\""; - $lsconf_var[LS_VAR_IP2NAME] = "\"" . LS_DEF_IP2NAME . "\""; - $lsconf_var[LS_VAR_SKIPURL] = "\"" . LS_DEF_SKIPURL . "\""; - $lsconf_var[LS_VAR_SQUIDLOGTYPE]= LS_DEF_SQUIDLOGTYPE; - - // update variables from package GUI config - if (isset($config['installedpackages']['lightsquid']['config'][0])) { - $cfg = $config['installedpackages']['lightsquid']['config'][0]; - - $tm = $cfg[LS_XML_SHEDULERTIME]; - $tm_squid = $cfg[LS_XML_SQUID_SHEDULERTIME]; - - if (isset($cfg[LS_XML_LANG]) and !empty($cfg[LS_XML_LANG])) - $lsconf_var[LS_VAR_LANG] = "\"" . $cfg[LS_XML_LANG] . "\";"; - - if (isset($cfg[LS_XML_SKIPURL]) and !empty($cfg[LS_XML_SKIPURL])) - $lsconf_var[LS_VAR_SKIPURL] = "\"" . $cfg[LS_XML_SKIPURL] . "\";"; - - if (isset($cfg[LS_XML_IP2NAME]) and !empty($cfg[LS_XML_IP2NAME] )) - $lsconf_var[LS_VAR_IP2NAME] = "\"" . $cfg[LS_XML_IP2NAME] . "\";"; - - if (isset($cfg[LS_XML_TEMPLATE]) and !empty($cfg[LS_XML_TEMPLATE])) { - $tpl_val = $cfg[LS_XML_TEMPLATE]; - // check template path - if (!file_exists(LS_TEMPLATEPATH."/$tpl_val")) $tpl_val = 'base'; - $lsconf_var[LS_VAR_TEMPLATE] = "\"" . $tpl_val . "\";"; - } + $lsconf_var[LS_VAR_TPLPATH] = "\"" . LS_TEMPLATEPATH . "\""; + $lsconf_var[LS_VAR_LANGPATH] = "\"" . LS_LANGPATH . "\""; + $lsconf_var[LS_VAR_REPORTPATH] = "\"" . LS_REPORTPATH . "\""; + $lsconf_var[LS_VAR_IP2NAMEPATH] = "\"" . LS_IP2NAMEPATH . "\""; - if (isset($cfg[LS_XML_BARCOLOR]) and !empty($cfg[LS_XML_BARCOLOR])) - $lsconf_var[LS_VAR_BARCOLOR] = "\"" . $cfg[LS_XML_BARCOLOR] . "\";"; - } + $lsconf_var[LS_VAR_LANG] = "\"" . LS_DEF_LANG . "\""; + $lsconf_var[LS_VAR_TEMPLATE] = "\"" . LS_DEF_TEMPLATE . "\""; + $lsconf_var[LS_VAR_IP2NAME] = "\"" . LS_DEF_IP2NAME . "\""; + $lsconf_var[LS_VAR_SKIPURL] = "'" . LS_DEF_SKIPURL . "'"; + $lsconf_var[LS_VAR_SQUIDLOGTYPE]= LS_DEF_SQUIDLOGTYPE; - $lsconf = ""; - $lsconf_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE; - // open lightsquid config - if (file_exists($lsconf_file)) { - $lsconf = file_get_contents($lsconf_file); - update_log("Load config file $lsconf_file"); - } else { - update_log("Error loading config file $lsconf_file"); - // or open from 'lightsquid.cfg.dist' - $lsconf_dist_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE_DIST; - if (file_exists($lsconf_dist_file)) { - $lsconf = file_get_contents($lsconf_dist_file); - update_log("Load config dist. file $lsconf_dist_file"); - } else update_log("Error loading config dist. file $lsconf_dist_file"); + // Update variables from package GUI config + if (is_array($config['installedpackages']['lightsquid']['config'][0])) { + $lightsquid_config = $config['installedpackages']['lightsquid']['config'][0]; + + if (isset($lightsquid_config[LS_XML_LANG]) and !empty($lightsquid_config[LS_XML_LANG])) { + $lsconf_var[LS_VAR_LANG] = "\"" . $lightsquid_config[LS_XML_LANG] . "\""; } - // update lightsquid config - if (!empty($lsconf)) { - $lsconf = explode("\n", $lsconf); - foreach ($lsconf_var as $key => $val) { - for($i = 0; $i < count($lsconf); $i++) { - $s = trim($lsconf[$i]); - $e_key = "/^[$]" . $key . "[ ]*[=]+/i"; -# update_log("Regular: preg_match(\"$e_key," . "'$s')"); // debug regular template - if (preg_match($e_key, $s)) { -# update_log("Regular PASSED: preg_match(\"$e_key," . "'$s')"); // debug regular template - $lsconf[$i] = '$' . "$key = $val;"; - update_log("Update config: $key=$val"); - } - } - } + if (isset($lightsquid_config[LS_XML_SKIPURL]) and !empty($lightsquid_config[LS_XML_SKIPURL])) { + $lsconf_var[LS_VAR_SKIPURL] = "'" . str_replace(".", "\\.", $lightsquid_config[LS_XML_SKIPURL]) . "'"; + } - $lsconf = implode("\n", $lsconf); - $fl = file_put_contents($lsconf_file, $lsconf); - update_log("Save config file $lsconf_file ($fl)"); + if (isset($lightsquid_config[LS_XML_IP2NAME]) and !empty($lightsquid_config[LS_XML_IP2NAME] )) { + $lsconf_var[LS_VAR_IP2NAME] = "\"" . $lightsquid_config[LS_XML_IP2NAME] . "\""; } - // set shedule - refresh data job - if ($tm) { - $on = false; - $opt = array("*", "*", "*", "*", "*", "root", CRONTAB_LS_TEMPLATE . " today"); - switch($tm) { - case 'lhp_none': $on = false; break; - case 'lhp_10m': $on = true; $opt[0]= "*/10"; break; - case 'lhp_20m': $on = true; $opt[0]= "*/20"; break; - case 'lhp_30m': $on = true; $opt[0]= "*/30"; break; - case 'lhp_40m': $on = true; $opt[0]= "*/40"; break; - case 'lhp_50m': $on = true; $opt[0]= "*/50"; break; - case 'lhp_60m': $on = true; $opt[0]= "*/60"; break; - case 'lhp_2h': $on = true; $opt[0]= "0"; $opt[1]= "*/2"; break; - case 'lhp_3h': $on = true; $opt[0]= "0"; $opt[1]= "*/3"; break; - case 'lhp_4h': $on = true; $opt[0]= "0"; $opt[1]= "*/4"; break; - case 'lhp_6h': $on = true; $opt[0]= "0"; $opt[1]= "*/6"; break; - case 'lhp_8h': $on = true; $opt[0]= "0"; $opt[1]= "*/8"; break; - case 'lhp_12h': $on = true; $opt[0]= "0"; $opt[1]= "*/12"; break; - case 'lhp_24h': $on = true; $opt[0]= "45"; $opt[1]= "23"; break; # dayly at 23:45 + if (isset($lightsquid_config[LS_XML_TEMPLATE]) and !empty($lightsquid_config[LS_XML_TEMPLATE])) { + $tpl_val = $lightsquid_config[LS_XML_TEMPLATE]; + // check template path + if (!file_exists(LS_TEMPLATEPATH."/$tpl_val")) { + $tpl_val = 'base'; } - ls_setup_cron("lightsquid_parser_today", $opt, CRONTAB_LS_JOBKEY, $on); - - # fix possible data lost with 00:00 script start - rescan yesterday - $opt = array("15", "0", "*", "*", "*", "root", CRONTAB_LS_TEMPLATE . " yesterday"); - ls_setup_cron("lightsquid_parser_yesterday", $opt, CRONTAB_LS_JOBKEY, $on); - - } else { - ls_setup_cron("lightsquid_parser_today", "", "", false); - ls_setup_cron("lightsquid_parser_yesterday", "", "", false); + $lsconf_var[LS_VAR_TEMPLATE] = "\"" . $tpl_val . "\""; } - - ls_setup_cron("lightsquid_squid_rotate", "", "", false); - - // update squid conf - if (isset($config['installedpackages']['squid']['config'][0])) { - $squid_settings = $config['installedpackages']['squid']['config'][0]; - $squid_settings['log_enabled'] = 'on'; - if (empty($squid_settings['log_dir'])) - $squid_settings['log_dir'] = LS_SQUIDLOGPATH; - - # sqstat - $ifmgr = "127.0.0.1;"; - $iface = ($squid_settings['active_interface'] ? $squid_settings['active_interface'] : 'lan'); - $iface = explode(",", $iface); - foreach ($iface as $i => $if) { - $realif = ls_get_real_interface_address($if); - if ($realif[0]) - $ifmgr = $ifmgr . $realif[0] . ";"; - } - /* Only save and resync if we're actually making any changes. */ - if (strpos($config['installedpackages']['squidnac']['config'][0]['ext_cachemanager'], $ifmgr) === FALSE) { - $config['installedpackages']['squidnac']['config'][0]['ext_cachemanager'] = $ifmgr; - write_config(); - if (function_exists('squid_resync')) - squid_resync(); - else - update_log("Function 'squid_resync' not found."); - } + if (isset($lightsquid_config[LS_XML_BARCOLOR]) and !empty($lightsquid_config[LS_XML_BARCOLOR])) { + $lsconf_var[LS_VAR_BARCOLOR] = "\"" . $lightsquid_config[LS_XML_BARCOLOR] . "\""; } } - if ($_POST['Submit'] === 'Refresh now') refresh_now(); - if ($_POST['Submit'] === 'Refresh full') refresh_full(); -} - -// setup cron tasks -// original source from '/etc/inc/pfsense-utils.inc' function 'tdr_install_cron' -// this function safe for other tasks -// ***************************************************************************** -// - $task_name: cron task name (for config identification) /for searching my cron tasks/ -// - $options: array=[0:minute][1:hour][2:mday][3:month][4:wday][5:who][6:cmd] -// - $task_key: cron command key for searching -// - $on_off: true-'on task', false-'off' task -// required: $task_nameand $on_off -// ***************************************************************************** -define('FIELD_TASKNAME', 'task_name'); - -function ls_setup_cron($task_name, $options, $task_key, $on_off) { - global $config; - update_log("ls_setup_cron: start task_name=$task_name, task_key=$task_key, on_off=$on_off"); - - // check input params - if(!$task_name) { - update_log("ls_setup_cron: exit - uncomplete input params."); - return; + // Create or update lightsquid.cfg + $lsconf = ""; + $lsconf_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE; + // Always use the lightsquid.cfg.dist template to avoid issues with GUI values reconfiguration + $lsconf_dist_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE_DIST; + if (file_exists($lsconf_dist_file)) { + $lsconf = file_get_contents($lsconf_dist_file); + log_error("[lightsquid] Loaded default '{$lsconf_dist_file}' configuration file."); + } else { + log_error("[lightsquid] Error: Could not load default '{$lsconf_dist_file}' configuration file."); } - // delete old task(s) - if (is_array($config['cron']['item'])) { - foreach ($config['cron']['item'] as $key => $item) { - # unset crontask by name - if (!empty($task_name) && ($item[FIELD_TASKNAME] == $task_name)) { - unset($config['cron']['item'][$key]); - } else - # unset crontask by cmd - if ($options[6] && (strpos($item['command'], $options[6]) !== false)) { - unset($config['cron']['item'][$key]); - } + // Update lightsquid.cfg + if (!empty($lsconf)) { + $lsconf = explode("\n", $lsconf); + foreach ($lsconf_var as $key => $val) { + for ($i = 0; $i < count($lsconf); $i++) { + $s = trim($lsconf[$i]); + $e_key = "/^[$]" . $key . "[ ]*[=]+/i"; + if (preg_match($e_key, $s)) { + $lsconf[$i] = '$' . "$key = $val;"; + } + } } - } - # install cron task - if ($on_off) { - if ($task_key) { - if (is_array($options)) { - # add new - $cron_item = array(); - $cron_item[FIELD_TASKNAME] = $task_name; - $cron_item['minute'] = $options[0]; - $cron_item['hour'] = $options[1]; - $cron_item['mday'] = $options[2]; - $cron_item['month'] = $options[3]; - $cron_item['wday'] = $options[4]; - $cron_item['who'] = $options[5]; - $cron_item['command'] = $options[6]; - - # check options - if (!$cron_item['who']) $cron_item['who'] = "nobody"; - - $config['cron']['item'][] = $cron_item; - update_log("ls_setup_cron: add cron task '{$task_name}'='{$cron_item['command']}'"); + $lsconf = implode("\n", $lsconf); + if (file_put_contents($lsconf_file, $lsconf)) { + log_error("[lightsquid] Successfully created '{$lsconf_file}' configuration file."); + } else { + log_error("[lightsquid] Error: Could not create '{$lsconf_file}' configuration file."); } - } else - // log - update_log("ls_setup_cron: input prm 'task_key' not defined"); + } else { + log_error("[lightsquid] Error: Could not create '{$lsconf_file}' configuration file."); } - write_config("Installed cron task '$task_name' for 'lightsquid' package"); - configure_cron(); - update_log("ls_setup_cron: Apply new cron settings."); + // Set up scheduled reports updates + lightsquid_setup_cron(true); } -function update_log($log) { - if (LS_GUI_DEBUG === 'on') { - $t_ls_log = ''; - if (file_exists(LS_LOG_FILE)) - $t_ls_log = file_get_contents(LS_LOG_FILE); - $t_ls_log .= "\n$log"; - file_put_contents(LS_LOG_FILE, $t_ls_log); +/* + * Reports + */ + +/* Configure scheduled reports updates via cron */ +function lightsquid_setup_cron($active=false) { + global $config; + if (is_array($config['installedpackages']['lightsquid']['config'][0])) { + $cron_schedule = $config['installedpackages']['lightsquid']['config'][0][LS_XML_SHEDULERTIME]; + } else { + $cron_schedule = ''; + } + $lightsquid_parser_today = CRONTAB_LS_TEMPLATE . " today"; + $lightsquid_parser_yesterday = CRONTAB_LS_TEMPLATE . " yesterday"; + + if ($active && $cron_schedule) { + $on = false; + $opt = array("*", "*", "*", "*", "*", "root"); + // remove old cronjobs first ... + log_error("[lightsquid] Removing old cronjobs..."); + install_cron_job($lightsquid_parser_today, false); + install_cron_job($lightsquid_parser_yesterday, false); + // ... and configure updated cronjobs if needed + switch($cron_schedule) { + case 'lhp_none': $on = false; break; + case 'lhp_10m': $on = true; $opt[0]= "*/10"; break; + case 'lhp_20m': $on = true; $opt[0]= "*/20"; break; + case 'lhp_30m': $on = true; $opt[0]= "*/30"; break; + case 'lhp_40m': $on = true; $opt[0]= "*/40"; break; + case 'lhp_50m': $on = true; $opt[0]= "*/50"; break; + case 'lhp_60m': $on = true; $opt[0]= "*/60"; break; + case 'lhp_2h': $on = true; $opt[0]= "0"; $opt[1]= "*/2"; break; + case 'lhp_3h': $on = true; $opt[0]= "0"; $opt[1]= "*/3"; break; + case 'lhp_4h': $on = true; $opt[0]= "0"; $opt[1]= "*/4"; break; + case 'lhp_6h': $on = true; $opt[0]= "0"; $opt[1]= "*/6"; break; + case 'lhp_8h': $on = true; $opt[0]= "0"; $opt[1]= "*/8"; break; + case 'lhp_12h': $on = true; $opt[0]= "0"; $opt[1]= "*/12"; break; + case 'lhp_24h': $on = true; $opt[0]= "45"; $opt[1]= "23"; break; // daily at 23:45 + } + if ($on) { + log_error("[lightsquid] Updating cronjobs..."); + install_cron_job($lightsquid_parser_today, $on, $opt[0], $opt[1], $opt[2], $opt[3], $opt[4], $opt[5]); + // fix possible data lost with 00:00 script start - rescan yesterday + install_cron_job($lightsquid_parser_yesterday, true, "15", "0", "*", "*", "*", "root"); + } + } else { + log_error("[lightsquid] Removing all cronjobs..."); + install_cron_job($lightsquid_parser_today, false); + install_cron_job($lightsquid_parser_yesterday, false); } } -function refresh_now() { +/* Parse today's entires only in access.log via the GUI button */ +function lightsquid_refresh_now() { $cmd = CRONTAB_LS_TEMPLATE . " today"; - update_log("refresh_now: execute command '$cmd'"); - // create lightsquid report catalog - if (!file_exists(LS_REPORTPATH)) { - update_log("lightsquid_install: Create report dir " . LS_REPORTPATH); - mwexec("mkdir -p " . LS_REPORTPATH); + $lg = LS_SQUIDLOG; + lightsquid_create_reportdir(); + + if (file_exists(LS_SQUIDLOGPATH . "/{$lg}")) { + log_error("[lightsquid] Parsing today's entries in access.log using '{$cmd}'"); + mwexec_bg($cmd); + } else { + log_error("[lightsquid] Could not parse '{$lg}' - log does not exist!"); } - mwexec_bg($cmd); } -function refresh_full() { +/* Parse all entries in all access logs, including the rotated ones via the GUI button */ +function lightsquid_refresh_full() { $cmd = CRONTAB_LS_TEMPLATE; - $log_name = LS_SQUIDLOG; - update_log("refresh_full: start"); - - // create lightsquid report catalog - if (!file_exists(LS_REPORTPATH)) { - update_log("lightsquid_install: Create report dir " . LS_REPORTPATH); - mwexec("mkdir -p " . LS_REPORTPATH); - } + lightsquid_create_reportdir(); + log_error("[lightsquid] Parsing all access log(s) entries using '{$cmd}'..."); // parse access.log - update_log("refresh_full: execute command '$cmd'"); - mwexec_bg("$cmd $log_name"); - // parse access.log.x - if (isset($config['installedpackages']['squid']['config'][0])) { - for ($i=0; $i<100; $i++) { - $lg = LS_SQUIDLOG . ".$i"; - if (file_exists(LS_SQUIDLOGPATH . "/$lg")) { - update_log("refresh_full: execute command '$cmd $lg'"); - mwexec_bg("$cmd $lg"); - } else - // really go <= 10 cycles - break; + $lg = LS_SQUIDLOG; + if (file_exists(LS_SQUIDLOGPATH . "/{$lg}")) { + log_error("[lightsquid] Parsing log entries in '{$lg}'..."); + mwexec_bg("{$cmd} {$lg}"); + } else { + log_error("[lightsquid] Could not parse '{$lg}' - log does not exist!"); + } + // parse access.log.x; if user configured some insane amount of rotated logs, only parse the first 100 of them + for ($i = 0; $i < 100; $i++) { + $lg = LS_SQUIDLOG . ".{$i}"; + if (file_exists(LS_SQUIDLOGPATH . "/{$lg}")) { + log_error("[lightsquid] Parsing log entries in '{$lg}'..."); + mwexec_bg("{$cmd} {$lg}"); + } else { + break; } } - update_log("refresh_full: stop"); } -function ls_get_real_interface_address($iface) -{ +/* Helper function to create lightsquid reports directory if needed */ +function lightsquid_create_reportdir() { + if (!is_dir(LS_REPORTPATH)) { + log_error("[lightsquid] Creating report dir " . LS_REPORTPATH); + safe_mkdir(LS_REPORTPATH); + } +} + + +/* + * Input validation + * Check required Squid configuration and provide instructions to users, + * instead of trying to mess with Squid's settings directly. + */ +function lightsquid_validate_input($post, &$input_errors) { global $config; + /* Manual reports refresh; only allow to run if the configuration file exists already! */ + if ($post['refreshnow'] == 'Refresh now' || $post['refreshfull'] == 'Refresh full') { + $lsconf_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE; + if (file_exists($lsconf_file)) { + if ($post['refreshnow'] == 'Refresh now') { + lightsquid_refresh_now(); + return; + } elseif ($post['refreshfull'] == 'Refresh full') { + lightsquid_refresh_full(); + return; + } + } else { + $input_errors[] = "Please, configure LightSquid package first and Save settings before trying to manually refresh reports."; + } + } - $iface = convert_friendly_interface_to_real_interface_name($iface); - $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6")); - list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line); + /* Check whether Squid is configured at all */ + if (is_array($config['installedpackages']['squid']['config'][0])) { + $squid_settings = $config['installedpackages']['squid']['config'][0]; + } else { + $input_errors[] = "Please, configure Squid package 'General' settings first."; + $squid_settings = array(); + } - return array($ip, long2ip(hexdec($netmask))); -} + /* Check whether logging is enabled in Squid */ + if ($squid_settings['log_enabled'] != "on") { + $input_errors[] = "Please, enable Access Logging in Squid package 'General' settings first."; + } + + /* Check whether log directory is configured in Squid */ + if ($squid_settings['log_dir'] == "") { + $input_errors[] = "Please, configure Log Store Directory in Squid package 'General' settings first."; + } -/* If a path is a symlink but the target is missing, remove the link. */ -function ls_cleanup_bad_link($link) { - if (file_exists($link) && is_link($link)) { - $target = readlink($link); - if (!file_exists($target) || !is_executable($target)) { - unlink($link); + /* SqStat - check external cache managers + * This check is only needed for Squid 2.7 packages, any Squid 3.x package allows localhost as cache manager by default + */ + $ifmgr = "127.0.0.1"; + if (get_pkg_id("squid") !== -1) { + if (is_array($config['installedpackages']['squidnac']['config'])) { + $ext_cachemanager = ($config['installedpackages']['squidnac']['config'][0]['ext_cachemanager'] ?: ""); + } else { + $ext_cachemanager = ""; + } + if (strpos($ext_cachemanager, $ifmgr) === false) { + $input_errors[] = "Please, add '{$ifmgr}' to Squid - Access Control - External Cache-Managers first."; + } + } + /* SqStat - check that Squid listens on loopback unless the proxy is set as transparent (which makes it listen on localhost automatically) */ + if (is_array($config['installedpackages']['squid']['config'])) { + $active_interfaces = ($config['installedpackages']['squid']['config'][0]['active_interface'] ?: ""); + $transparent = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == "on" ? true : false); + } else { + $active_interfaces = ""; + $transparent = false; + } + if (!$transparent) { + if (strpos($active_interfaces, "lo0") === false) { + $input_errors[] = "Please, configure Squid - General - Proxy Interface(s) to include 'loopback' interface."; + } + } + + /* 'Skip URL(s)' validation */ + if ($post['lightsquid_skipurl'] != "") { + $hosts = explode("|", $post['lightsquid_skipurl']); + foreach ($hosts as $host) { + $host = trim($host); + if (!is_ipaddr($host) && !is_hostname($host) && !is_domain($host)) { + $input_errors[] = "'Skip URL(s)' entry '{$host}' is not a valid IP address, hostname, domain or subnet."; + } } } } diff --git a/config/lightsquid/lightsquid.priv.inc b/config/lightsquid/lightsquid.priv.inc new file mode 100644 index 00000000..f228ad1e --- /dev/null +++ b/config/lightsquid/lightsquid.priv.inc @@ -0,0 +1,40 @@ +<?php +/* + lightsquid.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-status-lightsquid'] = array(); +$priv_list['page-status-lightsquid']['name'] = "WebCfg - Status: LightSquid package"; +$priv_list['page-status-lightsquid']['descr'] = "Allow access to LightSquid package GUI"; +$priv_list['page-status-lightsquid']['match'] = array(); + +$priv_list['page-status-lightsquid']['match'][] = "pkg.php?xml=lightsquid.xml*"; +$priv_list['page-status-lightsquid']['match'][] = "pkg_edit.php?xml=lightsquid.xml*"; +$priv_list['page-status-lightsquid']['match'][] = "sqstat/sqstat.php*"; + +?> diff --git a/config/lightsquid/lightsquid.xml b/config/lightsquid/lightsquid.xml index f5f09b94..834efd46 100644 --- a/config/lightsquid/lightsquid.xml +++ b/config/lightsquid/lightsquid.xml @@ -2,453 +2,429 @@ <!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> <?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> - <copyright> - <![CDATA[ + <copyright> +<![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* - lightsquid.xml - part of pfSense (http://www.pfSense.com) - Copyright (C) 2007 to whom it may belong - All rights reserved. - - Based on m0n0wall (http://m0n0.ch/wall) - Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>. - All rights reserved. - */ -/* ========================================================================== */ + lightsquid.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006-2012 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC + All rights reserved. +*/ +/* ====================================================================================== */ /* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + 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. + 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. + 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. - */ -/* ========================================================================== */ - ]]> - </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> + + 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. +*/ +/* ====================================================================================== */ + ]]> + </copyright> <name>lightsquid</name> - <version>2.41</version> - <title>Services: Proxy Reports (LightSquid, SQStat) -> Settings</title> + <version>2.42</version> + <title>Squid Proxy Reports: Settings</title> <category>Status</category> <include_file>/usr/local/pkg/lightsquid.inc</include_file> <menu> - <name>Proxy report</name> - <tooltiptext>Proxy server statistic report</tooltiptext> + <name>Squid Proxy Reports</name> + <tooltiptext>Proxy Server Statistic Reports</tooltiptext> <section>Status</section> - <url>/pkg_edit.php?xml=lightsquid.xml&id=0</url> + <url>/pkg_edit.php?xml=lightsquid.xml</url> </menu> - <tabs> - <tab> - <text>Settings</text> - <url>/pkg_edit.php?xml=lightsquid.xml&id=0</url> - <active/> - </tab> - <tab> - <text>Lightsquid Report</text> - <url>/lightsquid/index.cgi</url> - </tab> - <tab> - <text>Proxy State</text> - <url>/sqstat/sqstat.php</url> - </tab> - </tabs> - <additional_files_needed> - <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/lightsquid.inc</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/sqstat/</prefix> - <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.class.php</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/sqstat/</prefix> - <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.php</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/sqstat/</prefix> - <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.css</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/sqstat/</prefix> - <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/zhabascript.js</item> - </additional_files_needed> + <tabs> + <tab> + <text>Settings</text> + <url>/pkg_edit.php?xml=lightsquid.xml</url> + <active/> + </tab> + <tab> + <text>Lightsquid Report</text> + <url>/lightsquid/index.cgi</url> + </tab> + <tab> + <text>Proxy Status</text> + <url>/sqstat/sqstat.php</url> + </tab> + </tabs> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/lightsquid.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/lightsquid.priv.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/sqstat/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.class.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/sqstat/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/sqstat/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.css</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/sqstat/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/zhabascript.js</item> + </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/bigfiles.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/day_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/graph.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/group_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/datetime.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/flag_red.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/graph.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/groups.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/printer.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/users.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/index.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/month_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/print.css</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/screen.css</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/topsites.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/user_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/user_month.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/user_time.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/whousesite.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/bigfiles.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/day_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/graph.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/group_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/datetime.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/flag_red.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/graph.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/groups.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/printer.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/users.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/index.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/month_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/print.css</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/screen.css</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/topsites.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/user_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/user_month.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/user_time.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/whousesite.html</item> </additional_files_needed> - <fields> - <field> - <fielddescr>Language</fielddescr> - <fieldname>lightsquid_lang</fieldname> - <description>Select report language</description> - <type>select</type> - <value>eng</value> - <options> - <option><name>Bulgarian</name><value>bg</value></option> - <option><name>Czech</name><value>cz</value></option> - <option><name>English</name><value>eng</value></option> - <option><name>French</name><value>fr</value></option> - <option><name>Hungarian</name><value>hu</value></option> - <option><name>Italian</name><value>it</value></option> - <option><name>Portuguese - Brazil</name><value>pt_br</value></option> - <option><name>Russian</name><value>ru</value></option> - <option><name>Russian KOI-8</name><value>ru-koi8</value></option> - <option><name>Spanish</name><value>sp</value></option> - <option><name>Ukrainian</name><value>ua</value></option> - </options> - </field> - <field> - <fielddescr>Bar color</fielddescr> - <fieldname>lightsquid_barcolor</fieldname> - <description>Select bar color</description> - <type>select</type> - <value>orange</value> - <options> - <option><name>Orange</name><value>orange</value></option> - <option><name>Blue</name><value>blue</value></option> - <option><name>Green</name><value>green</value></option> - <option><name>Yellow</name><value>yellow</value></option> - <option><name>Brown</name><value>brown</value></option> - <option><name>Red</name><value>red</value></option> - </options> - </field> - <field> - <fielddescr>Report scheme</fielddescr> - <fieldname>lightsquid_template</fieldname> - <description>Select report scheme</description> - <type>select</type> - <value>base</value> - <options> - <option><name>Base</name><value>base</value></option> - <option><name>Text</name><value>text</value></option> - <option><name>NovoSea</name><value>novosea</value></option> - <option><name>NovoPf</name><value>novopf</value></option> - </options> - </field> - <field> - <fielddescr>IP resolve method (future)</fielddescr> - <fieldname>lightsquid_ip2name</fieldname> - <description> - <table cellpadding=1 cellspacing=0 style="text-align: left;"> <tbody> - <tr><th colspan=2> Select IP to Name resolve method (take effect only on new data): </th><tr> - <tr><th> IP </th><td> - return IP </td><tr> - <tr><th> Demo </th><td> - return AUTHNAME, else DNSNAME, else IP </td><tr> - <tr><th> DNS </th><td> - return DNSNAME </td><tr> - <tr><th> Simple </th><td> - return AUTHNAME else IP </td><tr> - <tr><th> SMB </th><td> - return SMB name of pc </td><tr> - <tr><th> Squidauth </th><td> - return AUTHNAME else IP, allow cyrilyc name </td><tr> - </tbody> </table> - </description> - <type>select</type> - <value>dns</value> - <options> - <option><name>IP</name><value>ip</value></option> - <option><name>Demo</name><value>demo</value></option> - <option><name>DNS</name><value>dns</value></option> - <option><name>Simple</name><value>simple</value></option> - <option><name>SMB</name><value>smb</value></option> - <option><name>Squidauth</name><value>squidauth</value></option> - </options> - </field> - <field> - <fielddescr>Refresh sheduler</fielddescr> - <fieldname>lightsquid_refreshsheduler_time</fieldname> - <description> - Select data refresh period. System will execute task every XX time as from 00:00 hours. <br> - For example: if selected 2h - system wil start task at 0-2-4-..-24h. <br> - Note: (!),(*) - use only for powerful system; (+) - recomended. <br><br> - <input type="submit" name="Submit" value="Refresh now"><br> - <input type="submit" name="Submit" value="Refresh full"> - <br> Press button for start background refresh (this take some time). - <br> <span style="color: rgb(153, 51, 0);"> Note after installation: - <br> Firstly - enable log in squid package with "/var/squid/logs" path. - <br> Secondly - press Refresh button to create lightsquid reports, else you will have an error diagnostic page.</span> + <fields> + <field> + <name>Instructions</name> + <type>listtopic</type> + </field> + <field> + <type>info</type> + <fielddescr> + <![CDATA[ + <span class="errmsg">IMPORTANT: Perform these steps after install:</span> + ]]> + </fielddescr> + <description> + <![CDATA[ + 1/ <strong>Enable 'Access Logging' in the Squid package!</strong> It is strongly suggested to leave the 'Log Store Directory' in Squid package at default '/var/squid/logs' value.<br/><br/> + 2a/ <strong>ONLY if Squid is NOT set up as transparent proxy:</strong><br/> + - Configure Squid - General - Proxy Interface(s) to include <strong>'loopback'</strong> interface (in addition to any other interfaces you want Squid to bind on).<br/> + 2b/ <strong>ONLY if using Squid 2.7 package</strong> (this is not needed for Squid 3.x.):<br/> + - Add '127.0.0.1' to Squid - Access Control - External Cache-Managers.<br/><br/> + 3/ <strong>Configure 'Report Template Settings' and 'Reporting Settings and Scheduler' below and Save when finished.</strong><br/><br/> + 4/ <strong>Use the Refresh buttons in the 'Manual Refresh' section below to create initial LightSquid reports</strong>; otherwise you will get an error diagnostic page.<br/> + - <em>"Refresh now"</em> will (re)parse today's entries only in Squid's current access.log.<br/> + - <em>"Refresh full"</em> will (re)parse all entries in all Squid's access logs, including the rotated ones. <strong>Note: This may take long time to finish!</strong><br/> + ]]> </description> - <type>select</type> - <value>lhp_none</value> - <options> - <option><name>none</name><value>lhp_none</value></option> - <option><name>10min(!)</name><value>lhp_10m</value></option> - <option><name>20min(!)</name><value>lhp_20m</value></option> - <option><name>30min(*)</name><value>lhp_30m</value></option> - <option><name>40min(*)</name><value>lhp_40m</value></option> - <option><name>50min(+)</name><value>lhp_50m</value></option> - <option><name>60min(+)</name><value>lhp_60m</value></option> - <option><name>2h</name><value>lhp_2h</value></option> - <option><name>3h</name><value>lhp_3h</value></option> - <option><name>4h</name><value>lhp_4h</value></option> - <option><name>6h</name><value>lhp_6h</value></option> - <option><name>8h</name><value>lhp_8h</value></option> - <option><name>12h</name><value>lhp_12h</value></option> - <option><name>24(00)h</name><value>lhp_24h</value></option> - </options> - </field> - <!--field> - <fielddescr>Squid rotate log sheduler</fielddescr> - <fieldname>lightsquid_squidrotatelog_sheduler_time</fieldname> + </field> + <field> + <name>Report Template Settings</name> + <type>listtopic</type> + </field> + <field> + <fielddescr>Language</fielddescr> + <fieldname>lightsquid_lang</fieldname> + <description>Select report language.</description> + <type>select</type> + <default_value>eng</default_value> + <options> + <option><name>Bulgarian</name><value>bg</value></option> + <option><name>Czech</name><value>cz</value></option> + <option><name>English</name><value>eng</value></option> + <option><name>French</name><value>fr</value></option> + <option><name>Hungarian</name><value>hu</value></option> + <option><name>Italian</name><value>it</value></option> + <option><name>Portuguese (Brazilian)</name><value>pt_br</value></option> + <option><name>Russian</name><value>ru</value></option> + <option><name>Russian (KOI-8)</name><value>ru-koi8</value></option> + <option><name>Spanish</name><value>sp</value></option> + <option><name>Ukrainian</name><value>ua</value></option> + </options> + </field> + <field> + <fielddescr>Report Template</fielddescr> + <fieldname>lightsquid_template</fieldname> + <description>Select report template.</description> + <type>select</type> + <default_value>base</default_value> + <options> + <option><name>Base</name><value>base</value></option> + <option><name>Text</name><value>text</value></option> + <option><name>NovoSea</name><value>novosea</value></option> + <option><name>NovoPf</name><value>novopf</value></option> + </options> + </field> + <field> + <fielddescr>Bar Color</fielddescr> + <fieldname>lightsquid_barcolor</fieldname> + <description>Select bar color.</description> + <type>select</type> + <default_value>orange</default_value> + <options> + <option><name>Orange</name><value>orange</value></option> + <option><name>Blue</name><value>blue</value></option> + <option><name>Green</name><value>green</value></option> + <option><name>Yellow</name><value>yellow</value></option> + <option><name>Brown</name><value>brown</value></option> + <option><name>Red</name><value>red</value></option> + </options> + </field> + <field> + <name>Reporting Settings and Scheduler</name> + <type>listtopic</type> + </field> + <field> + <fielddescr>IP Resolve Method</fielddescr> + <fieldname>lightsquid_ip2name</fieldname> <description> - Select squid log rotate period. System will execute task every XX time as from 00:00 hours. <br> - This option will allow the updating of the faster <br> - For example: if selected '2 day' - system wil start task every 2 day of month. <br> - This option will allow the updating of the faster <br> - Note: You must choose from that the rate of filling dialogue access.log squid; <br> - The more customers, the more often it should be the job. + <![CDATA[ + <table cellpadding=1 cellspacing=0 style="text-align: left;"> + <tbody> + <tr><th colspan=2>Select which method(s) should be attempted (in the order listed below) to resolve IPs to hostnames:</th></tr> + <tr><th>IP </th><td> - Do not resolve IP addresses.</td></tr> + <tr><th>Demo </th><td> - Use Squid AUTHNAME, then DNSNAME, then IP.</td></tr> + <tr><th>DNS </th><td> - Use DNSNAME.</td></tr> + <tr><th>Simple </th><td> - Use Squid AUTHNAME, then IP address.</td></tr> + <tr><th>SMB </th><td> - Use NetBIOS name.</td></tr> + <tr><th>Squidauth </th><td> - Use Squid AUTHNAME, then IP address (allow international characters).</td></tr> + </tbody> + </table> + ]]> </description> <type>select</type> - <value>lsr_none</value> - <options> - <option><name>none</name><value>lsr_none</value></option> - <option><name>every 1 day</name><value>lsr_d1</value></option> - <option><name>every 2 day</name><value>lsr_d2</value></option> - <option><name>every 3 day</name><value>lsr_d3</value></option> - <option><name>every 4 day</name><value>lsr_d4</value></option> - <option><name>every 5 day</name><value>lsr_d5</value></option> - <option><name>every 6 day</name><value>lsr_d6</value></option> - <option><name>weekly at Monday</name><value>lsr_w1</value></option> - <option><name>weekly at Tuesday</name><value>lsr_w2</value></option> - <option><name>weekly at Wednesday</name><value>lsr_w3</value></option> - <option><name>weekly at Thursday</name><value>lsr_w4</value></option> - <option><name>weekly at Friday</name><value>lsr_w5</value></option> - <option><name>weekly at Saturday</name><value>lsr_w6</value></option> - <option><name>weekly at Sunday</name><value>lsr_w7</value></option> - <option><name>every 10 day</name><value>lsr_d10</value></option> - <option><name>every 15 day</name><value>lsr_d15</value></option> - <option><name>every 20 day</name><value>lsr_d20</value></option> - <option><name>every 25 day</name><value>lsr_d25</value></option> - <option><name>every 30 day</name><value>lsr_d30</value></option> - </options> - </field--> + <default_value>dns</default_value> + <options> + <option><name>IP</name><value>ip</value></option> + <option><name>Demo</name><value>demo</value></option> + <option><name>DNS</name><value>dns</value></option> + <option><name>Simple</name><value>simple</value></option> + <option><name>SMB</name><value>smb</value></option> + <option><name>Squidauth</name><value>squidauth</value></option> + </options> + </field> <field> - <fielddescr>Skip url</fielddescr> - <fieldname>lightsquid_skipurl</fieldname> + <fielddescr>Skip URL(s)</fielddescr> + <fieldname>lightsquid_skipurl</fieldname> <description> - If you want skip some sites from stat, example our local www server - Example, if you want skip LOCAL site, put it here - zdd.com|192.168.1.|cnn.com + <![CDATA[ + If you want to omit some sites from statistics (e.g., a local webserver), specify the URL(s) here.<br/> + Separate multiple entries by <strong>|</strong> character.<br/><br/> + Example: example.com|192.168.1.|example.net + ]]> </description> <type>textarea</type> <cols>60</cols> <rows>5</rows> </field> + <field> + <fielddescr>Refresh Scheduler</fielddescr> + <fieldname>lightsquid_refreshsheduler_time</fieldname> + <description> + <![CDATA[ + Select data refresh period. The reporting task will be executed every XX minutes/hours.<br/> + <strong>Legend:</strong> (!),(*) - use only with fast hardware; (+) - recommended values.<br/> + ]]> + </description> + <type>select</type> + <default_value>lhp_none</default_value> + <options> + <option><name>none</name><value>lhp_none</value></option> + <option><name>10min(!)</name><value>lhp_10m</value></option> + <option><name>20min(!)</name><value>lhp_20m</value></option> + <option><name>30min(*)</name><value>lhp_30m</value></option> + <option><name>40min(*)</name><value>lhp_40m</value></option> + <option><name>50min(+)</name><value>lhp_50m</value></option> + <option><name>60min(+)</name><value>lhp_60m</value></option> + <option><name>2h</name><value>lhp_2h</value></option> + <option><name>3h</name><value>lhp_3h</value></option> + <option><name>4h</name><value>lhp_4h</value></option> + <option><name>6h</name><value>lhp_6h</value></option> + <option><name>8h</name><value>lhp_8h</value></option> + <option><name>12h</name><value>lhp_12h</value></option> + <option><name>24h</name><value>lhp_24h</value></option> + </options> + </field> + <field> + <type>info</type> + <fielddescr>Manual Refresh</fielddescr> + <description> + <![CDATA[ + <input type="submit" name="refreshnow" id="refreshnow" value="Refresh now" /> will (re)parse today's entries only in Squid's current access.log.<br/><br/> + <input type="submit" name="refreshfull" id="refreshfull" value="Refresh full" /> will (re)parse all entries in all Squid's access logs, including the rotated ones. + <strong>Note: This may take long time to finish!</strong><br/><br/> + Press a button above to start background refresh (this will take some time).<br/> + ]]> + </description> + </field> </fields> - <custom_php_resync_config_command> - lightsquid_resync(); - </custom_php_resync_config_command> <custom_php_install_command> lightsquid_install(); - lightsquid_resync(); </custom_php_install_command> <custom_php_deinstall_command> lightsquid_deinstall(); </custom_php_deinstall_command> + <custom_php_resync_config_command> + <![CDATA[ + // Do not resync configuration on manual reports refresh + if ($_POST['refreshnow'] == "Refresh now" || $_POST['refreshfull'] == "Refresh full") { + return; + } + lightsquid_resync(); + ]]> + </custom_php_resync_config_command> + <custom_php_validation_command> + lightsquid_validate_input($_POST, $input_errors); + </custom_php_validation_command> </packagegui> diff --git a/config/lightsquid/sqstat.class.php b/config/lightsquid/sqstat.class.php index 88a5cfce..2f1dc9ba 100644 --- a/config/lightsquid/sqstat.class.php +++ b/config/lightsquid/sqstat.class.php @@ -1,133 +1,129 @@ <?php -/* $Id$ */ /* - sqstat.class.php - Squid Proxy Server realtime stat - - (c) Alex Samorukov, samm@os2.kiev.ua - modification by 2011 Serg Dvoriancev, dv_serg@mail.ru - Squid Proxy Server realtime stat - - part of pfSense (www.pfSense.com) - - 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. + sqstat.class.php + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006 Alex Samorukov <samm@os2.kiev.ua> + Copyright (C) 2011 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC + 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. */ - -// sqstat class +/* Squid Proxy Server realtime stats */ DEFINE('SQSTAT_VERSION', '1.20'); DEFINE('SQSTAT_SHOWLEN', 60); -class squidstat{ - var $fp; +class squidstat { + var $fp; - # conection - var $squidhost; - var $squidport; + // conection + var $squidhost; + var $squidport; - # hosts - var $hosts_file; + // hosts + var $hosts_file; var $hosts; - # versions + // versions var $server_version; var $sqstat_version; - # other - var $group_by; + // other + var $group_by; var $resolveip; var $autorefresh; var $use_sessions = false; - # cache manager + // cache manager var $cachemgr_passwd; - # errors + // errors var $errno; var $errstr; - function squidstat(){ - $this->sqstat_version = SQSTAT_VERSION; + function squidstat() { + $this->sqstat_version = SQSTAT_VERSION; - $this->squidhost = '127.0.0.1'; - $this->squidport = '3128'; + $this->squidhost = '127.0.0.1'; + $this->squidport = '3128'; - $this->group_by = 'host'; - $this->resolveip = true; - $this->hosts_file = ''; - $this->autorefresh = 0; - $this->cachemgr_passwd = ''; + $this->group_by = 'host'; + $this->resolveip = true; + $this->hosts_file = ''; + $this->autorefresh = 0; + $this->cachemgr_passwd = ''; - $errno = 0; - $errstr = ''; + $errno = 0; + $errstr = ''; - if (!function_exists("preg_match")) { $this->errorMsg(5, 'You need to install <a href="http://www.php.net/pcre/" target="_blank">PHP pcre extension</a> to run this script'); + if (!function_exists("preg_match")) { + $this->errorMsg(5, 'You need to install <a href="http://www.php.net/pcre/" target="_blank">PHP pcre extension</a> to run this script'); $this->showError(); exit(5); } // we need session support to gather avg. speed - if (function_exists("session_start")){ - $this->use_sessions=true; + if (function_exists("session_start")) { + $this->use_sessions = true; } - } - function formatXHTML($body, $refresh, $use_js = false){ - $text='<?xml version="1.0" encoding="UTF-8"?>'."\n". - '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n" - .'<html>' - .'<head>' - .'<link href="sqstat.css" rel="stylesheet" type="text/css"/>'; - if($refresh) $text.='<META HTTP-EQUIV=Refresh CONTENT="'.$refresh.'; URL='.$_SERVER["PHP_SELF"].'?refresh='.$refresh.'&config='.$GLOBALS["config"].'"/>'; - $text.='<title>SqStat '.SQSTAT_VERSION.'</title>' - .($use_js?'<script src="zhabascript.js" type="text/javascript"></script>':'').'</head>' - .($use_js?'<body onload="jsInit();"><div id="dhtmltooltip"></div><img id="dhtmlpointer" src="arrow.gif">':'<body>') - .$body.'</body></html>'; + function formatXHTML($body, $refresh, $use_js = false) { + $text = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" + .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n" + . '<html>' + . '<head>' + . '<link href="sqstat.css" rel="stylesheet" type="text/css"/>'; + if ($refresh) { + $text .= '<META HTTP-EQUIV=Refresh CONTENT="' . $refresh . '; URL=' . $_SERVER["PHP_SELF"] . '?refresh=' . $refresh . '&config=' . $GLOBALS["config"] . '"/>'; + } + $text .= '<title>SqStat ' . SQSTAT_VERSION . '</title>' . ($use_js ? '<script src="zhabascript.js" type="text/javascript"></script>' : '') . '</head>' + . ($use_js ? '<body onload="jsInit();"><div id="dhtmltooltip"></div><img id="dhtmlpointer" src="arrow.gif">' : '<body>') + . $body . '</body></html>'; return $text; } - function showError(){ - $text='<h1>SqStat error</h1>'. - '<h2 style="color:red">Error ('.$this->errno.'): '.$this->errstr.'</span>'; - echo $this->formatXHTML($text,0); + function showError() { + $text = '<h1>SqStat error</h1>' . '<h2 style="color:red">Error (' . $this->errno . ') : ' . $this->errstr . '</h2>'; + echo $this->formatXHTML($text, 0); } - function connect($squidhost, $squidport){ + function connect($squidhost, $squidport) { $this->fp = false; - # connecting to the squidhost + // connecting to the squidhost $this->fp = @fsockopen($squidhost, $squidport, $this->errno, $this->errstr, 10); if (!$this->fp) { - # failed to connect + // failed to connect return false; } return true; } - # based @ (c) moritz at barafranca dot com + // based @ (c) moritz at barafranca dot com function duration ($seconds) { - $takes_time = array(604800,86400,3600,60,0); - $suffixes = array("w","d","h","m","s"); + $takes_time = array(604800, 86400, 3600, 60, 0); + $suffixes = array("w", "d", "h", "m", "s"); $output = ""; - foreach ($takes_time as $key=>$val) { + foreach ($takes_time as $key => $val) { ${$suffixes[$key]} = ($val == 0) ? $seconds : floor(($seconds/$val)); $seconds -= ${$suffixes[$key]} * $val; if (${$suffixes[$key]} > 0) { @@ -145,31 +141,34 @@ class squidstat{ * @param int $bytes The number of bytes to format. Must be positive * @param string $format Optional. The output format for the string * @param string $force Optional. Force a certain unit. B|KB|MB|GB|TB - * @return string The formatted file size + * @return string The formatted file size */ - function filesize_format($bytes, $format = '', $force = '') - { + function filesize_format($bytes, $format = '', $force = '') { $force = strtoupper($force); $defaultFormat = '%01d %s'; - if (strlen($format) == 0) - $format = $defaultFormat; + if (strlen($format) == 0) { + $format = $defaultFormat; + } $bytes = max(0, (int) $bytes); $units = array('b', 'Kb', 'Mb', 'Gb', 'Tb', 'Pb'); $power = array_search($force, $units); - if ($power === false) - $power = $bytes > 0 ? floor(log($bytes)/log(1024)) : 0; + if ($power === false) { + $power = $bytes > 0 ? floor(log($bytes)/log(1024)) : 0; + } return sprintf($format, $bytes / pow(1024, $power), $units[$power]); } - function makeQuery($pass = ""){ + function makeQuery($pass = "") { $raw = array(); - # sending request - if(!$this->fp) - die("Please connect to server"); + // sending request + if (!$this->fp) { + die("Please connect to server"); + } $out = "GET cache_object://localhost/active_requests HTTP/1.0\r\n"; - if ($pass != "") - $out .= "Authorization: Basic ".base64_encode("cachemgr:$pass")."\r\n"; + if ($pass != "") { + $out .= "Authorization: Basic ". base64_encode("cachemgr:$pass") . "\r\n"; + } $out .= "\r\n"; fwrite($this->fp, $out); @@ -184,38 +183,56 @@ class squidstat{ return false; } - # parsing output; + // parsing output; $header = 1; $connection = 0; $parsed["server_version"] = "Unknown"; - foreach($raw as $key=>$v){ - # cutoff http header - if ($header==1 && $v=="") $header=0; + foreach ($raw as $key => $v) { + // cutoff http header + if ($header == 1 && $v == "") { + $header = 0; + } if ($header) { - if(substr(strtolower($v),0,7) == "server:") { # parsing server version - $parsed["server_version"] = substr($v,8); + if (substr(strtolower($v), 0, 7) == "server:") { + // parsing server version + $parsed["server_version"] = substr($v, 8); } - } - else { - if(substr($v,0,11) == "Connection:") { # parsing connection - $connection = substr($v,12); + } else { + if (substr($v, 0, 11) == "Connection:") { + // parsing connection + $connection = substr($v, 12); } if ($connection) { - # username field is avaible in Squid 2.6 stable - # peer changed to remote in Squid 3.2 or later - # me changed to local in Squid 3.2 or later - if(substr($v,0,9) == "username ") $parsed["con"][$connection]["username"] = substr($v, 9); - if(substr($v,0,7) == "remote:") $parsed["con"][$connection]["peer"] = substr($v, 8); - if(substr($v,0,5) == "peer:") $parsed["con"][$connection]["peer"] = substr($v, 6); - if(substr($v,0,6) == "local:") $parsed["con"][$connection]["me"] = substr($v, 7); - if(substr($v,0,3) == "me:") $parsed["con"][$connection]["me"] = substr($v, 4); - if(substr($v,0,4) == "uri ") $parsed["con"][$connection]["uri"] = substr($v, 4); - if(substr($v,0,10) == "delay_pool") $parsed["con"][$connection]["delay_pool"] = substr($v, 11); + /* username field is avaible in Squid 2.6+ + * peer changed to remote in Squid 3.2+ + * me changed to local in Squid 3.2+ + */ + if (substr($v, 0, 9) == "username ") { + $parsed["con"][$connection]["username"] = substr($v, 9); + } + if (substr($v, 0, 7) == "remote:") { + $parsed["con"][$connection]["peer"] = substr($v, 8); + } + if (substr($v, 0, 5) == "peer:") { + $parsed["con"][$connection]["peer"] = substr($v, 6); + } + if (substr($v, 0, 6) == "local:") { + $parsed["con"][$connection]["me"] = substr($v, 7); + } + if (substr($v, 0, 3) == "me:") { + $parsed["con"][$connection]["me"] = substr($v, 4); + } + if (substr($v, 0, 4) == "uri ") { + $parsed["con"][$connection]["uri"] = substr($v, 4); + } + if (substr($v, 0, 10) == "delay_pool") { + $parsed["con"][$connection]["delay_pool"] = substr($v, 11); + } if (preg_match('/out.offset \d+, out.size (\d+)/', $v, $matches)) { $parsed["con"][$connection]["bytes"] = $matches[1]; } - if (preg_match('/start \d+\.\d+ \((\d+).\d+ seconds ago\)/', $v, $matches)){ + if (preg_match('/start \d+\.\d+ \((\d+).\d+ seconds ago\)/', $v, $matches)) { $parsed["con"][$connection]["seconds"] = $matches[1]; } } @@ -225,7 +242,7 @@ class squidstat{ } function implode_with_keys($array, $glue) { - foreach ($array as $key => $v){ + foreach ($array as $key => $v) { $ret[] = $key . '=' . htmlspecialchars($v); } return implode($glue, $ret); @@ -233,96 +250,107 @@ class squidstat{ function makeHtmlReport($data, $resolveip = false, $hosts_array = array(), $use_js = true) { global $group_by; - if($this->use_sessions){ + if ($this->use_sessions) { session_name('SQDATA'); session_start(); } $total_avg = $total_curr = 0; // resort data array - $users=array(); - switch($group_by){ + $users = array(); + switch ($group_by) { case "host": - $group_by_name="Host"; - $group_by_key='return $ip;'; - break; + $group_by_name="Host"; + $group_by_key='return $ip;'; + break; case "username": - $group_by_name="User"; - $group_by_key='return $v["username"];'; - break; + $group_by_name="User"; + $group_by_key='return $v["username"];'; + break; default: - die("wrong group_by!"); + die("wrong group_by!"); } - foreach($data["con"] as $key => $v){ - if(substr($v["uri"],0,13)=="cache_object:") continue; // skip myself - $ip=substr($v["peer"],0,strpos($v["peer"],":")); - if(isset($hosts_array[$ip])){ - $ip=$hosts_array[$ip]; - } - // i use ip2long() to make ip sorting work correctly - elseif($resolveip){ - $hostname=gethostbyaddr($ip); - if($hostname==$ip) $ip=ip2long($ip);// resolve failed - else $ip=$hostname; + foreach ($data["con"] as $key => $v) { + if (substr($v["uri"], 0, 13) == "cache_object:") { + continue; // skip myself } - else{ - $ip=ip2long(substr($v["peer"],0,strpos($v["peer"],":"))); + $ip = substr($v["peer"], 0, strpos($v["peer"], ":")); + if (isset($hosts_array[$ip])) { + $ip = $hosts_array[$ip]; + // use ip2long() to make ip sorting work correctly + } elseif ($resolveip) { + $hostname = gethostbyaddr($ip); + if ($hostname == $ip) { + $ip = ip2long($ip); // resolve failed + } else { + $ip = $hostname; + } + } else { + $ip = ip2long(substr($v["peer"], 0, strpos($v["peer"],":"))); } $v['connection'] = $key; - if(!isset($v["username"])) $v["username"]="N/A"; - $users[eval($group_by_key)][]=$v; + if (!isset($v["username"])) { + $v["username"] = "N/A"; + } + $users[eval($group_by_key)][] = $v; } ksort($users); - $refresh=0; - if(isset($_GET["refresh"]) && !isset($_GET["stop"])) $refresh=(int)$_GET["refresh"]; - $text=''; - if(count($GLOBALS["configs"])==1) $servers=$GLOBALS["squidhost"].':'.$GLOBALS["squidport"]; - else{ - $servers='<select onchange="this.form.submit();" name="config">'; - foreach ($GLOBALS["configs"] as $key=>$v){ - $servers.='<option '.($GLOBALS["config"]==$key?' selected="selected" ':'').' value="'.$key.'">'.htmlspecialchars($v).'</option>'; + $refresh = 0; + if (isset($_GET["refresh"]) && !isset($_GET["stop"])) { + $refresh = (int)$_GET["refresh"]; + } + $text = ''; + if (count($GLOBALS["configs"]) == 1) { + $servers = $GLOBALS["squidhost"] . ':' . $GLOBALS["squidport"]; + } else { + $servers = '<select onchange="this.form.submit();" name="config">'; + foreach ($GLOBALS["configs"] as $key => $v) { + $servers .= '<option ' . ($GLOBALS["config"] == $key ? ' selected="selected" ' : '') . ' value="' . $key . '">' . htmlspecialchars($v) . '</option>'; } - $servers.='</select>'; + $servers .= '</select>'; } - $text.='<div class="header"><form method="get" action="'.$_SERVER["PHP_SELF"].'">'. - 'Squid RealTime stat for the '.$servers.' proxy server ('.$data["server_version"].').<br/>'. - 'Auto refresh: <input name="refresh" type="text" size="4" value="'.$refresh.'"/> sec. <input type="submit" value="Update"/> <input name="stop" type="submit" value="Stop"/> Created at: <tt>'.date("h:i:s d/m/Y").'</tt><br/>'. - '</div>'. - '<table class="result" align="center" width="100%" border="0">'. - '<tr>'. - '<th>'.$group_by_name.'</th><th>URI</th>'. - ($this->use_sessions?'<th>Curr. Speed</th><th>Avg. Speed</th>':''). - '<th>Size</th><th>Time</th>'. - '</tr>'; - $ausers=$acon=0; + $text .= '<div class="header"><form method="get" action="' . $_SERVER["PHP_SELF"] . '">' + . 'Squid RealTime stat for the ' . $servers . ' proxy server (' . $data["server_version"] . ').<br/>' + . 'Auto refresh: <input name="refresh" type="text" size="4" value="' . $refresh . '"/> sec. <input type="submit" value="Update"/> <input name="stop" type="submit" value="Stop"/> Created at: <tt>' . date("h:i:s d/m/Y") . '</tt><br/>' + . '</div>' + . '<table class="result" align="center" width="100%" border="0">' + . '<tr>' + . '<th>' . $group_by_name . '</th><th>URI</th>' + . ($this->use_sessions ? '<th>Curr. Speed</th><th>Avg. Speed</th>' : '') + . '<th>Size</th><th>Time</th>' + . '</tr>'; + $ausers = $acon = 0; unset($session_data); if (isset($_SESSION['time']) && ((time() - $_SESSION['time']) < 3*60) && isset($_SESSION['sqdata']) && is_array($_SESSION['sqdata'])) { - //only if the latest data was less than 3 minutes ago + // only if the latest data was less than 3 minutes ago $session_data = $_SESSION['sqdata']; } - $table=''; - foreach($users as $key=>$v){ + $table = ''; + foreach ($users as $key => $v) { $ausers++; - $table.='<tr><td style="border-right:0;" colspan="2"><b>'.(is_int($key)?long2ip($key):$key).'</b></td>'. - '<td style="border-left:0;" colspan="5"> </td></tr>'; - $user_avg = $user_curr = $con_color = 0; - foreach ($v as $con){ - if(substr($con["uri"],0,7)=="http://" || substr($con["uri"],0,6)=="ftp://"){ - if(strlen($con["uri"])>SQSTAT_SHOWLEN) $uritext=htmlspecialchars(substr($con["uri"],0,SQSTAT_SHOWLEN)).'</a> ....'; - else $uritext=htmlspecialchars($con["uri"]).'</a>'; - $uri='<a target="_blank" href="'.htmlspecialchars($con["uri"]).'">'.$uritext; + $table .= '<tr><td style="border-right:0;" colspan="2"><b>' . (is_int($key) ? long2ip($key) : $key) . '</b></td>' + . '<td style="border-left:0;" colspan="5"> </td></tr>'; + $user_avg = $user_curr = $con_color = 0; + foreach ($v as $con) { + if (substr($con["uri"], 0, 7) == "http://" || substr($con["uri"], 0, 6) == "ftp://") { + if (strlen($con["uri"]) > SQSTAT_SHOWLEN) { + $uritext = htmlspecialchars(substr($con["uri"], 0, SQSTAT_SHOWLEN)) . '</a> ....'; + } else { + $uritext = htmlspecialchars($con["uri"]) . '</a>'; + } + $uri = '<a target="_blank" href="' . htmlspecialchars($con["uri"]) . '">' . $uritext; + } else { + $uri = htmlspecialchars($con["uri"]); } - else $uri=htmlspecialchars($con["uri"]); $acon++; - //speed stuff + // speed stuff $con_id = $con['connection']; $is_time = time(); - $curr_speed=0; - $avg_speed=0; - if (isset($session_data[$con_id]) && $con_data = $session_data[$con_id] ) { - // if we have info about current connection, we do analyze its data - // current speed + $curr_speed = 0; + $avg_speed = 0; + if (isset($session_data[$con_id]) && $con_data == $session_data[$con_id]) { + // if we have info about current connection, we do analyze its data current speed $was_time = $con_data['time']; $was_size = $con_data['size']; if ($was_time && $was_size) { @@ -337,7 +365,7 @@ class squidstat{ $curr_speed = $con['bytes'] / 1024; } - //avg speed + // avg speed $avg_speed = $con['bytes'] / 1024; if ($con['seconds'] > 0) { $avg_speed /= $con['seconds']; @@ -347,241 +375,244 @@ class squidstat{ $new_data[$con_id]['time'] = $is_time; $new_data[$con_id]['size'] = $con['bytes']; - //sum speeds + // sum speeds $total_avg += $avg_speed; $user_avg += $avg_speed; $total_curr += $curr_speed; $user_curr += $curr_speed; - if($use_js) $js='onMouseout="hideddrivetip()" onMouseover="ddrivetip(\''.$this->implode_with_keys($con,'<br/>').'\')"'; - else $js=''; - $table.='<tr'.( (++$con_color % 2 == 0) ? ' class="odd"' : '' ).'><td id="white"></td>'. - '<td nowrap '.$js.' width="80%" >'.$uri.'</td>'; - if($this->use_sessions){ - $table .= '<td nowrap align="right">'.( (round($curr_speed, 2) > 0) ? sprintf("%01.2f KB/s", $curr_speed) : '' ).'</td>'. - '<td nowrap align="right">'.( (round($avg_speed, 2) > 0) ? sprintf("%01.2f KB/s", $avg_speed) : '' ). '</td>'; + if ($use_js) { + $js = 'onMouseout="hideddrivetip()" onMouseover="ddrivetip(\'' . $this->implode_with_keys($con, '<br/>') . '\')"'; + } else { + $js = ''; + } + $table .= '<tr' . ( (++$con_color % 2 == 0) ? ' class="odd"' : '' ) . '><td id="white"></td>' + . '<td nowrap ' . $js . ' width="80%" >' . $uri . '</td>'; + if ($this->use_sessions) { + $table .= '<td nowrap align="right">' . ( (round($curr_speed, 2) > 0) ? sprintf("%01.2f KB/s", $curr_speed) : '' ) . '</td>' + . '<td nowrap align="right">' . ( (round($avg_speed, 2) > 0) ? sprintf("%01.2f KB/s", $avg_speed) : '' ) . '</td>'; } - $table .= '<td nowrap align="right">'.$this->filesize_format($con["bytes"]).'</td>'. - '<td nowrap align="right">'.$this->duration($con["seconds"],"short").'</td>'. - '</tr>'; + $table .= '<td nowrap align="right">' . $this->filesize_format($con["bytes"]) . '</td>' + . '<td nowrap align="right">' . $this->duration($con["seconds"], "short") . '</td>' + . '</tr>'; } - if($this->use_sessions){ - $table.=sprintf("<tr><td colspan=\"2\"></td><td align=\"right\" id=\"highlight\">%01.2f KB/s</td><td align=\"right\" id=\"highlight\">%01.2f KB/s</td><td colspan=\"2\"></td>", - $user_curr, $user_avg); + if ($this->use_sessions) { + $table .= sprintf("<tr><td colspan=\"2\"></td><td align=\"right\" id=\"highlight\">%01.2f KB/s</td><td align=\"right\" id=\"highlight\">%01.2f KB/s</td><td colspan=\"2\"></td>", $user_curr, $user_avg); } } $_SESSION['time'] = time(); - if(isset($new_data)) $_SESSION['sqdata'] = $new_data; - $stat_row=''; - if($this->use_sessions){ - $stat_row.=sprintf("<tr class=\"total\"><td><b>Total:</b></td><td align=\"right\" colspan=\"5\"><b>%d</b> users and <b>%d</b> connections @ <b>%01.2f/%01.2f</b> KB/s (CURR/AVG)</td></tr>", - $ausers, $acon, $total_curr, $total_avg); + if (isset($new_data)) { + $_SESSION['sqdata'] = $new_data; } - else { - $stat_row.=sprintf("<tr class=\"total\"><td><b>Total:</b></td><td align=\"right\" colspan=\"5\"><b>%d</b> users and <b>%d</b> connections</td></tr>", - $ausers, $acon); + $stat_row = ''; + if ($this->use_sessions) { + $stat_row .= sprintf("<tr class=\"total\"><td><b>Total:</b></td><td align=\"right\" colspan=\"5\"><b>%d</b> users and <b>%d</b> connections @ <b>%01.2f/%01.2f</b> KB/s (CURR/AVG)</td></tr>", $ausers, $acon, $total_curr, $total_avg); + } else { + $stat_row .= sprintf("<tr class=\"total\"><td><b>Total:</b></td><td align=\"right\" colspan=\"5\"><b>%d</b> users and <b>%d</b> connections</td></tr>", $ausers, $acon); } - if($ausers==0){ - $text.='<tr><td colspan=6><b>No active connections</b></td></tr>'; + if ($ausers == 0) { + $text .= '<tr><td colspan=6><b>No active connections</b></td></tr>'; + } else { + $text .= $stat_row . $table . $stat_row; + } + $text .= '</table>' . '<p class="copyleft">© <a href="mailto:samm@os2.kiev.ua?subject=SqStat ' . SQSTAT_VERSION . '">Alex Samorukov</a>, 2006</p>'; + return $this->formatXHTML($text, $refresh, $use_js); + } + + function parseRequest($data, $group_by = 'host', $resolveip = false) { + $parsed = array(); + if ($this->use_sessions) { + session_name('SQDATA'); + session_start(); + } + + // resort data array + $users = array(); + switch ($group_by) { + case "username": + $group_by_name = "User"; + $group_by_key = "username"; + break; + case "host": + default: + $group_by_name = "Host"; + $group_by_key = "peer"; + break; + } + + // resolve IP & group + foreach ($data["con"] as $key => $v) { + // skip myself + if (substr($v["uri"], 0, 13) == "cache_object:") { + continue; + } + + $ip = substr($v["peer"], 0, strpos($v["peer"], ":")); + $v["peer"] = $ip; + + // name from hosts + if (isset($this->hosts[$ip])) { + $ip = $this->hosts[$ip]; + } elseif ($resolveip) { + // use ip2long() to make ip sorting work correctly + $hostname = gethostbyaddr($ip); + if ($hostname == $ip) { + $ip = ip2long($ip); // resolve failed. use (ip2long) key + } else { + $ip = $hostname; + } + } else { + $ip = ip2long(substr($v["peer"], 0, strpos($v["peer"], ":"))); + } + $v['con_id'] = $key; + $v["username"] = isset($v["username"]) ? $v["username"] : "N/A"; + + // users [key => conn_array] + $users[$v[$group_by_key]][] = $v; + } + ksort($users); + + unset($session_data); + if (isset($_SESSION['time']) && ((time() - $_SESSION['time']) < 3*60) && isset($_SESSION['sqdata']) && is_array($_SESSION['sqdata'])) { + // only if the latest data was less than 3 minutes ago + $session_data = $_SESSION['sqdata']; + } + + // users count & con count + $ausers = $acon = 0; + $total_avg = $total_curr = 0; + foreach ($users as $key => $v) { + $ausers++; + + $user_avg = $user_curr = $con_color = 0; + foreach ($v as $con_key => $con) { + $cres = array(); + $acon++; + + $uritext = $con["uri"]; + if (substr($con["uri"], 0, 7) == "http://" || substr($con["uri"], 0, 6) == "ftp://") { + if (strlen($uritext) > SQSTAT_SHOWLEN) { + $uritext = htmlspecialchars(substr($uritext, 0, SQSTAT_SHOWLEN)) . ' ....'; + } + } else { + $uritext = htmlspecialchars($uritext); + } + $cres['uritext'] = $uritext; + $cres['uri'] = $con["uri"]; + + // speed stuff + $con_id = $con['connection']; + $is_time = time(); + $curr_speed = $avg_speed = 0; + if (isset($session_data[$con_id]) && $con_data == $session_data[$con_id]) { + // if we have info about current connection, we do analyze its data current speed + $was_time = $con_data['time']; + $was_size = $con_data['size']; + if ($was_time && $was_size) { + $delta = $is_time - $was_time; + if ($delta == 0) { + $delta = 1; + } + if ($con['bytes'] >= $was_size) { + $curr_speed = ($con['bytes'] - $was_size) / 1024 / $delta; + } + } else { + $curr_speed = $con['bytes'] / 1024; + } + + // avg speed + $avg_speed = $con['bytes'] / 1024; + if ($con['seconds'] > 0) { + $avg_speed /= $con['seconds']; + } + } + $cres['cur_speed'] = $curr_speed; + $cres['avg_speed'] = $avg_speed; + $cres['seconds'] = $con["seconds"]; + $cres['bytes'] = $con["bytes"]; + + // grouped parsed[key => conn_key] + $parsed['users'][$key]['con'][$con_key] = $cres; + + // for sessions + $new_data[$con_id]['time'] = $is_time; + $new_data[$con_id]['size'] = $con['bytes']; + + // sum speeds + $total_avg += $avg_speed; + $user_avg += $avg_speed; + $total_curr += $curr_speed; + $user_curr += $curr_speed; + } + + // total per user + $parsed['users'][$key]['user_curr'] = $user_curr; + $parsed['users'][$key]['user_avg'] = $user_avg; } - else { - $text.=$stat_row.$table.$stat_row; + + // total info + $parsed['ausers'] = $ausers; + $parsed['acon'] = $acon; + $parsed['total_avg'] = $total_avg; + $parsed['total_curr'] = $total_curr; + + // update session info + $_SESSION['time'] = time(); + if (isset($new_data)) { + $_SESSION['sqdata'] = $new_data; } - $text .= '</table>'. - '<p class="copyleft">© <a href="mailto:samm@os2.kiev.ua?subject=SqStat '.SQSTAT_VERSION.'">Alex Samorukov</a>, 2006</p>'; - return $this->formatXHTML($text,$refresh,$use_js); + + return $parsed; } - function parseRequest($data, $group_by = 'host', $resolveip = false) { $parsed = array(); - if ($this->use_sessions) { - session_name('SQDATA'); - session_start(); - } - - # resort data array - $users = array(); - switch ($group_by) { - case "username": - $group_by_name = "User"; - $group_by_key = "username"; - break; - case "host": - default: - $group_by_name = "Host"; - $group_by_key = "peer"; - break; - } - - # resolve IP & group - foreach ($data["con"] as $key => $v) { # skip myself - if (substr($v["uri"], 0, 13) == "cache_object:") continue; - - $ip = substr($v["peer"], 0, strpos($v["peer"], ":")); - $v["peer"] = $ip; - - # name from hosts - if (isset($this->hosts[$ip])) { - $ip = $this->hosts[$ip]; - } - else - # i use ip2long() to make ip sorting work correctly - if ($resolveip) { - $hostname = gethostbyaddr($ip); - if ($hostname == $ip) - $ip = ip2long($ip); # resolve failed. use (ip2long) key - else $ip = $hostname; - } - else { - $ip = ip2long(substr($v["peer"], 0, strpos($v["peer"], ":"))); - } - $v['con_id'] = $key; - $v["username"] = isset($v["username"]) ? $v["username"] : "N/A"; - - # users [key => conn_array] - $users[$v[$group_by_key]][] = $v; - } - ksort($users); - - unset($session_data); - if (isset($_SESSION['time']) && ((time() - $_SESSION['time']) < 3*60) && - isset($_SESSION['sqdata']) && is_array($_SESSION['sqdata'])) { - # only if the latest data was less than 3 minutes ago - $session_data = $_SESSION['sqdata']; - } - - # users count & con cont - $ausers = $acon = 0; - $total_avg = $total_curr = 0; - foreach ($users as $key => $v) { $ausers++; - - $user_avg = $user_curr = $con_color = 0; - foreach ($v as $con_key => $con){ $cres = array(); - $acon++; - - $uritext = $con["uri"]; - if (substr($con["uri"], 0, 7) == "http://" || substr($con["uri"], 0, 6) == "ftp://") { - if (strlen($uritext) > SQSTAT_SHOWLEN) - $uritext = htmlspecialchars(substr($uritext, 0, SQSTAT_SHOWLEN)) . ' ....'; - } - else $uritext = htmlspecialchars($uritext); - $cres['uritext'] = $uritext; - $cres['uri'] = $con["uri"]; - - # speed stuff - $con_id = $con['connection']; - $is_time = time(); - $curr_speed = $avg_speed = 0; - if (isset($session_data[$con_id]) && $con_data = $session_data[$con_id] ) { - # if we have info about current connection, we do analyze its data - # current speed - $was_time = $con_data['time']; - $was_size = $con_data['size']; - if ($was_time && $was_size) { - $delta = $is_time - $was_time; - if ($delta == 0) { - $delta = 1; - } - if ($con['bytes'] >= $was_size) { - $curr_speed = ($con['bytes'] - $was_size) / 1024 / $delta; - } - } else { - $curr_speed = $con['bytes'] / 1024; - } - - # avg speed - $avg_speed = $con['bytes'] / 1024; - if ($con['seconds'] > 0) { - $avg_speed /= $con['seconds']; - } - } - $cres['cur_speed'] = $curr_speed; - $cres['avg_speed'] = $avg_speed; - $cres['seconds'] = $con["seconds"]; - $cres['bytes'] = $con["bytes"]; - - # groupped parsed[key => conn_key] - $parsed['users'][$key]['con'][$con_key] = $cres; - - # for sessions - $new_data[$con_id]['time'] = $is_time; - $new_data[$con_id]['size'] = $con['bytes']; - - # sum speeds - $total_avg += $avg_speed; - $user_avg += $avg_speed; - $total_curr += $curr_speed; - $user_curr += $curr_speed; - } - - # total per user - $parsed['users'][$key]['user_curr'] = $user_curr; - $parsed['users'][$key]['user_avg'] = $user_avg; - } - - # total info - $parsed['ausers'] = $ausers; - $parsed['acon'] = $acon; - $parsed['total_avg'] = $total_avg; - $parsed['total_curr'] = $total_curr; - - # update session info - $_SESSION['time'] = time(); - if (isset($new_data)) $_SESSION['sqdata'] = $new_data; - - return $parsed; + function errorMsg($errno, $errstr) { + $this->errno = $errno; + $this->errstr = $errstr; } - function errorMsg($errno, $errstr) - { $this->errno = $errno; - $this->errstr = $errstr; + function load_hosts() { + // loading hosts file + $hosts_array = array(); + + if (!empty($this->hosts_file)) { + if (is_file($this->hosts_file)) { + $handle = @fopen($this->hosts_file, "r"); + if ($handle) { + while (!feof($handle)) { + $buffer = fgets($handle, 4096); + unset($matches); + if (preg_match('/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[ \t]+(.+)$/i', $buffer, $matches)) { + $hosts_array[$matches[1]]=$matches[2]; + } + } + fclose($handle); + } + $this->hosts = $hosts_array; + } else { + // error + $this->errorMsg(4, "Hosts file not found. Cant read <tt>'{$this->hosts_file}'</tt>."); + return $this->errno; + } + } + + return 0; } - function load_hosts() - { - # loading hosts file - $hosts_array = array(); - - if (!empty($this->hosts_file)) { - if (is_file($this->hosts_file)) { - $handle = @fopen($this->hosts_file, "r"); - if ($handle) { - while (!feof($handle)) { - $buffer = fgets($handle, 4096); - unset($matches); - if (preg_match('/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[ \t]+(.+)$/i', $buffer, $matches)) { - $hosts_array[$matches[1]]=$matches[2]; - } - } - fclose($handle); - } - $this->hosts = $hosts_array; - } - else { - #error - $this->errorMsg(4, "Hosts file not found. Cant read <tt>'{$this->hosts_file}'</tt>."); - return $this->errno; - } - } - - return 0; - } - - function query_exec() - { - $data = ""; - - $this->server_version = '(unknown)'; - if ($this->connect($this->squidhost, $this->squidport)) { - $data = $this->makeQuery($this->cachemgr_passwd); - if ($this->errno == 0) { - $this->server_version = $data['server_version']; - $data = $this->parseRequest($data, 'host', true); - } - } - - return $data; - } + function query_exec() { + $data = ""; + + $this->server_version = '(unknown)'; + if ($this->connect($this->squidhost, $this->squidport)) { + $data = $this->makeQuery($this->cachemgr_passwd); + if ($this->errno == 0) { + $this->server_version = $data['server_version']; + $data = $this->parseRequest($data, 'host', true); + } + } + + return $data; + } } ?> diff --git a/config/lightsquid/sqstat.css b/config/lightsquid/sqstat.css index 7575933e..c29adad2 100644 --- a/config/lightsquid/sqstat.css +++ b/config/lightsquid/sqstat.css @@ -1,68 +1,73 @@ /* "connections" table */ -TABLE.result{ - border:1px solid #ccccdd;border-collapse:collapse; +table.result { + border: 1px solid #ccccdd; + border-collapse: collapse; } -TABLE.result TH{ - font-family: Verdana;font-size:14px; +table.result th { + font-family: Verdana; + font-size: 14px; } -TABLE.result TD{ - font-family: Verdana;font-size:11px;border:1px solid #c0c0c0;padding:2px; +table.result td { + font-family: Verdana; + font-size: 11px; + border: 1px solid #c0c0c0; + padding: 2px; } -TABLE.result TR.total TD{ - background-color:#DCDAD5; +table.result tr.total td { + background-color: #DCDAD5; } - -TABLE.result TH{ - background-color:#ccccdd; - white-space: nowrap; padding: 0px 2px; +table.result th { + background-color: #ccccdd; + white-space: nowrap; + padding: 0px 2px; } - -TABLE.result tr.odd td { - background-color: #eef; +table.result tr.odd td { + background-color: #eef; } -TABLE.result tr.odd td#white { - background-color: #fff; +table.result tr.odd td#white { + background-color: #fff; } -TABLE.result td#highlight { - background-color: #e9e9e9; +table.result td#highlight { + background-color: #e9e9e9; } - /* top header */ -DIV.header{ - border:3px solid #ccccdd;margin-bottom:10px;padding:3px; - font-family: Verdana;font-size:12pt; +div.header { + border: 3px solid #ccccdd; + margin-bottom: 10px; + padding: 3px; + font-family: Verdana; + font-size: 12pt; } -.copyleft,SELECT{ - font-family: Verdana;font-size:10px; +.copyleft, select { + font-family: Verdana; + font-size: 10px; } -.copyleft A{ - text-decoration:none +.copyleft a { + text-decoration: none } -.copyleft A:HOVER{ - text-decoration:underline +.copyleft a:hover { + text-decoration: underline } -FORM{ - margin:0;padding:0; +form { + margin: 0; + padding: 0; } - -#dhtmltooltip{ - position: absolute; - /* width: 350px; */ - border: 2px solid black; - padding: 2px; - background-color: lightyellow; - visibility: hidden; - z-index: 100; - font-family: Verdana; font-size: 10px; +#dhtmltooltip { + position: absolute; + /* width: 350px; */ + + border: 2px solid black; + padding: 2px; + background-color: lightyellow; + visibility: hidden; + z-index: 100; + font-family: Verdana; + font-size: 10px; } - - -#dhtmlpointer{ - position:absolute; - left: -300px; - z-index: 101; - visibility: hidden; +#dhtmlpointer { + position: absolute; + left: -300px; + z-index: 101; + visibility: hidden; } - - diff --git a/config/lightsquid/sqstat.php b/config/lightsquid/sqstat.php index 7b12b970..5d3a0e83 100644 --- a/config/lightsquid/sqstat.php +++ b/config/lightsquid/sqstat.php @@ -1,417 +1,385 @@ <?php -/* $Id$ */ /* - sqstat.php - Squid Proxy Server realtime stat - - (c) Alex Samorukov, samm@os2.kiev.ua - modification by 2011 Serg Dvoriancev, dv_serg@mail.ru - - part of pfSense (www.pfSense.com) - - 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. + sqstat.php + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006 Alex Samorukov <samm@os2.kiev.ua> + Copyright (C) 2011 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC + 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. */ - -/* -*** sqstat - Squid Proxy Server realtime stat *** -(c) Alex Samorukov, samm@os2.kiev.ua -*/ - +/* Squid Proxy Server realtime stats */ require_once('guiconfig.inc'); require_once('sqstat.class.php'); -# init +// init $squidclass = new squidstat(); -# ------------------------------------------------------------------------------ -# Requests -# ------------------------------------------------------------------------------ - -# AJAX responce -if ($_REQUEST['getactivity']) -{ - header("Content-type: text/javascript"); - echo sqstat_AJAX_response( $_REQUEST ); - exit; +/* + * Requests + */ + +/* AJAX response */ +if ($_REQUEST['getactivity']) { + header("Content-type: text/javascript"); + echo sqstat_AJAX_response( $_REQUEST ); + exit; } -# ------------------------------------------------------------------------------ -# HTML Page -# ------------------------------------------------------------------------------ +/* + * HTML Page + */ -$pgtitle = "Proxy Squid: Realtime stat (sqstat)"; +$pgtitle = "Squid Proxy Server: Realtime Stats (SQStat)"; require_once("head.inc"); -$csrf_token= csrf_get_tokens(); +$csrf_token = csrf_get_tokens(); ?> -<link href="sqstat.css" rel="stylesheet" type="text/css"/> +<link href="sqstat.css" rel="stylesheet" type="text/css"/> <script type="text/javascript" src="/javascript/scriptaculous/prototype.js"></script> <script type="text/javascript" src="zhabascript.js"></script> -<!-- Ajax Script --> +<!-- AJAX script --> <script type="text/javascript"> - +//<![CDATA[ var intervalID = 0; function el(id) { - return document.getElementById(id); + return document.getElementById(id); } function getactivity(action) { - var url = "<?php echo ($_SERVER["PHP_SELF"]); ?>"; - var pars = "getactivity=yes" + "<? echo '&__csrf_magic='.$csrf_token ?>"; - - var myAjax = new Ajax.Request( url, - { - method: 'post', - parameters: pars, - onComplete: activitycallback - }); + var url = "<?php echo ($_SERVER["PHP_SELF"]); ?>"; + var pars = "getactivity=yes" + "<? echo '&__csrf_magic='.$csrf_token ?>"; + + var myAjax = new Ajax.Request(url, { + method: 'post', + parameters: pars, + onComplete: activitycallback + }); } function activitycallback(transport) { - - if (200 == transport.status) { - result = transport.responseText; - } + if (200 == transport.status) { + result = transport.responseText; + } } function update_start() { - var cmax = parseInt(el('refresh').value); + var cmax = parseInt(el('refresh').value); - update_stop(); + update_stop(); - if (cmax > 0) { - intervalID = window.setInterval('getactivity();', cmax * 1000); - } + if (cmax > 0) { + intervalID = window.setInterval('getactivity();', cmax * 1000); + } } function update_stop() { - window.clearInterval(intervalID); - intervalID = 0; + window.clearInterval(intervalID); + intervalID = 0; } // pre-call window.setTimeout('update_start()', 150); +//]]> </script> -<!-- HTML --> - -<!-- begin --> +<!-- HTML start --> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> <?php - # prepare page data - $data = ''; - sqstat_loadconfig(); - if (sqstat_loadconfig() == 0) { - $data = $squidclass->query_exec(); - } - - if ($squidclass->errno == 0) { - $data = sqstat_resultHTML($data); - } - else { - # error - $data = sqstat_errorHTML(); - } + // Prepare page data + $data = ''; + sqstat_loadconfig(); + if (sqstat_loadconfig() == 0) { + $data = $squidclass->query_exec(); + } + + if ($squidclass->errno == 0) { + $data = sqstat_resultHTML($data); + } else { + // error + $data = sqstat_errorHTML(); + } ?> -<!-- form --> -<div id="sqstat_header" class="header" > - <?php echo ( sqstat_headerHTML() ); ?> +<!-- Form --> +<div id="sqstat_header" class="header"> + <?php echo ( sqstat_headerHTML() ); ?> </div> -<!-- result table --> +<!-- Result table --> <div id="sqstat_result" class="result"> - <?php echo ($data); ?> + <?php echo ($data); ?> </div> -<!-- end --> +<!-- HTML end --> <?php include("fend.inc"); ?> </body> </html> + <?php -# ------------------------------------------------------------------------------ -# Functions -# ------------------------------------------------------------------------------ +/* + * Functions + */ -function sqstat_AJAX_response( $request ) -{ - global $squidclass, $data; - $res = ''; +function sqstat_AJAX_response( $request ) { + global $squidclass, $data; + $res = ''; - if (sqstat_loadconfig() != 0) { - return sqstat_AJAX_error(sqstat_errorHTML()); - } + if (sqstat_loadconfig() != 0) { + return sqstat_AJAX_error(sqstat_errorHTML()); + } - # Actions - $data = $squidclass->query_exec(); + // Actions + $data = $squidclass->query_exec(); - $ver = sqstat_serverInfoHTML(); - $res .= "el('sqstat_serverver').innerHTML = '$ver';"; + $ver = sqstat_serverInfoHTML(); + $res .= "el('sqstat_serverver').innerHTML = '$ver';"; - $time = date("h:i:s d/m/Y"); - $res .= "el('sqstat_updtime').innerHTML = '$time';"; + $time = date("h:i:s d/m/Y"); + $res .= "el('sqstat_updtime').innerHTML = '$time';"; - $data = sqstat_resultHTML( $data ); - if ($squidclass->errno == 0) { - $data = sqstat_AJAX_prep($data); - $res .= "el('sqstat_result').innerHTML = '$data';"; - } - else { - # error - $res .= sqstat_AJAX_error(sqstat_errorHTML()); - } + $data = sqstat_resultHTML( $data ); + if ($squidclass->errno == 0) { + $data = sqstat_AJAX_prep($data); + $res .= "el('sqstat_result').innerHTML = '$data';"; + } else { + // error + $res .= sqstat_AJAX_error(sqstat_errorHTML()); + } - return $res; + return $res; } -function sqstat_AJAX_prep($text) -{ - $text = str_replace("'", "\'", $text); - $text = str_replace("\n", "\\r\\n", $text); - return $text; +function sqstat_AJAX_prep($text) { + $text = str_replace("'", "\'", $text); + $text = str_replace("\n", "\\r\\n", $text); + return $text; } -function sqstat_AJAX_error($err) -{ - $err = sqstat_AJAX_prep($err); - $t .= "el('sqstat_result').innerHTML = '$err';"; - return $t; +function sqstat_AJAX_error($err) { + $err = sqstat_AJAX_prep($err); + $t .= "el('sqstat_result').innerHTML = '$err';"; + return $t; } -# ------------------------------------------------------------------------------ -# Reports -# ------------------------------------------------------------------------------ +/* + *Reports + */ -function sqstat_headerHTML() -{ - global $squidclass; +function sqstat_headerHTML() { + global $squidclass; - $date = date("h:i:s d/m/Y"); - $squidinfo = sqstat_serverInfoHTML(); + $date = date("h:i:s d/m/Y"); + $squidinfo = sqstat_serverInfoHTML(); - if (empty($squidclass->autorefresh)) $squidclass->autorefresh = 0; + if (empty($squidclass->autorefresh)) { + $squidclass->autorefresh = 0; + } - return -<<<EOD + return <<< EOD <form method="get" action="{$_SERVER["PHP_SELF"]}"> - <input id="counter" name="counter" type="hidden" value=0/> + <input id="counter" name="counter" type="hidden" value=0 /> Squid RealTime stat {$squidclass->sqstat_version} for the {$servers} proxy server <a id='sqstat_serverver'>{$squidinfo}</a>.<br/> Auto refresh: <input id="refresh" name="refresh" type="text" size="4" value="{$squidclass->autorefresh}"/> sec. - <input type="button" value="Update" onclick="update_start();"/> - <input type="button" value="Stop" onclick="update_stop();"/> Created at: <tt id='sqstat_updtime'>{$date}</tt><br/> + <input type="button" value="Update" onclick="update_start();" /> + <input type="button" value="Stop" onclick="update_stop();" /> Created at: <tt id='sqstat_updtime'>{$date}</tt><br/> </form> EOD; } -function sqstat_serverInfoHTML() -{ - global $squidclass; - return $squidclass->server_version . " ({$squidclass->squidhost}:{$squidclass->squidport})"; +function sqstat_serverInfoHTML() { + global $squidclass; + return $squidclass->server_version . " ({$squidclass->squidhost}:{$squidclass->squidport})"; } -function sqstat_resultHTML($data) -{ - global $squidclass; - - $group_by_name = $squidclass->group_by_name; - $use_js = true; - - $t = array(); - - # table header - $t[] = "<table class='result' align='center' width='100%' border='0'>"; - $t[] = "<tr>"; - $t[] = "<th>{$group_by_name}</th><th>URI</th>"; - if ($squidclass->use_sessions) - $t[] = "<th>Curr. Speed</th><th>Avg. Speed</th>"; - $t[] = "<th>Size</th><th>Time</th>"; - $t[] = "</tr>"; - - # table body - if (is_array($data['users'])) { - $tbl = array(); - - $con_color = 0; - foreach($data['users'] as $key => $v) { - # skeep total info - if ($key == 'total') continue; - # group row - $tbl[] = "<tr>"; - $tbl[] = "<td style='border-right:0;' colspan='2'><b>" . (is_int($key) ? long2ip($key) : $key) . "</b></td>"; - $tbl[] = "<td style='border-left:0;' colspan='5'> </td>"; - $tbl[] = "</tr>"; - - # connections row - foreach ($v['con'] as $con) { - if ($use_js) - $js = "onMouseout='hideddrivetip()' onMouseover='ddrivetip(\"" . $squidclass->implode_with_keys($con,"<br/>") . "\")'"; - else $js=''; - - # begin new row - $class = (++$con_color % 2 == 0) ? " class='odd'" : ""; - $tbl[] = "<tr ($class)>"; - - # URL - $uri = "<a target='_blank' href='" . htmlspecialchars($con["uri"]) ."'>{$con['uritext']}</a>"; - $tbl[] = "<td id='white'></td>"; - $tbl[] = "<td nowrap {$js} width='80%'>{$uri}</td>"; - - # speed - if ($squidclass->use_sessions) { - $cur_s = round($con['cur_speed'], 2) > 0 ? sprintf("%01.2f KB/s", $con['cur_speed']) : ''; - $avg_s = round($con['avg_speed'], 2) > 0 ? sprintf("%01.2f KB/s", $con['avg_speed']) : ''; - $tbl[] = "<td nowrap align='right'>{$cur_s}</td>"; - $tbl[] = "<td nowrap align='right'>{$avg_s}</td>"; - } - - # file size - $filesize = $squidclass->filesize_format($con["bytes"]); - $duration = $squidclass->duration($con["seconds"], "short"); - $tbl[] = "<td nowrap align='right'>{$filesize}</td>"; - $tbl[] = "<td nowrap align='right'>{$duration}</td>"; - - # end row - $tbl[] = "</tr>"; - } - - # total user speed - if ($squidclass->use_sessions) { - $user_curr = sprintf("%01.2f KB/s", $v['user_curr']); - $user_avg = sprintf("%01.2f KB/s", $v['user_avg']); - $tbl[] ="<tr>"; - $tbl[] ="<td colspan='2'></td>"; - $tbl[] ="<td align='right' id='highlight'>{$user_curr}</td>"; - $tbl[] ="<td align='right' id='highlight'>{$user_avg}</td>"; - $tbl[] ="<td colspan='2'></td>"; - } - } - - - # status row - $stat = array(); - $ausers = sprintf("%d", $data['ausers']); - $acon = sprintf("%d", $data['acon']); - $stat[] = "<tr class='total'><td><b>Total:</b></td>"; - if ($squidclass->use_sessions) { - $total_curr = sprintf("%01.2f", $data['total_curr']); - $total_avg = sprintf("%01.2f", $data['total_avg']); - $stat[] = "<td align='right' colspan='5'><b>{$ausers}</b> users and <b>{$acon}</b> connections @ <b>{$total_curr}/{$total_avg}</b> KB/s (CURR/AVG)</td>"; - } - else { - $stat[] = "<td align='right' colspan='5'><b>{$ausers}</b> users and <b>{$acon}</b> connections</td>"; - } - $t[] = "</tr>"; - } - - if ($ausers == 0) { - $t[] = "<tr><td colspan=6><b>No active connections</b></td></tr>"; - } - else { - $stat = implode("\n", $stat); - $tbl = implode("\n", $tbl); - $t[] = $stat . $tbl . $stat; - } - - $t[] = "</table>"; - $t[] = "<p class='copyleft'>Report based on SQStat © <a href='mailto:samm@os2.kiev.ua?subject=SqStat '" . SQSTAT_VERSION . "'>Alex Samorukov</a>, 2006</p>"; - - return implode("\n", $t); +function sqstat_resultHTML($data) { + global $squidclass; + + $group_by_name = $squidclass->group_by_name; + $use_js = true; + + $t = array(); + + // table header + $t[] = "<table class='result' align='center' width='100%' border='0'>"; + $t[] = "<tr>"; + $t[] = "<th>{$group_by_name}</th><th>URI</th>"; + if ($squidclass->use_sessions) { + $t[] = "<th>Curr. Speed</th><th>Avg. Speed</th>"; + } + $t[] = "<th>Size</th><th>Time</th>"; + $t[] = "</tr>"; + + // table body + if (is_array($data['users'])) { + $tbl = array(); + + $con_color = 0; + foreach($data['users'] as $key => $v) { + // skip total info + if ($key == 'total') { + continue; + } + // group row + $tbl[] = "<tr>"; + $tbl[] = "<td style='border-right:0;' colspan='2'><b>" . (is_int($key) ? long2ip($key) : $key) . "</b></td>"; + $tbl[] = "<td style='border-left:0;' colspan='5'> </td>"; + $tbl[] = "</tr>"; + + // connections row + foreach ($v['con'] as $con) { + if ($use_js) { + $js = "onMouseout='hideddrivetip()' onMouseover='ddrivetip(\"" . $squidclass->implode_with_keys($con,"<br/>") . "\")'"; + } else { + $js=''; + } + + // begin new row + $class = (++$con_color % 2 == 0) ? " class='odd'" : ""; + $tbl[] = "<tr ($class)>"; + + // URL + $uri = "<a target='_blank' href='" . htmlspecialchars($con["uri"]) ."'>{$con['uritext']}</a>"; + $tbl[] = "<td id='white'></td>"; + $tbl[] = "<td nowrap {$js} width='80%'>{$uri}</td>"; + + // speed + if ($squidclass->use_sessions) { + $cur_s = round($con['cur_speed'], 2) > 0 ? sprintf("%01.2f KB/s", $con['cur_speed']) : ''; + $avg_s = round($con['avg_speed'], 2) > 0 ? sprintf("%01.2f KB/s", $con['avg_speed']) : ''; + $tbl[] = "<td nowrap align='right'>{$cur_s}</td>"; + $tbl[] = "<td nowrap align='right'>{$avg_s}</td>"; + } + + // file size + $filesize = $squidclass->filesize_format($con["bytes"]); + $duration = $squidclass->duration($con["seconds"], "short"); + $tbl[] = "<td nowrap align='right'>{$filesize}</td>"; + $tbl[] = "<td nowrap align='right'>{$duration}</td>"; + + // end row + $tbl[] = "</tr>"; + } + + // total user speed + if ($squidclass->use_sessions) { + $user_curr = sprintf("%01.2f KB/s", $v['user_curr']); + $user_avg = sprintf("%01.2f KB/s", $v['user_avg']); + $tbl[] ="<tr>"; + $tbl[] ="<td colspan='2'></td>"; + $tbl[] ="<td align='right' id='highlight'>{$user_curr}</td>"; + $tbl[] ="<td align='right' id='highlight'>{$user_avg}</td>"; + $tbl[] ="<td colspan='2'></td>"; + } + } + + + // status row + $stat = array(); + $ausers = sprintf("%d", $data['ausers']); + $acon = sprintf("%d", $data['acon']); + $stat[] = "<tr class='total'><td><b>Total:</b></td>"; + if ($squidclass->use_sessions) { + $total_curr = sprintf("%01.2f", $data['total_curr']); + $total_avg = sprintf("%01.2f", $data['total_avg']); + $stat[] = "<td align='right' colspan='5'><b>{$ausers}</b> users and <b>{$acon}</b> connections @ <b>{$total_curr}/{$total_avg}</b> KB/s (CURR/AVG)</td>"; + } else { + $stat[] = "<td align='right' colspan='5'><b>{$ausers}</b> users and <b>{$acon}</b> connections</td>"; + } + $t[] = "</tr>"; + } // ENDIF (is_array($data['users'])) + + if ($ausers == 0) { + $t[] = "<tr><td colspan=6><b>No active connections</b></td></tr>"; + } else { + $stat = implode("\n", $stat); + $tbl = implode("\n", $tbl); + $t[] = $stat . $tbl . $stat; + } + + $t[] = "</table>"; + $t[] = "<p class='copyleft'>Report based on SQStat © <a href='mailto:samm@os2.kiev.ua?subject=SqStat '" . SQSTAT_VERSION . "'>Alex Samorukov</a>, 2006</p>"; + + return implode("\n", $t); } -function sqstat_errorHTML() -{ - global $squidclass; - $t = array(); +function sqstat_errorHTML() { + global $squidclass; + $t = array(); - # table header - $t[] = "<table class='result' align='center' width='100%' border='0'>"; - $t[] = "<tr><th align='left'>SqStat error</th></tr>"; - $t[] = "<tr><td>"; - $t[] = '<p style="color:red">Error (' . $squidclass->errno . '): ' . $squidclass->errstr . '</p>'; - $t[] = "</td></tr>"; - $t[] = "</table>"; + // table header + $t[] = "<table class='result' align='center' width='100%' border='0'>"; + $t[] = "<tr><th align='left'>SqStat error</th></tr>"; + $t[] = "<tr><td>"; + $t[] = '<p style="color:red">Error (' . $squidclass->errno . '): ' . $squidclass->errstr . '</p>'; + $t[] = "</td></tr>"; + $t[] = "</table>"; - return implode ("\n", $t); + return implode ("\n", $t); } -function sqstat_loadconfig() -{ - global $squidclass, $config; - - $squidclass->errno = 0; - $squidclass->errstr = ''; - - $squidclass->sqstat_version = SQSTAT_VERSION; - - # === load config from pfSense === - $iface = '127.0.0.1'; - $iport = 3128; - $squid_settings = $config['installedpackages']['squid']['config'][0]; - if (!empty($squid_settings)) { - # squid interface IP & port - $realif = array(); - $iface = ($squid_settings['active_interface'] ? $squid_settings['active_interface'] : 'lan'); - $iface = explode(",", $iface); - foreach ($iface as $i => $if) { - $realif[] = sqstat_get_real_interface_address($if); - $iface = $realif[$i][0] ? $realif[$i][0] : '127.0.0.1'; - } - $iport = $squid_settings['proxy_port'] ? $squid_settings['proxy_port'] : 3128; - } - $squidclass->squidhost = $iface; - $squidclass->squidport = $iport; - - $squidclass->group_by = "host"; - $squidclass->resolveip = true; - $squidclass->hosts_file = ''; # hosts file not used - $squidclass->autorefresh = 3; # refresh 3 sec by default - $squidclass->cachemgr_passwd = ''; - - # load hosts file, if defined - if (!empty($squidclass->hosts_file)) { - $squidclass->load_hosts(); - } - - return $squidclass->errno; -} +function sqstat_loadconfig() { + global $squidclass, $config; + + $squidclass->errno = 0; + $squidclass->errstr = ''; + + $squidclass->sqstat_version = SQSTAT_VERSION; + + $iface = '127.0.0.1'; + /* Load config from pfSense and find proxy port */ + $iport = 3128; + if (is_array($config['installedpackages']['squid']['config'][0])) { + $squid_settings = $config['installedpackages']['squid']['config'][0]; + } else { + $squid_settings = array(); + } + $iport = $squid_settings['proxy_port'] ? $squid_settings['proxy_port'] : 3128; + + $squidclass->squidhost = $iface; + $squidclass->squidport = $iport; -function sqstat_get_real_interface_address($iface) -{ - global $config; + $squidclass->group_by = "host"; + $squidclass->resolveip = true; + $squidclass->hosts_file = ''; // hosts file not used + $squidclass->autorefresh = 3; // refresh 3 secs by default + $squidclass->cachemgr_passwd = ''; - $iface = convert_friendly_interface_to_real_interface_name($iface); - $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6")); - list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line); + // Load hosts file if defined + if (!empty($squidclass->hosts_file)) { + $squidclass->load_hosts(); + } - return array($ip, long2ip(hexdec($netmask))); + return $squidclass->errno; } ?> diff --git a/config/lightsquid/tpl/novopf/index.html b/config/lightsquid/tpl/novopf/index.html index 5680866c..9d8ca329 100755 --- a/config/lightsquid/tpl/novopf/index.html +++ b/config/lightsquid/tpl/novopf/index.html @@ -97,7 +97,7 @@ <TR class=total> <TD align="left">##MSG_TOTAL_AVERAGE##:</Td> <!-- HIDE group start --> - <TD> </TD> + <TD> </TD> <!-- HIDE group end --> <TD align="center">##USERAVERAGE##</TD> <!-- HIDE oversize start--> diff --git a/config/lightsquid/tpl/novopf/user_detail.html b/config/lightsquid/tpl/novopf/user_detail.html index b3a7b168..8a8ff2cb 100755 --- a/config/lightsquid/tpl/novopf/user_detail.html +++ b/config/lightsquid/tpl/novopf/user_detail.html @@ -45,8 +45,8 @@ <tbody> <tr class=total> <th align="left" >##MSG_TOTAL##</th> - <th> </th> - <th> </th> + <th> </th> + <th> </th> <th align="right" nowrap="true">##TOTAL##</th> <th colspan=2> </th> </tr> diff --git a/config/lightsquid/tpl/novopf/user_month.html b/config/lightsquid/tpl/novopf/user_month.html index de7d8cab..f51e051e 100755 --- a/config/lightsquid/tpl/novopf/user_month.html +++ b/config/lightsquid/tpl/novopf/user_month.html @@ -63,8 +63,8 @@ <TR class="total"> <TD align="center">##MSG_TOTAL##</TD> <TD align="right" nowrap="true"><FONT size="-1">##TOTALBYTES##</FONT></TD> - <td align="right" nowrap="true"> </td> - <td align="right" nowrap="true"> </td> + <td align="right" nowrap="true"> </td> + <td align="right" nowrap="true"> </td> </TR> </tbody> </table> diff --git a/config/lightsquid/tpl/novopf/whousesite.html b/config/lightsquid/tpl/novopf/whousesite.html index ffd288f4..5da69edc 100755 --- a/config/lightsquid/tpl/novopf/whousesite.html +++ b/config/lightsquid/tpl/novopf/whousesite.html @@ -61,7 +61,7 @@ <tr class=total> <th align="left">##MSG_TOTAL##</th> <!-- HIDE realname start--> - <td> </td> + <td> </td> <!-- HIDE realname end--> <th align="right">##TOTALCONNECT##</th> <th align="right">##TOTAL##</th> diff --git a/config/lightsquid/tpl/novosea/index.html b/config/lightsquid/tpl/novosea/index.html index cf68c86d..874f196e 100755 --- a/config/lightsquid/tpl/novosea/index.html +++ b/config/lightsquid/tpl/novosea/index.html @@ -97,7 +97,7 @@ <TR class=total> <TD align="left">##MSG_TOTAL_AVERAGE##:</Td> <!-- HIDE group start --> - <TD> </TD> + <TD> </TD> <!-- HIDE group end --> <TD align="center">##USERAVERAGE##</TD> <!-- HIDE oversize start--> diff --git a/config/lightsquid/tpl/novosea/user_detail.html b/config/lightsquid/tpl/novosea/user_detail.html index b3a7b168..8a8ff2cb 100755 --- a/config/lightsquid/tpl/novosea/user_detail.html +++ b/config/lightsquid/tpl/novosea/user_detail.html @@ -45,8 +45,8 @@ <tbody> <tr class=total> <th align="left" >##MSG_TOTAL##</th> - <th> </th> - <th> </th> + <th> </th> + <th> </th> <th align="right" nowrap="true">##TOTAL##</th> <th colspan=2> </th> </tr> diff --git a/config/lightsquid/tpl/novosea/user_month.html b/config/lightsquid/tpl/novosea/user_month.html index de7d8cab..f51e051e 100755 --- a/config/lightsquid/tpl/novosea/user_month.html +++ b/config/lightsquid/tpl/novosea/user_month.html @@ -63,8 +63,8 @@ <TR class="total"> <TD align="center">##MSG_TOTAL##</TD> <TD align="right" nowrap="true"><FONT size="-1">##TOTALBYTES##</FONT></TD> - <td align="right" nowrap="true"> </td> - <td align="right" nowrap="true"> </td> + <td align="right" nowrap="true"> </td> + <td align="right" nowrap="true"> </td> </TR> </tbody> </table> diff --git a/config/lightsquid/tpl/novosea/whousesite.html b/config/lightsquid/tpl/novosea/whousesite.html index ffd288f4..5da69edc 100755 --- a/config/lightsquid/tpl/novosea/whousesite.html +++ b/config/lightsquid/tpl/novosea/whousesite.html @@ -61,7 +61,7 @@ <tr class=total> <th align="left">##MSG_TOTAL##</th> <!-- HIDE realname start--> - <td> </td> + <td> </td> <!-- HIDE realname end--> <th align="right">##TOTALCONNECT##</th> <th align="right">##TOTAL##</th> diff --git a/config/lightsquid/zhabascript.js b/config/lightsquid/zhabascript.js index 311e5fe9..7cdd898a 100644 --- a/config/lightsquid/zhabascript.js +++ b/config/lightsquid/zhabascript.js @@ -1,118 +1,106 @@ /*********************************************** -* Cool DHTML tooltip script- © Dynamic Drive DHTML code library (www.dynamicdrive.com) -* This notice MUST stay intact for legal use -* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code -***********************************************/ + * Cool DHTML tooltip script II- © Dynamic Drive DHTML code library (www.dynamicdrive.com) + * This notice MUST stay intact for legal use + * Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code + ***********************************************/ +var offsetxpoint = -60; //Customize x offset of tooltip +var offsetypoint = 20; //Customize y offset of tooltip +var ie = document.all; +var ns6 = document.getElementById && !document.all; +var enabletip = false; +var tipobj = false; -var offsetxpoint=-60 //Customize x offset of tooltip -var offsetypoint=20 //Customize y offset of tooltip -var ie=document.all -var ns6=document.getElementById && !document.all -var enabletip=false -var tipobj=false; - -function jsInit(){ - - if (ie||ns6) - tipobj=document.all? document.all["dhtmltooltip"] : document.getElementById? document.getElementById("dhtmltooltip") : "" - //alert(tipobj); +function jsInit() { + if (ie || ns6) { + tipobj = document.all ? document.all.dhtmltooltip : document.getElementById ? document.getElementById("dhtmltooltip") : ""; + //alert(tipobj); + } } -/*********************************************** -* Cool DHTML tooltip script II- © Dynamic Drive DHTML code library (www.dynamicdrive.com) -* This notice MUST stay intact for legal use -* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code -***********************************************/ - -var offsetfromcursorX=12 //Customize x offset of tooltip -var offsetfromcursorY=10 //Customize y offset of tooltip +var offsetfromcursorX = 12; //Customize x offset of tooltip +var offsetfromcursorY = 10; //Customize y offset of tooltip -var offsetdivfrompointerX=10 //Customize x offset of tooltip DIV relative to pointer image -var offsetdivfrompointerY=14 //Customize y offset of tooltip DIV relative to pointer image. Tip: Set it to (height_of_pointer_image-1). +var offsetdivfrompointerX = 10; //Customize x offset of tooltip DIV relative to pointer image +var offsetdivfrompointerY = 14; //Customize y offset of tooltip DIV relative to pointer image. Tip: Set it to (height_of_pointer_image-1). -//document.write('<div id="dhtmltooltip"></div>') //write out tooltip DIV -document.write('<img id="dhtmlpointer" src="arrow.gif">') //write out pointer image +document.write('<div id="dhtmltooltip"></div>'); //write out tooltip DIV +document.write('<img id="dhtmlpointer" src="arrow.gif">'); //write out pointer image -var ie=document.all -var ns6=document.getElementById && !document.all -var enabletip=false -if (ie||ns6) - var tipobj=document.all? document.all["dhtmltooltip"] : document.getElementById? document.getElementById("dhtmltooltip") : "" +if (ie || ns6) { + var tipobj = document.all ? document.all.dhtmltooltip : document.getElementById ? document.getElementById("dhtmltooltip") : ""; +} -var pointerobj=document.all? document.all["dhtmlpointer"] : document.getElementById? document.getElementById("dhtmlpointer") : "" +var pointerobj = document.all ? document.all.dhtmlpointer : document.getElementById ? document.getElementById("dhtmlpointer") : ""; -function ietruebody(){ - return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body +function ietruebody() { + return (document.compatMode && document.compatMode !== "BackCompat") ? document.documentElement : document.body; } -function ddrivetip(thetext, thewidth, thecolor){ - if(!tipobj) return false; - if (ns6||ie){ - if (typeof thewidth!="undefined") tipobj.style.width=thewidth+"px" - if (typeof thecolor!="undefined" && thecolor!="") tipobj.style.backgroundColor=thecolor - tipobj.innerHTML=thetext - enabletip=true - return false - } +function ddrivetip(thetext, thewidth, thecolor) { + if (!tipobj) { + return false; + } + if (ns6 || ie) { + if (thewidth !== undefined) { + tipobj.style.width = thewidth + "px"; + } + if (thecolor !== undefined && thecolor !== "") { + tipobj.style.backgroundColor = thecolor; + } + tipobj.innerHTML = thetext; + enabletip = true; + return false; + } } -function positiontip(e){ - if (enabletip){ - var nondefaultpos=false - var curX=(ns6)?e.pageX : event.clientX+ietruebody().scrollLeft; - var curY=(ns6)?e.pageY : event.clientY+ietruebody().scrollTop; - //Find out how close the mouse is to the corner of the window - var winwidth=ie&&!window.opera? ietruebody().clientWidth : window.innerWidth-20 - var winheight=ie&&!window.opera? ietruebody().clientHeight : window.innerHeight-20 - - var rightedge=ie&&!window.opera? winwidth-event.clientX-offsetfromcursorX : winwidth-e.clientX-offsetfromcursorX - var bottomedge=ie&&!window.opera? winheight-event.clientY-offsetfromcursorY : winheight-e.clientY-offsetfromcursorY - - var leftedge=(offsetfromcursorX<0)? offsetfromcursorX*(-1) : -1000 - - //if the horizontal distance isn't enough to accomodate the width of the context menu -/* if (rightedge<tipobj.offsetWidth){ - //move the horizontal position of the menu to the left by it's width - tipobj.style.left=curX-tipobj.offsetWidth+"px" - nondefaultpos=true - alert(1); - } - else */ - if (curX<leftedge) - tipobj.style.left="5px" - else{ - //position the horizontal position of the menu where the mouse is positioned - tipobj.style.left=curX+offsetfromcursorX-offsetdivfrompointerX+"px" - pointerobj.style.left=curX+offsetfromcursorX+"px" - } - - //same concept with the vertical position - if (bottomedge<tipobj.offsetHeight){ - tipobj.style.top=curY-tipobj.offsetHeight-offsetfromcursorY+"px" - nondefaultpos=true - } - else{ - tipobj.style.top=curY+offsetfromcursorY+offsetdivfrompointerY+"px" - pointerobj.style.top=curY+offsetfromcursorY+"px" - } - tipobj.style.visibility="visible" - if (!nondefaultpos) - pointerobj.style.visibility="visible" - else - pointerobj.style.visibility="hidden" - } -} +function positiontip(e) { + if (enabletip) { + var nondefaultpos = false; + var curX = (ns6) ? e.pageX : event.clientX + ietruebody().scrollLeft; + var curY = (ns6) ? e.pageY : event.clientY + ietruebody().scrollTop; + //Find out how close the mouse is to the corner of the window + var winwidth = (ie && !window.opera) ? ietruebody().clientWidth : window.innerWidth - 20; + var winheight = (ie && !window.opera) ? ietruebody().clientHeight : window.innerHeight - 20; -function hideddrivetip(){ - if (ns6||ie){ - enabletip=false - tipobj.style.visibility="hidden" - pointerobj.style.visibility="hidden" - tipobj.style.left="-1000px" - tipobj.style.backgroundColor='' - tipobj.style.width='' - } + var rightedge = (ie && !window.opera) ? winwidth - event.clientX - offsetfromcursorX : winwidth - e.clientX - offsetfromcursorX; + var bottomedge = (ie && !window.opera) ? winheight - event.clientY - offsetfromcursorY : winheight - e.clientY - offsetfromcursorY; + + var leftedge = (offsetfromcursorX < 0) ? offsetfromcursorX * (-1) : -1000; + + if (curX < leftedge) { + tipobj.style.left = "5px"; + } else { + //position the horizontal position of the menu where the mouse is positioned + tipobj.style.left = curX + offsetfromcursorX - offsetdivfrompointerX + "px"; + pointerobj.style.left = curX + offsetfromcursorX + "px"; + } + + //same concept with the vertical position + if (bottomedge < tipobj.offsetHeight) { + tipobj.style.top = curY - tipobj.offsetHeight - offsetfromcursorY + "px"; + nondefaultpos = true; + } else { + tipobj.style.top = curY + offsetfromcursorY + offsetdivfrompointerY + "px"; + pointerobj.style.top = curY + offsetfromcursorY + "px"; + } + tipobj.style.visibility = "visible"; + if (!nondefaultpos) { + pointerobj.style.visibility = "visible"; + } else { + pointerobj.style.visibility = "hidden"; + } + } } -document.onmousemove=positiontip +function hideddrivetip() { + if (ns6 || ie) { + enabletip = false; + tipobj.style.visibility = "hidden"; + pointerobj.style.visibility = "hidden"; + tipobj.style.left = "-1000px"; + tipobj.style.backgroundColor = ''; + tipobj.style.width = ''; + } +} +document.onmousemove = positiontip; diff --git a/config/nut/nut.xml b/config/nut/nut.xml index ca7ca956..e066bc83 100644 --- a/config/nut/nut.xml +++ b/config/nut/nut.xml @@ -41,7 +41,7 @@ ]]> </copyright> <name>nut</name> - <version>2.0.5</version> + <version>2.1.1</version> <title>Services: NUT</title> <savetext>Change</savetext> <aftersaveredirect>/status_nut.php</aftersaveredirect> @@ -77,6 +77,18 @@ <prefix>/usr/local/www/</prefix> <item>https://packages.pfsense.org/packages/config/nut/status_nut.php</item> </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/widgets/</prefix> + <item>https://packages.pfsense.org/packages/config/nut/ups_status.widget.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/javascript/</prefix> + <item>https://packages.pfsense.org/packages/config/nut/ups_status.js</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/include/</prefix> + <item>https://packages.pfsense.org/packages/config/nut/ups_status.inc</item> + </additional_files_needed> <advanced_options>enabled</advanced_options> <fields> <field> diff --git a/config/nut/ups_status.inc b/config/nut/ups_status.inc new file mode 100644 index 00000000..8953ff94 --- /dev/null +++ b/config/nut/ups_status.inc @@ -0,0 +1,7 @@ +<?php + +// set variable for custom title +$ups_status_title = "UPS Status"; +$ups_status_title_link = "status_nut.php"; + +?> diff --git a/config/nut/ups_status.js b/config/nut/ups_status.js new file mode 100644 index 00000000..4c64498f --- /dev/null +++ b/config/nut/ups_status.js @@ -0,0 +1,81 @@ +/* + ups_status.js + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2015 SunStroke <andrey.b.nikitin@gmail.com> + Copyright (C) 2015 ESF, LLC + 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. +*/ +//should be called from "ups_status.widget.php" +function showUPSData() { + + //get data from ups_status.widget.php + url = "/widgets/widgets/ups_status.widget.php?getUPSData=1" + //IE fix to disable cache when using http:// , just append timespan + + new Date().getTime(); + + jQuery.ajax(url, { + type: 'get', + success: function(data) { + var upsData = data || ""; + updateUPSWidgetContent(upsData); + }, + error: function(jqXHR, status, error){ + updateUPSWidgetContent("Error getting data from [ups_status.widget.php]"); + } + }); + + //call itself in 11 seconds + window.setTimeout(showUPSData, 11000); +} + +function updateUPSWidgetContent(upsData) { + + upsdata_array = upsData.split(":"); + + if(upsdata_array.length > 1) { + jQuery("#ups_monitoring").html(upsdata_array[0]); + jQuery("#ups_model").html(upsdata_array[1]); + jQuery("#ups__status").html(upsdata_array[2]); + jQuery("#ups_batmeter_graph").css('width', upsdata_array[3]); + jQuery("#ups_batmeter").html(upsdata_array[3]); + jQuery("#ups_runtime").html(upsdata_array[4]); + // Change title to "Battery Voltage" or "Battery Temp" + if(upsdata_array[5].indexOf("V")) { + jQuery("#ups_celltitle_VT").html("Battery Voltage"); + } else if(upsdata_array[5].indexOf("C")) { + jQuery("#ups_celltitle_VT").html("Battery Temp"); + } + jQuery("#ups_bvoltage").html(upsdata_array[5]); + jQuery("#ups_loadmeter_graph").css('width', upsdata_array[6]); + jQuery("#ups_loadmeter").html(upsdata_array[6]); + jQuery("#ups_inputv").html(upsdata_array[7]); + jQuery("#ups_outputv").html(upsdata_array[8]); + jQuery("#ups_widget").css('opacity', '1'); + jQuery("#ups_error_description").html(""); + } else { + // print error description ($condition variable from ups_status.widget.php) + jQuery("#ups_widget").css('opacity', '0.2'); + jQuery("#ups_error_description").html("ERROR: " + upsdata_array[0]); + } +} diff --git a/config/nut/ups_status.widget.php b/config/nut/ups_status.widget.php new file mode 100644 index 00000000..f2a766e1 --- /dev/null +++ b/config/nut/ups_status.widget.php @@ -0,0 +1,216 @@ +<?php +/* + ups_status.widget.php + part of pfSense (https://www.pfsense.org/) + Copyright (C) 2015 SunStroke <andrey.b.nikitin@gmail.com> + Copyright (C) 2015 ESF, LLC + 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. +*/ +require_once("guiconfig.inc"); // NOTE: maybe not needed (no GUI settings)? Remove if so. +require_once("/usr/local/www/widgets/include/ups_status.inc"); + +//called by showUPSData() (jQuery Ajax call) in ups_status.js +if (isset($_GET["getUPSData"])) { + //get UPS data and return it in ajax response + echo getUPSData(); + return; +} + +function getUPSData() { + + global $config; + $data = ""; + $cmd = ""; + $nut_config = $config['installedpackages']['nut']['config'][0]; + + if ($nut_config['monitor'] == "local") { + // "Monitoring" field - upsdata_array[0] + $data = gettext("Local UPS"); + $cmd = "upsc {$nut_config['name']}@localhost"; + } elseif ($nut_config['monitor'] == "remote") { + // "Monitoring" field - upsdata_array[0] + $data = gettext("Remote UPS"); + $cmd = "upsc {$nut_config['remotename']}@{$nut_config['remoteaddr']}"; + } elseif ($nut_config['monitor'] == "snmp") { + // "Monitoring" field - upsdata_array[0] + $data = gettext("SNMP UPS"); + $cmd = "upsc {$nut_config['snmpname']}@localhost"; + } + + if (is_process_running('upsmon')) { + $handle = popen($cmd, 'r'); + if ($handle) { + $read = fread($handle, 4096); + pclose($handle); + $lines = explode("\n", $read); + if (count($lines) == 1) { + $condition = gettext("Data stale!"); + } else { + $ups = array(); + foreach ($lines as $line) { + $line = explode(':', $line); + $ups[$line[0]] = trim($line[1]); + } + } + } + } else { + $condition = gettext("NUT enabled, but service not running!"); + if ($nut_config['monitor'] == "snmp") { + $condition .= gettext("\nSNMP UPS may be unreachable."); + } + } + if (isset($condition)) { + // Return error description + return $condition; + } + // "Model" field - upsdata_array[1] + $data .= ":" . (($ups['ups.model'] != "") ? $ups['ups.model'] : gettext("n/a")); + // "Status" field - upsdata_array[2] + $status = explode(" ", $ups['ups.status']); + foreach($status as $condition) { + if($disp_status) $disp_status .= ", "; + switch ($condition) { + case "WAIT": + $disp_status .= gettext("Waiting"); + break; + case "OFF": + $disp_status .= gettext("Off Line"); + break; + case "OL": + $disp_status .= gettext("On Line"); + break; + case "OB": + $disp_status .= gettext("On Battery"); + break; + case "TRIM": + $disp_status .= gettext("SmartTrim"); + break; + case "BOOST": + $disp_status .= gettext("SmartBoost"); + break; + case "OVER": + $disp_status .= gettext("Overload"); + break; + case "LB": + $disp_status .= gettext("Battery Low"); + break; + case "RB": + $disp_status .= gettext("Replace Battery"); + break; + case "CAL": + $disp_status .= gettext("Calibration"); + break; + case "CHRG": + $disp_status .= gettext("Charging"); + break; + default: + $disp_status .= $condition; + break; + } + } + $data .= ":" . $disp_status; + // "Battery Charge" bars and field - upsdata_array[3] + $data .= ":" . $ups['battery.charge'] . "%"; + // "Time Remaning" field - upsdata_array[4] + $secs = $ups['battery.runtime']; + if ($secs < 0 || $secs == "") { + $data .= ":" . gettext("n/a"); + } else { + $m = (int)($secs / 60); + $h = (int)($m / 60) % 24; + $m = $m % 60; + $s = $secs % 60; + $data .= ":" . $h."h " . $m."m " . $s."s"; + } + // "Battery Voltage or Battery Temp" field - upsdata_array[5] + if($ups['battery.voltage'] > 0) { + $data .= ":" . $ups['battery.voltage'] . " V"; + } elseif ($ups['ups.temperature'] > 0) { + $data .= ":" . $ups['ups.temperature'] . "&#176;C"; + } else { + $data .= ":" . ""; + } + // "Load" bars and field - upsdata_array[6] + $data .= ":" . $ups['ups.load'] . "%"; + // "Input Voltage" field - upsdata_array[7] + $data .= ":" . $ups['input.voltage'] . " V"; + // "Output Voltage" field - upsdata_array[8] + $data .= ":" . $ups['output.voltage'] . " V"; + + return $data; + +} +?> + +<script type="text/javascript"> +//<![CDATA[ + //start showing ups data + //NOTE: the refresh interval will be reset to a proper value in showUPSData() (ups_status.js). + jQuery(document).ready(function() { + showUPSData(); + }); +//]]> +</script> + +<div id="UPSWidgetContainer"> + <table id="ups_widget" bgcolor="#990000" width="100%" border="0" cellspacing="0" cellpadding="0" summary="UPS status"> + <tr> + <td class="widgetsubheader" align="center"><strong><?php echo gettext("Monitoring"); ?></strong></td> + <td class="widgetsubheader" align="center"><strong><?php echo gettext("Model"); ?></strong></td> + <td class="widgetsubheader" align="center"><strong><?php echo gettext("Status"); ?></strong></td> + </tr> + <tr> + <td class="listlr" align="center" id="ups_monitoring"></td> + <td class="listr" align="center" id="ups_model"></td> + <td class="listr" align="center" id="ups__status"></td> + </tr> + <tr> + <td class="widgetsubheader" align="center"><?php echo gettext("Battery Charge"); ?></td> + <td class="widgetsubheader" align="center"><?php echo gettext("Time Remain"); ?></td> + <td class="widgetsubheader" align="center" id="ups_celltitle_VT"></td> + </tr> + <tr> + <td class="listlr" align="center" id="ups_charge"> + <div class="ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar"><div id="ups_batmeter_graph" class="ui-progressbar-value ui-widget-header ui-corner-left"></div></div> + <span id="ups_batmeter"></span> + </td> + <td class="listr" align="center" id="ups_runtime"></td> + <td class="listr" align="center" id="ups_bvoltage"></td> + </tr> + <tr> + <td class="widgetsubheader" align="center"><?php echo gettext("Load"); ?></td> + <td class="widgetsubheader" align="center"><?php echo gettext("Input Voltage"); ?></td> + <td class="widgetsubheader" align="center"><?php echo gettext("Output Voltage"); ?></td> + </tr> + <tr> + <td class="listlr" align="center" id="ups_load"> + <div class="ui-progressbar ui-widget ui-widget-content ui-corner-all" role="progressbar"><div id="ups_loadmeter_graph" class="ui-progressbar-value ui-widget-header ui-corner-left"></div></div> + <span id="ups_loadmeter"></span> + </td> + <td class="listr" align="center" id="ups_inputv"></td> + <td class="listr" align="center" id="ups_outputv"></td> + </tr> + </table> + <span id="ups_error_description"></span> +</div> diff --git a/config/openbgpd/openbgpd.inc b/config/openbgpd/openbgpd.inc index 93364be9..ddfef18f 100644 --- a/config/openbgpd/openbgpd.inc +++ b/config/openbgpd/openbgpd.inc @@ -179,10 +179,12 @@ function openbgpd_install_conf() { $conffile .= "\t{$row['parameters']} {$row['parmvalue']} \n"; } } - if ($setlocaladdr == true && !empty($openbgpd_conf['listenip'])) { - $conffile .= "\tlocal-address {$openbgpd_conf['listenip']}\n"; - } else { - $conffile .= "\tlocal-address 0.0.0.0\n"; + if ($setlocaladdr == true) { + if (!empty($openbgpd_conf['listenip'])) { + $conffile .= "\tlocal-address {$openbgpd_conf['listenip']}\n"; + } else { + $conffile .= "\tlocal-address 0.0.0.0\n"; + } } $conffile .= "}\n"; } diff --git a/config/postfix/postfix.inc b/config/postfix/postfix.inc index 0629c187..9db7e5a1 100755 --- a/config/postfix/postfix.inc +++ b/config/postfix/postfix.inc @@ -1,16 +1,16 @@ <?php /* postfix.inc - part of the Postfix package for pfSense + part of pfSense (https://www.pfSense.org/) Copyright (C) 2010 Erik Fonnesbeck Copyright (C) 2011-2014 Marcello Coutinho - + Copyright (C) 2015 ESF, LLC 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, + 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 @@ -27,7 +27,6 @@ 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 = "postfix"; require_once("util.inc"); @@ -689,8 +688,15 @@ MASTEREOF2; //check postfix etc dir on 2.2 $pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); $postfix_etc_lnk="/usr/local/etc/postfix"; - if ($pfs_version == 2.2 && !is_dir($postfix_etc_lnk)) + if ($pfs_version == 2.2 && !is_dir($postfix_etc_lnk)) { @symlink(POSTFIX_LOCALBASE.'/etc/postfix',$postfix_etc_lnk); + } + + // Fixup library path so postfix can find its libraries + // XXX: Bug #4420 + if (POSTFIX_LOCALBASE != '/usr/local') { + mwexec("/sbin/ldconfig -m " . POSTFIX_LOCALBASE . "/local/lib/"); + } log_error("Writing out configuration"); file_put_contents(POSTFIX_LOCALBASE."/etc/postfix/main.cf", $postfix_main, LOCK_EX); @@ -737,6 +743,12 @@ MASTEREOF2; function postfix_start(){ global $config; $pf_dir=POSTFIX_LOCALBASE; + if (POSTFIX_LOCALBASE != '/usr/local') { + $pf_libdir = POSTFIX_LOCALBASE . "/local/lib"; + $pf_start_cmd = "LD_LIBRARY_PATH={$pf_libdir} {$pf_dir}/sbin/postfix start"; + } else { + $pf_start_cmd = "{$pf_dir}/sbin/postfix start"; + } $start=<<<EOF sysctl kern.ipc.nmbclusters=65536 @@ -744,7 +756,7 @@ function postfix_start(){ sysctl kern.maxfiles=131072 sysctl kern.maxfilesperproc=104856 sysctl kern.threads.max_threads_per_proc=4096 - {$pf_dir}/sbin/postfix start + {$pf_start_cmd} EOF; $stop = POSTFIX_LOCALBASE."/sbin/postfix stop\n"; @@ -813,163 +825,166 @@ function postfix_php_deinstall_command() { /* Uses XMLRPC to synchronize the changes to a remote node */ function postfix_sync_on_changes() { global $config, $g; - if (is_array($config['installedpackages']['postfixsync']['config'])){ - $postfix_sync=$config['installedpackages']['postfixsync']['config'][0]; - $synctimeout = $postfix_sync['synctimeout']; + if (is_array($config['installedpackages']['postfixsync']['config'])) { + $postfix_sync = $config['installedpackages']['postfixsync']['config'][0]; + $synctimeout = $postfix_sync['synctimeout'] ?: '250'; $synconchanges = $postfix_sync['synconchanges']; - switch ($synconchanges){ + switch ($synconchanges) { case "manual": - if (is_array($postfix_sync[row])){ - $rs=$postfix_sync[row]; - } - else{ - log_error("[postfix] xmlrpc sync is enabled but there is no hosts to push postfix config."); + if (is_array($postfix_sync['row'])) { + $rs = $postfix_sync['row']; + } else { + log_error("[postfix] XMLRPC sync is enabled but there are no hosts configured as replication targets."); 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']; - $rs[0]['enabless']=true; - $rs[0]['sync_type']="xmlrpc"; - if (! is_ipaddr($system_carp['synchronizetoip'])){ - log_error("[postfix] xmlrpc sync is enabled but there is no system backup hosts to push postfix config."); - return; - } + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; + $rs[0]['ipaddress'] = $system_carp['synchronizetoip']; + $rs[0]['username'] = $system_carp['username']; + $rs[0]['password'] = $system_carp['password']; + $rs[0]['sync_type'] = "xmlrpc"; + $rs[0]['enabless'] = FALSE; + + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['syncprotocol'] = "http"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['syncprotocol'] = "https"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '443'; } - else{ - log_error("[postfix] xmlrpc sync is enabled but there is no system backup hosts to push postfix config."); + if (!is_ipaddr($system_carp['synchronizetoip'])) { + log_error("[postfix] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); return; + } else { + $rs[0]['enabless'] = TRUE; } + } else { + log_error("[postfix] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } break; default: return; - break; + break; } - if (is_array($rs)){ - log_error("[postfix] xmlrpc sync is starting."); - foreach($rs as $sh){ - $sync_to_ip = $sh['ipaddress']; - if($sh['username']) - $username = $sh['username']; - else - $username = 'admin'; - if($sh['password'] && $sh['ipaddress'] && $sh['enabless']) - postfix_do_xmlrpc_sync($sh['ipaddress'], $username, $sh['password'],$sh['sync_type'],$synctimeout); + if (is_array($rs)) { + log_error("[postfix] XMLRPC sync is starting."); + foreach($rs as $sh) { + if ($sh['enabless'] && $sh['sync_type'] == 'xmlrpc') { + $sync_to_ip = $sh['ipaddress']; + $port = $sh['syncport']; + $username = $sh['username'] ?: 'admin'; + $password = $sh['password']; + $protocol = $sh['syncprotocol']; + $sync_type = $sh['sync_type']; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + postfix_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout); + } else { + log_error("[postfix] XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } } - log_error("[postfix] xmlrpc sync is ending."); } - } + log_error("[postfix] XMLRPC sync completed."); + } + } } /* Do the actual XMLRPC sync */ -function postfix_do_xmlrpc_sync($sync_to_ip,$username,$password,$sync_type,$synctimeout) { +function postfix_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) { global $config, $g; - if(!$username) - $username="admin"; - - if(!$password) + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("[postfix] A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; + } - if(!$sync_to_ip) - return; + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; + } - if(!$synctimeout) - $synctimeout=120; - - $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; + $url = "{$protocol}://{$sync_to_ip}"; - /* xml will hold the sections to sync */ + /* XML will hold the sections to sync. */ $xml = array(); - $sync_xml=$config['installedpackages']['postfixsync']['config'][0]['synconchanges']; - $sync_db=$config['installedpackages']['postfixsync']['config'][0]['rsync']; - if ($sync_xml && preg_match("/xmlrpc/",$sync_type)){ - log_error("Include postfix xmls"); - $xml['postfix'] = $config['installedpackages']['postfix']; - $xml['postfixdomains'] = $config['installedpackages']['postfixdomains']; - $xml['postfixacl'] = $config['installedpackages']['postfixacl']; - $xml['postfixrecipients'] = $config['installedpackages']['postfixrecipients']; - $xml['postfixantispam'] = $config['installedpackages']['postfixantispam']; - } - if (count($xml) > 0){ - /* 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("Beginning Postfix 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 $sync_timeout seconds */ + $xml['postfix'] = $config['installedpackages']['postfix']; + $xml['postfixdomains'] = $config['installedpackages']['postfixdomains']; + $xml['postfixacl'] = $config['installedpackages']['postfixacl']; + $xml['postfixrecipients'] = $config['installedpackages']['postfixrecipients']; + $xml['postfixantispam'] = $config['installedpackages']['postfixantispam']; + + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($xml)); + + /* Set a few variables needed for sync code */ + log_error("[postfix] Beginning 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 XMLRPC sync with {$url}:{$port}."; + log_error("[postfix] {$error}"); + file_notice("sync_settings", $error, "Postfix Settings Sync", ""); + } elseif ($resp->faultCode()) { + $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - if(!$resp) { - $error = "A communications error occurred while attempting postfix XMLRPC sync with {$url}:{$port}."; - log_error($error); - file_notice("sync_settings", $error, "Postfix Settings Sync", ""); - } elseif($resp->faultCode()) { - $cli->setDebug(1); - $resp = $cli->send($msg, $synctimeout); - $error = "An error code was received while attempting postfix XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); - file_notice("sync_settings", $error, "Postfix Settings Sync", ""); - } else { - log_error("Postfix XMLRPC sync successfully completed with {$url}:{$port}."); - } + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[postfix] {$error}"); + file_notice("sync_settings", $error, "Postfix Settings Sync", ""); + } else { + log_error("[postfix] XMLRPC sync successfully completed with {$url}:{$port}."); + } - /* tell postfix to reload our settings on the destionation sync host. */ - $method = 'pfsense.exec_php'; - $execcmd = "require_once('/usr/local/pkg/postfix.inc');\n"; - $execcmd .= "sync_package_postfix('yes');"; - - /* assemble xmlrpc payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($execcmd) - ); - - log_error("postfix 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); + /* Tell postfix to reload our settings on the destionation sync host. */ + $method = 'pfsense.exec_php'; + $execcmd = "require_once('/usr/local/pkg/postfix.inc');\n"; + $execcmd .= "sync_package_postfix('yes');"; + + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); + log_error("[postfix] 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 XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; + log_error("[postfix] {$error}"); + file_notice("sync_settings", $error, "postfix Settings Sync", ""); + } elseif($resp->faultCode()) { + $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - if(!$resp) { - $error = "A communications error occurred while attempting postfix XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; - log_error($error); - file_notice("sync_settings", $error, "postfix Settings Sync", ""); - } elseif($resp->faultCode()) { - $cli->setDebug(1); - $resp = $cli->send($msg, $synctimeout); - $error = "An error code was received while attempting postfix XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); - file_notice("sync_settings", $error, "postfix Settings Sync", ""); - } else { - log_error("postfix XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); - } + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[postfix] {$error}"); + file_notice("sync_settings", $error, "postfix Settings Sync", ""); + } else { + log_error("[postfix] XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); } } diff --git a/config/postfix/postfix.php b/config/postfix/postfix.php index 4cf85033..4c444ab8 100644 --- a/config/postfix/postfix.php +++ b/config/postfix/postfix.php @@ -1,15 +1,15 @@ <?php /* postfix.php - part of pfSense (https://www.pfsense.org/) + part of pfSense (https://www.pfSense.org/) Copyright (C) 2011-2014 Marcello Coutinho <marcellocoutinho@gmail.com> - based on varnish_view_config. + Copyright (C) 2015 ESF, LLC 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, + 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 @@ -33,110 +33,140 @@ require_once("/etc/inc/pkg-utils.inc"); require_once("/etc/inc/globals.inc"); require_once("/usr/local/pkg/postfix.inc"); -$uname=posix_uname(); -if ($uname['machine']=='amd64') +$uname = posix_uname(); +if ($uname['machine'] == 'amd64') { ini_set('memory_limit', '250M'); +} -function get_remote_log(){ - global $config,$g,$postfix_dir; +function get_remote_log() { + global $config, $g, $postfix_dir; $curr_time = time(); - $log_time=date('YmdHis',$curr_time); - #get protocol - if($config['system']['webgui']['protocol'] != "") - $synchronizetoip = $config['system']['webgui']['protocol']. "://"; - #get port - $port = $config['system']['webgui']['port']; - #if port is empty lets rely on the protocol selection - if($port == "") - $port =($config['system']['webgui']['protocol'] == "http"?"80":"443"); - $synchronizetoip .= $sync_to_ip; - if (is_array($config['installedpackages']['postfixsync'])) - foreach($config['installedpackages']['postfixsync']['config'][0]['row'] as $sh){ - $sync_to_ip = $sh['ipaddress']; - $sync_type = $sh['sync_type']; - $password = $sh['password']; - $file= '/var/db/postfix/'.$server.'.sql'; - #get remote data - if ($sync_type=='fetch'){ - $url= $synchronizetoip . $sync_to_ip; - print "$sync_to_ip $url, $port\n"; - $method = 'pfsense.exec_php'; - $execcmd = "require_once('/usr/local/www/postfix.php');\n"; - $execcmd .= '$toreturn=get_sql('.$log_time.');'; - /* assemble xmlrpc payload */ - $params = array(XML_RPC_encode($password), - XML_RPC_encode($execcmd)); - log_error("postfix get sql data from {$sync_to_ip}."); - $msg = new XML_RPC_Message($method, $params); - $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); - $cli->setCredentials('admin', $password); - #$cli->setDebug(1); - $resp = $cli->send($msg, "250"); - $a=$resp->value(); - $errors=0; - #var_dump($sql); - foreach($a as $b) - foreach ($b as $c) - foreach ($c as $d) - foreach ($d as $e){ - $update=unserialize($e['string']); - print $update['day']."\n"; - if ($update['day'] != ""){ - create_db($update['day'].".db"); - if ($debug=true) - print $update['day'] ." writing from remote system to db..."; - $dbhandle = sqlite_open($postfix_dir.'/'.$update['day'].".db", 0666, $error); - #file_put_contents("/tmp/".$key.'-'.$update['day'].".sql",gzuncompress(base64_decode($update['sql'])), LOCK_EX); - $ok = sqlite_exec($dbhandle, gzuncompress(base64_decode($update['sql'])), $error); - if (!$ok){ - $errors++; - die ("Cannot execute query. $error\n".$update['sql']."\n"); - } - else{ - if ($debug=true) - print "ok\n"; - } - sqlite_close($dbhandle); - } - } - if ($errors ==0){ + $log_time = date('YmdHis', $curr_time); + + if (is_array($config['installedpackages']['postfixsync'])) { + $synctimeout = $config['installedpackages']['postfixsync']['config'][0]['synctimeout'] ?: '250'; + foreach ($config['installedpackages']['postfixsync']['config'][0]['row'] as $sh) { + // Get remote data for enabled fetch hosts + if ($sh['enabless'] && $sh['sync_type'] == 'fetch') { + $sync_to_ip = $sh['ipaddress']; + $port = $sh['syncport']; + $username = $sh['username'] ?: 'admin'; + $password = $sh['password']; + $protocol = $sh['syncprotocol']; + $file = '/var/db/postfix/' . $server . '.sql'; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; + } + if ($protocol == "") { + $error = "Protocol parameter is empty. "; + $valid = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; + } + $url = "{$protocol}://{$sync_to_ip}"; + + print "{$sync_to_ip} {$url}, {$port}\n"; $method = 'pfsense.exec_php'; $execcmd = "require_once('/usr/local/www/postfix.php');\n"; - $execcmd .= 'flush_sql('.$log_time.');'; - /* assemble xmlrpc payload */ - $params = array(XML_RPC_encode($password), - XML_RPC_encode($execcmd)); - log_error("postfix flush sql buffer file from {$sync_to_ip}."); + $execcmd .= '$toreturn = get_sql('.$log_time.');'; + + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); + log_error("[postfix] Fetching sql data from {$sync_to_ip}."); $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); - $cli->setCredentials('admin', $password); - #$cli->setDebug(1); - $resp = $cli->send($msg, "250"); + $cli->setCredentials($username, $password); + //$cli->setDebug(1); + $resp = $cli->send($msg, $synctimeout); + $a = $resp->value(); + $errors = 0; + //var_dump($sql); + foreach($a as $b) { + foreach ($b as $c) { + foreach ($c as $d) { + foreach ($d as $e) { + $update = unserialize($e['string']); + print $update['day'] . "\n"; + if ($update['day'] != "") { + create_db($update['day'] . ".db"); + if ($debug) { + print $update['day'] . " writing from remote system to db..."; + } + $dbhandle = sqlite_open($postfix_dir . '/' . $update['day'] . ".db", 0666, $error); + //file_put_contents("/tmp/" . $key . '-' . $update['day'] . ".sql", gzuncompress(base64_decode($update['sql'])), LOCK_EX); + $ok = sqlite_exec($dbhandle, gzuncompress(base64_decode($update['sql'])), $error); + if (!$ok) { + $errors++; + die ("Cannot execute query. $error\n".$update['sql']."\n"); + } elseif ($debug) { + print "ok\n"; + } + sqlite_close($dbhandle); + } + } + } + } + } + if ($errors == 0) { + $method = 'pfsense.exec_php'; + $execcmd = "require_once('/usr/local/www/postfix.php');\n"; + $execcmd .= 'flush_sql('.$log_time.');'; + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); + log_error("[postfix] Flushing sql buffer file from {$sync_to_ip}."); + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials($username, $password); + //$cli->setDebug(1); + $resp = $cli->send($msg, $synctimeout); } + } else { + log_error("[postfix] Fetch sql database from '{$sync_to_ip}' aborted due to the following error(s): {$error}"); } + } } + log_error("[postfix] Fetch sql database completed."); + } } -function get_sql($log_time){ - global $config,$xmlrpc_g; - $server=$_SERVER['REMOTE_ADDR']; - if (is_array($config['installedpackages']['postfixsync'])) - foreach($config['installedpackages']['postfixsync']['config'][0]['row'] as $sh){ +function get_sql($log_time) { + global $config, $xmlrpc_g; + $server = $_SERVER['REMOTE_ADDR']; + + if (is_array($config['installedpackages']['postfixsync'])) { + foreach($config['installedpackages']['postfixsync']['config'][0]['row'] as $sh) { $sync_to_ip = $sh['ipaddress']; $sync_type = $sh['sync_type']; - $password = $sh['password']; - $file= '/var/db/postfix/'.$server.'.sql'; - if ($sync_to_ip==$server && $sync_type=='share' && file_exists($file)){ - rename($file,$file.".$log_time"); - return (file($file.".$log_time")); - } + $file = '/var/db/postfix/' . $server . '.sql'; + if ($sync_to_ip == "{$server}" && $sync_type == "share" && file_exists($file)) { + rename($file, $file . ".$log_time"); + return (file($file . ".$log_time")); + } } return ""; + } } -function flush_sql($log_time){ - if (preg_match("/\d+\.\d+\.\d+\.\d+/",$_SERVER['REMOTE_ADDR'])) - unlink_if_exists('/var/db/postfix/'.$_SERVER['REMOTE_ADDR'].".sql.$log_time"); +function flush_sql($log_time) { + if (preg_match("/\d+\.\d+\.\d+\.\d+/", $_SERVER['REMOTE_ADDR'])) { + unlink_if_exists('/var/db/postfix/' . $_SERVER['REMOTE_ADDR'] . ".sql.{$log_time}"); + } } function grep_log(){ @@ -296,73 +326,60 @@ function grep_log(){ } } - $config=parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']); - //print count($config['installedpackages']); - #start db replication if configured - if ($config['installedpackages']['postfixsync']['config'][0]['rsync']) - foreach ($config['installedpackages']['postfixsync']['config'] as $rs ) - foreach($rs['row'] as $sh){ - $sync_to_ip = $sh['ipaddress']; - $sync_type = $sh['sync_type']; - $password = $sh['password']; - print "checking replication to $sync_to_ip..."; - if ($password && $sync_to_ip && preg_match("/(both|database)/",$sync_type)) - postfix_do_xmlrpc_sync($sync_to_ip, $password,$sync_type); - print "ok\n"; - } - } -function write_db($stm,$table,$days){ - global $postfix_dir,$config,$g; +function write_db($stm, $table, $days) { + global $postfix_dir, $config, $g; conf_mount_rw(); - $do_sync=array(); + $do_sync = array(); print "writing to database..."; - foreach ($days as $day) - if (strlen($stm[$day]) > 10){ - if ($config['installedpackages']['postfixsync']['config'][0]) - foreach ($config['installedpackages']['postfixsync']['config'] as $rs ) - foreach($rs['row'] as $sh){ + foreach ($days as $day) { + if ((strlen($stm[$day]) > 10) && (is_array($config['installedpackages']['postfixsync']['config']))) { + foreach ($config['installedpackages']['postfixsync']['config'] as $rs) { + foreach($rs['row'] as $sh) { $sync_to_ip = $sh['ipaddress']; $sync_type = $sh['sync_type']; $password = $sh['password']; - $sql_file='/var/db/postfix/'.$sync_to_ip.'.sql'; - ${$sync_to_ip}=""; - if (file_exists($sql_file)) - ${$sync_to_ip}=file_get_contents($sql_file); - if ($sync_to_ip && $sync_type=="share"){ - ${$sync_to_ip}.=serialize(array('day'=> $day,'sql'=> base64_encode(gzcompress($stm[$day]."COMMIT;",9))))."\n"; - if (! in_array($sync_to_ip,$do_sync)) - $do_sync[]=$sync_to_ip; + $sql_file = '/var/db/postfix/' . $sync_to_ip . '.sql'; + ${$sync_to_ip} = ""; + if (file_exists($sql_file)) { + ${$sync_to_ip} = file_get_contents($sql_file); + } + if ($sync_to_ip && $sync_type == "share") { + ${$sync_to_ip} .= serialize(array('day' => $day, 'sql' => base64_encode(gzcompress($stm[$day] . "COMMIT;", 9)))) . "\n"; + if (!in_array($sync_to_ip, $do_sync)) { + $do_sync[] = $sync_to_ip; } } - #write local db file - create_db($day.".db"); - if ($debug=true) - print " writing to local db $day..."; - $dbhandle = sqlite_open($postfix_dir.$day.".db", 0666, $error); - if (!$dbhandle) die ($error); - #file_put_contents("/tmp/".$key.'-'.$update['day'].".sql",gzuncompress(base64_decode($update['sql'])), LOCK_EX); - $ok = sqlite_exec($dbhandle, $stm[$day]."COMMIT;", $error); - if (!$ok){ - if ($debug=true) - print ("Cannot execute query. $error\n".$stm[$day]."COMMIT;\n"); - } - else{ - if ($debug=true) - print "ok\n"; } - sqlite_close($dbhandle); } - #write update sql files - if (count ($do_sync) > 0 ){ - - foreach($do_sync as $ip) - file_put_contents('/var/db/postfix/'.$ip.'.sql',${$ip},LOCK_EX); - conf_mount_ro(); + /* Write local db file */ + create_db($day . ".db"); + if ($debug) { + print "writing to local db $day..."; + } + $dbhandle = sqlite_open($postfix_dir.$day.".db", 0666, $error); + if (!$dbhandle) { + die ($error); + } + //file_put_contents("/tmp/" . $key . '-' . $update['day'] . ".sql", gzuncompress(base64_decode($update['sql'])), LOCK_EX); + $ok = sqlite_exec($dbhandle, $stm[$day] . "COMMIT;", $error); + if (!$ok) { + print ("Cannot execute query. $error\n" . $stm[$day] . "COMMIT;\n"); + } elseif ($debug) { + print "ok\n"; + } + sqlite_close($dbhandle); + } } - #write local file - + /* Write updated sql files */ + if (count($do_sync) > 0 ) { + foreach ($do_sync as $ip) { + file_put_contents('/var/db/postfix/' . $ip . '.sql', ${$ip}, LOCK_EX); + } + } + conf_mount_ro(); + /* Write local file */ } function create_db($postfix_db){ @@ -748,4 +765,4 @@ if ($_REQUEST['files']!= ""){ print '</table>'; } } -?>
\ No newline at end of file +?> diff --git a/config/postfix/postfix_sync.xml b/config/postfix/postfix_sync.xml index 727305ff..eb3ab27b 100644 --- a/config/postfix/postfix_sync.xml +++ b/config/postfix/postfix_sync.xml @@ -5,44 +5,44 @@ <copyright> <![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* - postfix_sync.xml - part of the Postfix package for pfSense - Copyright (C) 2011-2014 Marcello Coutinho - All rights reserved. - */ -/* ========================================================================== */ + postfix_sync.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2011-2014 Marcello Coutinho + Copyright (C) 2015 ESF, LLC + All rights reserved. +*/ +/* ====================================================================================== */ /* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + 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. + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. - 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. - */ -/* ========================================================================== */ + 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. +*/ +/* ====================================================================================== */ ]]> </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> - <name>postfix_sync</name> - <version>1.0</version> + <name>postfixsync</name> + <version>2.4.5</version> <title>Services: Postfix relay and antispam</title> <include_file>/usr/local/pkg/postfix.inc</include_file> <menu> @@ -100,12 +100,12 @@ <type>listtopic</type> </field> <field> - <fielddescr>Sync method</fielddescr> + <fielddescr>Sync Method</fielddescr> <fieldname>synconchanges</fieldname> <description>Automatically sync postfix configuration changes.</description> <type>select</type> <required/> - <default_value>auto</default_value> + <default_value>disabled</default_value> <options> <option><name>Sync to configured system backup server</name><value>auto</value></option> <option><name>Sync to host(s) defined below</name><value>manual</value></option> @@ -113,7 +113,7 @@ </options> </field> <field> - <fielddescr>Sync timeout</fielddescr> + <fielddescr>Sync Timeout</fielddescr> <fieldname>synctimeout</fieldname> <description>Select sync max wait time</description> <type>select</type> @@ -128,73 +128,89 @@ </options> </field> <field> - <fielddescr><![CDATA[Remote Server]]></fielddescr> + <fielddescr>Remote Server</fielddescr> <fieldname>none</fieldname> <type>rowhelper</type> <dontdisplayname/> <usecolspan2/> <rowhelper> - <rowhelperfield> - <fielddescr>Enable</fielddescr> - <fieldname>enabless</fieldname> - <type>checkbox</type> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Sync Type </fielddescr> - <fieldname>sync_type</fieldname> - <type>select</type> - <options> - <option><name>XMLRPC Sync</name><value>xmlrpc</value></option> - <option><name>Share Database To</name><value>share</value></option> - <option><name>Fetch Database From</name><value>fetch</value></option> - <option><name>Disabled</name><value>disabled</value></option> - </options> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Remote Server IP</fielddescr> - <fieldname>ipaddress</fieldname> - <description>IP Address of remote server</description> - <type>input</type> - <size>10</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Username</fielddescr> - <fieldname>username</fieldname> - <description>Username for remote server.</description> - <type>input</type> - <size>10</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Password</fielddescr> - <fieldname>password</fieldname> - <description>Password for remote server.</description> - <type>password</type> - <size>10</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Description</fielddescr> - <fieldname>description</fieldname> - <type>input</type> - <size>27</size> - </rowhelperfield> + <rowhelperfield> + <fielddescr>Enable</fielddescr> + <fieldname>enabless</fieldname> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Sync Type</fielddescr> + <fieldname>sync_type</fieldname> + <type>select</type> + <options> + <option><name>XMLRPC Sync</name><value>xmlrpc</value></option> + <option><name>Share Database To</name><value>share</value></option> + <option><name>Fetch Database From</name><value>fetch</value></option> + <option><name>Disabled</name><value>disabled</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>syncprotocol</fieldname> + <description>Choose the protocol used to sync with the destination host (HTTP or HTTPS).</description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Remote Server IP/Hostname</fielddescr> + <fieldname>ipaddress</fieldname> + <description>IP address or hostname of remote server</description> + <type>input</type> + <size>30</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>syncport</fieldname> + <description>Choose the sync port of the remote server.</description> + <type>input</type> + <size>5</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Username</fielddescr> + <fieldname>username</fieldname> + <description>Username for remote server.</description> + <type>input</type> + <size>20</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Password</fielddescr> + <fieldname>password</fieldname> + <description>Password for remote server.</description> + <type>password</type> + <size>20</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Description</fielddescr> + <fieldname>description</fieldname> + <type>input</type> + <size>30</size> + </rowhelperfield> </rowhelper> - <description><![CDATA[<br>Sync types Description:<br><br> - <strong>XMLRPC Sync</strong> - Forward postfix settings to other pfsense boxes. Remote password required<br> - <strong>Share Database To</strong> - Allow other pfsense boxes to fetch maillog data via xml. Remote password NOT required.<br> - <strong>Fetch Database From</strong> - Merge logs from other pfsense boxes to this local database. Remote password required.<br> - <strong>Disabled</strong> - Ignore this host while sync.<br><br> - While sharing databases works only when you select 'Sync to host(s) defined below' on sync method and you must setup 'Share Database To' in source box and 'Fetch Database From' on destination box.]]></description> + <description> + <![CDATA[ + <br/>Sync types Description:<br/><br/> + <strong>XMLRPC Sync</strong> - Forward postfix settings to other pfSense boxes. Remote password required.<br/> + <strong>Share Database To</strong> - Allow other pfSense boxes to fetch maillog data via XMLRPC. Remote password NOT required.<br/> + <strong>Fetch Database From</strong> - Merge logs from other pfSense boxes to this local database. Remote password required.<br/> + <strong>Disabled</strong> - Ignore this host while syncing.<br/><br/> + Sharing databases works only when you select 'Sync to host(s) defined below' sync method; you must setup 'Share Database To' in source box and 'Fetch Database From' on destination box. + ]]> + </description> </field> </fields> - <custom_php_install_command> - postfix_php_install_command(); - </custom_php_install_command> - <custom_php_deinstall_command> - postfix_php_deinstall_command(); - </custom_php_deinstall_command> <custom_php_validation_command> postfix_validate_input($_POST, $input_errors); - </custom_php_validation_command> + </custom_php_validation_command> <custom_php_resync_config_command> sync_package_postfix(); </custom_php_resync_config_command> diff --git a/config/sarg/sarg.inc b/config/sarg/sarg.inc index 85410560..561f7c61 100644 --- a/config/sarg/sarg.inc +++ b/config/sarg/sarg.inc @@ -438,18 +438,20 @@ function sarg_validate_input($post, &$input_errors) { } # check squidguard - if (substr($key, 0, 10) == "proxy_server" && $value == "squidguard") - if (!is_array($config['installedpackages']['squidguardgeneral'])) + if (substr($key, 0, 10) == "proxy_server" && $value == "squidguard") { + if (!is_array($config['installedpackages']['squidguardgeneral'])) { $input_errors[]='squidguard package not detected'; + } + } # check squid if (substr($key, 0, 5) == "proxy_server" && $value == "squid") { if (is_array($config['installedpackages']['squid'])) { if (!$config['installedpackages']['squid']['log_enabled']) { - $input_errors[]='squidlogs not enabled'; + $input_errors[] = 'Squid logging not enabled'; } } else { - $input_errors[]='squid package not installed'; + $input_errors[] = 'Squid package not installed'; } } @@ -469,108 +471,113 @@ function sarg_validate_input($post, &$input_errors) { /* Uses XMLRPC to synchronize the changes to a remote node */ function sarg_sync_on_changes() { global $config, $g; + if (is_array($config['installedpackages']['sargsync']['config'])) { $sarg_sync = $config['installedpackages']['sargsync']['config'][0]; $synconchanges = $sarg_sync['synconchanges']; - $synctimeout = $sarg_sync['synctimeout']; + $synctimeout = $sarg_sync['synctimeout'] ?: '250'; switch ($synconchanges) { case "manual": - if (is_array($sarg_sync[row])) { - $rs = $sarg_sync[row]; + if (is_array($sarg_sync['row'])) { + $rs = $sarg_sync['row']; } else { - log_error("[sarg] xmlrpc sync is enabled but there is no hosts to push on sarg config."); + log_error("[sarg] XMLRPC sync is enabled but there are no hosts configured as replication targets."); return; } break; case "auto": - if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])) { - $system_carp = $config['installedpackages']['carpsettings']['config'][0]; + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; $rs[0]['ipaddress'] = $system_carp['synchronizetoip']; $rs[0]['username'] = $system_carp['username']; $rs[0]['password'] = $system_carp['password']; - if ($system_carp['synchronizetoip'] == "" || $system_carp['username'] == "") { - log_error("[sarg] xmlrpc sync is enabled but there are no system backup hosts to push sarg config."); + $rs[0]['syncdestinenable'] = FALSE; + + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['syncprotocol'] = "http"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['syncprotocol'] = "https"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '443'; + } + if ($system_carp['synchronizetoip'] == "") { + log_error("[sarg] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); return; + } else { + $rs[0]['syncdestinenable'] = TRUE; } - } else { - log_error("[sarg] xmlrpc sync is enabled but there are no system backup hosts to push sarg config."); + log_error("[sarg] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); return; } break; default: return; - break; + break; } if (is_array($rs)) { - log_error("[sarg] 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) { - sarg_do_xmlrpc_sync($sync_to_ip, $username, $password,$synctimeout); + log_error("[sarg] XMLRPC sync is starting."); + foreach ($rs as $sh) { + // Only sync enabled replication targets + if ($sh['syncdestinenable']) { + $sync_to_ip = $sh['ipaddress']; + $port = $sh['syncport']; + $username = $sh['username'] ?: 'admin'; + $password = $sh['password']; + $protocol = $sh['syncprotocol']; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + sarg_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout); + } else { + log_error("[sarg] XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } } } - log_error("[sarg] xmlrpc sync is ending."); + log_error("[sarg] XMLRPC sync completed."); } } } /* do the actual XMLRPC sync */ -function sarg_do_xmlrpc_sync($sync_to_ip, $username, $password,$synctimeout) { +function sarg_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) { global $config, $g; - if (!$username) { - return; - } - - if (!$password) { + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("[sarg] A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; } - if (!$sync_to_ip) { - return; + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; } - if (!$synctimeout) { - $synctimeout="250"; - } - - $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, let's rely on the protocol selection */ - if ($port == "") { - if ($config['system']['webgui']['protocol'] == "http") { - $port = "80"; - } else { - $port = "443"; - } - } - $synchronizetoip .= $sync_to_ip; + $url = "{$protocol}://{$sync_to_ip}"; - /* xml will hold the sections to sync */ + /* XML will hold the sections to sync. */ $xml = array(); $xml['sarg'] = $config['installedpackages']['sarg']; $xml['sarguser'] = $config['installedpackages']['sarguser']; - /* assemble xmlrpc payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($xml) - ); - - /* set a few variables needed for sync code */ - $url = $synchronizetoip; - log_error("Beginning sarg XMLRPC sync to {$url}:{$port}."); + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($xml)); + + /* Set a few variables needed for sync code */ $method = 'pfsense.merge_installedpackages_section_xmlrpc'; $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); @@ -578,49 +585,45 @@ function sarg_do_xmlrpc_sync($sync_to_ip, $username, $password,$synctimeout) { if ($g['debug']) { $cli->setDebug(1); } - /* send our XMLRPC message and timeout after $synctimeout seconds */ + /* 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 sarg XMLRPC sync with {$url}:{$port}."; - log_error($error); + $error = "A communications error occurred while attempting XMLRPC sync with {$url}:{$port}."; + log_error("[sarg] {$error}"); file_notice("sync_settings", $error, "sarg Settings Sync", ""); } elseif ($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - $error = "An error code was received while attempting sarg XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[sarg] {$error}"); file_notice("sync_settings", $error, "sarg Settings Sync", ""); } else { - log_error("sarg XMLRPC sync successfully completed with {$url}:{$port}."); + log_error("[sarg] XMLRPC sync successfully completed with {$url}:{$port}."); } - /* tell sarg to reload our settings on the destionation sync host. */ + /* Tell sarg to reload our settings on the destionation sync host. */ $method = 'pfsense.exec_php'; $execcmd = "require_once('/usr/local/pkg/sarg.inc');\n"; $execcmd .= "sync_package_sarg();"; - /* assemble xmlrpc payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($execcmd) - ); + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); - log_error("sarg 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 sarg XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; - log_error($error); + $error = "A communications error occurred while attempting XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; + log_error("[sarg] {$error}"); file_notice("sync_settings", $error, "sarg Settings Sync", ""); } elseif ($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - $error = "An error code was received while attempting sarg XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[sarg] {$error}"); file_notice("sync_settings", $error, "sarg Settings Sync", ""); } else { - log_error("sarg XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); + log_error("[sarg] XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); } } diff --git a/config/sarg/sarg_sync.xml b/config/sarg/sarg_sync.xml index 9ae141e5..64e93fe3 100755 --- a/config/sarg/sarg_sync.xml +++ b/config/sarg/sarg_sync.xml @@ -42,7 +42,7 @@ ]]> </copyright> <name>sargsync</name> - <version>0.6.5</version> + <version>0.6.6</version> <title>Status: Sarg Sync</title> <include_file>/usr/local/pkg/sarg.inc</include_file> <tabs> @@ -82,9 +82,15 @@ <type>listtopic</type> </field> <field> - <fielddescr>Automatically Sync Sarg Configuration Changes.</fielddescr> + <fielddescr>Enable Sync</fielddescr> <fieldname>synconchanges</fieldname> - <description>Select a sync method for Sarg.</description> + <description> + <![CDATA[ + Select a sync method for Sarg.<br/><br/> + <strong>Important:</strong> While using "Sync to host(s) defined below", only sync from host A to B, A to C but <strong>do not</strong> enable XMLRPC sync <b>to</b> A. + This will result in a loop! + ]]> + </description> <type>select</type> <required/> <default_value>auto</default_value> @@ -97,7 +103,7 @@ <field> <fielddescr>Sync Timeout</fielddescr> <fieldname>synctimeout</fieldname> - <description>Select sync max wait time</description> + <description>XMLRPC timeout in seconds.</description> <type>select</type> <required/> <default_value>250</default_value> @@ -110,21 +116,45 @@ </options> </field> <field> - <fielddescr>Remote Server</fielddescr> + <fielddescr>Replication Targets</fielddescr> <fieldname>none</fieldname> <type>rowhelper</type> <rowhelper> <rowhelperfield> - <fielddescr>IP Address</fielddescr> + <fielddescr>Enable</fielddescr> + <fieldname>syncdestinenable</fieldname> + <description><![CDATA[Enable this host as a replication target]]></description> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>syncprotocol</fieldname> + <description><![CDATA[Choose the protocol used to sync with the destination host (HTTP or HTTPS).]]></description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>IP Address/Hostname</fielddescr> <fieldname>ipaddress</fieldname> - <description>IP Address of remote server</description> + <description><![CDATA[IP address or hostname of the destination host.]]></description> <type>input</type> - <size>20</size> + <size>40</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>syncport</fieldname> + <description><![CDATA[Choose the sync port of the destination host.]]></description> + <type>input</type> + <size>3</size> </rowhelperfield> <rowhelperfield> - <fielddescr>Password</fielddescr> + <fielddescr>Admin Password</fielddescr> <fieldname>password</fieldname> - <description>Password for remote server.</description> + <description><![CDATA[Password of the user "admin" on the destination host.]]></description> <type>password</type> <size>20</size> </rowhelperfield> diff --git a/config/shellcmd/shellcmd.xml b/config/shellcmd/shellcmd.xml index f6b34ee4..ea3144ff 100644 --- a/config/shellcmd/shellcmd.xml +++ b/config/shellcmd/shellcmd.xml @@ -124,8 +124,8 @@ Choose the shellcmd type.<br /><br /> <strong>shellcmd</strong> will run the command specified towards the end of the boot process.<br /> <strong>earlyshellcmd</strong> will run the command specified at the beginning of the boot process.<br /> - <strong>afterfilterchangeshellcmd</strong> will run after each filter_configure() call. - See <a href="https://github.com/pfsense/pfsense/blob/master/etc/inc/filter.inc">filter.inc source code</a> for "documentation". + <strong>afterfilterchangeshellcmd</strong> will run after each filter_configure() call. + See /etc/inc/filter.inc source code for "documentation". <span class="errmsg">N.B.: Only one entry of this type can be configured!</span><br /> <strong>disabled</strong> will save the command in package configuration but it will NOT run on boot.<br /><br /> See <a href="https://doc.pfsense.org/index.php/Executing_commands_at_boot_time">Executing commands at boot time</a> for detailed explanation. diff --git a/config/snort/snort.inc b/config/snort/snort.inc index b7d4299e..60959ad6 100755 --- a/config/snort/snort.inc +++ b/config/snort/snort.inc @@ -3737,103 +3737,117 @@ function snort_sync_on_changes() { /* Do not attempt a package sync while booting up or installing package */ if ($g['booting'] || $g['snort_postinstall']) { - log_error("[snort] No xmlrpc sync to CARP targets when booting up or during package reinstallation."); + log_error("[snort] Skipping XMLRPC sync when booting up or during package reinstallation."); return; } if (is_array($config['installedpackages']['snortsync']['config'])){ - $snort_sync=$config['installedpackages']['snortsync']['config'][0]; + $snort_sync = $config['installedpackages']['snortsync']['config'][0]; $synconchanges = $snort_sync['varsynconchanges']; - $synctimeout = $snort_sync['varsynctimeout']; + $synctimeout = $snort_sync['varsynctimeout'] ?: '150'; $syncdownloadrules = $snort_sync['vardownloadrules']; switch ($synconchanges){ case "manual": if (is_array($snort_sync['row'])){ $rs=$snort_sync['row']; - } - else{ - log_error("[snort] xmlrpc sync is enabled but there are no hosts configured as replication targets."); + } else { + log_error("[snort] XMLRPC sync is enabled but there are no hosts configured as replication targets."); return; } break; case "auto": - if (is_array($config['hasync'])) { - $system_carp=$config['hasync']; - $rs[0]['varsyncipaddress']=$system_carp['synchronizetoip']; - $rs[0]['varsyncusername']=$system_carp['username']; - $rs[0]['varsyncpassword']=$system_carp['password']; - $rs[0]['varsyncsnortstart']="no"; - if ($system_carp['synchronizetoip'] ==""){ - log_error("[snort] xmlrpc sync is enabled but there are no system backup hosts configured as replication targets."); - return; - } + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; + $rs[0]['varsyncipaddress'] = $system_carp['synchronizetoip']; + $rs[0]['varsyncusername'] = $system_carp['username']; + $rs[0]['varsyncpassword'] = $system_carp['password']; + $rs[0]['varsyncsnortstart'] = FALSE; + $rs[0]['varsyncdestinenable'] = FALSE; + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['varsyncprotocol'] = "http"; + $rs[0]['varsyncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['varsyncprotocol'] = "https"; + $rs[0]['varsyncport'] = $config['system']['webgui']['port'] ?: '443'; } - else{ - log_error("[snort] xmlrpc sync is enabled but there are no system backup hosts configured as replication targets."); + if ($system_carp['synchronizetoip'] == "") { + log_error("[snort] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); return; + } else { + $rs[0]['varsyncdestinenable'] = TRUE; } + } else { + log_error("[snort] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } break; default: return; - break; + break; } if (is_array($rs)){ - log_error("[snort] Snort pkg xmlrpc sync is starting."); - foreach($rs as $sh){ - if ($sh['varsyncsnortstart']) - $syncstartsnort = $sh['varsyncsnortstart']; - else - $syncstartsnort = "OFF"; - $sync_to_ip = $sh['varsyncipaddress']; - $port = $sh['varsyncport']; - $password = $sh['varsyncpassword']; - if($sh['varsyncusername']) - $username = $sh['varsyncusername']; - else - $username = 'admin'; - if($password && $sync_to_ip) - snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, $password, $synctimeout, $syncstartsnort); + log_error("[snort] XMLRPC sync is starting."); + foreach ($rs as $sh){ + // Only sync enabled replication targets + if ($sh['varsyncdestinenable']) { + if ($sh['varsyncsnortstart']) { + $syncstartsnort = $sh['varsyncsnortstart']; + } else { + $syncstartsnort = "OFF"; + } + $sync_to_ip = $sh['varsyncipaddress']; + $port = $sh['varsyncport']; + $password = $sh['varsyncpassword']; + $protocol = $sh['varsyncprotocol']; + $error = ''; + $success = TRUE; + $username = $sh['varsyncusername'] ?: 'admin'; + if ($password == "") { + $error = "Password parameter is empty. "; + $success = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address. "; + $success = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $success = FALSE; + } + if ($success) { + snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $protocol, $username, $password, $synctimeout, $syncstartsnort); + } else { + log_error("[snort] XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } + } } - log_error("[snort] Snort pkg xmlrpc sync completed."); + log_error("[snort] XMLRPC sync completed."); } } } /* Do the actual XMLRPC sync */ -function snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, $password, $synctimeout, $syncstartsnort) { +function snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $protocol, $username, $password, $synctimeout = 150, $syncstartsnort) { global $config, $g; /* Do not attempt a package sync while booting up or installing package */ if ($g['booting'] || $g['snort_postinstall']) { - log_error("[snort] No xmlrpc sync to CARP targets when booting up or during package reinstallation."); + log_error("[snort] Skipping XMLRPC sync when booting up or during package reinstallation."); return; } - if(!$username || !$password || !$sync_to_ip) { - log_error("[snort] A required XMLRPC sync parameter (user, host IP or password) is empty ... aborting pkg sync"); + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("[snort] A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; } - /* Test key variables and set defaults if empty */ - if(!$synctimeout) - $synctimeout=150; - - $xmlrpc_sync_neighbor = $sync_to_ip; - if($config['system']['webgui']['protocol'] != "") { - $synchronizetoip = $config['system']['webgui']['protocol']; - $synchronizetoip .= "://"; - } - if ($port == "") - $port = $config['system']['webgui']['port']; - /* if port is empty let's rely on the protocol selection */ - if($port == "") { - if($config['system']['webgui']['protocol'] == "http") - $port = "80"; - else - $port = "443"; + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; } - $synchronizetoip .= $sync_to_ip; - $url = $synchronizetoip; + + $url = "{$protocol}://{$sync_to_ip}"; /*************************************************/ /* Send over any auto-SID management files */ @@ -3847,25 +3861,26 @@ function snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, $method = 'pfsense.exec_php'; $params = array( XML_RPC_encode($password), XML_RPC_encode($payload) ); - log_error("[snort] Snort XMLRPC CARP sync sending auto-SID conf files to {$url}:{$port}."); + log_error("[snort] Snort XMLRPC sync sending auto-SID conf files to {$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); $error = ""; if(!$resp) { - $error = "A communications error occurred while attempting Snort XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file); + $error = "A communications error occurred while attempting Snort XMLRPC sync with {$url}:{$port}. Failed to transfer file: " . basename($file); log_error($error); file_notice("sync_settings", $error, "Snort Settings Sync", ""); } elseif($resp->faultCode()) { - $error = "An error code was received while attempting Snort XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); + $error = "An error code was received while attempting Snort XMLRPC sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "Snort Settings Sync", ""); } } - if (!empty($sid_files) && $error == "") - log_error("[snort] Snort pkg XMLRPC CARP sync auto-SID conf files success with {$url}:{$port} (pfsense.exec_php)."); + if (!empty($sid_files) && $error == "") { + log_error("[snort] XMLRPC sync auto-SID conf files success with {$url}:{$port} (pfsense.exec_php)."); + } /*************************************************/ /* Send over any IPREP IP List files */ @@ -3879,25 +3894,26 @@ function snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, $method = 'pfsense.exec_php'; $params = array( XML_RPC_encode($password), XML_RPC_encode($payload) ); - log_error("[snort] Snort XMLRPC CARP sync sending IPREP files to {$url}:{$port}."); + log_error("[snort] Snort XMLRPC sync sending IPREP files to {$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); $error = ""; - if(!$resp) { - $error = "A communications error occurred while attempting Snort XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file); + if (!$resp) { + $error = "A communications error occurred while attempting Snort XMLRPC sync with {$url}:{$port}. Failed to transfer file: " . basename($file); log_error($error); file_notice("sync_settings", $error, "Snort Settings Sync", ""); - } elseif($resp->faultCode()) { - $error = "An error code was received while attempting Snort XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting Snort XMLRPC sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "Snort Settings Sync", ""); } } - if (!empty($sid_files) && $error == "") - log_error("[snort] Snort pkg XMLRPC CARP sync IPREP files success with {$url}:{$port} (pfsense.exec_php)."); + if (!empty($sid_files) && $error == "") { + log_error("[snort] XMLRPC sync IPREP files success with {$url}:{$port} (pfsense.exec_php)."); + } /**************************************************/ /* Send over the <snortglobal> portion of the */ @@ -3911,7 +3927,7 @@ function snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, XML_RPC_encode($xml) ); - log_error("[snort] Beginning Snort pkg configuration XMLRPC sync to {$url}:{$port}."); + log_error("[snort] Beginning package configuration 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); @@ -3919,16 +3935,16 @@ function snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, /* send our XMLRPC message and timeout after defined sync timeout value*/ $resp = $cli->send($msg, $synctimeout); - if(!$resp) { + if (!$resp) { $error = "A communications error occurred while attempting snort XMLRPC sync with {$url}:{$port}."; log_error($error); file_notice("sync_settings", $error, "snort Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $error = "An error code was received while attempting snort XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "snort Settings Sync", ""); } else { - log_error("[snort] Snort pkg configuration XMLRPC sync successfully completed with {$url}:{$port}."); + log_error("[snort] Package configuration XMLRPC sync successfully completed with {$url}:{$port}."); } $downloadrulescmd = ""; @@ -3992,16 +4008,16 @@ EOD; $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); $cli->setCredentials($username, $password); $resp = $cli->send($msg, $synctimeout); - if(!$resp) { + if (!$resp) { $error = "A communications error occurred while attempting snort XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; log_error($error); file_notice("sync_settings", $error, "snort Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $error = "An error code was received while attempting snort XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "snort Settings Sync", ""); } else { - log_error("[snort] Snort pkg XMLRPC reload configuration success with {$url}:{$port} (pfsense.exec_php)."); + log_error("[snort] XMLRPC reload configuration success with {$url}:{$port} (pfsense.exec_php)."); } /*************************************************/ @@ -4016,16 +4032,16 @@ EOD; log_error("[snort] Snort XMLRPC sending {$url}:{$port} cmd to execute configuration reload."); $msg2 = new XML_RPC_Message($method, $params2); $resp = $cli->send($msg2, $synctimeout); - if(!$resp) { + if (!$resp) { $error = "A communications error occurred while attempting snort XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; log_error($error); file_notice("sync_settings", $error, "snort Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $error = "An error code was received while attempting snort XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "snort Settings Sync", ""); } else { - log_error("[snort] Snort pkg XMLRPC reload configuration success with {$url}:{$port} (pfsense.exec_php)."); + log_error("[snort] XMLRPC reload configuration success with {$url}:{$port} (pfsense.exec_php)."); } } diff --git a/config/snort/snort_sync.xml b/config/snort/snort_sync.xml index 46922822..6b9e6a7f 100755 --- a/config/snort/snort_sync.xml +++ b/config/snort/snort_sync.xml @@ -172,11 +172,11 @@ </options> </rowhelperfield> <rowhelperfield> - <fielddescr>IP-Address</fielddescr> + <fielddescr>IP Address/Hostname</fielddescr> <fieldname>varsyncipaddress</fieldname> - <description><![CDATA[IP Address of the destination host.]]></description> + <description><![CDATA[IP address or hostname of the destination host.]]></description> <type>input</type> - <size>15</size> + <size>40</size> </rowhelperfield> <rowhelperfield> <fielddescr>Port</fielddescr> @@ -202,8 +202,6 @@ </rowhelper> </field> </fields> - <custom_delete_php_command> - </custom_delete_php_command> <custom_php_resync_config_command> write_config("Snort pkg: saved changes to XMLRPC sync configuration.");snort_sync_on_changes(); </custom_php_resync_config_command> diff --git a/config/spamd/spamd.inc b/config/spamd/spamd.inc index 548a2934..13edb7ce 100644 --- a/config/spamd/spamd.inc +++ b/config/spamd/spamd.inc @@ -299,49 +299,6 @@ function remove_spaces($string) { return $string; } -function sync_spamd_config_to_backup() { - global $config; - if (is_array($config['installedpackages']['carpsettings']['config'])) { - foreach ($config['installedpackages']['carpsettings']['config'] as $carp) { - if ($carp['synchronizetoip'] != "") { - $synctoip = $carp['synchronizetoip']; - $password = $carp['password']; - if ($config['system']['username']) { - $username = $config['system']['username']; - } else { - $username = "admin"; - } - } - } - } - if ($synctoip and $password) { - 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"; - } - } - $params = array(XML_RPC_encode($password),XML_RPC_encode($xml)); - /* create files to sync array */ - $filetosync = array("/var/db/spamd", "/var/db/whitelist.txt"); - /* loop through files to sync list and sync them up */ - foreach ($filetosync as $f2s) { - $f2c_contents = file_get_contents($f2s); - xmlrpc_sync_file($url, $password, $f2s, $f2c_contents, $port); - } - /* signal remote process config reload */ - xmlrpc_exec_shell($url, $password, "/usr/bin/killall -HUP spamlogd", $port); - xmlrpc_exec_shell($url, $password, "/usr/bin/killall -HUP spamd", $port); - } -} - function custom_php_install_command() { global $config; system("touch /var/db/whitelist.txt"); diff --git a/config/squid3/31/squid.inc b/config/squid3/31/squid.inc index d565810c..df900e43 100644 --- a/config/squid3/31/squid.inc +++ b/config/squid3/31/squid.inc @@ -1854,8 +1854,8 @@ function squid_sync_on_changes() { $synctimeout = $squid_sync['synctimeout']; switch ($synconchanges){ case "manual": - if (is_array($squid_sync[row])){ - $rs=$squid_sync[row]; + if (is_array($squid_sync['row'])){ + $rs=$squid_sync['row']; } else{ log_error("[squid] xmlrpc sync is enabled but there is no hosts to push on squid config."); @@ -1863,8 +1863,8 @@ function squid_sync_on_changes() { } break; case "auto": - if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){ - $system_carp=$config['installedpackages']['carpsettings']['config'][0]; + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; $rs[0]['ipaddress']=$system_carp['synchronizetoip']; $rs[0]['username']=$system_carp['username']; $rs[0]['password']=$system_carp['password']; diff --git a/config/squid3/33/squid.inc b/config/squid3/33/squid.inc index 0f71def8..57b49d5f 100755 --- a/config/squid3/33/squid.inc +++ b/config/squid3/33/squid.inc @@ -2314,8 +2314,8 @@ function squid_sync_on_changes() { $synctimeout = $squid_sync['synctimeout']; switch ($synconchanges){ case "manual": - if (is_array($squid_sync[row])){ - $rs=$squid_sync[row]; + if (is_array($squid_sync['row'])){ + $rs=$squid_sync['row']; } else{ log_error("[squid] xmlrpc sync is enabled but there is no hosts to push on squid config."); @@ -2323,8 +2323,8 @@ function squid_sync_on_changes() { } break; case "auto": - if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){ - $system_carp=$config['installedpackages']['carpsettings']['config'][0]; + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; $rs[0]['ipaddress']=$system_carp['synchronizetoip']; $rs[0]['username']=$system_carp['username']; $rs[0]['password']=$system_carp['password']; diff --git a/config/squid3/34/squid.inc b/config/squid3/34/squid.inc index 07d1da26..973bbf05 100755 --- a/config/squid3/34/squid.inc +++ b/config/squid3/34/squid.inc @@ -452,9 +452,6 @@ function squid_restart_services() { function squid_install_command() { global $config, $g; - update_output_window("This operation may take quite some time, please be patient. Do not press stop or attempt to navigate away from this page during this process."); - update_output_window("Checking if there is configuration to migrate... One moment please..."); - /* Set storage system for nanobsd */ if (!is_array($config['installedpackages']['squidcache'])) { $config['installedpackages']['squidcache'] = array(); @@ -502,8 +499,9 @@ function squid_install_command() { // remove unwanted PBI rc script unlink_if_exists("/usr/local/etc/rc.d/squid"); - // remove broken cronjob possibly left over after 'Clear Cache on Log Rotate' misfeature + // remove broken cronjobs possibly left over after 'Clear Cache on Log Rotate' misfeature install_cron_job("/usr/local/pkg/swapstate_check.php clean;", false); + install_cron_job("/bin/rm /var/squid/cache/swap.state;", false); } @@ -514,14 +512,15 @@ function squid_deinstall_command() { squid_install_cron(false); /* kill all running services */ - update_output_window("Stopping and removing services..."); mwexec('/usr/local/etc/rc.d/sqp_monitor.sh stop'); - mwexec("/bin/ps awux | /usr/bin/grep '[s]quid' | /usr/bin/awk '{ print $2 }' | /usr/bin/xargs kill"); + mwexec("/bin/ps awux | /usr/bin/egrep -i '[s]quid -f|\([s]quid\)' | /usr/bin/awk '{ print $2 }' | /usr/bin/xargs kill"); + mwexec("/bin/ps awux | /usr/bin/grep '[d]iskd' | /usr/bin/awk '{ print $2 }' | /usr/bin/xargs kill"); mwexec("/bin/ps awux | /usr/bin/grep '[d]nsserver' | /usr/bin/awk '{ print $2 }' | /usr/bin/xargs kill"); mwexec("/bin/ps awux | /usr/bin/grep '[u]nlinkd' | /usr/bin/awk '{ print $2 }' | /usr/bin/xargs kill"); /* delete rc scripts */ unlink_if_exists('/usr/local/etc/rc.d/sqp_monitor.sh'); + unlink_if_exists('/usr/local/etc/rc.d/squid.sh'); /* clean up created directories if 'Keep Settings/Data' is disabled */ if (is_array($config['installedpackages']['squidcache'])) { @@ -539,8 +538,6 @@ function squid_deinstall_command() { $keep = ($squidsettings['keep_squid_data'] ? true : false); if (!$keep) { - update_output_window("Removing cache and logs ... One moment please..."); - update_output_window("This operation may take quite some time, please be patient. Do not press stop or attempt to navigate away from this page during this process."); if (is_dir("{$cachedir}")) { if (substr($cachedir, 0, 11) === "/var/squid/") { mwexec_bg("/bin/rm -rf {$cachedir}"); @@ -555,7 +552,6 @@ function squid_deinstall_command() { log_error("[squid] Will NOT delete Squid log dir '{$logdir}' since it is not located under /var/squid. Delete manually if required."); } } - update_output_window("Removing remaining Squid directories ... One moment please..."); $dirs = array("/var/run/squid", "/var/squid"); foreach ($dirs as $dir) { if (is_dir("{$dir}")) { @@ -567,7 +563,6 @@ function squid_deinstall_command() { // remove antivirus integration features squid_antivirus_deinstall_command(); - update_output_window("Reloading filter..."); filter_configure(); /* Remove package settings from config if 'Keep Settings/Data' is disabled */ @@ -600,6 +595,9 @@ function squid_deinstall_command() { if (is_array($config['installedpackages']['squidreverseredir'])) { unset($config['installedpackages']['squidreverseredir']); } + if (is_array($config['installedpackages']['squidreverseuri'])) { + unset($config['installedpackages']['squidreverseuri']); + } if (is_array($config['installedpackages']['squidsync'])) { unset($config['installedpackages']['squidsync']); } @@ -613,7 +611,6 @@ function squid_deinstall_command() { unset($config['installedpackages']['squidusers']); } } - update_output_window("Squid3 has been uninstalled."); } /* Migrate configuration from god knows which Squid package versions */ @@ -698,7 +695,6 @@ function squid_upgrade_config() { /* unset broken antivirus settings */ squid_antivirus_upgrade_config(); - update_output_window("Writing configuration... One moment please..."); write_config(); } @@ -888,8 +884,8 @@ function squid_validate_nac($post, &$input_errors) { $allowed_subnets = explode("\n", $post['allowed_subnets']); foreach ($allowed_subnets as $subnet) { $subnet = trim($subnet); - if (!empty($subnet) && !is_subnet($subnet)) { - $input_errors[] = "The subnet '$subnet' is not a valid CIDR range."; + if (!empty($subnet) && !is_subnet($subnet) && $subnet != "all") { + $input_errors[] = "'Allowed Subnets' must be a valid CIDR range or 'all'. The subnet '$subnet' is not valid."; } } @@ -953,7 +949,7 @@ function squid_validate_traffic($post, &$input_errors) { if (!empty($post['quick_abort_min'])) { $value = trim($post['quick_abort_min']); - if ((!is_numericint($value)) && ($value !== -1)) { + if ((!is_numericint($value)) && ($value != "-1")) { $input_errors[] = "'Finish when remaining KB' must contain a positive integer or '-1'."; } } @@ -971,6 +967,14 @@ function squid_validate_traffic($post, &$input_errors) { $input_errors[] = "'Finish when remaining %' must contain valid percentage (1-100)."; } } + + if ($post['throttle_specific'] == "on") { + $others = trim($post['throttle_others']); + if ($post['throttle_binaries'] == "" && $post['throttle_cdimages'] == "" && $post['throttle_multimedia'] == "" && $others == "") { + $input_errors[] = "'Throttle Only Specific Extensions' enabled but no extensions specified. Select some options under 'Squid Transfer Extension Settings' or disable this option."; + } + } + } /* Proxy Server: Authentication input validation */ @@ -1065,12 +1069,21 @@ function squid_resync_general() { // cert, key, version, cipher, options, clientca, cafile, capath, crlfile, dhparams, sslflags, sslcontext $crt_pk = SQUID_CONFBASE . "/serverkey.pem"; $crt_capath = SQUID_LOCALBASE . "/share/certs/"; + /* XXX: Bug #4453 + * http://wiki.squid-cache.org/ConfigExamples/Intercept/SslBumpExplicit#Modern_DH.2Fciphers_usage + */ + //$sslproxy_cipher = "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS"; + $sslproxy_cipher = "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:HIGH:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS"; + $sslproxy_dhparams = "/etc/dh-parameters.2048"; + $sslproxy_options = "NO_SSLv2,NO_SSLv3,SINGLE_DH_USE"; file_put_contents($crt_pk, base64_decode($srv_cert['prv']) . base64_decode($srv_cert['crt'])); $sslcrtd_children = ($settings['sslcrtd_children'] ? $settings['sslcrtd_children'] : 5); - $ssl_interception .= "ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=" . ($sslcrtd_children*2) . "MB cert={$crt_pk} capath={$crt_capath}\n"; + $ssl_interception .= "ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=" . ($sslcrtd_children*2) . "MB cert={$crt_pk} capath={$crt_capath} cipher={$sslproxy_cipher} dhparams={$sslproxy_dhparams} options={$sslproxy_options}\n"; $interception_checks = "sslcrtd_program " . SQUID_LOCALBASE . "/libexec/squid/ssl_crtd -s " . SQUID_SSL_DB . " -M 4MB -b 2048\n"; $interception_checks .= "sslcrtd_children {$sslcrtd_children}\n"; $interception_checks .= "sslproxy_capath {$crt_capath}\n"; + $interception_checks .= "sslproxy_options {$sslproxy_options}\n"; + $interception_checks .= "sslproxy_cipher {$sslproxy_cipher}\n"; if (preg_match("/sslproxy_cert_error/", $settings["interception_checks"])) { $interception_checks .= "sslproxy_cert_error allow all\n"; } @@ -1620,6 +1633,7 @@ EOD; $conf .= "delay_access 1 allow throttle_exts\n"; $conf .= "delay_access 1 deny allsrc\n"; } else { + unlink_if_exists(SQUID_ACLDIR . '/throttle_exts.acl'); $conf .= "delay_access 1 allow allsrc\n"; } @@ -1766,7 +1780,7 @@ function squid_resync_auth() { $conf .= "http_access allow $acl\n"; } } else { - $noauth = implode(' ', explode("\n", base64_decode($settings['no_auth_hosts']))); + $noauth = implode(' ', explode("\n", sq_text_area_decode($settings['no_auth_hosts']))); if (!empty($noauth)) { $conf .= "acl noauth src $noauth\n"; $valid_acls[] = 'noauth'; @@ -2139,28 +2153,45 @@ function squid_generate_rules($type) { /* XMLRPC sync configuration */ function squid_sync_on_changes() { - global $config, $g; + global $config; + if (is_array($config['installedpackages']['squidsync']['config'])) { $squid_sync = $config['installedpackages']['squidsync']['config'][0]; $synconchanges = $squid_sync['synconchanges']; - $synctimeout = $squid_sync['synctimeout']; + $synctimeout = $squid_sync['synctimeout'] ?: '250'; switch ($synconchanges) { case "manual": if (is_array($squid_sync['row'])) { $rs = $squid_sync['row']; } else { - log_error("[squid] XMLRPC sync is enabled but there is no hosts to push on Squid config."); + log_error("[squid] XMLRPC sync is enabled but there are no hosts configured as replication targets."); return; } break; case "auto": - if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])) { - $system_carp = $config['installedpackages']['carpsettings']['config'][0]; + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; $rs[0]['ipaddress'] = $system_carp['synchronizetoip']; $rs[0]['username'] = $system_carp['username']; $rs[0]['password'] = $system_carp['password']; + $rs[0]['syncdestinenable'] = FALSE; + + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['syncprotocol'] = "http"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['syncprotocol'] = "https"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '443'; + } + if ($system_carp['synchronizetoip'] == "") { + log_error("[squid] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } else { + $rs[0]['syncdestinenable'] = TRUE; + } } else { - log_error("[squid] XMLRPC sync is enabled but there is no system backup hosts to push Squid config."); + log_error("[squid] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); return; } break; @@ -2171,45 +2202,56 @@ function squid_sync_on_changes() { if (is_array($rs)) { log_error("[squid] 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) { - squid_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout); + // Only sync enabled replication targets + if ($sh['syncdestinenable']) { + $sync_to_ip = $sh['ipaddress']; + $port = $sh['syncport']; + $username = $sh['username'] ?: 'admin'; + $password = $sh['password']; + $protocol = $sh['syncprotocol']; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + squid_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout); + } else { + log_error("[squid] XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } } } - log_error("[squid] XMLRPC sync is ending."); + log_error("[squid] XMLRPC sync completed."); } - } + } } /* Perform the actual XMLRPC sync */ -function squid_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout) { +function squid_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) { global $config, $g; - if (!$username || !$password || !$sync_to_ip) { + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("[squid] A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; } - if (!$synctimeout) { - $synctimeout = 250; + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; } - $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 let's rely on the protocol selection */ - if ($port == "") { - $port = $config['system']['webgui']['protocol'] == "http" ? "80" : "443"; - } - $synchronizetoip .= $sync_to_ip; + $url = "{$protocol}://{$sync_to_ip}"; /* XML will hold the sections to sync */ $xml = array(); @@ -2225,14 +2267,9 @@ function squid_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout) { $xml['squidauth'] = $config['installedpackages']['squidauth']; $xml['squidusers'] = $config['installedpackages']['squidusers']; /* Assemble XMLRPC payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($xml) - ); + $params = array(XML_RPC_encode($password), XML_RPC_encode($xml)); /* Set a few variables needed for sync */ - $url = $synchronizetoip; - log_error("[squid] Beginning 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); @@ -2243,14 +2280,14 @@ function squid_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout) { /* Send our XMLRPC message and timeout after defined sync timeout value*/ $resp = $cli->send($msg, $synctimeout); if (!$resp) { - $error = "[squid] Communication error occurred while attempting XMLRPC sync with {$url}:{$port}."; - log_error($error); + $error = "A communication error occurred while attempting XMLRPC sync with {$url}:{$port}."; + log_error("[squid] {$error}"); file_notice("sync_settings", $error, "Squid Settings Sync", ""); } elseif ($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - $error = "[squid] An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[squid] {$error}"); file_notice("sync_settings", $error, "Squid Settings Sync", ""); } else { log_error("[squid] XMLRPC sync successfully completed with {$url}:{$port}."); @@ -2261,25 +2298,21 @@ function squid_do_xmlrpc_sync($sync_to_ip, $username, $password, $synctimeout) { $execcmd = "require_once('/usr/local/pkg/squid.inc');\n"; $execcmd .= "squid_resync('yes');"; /* Assemble XMLRPC payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($execcmd) - ); + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); - log_error("[squid] 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 = "[squid] Communication error occurred while attempting XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; - log_error($error); + $error = "A communication error occurred while attempting XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; + log_error("[squid] {$error}"); file_notice("sync_settings", $error, "Squid Settings Sync", ""); } elseif ($resp->faultCode()) { $cli->setDebug(1); $resp = $cli->send($msg, $synctimeout); - $error = "[squid] An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[squid] {$error}"); file_notice("sync_settings", $error, "Squid Settings Sync", ""); } else { log_error("[squid] XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); diff --git a/config/squid3/34/squid.xml b/config/squid3/34/squid.xml index a7b53fca..28326d7f 100644 --- a/config/squid3/34/squid.xml +++ b/config/squid3/34/squid.xml @@ -399,7 +399,7 @@ <fieldname>private_subnet_proxy_off</fieldname> <description> <![CDATA[ - Do not forward traffic to Private Address Space (RFC 1918) <strong>destinations</strong> through the proxy server but let is pass directly through the firewall. + Do not forward traffic to Private Address Space (RFC 1918) <strong>destinations</strong> through the proxy server but let it pass directly through the firewall. ]]> </description> <type>checkbox</type> diff --git a/config/squid3/34/squid_antivirus.inc b/config/squid3/34/squid_antivirus.inc index 9a678fa9..fe8406e7 100644 --- a/config/squid3/34/squid_antivirus.inc +++ b/config/squid3/34/squid_antivirus.inc @@ -41,11 +41,20 @@ function squid_check_clamav_user() { if (SQUID_BASE == '/usr/local') { return; } else { - if (!exec("/usr/sbin/pw usershow clamav")) { - mwexec("/usr/sbin/pw useradd clamav -G wheel -u 9595 -s /sbin/nologin"); - } - if (!exec("/usr/sbin/pw groupshow wheel | /usr/bin/grep clamav")) { - mwexec("/usr/sbin/pw usermod clamav -G wheel"); + /* + * Check whether clamav user already exists and is a member of wheel group. + * If the account already exists, modify the UID to 9595, otherwise things blow up because the PBI clusterfuck adds the account with UID=106. + * If the account does not exist yes because PBI screwed things once again, create it with the proper UID. + * If clamav user is not a member of wheel group, add it there as well and avoid re-adding it to wheel everytime this code runs. + * Note that the clamav group (GID=106) added by PBI is irrelevant because it's not used for anything. + */ + $_gc = exec("/usr/sbin/pw groupshow wheel | /usr/bin/grep clamav", $group_ex_output, $group_ex_return); + $group_arg = ($group_ex_return != 0 ? "-G wheel" : ""); + $_gc = exec("/usr/sbin/pw usershow clamav", $user_ex_output, $user_ex_return); + $user_arg = ($user_ex_return == 0 ? "mod" : "add"); + $_gc = exec("/usr/sbin/pw user{$user_arg} clamav {$group_arg} -u 9595 -s /sbin/nologin", $user_ex_output, $user_ex_return); + if ($user_ex_return != 0) { + log_error("[squid] Could not change clamav user settings. " . serialize($user_ex_output)); } } } @@ -55,14 +64,22 @@ function squid_check_antivirus_dirs() { $dirs = array( "/var/run/c-icap" => "clamav", "/var/log/c-icap" => "clamav", + + ); + foreach ($dirs as $dir_path => $dir_user) { + safe_mkdir($dir_path, 0755); + chown($dir_path, $dir_user); + chgrp($dir_path, "wheel"); + } + /* These ClamAV dirs MUST be chown-ed recursively, see the notes on PBI idiocy in squid_check_clamav_user() */ + $dirs = array( "/var/log/clamav" => "clamav", "/var/run/clamav" => "clamav", "/var/db/clamav" => "clamav" ); foreach ($dirs as $dir_path => $dir_user) { safe_mkdir($dir_path, 0755); - chown($dir_path, $dir_user); - chgrp($dir_path, "wheel"); + squid_chown_recursive($dir_path, $dir_user, "wheel"); } } @@ -98,7 +115,7 @@ function squid_install_freshclam_cron($should_install) { /* Manually update ClamAV virus definitions via the GUI button */ function squid_update_clamav() { squid_check_antivirus_dirs(); - log_error("[squid] Updating ClamAV definitions now... This will take a while. Check /var/log/clamav/freshclam.log for progress information."); + log_error("[squid] Updating ClamAV definitions now... This will take a while. Check freshclam log on the 'Real Time' tab for progress information."); mwexec_bg(SQUID_BASE . "/bin/freshclam --config-file=" . SQUID_BASE . "/etc/freshclam.conf"); } @@ -147,23 +164,11 @@ function squid_antivirus_install_command() { /* Run on Squid package uninstall */ function squid_antivirus_deinstall_command() { global $config, $keep; - /* kill all running services */ - if (is_process_running("c-icap")) { - mwexec('/bin/echo -n "stop" > /var/run/c-icap/c-icap.ctl'); - } - mwexec("/bin/ps awux | /usr/bin/grep '[c]lamd' | /usr/bin/awk '{ print $2 }' | /usr/bin/xargs kill"); + /* Stop all running services, remove rc scripts and cronjobs */ + squid_stop_antivirus(); mwexec("/bin/ps awux | /usr/bin/grep '[f]reshclam' | /usr/bin/awk '{ print $2 }' | /usr/bin/xargs kill"); - /* remove cronjobs */ - squid_install_freshclam_cron(false); - - /* delete rc scripts */ - unlink_if_exists('/usr/local/etc/rc.d/squid.sh'); - unlink_if_exists("/usr/local/etc/rc.d/c-icap.sh"); - unlink_if_exists('/usr/local/etc/rc.d/clamd.sh'); - /* clean up created PBI symlinks */ - update_output_window("Finishing package cleanup."); if (SQUID_LOCALBASE != '/usr/local') { $ln_icap = array('bin/c-icap', 'bin/c-icap-client', 'c-icap-config', 'c-icap-libicapapi-config', 'c-icap-stretch', 'lib/c_icap', 'share/c_icap', 'etc/c-icap'); foreach ($ln_icap as $ln) { @@ -185,7 +190,6 @@ function squid_antivirus_deinstall_command() { $keep = ($squidsettings['keep_squid_data'] ? true : false); if (!$keep) { - update_output_window("Removing antivirus definitions and logs ... One moment please..."); $dirs = array("/var/run/c-icap", "/var/log/c-icap", "/var/log/clamav", "/var/run/clamav", "/var/db/clamav"); foreach ($dirs as $dir) { if (is_dir("{$dir}")) { @@ -212,7 +216,6 @@ function squid_antivirus_deinstall_command() { /* check if clamav/c_icap is enabled in rc.conf.local */ // XXX: This hasn't been used since 0.3.7; to be removed in future if (file_exists("/etc/rc.conf.local")) { - update_output_window("Removing antivirus services from /etc/rc.conf.local..."); $sample_file = file_get_contents("/etc/rc.conf.local"); $rcconf_local_m[0] = "@c_icap_enable(.*)\n@"; $rcconf_local_m[1] = "@clamav_clamd_enable(.*)\n@"; @@ -656,11 +659,11 @@ function squid_antivirus_put_raw_config($rawfiles) { break; case 'raw_freshclam_conf': $confdir = ""; - $conffile = "freshclam.conf"; + $conffile = "/freshclam.conf"; break; case 'raw_clamd_conf': $confdir = ""; - $conffile = "clamd.conf"; + $conffile = "/clamd.conf"; break; default: $confdir = ""; @@ -677,10 +680,11 @@ function squid_antivirus_put_raw_config($rawfiles) { /* Helper function for squid_antivirus_put_raw_config() */ function squid_antivirus_write_conffile($dir, $file, $text) { if ($file && $text) { - if (!file_put_contents(SQUID_LOCALBASE . "/etc" . "{$dir}" . "/{$file}", preg_replace("/\r\n/", "\n", base64_decode($text)), LOCK_EX)) { - log_error("[squid] Could not save '{$file}' configuration file."); + $cfgfile = SQUID_LOCALBASE . "/etc" . "{$dir}" . "{$file}"; + if (!file_put_contents("{$cfgfile}", preg_replace("/\r\n/", "\n", base64_decode($text)), LOCK_EX)) { + log_error("[squid] Could not save '{$cfgfile}' configuration file."); } else { - log_error("[squid] Saved '{$file}' configuration file."); + log_error("[squid] Saved '{$cfgfile}' configuration file."); } } } @@ -697,7 +701,7 @@ function squid_write_clamd_rcfile() { $rc['start'] = <<< EOD if [ ! -f /var/db/clamav/main.cvd -a ! -f /var/db/clamav/main.cld ]; then - echo "Missing /var/db/clamav/*.cvd or *.cld files. You must run freshclam first" + echo "Missing /var/db/clamav/*.cvd or *.cld files. You must run freshclam first!" exit 1 fi @@ -717,6 +721,7 @@ fi EOD; conf_mount_rw(); + log_error("[squid] Creating 'clamd.sh' rc script."); write_rcfile($rc); conf_mount_ro(); } @@ -730,6 +735,7 @@ function squid_write_cicap_rcfile() { $cicap_start_cmd = "LD_LIBRARY_PATH={$cicap_libdir} {$cicap_bin} -f {$cicap_conf}"; $cicap_stop_cmd = '/bin/echo -n "stop" > /var/run/c-icap/c-icap.ctl'; conf_mount_rw(); + log_error("[squid] Creating '{$c_icap_rcfile}' rc script."); write_rcfile(array( "file" => "{$c_icap_rcfile}", "start" => "{$cicap_start_cmd}", @@ -739,7 +745,7 @@ function squid_write_cicap_rcfile() { conf_mount_ro(); } -/* (Re)start antivirus services if AV features are enabled; otherwise stop and disable them */ +/* (Re)start antivirus services if AV features are enabled */ function squid_restart_antivirus() { global $config; if (is_array($config['installedpackages']['squidantivirus'])) { @@ -751,6 +757,7 @@ function squid_restart_antivirus() { // reconfigure and (re)start service as needed if enabled, otherwise stop them // do not (re)start antivirus services on boot if (platform_booting()) { + log_error("[squid] Skipping antivirus services (re)start on boot."); return; } @@ -758,7 +765,7 @@ function squid_restart_antivirus() { // Check clamav database if (count(glob("/var/db/clamav/*d")) == 0) { log_error("[squid] Missing /var/db/clamav/*.cvd or *.cld files. Running freshclam in background."); - log_error("[squid] Do NOT attempt to start ClamAV service until AV definitions are downloaded. Check /var/log/clamav/freshclam.log for progress information."); + log_error("[squid] Do NOT attempt to start ClamAV service until AV definitions are downloaded."); squid_update_clamav(); } elseif ($antivirus_config['clamav_safebrowsing'] == "on" && !is_file("/var/db/clamav/safebrowsing.cvd")) { log_error("[squid] Google Safe Browsing is enabled but missing safebrowsing.cvd definitions. Running freshclam in background."); @@ -789,31 +796,55 @@ function squid_restart_antivirus() { squid_write_cicap_rcfile(); } if (is_process_running("c-icap")) { + log_error("[squid] Reloading C-ICAP..."); mwexec_bg('/bin/echo -n "reconfigure" > /var/run/c-icap/c-icap.ctl'); } else { + log_error("[squid] Starting C-ICAP..."); mwexec_bg("{$c_icap_rcfile} start"); } } else { // stop AV services and disable all C-ICAP/AV features log_error("[squid] Antivirus features disabled."); - if (is_process_running("clamd")) { - log_error("[squid] Stopping and disabling ClamAV..."); - mwexec("/usr/bin/killall clamd"); - } - unlink_if_exists("/usr/local/etc/rc.d/clamd.sh"); - - // freshclam cronjob - squid_install_freshclam_cron(false); + squid_stop_antivirus(); + } +} - // check c-icap rcfile +/* Stop AV services and disable all C-ICAP/AV features */ +function squid_stop_antivirus() { + // Stop C-ICAP + if (is_process_running("c-icap")) { + log_error("[squid] Stopping and disabling C-ICAP..."); + mwexec('/bin/echo -n "stop" > /var/run/c-icap/c-icap.ctl'); + sleep(5); if (is_process_running("c-icap")) { - log_error("[squid] Stopping and disabling C-ICAP..."); - mwexec('/bin/echo -n "stop" > /var/run/c-icap/c-icap.ctl'); + log_error("[squid] C-ICAP still running, forcibly killing c-icap process(es)."); + mwexec("/bin/ps awux | /usr/bin/grep '[c]-icap' | /usr/bin/awk '{ print $2 }' | /usr/bin/xargs kill -9"); } - unlink_if_exists("/usr/local/etc/rc.d/c-icap.sh"); } + unlink_if_exists("/usr/local/etc/rc.d/c-icap.sh"); + + // Stop ClamAV + if (is_process_running("clamd")) { + log_error("[squid] Stopping and disabling ClamAV..."); + mwexec("/usr/bin/killall clamd"); + // sleep for a couple of seconds to give clamd a chance to perform clean exit + for ($i = 0; $i < 10; $i++) { + if (is_process_running('clamd')) { + sleep(1); + } + } + } + if (is_process_running("clamd")) { + log_error("[squid] ClamAV still running, forcibly killing clamd process(es)."); + mwexec("/usr/bin/killall -9 clamd"); + } + unlink_if_exists("/usr/local/etc/rc.d/clamd.sh"); + + // Remove freshclam cronjob + squid_install_freshclam_cron(false); } + /* * Input validation */ diff --git a/config/squid3/34/squid_antivirus.xml b/config/squid3/34/squid_antivirus.xml index 44820257..495ef342 100755 --- a/config/squid3/34/squid_antivirus.xml +++ b/config/squid3/34/squid_antivirus.xml @@ -42,8 +42,8 @@ ]]> </copyright> <name>squidantivirus</name> - <version>0.4.0</version> - <title>Proxy server: Antivirus</title> + <version>0.4.1</version> + <title>Proxy Server: Antivirus</title> <include_file>/usr/local/pkg/squid.inc</include_file> <tabs> <tab> @@ -148,7 +148,7 @@ ]]> </description> <type>input</type> - <cols>60</cols> + <size>60</size> </field> <field> @@ -173,7 +173,7 @@ Select the desired frequency here.<br/><br/> <input name='update_av' id='update_av' type='submit' value='Update AV' /> Click the button to update AV databases now.<br/> - <strong>Note: This will take a while.</strong> Check /var/log/clamav/freshclam.log for progress information. + <strong>Note: This will take a while.</strong> Check freshclam log on the <a href="squid_monitor.php">'Real Time' tab</a> for progress information. ]]> </description> <type>select</type> @@ -229,7 +229,7 @@ ]]> </description> <type>input</type> - <cols>60</cols> + <size>60</size> </field> <field> <fielddescr>squidclamav.conf</fielddescr> diff --git a/config/squid3/34/squid_antivirus_status.widget.php b/config/squid3/34/squid_antivirus_status.widget.php index 41c8c2fd..d739da33 100644 --- a/config/squid3/34/squid_antivirus_status.widget.php +++ b/config/squid3/34/squid_antivirus_status.widget.php @@ -44,8 +44,8 @@ global $clamd_path, $cicap_cfg_path, $img; $clamd_path = SQUID_BASE . "/bin/clamd"; $cicap_cfg_path = SQUID_LOCALBASE . "/bin/c-icap-config"; $img = array(); -$img['up'] = "<img src ='data:image/gif;base64,R0lGODlhCwALAIABACPcMP///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgABACwAAAAACwALAAACFYwNpwi50eKK9NA722Puyf15GjgaBQA7' title='Service running' alt='' />"; -$img['down'] = "<img src ='data:image/gif;base64,R0lGODlhCwALAIABANwjI////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgABACwAAAAACwALAAACFowDeYvKlsCD7sXZ5Iq89kpdFshoRwEAOw==' title='Service not running' alt='' />"; +$img['up'] = "<img src='data:image/gif;base64,R0lGODlhCwALAIABACPcMP///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgABACwAAAAACwALAAACFYwNpwi50eKK9NA722Puyf15GjgaBQA7' title='Service running' alt='' />"; +$img['down'] = "<img src='data:image/gif;base64,R0lGODlhCwALAIABANwjI////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgABACwAAAAACwALAAACFowDeYvKlsCD7sXZ5Iq89kpdFshoRwEAOw==' title='Service not running' alt='' />"; function squid_avdb_info($filename) { $stl = "style='padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; border-left: 1px solid #999999;'"; @@ -71,10 +71,10 @@ function squid_avdb_info($filename) { function squid_antivirus_bases_info() { $db = '<table width="100%" border="0" cellspacing="0" cellpadding="1"><tbody>'; $db .= '<tr class="vncellt" ><td>Database</td><td>Date</td><td>Version</td><td>Builder</td></tr>'; - $db .= squid_avdb_info("daily.cvd"); - $db .= squid_avdb_info("bytecode.cvd"); - $db .= squid_avdb_info("main.cvd"); - $db .= squid_avdb_info("safebrowsing.cvd"); + $avdbs = array("daily.cvd", "daily.cld", "bytecode.cvd", "bytecode.cld", "main.cvd", "main.cld", "safebrowsing.cvd", "safebrowsing.cld"); + foreach ($avdbs as $avdb) { + $db .= squid_avdb_info($avdb); + } $db .= '</tbody></table>'; return $db; } diff --git a/config/squid3/34/squid_cache.xml b/config/squid3/34/squid_cache.xml index 47471df9..b4f1aedf 100755 --- a/config/squid3/34/squid_cache.xml +++ b/config/squid3/34/squid_cache.xml @@ -42,8 +42,8 @@ ]]> </copyright> <name>squidcache</name> - <version>0.4.0</version> - <title>Proxy Server: Cache management</title> + <version>0.4.1</version> + <title>Proxy Server: Cache Management</title> <include_file>/usr/local/pkg/squid.inc</include_file> <tabs> <tab> @@ -410,7 +410,9 @@ // do not leave orphaned cachedirs if harddisk_cache_location changed if ($_POST['harddisk_cache_location'] != $config['installedpackages']['squidcache']['config'][0]['harddisk_cache_location']) { $oldcachedir = $config['installedpackages']['squidcache']['config'][0]['harddisk_cache_location']; - $cachedir_changed = true; + if ($oldcachedir != "") { + $cachedir_changed = true; + } } ]]> </custom_php_command_before_form> diff --git a/config/squid3/34/squid_monitor.php b/config/squid3/34/squid_monitor.php index 80e15a64..840d9a60 100755 --- a/config/squid3/34/squid_monitor.php +++ b/config/squid3/34/squid_monitor.php @@ -74,7 +74,7 @@ include("head.inc"); $tab_array[] = array(gettext("Web Servers"), false, "/pkg.php?xml=squid_reverse_peer.xml"); $tab_array[] = array(gettext("Mappings"), false, "/pkg.php?xml=squid_reverse_uri.xml"); $tab_array[] = array(gettext("Redirects"), false, "/pkg.php?xml=squid_reverse_redir.xml"); - $tab_array[] = array(gettext("Real time"), true, "/squid_monitor.php?menu=reverse"); + $tab_array[] = array(gettext("Real Time"), true, "/squid_monitor.php?menu=reverse"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=squid_reverse_sync.xml"); } else { $tab_array[] = array(gettext("General"), false, "/pkg_edit.php?xml=squid.xml&id=0"); @@ -85,7 +85,7 @@ include("head.inc"); $tab_array[] = array(gettext("Traffic Mgmt"), false, "/pkg_edit.php?xml=squid_traffic.xml&id=0"); $tab_array[] = array(gettext("Authentication"), false, "/pkg_edit.php?xml=squid_auth.xml&id=0"); $tab_array[] = array(gettext("Users"), false, "/pkg.php?xml=squid_users.xml"); - $tab_array[] = array(gettext("Real time"), true, "/squid_monitor.php"); + $tab_array[] = array(gettext("Real Time"), true, "/squid_monitor.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=squid_sync.xml"); } display_top_tabs($tab_array); @@ -93,7 +93,7 @@ include("head.inc"); </td></tr> <tr><td> <div id="mainarea" style="padding-top: 0px; padding-bottom: 0px; "> - <form id="paramsForm" name="paramsForm" method="post"> + <form id="paramsForm" name="paramsForm" method="post" action=""> <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="6"> <tbody> <tr> @@ -130,19 +130,39 @@ include("head.inc"); </table> </form> - <!-- Squid Table --> + <!-- Squid Access Table --> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tbody> <tr><td> <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0"> - <tr> - <td colspan="6" class="listtopic" align="center"><?=gettext("Squid Logs"); ?></td> - </tr> + <thead><tr> + <td colspan="6" class="listtopic" align="center"><?=gettext("Squid - Access Logs"); ?></td> + </tr></thead> <tbody id="squidView"> + <tr><td> <script type="text/javascript"> - // Call function to show squid log showLog('squidView', 'squid_monitor_data.php', 'squid'); </script> + </td></tr> + </tbody> + </table> + </td></tr> + </tbody> + </table> + <!-- Squid Cache Table --> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr><td> + <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0"> + <thead><tr> + <td colspan="2" class="listtopic" align="center"><?=gettext("Squid - Cache Logs"); ?></td> + </tr></thead> + <tbody id="squidCacheView"> + <tr><td> + <script type="text/javascript"> + showLog('squidCacheView', 'squid_monitor_data.php', 'squid_cache'); + </script> + </td></tr> </tbody> </table> </td></tr> @@ -154,32 +174,110 @@ include("head.inc"); <tbody> <tr><td> <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0"> - <tr> + <thead><tr> <td colspan="5" class="listtopic" align="center"><?=gettext("SquidGuard Logs"); ?></td> - </tr> + </tr></thead> <tbody id="sguardView"> + <tr><td> <script type="text/javascript"> - // Call function to show squidGuard log showLog('sguardView', 'squid_monitor_data.php', 'sguard'); </script> + </td></tr> + </tbody> + </table> + </td></tr> + </tbody> + </table> + <!-- C-ICAP Virus Table --> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr><td> + <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0"> + <thead><tr> + <td colspan="6" class="listtopic" align="center"><?=gettext("C-ICAP - Virus Logs"); ?></td> + </tr></thead> + <tbody id="CICIAPVirusView"> + <tr><td> + <script type="text/javascript"> + showLog('CICIAPVirusView', 'squid_monitor_data.php', 'cicap_virus'); + </script> + </td></tr> + </tbody> + </table> + </td></tr> + </tbody> + </table> + <!-- C-ICAP Access Table --> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr><td> + <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0"> + <thead><tr> + <td colspan="2" class="listtopic" align="center"><?=gettext("C-ICAP - Access Logs"); ?></td> + </tr></thead> + <tbody id="CICAPAccessView"> + <tr><td> + <script type="text/javascript"> + showLog('CICAPAccessView', 'squid_monitor_data.php', 'cicap_access'); + </script> + </td></tr> + </tbody> + </table> + </td></tr> + </tbody> + </table> + <!-- C-ICAP Server Table --> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr><td> + <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0"> + <thead><tr> + <td colspan="2" class="listtopic" align="center"><?=gettext("C-ICAP - Server Logs"); ?></td> + </tr></thead> + <tbody id="CICAPServerView"> + <tr><td> + <script type="text/javascript"> + showLog('CICAPServerView', 'squid_monitor_data.php', 'cicap_server'); + </script> + </td></tr> + </tbody> + </table> + </td></tr> + </tbody> + </table> + <!-- freshclam Table --> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr><td> + <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0"> + <thead><tr> + <td colspan="1" class="listtopic" align="center"><?=gettext("ClamAV - freshclam Logs"); ?></td> + </tr></thead> + <tbody id="freshclamView"> + <tr><td> + <script type="text/javascript"> + showLog('freshclamView', 'squid_monitor_data.php', 'freshclam'); + </script> + </td></tr> </tbody> </table> </td></tr> </tbody> </table> - <!-- clamav Table --> + <!-- clamd Table --> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tbody> <tr><td> <table class="tabcont" width="100%" border="0" cellspacing="0" cellpadding="0"> - <tr> - <td colspan="6" class="listtopic" align="center"><?=gettext("clamav Logs"); ?></td> - </tr> - <tbody id="clamView"> + <thead><tr> + <td colspan="1" class="listtopic" align="center"><?=gettext("ClamAV - clamd Logs"); ?></td> + </tr></thead> + <tbody id="clamdView"> + <tr><td> <script type="text/javascript"> - // Call function to show squidGuard log - showLog('clamView', 'squid_monitor_data.php', 'clamav'); + showLog('clamdView', 'squid_monitor_data.php', 'clamd'); </script> + </td></tr> </tbody> </table> </td></tr> diff --git a/config/squid3/34/squid_monitor_data.php b/config/squid3/34/squid_monitor_data.php index c2c3264d..747699cd 100755 --- a/config/squid3/34/squid_monitor_data.php +++ b/config/squid3/34/squid_monitor_data.php @@ -49,9 +49,6 @@ if ($_POST) { // Split line by space delimiter $logline = preg_split("/\s+/", $logent); - // Apply date format to first line - //$logline[0] = date("d.m.Y H:i:s",$logline[0]); - // Word wrap the URL $logline[7] = htmlentities($logline[7]); $logline[7] = html_autowrap($logline[7]); @@ -62,7 +59,7 @@ if ($_POST) { // Apply filter and color // Need validate special chars if ($filter != "") { - $logline = preg_replace("@($filter)@i","<spam><font color='red'>$1</font></span>", $logline); + $logline = preg_replace("@($filter)@i","<span><font color='red'>$1</font></span>", $logline); } echo "<tr valign=\"top\">\n"; @@ -75,6 +72,30 @@ if ($_POST) { echo "</tr>\n"; } break; + case 'squid_cache'; + // Define log file + $log = '/var/squid/logs/cache.log'; + // Show table headers + show_tds(array("Date-Time", "Message")); + // Fetch lines + $logarr = fetch_log($log); + foreach ($logarr as $logent) { + // Split line by delimiter + $logline = preg_split("@\|@", $logent); + + // Replace some build host nonsense and apply time format + $logline[0] = date("d.m.Y H:i:s", strtotime(str_replace("kid1", "", $logline[0]))); + + // Word wrap the message + $logline[1] = htmlentities($logline[1]); + $logline[1] = html_autowrap($logline[1]); + + echo "<tr>\n"; + echo "<td class=\"listlr\" nowrap=\"nowrap\">{$logline[0]}</td>\n"; + echo "<td class=\"listr\" nowrap=\"nowrap\">{$logline[1]}</td>\n"; + echo "</tr>\n"; + } + break; case 'sguard'; $log = '/var/squidGuard/log/block.log'; // Show table headers @@ -107,7 +128,7 @@ if ($_POST) { echo "</tr>\n"; } break; - case 'clamav'; + case 'cicap_virus'; // Define log file $log = '/var/log/c-icap/virus.log'; // Show table headers @@ -115,7 +136,7 @@ if ($_POST) { // Fetch lines $logarr = fetch_log($log); foreach ($logarr as $logent) { - // Split line by space delimiter + // Split line by delimiter $logline = preg_split("/\|/", $logent); // Apply time format @@ -135,7 +156,91 @@ if ($_POST) { echo "</tr>\n"; } break; - } + case 'cicap_access'; + // Define log file + $log = '/var/log/c-icap/access.log'; + // Show table headers + show_tds(array("Date-Time", "Message")); + // Fetch lines + $logarr = fetch_log($log); + foreach ($logarr as $logent) { + // Split line by delimiter + $logline = preg_split("/,/", $logent); + + // Apply time format + $logline[0] = date("d.m.Y H:i:s", strtotime($logline[0])); + + // Word wrap the message + $logline[1] = htmlentities($logline[1]); + $logline[1] = html_autowrap($logline[1]); + + echo "<tr>\n"; + echo "<td class=\"listlr\" nowrap=\"nowrap\">{$logline[0]}</td>\n"; + echo "<td class=\"listr\" nowrap=\"nowrap\">{$logline[1]}</td>\n"; + echo "</tr>\n"; + } + break; + case 'cicap_server'; + // Define log file + $log = '/var/log/c-icap/server.log'; + // Show table headers + show_tds(array("Date-Time", "Message")); + // Fetch lines + $logarr = fetch_log($log); + foreach ($logarr as $logent) { + // Split line by delimiter + $logline = preg_split("/,/", $logent); + + // Apply time format + $logline[0] = date("d.m.Y H:i:s", strtotime($logline[0])); + + // Word wrap the message + $logline[2] = htmlentities($logline[2]); + $logline[2] = html_autowrap($logline[2]); + + echo "<tr>\n"; + echo "<td class=\"listlr\" nowrap=\"nowrap\">{$logline[0]}</td>\n"; + echo "<td class=\"listr\" nowrap=\"nowrap\">{$logline[2]}</td>\n"; + echo "</tr>\n"; + } + break; + case 'freshclam'; + // Define log file + $log = '/var/log/clamav/freshclam.log'; + // Show table headers + show_tds(array("Message")); + // Fetch lines + $logarr = fetch_log($log); + foreach ($logarr as $logent) { + $logline = preg_split("/\n/", $logent); + // Word wrap the message + $logline[0] = htmlentities($logline[0]); + $logline[0] = html_autowrap($logline[0]); + + echo "<tr>\n"; + echo "<td class=\"listlr\" nowrap=\"nowrap\">{$logline[0]}</td>\n"; + echo "</tr>\n"; + } + break; + case 'clamd'; + // Define log file + $log = '/var/log/clamav/clamd.log'; + // Show table headers + show_tds(array("Message")); + // Fetch lines + $logarr = fetch_log($log); + foreach ($logarr as $logent) { + $logline = preg_split("/\n/", $logent); + // Word wrap the message + $logline[0] = htmlentities($logline[0]); + $logline[0] = html_autowrap($logline[0]); + + echo "<tr>\n"; + echo "<td class=\"listlr\" nowrap=\"nowrap\">{$logline[0]}</td>\n"; + echo "</tr>\n"; + } + break; + } } /* Functions */ diff --git a/config/squid3/34/squid_nac.xml b/config/squid3/34/squid_nac.xml index 4a81ac91..d621231f 100755 --- a/config/squid3/34/squid_nac.xml +++ b/config/squid3/34/squid_nac.xml @@ -42,7 +42,7 @@ ]]> </copyright> <name>squidnac</name> - <version>0.3.5</version> + <version>0.4.1</version> <title>Proxy Server: Access Control</title> <include_file>/usr/local/pkg/squid.inc</include_file> <tabs> @@ -98,9 +98,10 @@ <fieldname>allowed_subnets</fieldname> <description> <![CDATA[ - Enter each subnet on a new line that is allowed to use the proxy.<br/> - The subnets must be expressed as CIDR ranges (e.g.: 192.168.1.0/24).<br/><br/> - Note: The proxy interface subnet is already an allowed subnet. All the other subnets won't be able to use the proxy. + Enter subnets that are allowed to use the proxy.<br/> + The subnets must be expressed as CIDR ranges (e.g.: 192.168.1.0/24).<br/> + The proxy interface subnet is already an allowed subnet. All the other subnets won't be able to use the proxy.<br/> + <strong>Note: Put each entry on a separate line.</strong> ]]> </description> <type>textarea</type> diff --git a/config/squid3/34/squid_reverse.inc b/config/squid3/34/squid_reverse.inc index 9693b21f..483069e4 100755 --- a/config/squid3/34/squid_reverse.inc +++ b/config/squid3/34/squid_reverse.inc @@ -209,7 +209,11 @@ function squid_resync_reverse() { } if (($settings['reverse_owa'] == 'on') && (!empty($settings['reverse_owa_ip'])) && ($settings['reverse_owa_autodiscover'] == 'on')) { - $reverse_external_domain = strstr($settings['reverse_external_fqdn'], '.'); + if (substr_count($settings['reverse_external_fqdn'], ".") > 1) { + $reverse_external_domain = strstr($settings['reverse_external_fqdn'], '.'); + } else { + $reverse_external_domain = ".{$settings['reverse_external_fqdn']}"; + } $conf .= "acl OWA_URI_pfs url_regex -i ^http://{$settings['reverse_external_fqdn']}/AutoDiscover/AutoDiscover.xml\n"; $conf .= "acl OWA_URI_pfs url_regex -i ^https://{$settings['reverse_external_fqdn']}/AutoDiscover/AutoDiscover.xml\n"; $conf .= "acl OWA_URI_pfs url_regex -i ^http://autodiscover{$reverse_external_domain}/AutoDiscover/AutoDiscover.xml\n"; diff --git a/config/squid3/34/squid_reverse_sync.xml b/config/squid3/34/squid_reverse_sync.xml index eb52540f..1091fce8 100755 --- a/config/squid3/34/squid_reverse_sync.xml +++ b/config/squid3/34/squid_reverse_sync.xml @@ -42,7 +42,7 @@ ]]> </copyright> <name>squidsync</name> - <version>0.3.7</version> + <version>0.4.2</version> <title>Reverse Proxy Server: XMLRPC Sync</title> <include_file>/usr/local/pkg/squid.inc</include_file> <tabs> @@ -63,7 +63,7 @@ <url>/pkg.php?xml=squid_reverse_redir.xml</url> </tab> <tab> - <text>Real time</text> + <text>Real Time</text> <url>/squid_monitor.php?menu=reverse</url> </tab> <tab> @@ -78,12 +78,18 @@ <type>listtopic</type> </field> <field> - <fielddescr>Automatically sync Squid configuration changes</fielddescr> + <fielddescr>Enable Sync</fielddescr> <fieldname>synconchanges</fieldname> - <description>Select a sync method for Squid.</description> + <description> + <![CDATA[ + Select a sync method for Squid Reverse Proxy.<br/><br/> + <strong>Important:</strong> While using "Sync to host(s) defined below", only sync from host A to B, A to C but <strong>do not</strong> enable XMLRPC sync <b>to</b> A. + This will result in a loop! + ]]> + </description> <type>select</type> <required/> - <default_value>auto</default_value> + <default_value>disabled</default_value> <options> <option><name>Sync to configured system backup server</name><value>auto</value></option> <option><name>Sync to host(s) defined below</name><value>manual</value></option> @@ -106,19 +112,45 @@ </options> </field> <field> - <fielddescr>Remote Server</fielddescr> + <fielddescr>Replication Targets</fielddescr> <fieldname>none</fieldname> <type>rowhelper</type> <rowhelper> <rowhelperfield> - <fielddescr>IP Address</fielddescr> + <fielddescr>Enable</fielddescr> + <fieldname>syncdestinenable</fieldname> + <description><![CDATA[Enable this host as a replication target]]></description> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>syncprotocol</fieldname> + <description><![CDATA[Choose the protocol used to sync with the destination host (HTTP or HTTPS).]]></description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>IP Address/Hostname</fielddescr> <fieldname>ipaddress</fieldname> + <description><![CDATA[IP address or hostname of the destination host.]]></description> <type>input</type> - <size>20</size> + <size>40</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>syncport</fieldname> + <description><![CDATA[Choose the sync port of the destination host.]]></description> + <type>input</type> + <size>3</size> </rowhelperfield> <rowhelperfield> - <fielddescr>Password (admin)</fielddescr> + <fielddescr>Admin Password</fielddescr> <fieldname>password</fieldname> + <description><![CDATA[Password of the user "admin" on the destination host.]]></description> <type>password</type> <size>20</size> </rowhelperfield> diff --git a/config/squid3/34/squid_sync.xml b/config/squid3/34/squid_sync.xml index 60e1190c..a7670ff5 100755 --- a/config/squid3/34/squid_sync.xml +++ b/config/squid3/34/squid_sync.xml @@ -42,8 +42,8 @@ ]]> </copyright> <name>squidsync</name> - <version>0.3.7</version> - <title>Proxy server: XMLRPC Sync</title> + <version>0.4.2</version> + <title>Proxy Server: XMLRPC Sync</title> <include_file>/usr/local/pkg/squid.inc</include_file> <tabs> <tab> @@ -94,12 +94,18 @@ <type>listtopic</type> </field> <field> - <fielddescr>Automatically sync Squid configuration changes</fielddescr> + <fielddescr>Enable Sync</fielddescr> <fieldname>synconchanges</fieldname> - <description>Select a sync method for Squid.</description> + <description> + <![CDATA[ + Select a sync method for Squid.<br/><br/> + <strong>Important:</strong> While using "Sync to host(s) defined below", only sync from host A to B, A to C but <strong>do not</strong> enable XMLRPC sync <b>to</b> A. + This will result in a loop! + ]]> + </description> <type>select</type> <required/> - <default_value>auto</default_value> + <default_value>disabled</default_value> <options> <option><name>Sync to configured system backup server</name><value>auto</value></option> <option><name>Sync to host(s) defined below</name><value>manual</value></option> @@ -122,19 +128,45 @@ </options> </field> <field> - <fielddescr>Remote Server</fielddescr> + <fielddescr>Replication Targets</fielddescr> <fieldname>none</fieldname> <type>rowhelper</type> <rowhelper> <rowhelperfield> - <fielddescr>IP Address</fielddescr> + <fielddescr>Enable</fielddescr> + <fieldname>syncdestinenable</fieldname> + <description><![CDATA[Enable this host as a replication target]]></description> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>syncprotocol</fieldname> + <description><![CDATA[Choose the protocol used to sync with the destination host (HTTP or HTTPS).]]></description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>IP Address/Hostname</fielddescr> <fieldname>ipaddress</fieldname> + <description><![CDATA[IP address or hostname of the destination host.]]></description> <type>input</type> - <size>20</size> + <size>40</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>syncport</fieldname> + <description><![CDATA[Choose the sync port of the destination host.]]></description> + <type>input</type> + <size>3</size> </rowhelperfield> <rowhelperfield> - <fielddescr>Password (admin)</fielddescr> + <fielddescr>Admin Password</fielddescr> <fieldname>password</fieldname> + <description><![CDATA[Password of the user "admin" on the destination host.]]></description> <type>password</type> <size>20</size> </rowhelperfield> diff --git a/config/squid3/34/squid_traffic.xml b/config/squid3/34/squid_traffic.xml index bd01bbb7..810fa62d 100755 --- a/config/squid3/34/squid_traffic.xml +++ b/config/squid3/34/squid_traffic.xml @@ -42,8 +42,8 @@ ]]> </copyright> <name>squidtraffic</name> - <version>0.3.5</version> - <title>Proxy server: Traffic Management</title> + <version>0.4.1</version> + <title>Proxy Server: Traffic Management</title> <include_file>/usr/local/pkg/squid.inc</include_file> <tabs> <tab> @@ -160,7 +160,6 @@ <description>Leave this checked to be able to choose the extensions that throttling will be applied to. Otherwise, all files will be throttled.</description> <type>checkbox</type> <enablefields>throttle_binaries,throttle_cdimages,throttle_multimedia,throttle_others</enablefields> - <default_value>on</default_value> </field> <field> <fielddescr>Throttle Binary Files</fielddescr> diff --git a/config/squid3/34/squid_users.xml b/config/squid3/34/squid_users.xml index c47395b9..fb791b9e 100755 --- a/config/squid3/34/squid_users.xml +++ b/config/squid3/34/squid_users.xml @@ -42,8 +42,8 @@ ]]> </copyright> <name>squidusers</name> - <version>0.3.5</version> - <title>Proxy server: Local users</title> + <version>0.4.1</version> + <title>Proxy Server: Local Users</title> <include_file>/usr/local/pkg/squid.inc</include_file> <delete_string>A proxy server user has been deleted.</delete_string> <addedit_string>A proxy server user has been created/modified.</addedit_string> diff --git a/config/squidGuard-devel/squidguard.priv.inc b/config/squidGuard-devel/squidguard.priv.inc new file mode 100644 index 00000000..a80c798b --- /dev/null +++ b/config/squidGuard-devel/squidguard.priv.inc @@ -0,0 +1,55 @@ +<?php +/* + squidguard.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-squidguard'] = array(); +$priv_list['page-services-squidguard']['name'] = "WebCfg - Services: SquidGuard package"; +$priv_list['page-services-squidguard']['descr'] = "Allow access to SquidGuard package GUI"; +$priv_list['page-services-squidguard']['match'] = array(); + +$priv_list['page-services-squidguard']['match'][] = "pkg.php?xml=squidguard.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg.php?xml=squidguard_acl.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg.php?xml=squidguard_default.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg.php?xml=squidguard_dest.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg.php?xml=squidguard_sync.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg.php?xml=squidguard_time.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg.php?xml=squidguard_rewr.xml*"; + +$priv_list['page-services-squidguard']['match'][] = "pkg_edit.php?xml=squidguard.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg_edit.php?xml=squidguard_acl.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg_edit.php?xml=squidguard_default.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg_edit.php?xml=squidguard_dest.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg_edit.php?xml=squidguard_sync.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg_edit.php?xml=squidguard_time.xml*"; +$priv_list['page-services-squidguard']['match'][] = "pkg_edit.php?xml=squidguard_rewr.xml*"; + +$priv_list['page-services-squidguard']['match'][] = "squidguard_blacklist.php*"; +$priv_list['page-services-squidguard']['match'][] = "squidguard_log.php*"; + +?> diff --git a/config/squidGuard-devel/squidguard.xml b/config/squidGuard-devel/squidguard.xml index 3c91402a..b7874f82 100644 --- a/config/squidGuard-devel/squidguard.xml +++ b/config/squidGuard-devel/squidguard.xml @@ -2,16 +2,52 @@ <!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> <?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> - <description>[<![CDATA[Describe your package here]]></description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> + <copyright> +<![CDATA[ +/* $Id$ */ +/* ====================================================================================== */ +/* + squidguard.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006-2013 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC + 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. +*/ +/* ====================================================================================== */ + ]]> + </copyright> <name>squidguardgeneral</name> - <version>1.5_1</version> + <version>1.5.8</version> <title>Proxy filter SquidGuard: General settings</title> <include_file>/usr/local/pkg/squidguard.inc</include_file> <!-- Installation --> <menu> - <name>Proxy filter</name> + <name>SquidGuard Proxy Filter</name> <tooltiptext>Modify the proxy server's filter settings</tooltiptext> <section>Services</section> <url>/pkg_edit.php?xml=squidguard.xml&id=0</url> @@ -62,57 +98,50 @@ </service> <additional_files_needed> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard.inc</item> </additional_files_needed> <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard.priv.inc</item> + </additional_files_needed> + <additional_files_needed> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_configurator.inc</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_acl.xml</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_default.xml</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_dest.xml</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_rewr.xml</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_time.xml</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_sync.xml</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/www/squidGuard/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_log.php</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/www/squidGuard/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/squidguard_blacklist.php</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/www/</prefix> - <chmod>0755</chmod> <item>https://packages.pfsense.org/packages/config/squidGuard-devel/sgerror.php</item> </additional_files_needed> <fields> diff --git a/config/squidGuard/.project b/config/squidGuard/.project deleted file mode 100644 index 49cdc3c9..00000000 --- a/config/squidGuard/.project +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<projectDescription> - <name>squidGuard</name> - <comment></comment> - <projects> - </projects> - <buildSpec> - </buildSpec> - <natures> - </natures> -</projectDescription> diff --git a/config/sshdcond/sshdcond.inc b/config/sshdcond/sshdcond.inc index 9c3a8bb9..7c1be614 100644 --- a/config/sshdcond/sshdcond.inc +++ b/config/sshdcond/sshdcond.inc @@ -37,8 +37,6 @@ function restart_sshd() { } function sshdcond_custom_php_install_command() { - global $g, $config; - /* We need to generate an outfile for our extra commands. The patched g_szSSHDFileGenerate php file then reads and appends that config. */ @@ -48,8 +46,6 @@ function sshdcond_custom_php_install_command() { } function sshdcond_custom_php_deinstall_command() { - global $g, $config; - /* Delete our config file. */ unlink_if_exists("/etc/ssh/sshd_extra"); @@ -59,7 +55,7 @@ function sshdcond_custom_php_deinstall_command() { } function sshdcond_custom_php_write_config() { - global $g, $config, $pkg_interface; + global $g, $config; /* Detect boot process, do nothing during boot. */ if (function_exists("platform_booting")) { @@ -113,71 +109,113 @@ function sshdcond_custom_php_write_config() { /* Uses XMLRPC to synchronize the changes to a remote node. */ function sshdcond_sync_on_changes() { - global $config, $g; - - /* Basically, this package was never configured */ - if (!is_array($config['installedpackages']['sshdcondsync'])) { - return; - } - /* Package is configured but XMLRPC sync is disabled */ - if (!isset($config['installedpackages']['sshdcondsync']['config'][0]['synconchanges'])) { - return; - } - /* Do XMLRPC sync */ - log_error("[sshdcond] xmlrpc sync is starting."); - foreach ($config['installedpackages']['sshdcondsync']['config'] as $rs) { - foreach($rs['row'] as $sh) { - $sync_to_ip = $sh['ipaddress']; - $password = $sh['password']; - if ($password && $sync_to_ip) { - sshdcond_do_xmlrpc_sync($sync_to_ip, $password); + global $config; + + if (is_array($config['installedpackages']['sshdcondsync']['config'])) { + $sshdcond_sync = $config['installedpackages']['sshdcondsync']['config'][0]; + $synconchanges = $sshdcond_sync['synconchanges']; + $synctimeout = $sshdcond_sync['synctimeout'] ?: '150'; + switch ($synconchanges) { + case "manual": + if (is_array($sshdcond_sync['row'])) { + $rs = $sshdcond_sync['row']; + } else { + log_error("[sshdcond] XMLRPC sync is enabled but there are no hosts configured as replication targets."); + return; + } + break; + case "auto": + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; + $rs[0]['ipaddress'] = $system_carp['synchronizetoip']; + $rs[0]['username'] = $system_carp['username']; + $rs[0]['password'] = $system_carp['password']; + $rs[0]['syncdestinenable'] = FALSE; + + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['syncprotocol'] = "http"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['syncprotocol'] = "https"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '443'; + } + if ($system_carp['synchronizetoip'] == "") { + log_error("[sshdcond] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } else { + $rs[0]['syncdestinenable'] = TRUE; + } + } else { + log_error("[sshdcond] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } + break; + default: + return; + break; + } + if (is_array($rs)) { + log_error("[sshdcond] XMLRPC sync is starting."); + foreach ($rs as $sh) { + // Only sync enabled replication targets + if ($sh['syncdestinenable']) { + $sync_to_ip = $sh['ipaddress']; + $port = $sh['syncport']; + $username = $sh['username'] ?: 'admin'; + $password = $sh['password']; + $protocol = $sh['syncprotocol']; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + sshdcond_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout); + } else { + log_error("[sshdcond] XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } + } } + log_error("[sshdcond] XMLRPC sync completed."); } - } - log_error("[sshdcond] xmlrpc sync is ending."); + } } /* Do the actual XMLRPC sync. */ -function sshdcond_do_xmlrpc_sync($sync_to_ip, $password) { +function sshdcond_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) { global $config, $g; - if (!$password) { + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("[sshdcond] A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; } - if (!$sync_to_ip) { - return; + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; } - $username='admin'; - $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, let's rely on the protocol selection. */ - if ($port == "") { - if ($config['system']['webgui']['protocol'] == "http") { - $port = "80"; - } else { - $port = "443"; - } - } - $synchronizetoip .= $sync_to_ip; + $url = "{$protocol}://{$sync_to_ip}"; - /* xml will hold the sections to sync. */ + /* XML will hold the sections to sync. */ $xml = array(); $xml['sshdcond'] = $config['installedpackages']['sshdcond']; /* 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("Beginning sshdcond XMLRPC sync to {$url}:{$port}."); + $params = array(XML_RPC_encode($password), XML_RPC_encode($xml)); + + /* Set a few variables needed for sync code */ $method = 'pfsense.merge_installedpackages_section_xmlrpc'; $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); @@ -185,20 +223,20 @@ function sshdcond_do_xmlrpc_sync($sync_to_ip, $password) { if ($g['debug']) { $cli->setDebug(1); } - /* Send our XMLRPC message and timeout after 250 seconds. */ - $resp = $cli->send($msg, "250"); + /* 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 sshdcond XMLRPC sync with {$url}:{$port}."; - log_error($error); + $error = "A communications error occurred while attempting XMLRPC sync with {$url}:{$port}."; + log_error("[sshdcond] {$error}"); file_notice("sync_settings", $error, "sshdcond Settings Sync", ""); } elseif ($resp->faultCode()) { $cli->setDebug(1); - $resp = $cli->send($msg, "250"); + $resp = $cli->send($msg, $synctimeout); $error = "An error code was received while attempting sshdcond XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + log_error("[sshdcond] {$error}"); file_notice("sync_settings", $error, "sshdcond Settings Sync", ""); } else { - log_error("sshdcond XMLRPC sync successfully completed with {$url}:{$port}."); + log_error("[sshdcond] XMLRPC sync successfully completed with {$url}:{$port}."); } /* Tell sshdcond to reload our settings on the destination sync host. */ @@ -206,28 +244,24 @@ function sshdcond_do_xmlrpc_sync($sync_to_ip, $password) { $execcmd = "require_once('/usr/local/pkg/sshdcond.inc');\n"; $execcmd .= "sshdcond_custom_php_write_config();"; /* Assemble XMLRPC payload. */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($execcmd) - ); + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); - log_error("sshdcond 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, "250"); + $resp = $cli->send($msg, $synctimeout); if (!$resp) { $error = "A communications error occurred while attempting sshdcond XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; - log_error($error); + log_error("[sshdcond] {$error}"); file_notice("sync_settings", $error, "sshdcond Settings Sync", ""); } elseif ($resp->faultCode()) { $cli->setDebug(1); - $resp = $cli->send($msg, "250"); + $resp = $cli->send($msg, $synctimeout); $error = "An error code was received while attempting sshdcond XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + log_error("[sshdcond] {$error}"); file_notice("sync_settings", $error, "sshdcond Settings Sync", ""); } else { - log_error("sshdcond XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); + log_error("[sshdcond] XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); } } ?> diff --git a/config/sshdcond/sshdcond.priv.inc b/config/sshdcond/sshdcond.priv.inc new file mode 100644 index 00000000..fddb86c1 --- /dev/null +++ b/config/sshdcond/sshdcond.priv.inc @@ -0,0 +1,42 @@ +<?php +/* + sshdcond.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-sshdcond'] = array(); +$priv_list['page-services-sshdcond']['name'] = "WebCfg - Services: SSHDCond package"; +$priv_list['page-services-sshdcond']['descr'] = "Allow access to SSHDCond package GUI"; +$priv_list['page-services-sshdcond']['match'] = array(); + +$priv_list['page-services-sshdcond']['match'][] = "pkg.php?xml=sshdcond.xml*"; +$priv_list['page-services-sshdcond']['match'][] = "pkg.php?xml=sshdcond_sync.xml*"; + +$priv_list['page-services-sshdcond']['match'][] = "pkg_edit.php?xml=sshdcond.xml*"; +$priv_list['page-services-sshdcond']['match'][] = "pkg_edit.php?xml=sshdcond_sync.xml*"; + +?> diff --git a/config/sshdcond/sshdcond.xml b/config/sshdcond/sshdcond.xml index 11104e1d..f0e27c80 100644 --- a/config/sshdcond/sshdcond.xml +++ b/config/sshdcond/sshdcond.xml @@ -43,12 +43,10 @@ ]]> </copyright> <name>sshdcond</name> - <version>1.0.2</version> - <title>SSH Conditional</title> - <description>SSH Conditional blocks</description> + <version>1.0.6</version> + <title>Services: SSH Conditional Options</title> <savetext>Save</savetext> <include_file>/usr/local/pkg/sshdcond.inc</include_file> - <menu> <name>SSH Conditions</name> <tooltiptext>Configure SSH conditional exceptions</tooltiptext> @@ -61,6 +59,10 @@ <item>https://packages.pfsense.org/packages/config/sshdcond/sshdcond.inc</item> </additional_files_needed> <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/sshdcond/sshdcond.priv.inc</item> + </additional_files_needed> + <additional_files_needed> <prefix>/usr/local/pkg/</prefix> <item>https://packages.pfsense.org/packages/config/sshdcond/sshdcond_sync.xml</item> </additional_files_needed> @@ -93,7 +95,6 @@ <field> <type>listtopic</type> <name>Conditional SSH Options</name> - <fieldname>temp</fieldname> </field> <field> <fielddescr>Enable</fielddescr> @@ -187,7 +188,4 @@ <custom_php_resync_config_command> sshdcond_custom_php_write_config(); </custom_php_resync_config_command> - <custom_php_command_before_form> - unset($_POST['temp']); - </custom_php_command_before_form> </packagegui> diff --git a/config/sshdcond/sshdcond_sync.xml b/config/sshdcond/sshdcond_sync.xml index 511df25b..f81f36b0 100755 --- a/config/sshdcond/sshdcond_sync.xml +++ b/config/sshdcond/sshdcond_sync.xml @@ -42,8 +42,8 @@ ]]> </copyright> <name>sshdcondsync</name> - <version>1.0.2</version> - <title>SSH Conditional - Sync</title> + <version>1.0.6</version> + <title>Services: SSH Conditional Options - Sync</title> <include_file>/usr/local/pkg/sshdcond.inc</include_file> <tabs> <tab> @@ -62,30 +62,74 @@ <type>listtopic</type> </field> <field> - <fielddescr>Automatically sync configuration changes</fielddescr> + <fielddescr>Enable Sync</fielddescr> <fieldname>synconchanges</fieldname> - <description>Automatically sync changes to the hosts defined below.</description> - <type>checkbox</type> + <description> + <![CDATA[ + When enabled, this will sync all configuration settings to the Replication Targets.<br/><br/> + <b>Important:</b> While using "Sync to host(s) defined below", only sync from host A to B, A to C but <strong>do not</strong> enable XMLRPC sync <b>to</b> A. This will result in a loop! + ]]> + </description> + <type>select</type> + <required/> + <default_value>disabled</default_value> + <options> + <option><name>Sync to configured system backup server</name><value>auto</value></option> + <option><name>Sync to host(s) defined below</name><value>manual</value></option> + <option><name>Do not sync this package configuration</name><value>disabled</value></option> + </options> </field> <field> - <fielddescr>Remote Server</fielddescr> + <fielddescr>XMLRPC Timeout</fielddescr> + <fieldname>synctimeout</fieldname> + <description><![CDATA[XMLRPC timeout in seconds. Default: 150]]></description> + <type>input</type> + <default_value>150</default_value> + <size>5</size> + </field> + <field> + <fielddescr>Replication Targets</fielddescr> <fieldname>none</fieldname> <type>rowhelper</type> <rowhelper> - <rowhelperfield> - <fielddescr>IP Address</fielddescr> - <fieldname>ipaddress</fieldname> - <description>IP Address of remote server.</description> - <type>input</type> - <size>20</size> - </rowhelperfield> - <rowhelperfield> - <fielddescr>Password</fielddescr> - <fieldname>password</fieldname> - <description>Password for remote server.</description> - <type>password</type> - <size>20</size> - </rowhelperfield> + <rowhelperfield> + <fielddescr>Enable</fielddescr> + <fieldname>syncdestinenable</fieldname> + <description><![CDATA[Enable this host as a replication target]]></description> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>syncprotocol</fieldname> + <description><![CDATA[Choose the protocol used to sync with the destination host (HTTP or HTTPS).]]></description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>IP Address/Hostname</fielddescr> + <fieldname>ipaddress</fieldname> + <description><![CDATA[IP address or hostname of the destination host.]]></description> + <type>input</type> + <size>40</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>syncport</fieldname> + <description><![CDATA[Choose the sync port of the destination host.]]></description> + <type>input</type> + <size>3</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Admin Password</fielddescr> + <fieldname>password</fieldname> + <description><![CDATA[Password of the user "admin" on the destination host.]]></description> + <type>password</type> + <size>20</size> + </rowhelperfield> </rowhelper> </field> </fields> diff --git a/config/stunnel/stunnel.priv.inc b/config/stunnel/stunnel.priv.inc new file mode 100644 index 00000000..f9857583 --- /dev/null +++ b/config/stunnel/stunnel.priv.inc @@ -0,0 +1,42 @@ +<?php +/* + stunnel.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-stunnel'] = array(); +$priv_list['page-services-stunnel']['name'] = "WebCfg - Services: stunnel package"; +$priv_list['page-services-stunnel']['descr'] = "Allow access to stunnel package GUI"; +$priv_list['page-services-stunnel']['match'] = array(); + +$priv_list['page-services-stunnel']['match'][] = "pkg.php?xml=stunnel.xml*"; +$priv_list['page-services-stunnel']['match'][] = "pkg.php?xml=stunnel_certs.xml*"; + +$priv_list['page-services-stunnel']['match'][] = "pkg_edit.php?xml=stunnel.xml*"; +$priv_list['page-services-stunnel']['match'][] = "pkg_edit.php?xml=stunnel_certs.xml*"; + +?> diff --git a/config/stunnel/stunnel.xml b/config/stunnel/stunnel.xml index c8957ba8..b5dfd6bd 100644 --- a/config/stunnel/stunnel.xml +++ b/config/stunnel/stunnel.xml @@ -42,14 +42,10 @@ ]]> </copyright> <name>stunnel</name> - <version>5.20.2</version> + <version>5.20.3</version> <title>Services: Secure Tunnel</title> <menu> <name>STunnel</name> - <tooltiptext>The stunnel program is designed to work as an SSL encryption wrapper between remote client and local (inetd-startable) or remote server. - It can be used to add SSL functionality to commonly used inetd daemons like POP2, POP3, and IMAP servers without any changes in the programs' code. - It will negotiate an SSL connection using the OpenSSL or SSLeay libraries. - It calls the underlying crypto libraries, so stunnel supports whatever cryptographic algorithms you compiled into your crypto package.</tooltiptext> <section>Services</section> <configfile>stunnel.xml</configfile> </menu> @@ -59,6 +55,10 @@ <item>https://packages.pfsense.org/packages/config/stunnel/stunnel.inc</item> </additional_files_needed> <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/stunnel/stunnel.priv.inc</item> + </additional_files_needed> + <additional_files_needed> <prefix>/usr/local/pkg/</prefix> <item>https://packages.pfsense.org/packages/config/stunnel/stunnel_certs.xml</item> </additional_files_needed> diff --git a/config/sudo/sudo.priv.inc b/config/sudo/sudo.priv.inc new file mode 100644 index 00000000..01cb2224 --- /dev/null +++ b/config/sudo/sudo.priv.inc @@ -0,0 +1,38 @@ +<?php +/* + sudo.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-system-sudo'] = array(); +$priv_list['page-system-sudo']['name'] = "WebCfg - System: sudo package"; +$priv_list['page-system-sudo']['descr'] = "Allow access to sudo package GUI"; +$priv_list['page-system-sudo']['match'] = array(); + +$priv_list['page-system-sudo']['match'][] = "pkg_edit.php?xml=sudo.xml*"; + +?> diff --git a/config/sudo/sudo.xml b/config/sudo/sudo.xml index 6124a641..e2b92cf1 100644 --- a/config/sudo/sudo.xml +++ b/config/sudo/sudo.xml @@ -1,4 +1,6 @@ <?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> <copyright> <![CDATA[ @@ -42,7 +44,7 @@ <description>Sudo Command Control</description> <requirements>None</requirements> <name>sudo</name> - <version>0.2.7</version> + <version>0.2.8</version> <title>Sudo - Shell Command Privilege Delegation Utility</title> <include_file>/usr/local/pkg/sudo.inc</include_file> <menu> @@ -56,6 +58,10 @@ <prefix>/usr/local/pkg/</prefix> <item>https://packages.pfsense.org/packages/config/sudo/sudo.inc</item> </additional_files_needed> + <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/sudo/sudo.priv.inc</item> + </additional_files_needed> <fields> <field> <type>listtopic</type> @@ -63,11 +69,14 @@ </field> <field> <type>info</type> - <description><![CDATA[ -User permission definitions for allowing the use of sudo by shell users to run commands as other users, such as root. -<br /><br />More information on the full command options may be found in the <a href="http://www.sudo.ws/sudoers.man.html">sudoers manual</a>. -<br /><br />By default the command is "ALL" meaning the user can run any commands. Leaving the commands field blank assumes "ALL". A comma-separated list of commands can be supplied to limit the user to individual binaries. Full paths to binaries must be used. - ]]></description> + <description> + <![CDATA[ + User permission definitions for allowing the use of sudo by shell users to run commands as other users, such as root.<br /><br /> + More information on the full command options may be found in the <a href="http://www.sudo.ws/sudoers.man.html">sudoers manual</a>.<br /><br /> + By default the command is "ALL" meaning the user can run any commands. Leaving the commands field blank assumes "ALL".<br /><br /> + A comma-separated list of commands can be supplied to limit the user to individual binaries. <strong>Full paths to binaries must be used.</strong> + ]]> + </description> </field> <field> <fielddescr>User Permissions</fielddescr> @@ -100,7 +109,7 @@ User permission definitions for allowing the use of sudo by shell users to run c <rowhelperfield> <fielddescr>Command List</fielddescr> <fieldname>cmdlist</fieldname> - <description>Commands the user may run. Comma-separated list, full paths preferred. Default: ALL</description> + <description>Commands the user may run. Comma-separated list, full paths required. Default: ALL</description> <type>input</type> <size>30</size> <value>ALL</value> diff --git a/config/suricata/suricata.inc b/config/suricata/suricata.inc index e3028570..bd7a181b 100644 --- a/config/suricata/suricata.inc +++ b/config/suricata/suricata.inc @@ -3304,102 +3304,118 @@ function suricata_sync_on_changes() { /* Do not attempt a package sync while booting up or installing package */ if ($g['booting'] || $g['suricata_postinstall'] == TRUE) { - log_error("[suricata] No xmlrpc sync to CARP targets when booting up or during package reinstallation."); + log_error("[suricata] Skipping XMLRPC sync when booting up or during package reinstallation."); return; } - if (is_array($config['installedpackages']['suricatasync']['config'])){ - $suricata_sync=$config['installedpackages']['suricatasync']['config'][0]; + if (is_array($config['installedpackages']['suricatasync']['config'])) { + $suricata_sync = $config['installedpackages']['suricatasync']['config'][0]; $synconchanges = $suricata_sync['varsynconchanges']; - $synctimeout = $suricata_sync['varsynctimeout']; + $synctimeout = $suricata_sync['varsynctimeout'] ?: '150'; $syncdownloadrules = $suricata_sync['vardownloadrules']; - switch ($synconchanges){ + switch ($synconchanges) { case "manual": - if (is_array($suricata_sync[row])){ - $rs=$suricata_sync[row]; - } - else{ - log_error("[suricata] xmlrpc CARP sync is enabled but there are no hosts configured as replication targets."); + if (is_array($suricata_sync['row'])) { + $rs = $suricata_sync['row']; + } else { + log_error("[suricata] XMLRPC sync is enabled but there are no hosts configured as replication targets."); 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]['varsyncipaddress']=$system_carp['synchronizetoip']; - $rs[0]['varsyncusername']=$system_carp['username']; - $rs[0]['varsyncpassword']=$system_carp['password']; - $rs[0]['varsyncsuricatastart']="no"; - if ($system_carp['synchronizetoip'] ==""){ - log_error("[suricata] xmlrpc CARP sync is enabled but there are no system backup hosts configured as replication targets."); - return; - } + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; + $rs[0]['varsyncipaddress'] = $system_carp['synchronizetoip']; + $rs[0]['varsyncusername'] = $system_carp['username']; + $rs[0]['varsyncpassword'] = $system_carp['password']; + $rs[0]['varsyncsuricatastart'] = FALSE; + $rs[0]['varsyncdestinenable'] = FALSE; + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['varsyncprotocol'] = "http"; + $rs[0]['varsyncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['varsyncprotocol'] = "https"; + $rs[0]['varsyncport'] = $config['system']['webgui']['port'] ?: '443'; } - else{ - log_error("[suricata] xmlrpc CARP sync is enabled but there are no system backup hosts configured as replication targets."); + if ($system_carp['synchronizetoip'] == "") { + log_error("[suricata] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); return; + } else { + $rs[0]['varsyncdestinenable'] = TRUE; } + } else { + log_error("[suricata] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } break; default: return; - break; + break; } - if (is_array($rs)){ - log_error("[suricata] Suricata pkg xmlrpc CARP sync is starting."); - foreach($rs as $sh){ - if ($sh['varsyncsuricatastart']) - $syncstartsuricata = $sh['varsyncsuricatastart']; - else - $syncstartsuricata = "OFF"; - $sync_to_ip = $sh['varsyncipaddress']; - $port = $sh['varsyncport']; - $password = $sh['varsyncpassword']; - if($sh['varsyncusername']) - $username = $sh['varsyncusername']; - else - $username = 'admin'; - if($password && $sync_to_ip) - suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, $password, $synctimeout, $syncstartsuricata); + if (is_array($rs)) { + log_error("[suricata] XMLRPC sync is starting."); + foreach ($rs as $sh) { + // Only sync enabled replication targets + if ($sh['varsyncdestinenable']) { + if ($sh['varsyncsuricatastart']) { + $syncstartsuricata = $sh['varsyncsuricatastart']; + } else { + $syncstartsuricata = "OFF"; + } + $sync_to_ip = $sh['varsyncipaddress']; + $password = $sh['varsyncpassword']; + $port = $sh['varsyncport']; + $protocol = $sh['varsyncprotocol']; + $error = ''; + $success = TRUE; + $username = $sh['varsyncusername'] ?: 'admin'; + if ($password == "") { + $error = "Password parameter is empty. "; + $success = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address. "; + $success = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $success = FALSE; + } + if ($success) { + suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $protocol, $username, $password, $synctimeout, $syncstartsuricata); + } else { + log_error("[suricata] XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } + } } - log_error("[suricata] Suricata pkg xmlrpc CARP sync completed."); + log_error("[suricata] XMLRPC sync completed."); } } } /* Do the actual XMLRPC sync */ -function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $username, $password, $synctimeout = 150, $syncstartsuricata) { +function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $protocol, $username, $password, $synctimeout = 150, $syncstartsuricata) { global $config, $g; /* Do not attempt a package sync while booting up or installing package */ if ($g['booting'] || isset($g['suricata_postinstall'])) { - log_error("[suricata] No xmlrpc sync to CARP targets when booting up or during package reinstallation."); + log_error("[suricata] Skipping XMLRPC sync when booting up or during package reinstallation."); return; } - if($username == "" || $password == "" || $sync_to_ip == "") { - log_error("[suricata] A required XMLRPC CARP sync parameter (user, host IP or password) is empty ... aborting pkg sync"); + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("[suricata] A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; } - /* Test key variables and set defaults if empty */ - if(!$synctimeout) - $synctimeout=150; - - $xmlrpc_sync_neighbor = $sync_to_ip; - if($config['system']['webgui']['protocol'] != "") { - $synchronizetoip = $config['system']['webgui']['protocol']; - $synchronizetoip .= "://"; + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; } - $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; - $url = $synchronizetoip; + + $url = "{$protocol}://{$sync_to_ip}"; + /*************************************************/ /* Send over any auto-SID management files */ @@ -3413,25 +3429,26 @@ function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $userna $method = 'pfsense.exec_php'; $params = array( XML_RPC_encode($password), XML_RPC_encode($payload) ); - log_error("[suricata] Suricata XMLRPC CARP sync sending auto-SID conf files to {$url}:{$port}."); + log_error("[suricata] XMLRPC sync sending auto-SID conf files to {$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); $error = ""; - if(!$resp) { - $error = "A communications error occurred while attempting Suricata XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file); + if (!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC sync with {$url}:{$port}. Failed to transfer file: " . basename($file); log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); - } elseif($resp->faultCode()) { - $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); } } - if (!empty($sid_files) && $error == "") - log_error("[suricata] Suricata pkg XMLRPC CARP sync auto-SID conf files success with {$url}:{$port} (pfsense.exec_php)."); + if (!empty($sid_files) && $error == "") { + log_error("[suricata] XMLRPC sync auto-SID conf files success with {$url}:{$port} (pfsense.exec_php)."); + } /*************************************************/ /* Send over any IPREP IP List files */ @@ -3445,25 +3462,26 @@ function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $userna $method = 'pfsense.exec_php'; $params = array( XML_RPC_encode($password), XML_RPC_encode($payload) ); - log_error("[suricata] Suricata XMLRPC CARP sync sending IPREP files to {$url}:{$port}."); + log_error("[suricata] Suricata XMLRPC sync sending IPREP files to {$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); $error = ""; - if(!$resp) { - $error = "A communications error occurred while attempting Suricata XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file); + if (!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC sync with {$url}:{$port}. Failed to transfer file: " . basename($file); log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); - } elseif($resp->faultCode()) { - $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC sync with {$url}:{$port}. Failed to transfer file: " . basename($file) . " - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); } } - if (!empty($iprep_files) && $error == "") - log_error("[suricata] Suricata pkg XMLRPC CARP sync IPREP files success with {$url}:{$port} (pfsense.exec_php)."); + if (!empty($iprep_files) && $error == "") { + log_error("[suricata] XMLRPC sync IPREP files success with {$url}:{$port} (pfsense.exec_php)."); + } /**************************************************/ /* Send over the <suricata> portion of config.xml */ @@ -3477,7 +3495,7 @@ function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $userna XML_RPC_encode($xml) ); - log_error("[suricata] Beginning Suricata pkg configuration XMLRPC sync to {$url}:{$port}."); + log_error("[suricata] Beginning package configuration 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); @@ -3485,31 +3503,31 @@ function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $userna /* 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 Suricata XMLRPC CARP sync with {$url}:{$port}."; + if (!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC sync with {$url}:{$port}."; log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); - } elseif($resp->faultCode()) { - $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); } else { - log_error("[suricata] Suricata pkg configuration XMLRPC CARP sync successfully completed with {$url}:{$port}."); + log_error("[suricata] Package configuration XMLRPC sync successfully completed with {$url}:{$port}."); } $downloadrulescmd = ""; if ($syncdownloadrules == "yes") { - $downloadrulescmd = "log_error(gettext(\"[suricata] XMLRPC pkg CARP sync: Update of downloaded rule sets requested...\"));\n"; + $downloadrulescmd = "log_error(gettext(\"[suricata] XMLRPC pkg sync: Update of downloaded rule sets requested...\"));\n"; $downloadrulescmd .= "\tinclude_once(\"/usr/local/pkg/suricata/suricata_check_for_rule_updates.php\");\n"; } $suricatastart = ""; if ($syncstartsuricata == "ON") { - $suricatastart = "log_error(gettext(\"[suricata] XMLRPC pkg CARP sync: Checking Suricata status...\"));\n"; + $suricatastart = "log_error(gettext(\"[suricata] XMLRPC pkg sync: Checking Suricata status...\"));\n"; $suricatastart .= "\tif (!is_process_running(\"suricata\")) {\n"; - $suricatastart .= "\t\tlog_error(gettext(\"[suricata] XMLRPC pkg CARP sync: Suricata not running. Sending a start command...\"));\n"; + $suricatastart .= "\t\tlog_error(gettext(\"[suricata] XMLRPC pkg sync: Suricata not running. Sending a start command...\"));\n"; $suricatastart .= "\t\t\$sh_script = RCFILEPREFIX . \"suricata.sh\";\n"; $suricatastart .= "\t\tmwexec_bg(\"{\$sh_script} start\");\n\t}\n"; - $suricatastart .= "\telse {\n\t\tlog_error(gettext(\"[suricata] XMLRPC pkg CARP sync: Suricata is running...\"));\n\t}\n"; + $suricatastart .= "\telse {\n\t\tlog_error(gettext(\"[suricata] XMLRPC pkg sync: Suricata is running...\"));\n\t}\n"; } /*************************************************/ @@ -3529,14 +3547,14 @@ function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $userna \$pkg_interface = "console"; {$downloadrulescmd} unset(\$g["suricata_postinstall"]); - log_error(gettext("[suricata] XMLRPC pkg CARP sync: Generating suricata.yaml file using Master Host settings...")); + log_error(gettext("[suricata] XMLRPC pkg sync: Generating suricata.yaml file using Master Host settings...")); \$rebuild_rules = true; conf_mount_rw(); sync_suricata_package_config(); conf_mount_ro(); \$rebuild_rules = false; {$suricatastart} - log_error(gettext("[suricata] XMLRPC pkg CARP sync process on this host is complete...")); + log_error(gettext("[suricata] XMLRPC pkg sync process on this host is complete...")); \$pkg_interface = \$orig_pkg_interface; unset(\$g["suricata_sync_in_progress"]); return true; @@ -3557,21 +3575,21 @@ EOD; XML_RPC_encode($execcmd) ); - log_error("[suricata] Suricata XMLRPC CARP sync sending reload configuration cmd set as a file to {$url}:{$port}."); + log_error("[suricata] XMLRPC sync sending reload configuration cmd set as a file to {$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 Suricata XMLRPC CARP sync with {$url}:{$port} (pfsense.exec_php)."; + if (!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); - } elseif($resp->faultCode()) { - $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); } else { - log_error("[suricata] Suricata pkg XMLRPC CARP sync reload configuration success with {$url}:{$port} (pfsense.exec_php)."); + log_error("[suricata] XMLRPC sync reload configuration success with {$url}:{$port} (pfsense.exec_php)."); } /*************************************************/ @@ -3583,19 +3601,19 @@ EOD; XML_RPC_encode($password), XML_RPC_encode($execcmd) ); - log_error("[suricata] Suricata XMLRPC CARP sync sending {$url}:{$port} cmd to execute configuration reload."); + log_error("[suricata] XMLRPC sync sending {$url}:{$port} cmd to execute configuration reload."); $msg2 = new XML_RPC_Message($method, $params2); $resp = $cli->send($msg2, $synctimeout); - if(!$resp) { - $error = "A communications error occurred while attempting Suricata XMLRPC CARP sync with {$url}:{$port} (pfsense.exec_php)."; + if (!$resp) { + $error = "A communications error occurred while attempting Suricata XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); - } elseif($resp->faultCode()) { - $error = "An error code was received while attempting Suricata XMLRPC CARP sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting Suricata XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); log_error($error); file_notice("sync_settings", $error, "Suricata Settings Sync", ""); } else { - log_error("[suricata] Suricata pkg XMLRPC CARP sync reload configuration success with {$url}:{$port} (pfsense.exec_php)."); + log_error("[suricata] XMLRPC sync reload configuration success with {$url}:{$port} (pfsense.exec_php)."); } } diff --git a/config/suricata/suricata_sync.xml b/config/suricata/suricata_sync.xml index 28083d8d..c2f5ec83 100644 --- a/config/suricata/suricata_sync.xml +++ b/config/suricata/suricata_sync.xml @@ -1,56 +1,49 @@ <?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd"> -<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> +<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> - <copyright> + <copyright> <![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* -based on snortsync.xml developed as part -of pfSense (http://www.pfSense.com) -Copyright (C) 2013 Marcello Coutinho -based on pfblocker_sync.xml -All rights reserved. - -modified for use with Suricata package -Copyright (C) 2014 Bill Meeks -All rights reserved. - -Based on m0n0wall (http://m0n0.ch/wall) -Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>. -All rights reserved. + suricata_sync.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2013 Marcello Coutinho + Copyright (C) 2014-2015 Bill Meeks + Copyright (C) 2015 ESF, LLC + All rights reserved. */ -/* ========================================================================== */ +/* ====================================================================================== */ /* -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + 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. -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. -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. + 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. */ -/* ========================================================================== */ -]]></copyright> - <description><![CDATA[Describe your package here]]></description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> +/* ====================================================================================== */ + ]]> + </copyright> <name>suricatasync</name> - <version>1.0</version> + <version>2.1.8</version> <title>Suricata: XMLRPC Sync</title> <include_file>/usr/local/pkg/suricata/suricata.inc</include_file> <tabs> @@ -183,11 +176,11 @@ POSSIBILITY OF SUCH DAMAGE. </options> </rowhelperfield> <rowhelperfield> - <fielddescr>IP-Address</fielddescr> + <fielddescr>IP Address/Hostname</fielddescr> <fieldname>varsyncipaddress</fieldname> - <description><![CDATA[IP Address of the destination host.]]></description> + <description><![CDATA[IP address or hostname of the destination host.]]></description> <type>input</type> - <size>15</size> + <size>40</size> </rowhelperfield> <rowhelperfield> <fielddescr>Port</fielddescr> @@ -213,8 +206,6 @@ POSSIBILITY OF SUCH DAMAGE. </rowhelper> </field> </fields> - <custom_delete_php_command> - </custom_delete_php_command> <custom_php_resync_config_command> write_config("Suricata pkg: updating CARP sync info.");suricata_sync_on_changes(); </custom_php_resync_config_command> diff --git a/config/tinydns/tinydns_xmlrpc_sync.php b/config/syslog-ng/syslog-ng.priv.inc index 0610e286..96722a7b 100644 --- a/config/tinydns/tinydns_xmlrpc_sync.php +++ b/config/syslog-ng/syslog-ng.priv.inc @@ -1,9 +1,8 @@ <?php - -/* $Id$ */ /* - tinydns_xmlrcpc_sync.php - Copyright (C) 2006 Scott Ullrich + syslog-ng.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC All rights reserved. Redistribution and use in source and binary forms, with or without @@ -27,33 +26,19 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +global $priv_list; -/* NOTE: this file gets included from the pfSense filter.inc plugin process */ - -require_once("config.inc"); -require_once("/usr/local/pkg/tinydns.inc"); -require_once("service-utils.inc"); - -if($notnow) { +$priv_list['page-services-syslogng'] = array(); +$priv_list['page-services-syslogng']['name'] = "WebCfg - Services: syslog-ng package"; +$priv_list['page-services-syslogng']['descr'] = "Allow access to syslog-ng package GUI"; +$priv_list['page-services-syslogng']['match'] = array(); - /* disabled until Ticket #1318 can be fixed */ +$priv_list['page-services-syslogng']['match'][] = "pkg.php?xml=syslog-ng.xml*"; +$priv_list['page-services-syslogng']['match'][] = "pkg.php?xml=syslog-ng_advanced.xml*"; - if(!$config) { - log_error("\$config is not enabled from tinydns_xmlrpc_sync.php!!"); - } else { - if($config['installedpackages']['carpsettings']['config']) - $password = $config['installedpackages']['carpsettings']['config'][0]['password']; - if($config['installedpackages']['carpsettings']['config']) - $syncip = $config['installedpackages']['carpsettings']['config'][0]['synchronizetoip']; - if($config['installedpackages']['carpsettings']['config']) - $syncxmlrpc = $config['installedpackages']['tinydns']['config'][0]['syncxmlrpc']; - /* option enabled? */ - if($syncxmlrpc) - if($syncip) - if($password) - tinydns_do_xmlrpc_sync($syncip, $password); - } +$priv_list['page-services-syslogng']['match'][] = "pkg_edit.php?xml=syslog-ng.xml*"; +$priv_list['page-services-syslogng']['match'][] = "pkg_edit.php?xml=syslog-ng_advanced.xml*"; -} +$priv_list['page-services-syslogng']['match'][] = "syslog-ng_log_viewer.php*"; -?>
\ No newline at end of file +?> diff --git a/config/syslog-ng/syslog-ng.xml b/config/syslog-ng/syslog-ng.xml index 9b0ccffc..81942926 100644 --- a/config/syslog-ng/syslog-ng.xml +++ b/config/syslog-ng/syslog-ng.xml @@ -42,7 +42,7 @@ ]]> </copyright> <name>Syslog-ng</name> - <version>1.0.8</version> + <version>1.1.1</version> <title>Services: Syslog-ng</title> <include_file>/usr/local/pkg/syslog-ng.inc</include_file> <menu> @@ -76,6 +76,10 @@ <item>https://packages.pfsense.org/packages/config/syslog-ng/syslog-ng.inc</item> </additional_files_needed> <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/syslog-ng/syslog-ng.priv.inc</item> + </additional_files_needed> + <additional_files_needed> <prefix>/usr/local/pkg/</prefix> <item>https://packages.pfsense.org/packages/config/syslog-ng/syslog-ng_advanced.xml</item> </additional_files_needed> diff --git a/config/tftp2/tftp.inc b/config/tftp2/tftp.inc index 67054619..75ddaac8 100644 --- a/config/tftp2/tftp.inc +++ b/config/tftp2/tftp.inc @@ -50,10 +50,10 @@ function tftp_install_command() { // Restore backup if it exists if (file_exists($tftpbackup)) { - system("/usr/bin/tar xvpfz {$tftpbackup} -C /"); - system("/bin/chmod -R 0744 {$tftpdir}/*"); - unset($tftpbackup); + mwexec("/usr/bin/tar xvpfz {$tftpbackup} -C /"); + mwexec("/bin/chmod -R 0744 {$tftpdir}/*"); } + unset($tftpdir, $tftpbackup); } function tftp_deinstall_command() { @@ -68,11 +68,9 @@ function tftp_generate_rules($type) { return; } - // Open inetd.conf write handle + // Add tftpd daemon to inetd $inetd_fd = fopen("/var/etc/inetd.conf", "a+"); - // Add tftp daemon fwrite($inetd_fd, "tftp\t\tdgram\tudp\twait\t\troot\t/usr/libexec/tftpd\ttftpd /tftpboot\n"); - // Close file handle fclose($inetd_fd); if (!empty($config['installedpackages']['tftpd']['config'][0]['tftpdinterface'])) { diff --git a/config/tftp2/tftp.priv.inc b/config/tftp2/tftp.priv.inc new file mode 100644 index 00000000..14691924 --- /dev/null +++ b/config/tftp2/tftp.priv.inc @@ -0,0 +1,38 @@ +<?php +/* + tftp.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-tftp'] = array(); +$priv_list['page-services-tftp']['name'] = "WebCfg - Services: TFTP package"; +$priv_list['page-services-tftp']['descr'] = "Allow access to TFTP package GUI"; +$priv_list['page-services-tftp']['match'] = array(); + +$priv_list['page-services-tftp']['match'][] = "tftp_files.php*"; + +?> diff --git a/config/tftp2/tftp.xml b/config/tftp2/tftp.xml index 2a526a4c..33fb9c3d 100644 --- a/config/tftp2/tftp.xml +++ b/config/tftp2/tftp.xml @@ -43,7 +43,7 @@ ]]> </copyright> <name>tftp Settings</name> - <version>2.0</version> + <version>2.2.2</version> <title>TFTP: Settings</title> <include_file>/usr/local/pkg/tftp.inc</include_file> <menu> @@ -56,23 +56,21 @@ <service> <name>tftp</name> <executable>inetd</executable> - <description>TFTP daemon</description> + <description>TFTP Daemon</description> </service> - <tabs> - <tab> - <text>Files</text> - <url>tftp_files.php</url> - </tab> - </tabs> <configpath>installedpackages->$packagename</configpath> <additional_files_needed> <prefix>/usr/local/pkg/</prefix> <item>https://packages.pfsense.org/packages/config/tftp2/tftp.inc</item> - </additional_files_needed> + </additional_files_needed> + <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/tftp2/tftp.priv.inc</item> + </additional_files_needed> <additional_files_needed> <prefix>/usr/local/www/</prefix> <item>https://packages.pfsense.org/packages/config/tftp2/tftp_files.php</item> - </additional_files_needed> + </additional_files_needed> <custom_php_install_command> tftp_install_command(); </custom_php_install_command> diff --git a/config/tftp2/tftp_files.php b/config/tftp2/tftp_files.php index eebe4c5e..0352f4a0 100644 --- a/config/tftp2/tftp_files.php +++ b/config/tftp2/tftp_files.php @@ -29,6 +29,7 @@ POSSIBILITY OF SUCH DAMAGE. */ require_once("guiconfig.inc"); +require_once("util.inc"); require_once("/usr/local/pkg/tftp.inc"); $pconfig['tftpdinterface'] = explode(",", $config['installedpackages']['tftpd']['config'][0]['tftpdinterface']); @@ -43,7 +44,7 @@ if (($_GET['a'] == "download") && $_GET['t'] == "backup") { conf_mount_rw(); $filename = $backup_filename; $download_dir = $backup_dir; - system("tar -czC / -f {$backup_path} tftpboot"); + mwexec("/usr/bin/tar -czC / -f {$backup_path} tftpboot"); conf_mount_ro(); } @@ -73,8 +74,8 @@ if ($_GET['a'] == "other") { if (file_exists($backup_path)) { //echo "The file $filename exists"; conf_mount_rw(); - system("tar -xpzC / -f {$backup_path}"); - system("chmod -R 744 {$files_dir}/*"); + mwexec("/usr/bin/tar -xpzC / -f {$backup_path}"); + mwexec("/bin/chmod -R 744 {$files_dir}/*"); header( 'Location: tftp_files.php?savemsg=Backup+has+been+restored.' ) ; conf_mount_ro(); } else { @@ -100,7 +101,7 @@ if (($_POST['submit'] == "Upload") && is_uploaded_file($_FILES['ulfile']['tmp_na conf_mount_rw(); move_uploaded_file($_FILES['ulfile']['tmp_name'], "{$files_dir}/{$_FILES['ulfile']['name']}"); $savemsg = "Uploaded file to {$files_dir}/" . htmlentities($_FILES['ulfile']['name']); - system('chmod -R 744 {$files_dir}/*'); + mwexec('/bin/chmod -R 744 {$files_dir}/*'); unset($_POST['txtCommand']); conf_mount_ro(); } @@ -122,7 +123,7 @@ include("head.inc"); <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> -<p class="pgtitle">TFTP: Files</p> +<p class="pgtitle">TFTP: Settings/Files</p> <?php $savemsg = $_GET["savemsg"]; @@ -137,7 +138,7 @@ if ($savemsg) { <?php $tab_array = array(); - $tab_array[] = array(gettext("Files"), false, "tftp_files.php"); + $tab_array[] = array(gettext("TFTP"), false, "tftp_files.php"); display_top_tabs($tab_array); ?> @@ -145,14 +146,16 @@ if ($savemsg) { </table> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tr><td> +<div id="mainarea"> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> <tr> - <td class="tabcont"> - <table width="100%" border="0" cellpadding="6" cellspacing="0"> + <td colspan="2" class="listtopic">TFTP Daemon Interfaces</td> + </tr> <tr> + <td width="22%" class="vncell">Select TFTP Daemon Interface(s).</td> <td width="78%" class="vtable"> <form action="tftp_files.php" method="post" enctype="multipart/form-data" name="frmInterfaces" onsubmit=""> - <p><span class="vexpl"><strong>TFTP Daemon Interfaces</strong></span></p> - <?=gettext("Choose the interfaces where you want the TFTP daemon to accept connections.");?><br/><br/> <select name="tftpdinterface[]" multiple="multiple" class="formselect" size="3"> <?php $ifdescs = get_configured_interface_with_descr(); @@ -164,70 +167,46 @@ if ($savemsg) { echo "\t\t\t<option value=\"{$ifent}\"{$selected}>" . $ifdesc . "</option>\n"; } ?> - </select><br /> - <input name="submit" type="submit" class="button" id="save" value="Save" /> + </select><br /><br /> + <span class="vexpl"> + Choose the interfaces where you want the TFTP Daemon to accept connections.<br/> + <strong>Hint:</strong> If you simply need to (re)start tftpd/inetd, just use the Save button without making any changes here.<br /><br /> + </span> + <input name="submit" type="submit" class="formbtns" id="save" value="Save" title="Save settings" /> </form> </td> </tr> <tr> - <td> - <p><span class="vexpl"><span class="red"><strong>TFTP files</strong></span><br /> - Trivial File Transport Protocol is a very simple file transfer protocol.<br /> - Use the file upload to add files to the /tftpboot directory.<br /> - Click on the file from the file list below to download it.<br /> - </span></p> - </td> + <td colspan="2" class="listtopic">TFTP Files Upload</td> </tr> - </table> - <br /> - <div id="niftyOutter"> - <form action="tftp_files.php" method="post" enctype="multipart/form-data" name="frmUpload" onsubmit=""> - <table> - <tr> - <td align="right">File to upload:</td> - <td valign="top" class="label"> - <input name="ulfile" type="file" class="button" id="ulfile" /> - </td> - </tr> - <tr> - <td valign="top"> </td> - <td valign="top" class="label"> - <input name="submit" type="submit" class="button" id="upload" value="Upload" /> - </td> - </tr> - </table> - </form> - </div> - <br /><br /> - - <table width='690' cellpadding='0' cellspacing='0' border='0'> <tr> - <td width='80%'> - <strong>Backup / Restore</strong><br /> - The 'Backup' button compresses /tftpboot/ to /root/backup/tftp.bak.tgz; after that it presents the backup for download.<br /> - If the backup file does not exist in /root/backup/tftp.bak.tgz then the 'Restore' button will be hidden.<br /> - Use Diagnostics -> Command -> File to upload: to browse to the file and then click on upload.<br /> - After that, backup will be ready to be restored.<br /><br /> - </td> - <td width='20%' valign='middle' align='right'> - <input type="button" value="Backup" onclick="document.location.href='tftp_files.php?a=download&t=backup'" /> - <?php - if (file_exists('/root/backup/tftp.bak.tgz')) { - echo "<input type='button' value='Restore' onclick=\"document.location.href='tftp_files.php?a=other&t=restore';\" />\n"; - } - ?> + <td width="22%" class="vncell">Use the file upload to add files to the /tftpboot directory.</td> + <td width="78%" class="vtable"> + <form action="tftp_files.php" method="post" enctype="multipart/form-data" name="frmUpload" onsubmit=""> + <span class="vexpl">1. Select file to upload: </span> + <input name="ulfile" type="file" class="formbtns" id="ulfile" title="Select file to upload" /> + <br /> + <span class="vexpl">2. Upload the selected file: </span> + <input name="submit" type="submit" class="formbtns" id="upload" value="Upload" title="Upload file" /> + </form> </td> </tr> - </table> - <br /><br /> - <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> - <td width="25%" class="listhdrr">File Name (download)</td> - <td width="50%" class="listhdr">Last Modified</td> - <td width="50%" class="listhdr">Size</td> + <td colspan="3" class="listtopic">TFTP Files Download</td> </tr> + <tr> + <td colspan="3" class="vexpl">Click on the file from the file list below to download it.</td> + </tr> + <tr> + <td colspan="3"> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td width="25%" class="listhdrr">File Name (download)</td> + <td width="50%" class="listhdr">Last Modified</td> + <td width="50%" class="listhdr">Size</td> + </tr> <?php if ($handle = opendir('/tftpboot')) { @@ -267,13 +246,37 @@ if ($handle = opendir('/tftpboot')) { } ?> + <tr> + <td class="list" colspan="3"></td> + <td class="list"></td> + </tr> + </table> + </td> + </tr> + <tr> - <td class="list" colspan="3"></td> - <td class="list"></td> + <td colspan="2" class="listtopic">TFTP Backup / Restore</td> </tr> - </table> - </td> + <tr> + <td width="22%" class="vncell">Use the file upload to add files to the /tftpboot directory.</td> + <td width="78%" class="vtable"> + <span class="vexpl"><strong>Backup:</strong> 'Backup' button compresses /tftpboot/ to /root/backup/tftp.bak.tgz; after that it presents the backup for download.<br /> + <strong>Restore:</strong> If the backup file does not exist in /root/backup/tftp.bak.tgz then the 'Restore' button will be hidden. + To 'Restore' a previously downloaded backup, use <a href="diag_backup.php" title="Upload file">Diagnostics -> Command Prompt -> File to upload</a> to browse to the file and then click on upload.<br /> + After that, backup will be ready to be restored.<br /><br /> + </span> + <input type="button" value="Backup" title="Create backup" onclick="document.location.href='tftp_files.php?a=download&t=backup'" /> + <?php + if (file_exists('/root/backup/tftp.bak.tgz')) { + echo "<input type='button' value='Restore' title='Restore backup' onclick=\"document.location.href='tftp_files.php?a=other&t=restore';\" />\n"; + } + ?> + </td> </tr> + </table> + +</div> +</td></tr> </table> </div> diff --git a/config/tinc/tinc.priv.inc b/config/tinc/tinc.priv.inc new file mode 100644 index 00000000..d8b45c5b --- /dev/null +++ b/config/tinc/tinc.priv.inc @@ -0,0 +1,44 @@ +<?php +/* + tinc.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-vpn-tinc'] = array(); +$priv_list['page-vpn-tinc']['name'] = "WebCfg - VPN: tinc package"; +$priv_list['page-vpn-tinc']['descr'] = "Allow access to tinc package GUI"; +$priv_list['page-vpn-tinc']['match'] = array(); + +$priv_list['page-vpn-tinc']['match'][] = "pkg.php?xml=tinc.xml*"; +$priv_list['page-vpn-tinc']['match'][] = "pkg.php?xml=tinc_hosts.xml*"; + +$priv_list['page-vpn-tinc']['match'][] = "pkg_edit.php?xml=tinc.xml*"; +$priv_list['page-vpn-tinc']['match'][] = "pkg_edit.php?xml=tinc_hosts.xml*"; + +$priv_list['page-vpn-tinc']['match'][] = "status_tinc.php*"; + +?> diff --git a/config/tinc/tinc.xml b/config/tinc/tinc.xml index 89d1e8ce..0f71e03d 100644 --- a/config/tinc/tinc.xml +++ b/config/tinc/tinc.xml @@ -42,8 +42,8 @@ </copyright> <description>A self-contained VPN solution designed to connect multiple sites together in a secure way.</description> <name>tinc</name> - <version>1.2.2</version> - <title>VPN: tinc - Config</title> + <version>1.2.4</version> + <title>VPN: Tinc: Settings</title> <include_file>/usr/local/pkg/tinc.inc</include_file> <configpath>['installedpackages']['package']['$packagename']['config']</configpath> <menu> @@ -53,7 +53,7 @@ <url>/pkg_edit.php?xml=tinc.xml</url> </menu> <menu> - <name>tinc VPN</name> + <name>Tinc VPN</name> <section>Status</section> <url>/status_tinc.php</url> </menu> @@ -65,7 +65,7 @@ </service> <tabs> <tab> - <text>Config</text> + <text>Settings</text> <url>/pkg_edit.php?xml=tinc.xml</url> <active/> </tab> @@ -79,6 +79,10 @@ <item>https://packages.pfsense.org/packages/config/tinc/tinc.inc</item> </additional_files_needed> <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/tinc/tinc.priv.inc</item> + </additional_files_needed> + <additional_files_needed> <prefix>/usr/local/pkg/</prefix> <item>https://packages.pfsense.org/packages/config/tinc/tinc_hosts.xml</item> </additional_files_needed> @@ -119,7 +123,7 @@ <fieldname>localip</fieldname> <description> <![CDATA[ - IP Address of local tunnel interface.<br /> + IP address of local tunnel interface.<br /> This is often the same IP as your routers LAN address. (Example: 192.168.2.1) ]]> </description> @@ -143,7 +147,7 @@ <fieldname>vpnnetmask</fieldname> <description> <![CDATA[ - This is the Netmask that defines what traffic is routed to the VPNs tunnel interface.<br /> + This is the netmask that defines what traffic is routed to the VPNs tunnel interface.<br /> It is usually broader then your local netmask. (Example: 255.255.0.0) ]]> </description> diff --git a/config/tinc/tinc_hosts.xml b/config/tinc/tinc_hosts.xml index b521d4a2..a10c1a9e 100644 --- a/config/tinc/tinc_hosts.xml +++ b/config/tinc/tinc_hosts.xml @@ -41,13 +41,13 @@ ]]> </copyright> <name>tinchosts</name> - <version>1.2.2</version> - <title>VPN: tinc - Hosts</title> + <version>1.2.4</version> + <title>VPN: Tinc: Hosts</title> <include_file>/usr/local/pkg/tinc.inc</include_file> <configpath>['installedpackages']['package']['$packagename']['config']</configpath> <tabs> <tab> - <text>Config</text> + <text>Settings</text> <url>/pkg_edit.php?xml=tinc.xml</url> </tab> <tab> @@ -75,7 +75,6 @@ <fieldname>connect</fieldname> <type>checkbox</type> </columnitem> - </adddeleteeditpagefields> <fields> <field> @@ -107,7 +106,7 @@ <type>checkbox</type> </field> <field> - <fielddescr>RSA public key</fielddescr> + <fielddescr>RSA Public Key</fielddescr> <fieldname>cert_pub</fieldname> <description> <![CDATA[ diff --git a/config/tinydns/tinydns.inc b/config/tinydns/tinydns.inc index 3bf64777..5e61fc05 100644 --- a/config/tinydns/tinydns.inc +++ b/config/tinydns/tinydns.inc @@ -1,11 +1,10 @@ <?php - -/* $Id$ */ /* tinydns.inc + part of pfSense (https://www.pfSense.org/) Copyright (C) 2006, 2007, 2008, 2009 Scott Ullrich - Parts Copyright (C) 2007 Goffredo Andreone - part of pfSense + Copyright (C) 2007 Goffredo Andreone + Copyright (C) 2015 ESF, LLC All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,7 +28,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - if(!function_exists("filter_configure")) require_once("filter.inc"); @@ -208,6 +206,35 @@ function tinydns_custom_php_deinstall_command() { conf_mount_ro(); } +function tinydns_upgrade_config() { + /* Remove obsolete XMLRPC sync configuration */ + if (is_array($config['installedpackages']['tinydnssync']['config'])) { + if (isset($config['installedpackages']['tinydnssync']['config'][0]['ipaddress'])) { + unset($config['installedpackages']['tinydnssync']['config'][0]['ipaddress']); + } + if (isset($config['installedpackages']['tinydnssync']['config'][0]['ipaddress2'])) { + unset($config['installedpackages']['tinydnssync']['config'][0]['ipaddress2']); + } + if (isset($config['installedpackages']['tinydnssync']['config'][0]['ipaddress3'])) { + unset($config['installedpackages']['tinydnssync']['config'][0]['ipaddress3']); + } + if (isset($config['installedpackages']['tinydnssync']['config'][0]['password'])) { + unset($config['installedpackages']['tinydnssync']['config'][0]['password']); + } + if (isset($config['installedpackages']['tinydnssync']['config'][0]['password2'])) { + unset($config['installedpackages']['tinydnssync']['config'][0]['password2']); + } + if (isset($config['installedpackages']['tinydnssync']['config'][0]['password3'])) { + unset($config['installedpackages']['tinydnssync']['config'][0]['password3']); + } + } + if (is_array($config['installedpackages']['tinydns']['config'])) { + if (isset($config['installedpackages']['tinydns']['config'][0]['syncxmlrpc'])) { + unset($config['installedpackages']['tinydns']['config'][0]['syncxmlrpc']); + } + } +} + function tinydns_custom_php_changeip_command() { global $g, $config; conf_mount_rw(); @@ -232,10 +259,18 @@ function tinydns_custom_php_changeip_command() { if(!is_dir("{$g['varrun_path']}/service")) exec("/bin/mkdir -p {$g['varrun_path']}/service"); - exec("/usr/sbin/pw useradd Gtinydns"); - exec("/usr/sbin/pw useradd Gdnslog"); - exec("/usr/sbin/pw useradd Gdnscache"); - exec("/usr/sbin/pw useradd Gaxfrdns"); + if (!exec("/usr/sbin/pw usershow Gtinydns")) { + exec("/usr/sbin/pw useradd Gtinydns"); + } + if (!exec("/usr/sbin/pw usershow Gdnslog")) { + exec("/usr/sbin/pw useradd Gdnslog"); + } + if (!exec("/usr/sbin/pw usershow Gdnscache")) { + exec("/usr/sbin/pw useradd Gdnscache"); + } + if (!exec("/usr/sbin/pw usershow Gaxfrdns")) { + exec("/usr/sbin/pw useradd Gaxfrdns"); + } exec("/bin/rm -r {$g['varetc_path']}/dnscache*"); exec("/bin/rm -r {$g['varrun_path']}/service/dnscache*"); @@ -259,21 +294,14 @@ function tinydns_custom_php_changeip_command() { foreach ($interfaces as $dnsidx => $dnsif) { $dnscacheif = convert_friendly_interface_to_real_interface_name($dnsif); $dnscacheip = find_interface_ip($dnscacheif); - if (intval($config['version']) >= 6) - $ipmask = find_interface_subnet($dnscacheif); - else - $ipmask = $config['interfaces'][$dnsif]['subnet']; - - if (intval($config['version']) <= 8) { - if (is_ipaddr($ipaddress)) - $arr = tinydns_get_ip_subnet_arpa($ipaddress, $ipmask); - } else { - if (is_ipaddrv4($ipaddress)) { - $arr = tinydns_get_ip_subnet_arpa($ipaddress, $ipmask); - } elseif (is_ipaddrv6($ipaddress)) { - $arr = tinydns_get_ip6_subnet_arpa($ipaddress, $ipmask); - } + $ipmask = find_interface_subnet($dnscacheif); + + if (is_ipaddrv4($ipaddress)) { + $arr = tinydns_get_ip_subnet_arpa($ipaddress, $ipmask); + } elseif (is_ipaddrv6($ipaddress)) { + $arr = tinydns_get_ip6_subnet_arpa($ipaddress, $ipmask); } + $dnsuserip = $arr[0]; //exec("/bin/mkdir -p {$g['varetc_path']}/dnscache{$dnsidx}"); exec("/usr/local/bin/dnscache-conf Gdnscache Gdnslog {$g['varetc_path']}/dnscache{$dnsidx} {$dnscacheip}"); @@ -305,7 +333,7 @@ function tinydns_custom_php_changeip_command() { exec("{$svc_path} -xk {$g['varetc_path']}/dnscache{$dnsidx}"); } } else { - $interfaces = explode(",", $$config['installedpackages']['tinydns']['config'][0]['interface']); + $interfaces = explode(",", $config['installedpackages']['tinydns']['config'][0]['interface']); foreach ($interfaces as $dnsidx => $dnsif) { if(is_dir("{$g['varetc_path']}/dnscache{$dnsidx}")) dnscache_use_root_servers($dnsidx); @@ -517,10 +545,7 @@ function tinydns_create_zone_file() { foreach ($interfaces as $dnsif) { $dnsrif = convert_friendly_interface_to_real_interface_name($dnsif); $dnsrip = find_interface_ip($dnsrif); - if (intval($config['version']) >= 6) - $ipmask = find_interface_subnet($dnsrif); - else - $ipmask = $config['interfaces'][$dnsif]['subnet']; + $ipmask = find_interface_subnet($dnsrif); $dhcpdfqdn = "{$dhcpdhostname}.{$dhcpddomain}"; tinydns_complete_soa_record($fd, $dnsrip, $ipmask, $dhcpdhostname, $dhcpddomain); } @@ -544,10 +569,7 @@ function tinydns_create_zone_file() { $dnsrif = convert_friendly_interface_to_real_interface_name($dnsif); $dnsrip = find_interface_ip($dnsrif); - if (intval($config['version']) >= 6) - $ipmask = find_interface_subnet($dnsrif); - else - $ipmask = $config['interfaces'][$dnsif]['subnet']; + $ipmask = find_interface_subnet($dnsrif); $dhcpdfqdn = "{$dhcpdhostname}.{$dhcpddomain}"; tinydns_complete_soa_record($fd, $dnsrip, $ipmask, $dhcpdhostname, $dhcpddomain); @@ -606,15 +628,10 @@ function tinydns_create_zone_file() { if($record_data) { fwrite($fd, $record_data . "\n"); if ($domain['rdns'] || ($domain['recordtype'] == 'PTR')) { - if (intval($config['version']) <= 8) { - if (is_ipaddr($ipaddress)) - $rip = tinydns_get_ip_subnet_arpa($ipaddress, 32); - } else { - if (is_ipaddrv4($ipaddress)) { - $rip = tinydns_get_ip_subnet_arpa($ipaddress, 32); - } elseif (is_ipaddrv6($ipaddress)) { - $rip = tinydns_get_ip6_subnet_arpa($ipaddress, 128); - } + if (is_ipaddrv4($ipaddress)) { + $rip = tinydns_get_ip_subnet_arpa($ipaddress, 32); + } elseif (is_ipaddrv6($ipaddress)) { + $rip = tinydns_get_ip6_subnet_arpa($ipaddress, 128); } if($rip) @@ -651,95 +668,146 @@ function tinydns_create_zone_file() { function tinydns_sync_on_changes() { global $g, $config; - log_error("[tinydns] tinydns_xmlrpc_sync.php is starting."); - $synconchanges = $config['installedpackages']['tinydnssync']['config'][0]['synconchanges']; - if(!$synconchanges) - return; - $sync_hosts = $config['installedpackages']['tinydnssync']['config']; - $previous_ip = ""; - $x=0; - $sh = $config['installedpackages']['tinydnssync']['config'][0]; - for($x=1; $x<5; $x++) { - if($x > 1) - $counter = $x; - else - $counter = ""; - $sync_to_ip = ""; - $password = ""; - if($sh['ipaddress' . $counter]) { - $sync_to_ip = $sh['ipaddress' . $counter]; - $password = $sh['password' . $counter]; + + /* XMLRPC sync */ + if (is_array($config['installedpackages']['tinydnssync']['config'])) { + $tinydns_sync = $config['installedpackages']['tinydnssync']['config'][0]; + $synconchanges = $tinydns_sync['synconchanges']; + $synctimeout = $tinydns_sync['synctimeout'] ?: '250'; + switch ($synconchanges) { + case "manual": + if (is_array($tinydns_sync['row'])) { + $rs = $tinydns_sync['row']; + } else { + log_error("[tinydns] XMLRPC sync is enabled but there are no hosts configured as replication targets."); + return; + } + break; + case "auto": + if (is_array($config['hasync'])) { + $system_carp = $config['hasync']; + $rs[0]['ipaddress'] = $system_carp['synchronizetoip']; + $rs[0]['username'] = $system_carp['username']; + $rs[0]['password'] = $system_carp['password']; + $rs[0]['syncdestinenable'] = FALSE; + + // XMLRPC sync is currently only supported over connections using the same protocol and port as this system + if ($config['system']['webgui']['protocol'] == "http") { + $rs[0]['syncprotocol'] = "http"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '80'; + } else { + $rs[0]['syncprotocol'] = "https"; + $rs[0]['syncport'] = $config['system']['webgui']['port'] ?: '443'; + } + if ($system_carp['synchronizetoip'] == "") { + log_error("[tinydns] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } else { + $rs[0]['syncdestinenable'] = TRUE; + } + } else { + log_error("[tinydns] XMLRPC CARP/HA sync is enabled but there are no system backup hosts configured as replication targets."); + return; + } + break; + default: + return; + break; } - if($password && $sync_to_ip) - tinydns_do_xmlrpc_sync($sync_to_ip, $password); - } - tinydns_create_zone_file(); - if ($config['installedpackages']['tinydns']['config'][0]['enableipmonitoring']) { - tinydns_setup_ping_items(); - } - log_error("[tinydns] tinydns_xmlrpc_sync.php is ending."); + if (is_array($rs)) { + log_error("[tinydns] XMLRPC sync is starting."); + foreach ($rs as $sh) { + // Only sync enabled replication targets + if ($sh['syncdestinenable']) { + $sync_to_ip = $sh['ipaddress']; + $port = $sh['syncport']; + $username = $sh['username'] ?: 'admin'; + $password = $sh['password']; + $protocol = $sh['syncprotocol']; + + $error = ''; + $valid = TRUE; + + if ($password == "") { + $error = "Password parameter is empty. "; + $valid = FALSE; + } + if (!is_ipaddr($sync_to_ip) && !is_hostname($sync_to_ip) && !is_domain($sync_to_ip)) { + $error .= "Misconfigured Replication Target IP Address or Hostname. "; + $valid = FALSE; + } + if (!is_port($port)) { + $error .= "Misconfigured Replication Target Port. "; + $valid = FALSE; + } + if ($valid) { + tinydns_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout); + } else { + log_error("[tinydns] XMLRPC sync with '{$sync_to_ip}' aborted due to the following error(s): {$error}"); + } + } + } + log_error("[tinydns] tinydns_xmlrpc_sync.php is ending."); + } + } } -function tinydns_do_xmlrpc_sync($sync_to_ip, $password) { +/* Do the actual XMLRPC sync. */ +function tinydns_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) { global $config, $g; - if(!$password) + /* Detect boot process, do nothing during boot. */ + if (function_exists("platform_booting")) { + if (platform_booting()) { + return; + } + } elseif ($g['booting']) { return; + } - if(!$sync_to_ip) + if ($username == "" || $password == "" || $sync_to_ip == "" || $port == "" || $protocol == "") { + log_error("[tinydns] A required XMLRPC sync parameter (username, password, replication target, port or protocol) is empty ... aborting pkg sync"); return; + } - $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; + // Take care of IPv6 literal address + if (is_ipaddrv6($sync_to_ip)) { + $sync_to_ip = "[{$sync_to_ip}]"; + } - /* xml will hold the sections to sync */ + $url = "{$protocol}://{$sync_to_ip}"; + + /* XML will hold the sections to sync. */ $xml = array(); $xml['tinydnsdomains'] = $config['installedpackages']['tinydnsdomains']; + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($xml)); - /* 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("Beginning TinyDNS XMLRPC sync to {$url}:{$port}."); + /* Set a few variables needed for sync code */ $method = 'pfsense.merge_installedpackages_section_xmlrpc'; $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); - $cli->setCredentials('admin', $password); - if($g['debug']) + $cli->setCredentials($username, $password); + if ($g['debug']) { $cli->setDebug(1); - /* send our XMLRPC message and timeout after 250 seconds */ - $resp = $cli->send($msg, "250"); - if(!$resp) { - $error = "A communications error occured while attempting tinydns XMLRPC sync with {$url}:{$port}."; - log_error($error); + } + /* Send our XMLRPC message and timeout after defined sync timeout value */ + $resp = $cli->send($msg, $synctimeout); + if (!$resp) { + $error = "A communications error occured while attempting XMLRPC sync with {$url}:{$port}."; + log_error("[tinydns] {$error}"); file_notice("sync_settings", $error, "tinydns Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $cli->setDebug(1); - $resp = $cli->send($msg, "250"); - $error = "An error code was received while attempting tinydns XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $resp = $cli->send($msg, $synctimeout); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[tinydns] {$error}"); file_notice("sync_settings", $error, "tinydns Settings Sync", ""); } else { - log_error("tinydns XMLRPC sync successfully completed with {$url}:{$port}."); + log_error("[tinydns] XMLRPC sync successfully completed with {$url}:{$port}."); } - /* tell tinydns to reload our settings on the destionation sync host. */ + /* Tell tinydns to reload our settings on the destionation sync host. */ $method = 'pfsense.exec_php'; $execcmd = "require_once('functions.inc');\n"; $execcmd .= "require_once('/usr/local/pkg/tinydns.inc');\n"; @@ -749,31 +817,27 @@ function tinydns_do_xmlrpc_sync($sync_to_ip, $password) { $execcmd .= "tinydns_setup_ping_items();\n"; } - /* assemble xmlrpc payload */ - $params = array( - XML_RPC_encode($password), - XML_RPC_encode($execcmd) - ); + /* Assemble XMLRPC payload. */ + $params = array(XML_RPC_encode($password), XML_RPC_encode($execcmd)); - log_error("tinydns XMLRPC reload data {$url}:{$port}."); + log_error("[tinydns] XMLRPC reload data {$url}:{$port}."); $msg = new XML_RPC_Message($method, $params); $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); - $cli->setCredentials('admin', $password); - $resp = $cli->send($msg, "250"); - if(!$resp) { - $error = "A communications error occured while attempting tinydns XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; - log_error($error); + $cli->setCredentials($username, $password); + $resp = $cli->send($msg, $synctimeout); + if (!$resp) { + $error = "A communications error occured while attempting XMLRPC sync with {$url}:{$port} (pfsense.exec_php)."; + log_error("[tinydns] {$error}"); file_notice("sync_settings", $error, "tinydns Settings Sync", ""); - } elseif($resp->faultCode()) { + } elseif ($resp->faultCode()) { $cli->setDebug(1); - $resp = $cli->send($msg, "250"); - $error = "An error code was received while attempting tinydns XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); - log_error($error); + $resp = $cli->send($msg, $synctimeout); + $error = "An error code was received while attempting XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error("[tinydns] {$error}"); file_notice("sync_settings", $error, "tinydns Settings Sync", ""); } else { - log_error("tinydns XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); + log_error("[tinydns] XMLRPC reload data success with {$url}:{$port} (pfsense.exec_php)."); } - } /* formats data as a tinydns data row item */ @@ -789,18 +853,15 @@ function tinydns_get_rowline_data($recordip, $recordtype, $ttl, $hostname, $rdns /* Note that some of these are simplistic versions of TinyDNS record handling. Uber-users can always do "raw" entries... */ case "SOA": // .fqdn:ip:x:ttl:timestamp:lo - if (intval($config['version']) <= 8) { - $record_data = ".{$hostname}::{$recordip}{$ttl_string}"; + if (is_ipaddrv6($hostname)) { + list($rip, $rmask) = explode("/", $hostname); + $rmask = empty($rmask) ? 128 : $rmask; + $ip6_arpa = tinydns_get_ip6_subnet_arpa($rip, $rmask); + $record_data = ".{$ip6_arpa[1]}::{$recordip}{$ttl_string}"; } else { - if (is_ipaddrv6($hostname)) { - list($rip, $rmask) = explode("/", $hostname); - $rmask = empty($rmask) ? 128 : $rmask; - $ip6_arpa = tinydns_get_ip6_subnet_arpa($rip, $rmask); - $record_data = ".{$ip6_arpa[1]}::{$recordip}{$ttl_string}"; - } else { - $record_data = ".{$hostname}::{$recordip}{$ttl_string}"; - } + $record_data = ".{$hostname}::{$recordip}{$ttl_string}"; } + break; case "NS": // &serious.panic.mil:1.8.248.6:a @@ -832,17 +893,11 @@ function tinydns_get_rowline_data($recordip, $recordtype, $ttl, $hostname, $rdns case "PTR": /* "^" creates "PTR" record only to allow reverse DNS */ // ^fqdn:p:ttl:timestamp:lo - - if (intval($config['version']) <= 8) { - if (is_ipaddr($recordip)) - $record_data = "^{$hostname}:{$recordip}{$ttl_string}"; - } else { - if (is_ipaddrv4($recordip)) { - $record_data = "^{$hostname}:{$recordip}{$ttl_string}"; - } elseif (is_ipaddrv6($recordip)) { - $ip6_arpa = tinydns_get_ip6_subnet_arpa($recordip, 128); - $record_data = "^{$ip6_arpa[1]}:{$hostname}{$ttl_string}"; - } + if (is_ipaddrv4($recordip)) { + $record_data = "^{$hostname}:{$recordip}{$ttl_string}"; + } elseif (is_ipaddrv6($recordip)) { + $ip6_arpa = tinydns_get_ip6_subnet_arpa($recordip, 128); + $record_data = "^{$ip6_arpa[1]}:{$hostname}{$ttl_string}"; } break; case "A": @@ -1016,15 +1071,10 @@ function tinydns_complete_soa_record($fd, $ip, $ipmask, $nsname, $domain) { global $config; $fqdn = "{$nsname}.{$domain}"; - if (intval($config['version']) <= 8) { - if (is_ipaddr($ipaddress)) - $rip = tinydns_get_ip_subnet_arpa($ipaddress, $ipmask); - } else { - if (is_ipaddrv4($ipaddress)) { - $rip = tinydns_get_ip_subnet_arpa($ipaddress, $ipmask); - } elseif (is_ipaddrv6($ipaddress)) { - $rip = tinydns_get_ip6_subnet_arpa($ipaddress, $ipmask); - } + if (is_ipaddrv4($ipaddress)) { + $rip = tinydns_get_ip_subnet_arpa($ipaddress, $ipmask); + } elseif (is_ipaddrv6($ipaddress)) { + $rip = tinydns_get_ip6_subnet_arpa($ipaddress, $ipmask); } $soa = ".{$domain}::{$fqdn}"; @@ -1181,53 +1231,20 @@ function tinydns_dnscache_forwarding_servers($index) { global $g, $config; exec("echo 1 > {$g['varetc_path']}/dnscache{$index}/env/FORWARDONLY"); - if(is_dir("{$g['varetc_path']}/dnscache{$index}/root/servers/")) + if (is_dir("{$g['varetc_path']}/dnscache{$index}/root/servers/")) { exec("rm -R {$g['varetc_path']}/dnscache/root/servers/"); + } exec("/bin/mkdir -p {$g['varetc_path']}/dnscache{$index}/root/servers/"); - if (intval($config['version']) >= 6) - if (!empty(glob("{$g['varetc_path']}/nameserver_*"))) { - exec("/bin/cat {$g['varetc_path']}/nameserver_* > {$g['varetc_path']}/dnscache{$index}/root/servers/@"); - } else { - $fw = fopen("{$g['varetc_path']}/dnscache{$index}/root/servers/@", "w"); - if (! $fw) { - printf("Error: cannot open dnscache/root/servers/@ in tinydns_register_forwarding_servers().\n"); - return 1; - } - fwrite($fw, $config['system']['dnsserver'][0]); - fclose($fw); - } - else { - $fr = fopen("{$g['varetc_path']}/resolv.conf.dnscache", "r"); - if (! $fr) { - printf("Error: cannot open resolv.conf.dnscache in tinydns_register_forwarding_servers().\n"); - return 1; - } - $lip = strlen("nameserver") + 1; - $j = 0; - $iprecords = ""; - while (!feof($fr)) { - $routers = fgets($fr, 4096); - $discard = ($routers[0] == "\n"); - if(!$discard) { - if ($routerip = strstr($routers,"nameserver")) { - $routerip = substr($routerip,$lip); - if($routerip) { - $j += 1; - $routera = "{$routerip}"; - $iprecords .= $routera; - } - } - } - } - fclose($fr); - $fr = fopen("{$g['varetc_path']}/dnscache{$index}/root/servers/@", "w"); - if (! $fr) { - printf("Error: cannot write to {$g['varetc_path']}/dnscache{$index}/root/servers/@ in tinydns_dnscache_forwarding_servers().\n"); + if (!empty(glob("{$g['varetc_path']}/nameserver_*"))) { + exec("/bin/cat {$g['varetc_path']}/nameserver_* > {$g['varetc_path']}/dnscache{$index}/root/servers/@"); + } else { + $fw = fopen("{$g['varetc_path']}/dnscache{$index}/root/servers/@", "w"); + if (!$fw) { + printf("Error: cannot open dnscache/root/servers/@ in tinydns_register_forwarding_servers().\n"); return 1; } - if($iprecords) - fwrite($fr, $iprecords); - fclose($fr); + fwrite($fw, $config['system']['dnsserver'][0]); + fclose($fw); } } diff --git a/config/tinydns/tinydns.xml b/config/tinydns/tinydns.xml index 55ee3269..bbb1cfa2 100644 --- a/config/tinydns/tinydns.xml +++ b/config/tinydns/tinydns.xml @@ -44,7 +44,7 @@ ]]> </copyright> <name>tinydns</name> - <version>1.0</version> + <version>1.0.6.24</version> <title>DNS Server: Settings</title> <aftersaveredirect>/pkg_edit.php?xml=tinydns.xml&id=0</aftersaveredirect> <include_file>/usr/local/pkg/tinydns.inc</include_file> @@ -59,13 +59,13 @@ <rcfile>svscan.sh</rcfile> <executable>svscan</executable> <description>Daemontools service directory watcher</description> - </service> + </service> <service> <name>DNS Server</name> <rcfile>tinydns.sh</rcfile> <executable>tinydns</executable> <description>TinyDNS DNS Server</description> - </service> + </service> <tabs> <tab> <text>Settings</text> @@ -99,10 +99,6 @@ <item>https://packages.pfsense.org/packages/config/tinydns/tinydns.inc</item> </additional_files_needed> <additional_files_needed> - <prefix>/usr/local/pkg/pf/</prefix> - <item>https://packages.pfsense.org/packages/config/tinydns/tinydns_xmlrpc_sync.php</item> - </additional_files_needed> - <additional_files_needed> <prefix>/usr/local/pkg/</prefix> <item>https://packages.pfsense.org/packages/config/tinydns/tinydns_domains.xml</item> </additional_files_needed> @@ -149,8 +145,7 @@ <field> <type>listtopic</type> <name>Binding IP Address</name> - <fieldname>temp</fieldname> - </field> + </field> <field> <fielddescr>IP Address</fielddescr> <fieldname>ipaddress</fieldname> @@ -160,8 +155,7 @@ <field> <type>listtopic</type> <name>Recursive DNS Resolver</name> - <fieldname>temp</fieldname> - </field> + </field> <field> <fielddescr>Enable recursive DNS responder</fielddescr> <fieldname>enableforwarding</fieldname> @@ -197,7 +191,6 @@ <field> <type>listtopic</type> <name>IP Monitoring</name> - <fieldname>temp</fieldname> </field> <field> <fielddescr>Enable IP monitoring</fielddescr> @@ -213,19 +206,7 @@ </field> <field> <type>listtopic</type> - <name>Sync TinyDNS settings via XMLRPC</name> - <fieldname>temp</fieldname> - </field> - <field> - <fielddescr>XMLRPC Sync</fielddescr> - <fieldname>syncxmlrpc</fieldname> - <description>Sync TinyDNS configuration to backup firewalls</description> - <type>checkbox</type> - </field> - <field> - <type>listtopic</type> <name>Zone transfers</name> - <fieldname>temp</fieldname> </field> <field> <fielddescr>Hosts allowed to perform DNS Zone Transfers - Note: this requires TCP port 53 firewall permit rule!</fielddescr> @@ -245,7 +226,7 @@ <description>Enter the DNS zone that this IP address is allowed to transfer (ex: domain.com)</description> <type>input</type> <size>20</size> - </rowhelperfield> + </rowhelperfield> </rowhelper> </field> </fields> @@ -254,7 +235,7 @@ tinydns_custom_php_install_command(); tinydns_create_zone_file(); tinydns_setup_ping_items(); - tinydns_sync_on_changes(); + tinydns_sync_on_changes(); </custom_delete_php_command> <custom_php_validation_command> tinydns_validate(); @@ -264,26 +245,24 @@ tinydns_custom_php_install_command(); tinydns_create_zone_file(); tinydns_setup_ping_items(); - tinydns_sync_on_changes(); + tinydns_sync_on_changes(); </custom_add_php_command> <custom_php_resync_config_command> tinydns_custom_php_changeip_command(); tinydns_custom_php_install_command(); tinydns_create_zone_file(); tinydns_setup_ping_items(); - tinydns_sync_on_changes(); + tinydns_sync_on_changes(); </custom_php_resync_config_command> <custom_php_install_command> tinydns_custom_php_install_command(); - tinydns_sync_on_changes(); + tinydns_upgrade_config(); </custom_php_install_command> <custom_php_deinstall_command> tinydns_custom_php_deinstall_command(); - tinydns_sync_on_changes(); </custom_php_deinstall_command> <custom_php_command_before_form> <![CDATA[ - unset($_POST['temp']); if (!is_process_running("svscan")) { $savemsg = "NOTE: svscan is not running. Please <a href='/status_services.php?mode=restartservice&service=svscan'>start svscan</a> to bring up the DNS Server"; } diff --git a/config/tinydns/tinydns_dhcp_filter.php b/config/tinydns/tinydns_dhcp_filter.php index 85f5f8e7..5b245d7f 100644 --- a/config/tinydns/tinydns_dhcp_filter.php +++ b/config/tinydns/tinydns_dhcp_filter.php @@ -1,10 +1,10 @@ <?php -/* $Id$ */ /* tinydns_dhcp_filter.php + part of pfSense (https://www.pfSense.org/) Copyright (C) 2006 Scott Ullrich - Parts Copyright (C) 2007 Goffredo Andreone <GAndreone@imapro.com> - part of pfSense + Copyright (C) 2007 Goffredo Andreone + Copyright (C) 2015 ESF, LLC All rights reserved. Redistribution and use in source and binary forms, with or without @@ -39,21 +39,17 @@ require("/usr/local/pkg/tinydns.inc"); require("guiconfig.inc"); +$closehead = false; $pgtitle = "TinyDNS: DHCP Domains"; include("head.inc"); -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); -if ($pf_version < 2.0) - $one_two = true; - ?> +<meta http-equiv="refresh" content="60;url=<?php print $_SERVER['SCRIPT_NAME']; ?>"> +</head> + <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> -<?php if($one_two): ?> -<p class="pgtitle"><?=$pgtitle?></font></p> -<?php endif; ?> - <?php if ($savemsg) print_info_box($savemsg); ?> <div id="mainlevel"> @@ -64,7 +60,7 @@ if ($pf_version < 2.0) $tab_array[] = array(gettext("Add/Edit Record"), false, "/tinydns_filter.php"); $tab_array[] = array(gettext("Failover Status"), false, "/tinydns_status.php"); $tab_array[] = array(gettext("Logs"), false, "/tinydns_view_logs.php"); - $tab_array[] = array(gettext("Zone Sync"), false, "/tinydns_xmlrpc_sync.php"); + $tab_array[] = array(gettext("Zone Sync"), false, "/pkg_edit.php?xml=tinydns_sync.xml"); $tab_array[] = array(gettext("New domain wizard"), false, "/wizard.php?xml=new_zone_wizard.xml"); display_top_tabs($tab_array); ?> @@ -124,6 +120,5 @@ while ($startofrecord < $datalen ){ </table> </div> <?php include("fend.inc"); ?> -<meta http-equiv="refresh" content="60;url=<?php print $_SERVER['SCRIPT_NAME']; ?>"> </body> </html> diff --git a/config/tinydns/tinydns_sync.xml b/config/tinydns/tinydns_sync.xml index 5fe8ac77..2f7da455 100644 --- a/config/tinydns/tinydns_sync.xml +++ b/config/tinydns/tinydns_sync.xml @@ -2,48 +2,48 @@ <!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> <?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> - <copyright> - <![CDATA[ + <copyright> + <![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* - tinydns_sync.xml - part of pfSense (http://www.pfSense.com) - Copyright (C) 2008 Scott Ullrich - All rights reserved. - */ -/* ========================================================================== */ + tinydns_sync.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2008 Scott Ullrich + Copyright (C) 2015 ESF, LLC + All rights reserved. +*/ +/* ====================================================================================== */ /* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + 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. + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. - 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. - */ -/* ========================================================================== */ - ]]> - </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> + 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. +*/ +/* ====================================================================================== */ + ]]> + </copyright> <name>tinydnssync</name> - <version>1.0</version> - <title>TinyDNS: Manual Sync</title> + <version>1.0.6.24</version> + <title>TinyDNS: XMLRPC Sync</title> <include_file>/usr/local/pkg/tinydns.inc</include_file> <tabs> <tab> @@ -76,71 +76,89 @@ <fields> <field> <type>listtopic</type> - <fieldname>temp</fieldname> - <name>Enable DNS zone sync</name> + <name>DNS zone synchronization</name> </field> <field> - <fielddescr>Enable DNS zone synchronization</fielddescr> + <fielddescr>Enable synchronization</fielddescr> <fieldname>synconchanges</fieldname> - <description>pfSense will automatically sync changes to the hosts defined below.</description> - <type>checkbox</type> - </field> - <field> - <type>listtopic</type> - <name>Sync host #1</name> - <fieldname>temp</fieldname> - </field> - <field> - <fielddescr>IP Address</fielddescr> - <fieldname>ipaddress</fieldname> - <description>IP address of the first TinyDNS sync host.</description> - <type>input</type> - </field> - <field> - <fielddescr>Password</fielddescr> - <fieldname>password</fieldname> - <description>Admin password of the first TinyDNS sync host.</description> - <type>password</type> + <description> + <![CDATA[ + Select a sync method for TinyDNS.<br/><br/> + <strong>Important:</strong> While using "Sync to host(s) defined below", only sync from host A to B, A to C but <strong>do not</strong> enable XMLRPC sync <b>to</b> A. + This will result in a loop! + ]]> + </description> + <type>select</type> + <required/> + <default_value>disabled</default_value> + <options> + <option><name>Sync to configured system backup server</name><value>auto</value></option> + <option><name>Sync to host(s) defined below</name><value>manual</value></option> + <option><name>Do not sync this package configuration</name><value>disabled</value></option> + </options> </field> <field> - <type>listtopic</type> - <name>Sync host #2</name> - <fieldname>temp</fieldname> - </field> - <field> - <fielddescr>IP Address 2</fielddescr> - <fieldname>ipaddress2</fieldname> - <description>IP address of the second TinyDNS sync host. (optional)</description> - <type>input</type> - </field> - <field> - <fielddescr>Password 2</fielddescr> - <fieldname>password2</fieldname> - <description>Admin password of the second TinyDNS sync host.</description> - <type>password</type> - </field> - <field> - <type>listtopic</type> - <name>Sync host #3</name> - <fieldname>temp</fieldname> - </field> - <field> - <fielddescr>IP Address 3</fielddescr> - <fieldname>ipaddress3</fieldname> - <description>IP address of the third TinyDNS sync host. (optional)</description> - <type>input</type> + <fielddescr>Sync Timeout</fielddescr> + <fieldname>synctimeout</fieldname> + <description>XMLRPC timeout in seconds.</description> + <type>select</type> + <required/> + <default_value>250</default_value> + <options> + <option><name>250 seconds (Default)</name><value>250</value></option> + <option><name>120 seconds</name><value>120</value></option> + <option><name>90 seconds</name><value>90</value></option> + <option><name>60 seconds</name><value>60</value></option> + <option><name>30 seconds</name><value>30</value></option> + </options> </field> <field> - <fielddescr>Password 3</fielddescr> - <fieldname>password3</fieldname> - <description>Admin password of the third TinyDNS sync host.</description> - <type>password</type> + <fielddescr>Replication Targets</fielddescr> + <fieldname>none</fieldname> + <type>rowhelper</type> + <rowhelper> + <rowhelperfield> + <fielddescr>Enable</fielddescr> + <fieldname>syncdestinenable</fieldname> + <description><![CDATA[Enable this host as a replication target]]></description> + <type>checkbox</type> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Protocol</fielddescr> + <fieldname>syncprotocol</fieldname> + <description><![CDATA[Choose the protocol used to sync with the destination host (HTTP or HTTPS).]]></description> + <type>select</type> + <default_value>HTTP</default_value> + <options> + <option><name>HTTP</name><value>http</value></option> + <option><name>HTTPS</name><value>https</value></option> + </options> + </rowhelperfield> + <rowhelperfield> + <fielddescr>IP Address/Hostname</fielddescr> + <fieldname>ipaddress</fieldname> + <description><![CDATA[IP address or hostname of the destination host.]]></description> + <type>input</type> + <size>40</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Port</fielddescr> + <fieldname>syncport</fieldname> + <description><![CDATA[Choose the sync port of the destination host.]]></description> + <type>input</type> + <size>3</size> + </rowhelperfield> + <rowhelperfield> + <fielddescr>Admin Password</fielddescr> + <fieldname>password</fieldname> + <description><![CDATA[Password of the user "admin" on the destination host.]]></description> + <type>password</type> + <size>20</size> + </rowhelperfield> + </rowhelper> </field> </fields> <custom_php_resync_config_command> tinydns_sync_on_changes(); </custom_php_resync_config_command> - <custom_php_command_before_form> - unset($_POST['temp']); - </custom_php_command_before_form> -</packagegui>
\ No newline at end of file +</packagegui> diff --git a/config/vhosts/vhosts.inc b/config/vhosts/vhosts.inc index b0e2db45..b3ae7a7e 100644 --- a/config/vhosts/vhosts.inc +++ b/config/vhosts/vhosts.inc @@ -273,7 +273,7 @@ EOF; // Set the default port if (strlen($port) == 0) { - $port = '8001'; + $port = '10081'; } if ($ipaddress . ':' . $port != $ipaddress_and_port_previous_value) { diff --git a/config/vhosts/vhosts.priv.inc b/config/vhosts/vhosts.priv.inc new file mode 100644 index 00000000..f29c0813 --- /dev/null +++ b/config/vhosts/vhosts.priv.inc @@ -0,0 +1,40 @@ +<?php +/* + vhosts.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-vhosts'] = array(); +$priv_list['page-services-vhosts']['name'] = "WebCfg - Services: vHosts package"; +$priv_list['page-services-vhosts']['descr'] = "Allow access to vHosts package GUI"; + +$priv_list['page-services-vhosts']['match'] = array(); +$priv_list['page-services-vhosts']['match'][] = "packages/vhosts/vhosts_php.php*"; +$priv_list['page-services-vhosts']['match'][] = "packages/vhosts/vhosts_php_edit.php*"; +$priv_list['page-services-vhosts']['match'][] = "packages/vhosts/system_advanced_create_certs.php*"; + +?> diff --git a/config/vhosts/vhosts.xml b/config/vhosts/vhosts.xml index 306ccc69..d1a6590c 100644 --- a/config/vhosts/vhosts.xml +++ b/config/vhosts/vhosts.xml @@ -43,7 +43,7 @@ </copyright> <description>vHosts</description> <name>vHosts Settings</name> - <version>0.8.0</version> + <version>0.8.3</version> <title>vHosts Settings</title> <include_file>/usr/local/pkg/vhosts.inc</include_file> <menu> @@ -65,6 +65,10 @@ <item>https://packages.pfsense.org/packages/config/vhosts/vhosts.inc</item> </additional_files_needed> <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/vhosts/vhosts.priv.inc</item> + </additional_files_needed> + <additional_files_needed> <prefix>/usr/local/www/packages/vhosts/</prefix> <item>https://packages.pfsense.org/packages/config/vhosts/vhosts_php.php</item> </additional_files_needed> diff --git a/config/vhosts/vhosts_php_edit.php b/config/vhosts/vhosts_php_edit.php index cb5a330f..a0969b9f 100644 --- a/config/vhosts/vhosts_php_edit.php +++ b/config/vhosts/vhosts_php_edit.php @@ -201,7 +201,7 @@ function openwindow(url) { <td width="78%" class="vtable"> <input name="host" type="text" class="formfld" id="host" size="40" value="<?=htmlspecialchars($pconfig['host']);?>" /> <br /> - Required. If the host is intended for internal you can use the DNS forwarder to set a host name that is valid inside the local network. default: vhost01.local + Required. If the host is intended for internal you can use the DNS forwarder to set a host name that is valid inside the local network. Default: vhost01.local </td> </tr> <tr> @@ -209,7 +209,7 @@ function openwindow(url) { <td width="78%" class="vtable"> <input name="ipaddress" type="text" class="formfld" id="ipaddress" size="40" value="<?=htmlspecialchars($pconfig['ipaddress']);?>" /> <br /> - Required. Make sure the IP and Port combination does not conflict with the local system. example: 192.168.0.1 + Required. Make sure the IP and Port combination does not conflict with the local system. Example: 192.168.0.1 </td> </tr> <tr> @@ -217,7 +217,7 @@ function openwindow(url) { <td width="78%" class="vtable"> <input name="port" type="text" class="formfld" id="port" size="40" value="<?=htmlspecialchars($pconfig['port']);?>" /> <br /> - Make sure the IP and Port combination does not conflict with the local system. default: 8001 + Make sure the IP and Port combination does not conflict with the local system. Default: 10081 </td> </tr> <tr> diff --git a/config/vnstat2/vnstat2.priv.inc b/config/vnstat2/vnstat2.priv.inc new file mode 100644 index 00000000..324ac435 --- /dev/null +++ b/config/vnstat2/vnstat2.priv.inc @@ -0,0 +1,44 @@ +<?php +/* + vnstat2.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-status-vnstat2'] = array(); +$priv_list['page-status-vnstat2']['name'] = "WebCfg - Status: vnstat2 package"; +$priv_list['page-status-vnstat2']['descr'] = "Allow access to vnstat2 package GUI"; + +$priv_list['page-status-vnstat2']['match'] = array(); +$priv_list['page-status-vnstat2']['match'][] = "pkg_edit.php?xml=vnstat2.xml*"; +$priv_list['page-status-vnstat2']['match'][] = "pkg_edit.php?xml=vnstati.xml*"; +$priv_list['page-status-vnstat2']['match'][] = "pkg_edit.php?xml=vnstatoutput.xml*"; +$priv_list['page-status-vnstat2']['match'][] = "diag_vnstat.php*"; +$priv_list['page-status-vnstat2']['match'][] = "diag_vnstat2.php*"; +$priv_list['page-status-vnstat2']['match'][] = "vnstat2_img.php*"; +$priv_list['page-status-vnstat2']['match'][] = "vnstati.php*"; + +?> diff --git a/config/vnstat2/vnstat2.xml b/config/vnstat2/vnstat2.xml index 7e65d465..8d586f10 100644 --- a/config/vnstat2/vnstat2.xml +++ b/config/vnstat2/vnstat2.xml @@ -42,24 +42,24 @@ ]]> </copyright> <name>vnstat2</name> - <version>1.12.5</version> + <version>1.12.8</version> <title>Vnstat2</title> - <aftersaveredirect>/pkg_edit.php?xml=vnstat2.xml&id=0</aftersaveredirect> + <aftersaveredirect>/pkg_edit.php?xml=vnstat2.xml</aftersaveredirect> <include_file>/usr/local/pkg/vnstat2/vnstat2.inc</include_file> <menu> <name>Vnstat2</name> <section>Status</section> - <url>/pkg_edit.php?xml=vnstat2.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstat2.xml</url> </menu> <tabs> <tab> <text>Config</text> - <url>/pkg_edit.php?xml=vnstat2.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstat2.xml</url> <active/> </tab> <tab> <text>Vnstati</text> - <url>/pkg_edit.php?xml=vnstati.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstati.xml</url> </tab> <tab> <text>Access vnstat php frontend</text> @@ -67,7 +67,7 @@ </tab> <tab> <text>vnstat info</text> - <url>/pkg_edit.php?xml=vnstatoutput.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstatoutput.xml</url> </tab> <tab> <text>vnstat summary</text> @@ -79,6 +79,10 @@ <item>https://packages.pfsense.org/packages/config/vnstat2/vnstat2.inc</item> </additional_files_needed> <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/vnstat2/vnstat2.priv.inc</item> + </additional_files_needed> + <additional_files_needed> <prefix>/usr/local/pkg/</prefix> <item>https://packages.pfsense.org/packages/config/vnstat2/vnstati.xml</item> </additional_files_needed> diff --git a/config/vnstat2/vnstati.xml b/config/vnstat2/vnstati.xml index b395e65f..373fa0eb 100644 --- a/config/vnstat2/vnstati.xml +++ b/config/vnstat2/vnstati.xml @@ -42,23 +42,23 @@ ]]> </copyright> <name>vnstat2</name> - <version>1.12.5</version> + <version>1.12.8</version> <title>Vnstat2</title> <aftersaveredirect>/vnstati.php</aftersaveredirect> <include_file>/usr/local/pkg/vnstat2/vnstat2.inc</include_file> <menu> <name>vnstat2</name> <section>Status</section> - <url>/pkg_edit.php?xml=vnstat2.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstat2.xml</url> </menu> <tabs> <tab> <text>Config</text> - <url>/pkg_edit.php?xml=vnstat2.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstat2.xml</url> </tab> <tab> <text>Vnstati</text> - <url>/pkg_edit.php?xml=vnstati.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstati.xml</url> <active/> </tab> <tab> @@ -67,7 +67,7 @@ </tab> <tab> <text>vnstat info</text> - <url>/pkg_edit.php?xml=vnstatoutput.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstatoutput.xml</url> </tab> <tab> <text>vnstat summary</text> diff --git a/config/vnstat2/vnstatoutput.xml b/config/vnstat2/vnstatoutput.xml index 297c171a..668c5ba2 100644 --- a/config/vnstat2/vnstatoutput.xml +++ b/config/vnstat2/vnstatoutput.xml @@ -49,16 +49,16 @@ <menu> <name>vnstat2</name> <section>Status</section> - <url>/pkg_edit.php?xml=vnstat2.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstat2.xml</url> </menu> <tabs> <tab> <text>Config</text> - <url>/pkg_edit.php?xml=vnstat2.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstat2.xml</url> </tab> <tab> <text>Vnstati</text> - <url>/pkg_edit.php?xml=vnstati.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstati.xml</url> </tab> <tab> <text>Access vnstat php frontend</text> @@ -66,7 +66,7 @@ </tab> <tab> <text>vnstat info</text> - <url>/pkg_edit.php?xml=vnstatoutput.xml&id=0</url> + <url>/pkg_edit.php?xml=vnstatoutput.xml</url> <active/> </tab> <tab> diff --git a/config/widentd/widentd.priv.inc b/config/widentd/widentd.priv.inc new file mode 100644 index 00000000..1d369627 --- /dev/null +++ b/config/widentd/widentd.priv.inc @@ -0,0 +1,38 @@ +<?php +/* + widentd.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-widentd'] = array(); +$priv_list['page-services-widentd']['name'] = "WebCfg - Services: widentd package"; +$priv_list['page-services-widentd']['descr'] = "Allow access to widentd package GUI"; + +$priv_list['page-services-widentd']['match'] = array(); +$priv_list['page-services-widentd']['match'][] = "pkg_edit.php?xml=widentd.xml*"; + +?> diff --git a/config/widentd/widentd.xml b/config/widentd/widentd.xml index fe28ba2d..9730160c 100644 --- a/config/widentd/widentd.xml +++ b/config/widentd/widentd.xml @@ -42,28 +42,32 @@ ]]> </copyright> <name>widentd</name> - <version>1.0.4</version> + <version>1.0.5</version> <title>Services: widentd</title> <menu> <name>widentd</name> <tooltiptext>Modify widentd settings.</tooltiptext> <section>Services</section> - <url>pkg_edit.php?xml=widentd.xml&id=0</url> + <url>pkg_edit.php?xml=widentd.xml</url> </menu> <service> <name>widentd</name> <rcfile>widentd.sh</rcfile> <executable>widentd</executable> </service> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/widentd/widentd.priv.inc</item> + <prefix>/etc/inc/priv/</prefix> + </additional_files_needed> <configpath>installedpackages->package->$packagename->configuration->settings</configpath> <fields> <field> - <fielddescr>Enable widentd daemon</fielddescr> + <fielddescr>Enable widentd Daemon</fielddescr> <fieldname>enable</fieldname> <type>checkbox</type> </field> <field> - <fielddescr>Listening interface</fielddescr> + <fielddescr>Listening Interface</fielddescr> <fieldname>interface</fieldname> <description> <![CDATA[ @@ -87,7 +91,7 @@ <type>input</type> </field> <field> - <fielddescr>System name</fielddescr> + <fielddescr>System Name</fielddescr> <fieldname>sysname</fieldname> <description> <![CDATA[ @@ -98,72 +102,65 @@ <type>input</type> </field> </fields> - <custom_php_global_functions> + <custom_php_resync_config_command> <![CDATA[ - function sync_package_widentd() { conf_mount_rw(); global $config; - /* Write widentd.sh */ - $int = convert_friendly_interface_to_real_interface_name($config['installedpackages']['widentd']['config'][0]['interface']); - $ip = find_interface_ip($int); - $user = $config['installedpackages']['widentd']['config'][0]['username'] ?: 'user'; - $system = $config['installedpackages']['widentd']['config'][0]['sysname'] ?: 'UNIX'; - $start = "/usr/local/sbin/widentd -u {$user} -o {$system} -i {$ip}"; - $stop = "/usr/bin/killall widentd"; - write_rcfile(array( - "file" => "widentd.sh", - "start" => $start, - "stop" => $stop - ) - ); - /* If the service is (being) disabled, stop it (if running) and do nothing else */ - if (!($config['installedpackages']['widentd']['config'][0][enable])) { - if (is_process_running("widentd")) { + if ($config['installedpackages']['widentd']['config'][0][enable] != "on") { + if (is_service_running("widentd")) { stop_service("widentd"); } - return; + unlink_if_exists("/usr/local/etc/rc.d/widentd.sh"); } else { - restart_service("widentd"); + $int = convert_friendly_interface_to_real_interface_name($config['installedpackages']['widentd']['config'][0]['interface']); + $ip = find_interface_ip($int); + $user = $config['installedpackages']['widentd']['config'][0]['username'] ?: 'user'; + $system = $config['installedpackages']['widentd']['config'][0]['sysname'] ?: 'UNIX'; + $start = "/usr/local/sbin/widentd -u {$user} -o {$system} -i {$ip}"; + $stop = "/usr/bin/killall widentd"; + write_rcfile(array( + "file" => "widentd.sh", + "start" => $start, + "stop" => $stop + ) + ); + /* (Re)start service */ + if (is_service_running("widentd")) { + restart_service("widentd"); + } else { + start_service("widentd"); + } } conf_mount_ro(); - } - - - function validate_input_widentd($post, &$input_errors) { + ]]> + </custom_php_resync_config_command> + <custom_php_validation_command> + <![CDATA[ /* Only allow ^[a-zA-Z\.]+$ otherwise the daemon will not start; see widentd manpage */ - if (($post['username'] != "") && !preg_match("/^[a-zA-Z\.]+$/", $post['username'])) { - $input_errors[] = 'Username may only contain uppercase and lowercase letters [a-zA-Z] and "." character.'; + if ($_POST['username'] != "") { + if (!preg_match("/^[a-zA-Z\.]+$/", $_POST['username'])) { + $input_errors[] = 'Username may only contain uppercase and lowercase letters [a-zA-Z] and "." character.'; + } } /* Technically, ^[A-Z][A-Z0-9\-.\/]+[A-Z0-9]$ should be valid characters here https://www.iana.org/assignments/operating-system-names/operating-system-names.xhtml However this is not supported by widentd; the service will not start. */ - if (($post['sysname'] != "") && !preg_match("/^[a-zA-Z]+$/", $post['sysname'])) { - $input_errors[] .= 'System name may only contain uppercase and lowercase letters [a-zA-Z].'; + if ($_POST['sysname'] != "") { + if (!preg_match("/^[a-zA-Z]+$/", $_POST['sysname'])) { + $input_errors[] = 'System name may only contain uppercase and lowercase letters [a-zA-Z].'; + } } /* Check for IPv6-only interfaces */ - $int = convert_friendly_interface_to_real_interface_name($post['interface']); + $int = convert_friendly_interface_to_real_interface_name($_POST['interface']); $ip = find_interface_ip($int); if (!is_ipaddrv4($ip)) { - $input_errors[] .= 'The selected interface has no IPv4 configured. Widentd does not support IPv6.'; + $input_errors[] = 'The selected interface has no IPv4 configured. Widentd does not support IPv6.'; } - } ]]> - </custom_php_global_functions> - <custom_add_php_command> - sync_package_widentd(); - </custom_add_php_command> - <custom_php_resync_config_command> - sync_package_widentd(); - </custom_php_resync_config_command> - <custom_php_install_command> - unlink_if_exists("/usr/local/etc/rc.d/widentd.sh"); - </custom_php_install_command> - <custom_php_validation_command> - validate_input_widentd($_POST, $input_errors); </custom_php_validation_command> </packagegui> diff --git a/config/zabbix-agent-lts/zabbix-agent-lts.priv.inc b/config/zabbix-agent-lts/zabbix-agent-lts.priv.inc new file mode 100644 index 00000000..433f3bb9 --- /dev/null +++ b/config/zabbix-agent-lts/zabbix-agent-lts.priv.inc @@ -0,0 +1,38 @@ +<?php +/* + zabbix-agent-lts.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-zabbix-agent-lts'] = array(); +$priv_list['page-services-zabbix-agent-lts']['name'] = "WebCfg - Services: Zabbix Agent LTS package"; +$priv_list['page-services-zabbix-agent-lts']['descr'] = "Allow access to Zabbix Agent LTS package GUI"; + +$priv_list['page-services-zabbix-agent-lts']['match'] = array(); +$priv_list['page-services-zabbix-agent-lts']['match'][] = "pkg_edit.php?xml=zabbix-agent-lts.xml*"; + +?> diff --git a/config/zabbix-agent-lts/zabbix-agent-lts.xml b/config/zabbix-agent-lts/zabbix-agent-lts.xml index 8883ff22..3ced7d07 100644 --- a/config/zabbix-agent-lts/zabbix-agent-lts.xml +++ b/config/zabbix-agent-lts/zabbix-agent-lts.xml @@ -45,7 +45,7 @@ <name>zabbixagentlts</name> <title>Services: Zabbix Agent LTS</title> <category>Monitoring</category> - <version>0.8.6</version> + <version>0.8.8</version> <include_file>/usr/local/pkg/zabbix-agent-lts.inc</include_file> <addedit_string>Zabbix Agent LTS has been created/modified.</addedit_string> <delete_string>Zabbix Agent LTS has been deleted.</delete_string> @@ -53,6 +53,10 @@ <item>https://packages.pfsense.org/packages/config/zabbix-agent-lts/zabbix-agent-lts.inc</item> <prefix>/usr/local/pkg/</prefix> </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/zabbix-agent-lts/zabbix-agent-lts.priv.inc</item> + <prefix>/etc/inc/priv/</prefix> + </additional_files_needed> <menu> <name>Zabbix Agent LTS</name> <tooltiptext>Setup Zabbix Agent specific settings</tooltiptext> diff --git a/config/zabbix-agent/zabbix-agent.xml b/config/zabbix-agent/zabbix-agent.xml deleted file mode 100644 index 885a54e3..00000000 --- a/config/zabbix-agent/zabbix-agent.xml +++ /dev/null @@ -1,263 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<packagegui> - <name>zabbixagent</name> - <title>Services: Zabbix Agent</title> - <category>Monitoring</category> - <version>1.1</version> - <addedit_string>Zabbix Agent has been created/modified.</addedit_string> - <delete_string>Zabbix Agent has been deleted.</delete_string> - <restart_command>/usr/local/etc/rc.d/zabbix_agentd.sh restart</restart_command> - <menu> - <name>Zabbix Agent</name> - <tooltiptext>Setup Zabbix Agent specific settings</tooltiptext> - <section>Services</section> - <url>/pkg_edit.php?xml=zabbix-agent.xml&id=0</url> - </menu> - <service> - <name>zabbix_agentd</name> - <rcfile>zabbix_agentd.sh</rcfile> - <executable>zabbix_agentd</executable> - <description>Zabbix Agent host monitor daemon</description> - </service> - <tabs> - <tab> - <text>Settings</text> - <url>/pkg_edit.php?xml=zabbix-agent.xml&id=0</url> - <active /> - </tab> - </tabs> - <fields> - <field> - <fielddescr>Server</fielddescr> - <fieldname>server</fieldname> - <description>List of comma delimited IP addresses (or hostnames) of ZABBIX servers</description> - <value>127.0.0.1</value> - <type>input</type> - <size>60</size> - <required>true</required> - </field> - <field> - <fielddescr>Server Port</fielddescr> - <fieldname>serverport</fieldname> - <description>Server port for sending active check (generally 10051)</description> - <value>10051</value> - <type>input</type> - <size>60</size> - <required>true</required> - </field> - <field> - <fielddescr>Hostname</fielddescr> - <fieldname>hostname</fieldname> - <description>Unique hostname. Required for active checks and must match hostname as configured on the Zabbix server (case sensitive).</description> - <value>localhost</value> - <type>input</type> - <size>60</size> - <required>true</required> - </field> - <field> - <fielddescr>Listen IP</fielddescr> - <fieldname>listenip</fieldname> - <value>0.0.0.0</value> - <type>input</type> - <size>60</size> - <required>true</required> - <description>Listen IP for connections from the server (generally 0.0.0.0 for all interfaces)</description> - </field> - <field> - <fielddescr>Listen Port</fielddescr> - <fieldname>listenport</fieldname> - <value>10050</value> - <type>input</type> - <size>60</size> - <required>true</required> - <description>Listen port for connections from the server (generally 10050)</description> - </field> - <field> - <fielddescr>Refresh Active Checks</fielddescr> - <fieldname>refreshactchecks</fieldname> - <value>120</value> - <type>input</type> - <size>60</size> - <required>false</required> - <description>The agent will refresh list of active checks once per 120 (default) seconds.</description> - </field> - <field> - <fielddescr>Timeout</fielddescr> - <fieldname>timeout</fieldname> - <value>3</value> - <type>input</type> - <size>60</size> - <required>true</required> - <description>Timeout (default 3). Do not spend more that Timeout seconds on getting requested value (1-255). The agent does not kill timeouted User Parameters processes!</description> - </field> - <field> - <fielddescr>Disable active checks</fielddescr> - <fieldname>disableactive</fieldname> - <type>checkbox</type> - <description>The agent will work only in passive mode listening for server. (generally net set)</description> - </field> - <field> - <fielddescr>Disable passive checks</fielddescr> - <fieldname>disablepassive</fieldname> - <type>checkbox</type> - <description>The agent will not listen on any TCP port. Only active checks will be processed. (generally not set)</description> - </field> - <field> - <fielddescr>User Parameters</fielddescr> - <fieldname>userparams</fieldname> - <encoding>base64</encoding> - <value></value> - <type>textarea</type> - <rows>5</rows> - <cols>50</cols> - <required>false</required> - <description>User-defined parameter to monitor. There can be several user-defined parameters. Value has form, example: UserParameter=users,who|wc -l <br><a href="https://www.zabbix.com/documentation/1.8/manual/tutorials/extending_agent" target="_new">See zabbix documentation for more information<a></description> - </field> - </fields> - <custom_php_install_command> - <![CDATA[ - global $config, $g; - - $pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); - switch ($pfs_version) { - case "1.2": - case "2.0": - define('ZABBIX_AGENT_BASE','/usr/local'); - break; - default: - define('ZABBIX_AGENT_BASE', '/usr/pbi/zabbix-agent-' . php_uname("m")); - } - - mwexec("mkdir -p /var/log/zabbix/"); - mwexec("mkdir -p /var/run/zabbix/"); - - conf_mount_rw(); - - /* create a few directories and ensure the sample files are in place */ - exec("/bin/mkdir -p " . ZABBIX_AGENT_BASE . "/etc/zabbix"); - exec("/bin/mkdir -p /var/log/zabbix"); - exec("/bin/mkdir -p /var/run/zabbix"); - - exec("/bin/rm -f " . ZABBIX_AGENT_BASE . "/etc/rc.d/zabbix_agentd"); - - $start = "/bin/mkdir -p /var/log/zabbix\n"; - $start .= "/usr/sbin/chown -R zabbix:zabbix /var/log/zabbix\n"; - - $start .= "/bin/mkdir -p /var/run/zabbix\n"; - $start .= "/usr/sbin/chown -R zabbix:zabbix /var/run/zabbix\n"; - - $start .= "echo \"Starting Zabbix Agent\"...\n"; - - /* start zabbix agent */ - $start .= ZABBIX_AGENT_BASE . "/sbin/zabbix_agentd\n"; - - $stop = "echo \"Stopping Zabbix Agent\"\n"; - $stop .= "/usr/bin/killall zabbix_agentd\n"; - /* write out rc.d start/stop file */ - write_rcfile(array( - "file" => "zabbix_agentd.sh", - "start" => "{$start}", - "restart" => "$stop\n" . "sleep 5\n" . "{$start}", - "stop" => "$stop" - ) - ); - - conf_mount_ro(); - ]]> - </custom_php_install_command> - <custom_php_command_before_form></custom_php_command_before_form> - <custom_php_after_head_command></custom_php_after_head_command> - <custom_php_after_form_command></custom_php_after_form_command> - <custom_php_validation_command> - <![CDATA[ - global $_POST; - $pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); - switch ($pfs_version) { - case "1.2": - case "2.0": - define('ZABBIX_AGENT_BASE','/usr/local'); - break; - default: - define('ZABBIX_AGENT_BASE', '/usr/pbi/zabbix-agent-' . php_uname("m")); - } - - $ListenIP=$_POST['listenip']; - if (!preg_match("/^(?:\d{1,3}\.){3}\d{1,3}$/", $ListenIP)) { - $input_errors[]='Listen IP is not an IP address.'; - } - - $ListenPort=$_POST['listenport']; - if (!preg_match("/^\d+$/", $ListenPort)) { - $input_errors[]='Listen Port is not numeric.'; - } - - $ServerPort=$_POST['serverport']; - if (!preg_match("/^\d+$/", $ServerPort)) { - $input_errors[]='Server Port is not numeric.'; - } - - $RefreshActiveChecks=$_POST['refreshactchecks']; - if (!preg_match("/^\d+$/", $RefreshActiveChecks)) { - $input_errors[]='Refresh Active Checks is not numeric.'; - } - - $Timeout=$_POST['timeout']; - if (!preg_match("/^\d+$/", $Timeout)) { - $input_errors[]='Timeout is not numeric.'; - } - ]]> - </custom_php_validation_command> - <custom_add_php_command></custom_add_php_command> - <custom_php_resync_config_command> - <![CDATA[ - conf_mount_rw(); - global $config; - global $g; - - $Server=$config['installedpackages']['zabbixagent']['config'][0]['server']; - $ServerPort=$config['installedpackages']['zabbixagent']['config'][0]['serverport']; - $Hostname=$config['installedpackages']['zabbixagent']['config'][0]['hostname']; - $ListenIP=$config['installedpackages']['zabbixagent']['config'][0]['listenip']; - $ListenPort=$config['installedpackages']['zabbixagent']['config'][0]['listenport']; - $RefreshActChecks=$config['installedpackages']['zabbixagent']['config'][0]['refreshactchecks']; - $Timeout=$config['installedpackages']['zabbixagent']['config'][0]['timeout']; - $DisableActive=$config['installedpackages']['zabbixagent']['config'][0]['disableactive']; - $DisablePassive=$config['installedpackages']['zabbixagent']['config'][0]['disablepassive']; - $UserParams=base64_decode($config['installedpackages']['zabbixagent']['config'][0]['userparams']); - - $conf = "Server=$Server\n"; - $conf .= "ServerPort=$ServerPort\n"; - $conf .= "Hostname=$Hostname\n"; - $conf .= "ListenIP=$ListenIP\n"; - $conf .= "ListenPort=$ListenPort\n"; - $conf .= "StartAgents=5\n"; - $conf .= "RefreshActiveChecks=$RefreshActChecks\n"; - $conf .= "DebugLevel=3\n"; - $conf .= "PidFile=/var/run/zabbix/zabbix_agentd.pid\n"; - $conf .= "LogFile=/var/log/zabbix/zabbix_agentd.log\n"; - $conf .= "LogFileSize=1\n"; - $conf .= "Timeout=$Timeout\n"; - if (isset($DisableActive) && ($DisableActive == "on")) { - $conf .= "DisableActive=1\n"; - } - if (isset($DisablePassive) && ($DisablePassive == "on")) { - $conf .= "DisablePassive=1\n"; - } - $conf .= "$UserParams\n"; - - file_put_contents(ZABBIX_AGENT_BASE . "/etc/zabbix/zabbix_agentd.conf", $conf); - conf_mount_ro(); - - ]]> - </custom_php_resync_config_command> - <custom_php_deinstall_command> - <![CDATA[ - exec("/usr/bin/killall zabbix_agentd"); - - exec("/bin/rm " . ZABBIX_AGENT_BASE . "/etc/rc.d/zabbix_agentd.sh"); - - exec("/bin/rm -r /var/log/zabbix/"); - exec("/bin/rm -r /var/run/zabbix/"); - ]]> - </custom_php_deinstall_command> -</packagegui> diff --git a/config/zabbix-proxy-lts/zabbix-proxy-lts.priv.inc b/config/zabbix-proxy-lts/zabbix-proxy-lts.priv.inc new file mode 100644 index 00000000..c6d30f65 --- /dev/null +++ b/config/zabbix-proxy-lts/zabbix-proxy-lts.priv.inc @@ -0,0 +1,38 @@ +<?php +/* + zabbix-proxy-lts.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-zabbix-proxy-lts'] = array(); +$priv_list['page-services-zabbix-proxy-lts']['name'] = "WebCfg - Services: Zabbix Proxy LTS package"; +$priv_list['page-services-zabbix-proxy-lts']['descr'] = "Allow access to Zabbix Proxy LTS package GUI"; + +$priv_list['page-services-zabbix-proxy-lts']['match'] = array(); +$priv_list['page-services-zabbix-proxy-lts']['match'][] = "pkg_edit.php?xml=zabbix-proxy-lts.xml*"; + +?> diff --git a/config/zabbix-proxy-lts/zabbix-proxy-lts.xml b/config/zabbix-proxy-lts/zabbix-proxy-lts.xml index 27092e59..f2e74265 100644 --- a/config/zabbix-proxy-lts/zabbix-proxy-lts.xml +++ b/config/zabbix-proxy-lts/zabbix-proxy-lts.xml @@ -45,7 +45,7 @@ <name>zabbixproxylts</name> <title>Services: Zabbix Proxy LTS</title> <category>Monitoring</category> - <version>0.8.6</version> + <version>0.8.8</version> <include_file>/usr/local/pkg/zabbix-proxy-lts.inc</include_file> <addedit_string>Zabbix Proxy has been created/modified.</addedit_string> <delete_string>Zabbix Proxy has been deleted.</delete_string> @@ -53,6 +53,10 @@ <item>https://packages.pfsense.org/packages/config/zabbix-proxy-lts/zabbix-proxy-lts.inc</item> <prefix>/usr/local/pkg/</prefix> </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/zabbix-proxy-lts/zabbix-proxy-lts.priv.inc</item> + <prefix>/etc/inc/priv/</prefix> + </additional_files_needed> <menu> <name>Zabbix Proxy LTS</name> <tooltiptext>Setup Zabbix Proxy LTS specific settings</tooltiptext> diff --git a/config/zabbix-proxy/zabbix-proxy.xml b/config/zabbix-proxy/zabbix-proxy.xml deleted file mode 100644 index 19930b49..00000000 --- a/config/zabbix-proxy/zabbix-proxy.xml +++ /dev/null @@ -1,250 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<packagegui> - <name>zabbixproxy</name> - <title>Services: Zabbix Proxy</title> - <category>Monitoring</category> - <version>1.1</version> - <addedit_string>Zabbix Proxy has been created/modified.</addedit_string> - <delete_string>Zabbix Proxy has been deleted.</delete_string> - <restart_command>/usr/local/etc/rc.d/zabbix_proxy.sh restart</restart_command> - <menu> - <name>Zabbix Proxy</name> - <tooltiptext>Setup Zabbix Proxy specific settings</tooltiptext> - <section>Services</section> - <url>/pkg_edit.php?xml=zabbix-proxy.xml&id=0</url> - </menu> - <service> - <name>zabbix-proxy</name> - <rcfile>zabbix-proxy.sh</rcfile> - <executable>zabbix_proxy</executable> - <description>Zabbix proxy collection daemon</description> - </service> - <tabs> - <tab> - <text>Settings</text> - <url>/pkg_edit.php?xml=zabbix-proxy.xml&id=0</url> - <active /> - </tab> - </tabs> - <fields> - <field> - <fielddescr>Server</fielddescr> - <fieldname>server</fieldname> - <description>List of comma delimited IP addresses (or hostnames) of ZABBIX servers</description> - <default_value>127.0.0.1</default_value> - <type>input</type> - <size>100</size> - <required>true</required> - </field> - <field> - <fielddescr>Server Port</fielddescr> - <fieldname>serverport</fieldname> - <description>Server port (generally 10051)</description> - <default_value>10051</default_value> - <type>input</type> - <size>6</size> - <required>true</required> - </field> - <field> - <fielddescr>Hostname</fielddescr> - <fieldname>hostname</fieldname> - <description>Unique, case-sensitive proxy name. Make sure the proxy name is known to the server</description> - <default_value>localhost</default_value> - <type>input</type> - <size>100</size> - <required>true</required> - </field> - <field> - <fielddescr>Active Mode</fielddescr> - <fieldname>activemode</fieldname> - <description>Check to run Zabbix proxy in active mode (default)</description> - <default_value>on</default_value> - <type>checkbox</type> - <required>true</required> - </field> - <field> - <fielddescr>Config Frequency</fielddescr> - <fieldname>configfrequency</fieldname> - <description>How often the proxy retrieves configuration data from the Zabbix server in seconds. Ignored if the proxy runs in passive mode.</description> - <default_value>3600</default_value> - <type>input</type> - <size>10</size> - <required>true</required> - </field> - </fields> - <custom_php_install_command> - <![CDATA[ - global $config, $g; - - $pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); - switch ($pfs_version) { - case "1.2": - case "2.0": - define('ZABBIX_PROXY_BASE', '/usr/local'); - break; - default: - define('ZABBIX_PROXY_BASE', '/usr/pbi/zabbix-proxy-' . php_uname("m")); - } - - mwexec("mkdir -p /var/log/zabbix/"); - mwexec("mkdir -p /var/run/zabbix/"); - mwexec("mkdir -p /var/db/zabbix/"); - - conf_mount_rw(); - - /* create a few directories and ensure the sample files are in place */ - exec("/bin/mkdir -p " . ZABBIX_PROXY_BASE . "/etc/zabbix"); - exec("/bin/mkdir -p /var/log/zabbix"); - exec("/bin/mkdir -p /var/run/zabbix"); - exec("/bin/mkdir -p /var/db/zabbix"); - - exec("/bin/rm -f " . ZABBIX_PROXY_BASE . "/etc/rc.d/zabbix_proxy"); - - $start = "/bin/mkdir -p /var/log/zabbix\n"; - $start .= "/usr/sbin/chown -R zabbix:zabbix /var/log/zabbix\n"; - - $start .= "/bin/mkdir -p /var/run/zabbix\n"; - $start .= "/usr/sbin/chown -R zabbix:zabbix /var/run/zabbix\n"; - - $start .= "/bin/mkdir -p /var/db/zabbix\n"; - $start .= "/usr/sbin/chown -R zabbix:zabbix /var/db/zabbix\n"; - - $start .= "echo \"Starting Zabbix Proxy\"...\n"; - - /* start zabbix proxy */ - $start .= ZABBIX_PROXY_BASE . "/sbin/zabbix_proxy\n"; - - $stop = "echo \"Stopping Zabbix Proxy\"\n"; - $stop .= "kill `cat /var/run/zabbix/zabbix_proxy.pid`\n"; - /* write out rc.d start/stop file */ - write_rcfile(array( - "file" => "zabbix_proxy.sh", - "start" => "{$start}", - "restart" => "$stop\n" . "sleep 5\n" . "{$start}", - "stop" => "$stop" - ) - ); - - conf_mount_ro(); - ]]> - </custom_php_install_command> - <custom_php_command_before_form></custom_php_command_before_form> - <custom_php_after_head_command></custom_php_after_head_command> - <custom_php_after_form_command></custom_php_after_form_command> - <custom_php_validation_command> - <![CDATA[ - global $_POST; - - $ServerPort=$_POST['serverport']; - if (!preg_match("/^\d+$/", $ServerPort)) { - $input_errors[]='Server Port is not numeric.'; - } - - $ConfigFrequency=$_POST['configfrequency']; - if (!preg_match("/^\d+$/", $ConfigFrequency)) { - $input_errors[]='Config Frequency is not numeric.'; - } - ]]> - </custom_php_validation_command> - <custom_add_php_command></custom_add_php_command> - <custom_php_resync_config_command> - <![CDATA[ - conf_mount_rw(); - global $config, $g; - - $pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); - switch ($pfs_version) { - case "1.2": - case "2.0": - define('ZABBIX_PROXY_BASE', '/usr/local'); - break; - default: - define('ZABBIX_PROXY_BASE', '/usr/pbi/zabbix-proxy-' . php_uname("m")); - } - - $zabbixproxy_config = $config['installedpackages']['zabbixproxy']['config'][0]; - - $Server=$zabbixproxy_config['server']; - $ServerPort=$zabbixproxy_config['serverport']; - $Hostname=$zabbixproxy_config['hostname']; - $ListenPort=$zabbixproxy_config['listenport']; - $ConfigFrequency=$zabbixproxy_config['configfrequency']; - if(isset($zabbixproxy_config['activemode'])) { - $Mode="0"; /* active */ - } else { - $Mode="1"; /* passive */ - } - - $conf = "Server=$Server\n"; - $conf .= "ServerPort=$ServerPort\n"; - $conf .= "Hostname=$Hostname\n"; - $conf .= "PidFile=/var/run/zabbix/zabbix_proxy.pid\n"; - $conf .= "DBName=/var/db/zabbix/proxy.db\n"; - $conf .= "LogFile=/var/log/zabbix/zabbix_proxy.log\n"; - $conf .= "ConfigFrequency=$ConfigFrequency\n"; - $conf .= "FpingLocation=/usr/local/sbin/fping\n"; - /* there's currently no fping6 (IPv6) dependency in the package, but if there was, the binary would likely also be in /usr/local/sbin */ - $conf .= "Fping6Location=/usr/local/sbin/fping6\n"; - $conf .= "ProxyMode=$Mode\n"; - - file_put_contents(ZABBIX_PROXY_BASE . "/etc/zabbix/zabbix_proxy.conf", $conf); - - $want_sysctls = array( - 'kern.ipc.shmall' => '2097152', - 'kern.ipc.shmmax' => '2147483648', - 'kern.ipc.semmsl' => '250' - ); - $sysctls = array(); - if (file_exists("/etc/sysctl.conf")) { - $sc = file_get_contents("/etc/sysctl.conf"); - $sc = explode("\n", $sc); - foreach ($sc as $num => $line) { - list($sysctl, $val) = explode("=", $line, 2); - if (array_key_exists($sysctl, $want_sysctls) || empty($sysctl)) - unset($sc[$num]); - } - } - foreach ($want_sysctls as $ws => $wv) { - $sc[] = "{$ws}={$wv}"; - exec("/sbin/sysctl {$ws}={$wv}"); - } - file_put_contents("/etc/sysctl.conf", implode("\n", $sc) . "\n"); - - $want_tunables = array( - 'kern.ipc.semopm' => '100', - 'kern.ipc.semmni' => '128', - 'kern.ipc.semmns' => '32000', - 'kern.ipc.shmmni' => '4096' - ); - $tunables = array(); - if (file_exists("/boot/loader.conf")) { - $lt = file_get_contents("/boot/loader.conf"); - $lt = explode("\n", $lt); - foreach ($lt as $num => $line) { - list($tunable, $val) = explode("=", $line, 2); - if (array_key_exists($tunable, $want_tunables) || empty($tunable)) - unset($lt[$num]); - } - } - foreach ($want_tunables as $wt => $wv) { - $lt[] = "{$wt}={$wv}"; - } - file_put_contents("/boot/loader.conf", implode("\n", $lt) . "\n"); - chmod("/var/log/zabbix", 0755); - chmod("/var/run/zabbix", 0755); - conf_mount_ro(); - - ]]> - </custom_php_resync_config_command> - <custom_php_deinstall_command> - <![CDATA[ - exec("kill `cat /var/run/zabbix/zabbix_proxy.pid`"); - - exec("/bin/rm " . ZABBIX_PROXY_BASE . "/etc/rc.d/zabbix_proxy.sh"); - - exec("/bin/rm -r /var/log/zabbix/"); - exec("/bin/rm -r /var/run/zabbix/"); - exec("/bin/rm -r /var/db/zabbix/"); - ]]> - </custom_php_deinstall_command> -</packagegui>
\ No newline at end of file diff --git a/config/zabbix2/zabbix2-agent.priv.inc b/config/zabbix2/zabbix2-agent.priv.inc new file mode 100644 index 00000000..bdd3543d --- /dev/null +++ b/config/zabbix2/zabbix2-agent.priv.inc @@ -0,0 +1,38 @@ +<?php +/* + zabbix2-agent.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-zabbix2-agent'] = array(); +$priv_list['page-services-zabbix2-agent']['name'] = "WebCfg - Services: Zabbix-2 Agent package"; +$priv_list['page-services-zabbix2-agent']['descr'] = "Allow access to Zabbix-2 Agent package GUI"; + +$priv_list['page-services-zabbix2-agent']['match'] = array(); +$priv_list['page-services-zabbix2-agent']['match'][] = "pkg_edit.php?xml=zabbix2-agent.xml*"; + +?> diff --git a/config/zabbix2/zabbix2-agent.xml b/config/zabbix2/zabbix2-agent.xml index 3d2400ad..e02caefc 100644 --- a/config/zabbix2/zabbix2-agent.xml +++ b/config/zabbix2/zabbix2-agent.xml @@ -1,47 +1,51 @@ <?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> -<copyright> + <copyright> <![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* - zabbix2-agent.xml - part of the Zabbix package for pfSense - Copyright (C) 2013 Danilo G. Baio + zabbix2-agent.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2013 Danilo G. Baio Copyright (C) 2013 Marcello Coutinho - - All rights reserved. - */ -/* ========================================================================== */ + Copyright (C) 2015 ESF, LLC + All rights reserved. +*/ +/* ====================================================================================== */ /* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + 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. + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. - 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. - */ -/* ========================================================================== */ + 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. +*/ +/* ====================================================================================== */ ]]> </copyright> <name>zabbixagent</name> <title>Services: Zabbix-2 Agent</title> <category>Monitoring</category> - <version>0.8.3</version> + <version>0.8.4</version> <include_file>/usr/local/pkg/zabbix2.inc</include_file> <addedit_string>Zabbix Agent has been created/modified.</addedit_string> <delete_string>Zabbix Agent has been deleted.</delete_string> @@ -49,7 +53,10 @@ <additional_files_needed> <item>https://packages.pfsense.org/packages/config/zabbix2/zabbix2.inc</item> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/zabbix2/zabbix2-agent.priv.inc</item> + <prefix>/etc/inc/priv/</prefix> </additional_files_needed> <menu> <name>Zabbix-2 Agent</name> @@ -61,7 +68,7 @@ <name>zabbix_agentd</name> <rcfile>zabbix2_agentd.sh</rcfile> <executable>zabbix_agentd</executable> - <description>Zabbix Agent host monitor daemon</description> + <description>Zabbix Agent Host Monitor Daemon</description> </service> <tabs> <tab> @@ -70,6 +77,7 @@ <active /> </tab> </tabs> + <advanced_options>enabled</advanced_options> <fields> <field> <name>Zabbix2 Agent Settings</name> @@ -78,27 +86,27 @@ <field> <fielddescr>Enable</fielddescr> <fieldname>agentenabled</fieldname> - <description>Enable Zabbix2 Agent service</description> + <description>Enable Zabbix2 Agent service.</description> <type>checkbox</type> </field> <field> <fielddescr>Server</fielddescr> <fieldname>server</fieldname> - <description>List of comma delimited IP addresses (or hostnames) of ZABBIX servers</description> + <description>List of comma delimited IP addresses (or hostnames) of Zabbix servers.</description> <type>input</type> <size>60</size> </field> <field> <fielddescr>Server Active</fielddescr> <fieldname>serveractive</fieldname> - <description>List of comma delimited IP:port (or hostname:port) pairs of Zabbix servers for active checks</description> + <description>List of comma delimited IP:port (or hostname:port) pairs of Zabbix servers for active checks.</description> <type>input</type> <size>60</size> </field> <field> <fielddescr>Hostname</fielddescr> <fieldname>hostname</fieldname> - <description>Unique hostname. Required for active checks and must match hostname as configured on the Zabbix server (case sensitive).</description> + <description>Unique, case sensitive hostname. Required for active checks and must match hostname as configured on the Zabbix server.</description> <type>input</type> <size>60</size> </field> @@ -108,7 +116,7 @@ <default_value>0.0.0.0</default_value> <type>input</type> <size>60</size> - <description>Listen IP for connections from the server (default 0.0.0.0 for all interfaces)</description> + <description>Listen IP for connections from the server. (Default: 0.0.0.0 - all interfaces)</description> </field> <field> <fielddescr>Listen Port</fielddescr> @@ -116,7 +124,7 @@ <default_value>10050</default_value> <type>input</type> <size>5</size> - <description>Listen port for connections from the server (default 10050)</description> + <description>Listen port for connections from the server. (Default: 10050)</description> </field> <field> <fielddescr>Refresh Active Checks</fielddescr> @@ -124,7 +132,7 @@ <default_value>120</default_value> <type>input</type> <size>5</size> - <description>The agent will refresh list of active checks once per 120 (default) seconds.</description> + <description>The agent will refresh list of active checks once per this number of seconds. (Default: 120)</description> </field> <field> <fielddescr>Timeout</fielddescr> @@ -132,7 +140,13 @@ <default_value>3</default_value> <type>input</type> <size>5</size> - <description>Timeout (default 3). Do not spend more that Timeout seconds on getting requested value (1-30). The agent does not kill timeouted User Parameters processes!</description> + <description> + <![CDATA[ + Do not spend more that N seconds on getting requested value.<br /> + Note: The agent does not kill timeouted User Parameters processes!<br /> + (Default: 3. Valid range: 1-30) + ]]> + </description> </field> <field> <fielddescr>Buffer Send</fielddescr> @@ -140,7 +154,12 @@ <default_value>5</default_value> <type>input</type> <size>5</size> - <description>Buffer Send (default 5). Do not keep data longer than N seconds in buffer (1-3600).</description> + <description> + <![CDATA[ + Do not keep data longer than N seconds in buffer.<br /> + (Default: 5. Valid range: 1-3600) + ]]> + </description> </field> <field> <fielddescr>Buffer Size</fielddescr> @@ -148,7 +167,12 @@ <default_value>100</default_value> <type>input</type> <size>5</size> - <description>Buffer Size (default 100). Maximum number of values in a memory buffer (2-65535). The agent will send all collected data to Zabbix server or proxy if the buffer is full.</description> + <description> + <![CDATA[ + Maximum number of values in the memory buffer. The agent will send all collected data to Zabbix server or proxy if the buffer is full.<br /> + (Default: 100. Valid range: 2-65535) + ]]> + </description> </field> <field> <fielddescr>Start Agents</fielddescr> @@ -156,7 +180,13 @@ <default_value>3</default_value> <type>input</type> <size>5</size> - <description>Start Agents (default 3). Number of pre-forked instances of zabbix_agentd that process passive checks (0-100).If set to 0, disables passive checks and the agent will not listen on any TCP port.</description> + <description> + <![CDATA[ + Number of pre-forked instances of zabbix_agentd that process passive checks.<br /> + Note: Setting to 0 disables passive checks and the agent will not listen on any TCP port.<br /> + (Default: 3. Valid range: 0-100) + ]]> + </description> </field> <field> <fielddescr>User Parameters</fielddescr> @@ -165,15 +195,25 @@ <type>textarea</type> <rows>5</rows> <cols>50</cols> - <description>User-defined parameter to monitor. There can be several user-defined parameters. Value has form, example: UserParameter=users,who|wc -l</description> + <description> + <![CDATA[ + User-defined parameter(s) to monitor. There can be multiple user-defined parameters.<br /> + Example: <em>UserParameter=users,who|wc -l</em> + ]]> + </description> + <advancedfield/> </field> </fields> - <custom_php_install_command>sync_package_zabbix2();</custom_php_install_command> - <custom_php_command_before_form></custom_php_command_before_form> - <custom_php_after_head_command></custom_php_after_head_command> - <custom_php_after_form_command></custom_php_after_form_command> - <custom_php_validation_command>validate_input_zabbix2($_POST, $input_errors);</custom_php_validation_command> - <custom_add_php_command></custom_add_php_command> - <custom_php_resync_config_command>sync_package_zabbix2();</custom_php_resync_config_command> - <custom_php_deinstall_command>php_deinstall_zabbix2_agent();</custom_php_deinstall_command> + <custom_php_install_command> + sync_package_zabbix2(); + </custom_php_install_command> + <custom_php_validation_command> + validate_input_zabbix2($_POST, $input_errors); + </custom_php_validation_command> + <custom_php_resync_config_command> + sync_package_zabbix2(); + </custom_php_resync_config_command> + <custom_php_deinstall_command> + php_deinstall_zabbix2_agent(); + </custom_php_deinstall_command> </packagegui> diff --git a/config/zabbix2/zabbix2-proxy.priv.inc b/config/zabbix2/zabbix2-proxy.priv.inc new file mode 100644 index 00000000..f3bfc5e1 --- /dev/null +++ b/config/zabbix2/zabbix2-proxy.priv.inc @@ -0,0 +1,38 @@ +<?php +/* + zabbix2-proxy.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + 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. +*/ +global $priv_list; + +$priv_list['page-services-zabbix2-proxy'] = array(); +$priv_list['page-services-zabbix2-proxy']['name'] = "WebCfg - Services: Zabbix-2 Proxy package"; +$priv_list['page-services-zabbix2-proxy']['descr'] = "Allow access to Zabbix-2 Proxy package GUI"; + +$priv_list['page-services-zabbix2-proxy']['match'] = array(); +$priv_list['page-services-zabbix2-proxy']['match'][] = "pkg_edit.php?xml=zabbix2-proxy.xml*"; + +?> diff --git a/config/zabbix2/zabbix2-proxy.xml b/config/zabbix2/zabbix2-proxy.xml index 00d9b106..398c3df4 100644 --- a/config/zabbix2/zabbix2-proxy.xml +++ b/config/zabbix2/zabbix2-proxy.xml @@ -1,47 +1,51 @@ <?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> -<copyright> + <copyright> <![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* - zabbix2-proxy.xml - part of the Zabbix package for pfSense - Copyright (C) 2013 Danilo G. Baio - Copyright (C) 2013 Marcello Coutinho - - All rights reserved. - */ -/* ========================================================================== */ + zabbix2-proxy.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2013 Danilo G. Baio + Copyright (C) 2013 Marcello Coutinho + Copyright (C) 2015 ESF, LLC + All rights reserved. +*/ +/* ====================================================================================== */ /* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + 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. + 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. + 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. - */ -/* ========================================================================== */ + + 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. +*/ +/* ====================================================================================== */ ]]> </copyright> <name>zabbixproxy</name> <title>Services: Zabbix-2 Proxy</title> <category>Monitoring</category> - <version>0.8.3</version> + <version>0.8.4</version> <include_file>/usr/local/pkg/zabbix2.inc</include_file> <addedit_string>Zabbix Proxy has been created/modified.</addedit_string> <delete_string>Zabbix Proxy has been deleted.</delete_string> @@ -49,7 +53,10 @@ <additional_files_needed> <item>https://packages.pfsense.org/packages/config/zabbix2/zabbix2.inc</item> <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/zabbix2/zabbix2-proxy.priv.inc</item> + <prefix>/etc/inc/priv/</prefix> </additional_files_needed> <menu> <name>Zabbix-2 Proxy</name> @@ -61,7 +68,7 @@ <name>zabbix_proxy</name> <rcfile>zabbix2_proxy.sh</rcfile> <executable>zabbix_proxy</executable> - <description>Zabbix proxy collection daemon</description> + <description>Zabbix Proxy Collection Daemon</description> </service> <tabs> <tab> @@ -70,6 +77,7 @@ <active /> </tab> </tabs> + <advanced_options>enabled</advanced_options> <fields> <field> <name>Zabbix2 Proxy Settings</name> @@ -78,31 +86,31 @@ <field> <fielddescr>Enable</fielddescr> <fieldname>proxyenabled</fieldname> - <description>Enable Zabbix2 Proxy service</description> + <description>Enable Zabbix2 Proxy service.</description> <type>checkbox</type> </field> <field> <fielddescr>Server</fielddescr> <fieldname>server</fieldname> - <description>List of comma delimited IP addresses (or hostnames) of ZABBIX servers</description> + <description>List of comma delimited IP addresses (or hostnames) of Zabbix servers.</description> <default_value>127.0.0.1</default_value> <type>input</type> <size>60</size> <required>true</required> </field> <field> - <fielddescr>Server Port</fielddescr> - <fieldname>serverport</fieldname> - <description>Port of Zabbix trapper on Zabbix server. default value 10051</description> - <default_value>10051</default_value> - <type>input</type> - <size>6</size> - <required>true</required> + <fielddescr>Server Port</fielddescr> + <fieldname>serverport</fieldname> + <description>Port of Zabbix trapper on Zabbix server. (Default: 10051)</description> + <default_value>10051</default_value> + <type>input</type> + <size>6</size> + <required>true</required> </field> <field> <fielddescr>Hostname</fielddescr> <fieldname>hostname</fieldname> - <description>Unique, case-sensitive proxy name. Make sure the proxy name is known to the server</description> + <description>Unique, case-sensitive proxy name. Make sure the proxy name is known to the server.</description> <default_value>localhost</default_value> <type>input</type> <size>50</size> @@ -111,7 +119,7 @@ <field> <fielddescr>Proxy Mode</fielddescr> <fieldname>proxymode</fieldname> - <description>Select Zabbix proxy mode (Active is default)</description> + <description>Select Zabbix proxy mode. (Default: Active)</description> <type>select</type> <default_value>0</default_value> <options> @@ -136,15 +144,20 @@ <type>textarea</type> <rows>5</rows> <cols>50</cols> - <description>Advanced parameters. There are some rarely used parameters that sometimes need to be defined. Value has form, example: StartDiscoverers=10</description> + <description>Advanced parameters. There are some rarely used parameters that sometimes need to be defined. Example: StartDiscoverers=10</description> + <advancedfield/> </field> </fields> - <custom_php_install_command>sync_package_zabbix2();</custom_php_install_command> - <custom_php_command_before_form></custom_php_command_before_form> - <custom_php_after_head_command></custom_php_after_head_command> - <custom_php_after_form_command></custom_php_after_form_command> - <custom_php_validation_command>validate_input_zabbix2($_POST, $input_errors);</custom_php_validation_command> - <custom_add_php_command></custom_add_php_command> - <custom_php_resync_config_command>sync_package_zabbix2();</custom_php_resync_config_command> - <custom_php_deinstall_command>php_deinstall_zabbix2_proxy();</custom_php_deinstall_command> + <custom_php_install_command> + sync_package_zabbix2(); + </custom_php_install_command> + <custom_php_validation_command> + validate_input_zabbix2($_POST, $input_errors); + </custom_php_validation_command> + <custom_php_resync_config_command> + sync_package_zabbix2(); + </custom_php_resync_config_command> + <custom_php_deinstall_command> + php_deinstall_zabbix2_proxy(); + </custom_php_deinstall_command> </packagegui> diff --git a/config/zabbix2/zabbix2.inc b/config/zabbix2/zabbix2.inc index 77f1d6e1..9b5f3ed3 100644 --- a/config/zabbix2/zabbix2.inc +++ b/config/zabbix2/zabbix2.inc @@ -1,205 +1,213 @@ <?php -/* $Id$ */ -/* ========================================================================== */ /* - zabbix2.inc - part of the Zabbix package for pfSense - Copyright (C) 2013 Danilo G. Baio - Copyright (C) 2013 Marcello Coutinho - - 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. - */ -/* ========================================================================== */ + zabbix2.inc + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2013 Danilo G. Baio + Copyright (C) 2013 Marcello Coutinho + Copyright (C) 2015 ESF, LLC + 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. +*/ require_once("util.inc"); require_once("functions.inc"); require_once("pkg-utils.inc"); require_once("globals.inc"); -function php_install_zabbix2(){ - sync_package_zabbix2(); +function php_zabbix2_pfs_version() { + $pfs_version = substr(trim(file_get_contents("/etc/version")), 0, 3); + return $pfs_version; } -function php_deinstall_zabbix2_agent(){ - global $config, $g; - - conf_mount_rw(); - $pfs_version = php_zabbix2_pfs_version(); - $zabbix2_pkg_base = php_zabbix2_pkg_base($pfs_version); - - if ($pfs_version > 2.0){ - define('ZABBIX_AGENT_BASE', '/usr/pbi/' . $zabbix2_pkg_base . '-agent-' . php_uname("m")); - } else { - define('ZABBIX_AGENT_BASE', '/usr/local'); - } - - exec("/usr/bin/killall zabbix_agentd"); - unlink_if_exists(ZABBIX_AGENT_BASE . "/etc/rc.d/zabbix2_agentd.sh"); - unlink_if_exists(ZABBIX_AGENT_BASE . "/etc/" . $zabbix2_pkg_base . "/zabbix_agentd.conf"); - unlink_if_exists("/var/log/zabbix2/zabbix2_agentd.log"); - unlink_if_exists("/var/run/zabbix2/zabbix2_agentd.pid"); - - if (!is_array($config['installedpackages']['zabbixproxy'])){ - if (is_dir("/var/log/zabbix2")) - exec("/bin/rm -r /var/log/zabbix2/"); - if (is_dir("/var/run/zabbix2")) - exec("/bin/rm -r /var/run/zabbix2/"); - } - - conf_mount_ro(); +function php_zabbix2_pkg_base($pfs_version) { + if ($pfs_version >= 2.2) { + // pfSense 2.2 with zabbix 2.4 + $zabbix2_pkg_base = "zabbix24"; + } else { + // pfSense 2.1 with zabbix 2.2 + $zabbix2_pkg_base = "zabbix22"; + } + return $zabbix2_pkg_base; } -function php_deinstall_zabbix2_proxy(){ - global $config, $g; - - conf_mount_rw(); - $pfs_version = php_zabbix2_pfs_version(); - $zabbix2_pkg_base = php_zabbix2_pkg_base($pfs_version); +function php_deinstall_zabbix2_agent() { + global $config, $g; - if ($pfs_version > 2.0){ - define('ZABBIX_PROXY_BASE', '/usr/pbi/' . $zabbix2_pkg_base . '-proxy-' . php_uname("m")); - } else { - define('ZABBIX_PROXY_BASE', '/usr/local'); - } + $pfs_version = php_zabbix2_pfs_version(); + $zabbix2_pkg_base = php_zabbix2_pkg_base($pfs_version); - exec("/usr/bin/killall zabbix_proxy"); - unlink_if_exists(ZABBIX_PROXY_BASE . "/etc/rc.d/zabbix2_proxy.sh"); - unlink_if_exists(ZABBIX_PROXY_BASE . "/etc/" . $zabbix2_pkg_base . "/zabbix_proxy.conf"); - unlink_if_exists("/var/log/zabbix2/zabbix_proxy.log"); - unlink_if_exists("/var/run/zabbix2/zabbix2_proxy.pid"); + if ($pfs_version == "2.1" || $pfs_version == "2.2") { + define('ZABBIX_AGENT_BASE', '/usr/pbi/' . $zabbix2_pkg_base . '-agent-' . php_uname("m")); + } else { + define('ZABBIX_AGENT_BASE', '/usr/local'); + } - if (!is_array($config['installedpackages']['zabbixagent'])){ - if (is_dir("/var/log/zabbix2")) - exec("/bin/rm -r /var/log/zabbix2/"); - if (is_dir("/var/run/zabbix2")) - exec("/bin/rm -r /var/run/zabbix2/"); - } + mwexec("/usr/bin/killall zabbix_agentd"); - if (is_dir("/var/db/zabbix2")) - exec("/bin/rm -r /var/db/zabbix2/"); + unlink_if_exists(ZABBIX_AGENT_BASE . "/etc/" . $zabbix2_pkg_base . "/zabbix_agentd.conf"); + unlink_if_exists("/var/log/zabbix2/zabbix2_agentd.log"); + unlink_if_exists("/var/run/zabbix2/zabbix2_agentd.pid"); - conf_mount_ro(); + if (!is_array($config['installedpackages']['zabbixproxy'])) { + if (is_dir("/var/log/zabbix2")) { + mwexec("/bin/rm -rf /var/log/zabbix2/"); + } + if (is_dir("/var/run/zabbix2")) { + mwexec("/bin/rm -rf /var/run/zabbix2/"); + } + } } -function validate_input_zabbix2($post, &$input_errors){ +function php_deinstall_zabbix2_proxy() { + global $config, $g; + + $pfs_version = php_zabbix2_pfs_version(); + $zabbix2_pkg_base = php_zabbix2_pkg_base($pfs_version); + + if ($pfs_version == "2.1" || $pfs_version == "2.2") { + define('ZABBIX_PROXY_BASE', '/usr/pbi/' . $zabbix2_pkg_base . '-proxy-' . php_uname("m")); + } else { + define('ZABBIX_PROXY_BASE', '/usr/local'); + } + + exec("/usr/bin/killall zabbix_proxy"); + unlink_if_exists(ZABBIX_PROXY_BASE . "/etc/" . $zabbix2_pkg_base . "/zabbix_proxy.conf"); + unlink_if_exists("/var/log/zabbix2/zabbix_proxy.log"); + unlink_if_exists("/var/run/zabbix2/zabbix2_proxy.pid"); + + if (!is_array($config['installedpackages']['zabbixagent'])) { + if (is_dir("/var/log/zabbix2")) { + exec("/bin/rm -r /var/log/zabbix2/"); + } + if (is_dir("/var/run/zabbix2")) { + exec("/bin/rm -r /var/run/zabbix2/"); + } + } - if (isset($post['proxyenabled'])){ + if (is_dir("/var/db/zabbix2")) { + exec("/bin/rm -r /var/db/zabbix2/"); + } +} + +function validate_input_zabbix2($post, &$input_errors) { + if (isset($post['proxyenabled'])) { if (!is_numericint($post['serverport'])) { - $input_errors[]='Server Port is not numeric.'.$ServerPort; - } - + $input_errors[] = "'Server Port' value is not numeric."; + } elseif ($post['serverport'] < 1 || $post['serverport'] > 65535) { + $input_errors[] = "You must enter a valid value for 'Server Port'."; + } + if (!is_numericint($post['configfrequency'])) { - $input_errors[]='Config Frequency is not numeric.'; - } + $input_errors[] = "'Config Frequency' value is not numeric."; } - if (isset($post['agentenabled'])){ + } + + if (isset($post['agentenabled'])) { if (!preg_match("/\w+/", $post['server'])) { - $input_errors[]='Server field is required.'; - } - + $input_errors[] = "Server field is required."; + } + if (!preg_match("/\w+/", $post['hostname'])) { - $input_errors[]='Hostname field is required.'; - } - + $input_errors[] = "Hostname field is required."; + } + if ($post['listenip'] != '') { - if (!is_ipaddr_configured($post['listenip']) && !preg_match("/(127.0.0.1|0.0.0.0)/",$post['listenip'])) { - $input_errors[]='Listen IP is not a configured IP address.'; + if (!is_ipaddr_configured($post['listenip']) && !preg_match("/(127.0.0.1|0.0.0.0)/", $post['listenip'])) { + $input_errors[] = "'Listen IP' is not a configured IP address."; } } if ($post['listenport'] != '') { - if (!preg_match("/^\d+$/", $post['listenport'])) { - $input_errors[]='Listen Port is not numeric.'; - } + if (!is_numericint($post['listenport'])) { + $input_errors[] = "'Listen Port' value is not numeric."; + } elseif ($post['listenport'] < 1 || $post['listenport'] > 65535) { + $input_errors[] = "You must enter a valid value for 'Listen Port'."; + } } if ($post['refreshactchecks'] != '') { - if (!preg_match("/^\d+$/", $post['refreshactchecks'])) { - $input_errors[]='Refresh Active Checks is not numeric.'; - } elseif ( $post['refreshactchecks'] < 60 || $post['refreshactchecks'] > 3600 ) { - $input_errors[]='You must enter a valid value for \'Refresh Active Checks\''; + if (!is_numericint($post['refreshactchecks'])) { + $input_errors[] = "'Refresh Active Checks' value is not numeric."; + } elseif ($post['refreshactchecks'] < 60 || $post['refreshactchecks'] > 3600) { + $input_errors[] = "You must enter a valid value for 'Refresh Active Checks'."; } } if ($post['timeout'] != '') { if (!is_numericint($post['timeout'])) { - $input_errors[]='Timeout is not numeric.'; - } elseif ( $post['timeout'] < 1 || $post['timeout'] > 30 ) { - $input_errors[]='You must enter a valid value for \'Timeout\''; + $input_errors[] = "Timeout value is not numeric."; + } elseif ($post['timeout'] < 1 || $post['timeout'] > 30) { + $input_errors[] = "You must enter a valid value for 'Timeout'."; } } - + if ($post['buffersend'] != '') { if (!is_numericint($post['buffersend'])) { - $input_errors[]='Buffer Send is not numeric.'; - } elseif ( $post['buffersend'] < 1 || $post['buffersend'] > 3600 ) { - $input_errors[]='You must enter a valid value for \'Buffer Send\''; + $input_errors[] = "'Buffer Send' value is not numeric."; + } elseif ($post['buffersend'] < 1 || $post['buffersend'] > 3600) { + $input_errors[] = "You must enter a valid value for 'Buffer Send'."; } } - + if ($post['buffersize'] != '') { if (!is_numericint($post['buffersize'])) { - $input_errors[]='Bufer Size is not numeric.'; - } elseif ( $post['buffersize'] < 2 || $post['buffersize'] > 65535 ) { - $input_errors[]='You must enter a valid value for \'Buffer Size\''; + $input_errors[] = "'Buffer Size' value is not numeric."; + } elseif ($post['buffersize'] < 2 || $post['buffersize'] > 65535) { + $input_errors[] = "You must enter a valid value for 'Buffer Size'."; } } - + if ($post['startagents'] != '') { if (!is_numericint($post['startagents'])) { $input_errors[]='Start Agents is not numeric.'; - } elseif ( $post['startagents'] < 0 || $post['startagents'] > 100 ) { - $input_errors[]='You must enter a valid value for \'Start Agents\''; + } elseif ($post['startagents'] < 0 || $post['startagents'] > 100) { + $input_errors[] = "You must enter a valid value for 'Start Agents'."; } } - } + } } -function sync_package_zabbix2(){ +function sync_package_zabbix2() { global $config, $g; conf_mount_rw(); $pfs_version = php_zabbix2_pfs_version(); $zabbix2_pkg_base = php_zabbix2_pkg_base($pfs_version); - if ($pfs_version > 2.0){ + if ($pfs_version == "2.1" || $pfs_version == "2.2") { define('ZABBIX_AGENT_BASE', '/usr/pbi/' . $zabbix2_pkg_base . '-agent-' . php_uname("m")); define('ZABBIX_PROXY_BASE', '/usr/pbi/' . $zabbix2_pkg_base . '-proxy-' . php_uname("m")); - } - else { + } else { define('ZABBIX_AGENT_BASE', '/usr/local'); define('ZABBIX_PROXY_BASE', '/usr/local'); } - #check zabbix proxy config - if (is_array($config['installedpackages']['zabbixproxy'])){ + // Check zabbix proxy config + if (is_array($config['installedpackages']['zabbixproxy'])) { $zbproxy_config = $config['installedpackages']['zabbixproxy']['config'][0]; - if ($zbproxy_config['proxyenabled']=="on"){ - $Mode=(is_numericint($zbproxy_config['proxymode'])?$zbproxy_config['proxymode'] : 0); - $AdvancedParams=base64_decode($zbproxy_config['advancedparams']); - + if ($zbproxy_config['proxyenabled'] == "on") { + $Mode = (is_numericint($zbproxy_config['proxymode']) ? $zbproxy_config['proxymode'] : 0); + $AdvancedParams = base64_decode($zbproxy_config['advancedparams']); + $zbproxy_conf_file = <<< EOF Server={$zbproxy_config['server']} ServerPort={$zbproxy_config['serverport']} @@ -209,7 +217,8 @@ DBName=/var/db/zabbix2/proxy.db LogFile=/var/log/zabbix2/zabbix_proxy.log ConfigFrequency={$zbproxy_config['configfrequency']} FpingLocation=/usr/local/sbin/fping -#there's currently no fping6 (IPv6) dependency in the package, but if there was, the binary would likely also be in /usr/local/sbin +# There's currently no fping6 (IPv6) dependency in the package, +# but if there was, the binary would likely also be in /usr/local/sbin. Fping6Location=/usr/local/sbin/fping6 ProxyMode={$Mode} {$AdvancedParams} @@ -218,19 +227,19 @@ EOF; file_put_contents(ZABBIX_PROXY_BASE . "/etc/" . $zabbix2_pkg_base . "/zabbix_proxy.conf", strtr($zbproxy_conf_file, array("\r" => ""))); } } - /* check zabbix agent settings*/ - if (is_array($config['installedpackages']['zabbixagent'])){ + // Check zabbix agent settings + if (is_array($config['installedpackages']['zabbixagent'])) { $zbagent_config = $config['installedpackages']['zabbixagent']['config'][0]; - if ($zbagent_config['agentenabled']=="on"){ - $RefreshActChecks=(preg_match("/(\d+)/",$zbagent_config['refreshactchecks'],$matches)? $matches[1] : "120"); - $BufferSend=(preg_match("/(\d+)/",$zbagent_config['buffersend'],$matches)? $matches[1] : "5" ); - $BufferSize=(preg_match("/(\d+)/",$zbagent_config['buffersize'],$matches)? $matches[1] : "100"); - $StartAgents=(preg_match("/(\d+)/",$zbagent_config['startagents'],$matches)? $matches[1] :"3" ); - $UserParams=base64_decode($zbagent_config['userparams']); - $ListenIp=($zbagent_config['listenip'] != ''? $zbagent_config['listenip'] : "0.0.0.0"); - $ListenPort=($zbagent_config['listenport'] != ''? $zbagent_config['listenport'] : "10050"); - $TimeOut=($zbagent_config['timeout'] != ''? $zbagent_config['timeout'] : "3"); - + if ($zbagent_config['agentenabled'] == "on") { + $RefreshActChecks = (preg_match("/(\d+)/", $zbagent_config['refreshactchecks'], $matches) ? $matches[1] : "120"); + $BufferSend = (preg_match("/(\d+)/", $zbagent_config['buffersend'], $matches) ? $matches[1] : "5"); + $BufferSize = (preg_match("/(\d+)/", $zbagent_config['buffersize'], $matches) ? $matches[1] : "100"); + $StartAgents = (preg_match("/(\d+)/", $zbagent_config['startagents'], $matches) ? $matches[1] : "3"); + $UserParams = base64_decode($zbagent_config['userparams']); + $ListenIp = $zbagent_config['listenip'] ?: "0.0.0.0"; + $ListenPort = $zbagent_config['listenport'] ?: "10050"; + $TimeOut = $zbagent_config['timeout'] ?: "3"; + $zbagent_conf_file = <<< EOF Server={$zbagent_config['server']} ServerActive={$zbagent_config['serveractive']} @@ -249,33 +258,35 @@ StartAgents={$StartAgents} {$UserParams} EOF; - file_put_contents(ZABBIX_AGENT_BASE . "/etc/" . $zabbix2_pkg_base . "/zabbix_agentd.conf", strtr($zbagent_conf_file, array("\r" => ""))); + file_put_contents(ZABBIX_AGENT_BASE . "/etc/" . $zabbix2_pkg_base . "/zabbix_agentd.conf", strtr($zbagent_conf_file, array("\r" => ""))); } } + $want_sysctls = array( 'kern.ipc.shmall' => '2097152', 'kern.ipc.shmmax' => '2147483648', 'kern.ipc.semmsl' => '250' ); $sysctls = array(); - #check sysctl file values + // Check sysctl file values $sc_file=""; if (file_exists("/etc/sysctl.conf")) { $sc = file("/etc/sysctl.conf"); foreach ($sc as $line) { list($sysk, $sysv) = explode("=", $line, 2); - if (preg_match("/\w/",$line) && !array_key_exists($sysk, $want_sysctls)) - $sc_file.=$line; + if (preg_match("/\w/", $line) && !array_key_exists($sysk, $want_sysctls)) { + $sc_file .= $line; } + } } - foreach ($want_sysctls as $ws=> $wv) { + foreach ($want_sysctls as $ws => $wv) { $sc_file .= "{$ws}={$wv}\n"; - exec("/sbin/sysctl {$ws}={$wv}"); + mwexec("/sbin/sysctl {$ws}={$wv}"); } file_put_contents("/etc/sysctl.conf", $sc_file); - #check bootloader values - $lt_file=""; + // Check bootloader values + $lt_file = ""; $want_tunables = array( 'kern.ipc.semopm' => '100', 'kern.ipc.semmni' => '128', @@ -287,110 +298,91 @@ EOF; $lt = file("/boot/loader.conf"); foreach ($lt as $line) { list($tunable, $val) = explode("=", $line, 2); - if (preg_match("/\w/",$line) && !array_key_exists($tunable, $want_tunables)) - $lt_file.=$line; + if (preg_match("/\w/", $line) && !array_key_exists($tunable, $want_tunables)) { + $lt_file .= $line; + } } } foreach ($want_tunables as $wt => $wv) { - $lt_file.= "{$wt}={$wv}\n"; + $lt_file .= "{$wt}={$wv}\n"; } file_put_contents("/boot/loader.conf", $lt_file); - /*check startup script files*/ - /* create a few directories and ensure the sample files are in place */ - if (!is_dir(ZABBIX_PROXY_BASE . "/etc/" . $zabbix2_pkg_base)) - exec("/bin/mkdir -p " . ZABBIX_PROXY_BASE . "/etc/" . $zabbix2_pkg_base); - - $dir_checks = <<< EOF -if [ ! -d /var/log/zabbix2 ] - then - /bin/mkdir -p /var/log/zabbix2 - /usr/sbin/chmod 755 /var/log/zabbix2 - fi -/usr/sbin/chown -R zabbix:zabbix /var/log/zabbix2 - -if [ ! -d /var/run/zabbix2 ] - then - /bin/mkdir -p /var/run/zabbix2 - /usr/sbin/chmod 755 /var/run/zabbix2 - fi -/usr/sbin/chown -R zabbix:zabbix /var/run/zabbix2 - -if [ ! -d /var/db/zabbix2 ] - then - /bin/mkdir -p /var/db/zabbix2 - /usr/sbin/chmod 755 /var/db/zabbix2 - fi -/usr/sbin/chown -R zabbix:zabbix /var/db/zabbix2 + // Check startup script files + // Create a few directories and ensure the sample files are in place + if (!is_dir(ZABBIX_PROXY_BASE . "/etc/" . $zabbix2_pkg_base)) { + mwexec("/bin/mkdir -p " . ZABBIX_PROXY_BASE . "/etc/" . $zabbix2_pkg_base); + } + + $dir_checks = <<< EOF + + if [ ! -d /var/log/zabbix2 ]; then + /bin/mkdir -p /var/log/zabbix2 + /usr/sbin/chmod 755 /var/log/zabbix2 + fi + /usr/sbin/chown -R zabbix:zabbix /var/log/zabbix2 + + if [ ! -d /var/run/zabbix2 ]; then + /bin/mkdir -p /var/run/zabbix2 + /usr/sbin/chmod 755 /var/run/zabbix2 + fi + /usr/sbin/chown -R zabbix:zabbix /var/run/zabbix2 + + if [ ! -d /var/db/zabbix2 ]; then + /bin/mkdir -p /var/db/zabbix2 + /usr/sbin/chmod 755 /var/db/zabbix2 + fi + /usr/sbin/chown -R zabbix:zabbix /var/db/zabbix2 EOF; - - $zproxy_rcfile="/usr/local/etc/rc.d/zabbix2_proxy.sh"; - if (is_array($zbproxy_config) && $zbproxy_config['proxyenabled']=="on"){ - $zproxy_start= strtr($dir_checks, array("\r" => "")). "\necho \"Starting Zabbix Proxy\"...\n"; - /* start zabbix proxy */ + + $zproxy_rcfile = "/usr/local/etc/rc.d/zabbix2_proxy.sh"; + if (is_array($zbproxy_config) && $zbproxy_config['proxyenabled'] == "on") { + $zproxy_start = strtr($dir_checks, array("\r" => "")). "\necho \"Starting Zabbix Proxy\"...\n"; $zproxy_start .= ZABBIX_PROXY_BASE . "/sbin/zabbix_proxy\n"; - + $zproxy_stop = "echo \"Stopping Zabbix Proxy\"\n"; $zproxy_stop .= "/usr/bin/killall zabbix_proxy\n"; $zproxy_stop .= "/bin/sleep 5\n"; - /* write out rc.d start/stop file */ write_rcfile(array( "file" => "zabbix2_proxy.sh", "start" => $zproxy_start, "stop" => $zproxy_stop ) ); - mwexec("{$zproxy_rcfile} restart"); - }else{ - if (file_exists($zproxy_rcfile)){ - mwexec("{$zproxy_rcfile} stop"); - unlink($zproxy_rcfile); + restart_service("zabbix_proxy"); + } else { + if (is_service_running("zabbix_proxy")) { + stop_service("zabbix_proxy"); } + unlink_if_exists($zproxy_rcfile); } - + $zagent_rcfile="/usr/local/etc/rc.d/zabbix2_agentd.sh"; - if (is_array($zbagent_config) && $zbagent_config['agentenabled']=="on"){ + if (is_array($zbagent_config) && $zbagent_config['agentenabled']=="on") { $zagent_start .= strtr($dir_checks, array("\r" => "")). "\necho \"Starting Zabbix Agent...\"\n"; $zagent_start .= ZABBIX_AGENT_BASE . "/sbin/zabbix_agentd\n"; - + $zagent_stop = "echo \"Stopping Zabbix Agent...\"\n"; $zagent_stop .= "/usr/bin/killall zabbix_agentd\n"; $zagent_stop .= "/bin/sleep 5\n"; - - /* write out rc.d start/stop file */ + write_rcfile(array( - "file" => "zabbix2_agentd.sh", - "start" => "$zagent_start", - "stop" => "$zagent_stop" - ) + "file" => "zabbix2_agentd.sh", + "start" => $zagent_start, + "stop" => $zagent_stop + ) ); - mwexec("{$zagent_rcfile} restart"); - }else{ - if (file_exists($zagent_rcfile)){ - mwexec("{$zagent_rcfile} stop"); - unlink($zagent_rcfile); + restart_service("zabbix_agentd"); + } else { + if (is_service_running("zabbix_agentd")) { + stop_service("zabbix_agentd"); } + unlink_if_exists($zagent_rcfile); } - - conf_mount_ro(); -} -function php_zabbix2_pfs_version(){ - $pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); - return $pfs_version; -} - -function php_zabbix2_pkg_base($pfs_version){ - if ($pfs_version >= 2.2){ - // pfSense 2.2 with zabbix 2.4 - $zabbix2_pkg_base = "zabbix24"; - }else{ - // pfSense 2.1 with zabbix 2.2 - $zabbix2_pkg_base = "zabbix22"; - } - return $zabbix2_pkg_base; + conf_mount_ro(); } ?> diff --git a/pkg_config.10.xml b/pkg_config.10.xml index ecbd591b..aac5719b 100644 --- a/pkg_config.10.xml +++ b/pkg_config.10.xml @@ -82,7 +82,7 @@ <category>File Management</category> <pkginfolink>https://doc.pfsense.org/index.php/Filer_package</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/filer/filer.xml</config_file> - <version>0.60.5</version> + <version>0.60.6</version> <status>Beta</status> <required_version>2.2</required_version> <maintainer>bscholer@cshl.edu</maintainer> @@ -166,26 +166,26 @@ The Reliable, High Performance TCP/HTTP(S) Load Balancer.<br /> This package implements the TCP, HTTP and HTTPS balancing features from haproxy.<br /> Supports ACLs for smart backend switching.<br /> - <strong>As of pkg v0.27 switched to using 1.6dev releases. If you need stable, switch to haproxy-1_5 package.</strong> + <strong>As of pkg v0.33 switched to using 1.6 stable releases.</strong> ]]> </descr> <website>http://haproxy.1wt.eu/</website> <category>Services</category> - <version>0.31</version> + <version>0.33</version> <status>Release</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy.xml</config_file> <configurationfile>haproxy.xml</configurationfile> - <run_depends>sbin/haproxy:net/haproxy-devel</run_depends> + <run_depends>sbin/haproxy:net/haproxy</run_depends> <port_category>net</port_category> <conflicts>haproxy</conflicts> - <depends_on_package_pbi>haproxy-devel-1.6-dev2-##ARCH##.pbi</depends_on_package_pbi> + <depends_on_package_pbi>haproxy-1.6.2_1-##ARCH##.pbi</depends_on_package_pbi> <build_pbi> - <ports_before>security/openssl</ports_before> - <custom_name>haproxy-devel</custom_name> - <port>net/haproxy-devel</port> + <ports_before>security/openssl lang/lua53</ports_before> + <custom_name>haproxy</custom_name> + <port>net/haproxy</port> </build_pbi> - <build_options>WITH_OPENSSL_PORT=yes;net_haproxy-devel_UNSET_FORCE=DPCRE;net_haproxy-devel_SET_FORCE=OPENSSL SPCRE LUA</build_options> + <build_options>WITH_OPENSSL_PORT=yes;net_haproxy_UNSET_FORCE=DPCRE;net_haproxy_SET_FORCE=OPENSSL SPCRE LUA CPU_AFFINITY</build_options> </package> <package> <name>Apache with mod_security-dev</name> @@ -200,7 +200,7 @@ ]]> </descr> <category>Network Management</category> - <version>0.44</version> + <version>0.45</version> <status>ALPHA</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/apache_mod_security-dev/apache_virtualhost.xml</config_file> @@ -325,7 +325,7 @@ <pkginfolink/> <port_category>ftp</port_category> <config_file>https://packages.pfsense.org/packages/config/tftp2/tftp.xml</config_file> - <version>2.2.1</version> + <version>2.2.2</version> <status>Stable</status> <required_version>2.2</required_version> <configurationfile>tftp.xml</configurationfile> @@ -373,8 +373,8 @@ <port_category>www</port_category> <pkginfolink>https://doc.pfsense.org/index.php/vhosts</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/vhosts/vhosts.xml</config_file> - <version>0.8.2</version> - <status>ALPHA</status> + <version>0.8.3</version> + <status>Beta</status> <required_version>2.2</required_version> <maintainer>markjcrane@gmail.com</maintainer> <configurationfile>vhosts.xml</configurationfile> @@ -395,7 +395,7 @@ </build_pbi> <build_options>barnyard2_UNSET_FORCE=ODBC PGSQL PRELUDE;barnyard2_SET_FORCE=GRE IPV6 MPLS MYSQL PORT_PCAP BRO;snort_SET_FORCE=BARNYARD PERFPROFILE SOURCEFIRE GRE IPV6 NORMALIZER APPID;snort_UNSET_FORCE=PULLEDPORK FILEINSPECT HA</build_options> <config_file>https://packages.pfsense.org/packages/config/snort/snort.xml</config_file> - <version>3.2.8.2</version> + <version>3.2.8.3</version> <required_version>2.2</required_version> <status>Stable</status> <configurationfile>/snort.xml</configurationfile> @@ -460,14 +460,14 @@ <descr><![CDATA[ Postfix mail forwarder acts as a relay server for your domain.<br /> It can do first and second line antispam combat before sending incoming mail to local mail servers.<br /> - Postfix can also detect zombies, check RBLS, SPF, search ldap for valid recipients and use third part antispam engines like policyd and mailscanner for better antispam solution. + Postfix can also detect zombies, check RBLS, SPF, search LDAP for valid recipients and use third part antispam engines like policyd and mailscanner for better antispam solution. ]]> </descr> <category>Services</category> <pkginfolink>https://forum.pfsense.org/index.php/topic,40622.0.html</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/postfix/postfix.xml</config_file> <depends_on_package_pbi>postfix-2.11.3_2-##ARCH##.pbi</depends_on_package_pbi> - <version>2.4.4</version> + <version>2.4.5</version> <status>Release</status> <required_version>2.2</required_version> <configurationfile>postfix.xml</configurationfile> @@ -568,7 +568,7 @@ <build_pbi> <port>net/openbgpd</port> </build_pbi> - <version>0.9.3.7</version> + <version>0.9.3.8</version> <status>STABLE</status> <pkginfolink>https://doc.pfsense.org/index.php/OpenBGPD_package</pkginfolink> <required_version>2.2</required_version> @@ -580,7 +580,7 @@ <descr>LightSquid is a high performance web proxy reporting tool. Proxy realtime statistics (SQStat). Requires Squid HTTP proxy.</descr> <website>http://lightsquid.sf.net/</website> <category>Network Report</category> - <version>2.41</version> + <version>2.42</version> <maintainer>dv_serg@mail.ru</maintainer> <port_category>www</port_category> <run_depends>libexec/lightsquid/ip2name.list:www/lightsquid</run_depends> @@ -595,6 +595,7 @@ <config_file>https://packages.pfsense.org/packages/config/lightsquid/lightsquid.xml</config_file> <configurationfile>lightsquid.xml</configurationfile> <noembedded>true</noembedded> + <after_install_info>Please visit Status - Squid Proxy Reports - Settings and read the configuration and usage instructions.</after_install_info> </package> <package> <name>Sarg</name> @@ -608,7 +609,7 @@ <config_file>https://packages.pfsense.org/packages/config/sarg/sarg.xml</config_file> <pkginfolink>https://forum.pfsense.org/index.php/topic,47765.0.html</pkginfolink> <depends_on_package_pbi>sarg-2.3.9-##ARCH##.pbi</depends_on_package_pbi> - <version>0.6.6</version> + <version>0.6.7</version> <status>Release</status> <required_version>2.2</required_version> <port_category>www</port_category> @@ -690,7 +691,7 @@ <build_pbi> <port>net/vnstat</port> </build_pbi> - <version>1.12.7</version> + <version>1.12.8</version> <status>Stable</status> <required_version>2.2</required_version> <maintainer>crazypark2@yahoo.dk</maintainer> @@ -703,7 +704,7 @@ <descr>pfSense version of TinyDNS which features failover host support.</descr> <website>http://cr.yp.to/djbdns.html</website> <category>Services</category> - <version>1.0.6.23</version> + <version>1.0.6.24</version> <status>Beta</status> <pkginfolink>https://doc.pfsense.org/index.php/Tinydns_package</pkginfolink> <required_version>2.2</required_version> @@ -816,7 +817,7 @@ <descr>Network UPS Tools.</descr> <website>http://www.networkupstools.org/</website> <category>Network Management</category> - <version>2.1.0</version> + <version>2.1.1</version> <status>BETA</status> <required_version>2.2</required_version> <maintainer>rswagoner@gmail.com</maintainer> @@ -884,7 +885,7 @@ <website>http://bsdforge.com/projects/source/net/widentd/</website> <category>Services</category> <depends_on_package_pbi>widentd-1.03_2-##ARCH##.pbi</depends_on_package_pbi> - <version>1.0.4</version> + <version>1.0.5</version> <status>Stable</status> <pkginfolink>https://doc.pfsense.org/index.php/Widentd_package</pkginfolink> <required_version>2.2</required_version> @@ -909,7 +910,7 @@ </descr> <pkginfolink>https://doc.pfsense.org/index.php/FreeRADIUS_2.x_package</pkginfolink> <category>System</category> - <version>1.6.15</version> + <version>1.6.17</version> <status>RC1</status> <required_version>2.2</required_version> <maintainer>nachtfalkeaw@web.de</maintainer> @@ -953,7 +954,7 @@ <descr>SSL encryption wrapper between remote client and local or remote servers.</descr> <category>Network Management</category> <depends_on_package_pbi>stunnel-5.20-##ARCH##.pbi</depends_on_package_pbi> - <version>5.20.2</version> + <version>5.20.3</version> <status>Stable</status> <pkginfolink>https://doc.pfsense.org/index.php/Stunnel_package</pkginfolink> <required_version>2.2</required_version> @@ -1055,7 +1056,7 @@ <pkginfolink>https://forum.pfsense.org/index.php/topic,48347.0.html</pkginfolink> <website>http://www.squid-cache.org/</website> <category>Network</category> - <version>0.4.0</version> + <version>0.4.2</version> <status>beta</status> <required_version>2.2</required_version> <maintainer>marcellocoutinho@gmail.com fernando@netfilter.com.br seth.mos@dds.nl mfuchs77@googlemail.com jimp@pfsense.org</maintainer> @@ -1168,7 +1169,7 @@ <website>http://www.squidGuard.org/</website> <maintainer>gugabsd@mundounix.com.br</maintainer> <category>Network Management</category> - <version>1.5.7</version> + <version>1.5.8</version> <status>Beta</status> <required_version>2.2</required_version> <depends_on_package_pbi>squidguard-devel-1.5_1-##ARCH##.pbi</depends_on_package_pbi> @@ -1349,7 +1350,7 @@ ]]> </descr> <category>Enhancements</category> - <version>1.0.5</version> + <version>1.0.6</version> <status>Beta</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/sshdcond/sshdcond.xml</config_file> @@ -1490,7 +1491,7 @@ <build_pbi> <port>security/tinc</port> </build_pbi> - <version>1.2.3</version> + <version>1.2.4</version> <status>ALPHA</status> <pkginfolink>https://doc.pfsense.org/index.php/tinc_package</pkginfolink> <required_version>2.2</required_version> @@ -1508,8 +1509,8 @@ <website>http://www.balabit.com/network-security/syslog-ng/</website> <descr>Syslog-ng syslog server. This service is not intended to replace the default pfSense syslog server but rather acts as an independent syslog server.</descr> <category>Services</category> - <version>1.1</version> - <status>ALPHA</status> + <version>1.1.1</version> + <status>BETA</status> <required_version>2.2</required_version> <depends_on_package_pbi>syslog-ng-3.6.2_3-##ARCH##.pbi</depends_on_package_pbi> <port_category>sysutils</port_category> @@ -1536,7 +1537,7 @@ <website>http://www.zabbix.com/product.php</website> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/zabbix-agent-lts/zabbix-agent-lts.xml</config_file> - <version>0.8.7</version> + <version>0.8.8</version> <status>BETA</status> <required_version>2.2</required_version> <configurationfile>zabbix-agent-lts.xml</configurationfile> @@ -1563,7 +1564,7 @@ <website>http://www.zabbix.com/product.php</website> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/zabbix-proxy-lts/zabbix-proxy-lts.xml</config_file> - <version>0.8.7</version> + <version>0.8.8</version> <status>BETA</status> <required_version>2.2</required_version> <configurationfile>zabbix-proxy-lts.xml</configurationfile> @@ -1590,7 +1591,7 @@ <website>http://www.zabbix.com/product.php</website> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/zabbix2/zabbix2-agent.xml</config_file> - <version>zabbix24-agent-2.4.3 pkg v0.8.3</version> + <version>0.8.4</version> <status>BETA</status> <required_version>2.2</required_version> <configurationfile>zabbix2-agent.xml</configurationfile> @@ -1615,7 +1616,7 @@ <website>http://www.zabbix.com/product.php</website> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/zabbix2/zabbix2-proxy.xml</config_file> - <version>zabbix24-proxy-2.4.3 pkg v0.8.3</version> + <version>0.8.4</version> <status>BETA</status> <required_version>2.2</required_version> <configurationfile>zabbix2-proxy.xml</configurationfile> @@ -1634,7 +1635,7 @@ <descr>sudo allows delegation of privileges to users in the shell so commands can be run as other users, such as root.</descr> <website>http://www.sudo.ws/</website> <category>Security</category> - <version>0.2.7</version> + <version>0.2.8</version> <status>Beta</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/sudo/sudo.xml</config_file> @@ -1717,7 +1718,7 @@ <website>http://suricata-ids.org/</website> <descr>High Performance Network IDS, IPS and Security Monitoring engine by OISF.</descr> <category>Security</category> - <version>2.1.6</version> + <version>2.1.8</version> <status>Stable</status> <required_version>2.2</required_version> <config_file>https://packages.pfsense.org/packages/config/suricata/suricata.xml</config_file> diff --git a/pkg_config.8.xml b/pkg_config.8.xml index 59b3491d..4b52c27b 100644 --- a/pkg_config.8.xml +++ b/pkg_config.8.xml @@ -74,7 +74,7 @@ <category>File Management</category> <pkginfolink>https://doc.pfsense.org/index.php/Filer_package</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/filer/filer.xml</config_file> - <version>0.60.5</version> + <version>0.60.6</version> <status>Beta</status> <required_version>2.0</required_version> <maintainer>bscholer@cshl.edu</maintainer> @@ -149,9 +149,9 @@ (Legacy version)]]></descr> <website>http://haproxy.1wt.eu/</website> <category>Services</category> - <version>1.4.24 pkg v 1.1.2</version> + <version>1.4.24 pkg v 1.1.3</version> <status>Release</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/haproxy-legacy/haproxy.xml</config_file> <configurationfile>haproxy.xml</configurationfile> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> @@ -190,7 +190,7 @@ Supports ACLs for smart backend switching.]]></descr> <website>http://haproxy.1wt.eu/</website> <category>Services</category> - <version>1.5.3 pkg v 0.31</version> + <version>1.5.3 pkg v 0.33</version> <status>Release</status> <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy.xml</config_file> @@ -215,9 +215,9 @@ In addition this package allows URL forwarding which can be convenient for hosting multiple websites behind pfSense using 1 IP address.<br> <b>Backup your location config before updating from 0.2.x to 0.3 package version.</b>]]></descr> <category>Network Management</category> - <version>2.4.9 pkg v0.43</version> + <version>2.4.9 pkg v0.45</version> <status>ALPHA</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/apache_mod_security-dev/apache_virtualhost.xml</config_file> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> <depends_on_package>db42-4.2.52_5.tbz</depends_on_package> @@ -397,7 +397,7 @@ <pkginfolink/> <config_file>https://packages.pfsense.org/packages/config/tftp2/tftp.xml</config_file> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> - <version>2.1</version> + <version>2.2.2</version> <status>Stable</status> <required_version>2.0</required_version> <configurationfile>tftp.xml</configurationfile> @@ -452,8 +452,8 @@ <pkginfolink>https://doc.pfsense.org/index.php/vhosts</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/vhosts/vhosts.xml</config_file> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> - <version>0.7.5</version> - <status>Stable</status> + <version>0.8.3</version> + <status>Beta</status> <required_version>1.2.3</required_version> <maintainer>markjcrane@gmail.com</maintainer> <configurationfile>vhosts.xml</configurationfile> @@ -508,7 +508,7 @@ <website>http://www.postfix.org/</website> <descr><![CDATA[Postfix mail forwarder acts as a relay server for your domain.<br /> It can do first and second line antispam combat before sending incoming mail to local mail servers.<br /> - Postfix can also detect zombies, check RBLS, SPF, seach ldap for valid recipients and use third part antispam engines like policyd and mailscanner for better antispam solution.]]></descr> + Postfix can also detect zombies, check RBLS, SPF, seach LDAP for valid recipients and use third part antispam engines like policyd and mailscanner for better antispam solution.]]></descr> <category>Services</category> <pkginfolink>https://forum.pfsense.org/index.php/topic,40622.0.html</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/postfix/postfix.xml</config_file> @@ -516,7 +516,7 @@ <depends_on_package>postfix-2.10.2,1.tbz</depends_on_package> <depends_on_package>perl5-5.16.3_4.tbz</depends_on_package> <depends_on_package_pbi>postfix-2.10.2-i386.pbi</depends_on_package_pbi> - <version>2.10.2 pkg v.2.4.4</version> + <version>2.10.2 pkg v2.4.5</version> <status>Release</status> <required_version>2.1</required_version> <configurationfile>postfix.xml</configurationfile> @@ -626,7 +626,7 @@ <descr>High performance web proxy report (LightSquid). Proxy realtime stat (SQStat). Requires squid HTTP proxy.</descr> <website>http://lightsquid.sf.net/</website> <category>Network Report</category> - <version>2.41</version> + <version>2.42</version> <maintainer>dv_serg@mail.ru</maintainer> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> <depends_on_package>lightsquid-1.8_2.tbz</depends_on_package> @@ -644,6 +644,7 @@ <pkginfolink></pkginfolink> <configurationfile>lightsquid.xml</configurationfile> <noembedded>true</noembedded> + <after_install_info>Please visit Status - Squid Proxy Reports - Settings and read the configuration and usage instructions.</after_install_info> </package> <package> <name>Sarg</name> @@ -657,9 +658,9 @@ <depends_on_package>sarg-2.3.6_2.tbz</depends_on_package> <depends_on_package>gd-2.0.35_8,1.tbz</depends_on_package> <depends_on_package_pbi>sarg-2.3.6_2-i386.pbi</depends_on_package_pbi> - <version>2.3.6_2 pkg v.0.6.6</version> + <version>2.3.6_2 pkg v0.6.7</version> <status>Release</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <configurationfile>sarg.xml</configurationfile> <build_port_path>/usr/ports/www/sarg</build_port_path> <build_options>sarg_UNSET_FORCE=PHP</build_options> @@ -740,7 +741,7 @@ <depends_on_package>vnstat-1.11.tbz</depends_on_package> <depends_on_package_pbi>vnstat-1.11_1-i386.pbi</depends_on_package_pbi> <build_port_path>/usr/ports/net/vnstat</build_port_path> - <version>1.11_1,4</version> + <version>1.12.8</version> <status>Stable</status> <required_version>2.0</required_version> <maintainer>bryan.paradis@gmail.com</maintainer> @@ -769,10 +770,10 @@ <descr>pfSense version of TinyDNS which features failover host support</descr> <website>http://cr.yp.to/djbdns.html</website> <category>Services</category> - <version>1.0.6.21</version> + <version>1.0.6.24</version> <status>Beta</status> <pkginfolink>https://doc.pfsense.org/index.php/Tinydns_package</pkginfolink> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/tinydns/tinydns.xml</config_file> <configurationfile>tinydns.xml</configurationfile> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> @@ -898,7 +899,7 @@ <descr>Network UPS Tools</descr> <website>http://www.networkupstools.org/</website> <category>Network Management</category> - <version>2.6.5_1 pkg 2.1.0</version> + <version>2.6.5_1 pkg 2.1.1</version> <status>BETA</status> <required_version>2.0</required_version> <maintainer>rswagoner@gmail.com</maintainer> @@ -962,7 +963,7 @@ <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> <depends_on_package>widentd-1.03_1.tbz</depends_on_package> <depends_on_package_pbi>widentd-1.03_1-i386.pbi</depends_on_package_pbi> - <version>1.03_1</version> + <version>1.05</version> <status>Stable</status> <pkginfolink>https://doc.pfsense.org/index.php/Widentd_package</pkginfolink> <required_version>1.2.1</required_version> @@ -1002,7 +1003,7 @@ On pfSense docs there is a how-to which could help you on porting users.]]></descr> <pkginfolink>https://doc.pfsense.org/index.php/FreeRADIUS_2.x_package</pkginfolink> <category>System</category> - <version>1.6.14</version> + <version>1.6.16</version> <status>RC1</status> <required_version>2.1</required_version> <maintainer>nachtfalkeaw@web.de</maintainer> @@ -1045,12 +1046,12 @@ <package> <name>stunnel</name> <website>http://www.stunnel.org/</website> - <descr>An SSL encryption wrapper between remote client and local or remote servers. </descr> + <descr>An SSL encryption wrapper between remote client and local or remote servers.</descr> <category>Network Management</category> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> <depends_on_package>stunnel-4.43.tbz</depends_on_package> <depends_on_package_pbi>stunnel-4.54-i386.pbi</depends_on_package_pbi> - <version>4.43.0</version> + <version>4.54 pkg v5.20.3</version> <status>Stable</status> <pkginfolink>https://doc.pfsense.org/index.php/Stunnel_package</pkginfolink> <required_version>1.2.1</required_version> @@ -1145,9 +1146,9 @@ <pkginfolink>https://forum.pfsense.org/index.php/topic,48347.0.html</pkginfolink> <website>http://www.squid-cache.org/</website> <category>Network</category> - <version>3.1.20 pkg 2.1.3</version> + <version>3.1.20 pkg 2.1.4</version> <status>beta</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <maintainer>marcellocoutinho@gmail.com fernando@netfilter.com.br seth.mos@dds.nl mfuchs77@googlemail.com jimp@pfsense.org</maintainer> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> <depends_on_package>squid-3.1.20.tbz</depends_on_package> @@ -1176,9 +1177,9 @@ <pkginfolink>https://forum.pfsense.org/index.php/topic,48347.0.html</pkginfolink> <website>http://www.squid-cache.org/</website> <category>Network</category> - <version>3.3.10 pkg 2.3.0</version> + <version>3.3.10 pkg 2.3.1</version> <status>beta</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <maintainer>marcellocoutinho@gmail.com fernando@netfilter.com.br seth.mos@dds.nl mfuchs77@googlemail.com jimp@pfsense.org</maintainer> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> <depends_on_package>squid-3.3.5.tbz</depends_on_package> @@ -1295,7 +1296,7 @@ <website>http://www.squidGuard.org/</website> <maintainer>gugabsd@mundounix.com.br</maintainer> <category>Network Management</category> - <version>1.5_1beta pkg v.1.5.6</version> + <version>1.5_1beta pkg v1.5.8</version> <status>Beta</status> <required_version>2.1</required_version> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> @@ -1337,46 +1338,6 @@ <configurationfile>squidguard.xml</configurationfile> </package> <package> - <name>Zabbix Agent</name> - <descr>Monitoring agent.</descr> - <category>Services</category> - <config_file>https://packages.pfsense.org/packages/config/zabbix-agent/zabbix-agent.xml</config_file> - <version>1.8.10,2 pkg v1.1</version> - <status>FINAL</status> - <required_version>1.2.3</required_version> - <configurationfile>zabbix-agent.xml</configurationfile> - <maintainer>remco.verhoef@redfive.biz</maintainer> - <build_port_path>/usr/ports/net-mgmt/zabbix-agent</build_port_path> - <build_pbi> - <custom_name>zabbix-agent</custom_name> - <port>net-mgmt/zabbix-agent</port> - </build_pbi> - <build_options>ca_root_nss_UNSET_FORCE=ETCSYMLINK;zabbix22_SET=LDAP SSH SQLITE;zabbix22_UNSET_FORCE=MYSQL</build_options> - <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> - <depends_on_package>zabbix-agent-1.8.10,2.tbz</depends_on_package> - <depends_on_package_pbi>zabbix-agent-1.8.13-i386.pbi</depends_on_package_pbi> - </package> - <package> - <name>Zabbix Proxy</name> - <descr>Monitoring agent proxy.</descr> - <category>Services</category> - <config_file>https://packages.pfsense.org/packages/config/zabbix-proxy/zabbix-proxy.xml</config_file> - <version>1.8.8,2 pkg v1.1</version> - <status>FINAL</status> - <required_version>1.2.3</required_version> - <configurationfile>zabbix-proxy.xml</configurationfile> - <maintainer>cmb@pfsense.org</maintainer> - <build_port_path>/usr/ports/net-mgmt/zabbix-proxy</build_port_path> - <build_pbi> - <custom_name>zabbix-proxy</custom_name> - <port>net-mgmt/zabbix-proxy</port> - </build_pbi> - <build_options>ca_root_nss_UNSET_FORCE=ETCSYMLINK;zabbix22_SET=LDAP SSH SQLITE;zabbix22_UNSET_FORCE=MYSQL</build_options> - <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> - <depends_on_package>zabbix-proxy-1.8.8,2.tbz</depends_on_package> - <depends_on_package_pbi>zabbix-proxy-1.8.13-i386.pbi</depends_on_package_pbi> - </package> - <package> <name>OpenVPN Client Export Utility</name> <descr>Allows a pre-configured OpenVPN Windows Client or Mac OS X's Viscosity configuration bundle to be exported directly from pfSense.</descr> <category>Security</category> @@ -1569,10 +1530,10 @@ </package> <package> <name>SSHDCond</name> - <descr><![CDATA[Allows to define SSH overrides for users,groups,hosts and addresses using Match in a convenient way.<br /> - This package acts as an access list frontend for ssh connections]]></descr> + <descr><![CDATA[Allows to define SSH overrides for users, groups, hosts and addresses using Match in a convenient way.<br /> + This package acts as an access list frontend for ssh connections.]]></descr> <category>Enhancements</category> - <version>1.0.5</version> + <version>1.0.6</version> <status>Beta</status> <required_version>2.0</required_version> <config_file>https://packages.pfsense.org/packages/config/sshdcond/sshdcond.xml</config_file> @@ -1706,7 +1667,7 @@ <port>security/tinc</port> </build_pbi> <build_options></build_options> - <version>1.0.23 v1.2.2</version> + <version>1.0.23 pkg v1.2.4</version> <status>ALPHA</status> <pkginfolink>https://doc.pfsense.org/index.php/tinc_package</pkginfolink> <required_version>2.1</required_version> @@ -1723,8 +1684,8 @@ <website>http://www.balabit.com/network-security/syslog-ng/</website> <descr>Syslog-ng syslog server. This service is not intended to replace the default pfSense syslog server but rather acts as an independent syslog server.</descr> <category>Services</category> - <version>3.5.4.1 pkg.v.1.0.2</version> - <status>ALPHA</status> + <version>3.5.4.1 pkg v1.1.1</version> + <status>BETA</status> <required_version>2.1</required_version> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> <depends_on_package_pbi>syslog-ng-3.5.4.1-i386.pbi</depends_on_package_pbi> @@ -1742,7 +1703,7 @@ <descr>Monitoring agent.</descr> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/zabbix2/zabbix2-agent.xml</config_file> - <version>zabbix2-agent-2.2.5 pkg v0.8.3</version> + <version>zabbix2-agent-2.2.5 pkg v0.8.4</version> <status>BETA</status> <required_version>2.0</required_version> <configurationfile>zabbix2-agent.xml</configurationfile> @@ -1760,7 +1721,7 @@ <descr>Monitoring agent proxy.</descr> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/zabbix2/zabbix2-proxy.xml</config_file> - <version>zabbix2-proxy-2.2.5 pkg v0.8.3</version> + <version>zabbix2-proxy-2.2.5 pkg v0.8.4</version> <status>BETA</status> <required_version>2.0</required_version> <configurationfile>zabbix2-proxy.xml</configurationfile> @@ -1798,7 +1759,7 @@ <pkginfolink>https://doc.pfsense.org/index.php/Sudo_Package</pkginfolink> <descr><![CDATA[sudo allows delegation of privileges to users in the shell so commands can be run as other users, such as root.]]></descr> <category>Security</category> - <version>0.2.3</version> + <version>0.2.8</version> <status>Beta</status> <required_version>2.0.2</required_version> <config_file>https://packages.pfsense.org/packages/config/sudo/sudo.xml</config_file> @@ -1881,7 +1842,7 @@ <website>http://suricata-ids.org/</website> <descr><![CDATA[High Performance Network IDS, IPS and Security Monitoring engine by OISF.]]></descr> <category>Security</category> - <version>2.0.4 pkg v2.1.4</version> + <version>2.0.4 pkg v2.1.8</version> <status>Stable</status> <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/suricata/suricata.xml</config_file> diff --git a/pkg_config.8.xml.amd64 b/pkg_config.8.xml.amd64 index cc06e096..3113d5e3 100644 --- a/pkg_config.8.xml.amd64 +++ b/pkg_config.8.xml.amd64 @@ -74,7 +74,7 @@ <category>File Management</category> <pkginfolink>https://doc.pfsense.org/index.php/Filer_package</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/filer/filer.xml</config_file> - <version>0.60.5</version> + <version>0.60.6</version> <status>Beta</status> <required_version>2.0</required_version> <maintainer>bscholer@cshl.edu</maintainer> @@ -136,9 +136,9 @@ (Legacy version)]]></descr> <website>http://haproxy.1wt.eu/</website> <category>Services</category> - <version>1.4.24 pkg v 1.1.2</version> + <version>1.4.24 pkg v 1.1.3</version> <status>Release</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/haproxy-legacy/haproxy.xml</config_file> <configurationfile>haproxy.xml</configurationfile> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> @@ -177,7 +177,7 @@ Supports ACLs for smart backend switching.]]></descr> <website>http://haproxy.1wt.eu/</website> <category>Services</category> - <version>1.5.3 pkg v 0.31</version> + <version>1.5.3 pkg v 0.33</version> <status>Release</status> <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/haproxy-devel/haproxy.xml</config_file> @@ -202,9 +202,9 @@ In addition this package allows URL forwarding which can be convenient for hosting multiple websites behind pfSense using 1 IP address.<br> <b>Backup your location config before updating from 0.2.x to 0.3 package version.</b>]]></descr> <category>Network Management</category> - <version>2.4.9 pkg v0.43</version> + <version>2.4.9 pkg v0.45</version> <status>ALPHA</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/apache_mod_security-dev/apache_virtualhost.xml</config_file> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> <depends_on_package>db42-4.2.52_5.tbz</depends_on_package> @@ -384,7 +384,7 @@ <pkginfolink/> <config_file>https://packages.pfsense.org/packages/config/tftp2/tftp.xml</config_file> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> - <version>2.1</version> + <version>2.2.2</version> <status>Stable</status> <required_version>2.0</required_version> <configurationfile>tftp.xml</configurationfile> @@ -439,8 +439,8 @@ <pkginfolink>https://doc.pfsense.org/index.php/vhosts</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/vhosts/vhosts.xml</config_file> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> - <version>0.7.5</version> - <status>Stable</status> + <version>0.8.3</version> + <status>Beta</status> <required_version>1.2.3</required_version> <maintainer>markjcrane@gmail.com</maintainer> <configurationfile>vhosts.xml</configurationfile> @@ -495,7 +495,7 @@ <website>http://www.postfix.org/</website> <descr><![CDATA[Postfix mail forwarder acts as a relay server for your domain.<br /> It can do first and second line antispam combat before sending incoming mail to local mail servers.<br /> - Postfix can also detect zombies, check RBLS, SPF, seach ldap for valid recipients and use third part antispam engines like policyd and mailscanner for better antispam solution.]]></descr> + Postfix can also detect zombies, check RBLS, SPF, seach LDAP for valid recipients and use third part antispam engines like policyd and mailscanner for better antispam solution.]]></descr> <category>Services</category> <pkginfolink>https://forum.pfsense.org/index.php/topic,40622.0.html</pkginfolink> <config_file>https://packages.pfsense.org/packages/config/postfix/postfix.xml</config_file> @@ -503,7 +503,7 @@ <depends_on_package>postfix-2.10.2,1.tbz</depends_on_package> <depends_on_package>perl5-5.16.3_4.tbz</depends_on_package> <depends_on_package_pbi>postfix-2.10.2-amd64.pbi</depends_on_package_pbi> - <version>2.10.2 pkg v.2.4.4</version> + <version>2.10.2 pkg v2.4.5</version> <status>Release</status> <required_version>2.1</required_version> <configurationfile>postfix.xml</configurationfile> @@ -613,7 +613,7 @@ <descr>High performance web proxy report (LightSquid). Proxy realtime stat (SQStat). Requires squid HTTP proxy.</descr> <website>http://lightsquid.sf.net/</website> <category>Network Report</category> - <version>2.41</version> + <version>2.42</version> <maintainer>dv_serg@mail.ru</maintainer> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> <depends_on_package>lightsquid-1.8_2.tbz</depends_on_package> @@ -631,6 +631,7 @@ <pkginfolink></pkginfolink> <configurationfile>lightsquid.xml</configurationfile> <noembedded>true</noembedded> + <after_install_info>Please visit Status - Squid Proxy Reports - Settings and read the configuration and usage instructions.</after_install_info> </package> <package> <name>Sarg</name> @@ -644,9 +645,9 @@ <depends_on_package>sarg-2.3.6_2.tbz</depends_on_package> <depends_on_package>gd-2.0.35_8,1.tbz</depends_on_package> <depends_on_package_pbi>sarg-2.3.6_2-amd64.pbi</depends_on_package_pbi> - <version>2.3.6_2 pkg v.0.6.6</version> + <version>2.3.6_2 pkg v0.6.7</version> <status>Release</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <configurationfile>sarg.xml</configurationfile> <build_port_path>/usr/ports/www/sarg</build_port_path> <build_options>sarg_UNSET_FORCE=PHP</build_options> @@ -727,7 +728,7 @@ <depends_on_package>vnstat-1.11.tbz</depends_on_package> <depends_on_package_pbi>vnstat-1.11_1-amd64.pbi</depends_on_package_pbi> <build_port_path>/usr/ports/net/vnstat</build_port_path> - <version>1.11_1,4</version> + <version>1.12.8</version> <status>Stable</status> <required_version>2.0</required_version> <maintainer>bryan.paradis@gmail.com</maintainer> @@ -756,10 +757,10 @@ <descr>pfSense version of TinyDNS which features failover host support</descr> <website>http://cr.yp.to/djbdns.html</website> <category>Services</category> - <version>1.0.6.21</version> + <version>1.0.6.24</version> <status>Beta</status> <pkginfolink>https://doc.pfsense.org/index.php/Tinydns_package</pkginfolink> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/tinydns/tinydns.xml</config_file> <configurationfile>tinydns.xml</configurationfile> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> @@ -885,7 +886,7 @@ <descr>Network UPS Tools</descr> <website>http://www.networkupstools.org/</website> <category>Network Management</category> - <version>2.6.5_1 pkg 2.1.0</version> + <version>2.6.5_1 pkg 2.1.1</version> <status>BETA</status> <required_version>2.0</required_version> <maintainer>rswagoner@gmail.com</maintainer> @@ -949,7 +950,7 @@ <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> <depends_on_package>widentd-1.03_1.tbz</depends_on_package> <depends_on_package_pbi>widentd-1.03_1-amd64.pbi</depends_on_package_pbi> - <version>1.03_1</version> + <version>1.05</version> <status>Stable</status> <pkginfolink>https://doc.pfsense.org/index.php/Widentd_package</pkginfolink> <required_version>1.2.1</required_version> @@ -989,7 +990,7 @@ On pfSense docs there is a how-to which could help you on porting users.]]></descr> <pkginfolink>https://doc.pfsense.org/index.php/FreeRADIUS_2.x_package</pkginfolink> <category>System</category> - <version>1.6.14</version> + <version>1.6.16</version> <status>RC1</status> <required_version>2.1</required_version> <maintainer>nachtfalkeaw@web.de</maintainer> @@ -1032,12 +1033,12 @@ <package> <name>stunnel</name> <website>http://www.stunnel.org/</website> - <descr>An SSL encryption wrapper between remote client and local or remote servers. </descr> + <descr>An SSL encryption wrapper between remote client and local or remote servers.</descr> <category>Network Management</category> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> <depends_on_package>stunnel-4.43.tbz</depends_on_package> <depends_on_package_pbi>stunnel-4.54-amd64.pbi</depends_on_package_pbi> - <version>4.43</version> + <version>4.54 pkg v5.20.3</version> <status>Stable</status> <pkginfolink>https://doc.pfsense.org/index.php/Stunnel_package</pkginfolink> <required_version>1.2.1</required_version> @@ -1132,9 +1133,9 @@ <pkginfolink>https://forum.pfsense.org/index.php/topic,48347.0.html</pkginfolink> <website>http://www.squid-cache.org/</website> <category>Network</category> - <version>3.1.20 pkg 2.1.3</version> + <version>3.1.20 pkg 2.1.4</version> <status>beta</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <maintainer>marcellocoutinho@gmail.com fernando@netfilter.com.br seth.mos@dds.nl mfuchs77@googlemail.com jimp@pfsense.org</maintainer> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> <depends_on_package>squid-3.1.20.tbz</depends_on_package> @@ -1165,9 +1166,9 @@ <pkginfolink>https://forum.pfsense.org/index.php/topic,48347.0.html</pkginfolink> <website>http://www.squid-cache.org/</website> <category>Network</category> - <version>3.3.10 pkg 2.3.0</version> + <version>3.3.10 pkg 2.3.1</version> <status>beta</status> - <required_version>2.0</required_version> + <required_version>2.1</required_version> <maintainer>marcellocoutinho@gmail.com fernando@netfilter.com.br seth.mos@dds.nl mfuchs77@googlemail.com jimp@pfsense.org</maintainer> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> <depends_on_package>squid-3.3.5.tbz</depends_on_package> @@ -1282,7 +1283,7 @@ <website>http://www.squidGuard.org/</website> <maintainer>gugabsd@mundounix.com.br</maintainer> <category>Network Management</category> - <version>1.5_1beta pkg v.1.5.6</version> + <version>1.5_1beta pkg v1.5.8</version> <status>Beta</status> <required_version>2.1</required_version> <depends_on_package_base_url>https://files.pfsense.org/packages/8/All/</depends_on_package_base_url> @@ -1324,46 +1325,6 @@ <configurationfile>squidguard.xml</configurationfile> </package> <package> - <name>Zabbix Agent</name> - <descr>Monitoring agent.</descr> - <category>Services</category> - <config_file>https://packages.pfsense.org/packages/config/zabbix-agent/zabbix-agent.xml</config_file> - <version>1.8.10,2 pkg v1.1</version> - <status>FINAL</status> - <required_version>1.2.3</required_version> - <configurationfile>zabbix-agent.xml</configurationfile> - <maintainer>remco.verhoef@redfive.biz</maintainer> - <build_port_path>/usr/ports/net-mgmt/zabbix-agent</build_port_path> - <build_pbi> - <custom_name>zabbix-agent</custom_name> - <port>net-mgmt/zabbix-agent</port> - </build_pbi> - <build_options>ca_root_nss_UNSET_FORCE=ETCSYMLINK;zabbix22_SET=LDAP SSH SQLITE;zabbix22_UNSET_FORCE=MYSQL</build_options> - <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> - <depends_on_package>zabbix-agent-1.8.10,2.tbz</depends_on_package> - <depends_on_package_pbi>zabbix-agent-1.8.13-amd64.pbi</depends_on_package_pbi> - </package> - <package> - <name>Zabbix Proxy</name> - <descr>Monitoring agent proxy.</descr> - <category>Services</category> - <config_file>https://packages.pfsense.org/packages/config/zabbix-proxy/zabbix-proxy.xml</config_file> - <version>1.8.8,2 pkg v1.1</version> - <status>FINAL</status> - <required_version>1.2.3</required_version> - <configurationfile>zabbix-proxy.xml</configurationfile> - <maintainer>cmb@pfsense.org</maintainer> - <build_port_path>/usr/ports/net-mgmt/zabbix-proxy</build_port_path> - <build_pbi> - <custom_name>zabbix-proxy</custom_name> - <port>net-mgmt/zabbix-proxy</port> - </build_pbi> - <build_options>ca_root_nss_UNSET_FORCE=ETCSYMLINK;zabbix22_SET=LDAP SSH SQLITE;zabbix22_UNSET_FORCE=MYSQL</build_options> - <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> - <depends_on_package>zabbix-proxy-1.8.8,2.tbz</depends_on_package> - <depends_on_package_pbi>zabbix-proxy-1.8.13-amd64.pbi</depends_on_package_pbi> - </package> - <package> <name>OpenVPN Client Export Utility</name> <descr>Allows a pre-configured OpenVPN Windows Client or Mac OSX's Viscosity configuration bundle to be exported directly from pfSense.</descr> <category>Security</category> @@ -1556,10 +1517,10 @@ </package> <package> <name>SSHDCond</name> - <descr><![CDATA[Allows to define SSH overrides for users,groups,hosts and addresses using Match in a convenient way.<br /> - This package acts as an access list frontend for ssh connections]]></descr> + <descr><![CDATA[Allows to define SSH overrides for users, groups, hosts and addresses using Match in a convenient way.<br /> + This package acts as an access list frontend for ssh connections.]]></descr> <category>Enhancements</category> - <version>1.0.5</version> + <version>1.0.6</version> <status>Beta</status> <required_version>2.0</required_version> <config_file>https://packages.pfsense.org/packages/config/sshdcond/sshdcond.xml</config_file> @@ -1693,7 +1654,7 @@ <port>security/tinc</port> </build_pbi> <build_options></build_options> - <version>1.0.23 v1.2.2</version> + <version>1.0.23 pkg v1.2.4</version> <status>ALPHA</status> <pkginfolink>https://doc.pfsense.org/index.php/tinc_package</pkginfolink> <required_version>2.1</required_version> @@ -1710,8 +1671,8 @@ <website>http://www.balabit.com/network-security/syslog-ng/</website> <descr>Syslog-ng syslog server. This service is not intended to replace the default pfSense syslog server but rather acts as an independent syslog server.</descr> <category>Services</category> - <version>3.5.4.1 pkg.v.1.0.2</version> - <status>ALPHA</status> + <version>3.5.4.1 pkg v1.1.1</version> + <status>BETA</status> <required_version>2.1</required_version> <depends_on_package_base_url>https://files.pfsense.org/packages/amd64/8/All/</depends_on_package_base_url> <depends_on_package_pbi>syslog-ng-3.5.4.1-amd64.pbi</depends_on_package_pbi> @@ -1729,7 +1690,7 @@ <descr>Monitoring agent.</descr> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/zabbix2/zabbix2-agent.xml</config_file> - <version>zabbix2-agent-2.2.5 pkg v0.8.3</version> + <version>zabbix2-agent-2.2.5 pkg v0.8.4</version> <status>BETA</status> <required_version>2.0</required_version> <configurationfile>zabbix2-agent.xml</configurationfile> @@ -1747,7 +1708,7 @@ <descr>Monitoring agent proxy.</descr> <category>Services</category> <config_file>https://packages.pfsense.org/packages/config/zabbix2/zabbix2-proxy.xml</config_file> - <version>zabbix2-proxy-2.2.5 pkg v0.8.3</version> + <version>zabbix2-proxy-2.2.5 pkg v0.8.4</version> <status>BETA</status> <required_version>2.0</required_version> <configurationfile>zabbix2-proxy.xml</configurationfile> @@ -1785,7 +1746,7 @@ <pkginfolink>https://doc.pfsense.org/index.php/Sudo_Package</pkginfolink> <descr><![CDATA[sudo allows delegation of privileges to users in the shell so commands can be run as other users, such as root.]]></descr> <category>Security</category> - <version>0.2.3</version> + <version>0.2.8</version> <status>Beta</status> <required_version>2.0.2</required_version> <config_file>https://packages.pfsense.org/packages/config/sudo/sudo.xml</config_file> @@ -1868,7 +1829,7 @@ <website>http://suricata-ids.org/</website> <descr><![CDATA[High Performance Network IDS, IPS and Security Monitoring engine by OISF.]]></descr> <category>Security</category> - <version>2.0.4 pkg v2.1.4</version> + <version>2.0.4 pkg v2.1.8</version> <status>Stable</status> <required_version>2.1</required_version> <config_file>https://packages.pfsense.org/packages/config/suricata/suricata.xml</config_file> |