diff options
author | Renato Botelho <renato@netgate.com> | 2015-08-25 08:08:24 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2015-08-25 14:49:54 -0300 |
commit | 46bc6e545a17e77202aaf01ec0cd8d5a46567525 (patch) | |
tree | 32d18dda436ec739c67c489ceb771e8629cd926f /src/etc/rc.filter_synchronize | |
parent | 4d9801c2dbd2b3e54a39578ee62b93af66607227 (diff) | |
download | pfsense-46bc6e545a17e77202aaf01ec0cd8d5a46567525.zip pfsense-46bc6e545a17e77202aaf01ec0cd8d5a46567525.tar.gz |
Move main pfSense content to src/
Diffstat (limited to 'src/etc/rc.filter_synchronize')
-rwxr-xr-x | src/etc/rc.filter_synchronize | 488 |
1 files changed, 488 insertions, 0 deletions
diff --git a/src/etc/rc.filter_synchronize b/src/etc/rc.filter_synchronize new file mode 100755 index 0000000..f31fa34 --- /dev/null +++ b/src/etc/rc.filter_synchronize @@ -0,0 +1,488 @@ +#!/usr/local/bin/php-cgi -f +<?php +/* + rc.filter_synchronize + Copyright (C) 2004-2006 Scott Ullrich + Copyright (C) 2005 Bill Marquette + Copyright (C) 2006 Peter Allgeyer + Copyright (C) 2008 Ermal Luçi + All rights reserved. + + originally part of m0n0wall (http://m0n0.ch/wall) + Copyright (C) 2003-2004 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: + + 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("globals.inc"); +require_once("config.inc"); +require_once("functions.inc"); +require_once("filter.inc"); +require_once("shaper.inc"); +require_once("xmlrpc.inc"); +require_once("interfaces.inc"); + +/* + * backup_vip_config_section($section): returns as an xml file string of + * the configuration section + */ +function backup_vip_config_section() { + global $config; + + if (!is_array($config['virtualip']['vip'])) { + return; + } + $temp = array(); + $temp['vip'] = array(); + foreach ($config['virtualip']['vip'] as $section) { + if (($section['mode'] == 'proxyarp' || $section['mode'] == 'ipalias') && + (strpos($section['interface'], '_vip') === FALSE) && + (strpos($section['interface'], 'lo0') === FALSE)) { + continue; + } + if ($section['advskew'] <> "") { + $section_val = intval($section['advskew']); + $section_val=$section_val+100; + if ($section_val > 254) { + $section_val = 254; + } + $section['advskew'] = $section_val; + } + if ($section['advbase'] <> "") { + $section_val = intval($section['advbase']); + if ($section_val > 254) { + $section_val = 254; + } + $section['advbase'] = $section_val; + } + $temp['vip'][] = $section; + } + return $temp; +} + +function remove_special_characters($string) { + $match_array = ""; + preg_match_all("/[a-zA-Z0-9\_\-]+/", $string, $match_array); + $string = ""; + foreach ($match_array[0] as $ma) { + if ($string <> "") { + $string .= " "; + } + $string .= $ma; + } + return $string; +} + +function carp_check_version($url, $username, $password, $port = 80, $method = 'pfsense.host_firmware_version') { + global $config, $g; + + if (file_exists("{$g['varrun_path']}/booting") || platform_booting()) { + return; + } + + $params = array( + XML_RPC_encode($password) + ); + + $numberofruns = 0; + while ($numberofruns < 2) { + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials($username, $password); + if ($numberofruns > 0) { + $cli->setDebug(1); + } + /* send our XMLRPC message and timeout after 240 seconds */ + $resp = $cli->send($msg, "240"); + if (!is_object($resp)) { + $error = "A communications error occurred while attempting XMLRPC sync with username {$username} {$url}:{$port}."; + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting XMLRPC sync with username {$username} {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + } else { + $parsed_response = XML_RPC_decode($resp->value()); + if (!is_array($parsed_response)) { + if (trim($parsed_response) == "Authentication failed") { + $error = "An authentication failure occurred while trying to access {$url}:{$port} ({$method})."; + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + return false; + } + } else { + if (!isset($parsed_response['config_version']) || + ($parsed_response['config_version'] < $config['version']) || + ($parsed_response['config_version'] > $config['version'])) { + update_filter_reload_status("The other member is on a different configuration version of {$g['product_name']}. Sync will not be done to prevent problems!"); + log_error("The other member is on a different configuration version of {$g['product_name']}. Sync will not be done to prevent problems!"); + return false; + } else { + return true; + } + } + } + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + $numberofruns++; + } + + return false; +} + +function carp_sync_xml($url, $username, $password, $sections, $port = 80, $method = 'pfsense.restore_config_section') { + global $config, $g; + + if (file_exists("{$g['varrun_path']}/booting") || platform_booting()) { + return; + } + + update_filter_reload_status("Syncing CARP data to {$url}"); + + /* make a copy of config */ + $config_copy = $config; + + /* strip out nosync items */ + if (is_array($config_copy['nat']['outbound']['rule'])) { + $rulescnt = count($config_copy['nat']['outbound']['rule']); + for ($x = 0; $x < $rulescnt; $x++) { + $config_copy['nat']['outbound']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['outbound']['rule'][$x]['descr']); + if (isset ($config_copy['nat']['outbound']['rule'][$x]['nosync'])) { + unset ($config_copy['nat']['outbound']['rule'][$x]); + } + } + } + if (is_array($config_copy['nat']['rule'])) { + $natcnt = count($config_copy['nat']['rule']); + for ($x = 0; $x < $natcnt; $x++) { + $config_copy['nat']['rule'][$x]['descr'] = remove_special_characters($config_copy['nat']['rule'][$x]['descr']); + if (isset ($config_copy['nat']['rule'][$x]['nosync'])) { + unset ($config_copy['nat']['rule'][$x]); + } + } + } + if (is_array($config_copy['filter']['rule'])) { + $filtercnt = count($config_copy['filter']['rule']); + for ($x = 0; $x < $filtercnt; $x++) { + $config_copy['filter']['rule'][$x]['descr'] = remove_special_characters($config_copy['filter']['rule'][$x]['descr']); + if (isset ($config_copy['filter']['rule'][$x]['nosync'])) { + unset ($config_copy['filter']['rule'][$x]); + } + } + } + if (is_array($config_copy['aliases']['alias'])) { + $aliascnt = count($config_copy['aliases']['alias']); + for ($x = 0; $x < $aliascnt; $x++) { + $config_copy['aliases']['alias'][$x]['descr'] = remove_special_characters($config_copy['aliases']['alias'][$x]['descr']); + if (isset ($config_copy['aliases']['alias'][$x]['nosync'])) { + unset ($config_copy['aliases']['alias'][$x]); + } + } + } + if (is_array($config_copy['dnsmasq']['hosts'])) { + $dnscnt = count($config_copy['dnsmasq']['hosts']); + for ($x = 0; $x < $dnscnt; $x++) { + $config_copy['dnsmasq']['hosts'][$x]['descr'] = remove_special_characters($config_copy['dnsmasq']['hosts'][$x]['descr']); + if (isset ($config_copy['dnsmasq']['hosts'][$x]['nosync'])) { + unset ($config_copy['dnsmasq']['hosts'][$x]); + } + } + } + if (is_array($config_copy['ipsec']['tunnel'])) { + $ipseccnt = count($config_copy['ipsec']['tunnel']); + for ($x = 0; $x < $ipseccnt; $x++) { + $config_copy['ipsec']['tunnel'][$x]['descr'] = remove_special_characters($config_copy['ipsec']['tunnel'][$x]['descr']); + if (isset ($config_copy['ipsec']['tunnel'][$x]['nosync'])) { + unset ($config_copy['ipsec']['tunnel'][$x]); + } + } + } + + if (is_array($config_copy['dhcpd'])) { + foreach ($config_copy['dhcpd'] as $dhcpif => $dhcpifconf) { + if ($dhcpifconf['failover_peerip'] <> "") { + $int = guess_interface_from_ip($dhcpifconf['failover_peerip']); + $intip = find_interface_ip($int); + $config_copy['dhcpd'][$dhcpif]['failover_peerip'] = $intip; + } + } + } + + foreach ($sections as $section) { + /* we can't use array_intersect_key() + * due to the vip 'special case' + */ + switch ($section) { + case 'virtualip': + $xml[$section] = backup_vip_config_section(); + break; + case 'user': + $xml['system'][$section] = $config_copy['system'][$section]; + $xml['system']['nextuid'] = $config_copy['system']['nextuid']; + break; + case 'group': + $xml['system'][$section] = $config_copy['system'][$section]; + $xml['system']['nextgid'] = $config_copy['system']['nextgid']; + break; + case 'authserver': + $xml['system'][$section] = $config_copy['system'][$section]; + default: + $xml[$section] = $config_copy[$section]; + } + } + + $params = array( + XML_RPC_encode($password), + XML_RPC_encode($xml) + ); + + $numberofruns = 0; + while ($numberofruns < 2) { + log_error("Beginning XMLRPC sync to {$url}:{$port}."); + $msg = new XML_RPC_Message($method, $params); + $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port); + $cli->setCredentials($username, $password); + if ($numberofruns > 0) { + $cli->setDebug(1); + } + /* send our XMLRPC message and timeout after 240 seconds */ + $resp = $cli->send($msg, "240"); + if (!is_object($resp)) { + $error = "A communications error occurred while attempting XMLRPC sync with username {$username} {$url}:{$port}."; + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting XMLRPC sync with username {$username} {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + } else { + $parsed_response = XML_RPC_decode($resp->value()); + if (!is_array($parsed_response) && trim($parsed_response) == "Authentication failed") { + $error = "An authentication failure occurred while trying to access {$url}:{$port} ($method)."; + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + return -1; + } else { + log_error("XMLRPC sync successfully completed with {$url}:{$port}."); + update_filter_reload_status("XMLRPC sync successfully completed with {$url}:{$port}."); + } + $numberofruns = 3; + } + $numberofruns++; + } +} + +if (platform_booting()) { + return; +} + +if (is_array($config['hasync'])) { + update_filter_reload_status("Building high availability sync information"); + $hasync = $config['hasync']; + + if (empty($hasync['synchronizetoip'])) { + /* this gets hit on every filter sync on the secondary, a log here creates a lot of log spam and I never saw it actually log anything useful */ + return; + } + + /* + * XXX: The way we're finding the port right now is really suboptimal - + * we can't assume that the other machine is setup identically. + */ + if (!empty($config['system']['webgui']['protocol'])) { + $synchronizetoip = $config['system']['webgui']['protocol']; + $synchronizetoip .= "://"; + } + + /* if port is empty lets rely on the protocol selection */ + $port = $config['system']['webgui']['port']; + if (empty($port)) { + if ($config['system']['webgui']['protocol'] == "http") { + $port = "80"; + } else { + $port = "443"; + } + } + + if (is_ipaddrv6($hasync['synchronizetoip'])) { + $hasync['synchronizetoip'] = "[{$hasync['synchronizetoip']}]"; + } + $synchronizetoip .= $hasync['synchronizetoip']; + if ($hasync['synchronizerules'] != "") { + if (!is_array($config['filter'])) { + $config['filter'] = array(); + } + $sections[] = 'filter'; + } + if ($hasync['synchronizenat'] != "") { + if (!is_array($config['nat'])) { + $config['nat'] = array(); + } + $sections[] = 'nat'; + } + if ($hasync['synchronizealiases'] != "") { + if (!is_array($config['aliases'])) { + $config['aliases'] = array(); + } + $sections[] = 'aliases'; + } + if ($hasync['synchronizedhcpd'] != "" and is_array($config['dhcpd'])) { + $sections[] = 'dhcpd'; + } + if ($hasync['synchronizewol'] != "") { + if (!is_array($config['wol'])) { + $config['wol'] = array(); + } + $sections[] = 'wol'; + } + if ($hasync['synchronizetrafficshaper'] != "" and is_array($config['shaper'])) { + $sections[] = 'shaper'; + } + if ($hasync['synchronizetrafficshaperlimiter'] != "" and is_array($config['dnshaper'])) { + $sections[] = 'dnshaper'; + } + if ($hasync['synchronizetrafficshaperlayer7'] != "" and is_array($config['l7shaper'])) { + $sections[] = 'l7shaper'; + } + if ($hasync['synchronizestaticroutes'] != "") { + if (!is_array($config['staticroutes'])) { + $config['staticroutes'] = array(); + } + if (!is_array($config['staticroutes']['route'])) { + $config['staticroutes']['route'] = array(); + } + $sections[] = 'staticroutes'; + if (!is_array($config['gateways'])) { + $config['gateways'] = array(); + } + $sections[] = 'gateways'; + } + if ($hasync['synchronizevirtualip'] != "") { + if (!is_array($config['virtualip'])) { + $config['virtualip'] = array(); + } + $sections[] = 'virtualip'; + } + if ($hasync['synchronizelb'] != "") { + if (!is_array($config['load_balancer'])) { + $config['load_balancer'] = array(); + } + $sections[] = 'load_balancer'; + } + if ($hasync['synchronizeipsec'] != "") { + if (!is_array($config['ipsec'])) { + $config['ipsec'] = array(); + } + $sections[] = 'ipsec'; + } + if ($hasync['synchronizeopenvpn'] != "") { + if (!is_array($config['openvpn'])) { + $config['openvpn'] = array(); + } + $sections[] = 'openvpn'; + } + if ($hasync['synchronizecerts'] != "" || $hasync['synchronizeopenvpn'] != "") { + if (!is_array($config['cert'])) { + $config['cert'] = array(); + } + $sections[] = 'cert'; + + if (!is_array($config['ca'])) { + $config['ca'] = array(); + } + $sections[] = 'ca'; + + if (!is_array($config['crl'])) { + $config['crl'] = array(); + } + $sections[] = 'crl'; + } + if ($hasync['synchronizeusers'] != "") { + $sections[] = 'user'; + $sections[] = 'group'; + } + if ($hasync['synchronizeauthservers'] != "") { + $sections[] = 'authserver'; + } + if ($hasync['synchronizednsforwarder'] != "") { + if (is_array($config['dnsmasq'])) { + $sections[] = 'dnsmasq'; + } + if (is_array($config['unbound'])) { + $sections[] = 'unbound'; + } + } + if ($hasync['synchronizeschedules'] != "" || $hasync['synchronizerules'] != "") { + if (!is_array($config['schedules'])) { + $config['schedules'] = array(); + } + $sections[] = 'schedules'; + } + if ($hasync['synchronizecaptiveportal'] != "" and is_array($config['captiveportal'])) { + $sections[] = 'captiveportal'; + } + if ($hasync['synchronizecaptiveportal'] != "" and is_array($config['vouchers'])) { + $sections[] = 'vouchers'; + } + + if (count($sections) <= 0) { + log_error("Nothing has been configured to be synched. Skipping...."); + return; + } + + if (empty($hasync['username'])) { + $username = "admin"; + } else { + $username = $hasync['username']; + } + + if (!carp_check_version($synchronizetoip, $username, $hasync['password'], $port)) { + return; + } + + update_filter_reload_status("Signaling CARP reload signal..."); + if (carp_sync_xml($synchronizetoip, $username, $hasync['password'], $sections, $port) == -1) { + return; + } + $cli = new XML_RPC_Client('/xmlrpc.php', $synchronizetoip, $port); + $params = array( + XML_RPC_encode($hasync['password']) + ); + + $msg = new XML_RPC_Message('pfsense.filter_configure', $params); + $cli->setCredentials($username, $hasync['password']); + $resp = $cli->send($msg, "900"); + + if (!is_object($resp)) { + $error = "A communications error occurred while attempting Filter sync with username {$username} {$synchronizetoip}:{$port}."; + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + } elseif ($resp->faultCode()) { + $error = "An error code was received while attempting Filter sync with username {$username} {$synchronizetoip}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString(); + log_error($error); + file_notice("sync_settings", $error, "Settings Sync", ""); + } else { + log_error("Filter sync successfully completed with {$synchronizetoip}:{$port}."); + $numberofruns = 3; + } +} + +?> |