"*/" . $matches[1], "hour" => "*", "mday" => "*", "month" => "*", "wday" => "*", "who" => "root", "command" => $cron_cmd . " " . $sarg_schedule_id); $config['cron'] = $new_cron; $cron_found++; } if (preg_match('/(\d+)h/', $sarg_schedule['frequency'], $matches) && $sarg_schedule['enable']) { $new_cron['item'][] = array("minute" => "0", "hour" => "*/" . $matches[1], "mday" => "*", "month" => "*", "wday" => "*", "who" => "root", "command" => $cron_cmd . " " . $sarg_schedule_id); $config['cron'] = $new_cron; $cron_found++; } if (preg_match('/(\d+)d/', $sarg_schedule['frequency'], $matches) && $sarg_schedule['enable']) { $new_cron['item'][] = array("minute" => "0", "hour" => "0", "mday" => "*/" . $matches[1], "month" => "*", "wday" => "*", "who" => "root", "command"=> $cron_cmd . " " . $sarg_schedule_id); $config['cron']=$new_cron; $cron_found++; } $sarg_schedule_id++; } } // update cron if ($cron_found > 0) { $config['cron'] = $new_cron; write_config(); configure_cron(); } } } function sarg_package_install() { sarg_check_dirs(); } function sarg_resync() { global $config; if (($_POST['Submit'] == 'Save') || !isset($_POST['Submit'])) { sync_package_sarg(); } if ($_POST['Submit'] == 'Force update now') { run_sarg(); } } function run_sarg($id = -1) { global $config, $g, $sarg_proxy; // mount filesystem writeable conf_mount_rw(); $cmd = SARG_DIR . "/bin/sarg"; if ($id >= 0 && is_array($config['installedpackages']['sargschedule']['config'])) { $args = $config['installedpackages']['sargschedule']['config'][$id]['args']; $gzip = $config['installedpackages']['sargschedule']['config'][$id]['gzip']; $find = $config['installedpackages']['sargschedule']['config'][$id]['find']; $gziplevel = $config['installedpackages']['sargschedule']['config'][$id]['gziplevel']; $daylimit = $config['installedpackages']['sargschedule']['config'][$id]['daylimit']; } else { $args = $_POST['args']; $gzip = $_POST['gzip']; $find = $_POST['find']; $gziplevel = $_POST['gziplevel']; $daylimit = ""; } $find = (preg_match("/(\d+)/", $find, $find_matches) ? $find_matches[1] : "60"); log_error("[sarg] Force refresh now with {$args} args, compress({$gzip})."); $gzip_script = "#!/bin/sh\n"; if ($gzip == "on") { // remove old file if exists unlink_if_exists("/root/sarg_run_{$id}.sh"); $gzip_script .= << 0) { write_config(); } // mount filesystem readonly conf_mount_ro(); sarg_sync_on_changes(); } function sarg_validate_input($post, &$input_errors) { global $config, $g; foreach ($post as $key => $value) { if (empty($value)) { continue; } // check dansguardian if (substr($key, 0, 12) == "proxy_server" && $value == "dansguardian") { if (is_array($config['installedpackages']['dansguardianlog'])) { if ($config['installedpackages']['dansguardianlog']['config'][0]['logfileformat'] != 3) { $input_errors[] = 'Sarg is only compatible with dansguardian squid mode log'; $input_errors[] = 'Please change it on Services -> Dansguardian -> Report and log -> Log file format'; } } else { $input_errors[]='DansGuardian package is not installed'; } } # check squidguard if (substr($key, 0, 10) == "proxy_server" && $value == "squidguard") if (!is_array($config['installedpackages']['squidguardgeneral'])) $input_errors[]='SquidGuard package is not installed'; # 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[]='Squid logging is not enabled'; } } else { $input_errors[]='Squid package is not installed'; } } if (substr($key, 0, 11) == "description" && !preg_match("@^[a-zA-Z0-9 _/.-]+$@", $value)) { $input_errors[] = "Do not use special characters in description"; } if (substr($key, 0, 8) == "fullfile" && !preg_match("@^[a-zA-Z0-9_/.-]+$@", $value)) { $input_errors[] = "Do not use special characters in filename"; } // check cron option if ($key == "frequency" && (!preg_match("/^\d+(h|m|d)$/", $value) || $value == 0)) { $input_errors[] = "A valid number with a time reference is required for the field 'Update Frequency'"; } } } /* 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'] ?: '250'; switch ($synconchanges) { case "manual": if (is_array($sarg_sync['row'])) { $rs = $sarg_sync['row']; } else { log_error("[sarg] 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("[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 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("[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 completed."); } } } /* do the actual XMLRPC sync */ function sarg_do_xmlrpc_sync($sync_to_ip, $port, $protocol, $username, $password, $synctimeout) { global $config, $g; 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; } // Take care of IPv6 literal address if (is_ipaddrv6($sync_to_ip)) { $sync_to_ip = "[{$sync_to_ip}]"; } $url = "{$protocol}://{$sync_to_ip}"; /* 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 */ $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("[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 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}."); } /* 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)); $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("[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 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)."); } } ?>