diff options
Diffstat (limited to 'config/suricata')
38 files changed, 4661 insertions, 2057 deletions
diff --git a/config/suricata/suricata.inc b/config/suricata/suricata.inc index b87e2f6a..c767f2d0 100644 --- a/config/suricata/suricata.inc +++ b/config/suricata/suricata.inc @@ -1,30 +1,41 @@ <?php /* - suricata.inc - - Copyright (C) 2014 Bill Meeks - 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. + * suricata.inc + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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("pfsense-utils.inc"); require_once("config.inc"); @@ -39,6 +50,15 @@ global $g, $config; if (!is_array($config['installedpackages']['suricata'])) $config['installedpackages']['suricata'] = array(); +/* Get installed package version for display */ +$suricata_package_version = "Suricata {$config['installedpackages']['package'][get_pkg_id("suricata")]['version']}"; + +// Define the installed package version +define('SURICATA_PKG_VER', $suricata_package_version); + +// Define the name of the pf table used for IP blocks +define('SURICATA_PF_TABLE', 'snort2c'); + // Create some other useful defines define('SURICATADIR', '/usr/pbi/suricata-' . php_uname("m") . '/etc/suricata/'); define('SURICATALOGDIR', '/var/log/suricata/'); @@ -73,16 +93,12 @@ function suricata_generate_id() { } function suricata_is_running($suricata_uuid, $if_real, $type = 'suricata') { - global $config, $g; - - if (isvalidpid("{$g['varrun_path']}/{$type}_{$if_real}{$suricata_uuid}.pid")) - return 'yes'; - else - return 'no'; + global $g; + return isvalidpid("{$g['varrun_path']}/{$type}_{$if_real}{$suricata_uuid}.pid"); } function suricata_barnyard_stop($suricatacfg, $if_real) { - global $config, $g; + global $g; $suricata_uuid = $suricatacfg['uuid']; if (isvalidpid("{$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid")) { @@ -92,13 +108,13 @@ function suricata_barnyard_stop($suricatacfg, $if_real) { } function suricata_stop($suricatacfg, $if_real) { - global $config, $g; + global $g; $suricata_uuid = $suricatacfg['uuid']; if (isvalidpid("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid")) { log_error("[Suricata] Suricata STOP for {$suricatacfg['descr']}({$if_real})..."); killbypid("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid"); - sleep(2); + sleep(1); // For some reason Suricata seems to need a double TERM signal to actually shutdown if (isvalidpid("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid")) @@ -109,7 +125,7 @@ function suricata_stop($suricatacfg, $if_real) { } function suricata_barnyard_start($suricatacfg, $if_real) { - global $config, $g; + global $g; $suricata_uuid = $suricatacfg['uuid']; $suricatadir = SURICATADIR . "suricata_{$suricata_uuid}_{$if_real}"; @@ -117,19 +133,19 @@ function suricata_barnyard_start($suricatacfg, $if_real) { if ($suricatacfg['barnyard_enable'] == 'on') { log_error("[Suricata] Barnyard2 START for {$suricatacfg['descr']}({$if_real})..."); - exec("/usr/local/bin/barnyard2 -r {$suricata_uuid} -f unified2.alert --pid-path {$g['varrun_path']} --nolock-pidfile -c {$suricatadir}/barnyard2.conf -d {$suricatalogdir} -D -q"); + mwexec_bg("/usr/local/bin/barnyard2 -r {$suricata_uuid} -f unified2.alert --pid-path {$g['varrun_path']} --nolock-pidfile -c {$suricatadir}/barnyard2.conf -d {$suricatalogdir} -D -q"); } } function suricata_start($suricatacfg, $if_real) { - global $config, $g; + global $g; $suricatadir = SURICATADIR; $suricata_uuid = $suricatacfg['uuid']; if ($suricatacfg['enable'] == 'on') { log_error("[Suricata] Suricata START for {$suricatacfg['descr']}({$if_real})..."); - exec("/usr/local/bin/suricata -i {$if_real} -D -c {$suricatadir}suricata_{$suricata_uuid}_{$if_real}/suricata.yaml --pidfile {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid"); + mwexec_bg("/usr/local/bin/suricata -i {$if_real} -D -c {$suricatadir}suricata_{$suricata_uuid}_{$if_real}/suricata.yaml --pidfile {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid"); } else return; @@ -150,11 +166,11 @@ function suricata_reload_config($suricatacfg, $signal="USR2") { /* */ /* $signal = USR2 (default) parses and reloads config. */ /**************************************************************/ - global $config, $g; + global $g; $suricatadir = SURICATADIR; $suricata_uuid = $suricatacfg['uuid']; - $if_real = suricata_get_real_interface($suricatacfg['interface']); + $if_real = get_real_interface($suricatacfg['interface']); /******************************************************/ /* Only send the SIGUSR2 if Suricata is running and */ @@ -162,8 +178,8 @@ function suricata_reload_config($suricatacfg, $signal="USR2") { /******************************************************/ if (isvalidpid("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid")) { log_error("[Suricata] Suricata LIVE RULE RELOAD initiated for {$suricatacfg['descr']} ({$if_real})..."); - sigkillbypid("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid", $signal); -// exec("/bin/pkill -{$signal} -F {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid 2>&1 &"); +// sigkillbypid("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid", $signal); + mwexec_bg("/bin/pkill -{$signal} -F {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid"); } } @@ -179,11 +195,11 @@ function suricata_barnyard_reload_config($suricatacfg, $signal="HUP") { /* */ /* $signal = HUP (default) parses and reloads config. */ /**************************************************************/ - global $config, $g; + global $g; $suricatadir = SURICATADIR; $suricata_uuid = $suricatacfg['uuid']; - $if_real = suricata_get_real_interface($suricatacfg['interface']); + $if_real = get_real_interface($suricatacfg['interface']); /******************************************************/ /* Only send the SIGHUP if Barnyard2 is running and */ @@ -191,36 +207,33 @@ function suricata_barnyard_reload_config($suricatacfg, $signal="HUP") { /******************************************************/ if (isvalidpid("{$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid")) { log_error("[Suricata] Barnyard2 CONFIG RELOAD initiated for {$suricatacfg['descr']} ({$if_real})..."); - sigkillbypid("{$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid", $signal); -// exec("/bin/pkill -{$signal} -F {$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid 2>&1 &"); +// sigkillbypid("{$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid", $signal); + mwexec_bg("/bin/pkill -{$signal} -F {$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid"); } } -function suricata_get_friendly_interface($interface) { - - // Pass this directly to the system for now. - // Later, this wrapper will be removed and all - // the Suricata code changed to use the system call. - return convert_friendly_interface_to_friendly_descr($interface); -} - -function suricata_get_real_interface($interface) { +function suricata_get_blocked_ips() { - // Pass this directly to the system for now. - // Later, this wrapper will be removed and all - // the Suricata code changed to use the system call. - return get_real_interface($interface); -} + $suri_pf_table = SURICATA_PF_TABLE; + $blocked_ips = ""; -function suricata_get_blocked_ips() { + exec("/sbin/pfctl -t {$suri_pf_table} -T show", $blocked_ips); - // This is a placeholder function for later use. - // Blocking is not currently enabled in Suricata. - return array(); + $blocked_ips_array = array(); + if (!empty($blocked_ips)) { + if (is_array($blocked_ips)) { + foreach ($blocked_ips as $blocked_ip) { + if (empty($blocked_ip)) + continue; + $blocked_ips_array[] = trim($blocked_ip, " \n\t"); + } + } + } + return $blocked_ips_array; } -/* func builds custom white lists */ -function suricata_find_list($find_name, $type = 'whitelist') { +/* func builds custom Pass Lists */ +function suricata_find_list($find_name, $type = 'passlist') { global $config; $suricataglob = $config['installedpackages']['suricata']; @@ -237,11 +250,11 @@ function suricata_find_list($find_name, $type = 'whitelist') { return array(); } -function suricata_build_list($suricatacfg, $listname = "", $whitelist = false) { +function suricata_build_list($suricatacfg, $listname = "", $passlist = false) { /***********************************************************/ /* The default is to build a HOME_NET variable unless */ - /* '$whitelist' is set to 'true' when calling. */ + /* '$passlist' is set to 'true' when calling. */ /***********************************************************/ global $config, $g, $aliastable, $filterdns; @@ -263,7 +276,7 @@ function suricata_build_list($suricatacfg, $listname = "", $whitelist = false) { $home_net = explode(" ", trim(filter_expand_alias($list['address']))); } - // Always add loopback to HOME_NET and whitelist (ftphelper) + // Always add loopback to HOME_NET and passlist (ftphelper) if (!in_array("127.0.0.1", $home_net)) $home_net[] = "127.0.0.1"; @@ -271,8 +284,8 @@ function suricata_build_list($suricatacfg, $listname = "", $whitelist = false) { /* Always put the interface running Suricata in HOME_NET and */ /* whitelist unless it's the WAN. WAN options are handled further */ /* down. If the user specifically chose not to include LOCAL_NETS */ - /* in the WHITELIST, then do not include the Suricata interface */ - /* subnet in the WHITELIST. We do include the actual LAN interface */ + /* in the PASS LIST, then do not include the Suricata interface */ + /* subnet in the PASS LIST. We do include the actual LAN interface */ /* IP for Suricata, though, to prevent locking out the firewall. */ /********************************************************************/ $suricataip = get_interface_ip($suricatacfg['interface']); @@ -313,8 +326,8 @@ function suricata_build_list($suricatacfg, $listname = "", $whitelist = false) { if (!$whitelist || $localnet == 'yes' || empty($localnet)) { /*************************************************************************/ - /* Iterate through the interface list and write out whitelist items and */ - /* also compile a HOME_NET list of all the local interfaces for suricata. */ + /* Iterate through the interface list and write out pass list items and */ + /* also compile a HOME_NET list of all local interfaces for suricata. */ /* Skip the WAN interface as we do not typically want that whole subnet */ /* whitelisted (just the i/f IP itself which was handled earlier). */ /*************************************************************************/ @@ -381,7 +394,7 @@ function suricata_build_list($suricatacfg, $listname = "", $whitelist = false) { } if($vips == 'yes') { - // iterate all vips and add to whitelist + // iterate all vips and add to passlist if (is_array($config['virtualip']) && is_array($config['virtualip']['vip'])) { foreach($config['virtualip']['vip'] as $vip) { if ($vip['subnet'] && $vip['mode'] != 'proxyarp') { @@ -422,7 +435,7 @@ function suricata_build_list($suricatacfg, $listname = "", $whitelist = false) { return $valresult; } -function suricata_rules_up_install_cron($should_install) { +function suricata_rules_up_install_cron($should_install=true) { global $config, $g; $command = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/www/suricata/suricata_check_for_rule_updates.php"; @@ -495,11 +508,109 @@ function suricata_rules_up_install_cron($should_install) { install_cron_job($command, $should_install, $suricata_rules_up_min, $suricata_rules_up_hr, $suricata_rules_up_mday, $suricata_rules_up_month, $suricata_rules_up_wday, "root"); } -function suricata_loglimit_install_cron($should_install) { +function suricata_loglimit_install_cron($should_install=true) { install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_check_cron_misc.inc", $should_install, "*/5"); } +function suricata_rm_blocked_install_cron($should_install) { + global $config, $g; + $suri_pf_table = SURICATA_PF_TABLE; + + $suricata_rm_blocked_info_ck = $config['installedpackages']['suricata']['config'][0]['rm_blocked']; + + if ($suricata_rm_blocked_info_ck == "15m_b") { + $suricata_rm_blocked_min = "*/1"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "900"; + } + if ($suricata_rm_blocked_info_ck == "30m_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "1800"; + } + if ($suricata_rm_blocked_info_ck == "1h_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "3600"; + } + if ($suricata_rm_blocked_info_ck == "3h_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "10800"; + } + if ($suricata_rm_blocked_info_ck == "6h_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "21600"; + } + if ($suricata_rm_blocked_info_ck == "12h_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "43200"; + } + if ($suricata_rm_blocked_info_ck == "1d_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "86400"; + } + if ($suricata_rm_blocked_info_ck == "4d_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "345600"; + } + if ($suricata_rm_blocked_info_ck == "7d_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "604800"; + } + if ($suricata_rm_blocked_info_ck == "28d_b") { + $suricata_rm_blocked_min = "*/5"; + $suricata_rm_blocked_hr = "*"; + $suricata_rm_blocked_mday = "*"; + $suricata_rm_blocked_month = "*"; + $suricata_rm_blocked_wday = "*"; + $suricata_rm_blocked_expire = "2419200"; + } + + // First, remove any existing cron task for "rm_blocked" hosts + install_cron_job("pfctl -t {$suri_pf_table} -T expire" , false); + + // Now add or update the cron task for "rm_blocked" hosts + // if enabled. + if ($should_install) { + $command = "/usr/bin/nice -n20 /sbin/pfctl -t {$suri_pf_table} -T expire {$suricata_rm_blocked_expire}"; + install_cron_job($command, $should_install, $suricata_rm_blocked_min, $suricata_rm_blocked_hr, $suricata_rm_blocked_mday, $suricata_rm_blocked_month, $suricata_rm_blocked_wday, "root"); + } +} + function sync_suricata_package_config() { global $config, $g; @@ -517,7 +628,7 @@ function sync_suricata_package_config() { $suricataconf = $config['installedpackages']['suricata']['rule']; foreach ($suricataconf as $value) { - $if_real = suricata_get_real_interface($value['interface']); + $if_real = get_real_interface($value['interface']); // create a suricata.yaml file for interface suricata_generate_yaml($value); @@ -532,9 +643,11 @@ function sync_suricata_package_config() { $suricataglob = $config['installedpackages']['suricata']['config'][0]; // setup the log directory size check job if enabled - suricata_loglimit_install_cron($suricataglob['suricataloglimit'] == 'on' ? true : false); + suricata_loglimit_install_cron(true); // setup the suricata rules update job if enabled - suricata_rules_up_install_cron($suricataglob['autoruleupdate'] != "never_up" ? true : false); + suricata_rules_up_install_cron($config['installedpackages']['suricata']['config'][0]['autoruleupdate'] != "never_up" ? true : false); + // set the suricata blocked hosts time + suricata_rm_blocked_install_cron($config['installedpackages']['suricata']['config'][0]['rm_blocked'] != "never_b" ? true : false); write_config(); configure_cron(); @@ -669,7 +782,7 @@ function suricata_post_delete_logs($suricata_uuid = 0) { foreach ($config['installedpackages']['suricata']['rule'] as $value) { if ($value['uuid'] != $suricata_uuid) continue; - $if_real = suricata_get_real_interface($value['interface']); + $if_real = get_real_interface($value['interface']); $suricata_log_dir = SURICATALOGDIR . "suricata_{$if_real}{$suricata_uuid}"; if ($if_real != '') { @@ -710,7 +823,19 @@ function suricata_build_sid_msg_map($rules_path, $sid_file) { /*************************************************************/ /* This function reads all the rules file in the passed */ /* $rules_path variable and produces a properly formatted */ - /* sid-msg.map file for use by Suricata and/or barnyard2. */ + /* sid-msg.map v2 file for use by Suricata and barnyard2. */ + /* */ + /* This function produces the new v2 format sid-msg.map */ + /* with the field layout as follows: */ + /* */ + /* GID || SID || REV || CLASSTYPE || PRI || MSG || REF ... */ + /* */ + /* On Entry: $rules_path --> array or directory of files */ + /* or a single file containing */ + /* the rules to read. */ + /* $sid_file --> the complete destination path */ + /* and filename for the output */ + /* sid-msg.map file. */ /*************************************************************/ $sidMap = array(); @@ -719,7 +844,7 @@ function suricata_build_sid_msg_map($rules_path, $sid_file) { // First check if we were passed a directory, a single file // or an array of filenames to read. Set our $rule_files // variable accordingly. If we can't figure it out, return - // and don't write a sid_msg_map file. + // and don't write a sid-msg.map file. if (is_string($rules_path)) { if (is_dir($rules_path)) $rule_files = glob($rules_path . "*.rules"); @@ -772,7 +897,11 @@ function suricata_build_sid_msg_map($rules_path, $sid_file) { $record = ""; // Parse the rule to find sid and any references. + $gid = '1'; // default to 1 for regular rules $sid = ''; + $rev = ''; + $classtype = 'NOCLASS'; // required default for v2 format + $priority = '0'; // required default for v2 format $msg = ''; $matches = ''; $sidEntry = ''; @@ -780,23 +909,32 @@ function suricata_build_sid_msg_map($rules_path, $sid_file) { $msg = trim($matches[1]); if (preg_match('/\bsid\s*:\s*(\d+)\s*;/i', $rule, $matches)) $sid = trim($matches[1]); - if (!empty($sid) && !empty($msg)) { - $sidEntry = $sid . ' || ' . $msg; + if (preg_match('/\bgid\s*:\s*(\d+)\s*;/i', $rule, $matches)) + $gid = trim($matches[1]); + if (preg_match('/\brev\s*:\s*([^\;]+)/i', $rule, $matches)) + $rev = trim($matches[1]); + if (preg_match('/\bclasstype\s*:\s*([^\;]+)/i', $rule, $matches)) + $classtype = trim($matches[1]); + if (preg_match('/\bpriority\s*:\s*([^\;]+)/i', $rule, $matches)) + $priority = trim($matches[1]); + + if (!empty($gid) && !empty($sid) && !empty($msg)) { + $sidEntry = $gid . ' || ' . $sid . ' || ' . $rev . ' || ' . $classtype . ' || '; + $sidEntry .= $priority . ' || ' . $msg; preg_match_all('/\breference\s*:\s*([^\;]+)/i', $rule, $matches); foreach ($matches[1] as $ref) $sidEntry .= " || " . trim($ref); $sidEntry .= "\n"; - if (!is_array($sidMap[$sid])) - $sidMap[$sid] = array(); - $sidMap[$sid] = $sidEntry; + $sidMap[] = $sidEntry; } } } - // Sort the generated sid-msg map by sid - ksort($sidMap); + // Sort the generated sid-msg map + natcasesort($sidMap); // Now print the result to the supplied file - @file_put_contents($sid_file, array_values($sidMap)); + @file_put_contents($sid_file, "#v2\n# sid-msg.map file auto-generated by Snort.\n\n"); + @file_put_contents($sid_file, array_values($sidMap), FILE_APPEND); } function suricata_merge_reference_configs($cfg_in, $cfg_out) { @@ -1508,7 +1646,7 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { return; // Log a message for rules rebuild in progress - log_error(gettext("[Suricata] Updating rules configuration for: " . suricata_get_friendly_interface($suricatacfg['interface']) . " ...")); + log_error(gettext("[Suricata] Updating rules configuration for: " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . " ...")); // Only rebuild rules if some are selected or an IPS Policy is enabled if (!empty($suricatacfg['rulesets']) || $suricatacfg['ips_policy_enable'] == 'on') { @@ -1581,7 +1719,7 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { // If auto-flowbit resolution is enabled, generate the dependent flowbits rules file. if ($suricatacfg['autoflowbitrules'] == 'on') { - log_error('[Suricata] Enabling any flowbit-required rules for: ' . suricata_get_friendly_interface($suricatacfg['interface']) . '...'); + log_error('[Suricata] Enabling any flowbit-required rules for: ' . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . '...'); $fbits = suricata_resolve_flowbits($all_rules, $enabled_rules); // Check for and disable any flowbit-required rules the user has @@ -1606,11 +1744,11 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { // Log a warning if the interface has no rules defined or enabled if ($no_rules_defined) - log_error(gettext("[Suricata] Warning - no text rules selected for: " . suricata_get_friendly_interface($suricatacfg['interface']) . " ...")); + log_error(gettext("[Suricata] Warning - no text rules selected for: " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . " ...")); // Build a new sid-msg.map file from the enabled // rules and copy it to the interface directory. - log_error(gettext("[Suricata] Building new sig-msg.map file for " . suricata_get_friendly_interface($suricatacfg['interface']) . "...")); + log_error(gettext("[Suricata] Building new sig-msg.map file for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . "...")); suricata_build_sid_msg_map("{$suricatacfgdir}/rules/", "{$suricatacfgdir}/sid-msg.map"); } @@ -1694,33 +1832,27 @@ function suricata_create_rc() { // Loop thru each configured interface and build // the shell script. foreach ($suricataconf as $value) { + // Skip disabled Suricata interfaces + if ($value['enable'] <> 'on') + continue; $suricata_uuid = $value['uuid']; - $if_real = suricata_get_real_interface($value['interface']); + $if_real = get_real_interface($value['interface']); $start_barnyard = <<<EOE if [ ! -f {$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid ]; then - pid=`/bin/pgrep -f "barnyard2 -r {$suricata_uuid} "` + pid=`/bin/pgrep -fn "barnyard2 -r {$suricata_uuid} "` else pid=`/bin/pgrep -F {$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid` fi + if [ ! -z \$pid ]; then - /usr/bin/logger -p daemon.info -i -t SuricataStartup "Barnyard2 STOP for {$value['descr']}({$suricata_uuid}_{$if_real})..." - /bin/pkill -TERM \$pid - time=0 timeout=30 - while /bin/kill -TERM \$pid 2>/dev/null; do - sleep 1 - time=\$((time+1)) - if [ \$time -gt \$timeout ]; then - break - fi - done - if [ -f /var/run/barnyard2_{$if_real}{$suricata_uuid}.pid ]; then - /bin/rm /var/run/barnyard2_{$if_real}{$suricata_uuid}.pid - fi + /usr/bin/logger -p daemon.info -i -t SuricataStartup "Barnyard2 SOFT RESTART for {$value['descr']}({$suricata_uuid}_{$if_real})..." + /bin/pkill -HUP \$pid + else + /usr/bin/logger -p daemon.info -i -t SuricataStartup "Barnyard2 START for {$value['descr']}({$suricata_uuid}_{$if_real})..." + /usr/local/bin/barnyard2 -r {$suricata_uuid} -f unified2.alert --pid-path {$g['varrun_path']} --nolock-pidfile -c {$suricatadir}suricata_{$suricata_uuid}_{$if_real}/barnyard2.conf -d {$suricatalogdir}suricata_{$if_real}{$suricata_uuid} -D -q fi - /usr/bin/logger -p daemon.info -i -t SuricataStartup "Barnyard2 START for {$value['descr']}({$suricata_uuid}_{$if_real})..." - /usr/local/bin/barnyard2 -r {$suricata_uuid} -f unified2.alert --pid-path {$g['varrun_path']} --nolock-pidfile -c {$suricatadir}suricata_{$suricata_uuid}_{$if_real}/barnyard2.conf -d {$suricatalogdir}suricata_{$if_real}{$suricata_uuid} -D -q EOE; $stop_barnyard2 = <<<EOE @@ -1741,9 +1873,9 @@ EOE; /bin/rm /var/run/barnyard2_{$if_real}{$suricata_uuid}.pid fi else - pid=`/bin/pgrep -f "barnyard2 -r {$suricata_uuid} "` + pid=`/bin/pgrep -fn "barnyard2 -r {$suricata_uuid} "` if [ ! -z \$pid ]; then - /bin/pkill -TERM -f "barnyard2 -r {$suricata_uuid} " + /bin/pkill -TERM -fn "barnyard2 -r {$suricata_uuid} " time=0 timeout=30 while /bin/kill -TERM \$pid 2>/dev/null; do sleep 1 @@ -1766,7 +1898,7 @@ EOE; ###### For Each Iface # Start suricata and barnyard2 if [ ! -f {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid ]; then - pid=`/bin/pgrep -f "suricata -i {$if_real} "` + pid=`/bin/pgrep -fn "suricata -i {$if_real} "` else pid=`/bin/pgrep -F {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid` fi @@ -1802,10 +1934,10 @@ EOE; /bin/rm /var/run/suricata_{$if_real}{$suricata_uuid}.pid fi else - pid=`/bin/pgrep -f "suricata -i {$if_real} "` + pid=`/bin/pgrep -fn "suricata -i {$if_real} "` if [ ! -z \$pid ]; then /usr/bin/logger -p daemon.info -i -t SuricataStartup "Suricata STOP for {$value['descr']}({$suricata_uuid}_{$if_real})..." - /bin/pkill -TERM -f "suricata -i {$if_real} " + /bin/pkill -TERM -fn "suricata -i {$if_real} " time=0 timeout=30 while /bin/kill -TERM \$pid 2>/dev/null; do sleep 1 @@ -1908,19 +2040,28 @@ function suricata_generate_barnyard2_conf($suricatacfg, $if_real) { $by2_dbpwd = base64_decode($suricatacfg['barnyard_dbpwd']); $suricatabarnyardlog_output_plugins .= "# database: log to a MySQL DB\noutput database: alert, mysql, "; $suricatabarnyardlog_output_plugins .= "user={$suricatacfg['barnyard_dbuser']} password={$by2_dbpwd} "; - $suricatabarnyardlog_output_plugins .= "dbname={$suricatacfg['barnyard_dbname']} host={$suricatacfg['barnyard_dbhost']}\n\n"; + $suricatabarnyardlog_output_plugins .= "dbname={$suricatacfg['barnyard_dbname']} host={$suricatacfg['barnyard_dbhost']}"; + if (isset($suricatacfg['barnyard_sensor_name']) && strlen($suricatacfg['barnyard_sensor_name']) > 0) + $suricatabarnyardlog_output_plugins .= " sensor_name={$suricatacfg['barnyard_sensor_name']}"; + if ($suricatacfg['barnyard_disable_sig_ref_tbl'] == 'on') + $suricatabarnyardlog_output_plugins .= " disable_signature_reference_table"; + $suricatabarnyardlog_output_plugins .= "\n\n"; } if ($suricatacfg['barnyard_syslog_enable'] == 'on') { $suricatabarnyardlog_output_plugins .= "# syslog_full: log to a syslog receiver\n"; $suricatabarnyardlog_output_plugins .= "output alert_syslog_full: sensor_name {$suricatabarnyardlog_hostname_info_chk}, "; if ($suricatacfg['barnyard_syslog_local'] == 'on') - $suricatabarnyardlog_output_plugins .= "local, log_facility LOG_AUTH, log_priority LOG_INFO\n"; + $suricatabarnyardlog_output_plugins .= "local, log_facility LOG_AUTH, log_priority LOG_INFO\n\n"; else { $suricatabarnyardlog_output_plugins .= "server {$suricatacfg['barnyard_syslog_rhost']}, protocol {$suricatacfg['barnyard_syslog_proto']}, "; $suricatabarnyardlog_output_plugins .= "port {$suricatacfg['barnyard_syslog_dport']}, operation_mode {$suricatacfg['barnyard_syslog_opmode']}, "; - $suricatabarnyardlog_output_plugins .= "log_facility {$suricatacfg['barnyard_syslog_facility']}, log_priority {$suricatacfg['barnyard_syslog_priority']}\n"; + $suricatabarnyardlog_output_plugins .= "log_facility {$suricatacfg['barnyard_syslog_facility']}, log_priority {$suricatacfg['barnyard_syslog_priority']}\n\n"; } } + if ($suricatacfg['barnyard_bro_ids_enable'] == 'on') { + $suricatabarnyardlog_output_plugins .= "# alert_bro: log to a Bro-IDS receiver\n"; + $suricatabarnyardlog_output_plugins .= "output alert_bro: {$suricatacfg['barnyard_bro_ids_rhost']}:{$suricatacfg['barnyard_bro_ids_dport']}\n"; + } // Trim leading and trailing newlines and spaces $suricatabarnyardlog_output_plugins = rtrim($suricatabarnyardlog_output_plugins, "\n"); @@ -1986,7 +2127,7 @@ function suricata_generate_yaml($suricatacfg) { $suricatalogdir = SURICATALOGDIR; $flowbit_rules_file = FLOWBITS_FILENAME; $suricata_enforcing_rules_file = ENFORCING_RULES_FILENAME; - $if_real = suricata_get_real_interface($suricatacfg['interface']); + $if_real = get_real_interface($suricatacfg['interface']); $suricata_uuid = $suricatacfg['uuid']; $suricatacfgdir = "{$suricatadir}suricata_{$suricata_uuid}_{$if_real}"; diff --git a/config/suricata/suricata.priv.inc b/config/suricata/suricata.priv.inc index 7f5f1825..3bbee55a 100644 --- a/config/suricata/suricata.priv.inc +++ b/config/suricata/suricata.priv.inc @@ -21,17 +21,18 @@ $priv_list['page-services-suricata']['match'][] = "suricata/suricata_interfaces_ $priv_list['page-services-suricata']['match'][] = "suricata/suricata_interfaces_global.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_suppress.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_suppress_edit.php*"; -$priv_list['page-services-suricata']['match'][] = "suricata/suricata_interfaces_whitelist.php*"; -$priv_list['page-services-suricata']['match'][] = "suricata/suricata_interfaces_whitelist_edit.php*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_select_alias.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_list_view.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_logs_browser.php*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_logs_mgmt.php*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_passlist.php*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_passlist_edit.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_post_install.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_flow_stream.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_rules.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_rules_edit.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_rules_flowbits.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_rulesets.php*"; -$priv_list['page-services-suricata']['match'][] = "suricata/suricata_select_alias.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_os_policy_engine.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_global.php*"; $priv_list['page-services-suricata']['match'][] = "pkg_edit.php?xml=suricata/suricata.xml*"; @@ -41,5 +42,7 @@ $priv_list['page-services-suricata']['match'][] = "suricata/suricata.inc*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_post_install.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_uninstall.php*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_generate_yaml.php*"; - +$priv_list['page-services-suricata']['match'][] = "widgets/javascript/suricata_alerts.js*"; +$priv_list['page-services-suricata']['match'][] = "widgets/widgets/suricata_alerts.widget.php*"; +$priv_list['page-services-suricata']['match'][] = "widgets/include/widget-suricata.inc*"; ?>
\ No newline at end of file diff --git a/config/suricata/suricata.xml b/config/suricata/suricata.xml index 4760149d..1a64d619 100644 --- a/config/suricata/suricata.xml +++ b/config/suricata/suricata.xml @@ -9,40 +9,49 @@ /* suricata.xml part of the Suricata package for pfSense - Copyright (C) 2014 Bill meeks - All rights reserved. - */ -/* ========================================================================== */ -/* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + Significant portions are based on original work done for the Snort + package for pfSense from the following contributors: + + Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + Copyright (C) 2006 Scott Ullrich + Copyright (C) 2009 Robert Zelaya Sr. Developer + Copyright (C) 2012 Ermal Luci + All rights reserved. + + Adapted for Suricata by: + Copyright (C) 2014 Bill Meeks + 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. - */ + 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> <description>Suricata IDS/IPS Package</description> <requirements>None</requirements> <name>suricata</name> - <version>1.4.6 pkg v0.1-BETA</version> + <version>1.4.6 pkg v1.0</version> <title>Services: Suricata IDS</title> <include_file>/usr/local/pkg/suricata/suricata.inc</include_file> <menu> @@ -58,159 +67,189 @@ <description>Suricata IDS/IPS Daemon</description> </service> <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata.priv.inc</item> <prefix>/etc/inc/priv/</prefix> <chmod>077</chmod> - <item>http://www.pfsense.com/packages/config/suricata/suricata.priv.inc</item> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata.inc</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata.inc</item> <prefix>/usr/local/pkg/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_check_cron_misc.inc</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_check_cron_misc.inc</item> <prefix>/usr/local/pkg/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_yaml_template.inc</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_yaml_template.inc</item> <prefix>/usr/local/pkg/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_generate_yaml.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_generate_yaml.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_download_updates.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_download_updates.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_global.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_global.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_alerts.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_alerts.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_interfaces.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_interfaces.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_interfaces_edit.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_interfaces_edit.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_download_rules.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_download_rules.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_check_for_rule_updates.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_check_for_rule_updates.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_rules.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_rules.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_rulesets.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_rulesets.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_rules_flowbits.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_rules_flowbits.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_rules_edit.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_rules_edit.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_flow_stream.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_flow_stream.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_os_policy_engine.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_os_policy_engine.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_import_aliases.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_import_aliases.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_select_alias.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_suppress.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_suppress.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_suppress_edit.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_suppress_edit.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_logs_browser.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_logs_browser.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_logs_mgmt.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_list_view.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_list_view.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_app_parsers.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_app_parsers.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_libhtp_policy_engine.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_libhtp_policy_engine.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_uninstall.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_uninstall.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_define_vars.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_define_vars.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_barnyard.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_barnyard.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_post_install.php</item> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_post_install.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> - <item>http://www.pfsense.com/packages/config/suricata/suricata_uninstall.php</item> <prefix>/usr/local/www/suricata/</prefix> - <chmod>0755</chmod> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_blocked.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/suricata/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_passlist.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/suricata/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_passlist_edit.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/suricata/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_select_alias.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/javascript/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_alerts.js</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/widgets/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_alerts.widget.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/widgets/include/</prefix> + <chmod>0644</chmod> + <item>https://packages.pfsense.org/packages/config/suricata/widget-suricata.inc</item> </additional_files_needed> <!-- configpath gets expanded out automatically and config items will be stored in that location --> <configpath>['installedpackages']['suricata']</configpath> diff --git a/config/suricata/suricata_alerts.js b/config/suricata/suricata_alerts.js new file mode 100644 index 00000000..b6a5d3c3 --- /dev/null +++ b/config/suricata/suricata_alerts.js @@ -0,0 +1,85 @@ + +var suricatatimer; +var suricataisBusy = false; +var suricataisPaused = false; + +function suricata_alerts_fetch_new_rules_callback(callback_data) { + var data_split; + var new_data_to_add = Array(); + var data = callback_data; + + data_split = data.split("\n"); + + // Loop through rows and generate replacement HTML + for(var x=0; x<data_split.length-1; x++) { + row_split = data_split[x].split("||"); + var line = ''; + line = '<td class="listMRr">' + row_split[0] + '<br/>' + row_split[1] + '</td>'; + line += '<td class="listMRr ellipsis" nowrap><div style="display:inline;" title="'; + line += row_split[2] + '">' + row_split[2] + '</div><br/><div style="display:inline;" title="'; + line += row_split[3] + '">' + row_split[3] + '</div></td>'; + line += '<td class="listMRr">' + 'Pri: ' + row_split[4] + ' ' + row_split[5] + '</td>'; + new_data_to_add[new_data_to_add.length] = line; + } + suricata_alerts_update_div_rows(new_data_to_add); + suricataisBusy = false; +} +function suricata_alerts_update_div_rows(data) { + if(suricataisPaused) + return; + + var rows = jQuery('#suricata-alert-entries>tr'); + + // Number of rows to move by + var move = rows.length + data.length - suri_nentries; + if (move < 0) + move = 0; + + for (var i = rows.length - 1; i >= move; i--) { + jQuery(rows[i]).html(jQuery(rows[i - move]).html()); + } + + var tbody = jQuery('#suricata-alert-entries'); + for (var i = data.length - 1; i >= 0; i--) { + if (i < rows.length) { + jQuery(rows[i]).html(data[i]); + } else { + jQuery(tbody).prepend('<tr>' + data[i] + '</tr>'); + } + } + + // Add the even/odd class to each of the rows now + // they have all been added. + rows = jQuery('#suricata-alert-entries>tr'); + for (var i = 0; i < rows.length; i++) { + rows[i].className = i % 2 == 0 ? 'listMRodd' : 'listMReven'; + } +} + +function fetch_new_surialerts() { + if(suricataisPaused) + return; + if(suricataisBusy) + return; + + suricataisBusy = true; + + jQuery.ajax('/widgets/widgets/suricata_alerts.widget.php?getNewAlerts=' + new Date().getTime(), { + type: 'GET', + dataType: 'text', + success: function(data) { + suricata_alerts_fetch_new_rules_callback(data); + } + }); +} + +function suricata_alerts_toggle_pause() { + if(suricataisPaused) { + suricataisPaused = false; + fetch_new_surialerts(); + } else { + suricataisPaused = true; + } +} +/* start local AJAX engine */ +suricatatimer = setInterval('fetch_new_surialerts()', suricataupdateDelay); diff --git a/config/suricata/suricata_alerts.php b/config/suricata/suricata_alerts.php index c36c0dd7..07e4eb1f 100644 --- a/config/suricata/suricata_alerts.php +++ b/config/suricata/suricata_alerts.php @@ -3,19 +3,30 @@ * suricata_alerts.php * part of pfSense * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -32,6 +43,7 @@ require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); $supplist = array(); +$suri_pf_table = SURICATA_PF_TABLE; function suricata_is_alert_globally_suppressed($list, $gid, $sid) { @@ -109,23 +121,24 @@ function suricata_add_supplist_entry($suppress) { } } - /* If we created a new list or updated an existing one, save the change, */ - /* tell Snort to load it, and return true; otherwise return false. */ + /* If we created a new list or updated an existing one, save the change */ + /* and return true; otherwise return false. */ if ($found_list) { write_config(); sync_suricata_package_config(); - suricata_reload_config($a_instance[$instanceid]); return true; } else return false; } -if ($_GET['instance']) - $instanceid = $_GET['instance']; -if ($_POST['instance']) +if (isset($_POST['instance']) && is_numericint($_POST['instance'])) $instanceid = $_POST['instance']; -if (empty($instanceid)) +// This is for the auto-refresh so we can stay on the same interface +elseif (isset($_GET['instance']) && is_numericint($_GET['instance'])) + $instanceid = $_GET['instance']; + +if (is_null($instanceid)) $instanceid = 0; if (!is_array($config['installedpackages']['suricata']['rule'])) @@ -163,63 +176,64 @@ if ($_POST['save']) { exit; } -//if ($_POST['todelete'] || $_GET['todelete']) { -// $ip = ""; -// if($_POST['todelete']) -// $ip = $_POST['todelete']; -// else if($_GET['todelete']) -// $ip = $_GET['todelete']; -// if (is_ipaddr($ip)) { -// exec("/sbin/pfctl -t snort2c -T delete {$ip}"); -// $savemsg = gettext("Host IP address {$ip} has been removed from the Blocked Table."); -// } -//} - -if ($_GET['act'] == "addsuppress" && is_numeric($_GET['sidid']) && is_numeric($_GET['gen_id'])) { - if (empty($_GET['descr'])) - $suppress = "suppress gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}\n"; - else - $suppress = "#{$_GET['descr']}\nsuppress gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}\n"; - - /* Add the new entry to the Suppress List */ - if (suricata_add_supplist_entry($suppress)) - $savemsg = gettext("An entry for 'suppress gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}' has been added to the Suppress List."); - else - $input_errors[] = gettext("Suppress List '{$a_instance[$instanceid]['suppresslistname']}' is defined for this interface, but it could not be found!"); +if ($_POST['unblock'] && $_POST['ip']) { + if (is_ipaddr($_POST['ip'])) { + exec("/sbin/pfctl -t {$suri_pf_table} -T delete {$_POST['ip']}"); + $savemsg = gettext("Host IP address {$_POST['ip']} has been removed from the Blocked Table."); + } } -if (($_GET['act'] == "addsuppress_srcip" || $_GET['act'] == "addsuppress_dstip") && is_numeric($_GET['sidid']) && is_numeric($_GET['gen_id'])) { - if ($_GET['act'] == "addsuppress_srcip") +if (($_POST['addsuppress_srcip'] || $_POST['addsuppress_dstip'] || $_POST['addsuppress']) && is_numeric($_POST['sidid']) && is_numeric($_POST['gen_id'])) { + if ($_POST['addsuppress_srcip']) $method = "by_src"; - else + elseif ($_POST['addsuppress_dstip']) $method = "by_dst"; - - /* Check for valid IP addresses, exit if not valid */ - if (is_ipaddr($_GET['ip']) || is_ipaddrv6($_GET['ip'])) { - if (empty($_GET['descr'])) - $suppress = "suppress gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}, track {$method}, ip {$_GET['ip']}\n"; - else - $suppress = "#{$_GET['descr']}\nsuppress gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}, track {$method}, ip {$_GET['ip']}\n"; - } - else { - header("Location: /suricata/suricata_alerts.php?instance={$instanceid}"); - exit; + else + $method ="all"; + + // See which kind of Suppress Entry to create + switch ($method) { + case "all": + if (empty($_POST['descr'])) + $suppress = "suppress gen_id {$_POST['gen_id']}, sig_id {$_POST['sidid']}\n"; + else + $suppress = "#{$_POST['descr']}\nsuppress gen_id {$_POST['gen_id']}, sig_id {$_POST['sidid']}\n"; + $success = gettext("An entry for 'suppress gen_id {$_POST['gen_id']}, sig_id {$_POST['sidid']}' has been added to the Suppress List."); + break; + case "by_src": + case "by_dst": + // Check for valid IP addresses, exit if not valid + if (is_ipaddr($_POST['ip'])) { + if (empty($_POST['descr'])) + $suppress = "suppress gen_id {$_POST['gen_id']}, sig_id {$_POST['sidid']}, track {$method}, ip {$_POST['ip']}\n"; + else + $suppress = "#{$_POST['descr']}\nsuppress gen_id {$_POST['gen_id']}, sig_id {$_POST['sidid']}, track {$method}, ip {$_POST['ip']}\n"; + $success = gettext("An entry for 'suppress gen_id {$_POST['gen_id']}, sig_id {$_POST['sidid']}, track {$method}, ip {$_POST['ip']}' has been added to the Suppress List."); + } + else { + header("Location: /suricata/suricata_alerts.php"); + exit; + } + break; + default: + header("Location: /suricata/suricata_alerts.php"); + exit; } - /* Add the new entry to the Suppress List */ - if (suricata_add_supplist_entry($suppress)) - $savemsg = gettext("An entry for 'suppress gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}, track {$method}, ip {$_GET['ip']}' has been added to the Suppress List."); + /* Add the new entry to the Suppress List and signal Suricata to reload config */ + if (suricata_add_supplist_entry($suppress)) { + suricata_reload_config($a_instance[$instanceid]); + $savemsg = $success; + sleep(2); + } else - /* We did not find the defined list, so notify the user with an error */ $input_errors[] = gettext("Suppress List '{$a_instance[$instanceid]['suppresslistname']}' is defined for this interface, but it could not be found!"); } -if ($_GET['act'] == "togglesid" && is_numeric($_GET['sidid']) && is_numeric($_GET['gen_id'])) { - // Get the GID tag embedded in the clicked rule icon. - $gid = $_GET['gen_id']; - - // Get the SID tag embedded in the clicked rule icon. - $sid= $_GET['sidid']; +if ($_POST['togglesid'] && is_numeric($_POST['sidid']) && is_numeric($_POST['gen_id'])) { + // Get the GID and SID tags embedded in the clicked rule icon. + $gid = $_POST['gen_id']; + $sid= $_POST['sidid']; // See if the target SID is in our list of modified SIDs, // and toggle it if present. @@ -268,21 +282,18 @@ if ($_GET['act'] == "togglesid" && is_numeric($_GET['sidid']) && is_numeric($_GE /* Signal Suricata to live-load the new rules */ suricata_reload_config($a_instance[$instanceid]); + sleep(2); - $savemsg = gettext("The state for rule {$gid}:{$sid} has been modified. Suricata is 'live-reloading' the new rules list. Please wait at least 30 secs for the process to complete before toggling additional rules."); + $savemsg = gettext("The state for rule {$gid}:{$sid} has been modified. Suricata is 'live-reloading' the new rules list. Please wait at least 15 secs for the process to complete before toggling additional rules."); } -if ($_GET['action'] == "clear" || $_POST['delete']) { - conf_mount_rw(); +if ($_POST['delete']) { suricata_post_delete_logs($suricata_uuid); $fd = @fopen("{$suricatalogdir}suricata_{$if_real}{$suricata_uuid}/alerts.log", "w+"); if ($fd) fclose($fd); - conf_mount_ro(); /* XXX: This is needed if suricata is run as suricata user */ mwexec('/bin/chmod 660 {$suricatalogdir}*', true); - if (file_exists("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid")) - mwexec("/bin/pkill -HUP -F {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid -a"); header("Location: /suricata/suricata_alerts.php?instance={$instanceid}"); exit; } @@ -332,16 +343,21 @@ if ($pconfig['arefresh'] == 'on') echo "<meta http-equiv=\"refresh\" content=\"60;url=/suricata/suricata_alerts.php?instance={$instanceid}\" />\n"; ?> -<?php if($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';} - /* Display Alert message */ - if ($input_errors) { - print_input_errors($input_errors); // TODO: add checks - } - if ($savemsg) { - print_info_box($savemsg); - } +<?php +/* Display Alert message */ +if ($input_errors) { + print_input_errors($input_errors); // TODO: add checks +} +if ($savemsg) { + print_info_box($savemsg); +} ?> <form action="/suricata/suricata_alerts.php" method="post" id="formalert"> +<input type="hidden" name="sidid" id="sidid" value=""/> +<input type="hidden" name="gen_id" id="gen_id" value=""/> +<input type="hidden" name="ip" id="ip" value=""/> +<input type="hidden" name="descr" id="descr" value=""/> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td> <?php @@ -349,10 +365,13 @@ if ($pconfig['arefresh'] == 'on') $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); - $tab_array[] = array(gettext("Alerts"), true, "/suricata/suricata_alerts.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Alerts"), true, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); ?> </td></tr> <tr> @@ -364,13 +383,13 @@ if ($pconfig['arefresh'] == 'on') <tr> <td width="22%" class="vncell"><?php echo gettext('Instance to Inspect'); ?></td> <td width="78%" class="vtable"> - <select name="instance" id="instance" class="formselect" onChange="document.getElementById('formalert').method='get';document.getElementById('formalert').submit()"> + <select name="instance" id="instance" class="formselect" onChange="document.getElementById('formalert').method='post';document.getElementById('formalert').submit()"> <?php foreach ($a_instance as $id => $instance) { $selected = ""; if ($id == $instanceid) $selected = "selected"; - echo "<option value='{$id}' {$selected}> (" . suricata_get_friendly_interface($instance['interface']) . "){$instance['descr']}</option>\n"; + echo "<option value='{$id}' {$selected}> (" . convert_friendly_interface_to_friendly_descr($instance['interface']) . ") {$instance['descr']}</option>\n"; } ?> </select> <?php echo gettext('Choose which instance alerts you want to inspect.'); ?> @@ -378,22 +397,23 @@ if ($pconfig['arefresh'] == 'on') <tr> <td width="22%" class="vncell"><?php echo gettext('Save or Remove Logs'); ?></td> <td width="78%" class="vtable"> - <input name="download" type="submit" class="formbtns" value="Download"> <?php echo gettext('All ' . - 'log files will be saved.'); ?> <a href="/suricata/suricata_alerts.php?action=clear&instance=<?=$instanceid;?>"> - <input name="delete" type="submit" class="formbtns" value="Clear" - onclick="return confirm('Do you really want to remove all instance logs?')"></a> - <span class="red"><strong><?php echo gettext('Warning:'); ?></strong></span> <?php echo ' ' . gettext('all log files will be deleted.'); ?> + <input name="download" type="submit" class="formbtns" value="Download" + title="<?=gettext("Download interface log files as a gzip archive");?>"/> + <?php echo gettext('All log files will be saved.');?> + <input name="delete" type="submit" class="formbtns" value="Clear" + onclick="return confirm('Do you really want to remove all instance logs?')" title="<?=gettext("Clear all interface log files");?>"/> + <span class="red"><strong><?php echo gettext('Warning:'); ?></strong></span> <?php echo gettext('all log files will be deleted.'); ?> </td> </tr> <tr> <td width="22%" class="vncell"><?php echo gettext('Auto Refresh and Log View'); ?></td> <td width="78%" class="vtable"> - <input name="save" type="submit" class="formbtns" value="Save"> - <?php echo gettext('Refresh'); ?> <input name="arefresh" type="checkbox" value="on" - <?php if ($config['installedpackages']['suricata']['alertsblocks']['arefresh']=="on") echo "checked"; ?>> - <?php printf(gettext('%sDefault%s is %sON%s.'), '<strong>', '</strong>', '<strong>', '</strong>'); ?> - <input name="alertnumber" type="text" class="formfld unknown" id="alertnumber" size="5" value="<?=htmlspecialchars($anentries);?>"> - <?php printf(gettext('Enter number of log entries to view. %sDefault%s is %s250%s.'), '<strong>', '</strong>', '<strong>', '</strong>'); ?> + <input name="save" type="submit" class="formbtns" value=" Save " title="<?=gettext("Save auto-refresh and view settings");?>"/> + <?php echo gettext('Refresh');?> <input name="arefresh" type="checkbox" value="on" + <?php if ($config['installedpackages']['snortglobal']['alertsblocks']['arefresh']=="on") echo "checked"; ?>/> + <?php printf(gettext('%sDefault%s is %sON%s.'), '<strong>', '</strong>', '<strong>', '</strong>'); ?> + <input name="alertnumber" type="text" class="formfld unknown" id="alertnumber" size="5" value="<?=htmlspecialchars($anentries);?>"/> + <?php printf(gettext('Enter number of log entries to view. %sDefault%s is %s250%s.'), '<strong>', '</strong>', '<strong>', '</strong>'); ?> </td> </tr> <tr> @@ -402,31 +422,31 @@ if ($pconfig['arefresh'] == 'on') </tr> <tr> <td width="100%" colspan="2"> - <table id="myTable" style="table-layout: fixed;" width="100%" class="sortable" border="1" cellpadding="0" cellspacing="0"> + <table id="myTable" style="table-layout: fixed;" width="100%" class="sortable" border="0" cellpadding="0" cellspacing="0"> <colgroup> <col width="10%" align="center" axis="date"> - <col width="41" align="center" axis="number"> - <col width="64" align="center" axis="string"> + <col width="40" align="center" axis="number"> + <col width="52" align="center" axis="string"> <col width="10%" axis="string"> <col width="13%" align="center" axis="string"> - <col width="8%" align="center" axis="string"> + <col width="7%" align="center" axis="string"> <col width="13%" align="center" axis="string"> - <col width="8%" align="center" axis="string"> - <col width="9%" align="center" axis="number"> + <col width="7%" align="center" axis="string"> + <col width="10%" align="center" axis="number"> <col axis="string"> </colgroup> <thead> <tr> - <th class="listhdrr" axis="date"><?php echo gettext("DATE"); ?></th> - <th class="listhdrr" axis="number"><?php echo gettext("PRI"); ?></th> - <th class="listhdrr" axis="string"><?php echo gettext("PROTO"); ?></th> - <th class="listhdrr" axis="string"><?php echo gettext("CLASS"); ?></th> - <th class="listhdrr" axis="string"><?php echo gettext("SRC"); ?></th> - <th class="listhdrr" axis="string"><?php echo gettext("SPORT"); ?></th> - <th class="listhdrr" axis="string"><?php echo gettext("DST"); ?></th> - <th class="listhdrr" axis="string"><?php echo gettext("DPORT"); ?></th> + <th class="listhdrr" axis="date"><?php echo gettext("Date"); ?></th> + <th class="listhdrr" axis="number"><?php echo gettext("Pri"); ?></th> + <th class="listhdrr" axis="string"><?php echo gettext("Proto"); ?></th> + <th class="listhdrr" axis="string"><?php echo gettext("Class"); ?></th> + <th class="listhdrr" axis="string"><?php echo gettext("Src"); ?></th> + <th class="listhdrr" axis="string"><?php echo gettext("SPort"); ?></th> + <th class="listhdrr" axis="string"><?php echo gettext("Dst"); ?></th> + <th class="listhdrr" axis="string"><?php echo gettext("DPort"); ?></th> <th class="listhdrr" axis="number"><?php echo gettext("SID"); ?></th> - <th class="listhdrr" axis="string"><?php echo gettext("DESCRIPTION"); ?></th> + <th class="listhdrr" axis="string"><?php echo gettext("Description"); ?></th> </tr> </thead> <tbody> @@ -434,21 +454,30 @@ if ($pconfig['arefresh'] == 'on') /* make sure alert file exists */ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log")) { - exec("tail -{$anentries} -r /var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log > /tmp/alerts_{$suricata_uuid}"); - if (file_exists("/tmp/alerts_{$suricata_uuid}")) { + exec("tail -{$anentries} -r /var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log > /tmp/alerts_suricata{$suricata_uuid}"); + if (file_exists("/tmp/alerts_suricata{$suricata_uuid}")) { $tmpblocked = array_flip(suricata_get_blocked_ips()); $counter = 0; /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */ /* File format timestamp,action,sig_generator,sig_id,sig_rev,msg,classification,priority,proto,src,srcport,dst,dstport */ - $fd = fopen("/tmp/alerts_{$suricata_uuid}", "r"); + $fd = fopen("/tmp/alerts_suricata{$suricata_uuid}", "r"); while (($fields = fgetcsv($fd, 1000, ',', '"')) !== FALSE) { - if(count($fields) < 12) + if(count($fields) < 13) continue; + // Create a DateTime object from the event timestamp that + // we can use to easily manipulate output formats. + $event_tm = date_create_from_format("m/d/Y-H:i:s.u", $fields[0]); + + // Check the 'CATEGORY' field for the text "(null)" and + // substitute "Not Assigned". + if ($fields[6] == "(null)") + $fields[6] = "Not Assigned"; + /* Time */ - $alert_time = substr($fields[0], strpos($fields[0], '-')+1, -7); + $alert_time = date_format($event_tm, "H:i:s"); /* Date */ - $alert_date = trim(substr($fields[0], 0, strpos($fields[0], '-'))); + $alert_date = date_format($event_tm, "m/d/Y"); /* Description */ $alert_descr = $fields[5]; $alert_descr_url = urlencode($fields[5]); @@ -470,9 +499,9 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo /* Add icons for auto-adding to Suppress List if appropriate */ if (!suricata_is_alert_globally_suppressed($supplist, $fields[2], $fields[3]) && !isset($supplist[$fields[2]][$fields[3]]['by_src'][$fields[9]])) { - $alert_ip_src .= " <a href='?instance={$instanceid}&act=addsuppress_srcip&sidid={$fields[3]}&gen_id={$fields[2]}&descr={$alert_descr_url}&ip=" . trim(urlencode($fields[9])) . "'>"; - $alert_ip_src .= "<img src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; - $alert_ip_src .= "title='" . gettext("Add this alert to the Suppress List and track by_src IP") . "'></a>"; + $alert_ip_src .= " <input type='image' name='addsuppress_srcip[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','{$fields[9]}','{$alert_descr}');\" "; + $alert_ip_src .= "src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; + $alert_ip_src .= "title='" . gettext("Add this alert to the Suppress List and track by_src IP") . "'/>"; } elseif (isset($supplist[$fields[2]][$fields[3]]['by_src'][$fields[9]])) { $alert_ip_src .= " <img src='../themes/{$g['theme']}/images/icons/icon_plus_d.gif' width='12' height='12' border='0' "; @@ -480,9 +509,8 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo } /* Add icon for auto-removing from Blocked Table if required */ if (isset($tmpblocked[$fields[9]])) { - $alert_ip_src .= " "; - $alert_ip_src .= "<a href='?instance={$instanceid}&todelete=" . trim(urlencode($fields[9])) . "'> - <img title=\"" . gettext("Remove host from Blocked Table") . "\" border=\"0\" width='12' height='12' name='todelete' id='todelete' alt=\"Remove from Blocked Hosts\" src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"></a>"; + $alert_ip_src .= " <input type='image' name='unblock[]' onClick=\"document.getElementById('ip').value='{$fields[9]}';\" "; + $alert_ip_src .= "title='" . gettext("Remove host from Blocked Table") . "' border='0' width='12' height='12' src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"/>"; } /* IP SRC Port */ $alert_src_p = $fields[10]; @@ -499,10 +527,10 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo $alert_ip_dst .= "title='" . gettext("Resolve host via reverse DNS lookup") . "'></a>"; /* Add icons for auto-adding to Suppress List if appropriate */ if (!suricata_is_alert_globally_suppressed($supplist, $fields[2], $fields[3]) && - !isset($supplist[$fields[2]][$fields[3]]['by_dst'][$fields[1]])) { - $alert_ip_dst .= " <a href='?instance={$instanceid}&act=addsuppress_dstip&sidid={$fields[3]}&gen_id={$fields[2]}&descr={$alert_descr_url}&ip=" . trim(urlencode($fields[11])) . "'>"; - $alert_ip_dst .= "<img src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; - $alert_ip_dst .= "title='" . gettext("Add this alert to the Suppress List and track by_dst IP") . "'></a>"; + !isset($supplist[$fields[2]][$fields[3]]['by_dst'][$fields[11]])) { + $alert_ip_dst .= " <input type='image' name='addsuppress_dstip[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','{$fields[11]}','{$alert_descr}');\" "; + $alert_ip_dst .= "src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; + $alert_ip_dst .= "title='" . gettext("Add this alert to the Suppress List and track by_dst IP") . "'/>"; } elseif (isset($supplist[$fields[2]][$fields[3]]['by_dst'][$fields[11]])) { $alert_ip_dst .= " <img src='../themes/{$g['theme']}/images/icons/icon_plus_d.gif' width='12' height='12' border='0' "; @@ -510,18 +538,17 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo } /* Add icon for auto-removing from Blocked Table if required */ if (isset($tmpblocked[$fields[11]])) { - $alert_ip_dst .= " "; - $alert_ip_dst .= "<a href='?instance={$instanceid}&todelete=" . trim(urlencode($fields[11])) . "'> - <img title=\"" . gettext("Remove host from Blocked Table") . "\" border=\"0\" width='12' height='12' name='todelete' id='todelete' alt=\"Remove from Blocked Hosts\" src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"></a>"; + $alert_ip_dst .= " <input type='image' name='unblock[]' onClick=\"document.getElementById('ip').value='{$fields[11]}';\" "; + $alert_ip_dst .= "title='" . gettext("Remove host from Blocked Table") . "' border='0' width='12' height='12' src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"/>"; } /* IP DST Port */ $alert_dst_p = $fields[12]; /* SID */ $alert_sid_str = "{$fields[2]}:{$fields[3]}"; if (!suricata_is_alert_globally_suppressed($supplist, $fields[2], $fields[3])) { - $sidsupplink = "<a href='?instance={$instanceid}&act=addsuppress&sidid={$fields[3]}&gen_id={$fields[2]}&descr={$alert_descr_url}'>"; - $sidsupplink .= "<img src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; - $sidsupplink .= "title='" . gettext("Add this alert to the Suppress List") . "'></a>"; + $sidsupplink = "<input type='image' name='addsuppress[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','','{$alert_descr}');\" "; + $sidsupplink .= "src='../themes/{$g['theme']}/images/icons/icon_plus.gif' width='12' height='12' border='0' "; + $sidsupplink .= "title='" . gettext("Add this alert to the Suppress List") . "'/>"; } else { $sidsupplink = "<img src='../themes/{$g['theme']}/images/icons/icon_plus_d.gif' width='12' height='12' border='0' "; @@ -529,14 +556,14 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo } /* Add icon for toggling rule state */ if (isset($disablesid[$fields[2]][$fields[3]])) { - $sid_dsbl_link = "<a href='?instance={$instanceid}&act=togglesid&sidid={$fields[3]}&gen_id={$fields[2]}'>"; - $sid_dsbl_link .= "<img src='../themes/{$g['theme']}/images/icons/icon_reject.gif' width='11' height='11' border='0' "; - $sid_dsbl_link .= "title='" . gettext("Rule is forced to a disabled state. Click to remove the force-disable action from this rule.") . "'></a>"; + $sid_dsbl_link = "<input type='image' name='togglesid[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','','');\" "; + $sid_dsbl_link .= "src='../themes/{$g['theme']}/images/icons/icon_reject.gif' width='11' height='11' border='0' "; + $sid_dsbl_link .= "title='" . gettext("Rule is forced to a disabled state. Click to remove the force-disable action from this rule.") . "'/>"; } else { - $sid_dsbl_link = "<a href='?instance={$instanceid}&act=togglesid&sidid={$fields[3]}&gen_id={$fields[2]}'>"; - $sid_dsbl_link .= "<img src='../themes/{$g['theme']}/images/icons/icon_block.gif' width='11' height='11' border='0' "; - $sid_dsbl_link .= "title='" . gettext("Force-disable this rule and remove it from current rules set.") . "'></a>"; + $sid_dsbl_link = "<input type='image' name='togglesid[]' onClick=\"encRuleSig('{$fields[2]}','{$fields[3]}','','');\" "; + $sid_dsbl_link .= "src='../themes/{$g['theme']}/images/icons/icon_block.gif' width='11' height='11' border='0' "; + $sid_dsbl_link .= "title='" . gettext("Force-disable this rule and remove it from current rules set.") . "'/>"; } /* DESCRIPTION */ $alert_class = $fields[6]; @@ -546,18 +573,18 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo <td class='listr' align='center'>{$alert_priority}</td> <td class='listr' align='center'>{$alert_proto}</td> <td class='listr' style=\"word-wrap:break-word;\">{$alert_class}</td> - <td class='listr' align='center'>{$alert_ip_src}</td> + <td class='listr' align='center' sorttable_customkey='{$fields[9]}'>{$alert_ip_src}</td> <td class='listr' align='center'>{$alert_src_p}</td> - <td class='listr' align='center'>{$alert_ip_dst}</td> + <td class='listr' align='center' sorttable_customkey='{$fields[11]}'>{$alert_ip_dst}</td> <td class='listr' align='center'>{$alert_dst_p}</td> - <td class='listr' align='center'>{$alert_sid_str}<br/>{$sidsupplink} {$sid_dsbl_link}</td> - <td class='listr' style=\"word-wrap:break-word;\">{$alert_descr}</td> + <td class='listr' align='center' sorttable_customkey='{$fields[3]}'>{$alert_sid_str}<br/>{$sidsupplink} {$sid_dsbl_link}</td> + <td class='listbg' style=\"word-wrap:break-word;\">{$alert_descr}</td> </tr>\n"; $counter++; } fclose($fd); - @unlink("/tmp/alerts_{$suricata_uuid}"); + @unlink("/tmp/alerts_suricata{$suricata_uuid}"); } } ?> @@ -573,6 +600,21 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo <?php include("fend.inc"); ?> - +<script type="text/javascript"> +function encRuleSig(rulegid,rulesid,srcip,ruledescr) { + + // This function stuffs the passed GID, SID + // and other values into hidden Form Fields + // for postback. + if (typeof srcipip == "undefined") + var srcipip = ""; + if (typeof ruledescr == "undefined") + var ruledescr = ""; + document.getElementById("sidid").value = rulesid; + document.getElementById("gen_id").value = rulegid; + document.getElementById("ip").value = srcip; + document.getElementById("descr").value = ruledescr; +} +</script> </body> </html> diff --git a/config/suricata/suricata_alerts.widget.php b/config/suricata/suricata_alerts.widget.php new file mode 100644 index 00000000..21fad03d --- /dev/null +++ b/config/suricata/suricata_alerts.widget.php @@ -0,0 +1,229 @@ +<?php +/* + suricata_alerts.widget.php + Copyright (C) 2009 Jim Pingle + mod 24-07-2012 + + Copyright (C) 2014 Bill Meeks + mod 03-Mar-2014 adapted for use with Suricata by Bill Meeks + + 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. +*/ + +$nocsrf = true; + +require_once("guiconfig.inc"); +require_once("/usr/local/www/widgets/include/widget-suricata.inc"); + +global $config, $g; + +/* Retrieve Suricata configuration */ +if (!is_array($config['installedpackages']['suricata']['rule'])) + $config['installedpackages']['suricata']['rule'] = array(); +$a_instance = &$config['installedpackages']['suricata']['rule']; + +/* array sorting */ +function sksort(&$array, $subkey="id", $sort_ascending=false) { + /* an empty array causes sksort to fail - this test alleviates the error */ + if(empty($array)) + return false; + if (count($array)){ + $temp_array[key($array)] = array_shift($array); + }; + foreach ($array as $key => $val){ + $offset = 0; + $found = false; + foreach ($temp_array as $tmp_key => $tmp_val) { + if (!$found and strtolower($val[$subkey]) > strtolower($tmp_val[$subkey])) { + $temp_array = array_merge((array)array_slice($temp_array,0,$offset), array($key => $val), array_slice($temp_array,$offset)); + $found = true; + }; + $offset++; + }; + if (!$found) $temp_array = array_merge($temp_array, array($key => $val)); + }; + + if ($sort_ascending) { + $array = array_reverse($temp_array); + } else $array = $temp_array; + /* below is the complement for empty array test */ + return true; +}; + +/* check if suricata widget variable is set */ +$suri_nentries = $config['widgets']['widget_suricata_display_lines']; +if (!isset($suri_nentries) || $suri_nentries < 0) + $suri_nentries = 5; + +// Called by Ajax to update alerts table contents +if (isset($_GET['getNewAlerts'])) { + $response = ""; + $suri_alerts = suricata_widget_get_alerts(); + $counter = 0; + foreach ($suri_alerts as $a) { + $response .= $a['instanceid'] . " " . $a['dateonly'] . "||" . $a['timeonly'] . "||" . $a['src'] . "||"; + $response .= $a['dst'] . "||" . $a['priority'] . "||" . $a['category'] . "\n"; + $counter++; + if($counter >= $suri_nentries) + break; + } + echo $response; + return; +} + +if(isset($_POST['widget_suricata_display_lines'])) { + $config['widgets']['widget_suricata_display_lines'] = $_POST['widget_suricata_display_lines']; + write_config("Saved Suricata Alerts Widget Displayed Lines Parameter via Dashboard"); + header("Location: ../../index.php"); +} + +// Read "$suri_nentries" worth of alerts from the top of the alerts.log file +function suricata_widget_get_alerts() { + + global $config, $a_instance, $suri_nentries; + $suricata_alerts = array(); + + /* read log file(s) */ + $counter=0; + foreach ($a_instance as $instanceid => $instance) { + $suricata_uuid = $a_instance[$instanceid]['uuid']; + $if_real = get_real_interface($a_instance[$instanceid]['interface']); + + // make sure alert file exists, then grab the most recent {$suri_nentries} from it + // and write them to a temp file. + if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log")) { + exec("tail -{$suri_nentries} -r /var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log > /tmp/surialerts_{$suricata_uuid}"); + if (file_exists("/tmp/surialerts_{$suricata_uuid}")) { + + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */ + /* File format: timestamp,action,sig_generator,sig_id,sig_rev,msg,classification,priority,proto,src,srcport,dst,dstport */ + $fd = fopen("/tmp/surialerts_{$suricata_uuid}", "r"); + while (($fields = fgetcsv($fd, 1000, ',', '"')) !== FALSE) { + if(count($fields) < 13) + continue; + + // Create a DateTime object from the event timestamp that + // we can use to easily manipulate output formats. + $event_tm = date_create_from_format("m/d/Y-H:i:s.u", $fields[0]); + + // Check the 'CATEGORY' field for the text "(null)" and + // substitute "No classtype defined". + if ($fields[6] == "(null)") + $fields[6] = "No classtype assigned"; + + $suricata_alerts[$counter]['instanceid'] = strtoupper($a_instance[$instanceid]['interface']); + $suricata_alerts[$counter]['timestamp'] = strval(date_timestamp_get($event_tm)); + $suricata_alerts[$counter]['timeonly'] = date_format($event_tm, "H:i:s"); + $suricata_alerts[$counter]['dateonly'] = date_format($event_tm, "M d"); + // Add square brackets around any IPv6 address + if (is_ipaddrv6($fields[9])) + $suricata_alerts[$counter]['src'] = "[" . $fields[9] . "]"; + else + $suricata_alerts[$counter]['src'] = $fields[9]; + // Add the SRC PORT if not null + if (!empty($fields[10])) + $suricata_alerts[$counter]['src'] .= ":" . $fields[10]; + // Add square brackets around any IPv6 address + if (is_ipaddrv6($fields[11])) + $suricata_alerts[$counter]['dst'] = "[" . $fields[11] . "]"; + else + $suricata_alerts[$counter]['dst'] = $fields[11]; + // Add the SRC PORT if not null + if (!empty($fields[12])) + $suricata_alerts[$counter]['dst'] .= ":" . $fields[12]; + $suricata_alerts[$counter]['priority'] = $fields[7]; + $suricata_alerts[$counter]['category'] = $fields[6]; + $counter++; + }; + fclose($fd); + @unlink("/tmp/surialerts_{$suricata_uuid}"); + }; + }; + }; + + // Sort the alerts array + if (isset($config['syslog']['reverse'])) { + sksort($suricata_alerts, 'timestamp', false); + } else { + sksort($suricata_alerts, 'timestamp', true); + } + + return $suricata_alerts; +} + +/* display the result */ +?> + +<input type="hidden" id="suricata_alerts-config" name="suricata_alerts-config" value=""/> +<div id="suricata_alerts-settings" class="widgetconfigdiv" style="display:none;"> + <form action="/widgets/widgets/suricata_alerts.widget.php" method="post" name="iformd"> + Enter number of recent alerts to display (default is 5)<br/> + <input type="text" size="5" name="widget_suricata_display_lines" class="formfld unknown" id="widget_suricata_display_lines" value="<?= $config['widgets']['widget_suricata_display_lines'] ?>" /> + <input id="submitd" name="submitd" type="submit" class="formbtn" value="Save" /> + </form> +</div> + +<table width="100%" border="0" cellspacing="0" cellpadding="0" style="table-layout: fixed;"> + <colgroup> + <col style="width: 24%;" /> + <col style="width: 38%;" /> + <col style="width: 38%;" /> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?=gettext("IF/Date");?></th> + <th class="listhdrr"><?=gettext("Src/Dst Address");?></th> + <th class="listhdrr"><?=gettext("Classification");?></th> + </tr> + </thead> + <tbody id="suricata-alert-entries"> + <?php + $suricata_alerts = suricata_widget_get_alerts($suri_nentries); + $counter=0; + if (is_array($suricata_alerts)) { + foreach ($suricata_alerts as $alert) { + $evenRowClass = $counter % 2 ? " listMReven" : " listMRodd"; + echo(" <tr class='" . $evenRowClass . "'> + <td class='listMRr'>" . $alert['instanceid'] . " " . $alert['dateonly'] . "<br/>" . $alert['timeonly'] . "</td> + <td class='listMRr ellipsis' nowrap><div style='display:inline;' title='" . $alert['src'] . "'>" . $alert['src'] . "</div><br/><div style='display:inline;' title='" . $alert['dst'] . "'>" . $alert['dst'] . "</div></td> + <td class='listMRr'>Pri: " . $alert['priority'] . " " . $alert['category'] . "</td></tr>"); + $counter++; + if($counter >= $suri_nentries) + break; + } + } + ?> + </tbody> +</table> + +<script type="text/javascript"> +//<![CDATA[ + var suricataupdateDelay = 10000; // update every 10 seconds + var suri_nentries = <?php echo $suri_nentries; ?>; // default is 5 + +<!-- needed to display the widget settings menu --> + selectIntLink = "suricata_alerts-configure"; + textlink = document.getElementById(selectIntLink); + textlink.style.display = "inline"; +//]]> +</script> + diff --git a/config/suricata/suricata_app_parsers.php b/config/suricata/suricata_app_parsers.php index 0be45c32..c28b99d1 100644 --- a/config/suricata/suricata_app_parsers.php +++ b/config/suricata/suricata_app_parsers.php @@ -3,12 +3,23 @@ * suricata_app_parsers.php * part of pfSense * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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. * @@ -28,19 +39,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ - require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); global $g, $rebuild_rules; -$id = $_GET['id']; -if (isset($_POST['id'])) +if (isset($_POST['id']) && is_numericint($_POST['id'])) $id = $_POST['id']; -if (is_null($id)) { - header("Location: /suricata/suricata_interfaces.php"); - exit; -} +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); + +if (is_null($id)) + $id = 0; if (!is_array($config['installedpackages']['suricata'])) $config['installedpackages']['suricata'] = array(); @@ -51,10 +61,21 @@ if (!is_array($config['installedpackages']['suricata']['rule'])) if (!is_array($config['installedpackages']['suricata']['rule'][$id]['libhtp_policy']['item'])) $config['installedpackages']['suricata']['rule'][$id]['libhtp_policy']['item'] = array(); +// Initialize required array variables as necessary +if (!is_array($config['aliases']['alias'])) + $config['aliases']['alias'] = array(); +$a_aliases = $config['aliases']['alias']; + $a_nat = &$config['installedpackages']['suricata']['rule']; $libhtp_engine_next_id = count($a_nat[$id]['libhtp_policy']['item']); +// Build a lookup array of currently used engine 'bind_to' Aliases +// so we can screen matching Alias names from the list. +$used = array(); +foreach ($a_nat[$id]['libhtp_policy']['item'] as $v) + $used[$v['bind_to']] = true; + $pconfig = array(); if (isset($id) && $a_nat[$id]) { /* Get current values from config for page form fields */ @@ -78,29 +99,143 @@ if (isset($id) && $a_nat[$id]) { $pconfig['libhtp_policy'] = $a_nat[$id]['libhtp_policy']; } -// Check for returned "selected alias" if action is import -if ($_GET['act'] == "import" && isset($_GET['varname']) && !empty($_GET['varvalue'])) { - $pconfig[$_GET['varname']] = $_GET['varvalue']; +// Check for "import or select alias mode" and set flags if TRUE. +// "selectalias", when true, displays radio buttons to limit +// multiple selections. +if ($_POST['import_alias']) { + $importalias = true; + $selectalias = false; + $title = "HTTP Server Policy"; } - -if ($_GET['act'] && isset($_GET['eng_id'])) { - +elseif ($_POST['select_alias']) { + $importalias = true; + $selectalias = true; + $title = "HTTP Server Policy"; + + // Preserve current Libhtp Policy Engine settings + $eng_id = $_POST['eng_id']; + $eng_name = $_POST['policy_name']; + $eng_bind = $_POST['policy_bind_to']; + $eng_personality = $_POST['personality']; + $eng_req_body_limit = $_POST['req_body_limit']; + $eng_resp_body_limit = $_POST['resp_body_limit']; + $eng_enable_double_decode_path = $_POST['enable_double_decode_path']; + $eng_enable_double_decode_query = $_POST['enable_double_decode_query']; + $mode = "add_edit_libhtp_policy"; +} +if ($_POST['save_libhtp_policy']) { + if ($_POST['eng_id'] != "") { + $eng_id = $_POST['eng_id']; + + // Grab all the POST values and save in new temp array + $engine = array(); + $policy_name = trim($_POST['policy_name']); + if ($policy_name) { + $engine['name'] = $policy_name; + } + else + $input_errors[] = gettext("The 'Policy Name' value cannot be blank."); + + if ($_POST['policy_bind_to']) { + if (is_alias($_POST['policy_bind_to'])) + $engine['bind_to'] = $_POST['policy_bind_to']; + elseif (strtolower(trim($_POST['policy_bind_to'])) == "all") + $engine['bind_to'] = "all"; + else + $input_errors[] = gettext("You must provide a valid Alias or the reserved keyword 'all' for the 'Bind-To IP Address' value."); + } + else + $input_errors[] = gettext("The 'Bind-To IP Address' value cannot be blank. Provide a valid Alias or the reserved keyword 'all'."); + + if ($_POST['personality']) { $engine['personality'] = $_POST['personality']; } else { $engine['personality'] = "bsd"; } + + if (is_numeric($_POST['req_body_limit']) && $_POST['req_body_limit'] >= 0) + $engine['request-body-limit'] = $_POST['req_body_limit']; + else + $input_errors[] = gettext("The value for 'Request Body Limit' must be all numbers and greater than or equal to zero."); + + if (is_numeric($_POST['resp_body_limit']) && $_POST['resp_body_limit'] >= 0) + $engine['response-body-limit'] = $_POST['resp_body_limit']; + else + $input_errors[] = gettext("The value for 'Response Body Limit' must be all numbers and greater than or equal to zero."); + + if ($_POST['enable_double_decode_path']) { $engine['double-decode-path'] = 'yes'; }else{ $engine['double-decode-path'] = 'no'; } + if ($_POST['enable_double_decode_query']) { $engine['double-decode-query'] = 'yes'; }else{ $engine['double-decode-query'] = 'no'; } + + // Can only have one "all" Bind_To address + if ($engine['bind_to'] == "all" && $engine['name'] <> "default") + $input_errors[] = gettext("Only one default OS-Policy Engine can be bound to all addresses."); + + // if no errors, write new entry to conf + if (!$input_errors) { + if (isset($eng_id) && $a_nat[$id]['libhtp_policy']['item'][$eng_id]) { + $a_nat[$id]['libhtp_policy']['item'][$eng_id] = $engine; + } + else + $a_nat[$id]['libhtp_policy']['item'][] = $engine; + + /* Reorder the engine array to ensure the */ + /* 'bind_to=all' entry is at the bottom */ + /* if it contains more than one entry. */ + if (count($a_nat[$id]['libhtp_policy']['item']) > 1) { + $i = -1; + foreach ($a_nat[$id]['libhtp_policy']['item'] as $f => $v) { + if ($v['bind_to'] == "all") { + $i = $f; + break; + } + } + /* Only relocate the entry if we */ + /* found it, and it's not already */ + /* at the end. */ + if ($i > -1 && ($i < (count($a_nat[$id]['libhtp_policy']['item']) - 1))) { + $tmp = $a_nat[$id]['libhtp_policy']['item'][$i]; + unset($a_nat[$id]['libhtp_policy']['item'][$i]); + $a_nat[$id]['libhtp_policy']['item'][] = $tmp; + } + } + + // Now write the new engine array to conf + write_config(); + $pconfig['libhtp_policy']['item'] = $a_nat[$id]['libhtp_policy']['item']; + } + else { + $add_edit_libhtp_policy = true; + $pengcfg = $engine; + } + } +} +elseif ($_POST['add_libhtp_policy']) { + $add_edit_libhtp_policy = true; + $pengcfg = array( "name" => "engine_{$libhtp_engine_next_id}", "bind_to" => "", "personality" => "IDS", + "request-body-limit" => "4096", "response-body-limit" => "4096", + "double-decode-path" => "no", "double-decode-query" => "no" ); + $eng_id = $libhtp_engine_next_id; +} +elseif ($_POST['edit_libhtp_policy']) { + if ($_POST['eng_id'] != "") { + $add_edit_libhtp_policy = true; + $eng_id = $_POST['eng_id']; + $pengcfg = $a_nat[$id]['libhtp_policy']['item'][$eng_id]; + } +} +elseif ($_POST['del_libhtp_policy']) { $natent = array(); $natent = $pconfig; - if ($_GET['act'] == "del_libhtp_policy") - unset($natent['libhtp_policy']['item'][$_GET['eng_id']]); - + if ($_POST['eng_id'] != "") { + unset($natent['libhtp_policy']['item'][$_POST['eng_id']]); + $pconfig = $natent; + } if (isset($id) && $a_nat[$id]) { $a_nat[$id] = $natent; write_config(); } - - header("Location: /suricata/suricata_app_parsers.php?id=$id"); - exit; } - -if ($_POST['ResetAll']) { +elseif ($_POST['cancel_libhtp_policy']) { + $add_edit_libhtp_policy = false; +} +elseif ($_POST['ResetAll']) { /* Reset all the settings to defaults */ $pconfig['asn1_max_frames'] = "256"; @@ -108,7 +243,111 @@ if ($_POST['ResetAll']) { /* Log a message at the top of the page to inform the user */ $savemsg = gettext("All flow and stream settings have been reset to their defaults."); } -elseif ($_POST['Submit']) { +elseif ($_POST['save_import_alias']) { + // If saving out of "select alias" mode, + // then return to Libhtp Policy Engine edit + // page. + if ($_POST['mode'] == 'add_edit_libhtp_policy') { + $pengcfg = array(); + $eng_id = $_POST['eng_id']; + $pengcfg['name'] = $_POST['eng_name']; + $pengcfg['bind_to'] = $_POST['eng_bind']; + $pengcfg['personality'] = $_POST['eng_personality']; + $pengcfg['request-body-limit'] = $_POST['eng_req_body_limit']; + $pengcfg['response-body-limit'] = $_POST['eng_resp_body_limit']; + $pengcfg['double-decode-path'] = $_POST['eng_enable_double_decode_path']; + $pengcfg['double-decode-query'] = $_POST['eng_enable_double_decode_query']; + $add_edit_libhtp_policy = true; + $mode = "add_edit_libhtp_policy"; + + if (is_array($_POST['aliastoimport']) && count($_POST['aliastoimport']) == 1) { + $pengcfg['bind_to'] = $_POST['aliastoimport'][0]; + $importalias = false; + $selectalias = false; + } + else { + $input_errors[] = gettext("No Alias is selected for import. Nothing to SAVE."); + $importalias = true; + $selectalias = true; + $eng_id = $_POST['eng_id']; + $eng_name = $_POST['eng_name']; + $eng_bind = $_POST['eng_bind']; + $eng_personality = $_POST['eng_personality']; + $eng_req_body_limit = $_POST['eng_req_body_limit']; + $eng_resp_body_limit = $_POST['eng_resp_body_limit']; + $eng_enable_double_decode_path = $_POST['eng_enable_double_decode_path']; + $eng_enable_double_decode_query = $_POST['eng_enable_double_decode_query']; + } + } + else { + $engine = array( "name" => "", "bind_to" => "", "personality" => "IDS", + "request-body-limit" => "4096", "response-body-limit" => "4096", + "double-decode-path" => "no", "double-decode-query" => "no" ); + + // See if anything was checked to import + if (is_array($_POST['aliastoimport']) && count($_POST['aliastoimport']) > 0) { + foreach ($_POST['aliastoimport'] as $item) { + $engine['name'] = strtolower($item); + $engine['bind_to'] = $item; + $a_nat[$id]['libhtp_policy']['item'][] = $engine; + } + } + else { + $input_errors[] = gettext("No entries were selected for import. Please select one or more Aliases for import and click SAVE."); + $importalias = true; + } + + // if no errors, write new entry to conf + if (!$input_errors) { + // Reorder the engine array to ensure the + // 'bind_to=all' entry is at the bottom if + // the array contains more than one entry. + if (count($a_nat[$id]['libhtp_policy']['item']) > 1) { + $i = -1; + foreach ($a_nat[$id]['libhtp_policy']['item'] as $f => $v) { + if ($v['bind_to'] == "all") { + $i = $f; + break; + } + } + // Only relocate the entry if we + // found it, and it's not already + // at the end. + if ($i > -1 && ($i < (count($a_nat[$id]['libhtp_policy']['item']) - 1))) { + $tmp = $a_nat[$id]['libhtp_policy']['item'][$i]; + unset($a_nat[$id]['libhtp_policy']['item'][$i]); + $a_nat[$id]['libhtp_policy']['item'][] = $tmp; + } + $pconfig['libhtp_policy']['item'] = $a_nat[$id]['libhtp_policy']['item']; + } + + // Write the new engine array to config file + write_config(); + $importalias = false; + } + } +} +elseif ($_POST['cancel_import_alias']) { + $importalias = false; + $selectalias = false; + $eng_id = $_POST['eng_id']; + + // If cancelling out of "select alias" mode, + // then return to Libhtp Policy Engine edit + // page. + if ($_POST['mode'] == 'add_edit_libhtp_policy') { + $pengcfg = array(); + $pengcfg['name'] = $_POST['eng_name']; + $pengcfg['bind_to'] = $_POST['eng_bind']; + $pengcfg['personality'] = $_POST['eng_personality']; + $pengcfg['request-body-limit'] = $_POST['eng_req_body_limit']; + $pengcfg['response-body-limit'] = $_POST['eng_resp_body_limit']; + $pengcfg['double-decode-path'] = $_POST['eng_enable_double_decode_path']; + $pengcfg['double-decode-query'] = $_POST['eng_enable_double_decode_query']; + $add_edit_libhtp_policy = true; + } +} +elseif ($_POST['save']) { $natent = array(); $natent = $pconfig; @@ -122,15 +361,14 @@ elseif ($_POST['Submit']) { /**************************************************/ /* If we have a valid rule ID, save configuration */ - /* then update the suricata.conf file and rebuild */ - /* the rules for this interface. */ + /* then update the suricata.conf file for this */ + /* interface. */ /**************************************************/ if (isset($id) && $a_nat[$id]) { $a_nat[$id] = $natent; write_config(); - $rebuild_rules = true; - suricata_generate_yaml($natent); $rebuild_rules = false; + suricata_generate_yaml($natent); } header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); @@ -149,40 +387,33 @@ include_once("head.inc"); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> -<?php include("fbegin.inc"); ?> -<?php if($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';} - - - /* Display Alert message */ - +<?php include("fbegin.inc"); + /* Display error or save message */ if ($input_errors) { - print_input_errors($input_errors); // TODO: add checks + print_input_errors($input_errors); } - if ($savemsg) { print_info_box($savemsg); } - ?> -<script type="text/javascript" src="/javascript/autosuggest.js"> -</script> -<script type="text/javascript" src="/javascript/suggestions.js"> -</script> - -<form action="suricata_app_parsers.php" method="post" - enctype="multipart/form-data" name="iform" id="iform"> +<form action="suricata_app_parsers.php" method="post" name="iform" id="iform"> +<input name="id" type="hidden" value="<?=$id;?>"/> +<input type="hidden" name="eng_id" id="eng_id" value="<?=$eng_id;?>"/> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); - $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td>'; $menu_iface=($if_friendly?substr($if_friendly,0,5)." ":"Iface "); @@ -194,10 +425,29 @@ include_once("head.inc"); $tab_array[] = array($menu_iface . gettext("App Parsers"), true, "/suricata/suricata_app_parsers.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Variables"), false, "/suricata/suricata_define_vars.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Barnyard2"), false, "/suricata/suricata_barnyard.php?id={$id}"); - display_top_tabs($tab_array); + display_top_tabs($tab_array, true); ?> </td></tr> <tr><td><div id="mainarea"> + +<?php if ($importalias) : ?> + <?php include("/usr/local/www/suricata/suricata_import_aliases.php"); + if ($selectalias) { + echo '<input type="hidden" name="eng_name" value="' . $eng_name . '"/>'; + echo '<input type="hidden" name="eng_bind" value="' . $eng_bind . '"/>'; + echo '<input type="hidden" name="eng_personality" value="' . $eng_personality . '"/>'; + echo '<input type="hidden" name="eng_req_body_limit" value="' . $eng_req_body_limit . '"/>'; + echo '<input type="hidden" name="eng_resp_body_limit" value="' . $eng_resp_body_limit . '"/>'; + echo '<input type="hidden" name="eng_enable_double_decode_path" value="' . $eng_enable_double_decode_path . '"/>'; + echo '<input type="hidden" name="eng_enable_double_decode_query" value="' . $eng_enable_double_decode_query . '"/>'; + } + ?> + +<?php elseif ($add_edit_libhtp_policy) : ?> + <?php include("/usr/local/www/suricata/suricata_libhtp_policy_engine.php"); ?> + +<?php else: ?> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> <tr> @@ -231,25 +481,23 @@ include_once("head.inc"); <tr> <th class="listhdrr" axis="string"><?php echo gettext("Name");?></th> <th class="listhdrr" axis="string"><?php echo gettext("Bind-To Address Alias");?></th> - <th class="list" align="right"><a href="suricata_import_aliases.php?id=<?=$id?>&eng=libhtp_policy"> - <img src="../themes/<?= $g['theme'];?>/images/icons/icon_import_alias.gif" width="17" - height="17" border="0" title="<?php echo gettext("Import server configuration from existing Aliases");?>"></a> - <a href="suricata_libhtp_policy_engine.php?id=<?=$id?>&eng_id=<?=$libhtp_engine_next_id?>"> - <img src="../themes/<?= $g['theme'];?>/images/icons/icon_plus.gif" width="17" - height="17" border="0" title="<?php echo gettext("Add a new server configuration");?>"></a></th> + <th class="list" align="right"><input type="image" name="import_alias[]" src="../themes/<?= $g['theme'];?>/images/icons/icon_import_alias.gif" width="17" + height="17" border="0" title="<?php echo gettext("Import server configuration from existing Aliases");?>"/> + <input type="image" name="add_libhtp_policy[]" src="../themes/<?= $g['theme'];?>/images/icons/icon_plus.gif" width="17" + height="17" border="0" title="<?php echo gettext("Add a new server configuration");?>"></th> </tr> </thead> <?php foreach ($pconfig['libhtp_policy']['item'] as $f => $v): ?> <tr> <td class="listlr" align="left"><?=gettext($v['name']);?></td> <td class="listbg" align="center"><?=gettext($v['bind_to']);?></td> - <td class="listt" align="right"><a href="suricata_libhtp_policy_engine.php?id=<?=$id;?>&eng_id=<?=$f;?>"> - <img src="/themes/<?=$g['theme'];?>/images/icons/icon_e.gif" - width="17" height="17" border="0" title="<?=gettext("Edit this server configuration");?>"></a> + <td class="listt" align="right"><input type="image" name="edit_libhtp_policy[]" value="<?=$f;?>" onclick="document.getElementById('eng_id').value='<?=$f;?>'" + src="/themes/<?=$g['theme'];?>/images/icons/icon_e.gif" + width="17" height="17" border="0" title="<?=gettext("Edit this server configuration");?>"/> <?php if ($v['bind_to'] <> "all") : ?> - <a href="suricata_app_parsers.php?id=<?=$id;?>&eng_id=<?=$f;?>&act=del_libhtp_policy" onclick="return confirm('Are you sure you want to delete this entry?');"> - <img src="/themes/<?=$g['theme'];?>/images/icons/icon_x.gif" width="17" height="17" border="0" - title="<?=gettext("Delete this server configuration");?>"></a> + <input type="image" name="del_libhtp_policy[]" value="<?=$f;?>" onclick="document.getElementById('eng_id').value='<?=$f;?>';return confirm('Are you sure you want to delete this entry?');" + src="/themes/<?=$g['theme'];?>/images/icons/icon_x.gif" width="17" height="17" border="0" + title="<?=gettext("Delete this server configuration");?>"> <?php else : ?> <img src="/themes/<?=$g['theme'];?>/images/icons/icon_x_d.gif" width="17" height="17" border="0" title="<?=gettext("Default server configuration cannot be deleted");?>"> @@ -263,9 +511,9 @@ include_once("head.inc"); <tr> <td width="22%" valign="top"> </td> <td width="78%"> - <input name="Submit" type="submit" class="formbtn" value="Save" title="<?php echo + <input name="save" type="submit" class="formbtn" value="Save" title="<?php echo gettext("Save flow and stream settings"); ?>"> - <input name="id" type="hidden" value="<?=$id;?>"> + <input name="ResetAll" type="submit" class="formbtn" value="Reset" title="<?php echo gettext("Reset all settings to defaults") . "\" onclick=\"return confirm('" . gettext("WARNING: This will reset ALL App Parsers settings to their defaults. Click OK to continue or CANCEL to quit.") . @@ -278,26 +526,12 @@ include_once("head.inc"); <?php echo gettext("may take several seconds. Suricata must also be restarted to activate any changes made on this screen."); ?></td> </tr> </table> + +<?php endif; ?> + </div> </td></tr></table> </form> -<script type="text/javascript"> -function wopen(url, name, w, h) -{ - // Fudge factors for window decoration space. - // In my tests these work well on all platforms & browsers. - w += 32; - h += 96; - var win = window.open(url, - name, - 'width=' + w + ', height=' + h + ', ' + - 'location=no, menubar=no, ' + - 'status=no, toolbar=no, scrollbars=yes, resizable=yes'); - win.resizeTo(w, h); - win.focus(); -} - -</script> <?php include("fend.inc"); ?> </body> </html> diff --git a/config/suricata/suricata_barnyard.php b/config/suricata/suricata_barnyard.php index f0bdbd17..d4afe4f4 100644 --- a/config/suricata/suricata_barnyard.php +++ b/config/suricata/suricata_barnyard.php @@ -3,12 +3,23 @@ * suricata_barnyard.php * part of pfSense * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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. * @@ -33,9 +44,11 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); global $g, $rebuild_rules; -$id = $_GET['id']; -if (isset($_POST['id'])) +if (isset($_POST['id']) && is_numericint($_POST['id'])) $id = $_POST['id']; +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); + if (is_null($id)) { header("Location: /suricata/suricata_interfaces.php"); exit; @@ -46,8 +59,8 @@ if (!is_array($config['installedpackages']['suricata']['rule'])) $a_nat = &$config['installedpackages']['suricata']['rule']; $pconfig = array(); + if (isset($id) && $a_nat[$id]) { - /* old options */ $pconfig = $a_nat[$id]; if (!empty($a_nat[$id]['barnconfigpassthru'])) $pconfig['barnconfigpassthru'] = base64_decode($a_nat[$id]['barnconfigpassthru']); @@ -69,28 +82,28 @@ if (isset($id) && $a_nat[$id]) { $pconfig['barnyard_syslog_facility'] = "LOG_USER"; if (empty($a_nat[$id]['barnyard_syslog_priority'])) $pconfig['barnyard_syslog_priority'] = "LOG_INFO"; + if (empty($a_nat[$id]['barnyard_bro_ids_dport'])) + $pconfig['barnyard_bro_ids_dport'] = "47760"; + if (empty($a_nat[$id]['barnyard_sensor_id'])) + $pconfig['barnyard_sensor_id'] = "0"; if (empty($a_nat[$id]['barnyard_sensor_name'])) $pconfig['barnyard_sensor_name'] = php_uname("n"); } -if (isset($_GET['dup'])) - unset($id); - -if ($_POST) { - - foreach ($a_nat as $natent) { - if (isset($id) && ($a_nat[$id]) && ($a_nat[$id] === $natent)) - continue; - if ($natent['interface'] != $_POST['interface']) - $input_error[] = "This interface has already an instance defined"; - } - +if ($_POST['save']) { // Check that at least one output plugin is enabled - if ($_POST['barnyard_mysql_enable'] != 'on' && $_POST['barnyard_syslog_enable'] != 'on') + if ($_POST['barnyard_mysql_enable'] != 'on' && $_POST['barnyard_syslog_enable'] != 'on' && + $_POST['barnyard_bro_ids_enable'] != 'on' && $_POST['barnyard_enable'] == "on") $input_errors[] = gettext("You must enable at least one output option when using Barnyard2."); + // Validate Sensor ID is a valid integer + if ($_POST['barnyard_enable'] == 'on') { + if (!is_numericint($_POST['barnyard_sensor_id']) || $_POST['barnyard_sensor_id'] < 0) + $input_errors[] = gettext("The value for 'Sensor ID' must be a valid positive integer."); + } + // Validate inputs if MySQL database loggging enabled - if ($_POST['barnyard_mysql_enable'] == 'on') { + if ($_POST['barnyard_mysql_enable'] == 'on' && $_POST['barnyard_enable'] == "on") { if (empty($_POST['barnyard_dbhost'])) $input_errors[] = gettext("Please provide a valid hostname or IP address for the MySQL database host."); if (empty($_POST['barnyard_dbname'])) @@ -100,13 +113,22 @@ if ($_POST) { } // Validate inputs if syslog output enabled - if ($_POST['barnyard_syslog_enable'] == 'on' && $_POST['barnyard_syslog_local'] <> 'on') { + if ($_POST['barnyard_syslog_enable'] == 'on' && $_POST['barnyard_syslog_local'] <> 'on' && + $_POST['barnyard_enable'] == "on") { if (empty($_POST['barnyard_syslog_dport']) || !is_numeric($_POST['barnyard_syslog_dport'])) $input_errors[] = gettext("Please provide a valid number between 1 and 65535 for the Syslog Remote Port."); if (empty($_POST['barnyard_syslog_rhost'])) $input_errors[] = gettext("Please provide a valid hostname or IP address for the Syslog Remote Host."); } + // Validate inputs if Bro-IDS output enabled + if ($_POST['barnyard_bro_ids_enable'] == 'on' && $_POST['barnyard_enable'] == "on") { + if (empty($_POST['barnyard_bro_ids_dport']) || !is_numeric($_POST['barnyard_bro_ids_dport'])) + $input_errors[] = gettext("Please provide a valid number between 1 and 65535 for the Bro-IDS Remote Port."); + if (empty($_POST['barnyard_bro_ids_rhost'])) + $input_errors[] = gettext("Please provide a valid hostname or IP address for the Bro-IDS Remote Host."); + } + // if no errors write to conf if (!$input_errors) { $natent = array(); @@ -121,9 +143,12 @@ if ($_POST) { $natent['barnyard_mysql_enable'] = $_POST['barnyard_mysql_enable'] ? 'on' : 'off'; $natent['barnyard_syslog_enable'] = $_POST['barnyard_syslog_enable'] ? 'on' : 'off'; $natent['barnyard_syslog_local'] = $_POST['barnyard_syslog_local'] ? 'on' : 'off'; + $natent['barnyard_bro_ids_enable'] = $_POST['barnyard_bro_ids_enable'] ? 'on' : 'off'; + $natent['barnyard_disable_sig_ref_tbl'] = $_POST['barnyard_disable_sig_ref_tbl'] ? 'on' : 'off'; $natent['barnyard_syslog_opmode'] = $_POST['barnyard_syslog_opmode']; $natent['barnyard_syslog_proto'] = $_POST['barnyard_syslog_proto']; + if ($_POST['barnyard_sensor_id']) $natent['barnyard_sensor_id'] = $_POST['barnyard_sensor_id']; else $natent['barnyard_sensor_id'] = '0'; if ($_POST['barnyard_sensor_name']) $natent['barnyard_sensor_name'] = $_POST['barnyard_sensor_name']; else unset($natent['barnyard_sensor_name']); if ($_POST['barnyard_dbhost']) $natent['barnyard_dbhost'] = $_POST['barnyard_dbhost']; else unset($natent['barnyard_dbhost']); if ($_POST['barnyard_dbname']) $natent['barnyard_dbname'] = $_POST['barnyard_dbname']; else unset($natent['barnyard_dbname']); @@ -133,70 +158,76 @@ if ($_POST) { if ($_POST['barnyard_syslog_dport']) $natent['barnyard_syslog_dport'] = $_POST['barnyard_syslog_dport']; else $natent['barnyard_syslog_dport'] = '514'; if ($_POST['barnyard_syslog_facility']) $natent['barnyard_syslog_facility'] = $_POST['barnyard_syslog_facility']; else $natent['barnyard_syslog_facility'] = 'LOG_USER'; if ($_POST['barnyard_syslog_priority']) $natent['barnyard_syslog_priority'] = $_POST['barnyard_syslog_priority']; else $natent['barnyard_syslog_priority'] = 'LOG_INFO'; + if ($_POST['barnyard_bro_ids_rhost']) $natent['barnyard_bro_ids_rhost'] = $_POST['barnyard_bro_ids_rhost']; else unset($natent['barnyard_bro_ids_rhost']); + if ($_POST['barnyard_bro_ids_dport']) $natent['barnyard_bro_ids_dport'] = $_POST['barnyard_bro_ids_dport']; else $natent['barnyard_bro_ids_dport'] = '47760'; if ($_POST['barnconfigpassthru']) $natent['barnconfigpassthru'] = base64_encode($_POST['barnconfigpassthru']); else unset($natent['barnconfigpassthru']); - if (isset($id) && $a_nat[$id]) - $a_nat[$id] = $natent; - else { - $a_nat[] = $natent; - } - + $a_nat[$id] = $natent; write_config(); - // No need to rebuild rules if just toggling Barnyard2 on or off + // No need to rebuild rules for Barnyard2 changes $rebuild_rules = false; sync_suricata_package_config(); - // Signal any running barnyard2 instance on this interface to - // reload its configuration to pick up any changes made. - suricata_barnyard_reload_config($a_nat[$id], "HUP"); - - // after click go to this page - header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); - header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); - header( 'Cache-Control: no-store, no-cache, must-revalidate' ); - header( 'Cache-Control: post-check=0, pre-check=0', false ); - header( 'Pragma: no-cache' ); - header("Location: suricata_barnyard.php?id=$id"); - exit; + // If disabling Barnyard2 on the interface, stop any + // currently running instance. If an instance is + // running, signal it to reload the configuration. + // If Barnyard2 is enabled but not running, start it. + if ($a_nat[$id]['barnyard_enable'] == "off") { + suricata_barnyard_stop($a_nat[$id], get_real_interface($a_nat[$id]['interface'])); + } + elseif ($a_nat[$id]['barnyard_enable'] == "on") { + if (suricata_is_running($a_nat[$id]['uuid'], get_real_interface($a_nat[$id]['interface']), "barnyard2")) + suricata_barnyard_reload_config($a_nat[$id], "HUP"); + else { + // Notify user a Suricata restart is required if enabling Barnyard2 for the first time + $savemsg = gettext("NOTE: you must restart Suricata on this interface to activate unified2 logging for Barnyard2."); + } + } + + $pconfig = $natent; + } + else { + // We had errors, so save previous field data to prevent retyping + $pconfig = $_POST; } } -$if_friendly = convert_friendly_interface_to_friendly_descr($pconfig['interface']); +$if_friendly = convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface']); $pgtitle = gettext("Suricata: Interface {$if_friendly} - Barnyard2 Settings"); include_once("head.inc"); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> -<?php include("fbegin.inc"); ?> -<?if($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';}?> +<?php include("fbegin.inc"); -<?php /* Display Alert message */ if ($input_errors) { - print_input_errors($input_errors); // TODO: add checks + print_input_errors($input_errors); } if ($savemsg) { print_info_box($savemsg); } - ?> +?> -<form action="suricata_barnyard.php" method="post" - enctype="multipart/form-data" name="iform" id="iform"> +<form action="suricata_barnyard.php" method="post" name="iform" id="iform"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; $tab_array = array(); @@ -208,7 +239,7 @@ include_once("head.inc"); $tab_array[] = array($menu_iface . gettext("App Parsers"), false, "/suricata/suricata_app_parsers.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Variables"), false, "/suricata/suricata_define_vars.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Barnyard2"), true, "/suricata/suricata_barnyard.php?id={$id}"); - display_top_tabs($tab_array); + display_top_tabs($tab_array, true); ?> </td></tr> <tr> @@ -254,14 +285,21 @@ include_once("head.inc"); <?php echo gettext("Enable obfuscation of logged IP addresses. Default value is ") . "<strong>" . gettext("Not Checked") . "</strong>"; ?> </td> <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Sensor ID"); ?></td> + <td width="78%" class="vtable"> + <input name="barnyard_sensor_id" type="text" class="formfld unknown" + id="barnyard_sensor_id" size="25" value="<?=htmlspecialchars($pconfig['barnyard_sensor_id']);?>"/> + <?php echo gettext("Sensor ID to use for this sensor. Default is ") . "<strong>" . gettext("0.") . "</strong>"; ?> + </td> + </tr> + <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Sensor Name"); ?></td> <td width="78%" class="vtable"> <input name="barnyard_sensor_name" type="text" class="formfld unknown" id="barnyard_sensor_name" size="25" value="<?=htmlspecialchars($pconfig['barnyard_sensor_name']);?>"/> - <?php echo gettext("Unique name to use for this sensor."); ?> + <?php echo gettext("Unique name to use for this sensor. (Optional)"); ?> </td> </tr> - </tr> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("MySQL Database Output Settings"); ?></td> </tr> @@ -272,6 +310,7 @@ include_once("head.inc"); onClick="toggle_mySQL()"/><?php echo gettext("Enable logging of alerts to a MySQL database instance"); ?><br/> <?php echo gettext("You will also have to provide the database credentials in the fields below."); ?></td> </tr> + <tbody id="mysql_config_rows"> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Database Host"); ?></td> <td width="78%" class="vtable"> @@ -305,6 +344,15 @@ include_once("head.inc"); </td> </tr> <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Disable Signature Reference Table"); ?></td> + <td width="78%" class="vtable"> + <input name="barnyard_disable_sig_ref_tbl" type="checkbox" value="on" <?php if ($pconfig['barnyard_disable_sig_ref_tbl'] == "on") echo "checked"; ?>/> + <?php echo gettext("Disable synchronization of sig_reference table in schema. Default value is ") . "<strong>" . gettext("Not Checked") . "</strong>"; ?><br/> + <br/><?php echo gettext("This option will speedup the process when checked, plus it can help work around a 'duplicate entry' error when running multiple Suricata instances."); ?> + </td> + </tr> + </tbody> + <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Syslog Output Settings"); ?></td> </tr> <tr> @@ -315,6 +363,7 @@ include_once("head.inc"); <?php echo gettext("Enable logging of alerts to a syslog receiver"); ?><br/> <?php echo gettext("This will send alert data to either a local or remote syslog receiver."); ?></td> </tr> + <tbody id="syslog_config_rows"> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Operation Mode"); ?></td> <td width="78%" class="vtable"> @@ -395,6 +444,36 @@ include_once("head.inc"); <?php echo gettext("Select Syslog Priority (Level) to use for remote reporting. Default is ") . "<strong>" . gettext("LOG_INFO") . "</strong>."; ?> </td> </tr> + </tbody> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Bro-IDS Output Settings"); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable Bro-IDS"); ?></td> + <td width="78%" class="vtable"> + <input name="barnyard_bro_ids_enable" type="checkbox" value="on" <?php if ($pconfig['barnyard_bro_ids_enable'] == "on") echo "checked"; ?> + onClick="toggle_bro_ids()"/> + <?php echo gettext("Enable logging of alerts to a Bro-IDS receiver"); ?><br/> + <?php echo gettext("This will send alert data to either a local or remote Bro-IDS receiver."); ?></td> + </tr> + <tbody id="bro_ids_config_rows"> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Remote Host"); ?></td> + <td width="78%" class="vtable"> + <input name="barnyard_bro_ids_rhost" type="text" class="formfld host" + id="barnyard_bro_ids_rhost" size="25" value="<?=htmlspecialchars($pconfig['barnyard_bro_ids_rhost']);?>"/> + <?php echo gettext("Hostname or IP address of remote Bro-IDS host"); ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Remote Port"); ?></td> + <td width="78%" class="vtable"> + <input name="barnyard_bro_ids_dport" type="text" class="formfld unknown" + id="barnyard_bro_ids_dport" size="25" value="<?=htmlspecialchars($pconfig['barnyard_bro_ids_dport']);?>"/> + <?php echo gettext("Port number for Bro-IDS instance on remote host. Default is ") . "<strong>" . gettext("47760") . "</strong>."; ?> + </td> + </tr> + </tbody> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Advanced Settings"); ?></td> </tr> @@ -410,7 +489,7 @@ include_once("head.inc"); <tr> <td width="22%" valign="top"> </td> <td width="78%"> - <input name="Submit" type="submit" class="formbtn" value="Save"> + <input name="save" type="submit" class="formbtn" value="Save"> <input name="id" type="hidden" value="<?=$id;?>"> </td> </tr> <tr> @@ -435,6 +514,12 @@ function toggle_mySQL() { document.iform.barnyard_dbname.disabled = endis; document.iform.barnyard_dbuser.disabled = endis; document.iform.barnyard_dbpwd.disabled = endis; + document.iform.barnyard_disable_sig_ref_tbl.disabled = endis; + + if (endis) + document.getElementById("mysql_config_rows").style.display = "none"; + else + document.getElementById("mysql_config_rows").style.display = ""; } function toggle_syslog() { @@ -449,6 +534,11 @@ function toggle_syslog() { document.iform.barnyard_syslog_proto_tcp.disabled = endis; document.iform.barnyard_syslog_facility.disabled = endis; document.iform.barnyard_syslog_priority.disabled = endis; + + if (endis) + document.getElementById("syslog_config_rows").style.display = "none"; + else + document.getElementById("syslog_config_rows").style.display = ""; } function toggle_local_syslog() { @@ -464,6 +554,18 @@ function toggle_local_syslog() { } } +function toggle_bro_ids() { + var endis = !document.iform.barnyard_bro_ids_enable.checked; + + document.iform.barnyard_bro_ids_rhost.disabled = endis; + document.iform.barnyard_bro_ids_dport.disabled = endis; + + if (endis) + document.getElementById("bro_ids_config_rows").style.display = "none"; + else + document.getElementById("bro_ids_config_rows").style.display = ""; +} + function enable_change(enable_change) { endis = !(document.iform.barnyard_enable.checked || enable_change); // make sure a default answer is called if this is invoked. @@ -472,12 +574,14 @@ function enable_change(enable_change) { document.iform.barnyard_show_year.disabled = endis; document.iform.barnyard_dump_payload.disabled = endis; document.iform.barnyard_obfuscate_ip.disabled = endis; + document.iform.barnyard_sensor_id.disabled = endis; document.iform.barnyard_sensor_name.disabled = endis; document.iform.barnyard_mysql_enable.disabled = endis; document.iform.barnyard_dbhost.disabled = endis; document.iform.barnyard_dbname.disabled = endis; document.iform.barnyard_dbuser.disabled = endis; document.iform.barnyard_dbpwd.disabled = endis; + document.iform.barnyard_disable_sig_ref_tbl.disabled = endis; document.iform.barnyard_syslog_enable.disabled = endis; document.iform.barnyard_syslog_local.disabled = endis; document.iform.barnyard_syslog_opmode_default.disabled = endis; @@ -488,6 +592,9 @@ function enable_change(enable_change) { document.iform.barnyard_syslog_proto_tcp.disabled = endis; document.iform.barnyard_syslog_facility.disabled = endis; document.iform.barnyard_syslog_priority.disabled = endis; + document.iform.barnyard_bro_ids_enable.disabled = endis; + document.iform.barnyard_bro_ids_rhost.disabled = endis; + document.iform.barnyard_bro_ids_dport.disabled = endis; document.iform.barnconfigpassthru.disabled = endis; } @@ -495,6 +602,7 @@ enable_change(false); toggle_mySQL(); toggle_syslog(); toggle_local_syslog(); +toggle_bro_ids(); </script> diff --git a/config/suricata/suricata_blocked.php b/config/suricata/suricata_blocked.php new file mode 100644 index 00000000..96171c1e --- /dev/null +++ b/config/suricata/suricata_blocked.php @@ -0,0 +1,323 @@ +<?php +/* + * suricata_blocked.php + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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"); +require_once("/usr/local/pkg/suricata/suricata.inc"); + +$suricatalogdir = SURICATALOGDIR; +$suri_pf_table = SURICATA_PF_TABLE; + +if (!is_array($config['installedpackages']['suricata']['alertsblocks'])) + $config['installedpackages']['suricata']['alertsblocks'] = array(); + +$pconfig['brefresh'] = $config['installedpackages']['suricata']['alertsblocks']['brefresh']; +$pconfig['blertnumber'] = $config['installedpackages']['suricata']['alertsblocks']['blertnumber']; + +if (empty($pconfig['blertnumber'])) + $bnentries = '500'; +else + $bnentries = $pconfig['blertnumber']; + +if ($_POST['todelete']) { + $ip = ""; + if ($_POST['ip']) + $ip = $_POST['ip']; + if (is_ipaddr($ip)) + exec("/sbin/pfctl -t {$suri_pf_table} -T delete {$ip}"); + else + $input_errors[] = gettext("An invalid IP address was provided as a parameter."); +} + +if ($_POST['remove']) { + exec("/sbin/pfctl -t {$suri_pf_table} -T flush"); + header("Location: /suricata/suricata_blocked.php"); + exit; +} + +/* TODO: build a file with block ip and disc */ +if ($_POST['download']) +{ + $blocked_ips_array_save = ""; + exec("/sbin/pfctl -t {$suri_pf_table} -T show", $blocked_ips_array_save); + /* build the list */ + if (is_array($blocked_ips_array_save) && count($blocked_ips_array_save) > 0) { + $save_date = exec('/bin/date "+%Y-%m-%d-%H-%M-%S"'); + $file_name = "suricata_blocked_{$save_date}.tar.gz"; + exec('/bin/mkdir -p /tmp/suricata_blocked'); + file_put_contents("/tmp/suricata_blocked/suricata_block.pf", ""); + foreach($blocked_ips_array_save as $counter => $fileline) { + if (empty($fileline)) + continue; + $fileline = trim($fileline, " \n\t"); + file_put_contents("/tmp/suricata_blocked/suricata_block.pf", "{$fileline}\n", FILE_APPEND); + } + + // Create a tar gzip archive of blocked host IP addresses + exec("/usr/bin/tar -czf /tmp/{$file_name} -C/tmp/suricata_blocked suricata_block.pf"); + + // If we successfully created the archive, send it to the browser. + if(file_exists("/tmp/{$file_name}")) { + ob_start(); //important or other posts will fail + if (isset($_SERVER['HTTPS'])) { + header('Pragma: '); + header('Cache-Control: '); + } else { + header("Pragma: private"); + header("Cache-Control: private, must-revalidate"); + } + header("Content-Type: application/octet-stream"); + header("Content-length: " . filesize("/tmp/{$file_name}")); + header("Content-disposition: attachment; filename = {$file_name}"); + ob_end_clean(); //important or other post will fail + readfile("/tmp/{$file_name}"); + + // Clean up the temp files and directory + @unlink("/tmp/{$file_name}"); + exec("/bin/rm -fr /tmp/suricata_blocked"); + } else + $savemsg = gettext("An error occurred while creating archive"); + } else + $savemsg = gettext("No content on suricata block list"); +} + +if ($_POST['save']) +{ + /* no errors */ + if (!$input_errors) { + $config['installedpackages']['suricata']['alertsblocks']['brefresh'] = $_POST['brefresh'] ? 'on' : 'off'; + $config['installedpackages']['suricata']['alertsblocks']['blertnumber'] = $_POST['blertnumber']; + + write_config("Suricata pkg: updated BLOCKED tab settings."); + + header("Location: /suricata/suricata_blocked.php"); + exit; + } + +} + +$pgtitle = gettext("Suricata: Blocked Hosts"); +include_once("head.inc"); + +?> + +<body link="#000000" vlink="#000000" alink="#000000"> +<script src="/javascript/filter_log.js" type="text/javascript"></script> + +<?php + +include_once("fbegin.inc"); + +/* refresh every 60 secs */ +if ($pconfig['brefresh'] == 'on') + echo "<meta http-equiv=\"refresh\" content=\"60;url=/suricata/suricata_blocked.php\" />\n"; + +/* Display Alert message */ +if ($input_errors) { + print_input_errors($input_errors); // TODO: add checks +} +if ($savemsg) { + print_info_box($savemsg); +} +?> + +<form action="/suricata/suricata_blocked.php" method="post"> +<input type="hidden" name="ip" id="ip" value=""/> + +<table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tr> + <td> + <?php + $tab_array = array(); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); + $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), true, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); + $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); + ?> + </td> +</tr> +<tr> + <td><div id="mainarea"> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("Blocked Hosts Log View Settings"); ?></td> + </tr> + <tr> + <td width="22%" class="vncell"><?php echo gettext("Save or Remove Hosts"); ?></td> + <td width="78%" class="vtable"> + <input name="download" type="submit" class="formbtns" value="Download" title="<?=gettext("Download list of blocked hosts as a gzip archive");?>"/> + <?php echo gettext("All blocked hosts will be saved."); ?> + <input name="remove" type="submit" class="formbtns" value="Clear" title="<?=gettext("Remove blocks for all listed hosts");?>" + onClick="return confirm('<?=gettext("Are you sure you want to remove all blocked hosts? Click OK to continue or CANCLE to quit.");?>');"/> + <span class="red"><strong><?php echo gettext("Warning:"); ?></strong></span> <?php echo gettext("all hosts will be removed."); ?> + </td> + </tr> + <tr> + <td width="22%" class="vncell"><?php echo gettext("Auto Refresh and Log View"); ?></td> + <td width="78%" class="vtable"> + <input name="save" type="submit" class="formbtns" value=" Save " title="<?=gettext("Save auto-refresh and view settings");?>"/> + <?php echo gettext("Refresh"); ?> <input name="brefresh" type="checkbox" value="on" + <?php if ($config['installedpackages']['suricata']['alertsblocks']['brefresh']=="on" || $config['installedpackages']['suricata']['alertsblocks']['brefresh']=='') echo "checked"; ?>/> + <?php printf(gettext("%sDefault%s is %sON%s."), '<strong>', '</strong>', '<strong>', '</strong>'); ?> + <input name="blertnumber" type="text" class="formfld unknown" id="blertnumber" + size="5" value="<?=htmlspecialchars($bnentries);?>"/> <?php printf(gettext("Enter number of " . + "blocked entries to view. %sDefault%s is %s500%s."), '<strong>', '</strong>', '<strong>', '</strong>'); ?> + </td> + </tr> + <tr> + <td colspan="2" class="listtopic"><?php printf(gettext("Last %s Hosts Blocked by Suricata"), $bnentries); ?></td> + </tr> + <tr> + <td colspan="2"> + <table id="sortabletable1" style="table-layout: fixed;" class="sortable" width="100%" border="0" cellpadding="2" cellspacing="0"> + <colgroup> + <col width="5%" align="center" axis="number"> + <col width="15%" align="center" axis="string"> + <col width="70%" align="left" axis="string"> + <col width="10%" align="center"> + </colgroup> + <thead> + <tr> + <th class="listhdrr" axis="number">#</th> + <th class="listhdrr" axis="string"><?php echo gettext("IP"); ?></th> + <th class="listhdrr" axis="string"><?php echo gettext("Alert Description"); ?></th> + <th class="listhdrr"><?php echo gettext("Remove"); ?></th> + </tr> + </thead> + <tbody> + <?php + + /* set the arrays */ + $blocked_ips_array = suricata_get_blocked_ips(); + if (!empty($blocked_ips_array)) { + foreach ($blocked_ips_array as &$ip) + $ip = inet_pton($ip); + $tmpblocked = array_flip($blocked_ips_array); + $src_ip_list = array(); + foreach (glob("{$suricatalogdir}*/block.log*") as $alertfile) { + $fd = fopen($alertfile, "r"); + if ($fd) { + /* 0 1 2 3 4 5 6 7 8 9 10 */ + /* File format timestamp,action,sig_generator,sig_id,sig_rev,msg,classification,priority,proto,ip,port */ + while (($fields = fgetcsv($fd, 1000, ',', '"')) !== FALSE) { + if(count($fields) < 11) + continue; + $fields[9] = inet_pton($fields[9]); + if (isset($tmpblocked[$fields[9]])) { + if (!is_array($src_ip_list[$fields[9]])) + $src_ip_list[$fields[9]] = array(); + $src_ip_list[$fields[9]][$fields[5]] = "{$fields[5]} - " . substr($fields[0], 0, -7); + } + } + fclose($fd); + } + } + + foreach($blocked_ips_array as $blocked_ip) { + if (is_ipaddr($blocked_ip) && !isset($src_ip_list[$blocked_ip])) + $src_ip_list[$blocked_ip] = array("N\A\n"); + } + + /* build final list, build html */ + $counter = 0; + foreach($src_ip_list as $blocked_ip => $blocked_msg) { + $blocked_desc = implode("<br/>", $blocked_msg); + if($counter > $bnentries) + break; + else + $counter++; + + $block_ip_str = inet_ntop($blocked_ip); + /* Add zero-width space as soft-break opportunity after each colon if we have an IPv6 address */ + $tmp_ip = str_replace(":", ":​", $block_ip_str); + /* Add reverse DNS lookup icons */ + $rdns_link = ""; + $rdns_link .= "<a onclick=\"javascript:getURL('/diag_dns.php?host={$block_ip_str}&dialog_output=true', outputrule);\">"; + $rdns_link .= "<img src='../themes/{$g['theme']}/images/icons/icon_log_d.gif' width='11' height='11' border='0' "; + $rdns_link .= "title='" . gettext("Resolve host via reverse DNS lookup (quick pop-up)") . "' style=\"cursor: pointer;\"></a> "; + $rdns_link .= "<a href='/diag_dns.php?host={$block_ip_str}'>"; + $rdns_link .= "<img src='../themes/{$g['theme']}/images/icons/icon_log.gif' width='11' height='11' border='0' "; + $rdns_link .= "title='" . gettext("Resolve host via reverse DNS lookup") . "'></a>"; + /* use one echo to do the magic*/ + echo "<tr> + <td align=\"center\" valign=\"middle\" class=\"listr\">{$counter}</td> + <td align=\"center\" valign=\"middle\" class=\"listr\">{$tmp_ip}<br/>{$rdns_link}</td> + <td valign=\"middle\" class=\"listr\">{$blocked_desc}</td> + <td align=\"center\" valign=\"middle\" class=\"listr\" sorttable_customkey=\"\"> + <input type=\"image\" name=\"todelete[]\" onClick=\"document.getElementById('ip').value='{$block_ip_str}';\" + src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\" title=\"" . gettext("Delete host from Blocked Table") . "\" border=\"0\" /></td> + </tr>\n"; + } + } + ?> + </tbody> + </table> + </td> + </tr> + <tr> + <td colspan="2" class="vexpl" align="center"> + <?php if (!empty($blocked_ips_array)) { + if ($counter > 1) + echo "{$counter}" . gettext(" host IP addresses are currently being blocked."); + else + echo "{$counter}" . gettext(" host IP address is currently being blocked."); + } + else { + echo gettext("There are currently no hosts being blocked by Suricata."); + } + ?> + </td> + </tr> + </table> + </div> + </td> +</tr> +</table> +</form> +<?php +include("fend.inc"); +?> +</body> +</html> diff --git a/config/suricata/suricata_check_cron_misc.inc b/config/suricata/suricata_check_cron_misc.inc index 88dfd5ff..f750c530 100644 --- a/config/suricata/suricata_check_cron_misc.inc +++ b/config/suricata/suricata_check_cron_misc.inc @@ -3,12 +3,23 @@ * suricata_check_cron_misc.inc * part of pfSense * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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. * @@ -30,80 +41,178 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); -// 'B' => 1, -// 'KB' => 1024, -// 'MB' => 1024 * 1024, -// 'GB' => 1024 * 1024 * 1024, -// 'TB' => 1024 * 1024 * 1024 * 1024, -// 'PB' => 1024 * 1024 * 1024 * 1024 * 1024, +global $g, $config; + +function suricata_check_dir_size_limit($suricataloglimitsize) { + + /******************************************************** + * This function checks the total size of the Suricata * + * logging sub-directory structure and prunes the files * + * for all Suricata interfaces if the size exceeds the * + * passed limit. * + * * + * On Entry: $surictaaloglimitsize = dir size limit * + * in megabytes * + ********************************************************/ + + global $config; + + // Convert Log Limit Size setting from MB to KB + $suricataloglimitsizeKB = round($suricataloglimitsize * 1024); + $suricatalogdirsizeKB = suricata_Getdirsize(SURICATALOGDIR); + + if ($suricatalogdirsizeKB > 0 && $suricatalogdirsizeKB > $suricataloglimitsizeKB) { + log_error(gettext("[Suricata] Log directory size exceeds configured limit of " . number_format($suricataloglimitsize) . " MB set on Global Settings tab. All Suricata log files will be truncated.")); + conf_mount_rw(); + + // Truncate the Rules Update Log file if it exists + if (file_exists(RULES_UPD_LOGFILE)) { + log_error(gettext("[Suricata] Truncating the Rules Update Log file...")); + @file_put_contents(RULES_UPD_LOGFILE, ""); + } + // Initialize an array of the log files we want to prune + $logs = array ( "alerts.log", "http.log", "files-json.log", "tls.log", "stats.log" ); -/* chk if snort log dir is full if so clear it */ -$suricataloglimit = $config['installedpackages']['suricata']['config'][0]['suricataloglimit']; -$suricataloglimitsize = $config['installedpackages']['suricata']['config'][0]['suricataloglimitsize']; + // Clean-up the logs for each configured Suricata instance + foreach ($config['installedpackages']['suricata']['rule'] as $value) { + $if_real = get_real_interface($value['interface']); + $suricata_uuid = $value['uuid']; + $suricata_log_dir = SURICATALOGDIR . "suricata_{$if_real}{$suricata_uuid}"; + log_error(gettext("[Suricata] Truncating logs for {$value['descr']} ({$if_real})...")); + suricata_post_delete_logs($suricata_uuid); + + foreach ($logs as $file) { + // Truncate the log file if it exists + if (file_exists("{$suricata_log_dir}/{$file}")) { + try { + file_put_contents("{$suricata_log_dir}/{$file}", ""); + } catch (Exception $e) { + log_error("[Suricata] Failed to truncate file '{$suricata_log_dir}/{$file}' -- error was {$e->getMessage()}"); + } + } + } -if ($g['booting']==true) - return; + // Check for any captured stored files and clean them up + unlink_if_exists("{$suricata_log_dir}/files/*"); -if ($suricataloglimit == 'off') - return; + // This is needed if suricata is run as suricata user + mwexec('/bin/chmod 660 /var/log/suricata/*', true); + } + conf_mount_ro(); + log_error(gettext("[Suricata] Automatic clean-up of Suricata logs completed.")); + } +} -if (!is_array($config['installedpackages']['suricata']['rule'])) - return; +function suricata_check_rotate_log($log_file, $log_limit, $retention) { + + /******************************************************** + * This function checks the passed log file against * + * the passed size limit and rotates the log file if * + * necessary. It also checks the age of previously * + * rotated logs and removes those older than the * + * rentention parameter. * + * * + * On Entry: $log_file -> full pathname/filename of * + * log file to check * + * $log_limit -> size of file in bytes to * + * trigger rotation. Zero * + * means no rotation. * + * $retention -> retention period in hours * + * for rotated logs. Zero * + * means never remove. * + ********************************************************/ + + // Check the current log to see if it needs rotating. + // If it does, rotate it and put the current time + // on the end of the filename as UNIX timestamp. + if (($log_limit > 0) && (filesize($log_file) >= $log_limit)) { + $newfile = $log_file . "." . strval(time()); + try { + copy($log_file, $newfile); + file_put_contents($log_file, ""); + } catch (Exception $e) { + log_error("[Suricata] Failed to rotate file '{$log_file}' -- error was {$e->getMessage()}"); + } + } -/* Convert Log Limit Size setting from MB to KB */ -$suricataloglimitsizeKB = round($suricataloglimitsize * 1024); -$suricatalogdirsizeKB = suricata_Getdirsize(SURICATALOGDIR); -if ($suricatalogdirsizeKB > 0 && $suricatalogdirsizeKB > $suricataloglimitsizeKB) { - log_error(gettext("[Suricata] Log directory size exceeds configured limit of " . number_format($suricataloglimitsize) . " MB set on Global Settings tab. All Suricata log files will be truncated.")); - conf_mount_rw(); - - /* Truncate the Rules Update Log file if it exists */ - if (file_exists(RULES_UPD_LOGFILE)) { - log_error(gettext("[Suricata] Truncating the Rules Update Log file...")); - $fd = @fopen(RULES_UPD_LOGFILE, "w+"); - if ($fd) - fclose($fd); + // Check previously rotated logs to see if time to + // delete any older than the retention period. + // Rotated logs have a UNIX timestamp appended to + // filename. + if ($retention > 0) { + $now = time(); + $rotated_files = glob("{$log_file}.*"); + foreach ($rotated_files as $file) { + if (($now - filemtime($file)) > ($retention * 3600)) + unlink_if_exists($file); + } + unset($rotated_files); } +} - /* Clean-up the logs for each configured Suricata instance */ - foreach ($config['installedpackages']['suricata']['rule'] as $value) { - $if_real = suricata_get_real_interface($value['interface']); - $suricata_uuid = $value['uuid']; - $suricata_log_dir = SURICATALOGDIR . "suricata_{$if_real}{$suricata_uuid}"; - log_error(gettext("[Suricata] Truncating logs for {$value['descr']} ({$if_real})...")); - suricata_post_delete_logs($suricata_uuid); +/************************* + * Start of main code * + *************************/ - // Initialize an array of the log files we want to prune - $logs = array ( "alerts.log", "http.log", "files-json.log", "tls.log", "stats.log" ); +// If firewall is booting, do nothing +if ($g['booting'] == true) + return; - foreach ($logs as $file) { - // Truncate the log file if it exists - if (file_exists("{$suricata_log_dir}/$file")) { - $fd = @fopen("{$suricata_log_dir}/$file", "w+"); - if ($fd) - fclose($fd); - } - } +// If no interfaces defined, there is nothing to clean up +if (!is_array($config['installedpackages']['suricata']['rule'])) + return; - // Check for any captured stored files and clean them up - $filelist = glob("{$suricata_log_dir}/files/*"); - if (!empty($filelist)) { - foreach ($filelist as $file) - @unlink($file); +$logs = array (); + +// Build an arry of files to check and limits to check them against from our saved configuration +$logs['alerts.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['alert_log_limit_size']; +$logs['alerts.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['alert_log_retention']; +$logs['files-json.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['files_json_log_limit_size']; +$logs['files-json.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['files_json_log_retention']; +$logs['http.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['http_log_limit_size']; +$logs['http.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['http_log_retention']; +$logs['stats.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['stats_log_limit_size']; +$logs['stats.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['stats_log_retention']; +$logs['tls.log']['limit'] = $config['installedpackages']['suricata']['config'][0]['tls_log_limit_size']; +$logs['tls.log']['retention'] = $config['installedpackages']['suricata']['config'][0]['tls_log_retention']; + +// Check log limits and retention in the interface logging directories if enabled +if ($config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] == 'on') { + foreach ($config['installedpackages']['suricata']['rule'] as $value) { + $if_real = get_real_interface($value['interface']); + $suricata_log_dir = SURICATALOGDIR . "suricata_{$if_real}{$value['uuid']}"; + foreach ($logs as $k => $p) + suricata_check_rotate_log("{$suricata_log_dir}/{$k}", $p['limit']*1024, $p['retention']); + + // Prune any aged-out Barnyard2 archived logs if any exist + if (is_dir("{$suricata_log_dir}/barnyard2/archive") && + $config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention'] > 0) { + $now = time(); + $files = glob("{$suricata_log_dir}/barnyard2/archive/unified2.alert.*"); + foreach ($files as $f) { + if (($now - filemtime($f)) > ($config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention'] * 3600)) + unlink_if_exists($f); + } } - - // This is needed if suricata is run as suricata user - mwexec('/bin/chmod 660 /var/log/suricata/*', true); - - // Soft-restart Suricata process to resync logging - if (file_exists("{$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid")) { - log_error(gettext("[Suricata] Restarting logging on {$value['descr']} ({$if_real})...")); - mwexec("/bin/pkill -HUP -F {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid -a"); + unset($files); + + // Prune aged-out File Store files if any exist + if (is_dir("{$suricata_log_dir}/files") && + $config['installedpackages']['suricata']['config'][0]['file_store_retention'] > 0) { + $now = time(); + $files = glob("{$suricata_log_dir}/files/file.*"); + foreach ($files as $f) { + if (($now - filemtime($f)) > ($config['installedpackages']['suricata']['config'][0]['file_store_retention'] * 3600)) + unlink_if_exists($f); + } } + unset($files); } - conf_mount_ro(); - log_error(gettext("[Suricata] Automatic clean-up of Suricata logs completed.")); } +// Check the overall log directory limit (if enabled) and prune if necessary +if ($config['installedpackages']['suricata']['config'][0]['suricataloglimit'] == 'on') + suricata_check_dir_size_limit($config['installedpackages']['suricata']['config'][0]['suricataloglimitsize']); + ?> diff --git a/config/suricata/suricata_check_for_rule_updates.php b/config/suricata/suricata_check_for_rule_updates.php index 9aa14f6e..bb29078f 100644 --- a/config/suricata/suricata_check_for_rule_updates.php +++ b/config/suricata/suricata_check_for_rule_updates.php @@ -2,19 +2,30 @@ /* * suricata_check_for_rule_updates.php * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -95,6 +106,9 @@ $snort_community_rules_filename = GPLV2_DNLD_FILENAME; $snort_community_rules_filename_md5 = GPLV2_DNLD_FILENAME . ".md5"; $snort_community_rules_url = GPLV2_DNLD_URL; +/* Mount the Suricata conf directories R/W so we can modify files there */ +conf_mount_rw(); + /* Set up Emerging Threats rules filenames and URL */ if ($etpro == "on") { $emergingthreats_filename = ETPRO_DNLD_FILENAME; @@ -139,22 +153,54 @@ function suricata_download_file_url($url, $file_out) { global $g, $config, $pkg_interface, $last_curl_error, $fout, $ch, $file_size, $downloaded, $first_progress_update; + $rfc2616 = array( + 100 => "100 Continue", + 101 => "101 Switching Protocols", + 200 => "200 OK", + 201 => "201 Created", + 202 => "202 Accepted", + 203 => "203 Non-Authoritative Information", + 204 => "204 No Content", + 205 => "205 Reset Content", + 206 => "206 Partial Content", + 300 => "300 Multiple Choices", + 301 => "301 Moved Permanently", + 302 => "302 Found", + 303 => "303 See Other", + 304 => "304 Not Modified", + 305 => "305 Use Proxy", + 306 => "306 (Unused)", + 307 => "307 Temporary Redirect", + 400 => "400 Bad Request", + 401 => "401 Unauthorized", + 402 => "402 Payment Required", + 403 => "403 Forbidden", + 404 => "404 Not Found", + 405 => "405 Method Not Allowed", + 406 => "406 Not Acceptable", + 407 => "407 Proxy Authentication Required", + 408 => "408 Request Timeout", + 409 => "409 Conflict", + 410 => "410 Gone", + 411 => "411 Length Required", + 412 => "412 Precondition Failed", + 413 => "413 Request Entity Too Large", + 414 => "414 Request-URI Too Long", + 415 => "415 Unsupported Media Type", + 416 => "416 Requested Range Not Satisfiable", + 417 => "417 Expectation Failed", + 500 => "500 Internal Server Error", + 501 => "501 Not Implemented", + 502 => "502 Bad Gateway", + 503 => "503 Service Unavailable", + 504 => "504 Gateway Timeout", + 505 => "505 HTTP Version Not Supported" + ); + // Initialize required variables for the pfSense "read_body()" function $file_size = 1; $downloaded = 1; $first_progress_update = TRUE; - - - // Array of message strings for HTTP Response Codes - $http_resp_msg = array( 200 => "OK", 202 => "Accepted", 204 => "No Content", 205 => "Reset Content", - 206 => "Partial Content", 301 => "Moved Permanently", 302 => "Found", - 305 => "Use Proxy", 307 => "Temporary Redirect", 400 => "Bad Request", - 401 => "Unauthorized", 402 => "Payment Required", 403 => "Forbidden", - 404 => "Not Found", 405 => "Method Not Allowed", 407 => "Proxy Authentication Required", - 408 => "Request Timeout", 410 => "Gone", 500 => "Internal Server Error", - 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", - 504 => "Gateway Timeout", 505 => "HTTP Version Not Supported" ); - $last_curl_error = ""; $fout = fopen($file_out, "wb"); @@ -204,8 +250,8 @@ function suricata_download_file_url($url, $file_out) { if ($rc === false) $last_curl_error = curl_error($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); - if (isset($http_resp_msg[$http_code])) - $last_curl_error = $http_resp_msg[$http_code]; + if (isset($rfc2616[$http_code])) + $last_curl_error = $rfc2616[$http_code]; curl_close($ch); fclose($fout); @@ -239,7 +285,7 @@ function suricata_check_rule_md5($file_url, $file_dst, $desc = "") { /* error occurred. */ /**********************************************************/ - global $pkg_interface, $suricata_rules_upd_log, $last_curl_error; + global $pkg_interface, $suricata_rules_upd_log, $last_curl_error, $update_errors; $suricatadir = SURICATADIR; $filename_md5 = basename($file_dst); @@ -284,6 +330,7 @@ function suricata_check_rule_md5($file_url, $file_dst, $desc = "") { if ($pkg_interface == "console") error_log(gettext("\tServer error message was: {$last_curl_error}\n"), 3, $suricata_rules_upd_log); error_log(gettext("\t{$desc} will not be updated.\n"), 3, $suricata_rules_upd_log); + $update_errors = true; return false; } } @@ -307,7 +354,7 @@ function suricata_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { /* FALSE if download was not successful. */ /**********************************************************/ - global $pkg_interface, $suricata_rules_upd_log, $last_curl_error; + global $pkg_interface, $suricata_rules_upd_log, $last_curl_error, $update_errors; $suricatadir = SURICATADIR; $filename = basename($file_dst); @@ -337,6 +384,7 @@ function suricata_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { error_log(gettext("\tDownloaded {$desc} file MD5: " . md5_file($file_dst) . "\n"), 3, $suricata_rules_upd_log); error_log(gettext("\tExpected {$desc} file MD5: {$file_md5}\n"), 3, $suricata_rules_upd_log); error_log(gettext("\t{$desc} file download failed. {$desc} will not be updated.\n"), 3, $suricata_rules_upd_log); + $update_errors = true; return false; } return true; @@ -349,13 +397,13 @@ function suricata_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { if ($pkg_interface == "console") error_log(gettext("\tThe error text was: {$last_curl_error}\n"), 3, $suricata_rules_upd_log); error_log(gettext("\t{$desc} will not be updated.\n"), 3, $suricata_rules_upd_log); + $update_errors = true; return false; } } /* Start of main code */ -conf_mount_rw(); /* remove old $tmpfname files if present */ if (is_dir("{$tmpfname}")) @@ -375,6 +423,7 @@ if (file_exists($suricata_rules_upd_log)) { /* Log start time for this rules update */ error_log(gettext("Starting rules update... Time: " . date("Y-m-d H:i:s") . "\n"), 3, $suricata_rules_upd_log); $last_curl_error = ""; +$update_errors = false; /* Check for and download any new Emerging Threats Rules sigs */ if ($emergingthreats == 'on') { @@ -426,22 +475,32 @@ if ($emergingthreats == 'on') { /* Remove the old Emerging Threats rules files */ $eto_prefix = ET_OPEN_FILE_PREFIX; $etpro_prefix = ET_PRO_FILE_PREFIX; - array_map('unlink', glob("{$suricatadir}rules/{$eto_prefix}*.rules")); - array_map('unlink', glob("{$suricatadir}rules/{$etpro_prefix}*.rules")); - array_map('unlink', glob("{$suricatadir}rules/{$eto_prefix}*ips.txt")); - array_map('unlink', glob("{$suricatadir}rules/{$etpro_prefix}*ips.txt")); + unlink_if_exists("{$suricatadir}rules/{$eto_prefix}*.rules"); + unlink_if_exists("{$suricatadir}rules/{$etpro_prefix}*.rules"); + unlink_if_exists("{$suricatadir}rules/{$eto_prefix}*ips.txt"); + unlink_if_exists("{$suricatadir}rules/{$etpro_prefix}*ips.txt"); - // The code below renames ET-Pro files with a prefix, so we + // The code below renames ET files with a prefix, so we // skip renaming the Suricata default events rule files - // that are also bundled in the ET-Pro rules. - $default_rules = array( "decoder-events.rules", "files.rules", "http-events.rules", "smtp-events.rules", "stream-events.rules" ); + // that are also bundled in the ET rules. + $default_rules = array( "decoder-events.rules", "files.rules", "http-events.rules", "smtp-events.rules", "stream-events.rules", "tls-events.rules" ); $files = glob("{$tmpfname}/emerging/rules/*.rules"); + // Determine the correct prefix to use based on which + // Emerging Threats rules package is enabled. + if ($etpro == "on") + $prefix = ET_PRO_FILE_PREFIX; + else + $prefix = ET_OPEN_FILE_PREFIX; foreach ($files as $file) { $newfile = basename($file); - if ($etpro == "on" && !in_array($newfile, $default_rules)) - @copy($file, "{$suricatadir}rules/" . ET_PRO_FILE_PREFIX . "{$newfile}"); - else + if (in_array($newfile, $default_rules)) @copy($file, "{$suricatadir}rules/{$newfile}"); + else { + if (strpos($newfile, $prefix) === FALSE) + @copy($file, "{$suricatadir}rules/{$prefix}{$newfile}"); + else + @copy($file, "{$suricatadir}rules/{$newfile}"); + } } /* IP lists for Emerging Threats rules */ $files = glob("{$tmpfname}/emerging/rules/*ips.txt"); @@ -478,7 +537,7 @@ if ($snortdownload == 'on') { if (file_exists("{$tmpfname}/{$snort_filename}")) { /* Remove the old Snort rules files */ $vrt_prefix = VRT_FILE_PREFIX; - array_map('unlink', glob("{$suricatadir}rules/{$vrt_prefix}*.rules")); + unlink_if_exists("{$suricatadir}rules/{$vrt_prefix}*.rules"); if ($pkg_interface <> "console") { update_status(gettext("Extracting Snort VRT rules...")); @@ -646,17 +705,38 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = $rebuild_rules = false; /* Restart Suricata if already running and we are not rebooting to pick up the new rules. */ - if (is_process_running("suricata") && !$g['booting']) { - if ($pkg_interface <> "console") { - update_status(gettext('Restarting Suricata to activate the new set of rules...')); - update_output_window(gettext("Please wait ... restarting Suricata will take some time...")); + if (is_process_running("suricata") && !$g['booting'] && + !empty($config['installedpackages']['suricata']['rule'])) { + + // See if "Live Reload" is configured and signal each Suricata instance + // if enabled, else just do a hard restart of all the instances. + if ($config['installedpackages']['suricata']['config'][0]['live_swap_updates'] == 'on') { + if ($pkg_interface <> "console") { + update_status(gettext('Signalling Suricata to live-load the new set of rules...')); + update_output_window(gettext("Please wait ... the process should complete in a few seconds...")); + } + log_error(gettext("[Suricata] Live-Reload of rules from auto-update is enabled...")); + error_log(gettext("\tLive-Reload of updated rules is enabled...\n"), 3, $suricata_rules_upd_log); + foreach ($config['installedpackages']['suricata']['rule'] as $value) { + $if_real = get_real_interface($value['interface']); + suricata_reload_config($value); + error_log(gettext("\tLive swap of updated rules requested for " . convert_friendly_interface_to_friendly_descr($value['interface']) . ".\n"), 3, $suricata_rules_upd_log); + } + log_error(gettext("[Suricata] Live-Reload of updated rules completed...")); + error_log(gettext("\tLive-Reload of the updated rules is complete.\n"), 3, $suricata_rules_upd_log); + } + else { + if ($pkg_interface <> "console") { + update_status(gettext('Restarting Suricata to activate the new set of rules...')); + update_output_window(gettext("Please wait ... restarting Suricata will take some time...")); + } + error_log(gettext("\tRestarting Suricata to activate the new set of rules...\n"), 3, $suricata_rules_upd_log); + restart_service("suricata"); + if ($pkg_interface <> "console") + update_output_window(gettext("Suricata has restarted with your new set of rules...")); + log_error(gettext("[Suricata] Suricata has restarted with your new set of rules...")); + error_log(gettext("\tSuricata has restarted with your new set of rules.\n"), 3, $suricata_rules_upd_log); } - error_log(gettext("\tRestarting Suricata to activate the new set of rules...\n"), 3, $suricata_rules_upd_log); - restart_service("suricata"); - if ($pkg_interface <> "console") - update_output_window(gettext("Suricata has restarted with your new set of rules...")); - log_error(gettext("[Suricata] Suricata has restarted with your new set of rules...")); - error_log(gettext("\tSuricata has restarted with your new set of rules.\n"), 3, $suricata_rules_upd_log); } else { if ($pkg_interface <> "console") @@ -666,13 +746,17 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = // Remove old $tmpfname files if (is_dir("{$tmpfname}")) { - if ($pkg_interface <> "console") + if ($pkg_interface <> "console") { update_status(gettext("Cleaning up after rules extraction...")); + update_output_window(gettext("Removing {$tmpfname} directory...")); + } exec("/bin/rm -r {$tmpfname}"); } -if ($pkg_interface <> "console") +if ($pkg_interface <> "console") { update_status(gettext("The Rules update has finished...")); + update_output_window(""); +} log_error(gettext("[Suricata] The Rules update has finished.")); error_log(gettext("The Rules update has finished. Time: " . date("Y-m-d H:i:s"). "\n\n"), 3, $suricata_rules_upd_log); conf_mount_ro(); @@ -680,4 +764,12 @@ conf_mount_ro(); // Restore the state of $pkg_interface $pkg_interface = $pkg_interface_orig; +/* Save this update status to the configuration file */ +if ($update_errors) + $config['installedpackages']['suricata']['config'][0]['last_rule_upd_status'] = gettext("failed"); +else + $config['installedpackages']['suricata']['config'][0]['last_rule_upd_status'] = gettext("success"); +$config['installedpackages']['suricata']['config'][0]['last_rule_upd_time'] = time(); +write_config(); + ?> diff --git a/config/suricata/suricata_define_vars.php b/config/suricata/suricata_define_vars.php index b1cbfee9..d072ff42 100644 --- a/config/suricata/suricata_define_vars.php +++ b/config/suricata/suricata_define_vars.php @@ -3,12 +3,23 @@ * suricata_define_vars.php * part of pfSense * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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. * @@ -34,9 +45,10 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); global $g, $rebuild_rules; -$id = $_GET['id']; -if (isset($_POST['id'])) +if (isset($_POST['id']) && is_numericint($_POST['id'])) $id = $_POST['id']; +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); if (is_null($id)) { header("Location: /suricata/suricata_interfaces.php"); exit; @@ -157,13 +169,16 @@ if ($savemsg) <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; $tab_array = array(); @@ -175,7 +190,7 @@ if ($savemsg) $tab_array[] = array($menu_iface . gettext("App Parsers"), false, "/suricata/suricata_app_parsers.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Variables"), true, "/suricata/suricata_define_vars.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Barnyard2"), false, "/suricata/suricata_barnyard.php?id={$id}"); - display_top_tabs($tab_array); + display_top_tabs($tab_array, true); ?> </td></tr> <tr> diff --git a/config/suricata/suricata_download_rules.php b/config/suricata/suricata_download_rules.php index 26737dcf..2de286ba 100644 --- a/config/suricata/suricata_download_rules.php +++ b/config/suricata/suricata_download_rules.php @@ -2,19 +2,31 @@ /* * suricata_download_rules.php * + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 diff --git a/config/suricata/suricata_download_updates.php b/config/suricata/suricata_download_updates.php index ecfd5f8b..b5377351 100644 --- a/config/suricata/suricata_download_updates.php +++ b/config/suricata/suricata_download_updates.php @@ -3,19 +3,30 @@ * suricata_download_updates.php * part of pfSense * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -35,38 +46,72 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); $suricatadir = SURICATADIR; $suricata_rules_upd_log = RULES_UPD_LOGFILE; -/* load only javascript that is needed */ -$suricata_load_jquery = 'yes'; -$suricata_load_jquery_colorbox = 'yes'; $snortdownload = $config['installedpackages']['suricata']['config'][0]['enable_vrt_rules']; $emergingthreats = $config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']; $etpro = $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']; $snortcommunityrules = $config['installedpackages']['suricata']['config'][0]['snortcommunityrules']; +/* Get last update information if available */ +if (!empty($config['installedpackages']['suricata']['config'][0]['last_rule_upd_time'])) + $last_rule_upd_time = date('M-d Y H:i', $config['installedpackages']['suricata']['config'][0]['last_rule_upd_time']); +else + $last_rule_upd_time = gettext("Unknown"); +if (!empty($config['installedpackages']['suricata']['config'][0]['last_rule_upd_status'])) + $last_rule_upd_status = htmlspecialchars($config['installedpackages']['suricata']['config'][0]['last_rule_upd_status']); +else + $last_rule_upd_status = gettext("Unknown"); + $snort_rules_file = VRT_DNLD_FILENAME; $snort_community_rules_filename = GPLV2_DNLD_FILENAME; if ($etpro == "on") { $emergingthreats_filename = ETPRO_DNLD_FILENAME; - $et_name = "EMERGING THREATS PRO RULES"; + $et_name = "Emerging Threats Pro Rules"; } else { $emergingthreats_filename = ET_DNLD_FILENAME; - $et_name = "EMERGING THREATS RULES"; + $et_name = "Emerging Threats Open Rules"; } /* quick md5 chk of downloaded rules */ -$snort_org_sig_chk_local = 'N/A'; -if (file_exists("{$suricatadir}{$snort_rules_file}.md5")) +if ($snortdownload == 'on') { + $snort_org_sig_chk_local = 'Not Downloaded'; + $snort_org_sig_date = 'Not Downloaded'; +} +else { + $snort_org_sig_chk_local = 'Not Enabled'; + $snort_org_sig_date = 'Not Enabled'; +} +if (file_exists("{$suricatadir}{$snort_rules_file}.md5")){ $snort_org_sig_chk_local = file_get_contents("{$suricatadir}{$snort_rules_file}.md5"); + $snort_org_sig_date = date(DATE_RFC850, filemtime("{$suricatadir}{$snort_rules_file}.md5")); +} -$emergingt_net_sig_chk_local = 'N/A'; -if (file_exists("{$suricatadir}{$emergingthreats_filename}.md5")) +if ($etpro == "on" || $emergingthreats == "on") { + $emergingt_net_sig_chk_local = 'Not Downloaded'; + $emergingt_net_sig_date = 'Not Downloaded'; +} +else { + $emergingt_net_sig_chk_local = 'Not Enabled'; + $emergingt_net_sig_date = 'Not Enabled'; +} +if (file_exists("{$suricatadir}{$emergingthreats_filename}.md5")) { $emergingt_net_sig_chk_local = file_get_contents("{$suricatadir}{$emergingthreats_filename}.md5"); + $emergingt_net_sig_date = date(DATE_RFC850, filemtime("{$suricatadir}{$emergingthreats_filename}.md5")); +} -$snort_community_sig_chk_local = 'N/A'; -if (file_exists("{$suricatadir}{$snort_community_rules_filename}.md5")) +if ($snortcommunityrules == 'on') { + $snort_community_sig_chk_local = 'Not Downloaded'; + $snort_community_sig_sig_date = 'Not Downloaded'; +} +else { + $snort_community_sig_chk_local = 'Not Enabled'; + $snort_community_sig_sig_date = 'Not Enabled'; +} +if (file_exists("{$suricatadir}{$snort_community_rules_filename}.md5")) { $snort_community_sig_chk_local = file_get_contents("{$suricatadir}{$snort_community_rules_filename}.md5"); + $snort_community_sig_sig_date = date(DATE_RFC850, filemtime("{$suricatadir}{$snort_community_rules_filename}.md5")); +} /* Check for postback to see if we should clear the update log file. */ if ($_POST['clear']) { @@ -74,7 +119,28 @@ if ($_POST['clear']) { mwexec("/bin/rm -f {$suricata_rules_upd_log}"); } -if ($_POST['update']) { +if ($_POST['check']) { + // Go see if new updates for rule sets are available + header("Location: /suricata/suricata_download_rules.php"); + exit; +} + +if ($_POST['force']) { + // Mount file system R/W since we need to remove files + conf_mount_rw(); + + // Remove the existing MD5 signature files to force a download + if (file_exists("{$suricatadir}{$emergingthreats_filename}.md5")) + @unlink("{$suricatadir}{$emergingthreats_filename}.md5"); + if (file_exists("{$suricatadir}{$snort_community_rules_filename}.md5")) + @unlink("{$suricatadir}{$snort_community_rules_filename}.md5"); + if (file_exists("{$suricatadir}{$snort_rules_file}.md5")) + @unlink("{$suricatadir}{$snort_rules_file}.md5"); + + // Revert file system to R/O. + conf_mount_ro(); + + // Go download the updates header("Location: /suricata/suricata_download_rules.php"); exit; } @@ -91,6 +157,9 @@ if ($_POST['view']&& $suricata_rules_upd_log_chk == 'yes') { $input_errors[] = gettext("Unable to read log file: {$suricata_rules_upd_log}"); } +if ($_POST['hide']) + $contents = ""; + $pgtitle = gettext("Suricata: Update Rules Set Files"); include_once("head.inc"); ?> @@ -118,9 +187,12 @@ include_once("head.inc"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), true, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); ?> </td></tr> <tr> @@ -128,21 +200,32 @@ include_once("head.inc"); <div id="mainarea"> <table id="maintable4" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> - <td valign="top" class="listtopic" align="center"><?php echo gettext("INSTALLED RULE SET MD5 SIGNATURES");?></td> + <td valign="top" class="listtopic" align="center"><?php echo gettext("INSTALLED RULE SET MD5 SIGNATURE");?></td> </tr> <tr> <td align="center"><br/> - <table width="100%" border="0" cellpadding="2" cellspacing="2"> + <table width="95%" border="0" cellpadding="2" cellspacing="2"> + <thead> + <tr> + <th class="listhdrr"><?=gettext("Rule Set Name/Publisher");?></th> + <th class="listhdrr"><?=gettext("MD5 Signature Hash");?></th> + <th class="listhdrr"><?=gettext("MD5 Signature Date");?></th> + </tr> + </thead> <tr> - <td align="right" class="vexpl"><b><?=$et_name;?> ---></b></td> - <td class="vexpl"><? echo $emergingt_net_sig_chk_local; ?></td> + <td align="center" class="vncell vexpl"><b><?=$et_name;?></b></td> + <td align="center" class="vncell vexpl"><? echo trim($emergingt_net_sig_chk_local);?></td> + <td align="center" class="vncell vexpl"><?php echo gettext($emergingt_net_sig_date);?></td> </tr> <tr> - <td align="right" class="vexpl"><b>SNORT VRT RULES ---></b></td> - <td class="vexpl"><? echo $snort_org_sig_chk_local; ?></td> + <td align="center" class="vncell vexpl"><b>Snort VRT Rules</b></td> + <td align="center" class="vncell vexpl"><? echo trim($snort_org_sig_chk_local);?></td> + <td align="center" class="vncell vexpl"><?php echo gettext($snort_org_sig_date);?></td> </tr> - <td align="right" class="vexpl"><b>SNORT GPLv2 COMMUNITY RULES ---></b></td> - <td class="vexpl"><? echo $snort_community_sig_chk_local; ?></td> + <tr> + <td align="center" class="vncell vexpl"><b>Snort GPLv2 Community Rules</b></td> + <td align="center" class="vncell vexpl"><? echo trim($snort_community_sig_chk_local);?></td> + <td align="center" class="vncell vexpl"><?php echo gettext($snort_community_sig_sig_date);?></td> </tr> </table><br/> </td> @@ -152,17 +235,39 @@ include_once("head.inc"); </tr> <tr> <td align="center"> + <table width="45%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr> + <td class="list" align="right"><strong><?php echo gettext("Last Update:");?></strong></td> + <td class="list" align="left"><?php echo $last_rule_upd_time;?></td> + </tr> + <tr> + <td class="list" align="right"><strong><?php echo gettext("Result:");?></strong></td> + <td class="list" align="left"><?php echo $last_rule_upd_status;?></td> + </tr> + </tbody> + </table> + </td> + </tr> + <tr> + <td align="center"> <?php if ($snortdownload != 'on' && $emergingthreats != 'on' && $etpro != 'on'): ?> - <br/><button disabled="disabled"><?php echo gettext("Update Rules"); ?></button><br/> - <p style="text-align:left;"> - <font color="red" size="2px"><b><?php echo gettext("WARNING:");?></b></font><font size="1px" color="#000000"> + <br/><button disabled="disabled"><?=gettext("Check");?></button> + <button disabled="disabled"><?=gettext("Force");?></button> + <br/> + <p style="text-align:center;" class="vexpl"> + <font class="red"><b><?php echo gettext("WARNING:");?></b></font> <?php echo gettext('No rule types have been selected for download. ') . gettext('Visit the ') . '<a href="/suricata/suricata_global.php">Global Settings Tab</a>' . gettext(' to select rule types.'); ?> - </font><br/></p> + <br/></p> <?php else: ?> <br/> - <input type="submit" value="<?php echo gettext(" Update "); ?>" name="update" id="submit" class="formbtn" - title="<?php echo gettext("Check for new updates to configured rulesets"); ?>"/><br/><br/> + <input type="submit" value="<?=gettext("Check");?>" name="check" id="check" class="formbtn" + title="<?php echo gettext("Check for new updates to enabled rule sets"); ?>"/> + <input type="submit" value="<?=gettext("Force");?>" name="force" id="force" class="formbtn" + title="<?=gettext("Force an update of all enabled rule sets");?>" + onclick="return confirm('<?=gettext("This will zero-out the MD5 hashes to force a fresh download of all enabled rule sets. Click OK to continue or CANCEL to quit");?>');"/> + <br/><br/> <?php endif; ?> </td> </tr> @@ -174,15 +279,20 @@ include_once("head.inc"); <td align="center" valign="middle" class="vexpl"> <?php if ($suricata_rules_upd_log_chk == 'yes'): ?> <br/> - <input type="submit" value="<?php echo gettext("View Log"); ?>" name="view" id="view" class="formbtn" - title="<?php echo gettext("View rules update log contents"); ?>"/> - - <input type="submit" value="<?php echo gettext("Clear Log"); ?>" name="clear" id="clear" class="formbtn" - title="<?php echo gettext("Clear rules update log contents"); ?>" onClick="return confirm('Are you sure?\nOK to confirm, or CANCEL to quit');"/> + <?php if (!empty($contents)): ?> + <input type="submit" value="<?php echo gettext("Hide"); ?>" name="hide" id="hide" class="formbtn" + title="<?php echo gettext("Hide rules update log"); ?>"/> + <?php else: ?> + <input type="submit" value="<?php echo gettext("View"); ?>" name="view" id="view" class="formbtn" + title="<?php echo gettext("View rules update log"); ?>"/> + <?php endif; ?> + + <input type="submit" value="<?php echo gettext("Clear"); ?>" name="clear" id="clear" class="formbtn" + title="<?php echo gettext("Clear rules update log"); ?>" onClick="return confirm('Are you sure you want to delete the log contents?\nOK to confirm, or CANCEL to quit');"/> <br/> <?php else: ?> <br/> - <button disabled='disabled'><?php echo gettext("View Log"); ?></button> <?php echo gettext("Log is empty."); ?><br/> + <button disabled='disabled'><?php echo gettext("View Log"); ?></button><br/><?php echo gettext("Log is empty."); ?><br/> <?php endif; ?> <br/><?php echo gettext("The log file is limited to 1024K in size and automatically clears when the limit is exceeded."); ?><br/><br/> </td> @@ -201,9 +311,9 @@ include_once("head.inc"); <?php endif; ?> <tr> <td align="center"> - <span class="vexpl"><br/><br/> + <span class="vexpl"><br/> <span class="red"><b><?php echo gettext("NOTE:"); ?></b></span> - <a href="http://www.snort.org/" target="_blank"><?php echo gettext("Snort.org") . "</a>" . + <a href="http://www.snort.org/" target="_blank"><?php echo gettext("Snort.org") . "</a>" . gettext(" and ") . "<a href=\"http://www.emergingthreats.net/\" target=\"_blank\">" . gettext("EmergingThreats.net") . "</a>" . gettext(" will go down from time to time. Please be patient."); ?></span><br/> </td> diff --git a/config/suricata/suricata_flow_stream.php b/config/suricata/suricata_flow_stream.php index 3a677d3a..ba594d55 100644 --- a/config/suricata/suricata_flow_stream.php +++ b/config/suricata/suricata_flow_stream.php @@ -3,12 +3,23 @@ * suricata_flow_stream.php * part of pfSense * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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. * @@ -28,25 +39,28 @@ * POSSIBILITY OF SUCH DAMAGE. */ - require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); global $g, $rebuild_rules; -$id = $_GET['id']; -if (isset($_POST['id'])) +if (isset($_POST['id']) && is_numericint($_POST['id'])) $id = $_POST['id']; -if (is_null($id)) { - header("Location: /suricata/suricata_interfaces.php"); - exit; -} +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); +if (is_null($id)) + $id=0; if (!is_array($config['installedpackages']['suricata'])) $config['installedpackages']['suricata'] = array(); if (!is_array($config['installedpackages']['suricata']['rule'])) $config['installedpackages']['suricata']['rule'] = array(); +// Initialize required array variables as necessary +if (!is_array($config['aliases']['alias'])) + $config['aliases']['alias'] = array(); +$a_aliases = $config['aliases']['alias']; + // Initialize Host-OS Policy engine arrays if necessary if (!is_array($config['installedpackages']['suricata']['rule'][$id]['host_os_policy']['item'])) $config['installedpackages']['suricata']['rule'][$id]['host_os_policy']['item'] = array(); @@ -55,6 +69,12 @@ $a_nat = &$config['installedpackages']['suricata']['rule']; $host_os_policy_engine_next_id = count($a_nat[$id]['host_os_policy']['item']); +// Build a lookup array of currently used engine 'bind_to' Aliases +// so we can screen matching Alias names from the list. +$used = array(); +foreach ($a_nat[$id]['host_os_policy']['item'] as $v) + $used[$v['bind_to']] = true; + $pconfig = array(); if (isset($id) && $a_nat[$id]) { /* Get current values from config for page form fields */ @@ -76,29 +96,129 @@ if (isset($id) && $a_nat[$id]) { $pconfig['host_os_policy'] = $a_nat[$id]['host_os_policy']; } -// Check for returned "selected alias" if action is import -if ($_GET['act'] == "import" && isset($_GET['varname']) && !empty($_GET['varvalue'])) { - $pconfig[$_GET['varname']] = $_GET['varvalue']; +// Check for "import or select alias mode" and set flags if TRUE. +// "selectalias", when true, displays radio buttons to limit +// multiple selections. +if ($_POST['import_alias']) { + $importalias = true; + $selectalias = false; + $title = "Host Operating System Policy"; +} +elseif ($_POST['select_alias']) { + $importalias = true; + $selectalias = true; + $title = "Host Operating System Policy"; + + // Preserve current OS Policy Engine settings + $eng_id = $_POST['eng_id']; + $eng_name = $_POST['policy_name']; + $eng_bind = $_POST['policy_bind_to']; + $eng_policy = $_POST['policy']; + $mode = "add_edit_os_policy"; } -if ($_GET['act'] && isset($_GET['eng_id'])) { +if ($_POST['save_os_policy']) { + if ($_POST['eng_id'] != "") { + $eng_id = $_POST['eng_id']; + + // Grab all the POST values and save in new temp array + $engine = array(); + $policy_name = trim($_POST['policy_name']); + if ($policy_name) { + $engine['name'] = $policy_name; + } + else { + $input_errors[] = gettext("The 'Policy Name' value cannot be blank."); + $add_edit_os_policy = true; + } + if ($_POST['policy_bind_to']) { + if (is_alias($_POST['policy_bind_to'])) + $engine['bind_to'] = $_POST['policy_bind_to']; + elseif (strtolower(trim($_POST['policy_bind_to'])) == "all") + $engine['bind_to'] = "all"; + else { + $input_errors[] = gettext("You must provide a valid Alias or the reserved keyword 'all' for the 'Bind-To IP Address' value."); + $add_edit_os_policy = true; + } + } + else { + $input_errors[] = gettext("The 'Bind-To IP Address' value cannot be blank. Provide a valid Alias or the reserved keyword 'all'."); + $add_edit_os_policy = true; + } + + if ($_POST['policy']) { $engine['policy'] = $_POST['policy']; } else { $engine['policy'] = "bsd"; } + + // Can only have one "all" Bind_To address + if ($engine['bind_to'] == "all" && $engine['name'] <> "default") { + $input_errors[] = gettext("Only one default OS-Policy Engine can be bound to all addresses."); + $add_edit_os_policy = true; + $pengcfg = $engine; + } + // if no errors, write new entry to conf + if (!$input_errors) { + if (isset($eng_id) && $a_nat[$id]['host_os_policy']['item'][$eng_id]) { + $a_nat[$id]['host_os_policy']['item'][$eng_id] = $engine; + } + else + $a_nat[$id]['host_os_policy']['item'][] = $engine; + + /* Reorder the engine array to ensure the */ + /* 'bind_to=all' entry is at the bottom */ + /* if it contains more than one entry. */ + if (count($a_nat[$id]['host_os_policy']['item']) > 1) { + $i = -1; + foreach ($a_nat[$id]['host_os_policy']['item'] as $f => $v) { + if ($v['bind_to'] == "all") { + $i = $f; + break; + } + } + /* Only relocate the entry if we */ + /* found it, and it's not already */ + /* at the end. */ + if ($i > -1 && ($i < (count($a_nat[$id]['host_os_policy']['item']) - 1))) { + $tmp = $a_nat[$id]['host_os_policy']['item'][$i]; + unset($a_nat[$id]['host_os_policy']['item'][$i]); + $a_nat[$id]['host_os_policy']['item'][] = $tmp; + } + } + + // Now write the new engine array to conf + write_config(); + $pconfig['host_os_policy']['item'] = $a_nat[$id]['host_os_policy']['item']; + } + } +} +elseif ($_POST['add_os_policy']) { + $add_edit_os_policy = true; + $pengcfg = array( "name" => "engine_{$host_os_policy_engine_next_id}", "bind_to" => "", "policy" => "bsd" ); + $eng_id = $host_os_policy_engine_next_id; +} +elseif ($_POST['edit_os_policy']) { + if ($_POST['eng_id'] != "") { + $add_edit_os_policy = true; + $eng_id = $_POST['eng_id']; + $pengcfg = $a_nat[$id]['host_os_policy']['item'][$eng_id]; + } +} +elseif ($_POST['del_os_policy']) { $natent = array(); $natent = $pconfig; - if ($_GET['act'] == "del_host_os_policy") - unset($natent['host_os_policy']['item'][$_GET['eng_id']]); - + if ($_POST['eng_id'] != "") { + unset($natent['host_os_policy']['item'][$_POST['eng_id']]); + $pconfig = $natent; + } if (isset($id) && $a_nat[$id]) { $a_nat[$id] = $natent; write_config(); } - - header("Location: /suricata/suricata_flow_stream.php?id=$id"); - exit; } - -if ($_POST['ResetAll']) { +elseif ($_POST['cancel_os_policy']) { + $add_edit_os_policy = false; +} +elseif ($_POST['ResetAll']) { /* Reset all the settings to defaults */ $pconfig['ip_max_frags'] = "65535"; @@ -143,7 +263,7 @@ if ($_POST['ResetAll']) { /* Log a message at the top of the page to inform the user */ $savemsg = gettext("All flow and stream settings have been reset to their defaults."); } -elseif ($_POST['Submit']) { +elseif ($_POST['save']) { $natent = array(); $natent = $pconfig; @@ -191,15 +311,14 @@ elseif ($_POST['Submit']) { /**************************************************/ /* If we have a valid rule ID, save configuration */ - /* then update the suricata.conf file and rebuild */ - /* the rules for this interface. */ + /* then update the suricata.conf file for this */ + /* interface. */ /**************************************************/ if (isset($id) && $a_nat[$id]) { $a_nat[$id] = $natent; write_config(); - $rebuild_rules = true; - suricata_generate_yaml($natent); $rebuild_rules = false; + suricata_generate_yaml($natent); } header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); @@ -211,6 +330,99 @@ elseif ($_POST['Submit']) { exit; } } +elseif ($_POST['save_import_alias']) { + // If saving out of "select alias" mode, + // then return to Host OS Policy Engine edit + // page. + if ($_POST['mode'] =='add_edit_os_policy') { + $pengcfg = array(); + $eng_id = $_POST['eng_id']; + $pengcfg['name'] = $_POST['eng_name']; + $pengcfg['bind_to'] = $_POST['eng_bind']; + $pengcfg['policy'] = $_POST['eng_policy']; + $add_edit_os_policy = true; + $mode = "add_edit_os_policy"; + + if (is_array($_POST['aliastoimport']) && count($_POST['aliastoimport']) == 1) { + $pengcfg['bind_to'] = $_POST['aliastoimport'][0]; + $importalias = false; + $selectalias = false; + } + else { + $input_errors[] = gettext("No Alias is selected for import. Nothing to SAVE."); + $importalias = true; + $selectalias = true; + $eng_id = $_POST['eng_id']; + $eng_name = $_POST['eng_name']; + $eng_bind = $_POST['eng_bind']; + $eng_policy = $_POST['eng_policy']; + } + } + else { + // Assume we are importing one or more aliases + // for use in new Host OS Policy engines. + $engine = array( "name" => "", "bind_to" => "", "policy" => "bsd" ); + + // See if anything was checked to import + if (is_array($_POST['aliastoimport']) && count($_POST['aliastoimport']) > 0) { + foreach ($_POST['aliastoimport'] as $item) { + $engine['name'] = strtolower($item); + $engine['bind_to'] = $item; + $a_nat[$id]['host_os_policy']['item'][] = $engine; + } + } + else { + $input_errors[] = gettext("No entries were selected for import. Please select one or more Aliases for import and click SAVE."); + $importalias = true; + } + + // if no errors, write new entry to conf + if (!$input_errors) { + // Reorder the engine array to ensure the + // 'bind_to=all' entry is at the bottom if + // the array contains more than one entry. + if (count($a_nat[$id]['host_os_policy']['item']) > 1) { + $i = -1; + foreach ($a_nat[$id]['host_os_policy']['item'] as $f => $v) { + if ($v['bind_to'] == "all") { + $i = $f; + break; + } + } + // Only relocate the entry if we + // found it, and it's not already + // at the end. + if ($i > -1 && ($i < (count($a_nat[$id]['host_os_policy']['item']) - 1))) { + $tmp = $a_nat[$id]['host_os_policy']['item'][$i]; + unset($a_nat[$id]['host_os_policy']['item'][$i]); + $a_nat[$id]['host_os_policy']['item'][] = $tmp; + } + $pconfig['host_os_policy']['item'] = $a_nat[$id]['host_os_policy']['item']; + } + + // Write the new engine array to config file + write_config(); + $importalias = false; + $selectalias = false; + } + } +} +elseif ($_POST['cancel_import_alias']) { + $importalias = false; + $selectalias = false; + $eng_id = $_POST['eng_id']; + + // If cancelling out of "select alias" mode, + // then return to Host OS Policy Engine edit + // page. + if ($_POST['mode'] == 'add_edit_os_policy') { + $pengcfg = array(); + $pengcfg['name'] = $_POST['eng_name']; + $pengcfg['bind_to'] = $_POST['eng_bind']; + $pengcfg['policy'] = $_POST['eng_policy']; + $add_edit_os_policy = true; + } +} $if_friendly = convert_friendly_interface_to_friendly_descr($pconfig['interface']); $pgtitle = gettext("Suricata: Interface {$if_friendly} - Flow and Stream"); @@ -218,40 +430,34 @@ include_once("head.inc"); ?> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> -<?php include("fbegin.inc"); ?> -<?php if($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';} - - - /* Display Alert message */ +<?php include("fbegin.inc"); + /* Display error or save message */ if ($input_errors) { print_input_errors($input_errors); // TODO: add checks } - if ($savemsg) { print_info_box($savemsg); } - ?> -<script type="text/javascript" src="/javascript/autosuggest.js"> -</script> -<script type="text/javascript" src="/javascript/suggestions.js"> -</script> +<form action="suricata_flow_stream.php" method="post" name="iform" id="iform"> +<input type="hidden" name="eng_id" id="eng_id" value="<?=$eng_id;?>"/> +<input type="hidden" name="id" id="id" value="<?=$id;?>"/> -<form action="suricata_flow_stream.php" method="post" - enctype="multipart/form-data" name="iform" id="iform"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); - $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td>'; $menu_iface=($if_friendly?substr($if_friendly,0,5)." ":"Iface "); @@ -263,10 +469,25 @@ include_once("head.inc"); $tab_array[] = array($menu_iface . gettext("App Parsers"), false, "/suricata/suricata_app_parsers.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Variables"), false, "/suricata/suricata_define_vars.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Barnyard2"), false, "/suricata/suricata_barnyard.php?id={$id}"); - display_top_tabs($tab_array); + display_top_tabs($tab_array, true); ?> </td></tr> <tr><td><div id="mainarea"> + +<?php if ($importalias) : ?> + <?php include("/usr/local/www/suricata/suricata_import_aliases.php"); + if ($selectalias) { + echo '<input type="hidden" name="eng_name" value="' . $eng_name . '"/>'; + echo '<input type="hidden" name="eng_bind" value="' . $eng_bind . '"/>'; + echo '<input type="hidden" name="eng_policy" value="' . $eng_policy . '"/>'; + } + ?> + +<?php elseif ($add_edit_os_policy) : ?> + <?php include("/usr/local/www/suricata/suricata_os_policy_engine.php"); ?> + +<?php else: ?> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Host-Specific Defrag and Stream Settings"); ?></td> @@ -284,25 +505,23 @@ include_once("head.inc"); <tr> <th class="listhdrr" axis="string"><?php echo gettext("Name");?></th> <th class="listhdrr" axis="string"><?php echo gettext("Bind-To Address Alias");?></th> - <th class="list" align="right"><a href="suricata_import_aliases.php?id=<?=$id?>&eng=host_os_policy"> - <img src="../themes/<?= $g['theme'];?>/images/icons/icon_import_alias.gif" width="17" - height="17" border="0" title="<?php echo gettext("Import policy configuration from existing Aliases");?>"></a> - <a href="suricata_os_policy_engine.php?id=<?=$id?>&eng_id=<?=$host_os_policy_engine_next_id?>"> - <img src="../themes/<?= $g['theme'];?>/images/icons/icon_plus.gif" width="17" - height="17" border="0" title="<?php echo gettext("Add a new policy configuration");?>"></a></th> + <th class="list" align="right"><input type="image" name="import_alias[]" src="../themes/<?= $g['theme'];?>/images/icons/icon_import_alias.gif" width="17" + height="17" border="0" title="<?php echo gettext("Import policy configuration from existing Aliases");?>"/> + <input type="image" name="add_os_policy[]" src="../themes/<?= $g['theme'];?>/images/icons/icon_plus.gif" width="17" + height="17" border="0" title="<?php echo gettext("Add a new policy configuration");?>"/></th> </tr> </thead> <?php foreach ($pconfig['host_os_policy']['item'] as $f => $v): ?> <tr> <td class="listlr" align="left"><?=gettext($v['name']);?></td> <td class="listbg" align="center"><?=gettext($v['bind_to']);?></td> - <td class="listt" align="right"><a href="suricata_os_policy_engine.php?id=<?=$id;?>&eng_id=<?=$f;?>"> - <img src="/themes/<?=$g['theme'];?>/images/icons/icon_e.gif" - width="17" height="17" border="0" title="<?=gettext("Edit this policy configuration");?>"></a> + <td class="listt" align="right"><input type="image" name="edit_os_policy[]" value="<?=$f;?>" onclick="document.getElementById('eng_id').value='<?=$f;?>'" + src="/themes/<?=$g['theme'];?>/images/icons/icon_e.gif" + width="17" height="17" border="0" title="<?=gettext("Edit this policy configuration");?>"/> <?php if ($v['bind_to'] <> "all") : ?> - <a href="suricata_flow_stream.php?id=<?=$id;?>&eng_id=<?=$f;?>&act=del_host_os_policy" onclick="return confirm('Are you sure you want to delete this entry?');"> - <img src="/themes/<?=$g['theme'];?>/images/icons/icon_x.gif" width="17" height="17" border="0" - title="<?=gettext("Delete this policy configuration");?>"></a> + <input type="image" name="del_os_policy[]" value="<?=$f;?>" onclick="document.getElementById('eng_id').value='<?=$f;?>';return confirm('Are you sure you want to delete this entry?');" + src="/themes/<?=$g['theme'];?>/images/icons/icon_x.gif" width="17" height="17" border="0" + title="<?=gettext("Delete this policy configuration");?>"/> <?php else : ?> <img src="/themes/<?=$g['theme'];?>/images/icons/icon_x_d.gif" width="17" height="17" border="0" title="<?=gettext("Default policy configuration cannot be deleted");?>"> @@ -314,7 +533,6 @@ include_once("head.inc"); </td> </tr> <tr> - <td colspan="2" valign="top" class="listtopic"><?php echo gettext("IP Defragmentation"); ?></td> </tr> <tr> @@ -603,7 +821,7 @@ include_once("head.inc"); <tr> <td width="22%" valign="top"> </td> <td width="78%"> - <input name="Submit" type="submit" class="formbtn" value="Save" title="<?php echo + <input name="save" type="submit" class="formbtn" value="Save" title="<?php echo gettext("Save flow and stream settings"); ?>"> <input name="id" type="hidden" value="<?=$id;?>"> <input name="ResetAll" type="submit" class="formbtn" value="Reset" title="<?php echo @@ -618,27 +836,12 @@ include_once("head.inc"); <?php echo gettext("may take several seconds. Suricata must also be restarted to activate any changes made on this screen."); ?></td> </tr> </table> + +<?php endif; ?> + </div> </td></tr></table> </form> -<script type="text/javascript"> - -function wopen(url, name, w, h) -{ - // Fudge factors for window decoration space. - // In my tests these work well on all platforms & browsers. - w += 32; - h += 96; - var win = window.open(url, - name, - 'width=' + w + ', height=' + h + ', ' + - 'location=no, menubar=no, ' + - 'status=no, toolbar=no, scrollbars=yes, resizable=yes'); - win.resizeTo(w, h); - win.focus(); -} - -</script> <?php include("fend.inc"); ?> </body> </html> diff --git a/config/suricata/suricata_generate_yaml.php b/config/suricata/suricata_generate_yaml.php index 0614adf8..bd3ce368 100644 --- a/config/suricata/suricata_generate_yaml.php +++ b/config/suricata/suricata_generate_yaml.php @@ -1,30 +1,41 @@ <?php /* - suricata_generate_yaml.php - - Copyright (C) 2014 Bill Meeks - 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. + * suricata_generate_yaml.php + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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. */ // Create required Suricata directories if they don't exist @@ -64,6 +75,11 @@ if (!empty($suricatacfg['externallistname']) && $suricatacfg['externallistname'] $external_net = trim($external_net); } +// Set the PASS LIST and write its contents to disk +$plist = suricata_build_list($suricatacfg, $suricatacfg['passlistname'], true); +@file_put_contents("{$suricatacfgdir}/passlist", implode("\n", $plist)); +$suri_passlist = "{$suricatacfgdir}/passlist"; + // Set default and user-defined variables for SERVER_VARS and PORT_VARS $suricata_servers = array ( "dns_servers" => "\$HOME_NET", "smtp_servers" => "\$HOME_NET", "http_servers" => "\$HOME_NET", @@ -137,6 +153,31 @@ if (!empty($suricatacfg['inspect_recursion_limit']) || $suricatacfg['inspect_rec else $inspection_recursion_limit = ""; +if ($suricatacfg['delayed_detect'] == 'on') + $delayed_detect = "yes"; +else + $delayed_detect = "no"; + +// Add interface-specific blocking settings +if ($suricatacfg['blockoffenders'] == 'on') + $suri_blockoffenders = "yes"; +else + $suri_blockoffenders = "no"; + +if ($suricatacfg['blockoffenderskill'] == 'on') + $suri_killstates = "yes"; +else + $suri_killstates = "no"; + +if ($suricatacfg['blockoffendersip'] == 'src') + $suri_blockip = 'SRC'; +elseif ($suricatacfg['blockoffendersip'] == 'dst') + $suri_blockip = 'DST'; +else + $suri_blockip = 'BOTH'; + +$suri_pf_table = SURICATA_PF_TABLE; + // Add interface-specific logging settings if ($suricatacfg['alertsystemlog'] == 'on') $alert_syslog = "yes"; @@ -226,6 +267,16 @@ if ($suricatacfg['barnyard_enable'] == 'on') else $barnyard2_enabled = "no"; +if (isset($config['installedpackages']['suricata']['config'][0]['unified2_log_limit'])) + $unified2_log_limit = "{$config['installedpackages']['suricata']['config'][0]['unified2_log_limit']}mb"; +else + $unified2_log_limit = "32mb"; + +if (isset($suricatacfg['barnyard_sensor_id'])) + $unified2_sensor_id = $suricatacfg['barnyard_sensor_id']; +else + $unified2_sensor_id = "0"; + // Add interface-specific IP defrag settings if (!empty($suricatacfg['frag_memcap'])) $frag_memcap = $suricatacfg['frag_memcap']; diff --git a/config/suricata/suricata_global.php b/config/suricata/suricata_global.php index f6b5d83d..9c932222 100644 --- a/config/suricata/suricata_global.php +++ b/config/suricata/suricata_global.php @@ -3,12 +3,23 @@ * suricata_global.php * part of pfSense * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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. * @@ -28,7 +39,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ - require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); @@ -42,23 +52,15 @@ $pconfig['etprocode'] = $config['installedpackages']['suricata']['config'][0]['e $pconfig['enable_etopen_rules'] = $config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']; $pconfig['enable_etpro_rules'] = $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']; $pconfig['rm_blocked'] = $config['installedpackages']['suricata']['config'][0]['rm_blocked']; -$pconfig['suricataloglimit'] = $config['installedpackages']['suricata']['config'][0]['suricataloglimit']; -$pconfig['suricataloglimitsize'] = $config['installedpackages']['suricata']['config'][0]['suricataloglimitsize']; $pconfig['autoruleupdate'] = $config['installedpackages']['suricata']['config'][0]['autoruleupdate']; $pconfig['autoruleupdatetime'] = $config['installedpackages']['suricata']['config'][0]['autoruleupdatetime']; +$pconfig['live_swap_updates'] = $config['installedpackages']['suricata']['config'][0]['live_swap_updates']; $pconfig['log_to_systemlog'] = $config['installedpackages']['suricata']['config'][0]['log_to_systemlog']; -$pconfig['clearlogs'] = $config['installedpackages']['suricata']['config'][0]['clearlogs']; $pconfig['forcekeepsettings'] = $config['installedpackages']['suricata']['config'][0]['forcekeepsettings']; $pconfig['snortcommunityrules'] = $config['installedpackages']['suricata']['config'][0]['snortcommunityrules']; -if (empty($pconfig['suricataloglimit'])) - $pconfig['suricataloglimit'] = 'on'; if (empty($pconfig['autoruleupdatetime'])) $pconfig['autoruleupdatetime'] = '00:30'; -if (empty($pconfig['suricataloglimitsize'])) - // Set limit to 20% of slice that is unused */ - $pconfig['suricataloglimitsize'] = round(exec('df -k /var | grep -v "Filesystem" | awk \'{print $4}\'') * .20 / 1024); - if ($_POST['autoruleupdatetime']) { if (!preg_match('/^([01]?[0-9]|2[0-3]):?([0-5][0-9])$/', $_POST['autoruleupdatetime'])) @@ -73,7 +75,7 @@ if ($_POST['enable_etpro_rules'] == "on" && empty($_POST['etprocode'])) /* if no errors move foward with save */ if (!$input_errors) { - if ($_POST["Submit"]) { + if ($_POST["save"]) { $config['installedpackages']['suricata']['config'][0]['enable_vrt_rules'] = $_POST['enable_vrt_rules'] ? 'on' : 'off'; $config['installedpackages']['suricata']['config'][0]['snortcommunityrules'] = $_POST['snortcommunityrules'] ? 'on' : 'off'; @@ -117,18 +119,7 @@ if (!$input_errors) { $config['installedpackages']['suricata']['config'][0]['oinkcode'] = $_POST['oinkcode']; $config['installedpackages']['suricata']['config'][0]['etprocode'] = $_POST['etprocode']; - $config['installedpackages']['suricata']['config'][0]['rm_blocked'] = $_POST['rm_blocked']; - if ($_POST['suricataloglimitsize']) { - $config['installedpackages']['suricata']['config'][0]['suricataloglimit'] = $_POST['suricataloglimit']; - $config['installedpackages']['suricata']['config'][0]['suricataloglimitsize'] = $_POST['suricataloglimitsize']; - } else { - $config['installedpackages']['suricata']['config'][0]['suricataloglimit'] = 'on'; - - /* code will set limit to 21% of slice that is unused */ - $suricataloglimitDSKsize = round(exec('df -k /var | grep -v "Filesystem" | awk \'{print $4}\'') * .22 / 1024); - $config['installedpackages']['suricata']['config'][0]['suricataloglimitsize'] = $suricataloglimitDSKsize; - } $config['installedpackages']['suricata']['config'][0]['autoruleupdate'] = $_POST['autoruleupdate']; /* Check and adjust format of Rule Update Starttime string to add colon and leading zero if necessary */ @@ -139,12 +130,12 @@ if (!$input_errors) { } $config['installedpackages']['suricata']['config'][0]['autoruleupdatetime'] = str_pad($_POST['autoruleupdatetime'], 4, "0", STR_PAD_LEFT); $config['installedpackages']['suricata']['config'][0]['log_to_systemlog'] = $_POST['log_to_systemlog'] ? 'on' : 'off'; - $config['installedpackages']['suricata']['config'][0]['clearlogs'] = $_POST['clearlogs'] ? 'on' : 'off'; + $config['installedpackages']['suricata']['config'][0]['live_swap_updates'] = $_POST['live_swap_updates'] ? 'on' : 'off'; $config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = $_POST['forcekeepsettings'] ? 'on' : 'off'; $retval = 0; - /* create whitelist and homenet file, then sync files */ + /* create passlist and homenet file, then sync files */ sync_suricata_package_config(); write_config(); @@ -187,10 +178,13 @@ if ($input_errors) $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), true, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); - $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); ?> </td></tr> <tr> @@ -206,13 +200,13 @@ if ($input_errors) <table width="100%" border="0" cellpadding="2" cellspacing="0"> <tr> <td valign="top" width="8%"><input name="enable_etopen_rules" type="checkbox" value="on" onclick="enable_et_rules();" - <?php if ($config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']=="on") echo "checked"; ?>></td> + <?php if ($config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']=="on") echo "checked"; ?>/></td> <td><span class="vexpl"><?php echo gettext("ETOpen is an open source set of Snort rules whose coverage " . "is more limited than ETPro."); ?></span></td> </tr> <tr> <td valign="top" width="8%"><input name="enable_etpro_rules" type="checkbox" value="on" onclick="enable_pro_rules();" - <?php if ($config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']=="on") echo "checked"; ?>></td> + <?php if ($config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']=="on") echo "checked"; ?>/></td> <td><span class="vexpl"><?php echo gettext("ETPro for Snort offers daily updates and extensive coverage of current malware threats."); ?></span></td> </tr> <tr> @@ -234,9 +228,8 @@ if ($input_errors) </tr> <tr> <td valign="top"><span class="vexpl"><strong><?php echo gettext("Code:"); ?></strong></span></td> - <td><input name="etprocode" type="text" - class="formfld unknown" id="etprocode" size="52" - value="<?=htmlspecialchars($pconfig['etprocode']);?>"><br/> + <td><input name="etprocode" type="text" class="formfld unknown" id="etprocode" size="52" + value="<?=htmlspecialchars($pconfig['etprocode']);?>"/><br/> <?php echo gettext("Obtain an ETPro subscription code and paste it here."); ?></td> </tr> </table> @@ -248,7 +241,7 @@ if ($input_errors) <table width="100%" border="0" cellpadding="2" cellspacing="0"> <tr> <td><input name="enable_vrt_rules" type="checkbox" id="enable_vrt_rules" value="on" onclick="enable_snort_vrt();" - <?php if($pconfig['enable_vrt_rules']=='on') echo 'checked'; ?>></td> + <?php if($pconfig['enable_vrt_rules']=='on') echo 'checked'; ?>/></td> <td><span class="vexpl"><?php echo gettext("Snort VRT free Registered User or paid Subscriber rules"); ?></span></td> <tr> <td> </td> @@ -266,9 +259,8 @@ if ($input_errors) </tr> <tr> <td valign="top"><span class="vexpl"><strong><?php echo gettext("Code:"); ?></strong></span></td> - <td><input name="oinkcode" type="text" - class="formfld unknown" id="oinkcode" size="52" - value="<?=htmlspecialchars($pconfig['oinkcode']);?>"><br/> + <td><input name="oinkcode" type="text" class="formfld unknown" id="oinkcode" size="52" + value="<?=htmlspecialchars($pconfig['oinkcode']);?>"/><br/> <?php echo gettext("Obtain a snort.org Oinkmaster code and paste it here."); ?></td> </tr> </table> @@ -279,7 +271,7 @@ if ($input_errors) <table width="100%" border="0" cellpadding="2" cellspacing="0"> <tr> <td valign="top" width="8%"><input name="snortcommunityrules" type="checkbox" value="on" - <?php if ($config['installedpackages']['suricata']['config'][0]['snortcommunityrules']=="on") echo "checked";?> ></td> + <?php if ($config['installedpackages']['suricata']['config'][0]['snortcommunityrules']=="on") echo " checked";?>/></td> <td class="vexpl"><?php echo gettext("The Snort Community Ruleset is a GPLv2 VRT certified ruleset that is distributed free of charge " . "without any VRT License restrictions. This ruleset is updated daily and is a subset of the subscriber ruleset.");?> <br/><br/><?php echo "<span class=\"red\"><strong>" . gettext("Note: ") . "</strong></span>" . @@ -302,100 +294,61 @@ if ($input_errors) <?php if ($iface3 == $pconfig['autoruleupdate']) echo "selected"; ?>> <?=htmlspecialchars($ifacename3);?></option> <?php endforeach; ?> - </select><span class="vexpl"> <?php echo gettext("Please select the interval for rule updates. Choosing ") . + </select> <?php echo gettext("Please select the interval for rule updates. Choosing ") . "<strong>" . gettext("NEVER") . "</strong>" . gettext(" disables auto-updates."); ?><br/><br/> - <?php echo "<span class=\"red\"><strong>" . gettext("Hint: ") . "</strong></span>" . gettext("in most cases, every 12 hours is a good choice."); ?></span></td> + <?php echo "<span class=\"red\"><strong>" . gettext("Hint: ") . "</strong></span>" . gettext("in most cases, every 12 hours is a good choice."); ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Update Start Time"); ?></td> <td width="78%" class="vtable"><input type="text" class="formfld time" name="autoruleupdatetime" id="autoruleupdatetime" size="4" - maxlength="5" value="<?=$pconfig['autoruleupdatetime'];?>" <?php if ($pconfig['autoruleupdate'] == "never_up") {echo "disabled";} ?>><span class="vexpl"> - <?php echo gettext("Enter the rule update start time in 24-hour format (HH:MM). ") . "<strong>" . - gettext("Default") . " </strong>" . gettext("is ") . "<strong>" . gettext("00:03") . "</strong></span>"; ?>.<br/><br/> + maxlength="5" value="<?=$pconfig['autoruleupdatetime'];?>" <?php if ($pconfig['autoruleupdate'] == "never_up") {echo "disabled";} ?>/> + <?php echo gettext("Enter the rule update start time in 24-hour format (HH:MM). Default is ") . "<strong>" . gettext("00:03") . "</strong>"; ?>.<br/><br/> <?php echo gettext("Rules will update at the interval chosen above starting at the time specified here. For example, using the default " . "start time of 00:03 and choosing 12 Hours for the interval, the rules will update at 00:03 and 12:03 each day."); ?></td> </tr> <tr> - <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Settings"); ?></td> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Live Rule Swap on Update"); ?></td> + <td width="78%" class="vtable"><input name="live_swap_updates" id="live_swap_updates" type="checkbox" value="yes" + <?php if ($config['installedpackages']['suricata']['config'][0]['live_swap_updates']=="on") echo " checked"; ?>/> + <?php echo gettext("Enable \"Live Swap\" reload of rules after downloading an update. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>"; ?><br/><br/> + <?php echo gettext("When enabled, Suricata will perform a live load of the new rules following an update instead of a hard restart. " . + "If issues are encountered with live load, uncheck this option to perform a hard restart of all Suricata instances following an update."); ?></td> </tr> <tr> -<?php $suricatalogCurrentDSKsize = round(exec('df -k /var | grep -v "Filesystem" | awk \'{print $4}\'') / 1024); ?> - <td width="22%" valign="top" class="vncell"><?php echo gettext("Log Directory Size " . - "Limit"); ?><br/> - <br/> - <br/> - <span class="red"><strong><?php echo gettext("Note:"); ?></strong></span><br/> - <?php echo gettext("Available space is"); ?> <strong><?php echo $suricatalogCurrentDSKsize; ?> MB</strong></td> - <td width="78%" class="vtable"> - <table cellpadding="0" cellspacing="0"> - <tr> - <td colspan="2"><input name="suricataloglimit" type="radio" id="suricataloglimit" value="on" - <?php if($pconfig['suricataloglimit']=='on') echo 'checked'; ?>><span class="vexpl"> - <strong><?php echo gettext("Enable"); ?></strong> <?php echo gettext("directory size limit"); ?> (<strong><?php echo gettext("Default"); ?></strong>)</span></td> - </tr> - <tr> - <td colspan="2"><input name="suricataloglimit" type="radio" id="suricataloglimit" value="off" - <?php if($pconfig['suricataloglimit']=='off') echo 'checked'; ?>> <span class="vexpl"><strong><?php echo gettext("Disable"); ?></strong> - <?php echo gettext("directory size limit"); ?></span><br/> - <br/> - <span class="red"><strong><?php echo gettext("Warning:"); ?></strong></span> <?php echo gettext("Nanobsd " . - "should use no more than 10MB of space."); ?></td> - </tr> - </table> - <table width="100%" border="0" cellpadding="2" cellspacing="0"> - <tr> - <td class="vexpl"><?php echo gettext("Size in ") . "<strong>" . gettext("MB:") . "</strong>";?> - <input name="suricataloglimitsize" type="text" class="formfld unknown" id="suricataloglimitsize" size="10" value="<?=htmlspecialchars($pconfig['suricataloglimitsize']);?>"> - <?php echo gettext("Default is ") . "<strong>" . gettext("20%") . "</strong>" . gettext(" of available space.");?></td> - </tr> - </table> - </td> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Settings"); ?></td> </tr> -<tr style="display:none;"> +<tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Remove Blocked Hosts Interval"); ?></td> <td width="78%" class="vtable"> <select name="rm_blocked" class="formselect" id="rm_blocked"> <?php $interfaces3 = array('never_b' => gettext('NEVER'), '15m_b' => gettext('15 MINS'), '30m_b' => gettext('30 MINS'), '1h_b' => gettext('1 HOUR'), '3h_b' => gettext('3 HOURS'), '6h_b' => gettext('6 HOURS'), '12h_b' => gettext('12 HOURS'), '1d_b' => gettext('1 DAY'), '4d_b' => gettext('4 DAYS'), '7d_b' => gettext('7 DAYS'), '28d_b' => gettext('28 DAYS')); foreach ($interfaces3 as $iface3 => $ifacename3): ?> - <option value="<?=$iface3;?>" - <?php if ($iface3 == $pconfig['rm_blocked']) echo "selected"; ?>> - <?=htmlspecialchars($ifacename3);?></option> - <?php endforeach; ?> - </select> + <option value="<?=$iface3;?>" + <?php if ($iface3 == $pconfig['rm_blocked']) echo "selected"; ?>> + <?=htmlspecialchars($ifacename3);?></option> + <?php endforeach; ?> + </select> <?php echo gettext("Please select the amount of time you would like hosts to be blocked."); ?><br/><br/> <?php echo "<span class=\"red\"><strong>" . gettext("Hint:") . "</strong></span>" . gettext(" in most cases, 1 hour is a good choice.");?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Log to System Log"); ?></td> - <td width="78%" class="vtable"><input name="log_to_systemlog" - id="log_to_systemlog" type="checkbox" value="yes" - <?php if ($config['installedpackages']['suricata']['config'][0]['log_to_systemlog']=="on") echo "checked"; ?> - > <?php echo gettext("Copy Suricata messages to the firewall system log."); ?></td> -</tr> -<tr> - <td width="22%" valign="top" class="vncell"><?php echo gettext("Remove Suricata Log Files After Deinstall"); ?></td> - <td width="78%" class="vtable"><input name="clearlogs" - id="clearlogs" type="checkbox" value="yes" - <?php if ($config['installedpackages']['suricata']['config'][0]['clearlogs']=="on") echo "checked"; ?> - > <?php echo gettext("Suricata log files will be removed during package deinstallation."); ?></td> + <td width="78%" class="vtable"><input name="log_to_systemlog" id="log_to_systemlog" type="checkbox" value="yes" + <?php if ($config['installedpackages']['suricata']['config'][0]['log_to_systemlog']=="on") echo " checked"; ?>/> + <?php echo gettext("Copy Suricata messages to the firewall system log."); ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Keep Suricata Settings After Deinstall"); ?></td> - <td width="78%" class="vtable"><input name="forcekeepsettings" - id="forcekeepsettings" type="checkbox" value="yes" - <?php if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings']=="on") echo "checked"; ?> - > <?php echo gettext("Settings will not be removed during package deinstallation."); ?></td> + <td width="78%" class="vtable"><input name="forcekeepsettings" id="forcekeepsettings" type="checkbox" value="yes" + <?php if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings']=="on") echo " checked"; ?>/> + <?php echo gettext("Settings will not be removed during package deinstallation."); ?></td> </tr> <tr> - <td width="22%" valign="top"> - <td width="78%"> - <input name="Submit" type="submit" class="formbtn" value="Save" > - </td> + <td colspan="2" align="center"><input name="save" type="submit" class="formbtn" value="Save"/></td> </tr> <tr> - <td width="22%" valign="top"> </td> - <td width="78%" class="vexpl"><span class="red"><strong><?php echo gettext("Note:");?></strong> + <td colspan="2" class="vexpl" align="center"><span class="red"><strong><?php echo gettext("Note:");?></strong> </span><?php echo gettext("Changing any settings on this page will affect all Suricata-configured interfaces.");?></td> </tr> </table> diff --git a/config/suricata/suricata_import_aliases.php b/config/suricata/suricata_import_aliases.php index c16ac65d..ccaaf29d 100644 --- a/config/suricata/suricata_import_aliases.php +++ b/config/suricata/suricata_import_aliases.php @@ -1,5 +1,4 @@ <?php -/* $Id$ */ /* suricata_import_aliases.php Copyright (C) 2014 Bill Meeks @@ -27,160 +26,51 @@ POSSIBILITY OF SUCH DAMAGE. */ -require("guiconfig.inc"); -require_once("functions.inc"); -require_once("/usr/local/pkg/suricata/suricata.inc"); +/************************************************************************************ + This file contains code for selecting and importing an existing Alias. + It is included and injected inline from other Suricata PHP pages that + use the Import Alias functionality. -// Retrieve any passed QUERY STRING or POST variables -$id = $_GET['id']; -$eng = $_GET['eng']; -if (isset($_POST['id'])) - $id = $_POST['id']; -if (isset($_POST['eng'])) - $eng = $_POST['eng']; + The following variables are assumed to exist and must be initialized + as necessary in order to utilize this page. -// Make sure we have a valid rule ID and ENGINE name, or -// else bail out to top-level menu. -if (is_null($id) || is_null($eng)) { - header("Location: /suricata/suricata_interfaces.php"); - exit; -} + $g --> system global variables array + $config --> global variable pointing to configuration information + $a_aliases --> $config['aliases']['alias'] array + $title --> title string for import alias engine type + $used --> array of currently used engine 'bind_to' Alias names + $selectalias --> boolean to display radio buttons instead of checkboxes + $mode --> string value to indicate current operation mode -// Used to track if any selectable Aliases are found -$selectablealias = false; + Information is returned from this page via the following form fields: -// Initialize required array variables as necessary -if (!is_array($config['aliases']['alias'])) - $config['aliases']['alias'] = array(); -$a_aliases = $config['aliases']['alias']; -if (!is_array($config['installedpackages']['suricata']['rule'])) - $config['installedpackages']['suricata']['rule'] = array(); - -// The $eng variable points to the specific Suricata config section -// engine we are importing values into. Initialize the config.xml -// array if necessary. -if (!is_array($config['installedpackages']['suricata']['rule'][$id][$eng]['item'])) - $config['installedpackages']['suricata']['rule'][$id][$eng]['item'] = array(); - -// Initialize a pointer to the Suricata config section engine we are -// importing values into. -$a_nat = &$config['installedpackages']['suricata']['rule'][$id][$eng]['item']; - -// Build a lookup array of currently used engine 'bind_to' Aliases -// so we can screen matching Alias names from the list. -$used = array(); -foreach ($a_nat as $v) - $used[$v['bind_to']] = true; - -// Construct the correct return URL based on the Suricata config section -// engine we were called with. This lets us return to the page we were -// called from. -switch ($eng) { - case "host_os_policy": - $returl = "/suricata/suricata_flow_stream.php"; - $multi_ip = true; - $title = "Host Operating System Policy"; - break; - case "libhtp_policy": - $returl = "/suricata/suricata_app_parsers.php"; - $multi_ip = true; - $title = "HTTP Server Policy"; - break; - default: - $returl = "/suricata/suricata_interface_edit"; - $multi_ip = true; - $title = ""; -} - -if ($_POST['cancel']) { - header("Location: {$returl}?id={$id}"); - exit; -} - -if ($_POST['save']) { - - // Define default engine configurations for each of the supported engines. - $def_os_policy = array( "name" => "", "bind_to" => "", "policy" => "bsd" ); - - $def_libhtp_policy = array( "name" => "default", "bind_to" => "all", "personality" => "IDS", - "request-body-limit" => 4096, "response-body-limit" => 4096, - "double-decode-path" => "no", "double-decode-query" => "no" ); - - // Figure out which engine type we are importing and set up default engine array - $engine = array(); - switch ($eng) { - case "host_os_policy": - $engine = $def_os_policy; - break; - case "libhtp_policy": - $engine = $def_libhtp_policy; - break; - default: - $engine = ""; - $input_errors[] = gettext("Invalid ENGINE TYPE passed in query string. Aborting operation."); - } + aliastoimport[] --> checkbox array containing selected alias names + save_import_alias --> Submit button for save operation and exit + cancel_import_alias --> Submit button to cancel operation and exit + ************************************************************************************/ +?> - // See if anything was checked to import - if (is_array($_POST['toimport']) && count($_POST['toimport']) > 0) { - foreach ($_POST['toimport'] as $item) { - $engine['name'] = strtolower($item); - $engine['bind_to'] = $item; - $a_nat[] = $engine; - } +<?php $selectablealias = false; + if (!is_array($a_aliases)) + $a_aliases = array(); + if ($mode <> "") + echo '<input type="hidden" name="mode" id="mode" value="' . $mode . '"/>'; + if ($selectalias == true) { + $fieldtype = "radio"; + $header = gettext("Select an Alias to use as {$title} target from the list below."); } - else - $input_errors[] = gettext("No entries were selected for import. Please select one or more Aliases for import and click SAVE."); - - // if no errors, write new entry to conf - if (!$input_errors) { - // Reorder the engine array to ensure the - // 'bind_to=all' entry is at the bottom if - // the array contains more than one entry. - if (count($a_nat) > 1) { - $i = -1; - foreach ($a_nat as $f => $v) { - if ($v['bind_to'] == "all") { - $i = $f; - break; - } - } - // Only relocate the entry if we - // found it, and it's not already - // at the end. - if ($i > -1 && ($i < (count($a_nat) - 1))) { - $tmp = $a_nat[$i]; - unset($a_nat[$i]); - $a_nat[] = $tmp; - } - } - - // Now write the new engine array to conf and return - write_config(); - - header("Location: {$returl}?id={$id}"); - exit; + else { + $fieldtype = "checkbox"; + $header = gettext("Select one or more Aliases to use as {$title} targets from the list below."); } -} - -$pgtitle = gettext("Suricata: Import Host/Network Alias for {$title}"); -include("head.inc"); - ?> -<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> -<?php include("fbegin.inc"); ?> -<form action="suricata_import_aliases.php" method="post"> -<input type="hidden" name="id" value="<?=$id;?>"> -<input type="hidden" name="eng" value="<?=$eng;?>"> -<?php if ($input_errors) print_input_errors($input_errors); ?> -<div id="boxarea"> -<table width="100%" border="0" cellpadding="0" cellspacing="0"> +<table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> <tr> - <td class="tabcont"><strong><?=gettext("Select one or more Aliases to use as {$title} targets from the list below.");?></strong><br/> - </td> + <td class="listtopic" align="center"><?=$header;?></td> </tr> <tr> - <td class="tabcont"> + <td> <table id="sortabletable1" style="table-layout: fixed;" class="sortable" width="100%" border="0" cellpadding="0" cellspacing="0"> <colgroup> <col width="5%" align="center"> @@ -221,7 +111,7 @@ include("head.inc"); <td class="listlr" align="center"><img src="../themes/<?=$g['theme'];?>/images/icons/icon_block_d.gif" width="11" height"11" border="0"/> <?php else: ?> <tr> - <td class="listlr" align="center"><input type="checkbox" name="toimport[]" value="<?=htmlspecialchars($alias['name']);?>" title="<?=$tooltip;?>"/></td> + <td class="listlr" align="center"><input type="<?=$fieldtype;?>" name="aliastoimport[]" value="<?=htmlspecialchars($alias['name']);?>" title="<?=$tooltip;?>"/></td> <?php endif; ?> <td class="listr" align="left"><?=$textss . htmlspecialchars($alias['name']) . $textse;?></td> <td class="listr" align="left"> @@ -244,29 +134,26 @@ include("head.inc"); </tr> <?php if (!$selectablealias): ?> <tr> - <td class="tabcont" align="center"><b><?php echo gettext("There are currently no defined Aliases eligible for import.");?></b></td> + <td align="center"><b><?php echo gettext("There are currently no defined Aliases eligible for import.");?></b></td> </tr> <tr> - <td class="tabcont" align="center"> - <input type="Submit" name="cancel" value="Cancel" id="cancel" class="formbtn" title="<?=gettext("Cancel import operation and return");?>"/> + <td align="center" valign="middle"> + <input type="Submit" name="cancel_import_alias" value="Cancel" id="cancel_import_alias" class="formbtn" title="<?=gettext("Cancel import operation and return");?>"/> </td> </tr> <?php else: ?> <tr> - <td class="tabcont" align="center"> - <input type="Submit" name="save" value="Save" id="save" class="formbtn" title="<?=gettext("Import selected item and return");?>"/> - <input type="Submit" name="cancel" value="Cancel" id="cancel" class="formbtn" title="<?=gettext("Cancel import operation and return");?>"/> + <td align="center" valign="middle"> + <input type="Submit" name="save_import_alias" value="Save" id="save_import_alias" class="formbtn" title="<?=gettext("Import selected item and return");?>"/> + <input type="Submit" name="cancel_import_alias" value="Cancel" id="cancel_import_alias" class="formbtn" title="<?=gettext("Cancel import operation and return");?>"/> </td> </tr> <?php endif; ?> <tr> - <td class="tabcont"> + <td> <span class="vexpl"><span class="red"><strong><?=gettext("Note:"); ?><br></strong></span><?=gettext("Fully-Qualified Domain Name (FQDN) host Aliases cannot be used as Suricata configuration parameters. Aliases resolving to a single FQDN value are disabled in the list above. In the case of nested Aliases where one or more of the nested values is a FQDN host, the FQDN host will not be included in the {$title} configuration.");?></span> </td> </tr> </table> -</div> -</form> -<?php include("fend.inc"); ?> -</body> -</html> + + diff --git a/config/suricata/suricata_interfaces.php b/config/suricata/suricata_interfaces.php index 26ccada3..26d57b71 100644 --- a/config/suricata/suricata_interfaces.php +++ b/config/suricata/suricata_interfaces.php @@ -2,19 +2,30 @@ /* * suricata_interfaces.php * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -27,7 +38,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -$nocsrf = true; require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); @@ -37,42 +47,26 @@ $suricatadir = SURICATADIR; $suricatalogdir = SURICATALOGDIR; $rcdir = RCFILEPREFIX; -$id = $_GET['id']; -if (isset($_POST['id'])) +if ($_POST['id']) $id = $_POST['id']; +else + $id = 0; if (!is_array($config['installedpackages']['suricata']['rule'])) $config['installedpackages']['suricata']['rule'] = array(); $a_nat = &$config['installedpackages']['suricata']['rule']; $id_gen = count($config['installedpackages']['suricata']['rule']); -if (isset($_POST['del_x'])) { - /* delete selected rules */ +if ($_POST['del_x']) { + /* delete selected interfaces */ if (is_array($_POST['rule'])) { conf_mount_rw(); foreach ($_POST['rule'] as $rulei) { - /* convert fake interfaces to real */ $if_real = get_real_interface($a_nat[$rulei]['interface']); $suricata_uuid = $a_nat[$rulei]['uuid']; suricata_stop($a_nat[$rulei], $if_real); exec("/bin/rm -r {$suricatalogdir}suricata_{$if_real}{$suricata_uuid}"); exec("/bin/rm -r {$suricatadir}suricata_{$suricata_uuid}_{$if_real}"); - - // If interface had auto-generated Suppress List, then - // delete that along with the interface - $autolist = "{$a_nat[$rulei]['interface']}" . "suppress"; - if (is_array($config['installedpackages']['suricata']['suppress']) && - is_array($config['installedpackages']['suricata']['suppress']['item'])) { - $a_suppress = &$config['installedpackages']['suricata']['suppress']['item']; - foreach ($a_suppress as $k => $i) { - if ($i['name'] == $autolist) { - unset($config['installedpackages']['suricata']['suppress']['item'][$k]); - break; - } - } - } - - // Finally delete the interface's config entry entirely unset($a_nat[$rulei]); } conf_mount_ro(); @@ -103,16 +97,15 @@ if (isset($_POST['del_x'])) { header("Location: /suricata/suricata_interfaces.php"); exit; } - } /* start/stop Barnyard2 */ -if ($_GET['act'] == 'bartoggle' && is_numeric($id)) { +if ($_POST['bartoggle']) { $suricatacfg = $config['installedpackages']['suricata']['rule'][$id]; $if_real = get_real_interface($suricatacfg['interface']); $if_friendly = convert_friendly_interface_to_friendly_descr($suricatacfg['interface']); - if (suricata_is_running($suricatacfg['uuid'], $if_real, 'barnyard2') == 'no') { + if (!suricata_is_running($suricatacfg['uuid'], $if_real, 'barnyard2')) { log_error("Toggle (barnyard starting) for {$if_friendly}({$suricatacfg['descr']})..."); sync_suricata_package_config(); suricata_barnyard_start($suricatacfg, $if_real); @@ -127,12 +120,12 @@ if ($_GET['act'] == 'bartoggle' && is_numeric($id)) { } /* start/stop Suricata */ -if ($_GET['act'] == 'toggle' && is_numeric($id)) { +if ($_POST['toggle']) { $suricatacfg = $config['installedpackages']['suricata']['rule'][$id]; $if_real = get_real_interface($suricatacfg['interface']); $if_friendly = convert_friendly_interface_to_friendly_descr($suricatacfg['interface']); - if (suricata_is_running($suricatacfg['uuid'], $if_real) == 'yes') { + if (suricata_is_running($suricatacfg['uuid'], $if_real)) { log_error("Toggle (suricata stopping) for {$if_friendly}({$suricatacfg['descr']})..."); suricata_stop($suricatacfg, $if_real); } else { @@ -152,24 +145,21 @@ if ($_GET['act'] == 'toggle' && is_numeric($id)) { header("Location: /suricata/suricata_interfaces.php"); exit; } - -$pgtitle = "Services: Suricata Intrusion Detection System"; +$suri_pkg_ver = SURICATA_PKG_VER; +$pgtitle = "Services: {$suri_pkg_ver} - Intrusion Detection System"; include_once("head.inc"); ?> <body link="#000000" vlink="#000000" alink="#000000"> -<?php -include_once("fbegin.inc"); -if ($pfsense_stable == 'yes') - echo '<p class="pgtitle">' . $pgtitle . '</p>'; -?> +<?php include_once("fbegin.inc"); ?> <form action="suricata_interfaces.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> +<input type="hidden" name="id" id="id" value=""> <?php /* Display Alert message */ if ($input_errors) - print_input_errors($input_errors); // TODO: add checks + print_input_errors($input_errors); if ($savemsg) print_info_box($savemsg); @@ -184,9 +174,12 @@ if ($pfsense_stable == 'yes') $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); ?> </td> </tr> @@ -194,25 +187,32 @@ if ($pfsense_stable == 'yes') <td> <div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> + + <colgroup> + <col width="3%" align="center"> + <col width="12%"> + <col width="14%"> + <col width="120" align="center"> + <col width="65" align="center"> + <col width="14%"> + <col> + <col width="20" align="center"> + </colgroup> + <thead> <tr id="frheader"> - <td width="3%" class="list"> </td> - <td width="10%" class="listhdrr"><?php echo gettext("Interface"); ?></td> - <td width="13%" class="listhdrr"><?php echo gettext("Suricata"); ?></td> - <td width="10%" class="listhdrr"><?php echo gettext("Pattern Match"); ?></td> - <td width="10%" class="listhdrr"><?php echo gettext("Block"); ?></td> - <td width="12%" class="listhdrr"><?php echo gettext("Barnyard2"); ?></td> - <td width="30%" class="listhdr"><?php echo gettext("Description"); ?></td> - <td width="3%" class="list"> - <table border="0" cellspacing="0" cellpadding="0"> - <tr> - <td></td> - <td align="center" valign="middle"><a href="suricata_interfaces_edit.php?id=<?php echo $id_gen;?>"><img - src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" - width="17" height="17" border="0" title="<?php echo gettext('Add Suricata interface mapping');?>"></a></td> - </tr> - </table> - </td> + <th class="list"> </th> + <th class="listhdrr"><?php echo gettext("Interface"); ?></th> + <th class="listhdrr"><?php echo gettext("Suricata"); ?></th> + <th class="listhdrr"><?php echo gettext("Pattern Match"); ?></th> + <th class="listhdrr"><?php echo gettext("Block"); ?></th> + <th class="listhdrr"><?php echo gettext("Barnyard2"); ?></th> + <th class="listhdr"><?php echo gettext("Description"); ?></th> + <th class="list"><a href="suricata_interfaces_edit.php?id=<?php echo $id_gen;?>"> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" + width="17" height="17" border="0" title="<?php echo gettext('Add Suricata interface mapping');?>"></a> + </th> </tr> + </thead> <?php $nnats = $i = 0; // Turn on buffering to speed up rendering @@ -237,7 +237,7 @@ if ($pfsense_stable == 'yes') $if_real = get_real_interface($natent['interface']); $natend_friendly= convert_friendly_interface_to_friendly_descr($natent['interface']); $suricata_uuid = $natent['uuid']; - if (suricata_is_running($suricata_uuid, $if_real) == 'no'){ + if (!suricata_is_running($suricata_uuid, $if_real)){ $iconfn = 'block'; $iconfn_msg1 = 'Suricata is not running on '; $iconfn_msg2 = '. Click to start.'; @@ -247,7 +247,7 @@ if ($pfsense_stable == 'yes') $iconfn_msg1 = 'Suricata is running on '; $iconfn_msg2 = '. Click to stop.'; } - if (suricata_is_running($suricata_uuid, $if_real, 'barnyard2') == 'no'){ + if (!suricata_is_running($suricata_uuid, $if_real, 'barnyard2')){ $biconfn = 'block'; $biconfn_msg1 = 'Barnyard2 is not running on '; $biconfn_msg2 = '. Click to start.'; @@ -275,31 +275,30 @@ if ($pfsense_stable == 'yes') <td class="listt"> <input type="checkbox" id="frc<?=$nnats;?>" name="rule[]" value="<?=$i;?>" onClick="fr_bgcolor('<?=$nnats;?>')" style="margin: 0; padding: 0;"> </td> - <td class="listr" - id="frd<?=$nnats;?>" valign="middle" + <td class="listr" valign="middle" + id="frd<?=$nnats;?>" ondblclick="document.location='suricata_interfaces_edit.php?id=<?=$nnats;?>';"> <?php echo $natend_friendly; ?> </td> - <td class="listr" + <td class="listr" valign="middle" id="frd<?=$nnats;?>" ondblclick="document.location='suricata_interfaces_edit.php?id=<?=$nnats;?>';"> <?php $check_suricata_info = $config['installedpackages']['suricata']['rule'][$nnats]['enable']; if ($check_suricata_info == "on") { - echo gettext("ENABLED"); - echo "<a href='?act=toggle&id={$i}'> - <img src='../themes/{$g['theme']}/images/icons/icon_{$iconfn}.gif' - width='13' height='13' border='0' - title='" . gettext($iconfn_msg1.$natend_friendly.$iconfn_msg2) . "'></a>"; + echo gettext("ENABLED") . " "; + echo "<input type='image' src='../themes/{$g['theme']}/images/icons/icon_{$iconfn}.gif' width='13' height='13' border='0' "; + echo "onClick='document.getElementById(\"id\").value=\"{$nnats}\";' name=\"toggle[]\" "; + echo "title='" . gettext($iconfn_msg1.$natend_friendly.$iconfn_msg2) . "'/>"; echo ($no_rules) ? " <img src=\"../themes/{$g['theme']}/images/icons/icon_frmfld_imp.png\" width=\"15\" height=\"15\" border=\"0\">" : ""; } else echo gettext("DISABLED"); ?> </td> <td class="listr" - id="frd<?=$nnats;?>" valign="middle" + id="frd<?=$nnats;?>" valign="middle" align="center" ondblclick="document.location='suricata_interfaces_edit.php?id=<?=$nnats;?>';"> <?php $check_performance_info = $config['installedpackages']['suricata']['rule'][$nnats]['mpm_algo']; @@ -311,7 +310,7 @@ if ($pfsense_stable == 'yes') ?> <?=strtoupper($check_performance);?> </td> <td class="listr" - id="frd<?=$nnats;?>" valign="middle" + id="frd<?=$nnats;?>" valign="middle" align="center" ondblclick="document.location='suricata_interfaces_edit.php?id=<?=$nnats;?>';"> <?php $check_blockoffenders_info = $config['installedpackages']['suricata']['rule'][$nnats]['blockoffenders']; @@ -329,11 +328,9 @@ if ($pfsense_stable == 'yes') <?php $check_suricatabarnyardlog_info = $config['installedpackages']['suricata']['rule'][$nnats]['barnyard_enable']; if ($check_suricatabarnyardlog_info == "on") { - echo gettext("ENABLED"); - echo "<a href='?act=bartoggle&id={$i}'> - <img src='../themes/{$g['theme']}/images/icons/icon_{$biconfn}.gif' - width='13' height='13' border='0' - title='" . gettext($biconfn_msg1.$natend_friendly.$biconfn_msg2) . "'></a>"; + echo gettext("ENABLED") . " "; + echo "<input type='image' name='bartoggle[]' src='../themes/{$g['theme']}/images/icons/icon_{$biconfn}.gif' width='13' height='13' border='0' "; + echo "onClick='document.getElementById(\"id\").value=\"{$nnats}\"'; title='" . gettext($biconfn_msg1.$natend_friendly.$biconfn_msg2) . "'/>"; } else echo gettext("DISABLED"); ?> @@ -343,14 +340,9 @@ if ($pfsense_stable == 'yes') <font color="#ffffff"> <?=htmlspecialchars($natent['descr']);?> </font> </td> <td valign="middle" class="list" nowrap> - <table border="0" cellspacing="0" cellpadding="0"> - <tr> - <td><a href="suricata_interfaces_edit.php?id=<?=$i;?>"><img - src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" - width="17" height="17" border="0" title="<?php echo gettext('Edit Suricata interface mapping'); ?>"></a> - </td> - </tr> - </table> + <a href="suricata_interfaces_edit.php?id=<?=$i;?>"> + <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" + width="17" height="17" border="0" title="<?php echo gettext('Edit Suricata interface mapping'); ?>"></a> </td> </tr> <?php $i++; $nnats++; endforeach; ob_end_flush(); ?> @@ -363,19 +355,13 @@ if ($pfsense_stable == 'yes') <?php endif; ?> </td> <td class="list" valign="middle" nowrap> - <table border="0" cellspacing="0" cellpadding="0"> - <tr> - <td><?php if ($nnats == 0): ?><img - src="../themes/<?= $g['theme']; ?>/images/icons/icon_x_d.gif" - width="17" height="17" " border="0"> - <?php else: ?> - <input name="del" type="image" - src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" - width="17" height="17" title="<?php echo gettext("Delete selected Suricata interface mapping(s)"); ?>" - onclick="return intf_del()"> - <?php endif; ?></td> - </tr> - </table> + <?php if ($nnats == 0): ?> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_x_d.gif" width="17" height="17" " border="0"> + <?php else: ?> + <input name="del" type="image" src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" + width="17" height="17" title="<?php echo gettext("Delete selected Suricata interface mapping(s)"); ?>" + onclick="return intf_del()"> + <?php endif; ?> </td> </tr> <tr> diff --git a/config/suricata/suricata_interfaces_edit.php b/config/suricata/suricata_interfaces_edit.php index 5f644a55..3b61755c 100644 --- a/config/suricata/suricata_interfaces_edit.php +++ b/config/suricata/suricata_interfaces_edit.php @@ -2,19 +2,30 @@ /* * suricata_interfaces_edit.php * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -32,6 +43,9 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); global $g, $rebuild_rules; +$suricatadir = SURICATADIR; +$suricatalogdir = SURICATALOGDIR; + if (!is_array($config['installedpackages']['suricata'])) $config['installedpackages']['suricata'] = array(); $suricataglob = $config['installedpackages']['suricata']; @@ -40,13 +54,13 @@ if (!is_array($config['installedpackages']['suricata']['rule'])) $config['installedpackages']['suricata']['rule'] = array(); $a_rule = &$config['installedpackages']['suricata']['rule']; -$id = $_GET['id']; -if (isset($_POST['id'])) +if (isset($_POST['id']) && is_numericint($_POST['id'])) $id = $_POST['id']; -if (is_null($id)) { - header("Location: /suricata/suricata_interfaces.php"); - exit; -} +elseif (isset($_GET['id']) && is_numericint($_GET['id'])); + $id = htmlspecialchars($_GET['id'], ENT_QUOTES | ENT_HTML401); + +if (is_null($id)) + $id = 0; $pconfig = array(); if (empty($suricataglob['rule'][$id]['uuid'])) { @@ -62,13 +76,7 @@ else { $suricata_uuid = $pconfig['uuid']; // Get the physical configured interfaces on the firewall -if (function_exists('get_configured_interface_with_descr')) - $interfaces = get_configured_interface_with_descr(); -else { - $interfaces = array('wan' => 'WAN', 'lan' => 'LAN'); - for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) - $interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr']; -} +$interfaces = get_configured_interface_with_descr(); // See if interface is already configured, and use its values if (isset($id) && $a_rule[$id]) { @@ -78,8 +86,8 @@ if (isset($id) && $a_rule[$id]) { if (empty($pconfig['uuid'])) $pconfig['uuid'] = $suricata_uuid; } -// Must be a new interface, so try to pick next available physical interface to use elseif (isset($id) && !isset($a_rule[$id])) { + // Must be a new interface, so try to pick next available physical interface to use $ifaces = get_configured_interface_list(); $ifrules = array(); foreach($a_rule as $r) @@ -87,6 +95,9 @@ elseif (isset($id) && !isset($a_rule[$id])) { foreach ($ifaces as $i) { if (!in_array($i, $ifrules)) { $pconfig['interface'] = $i; + $pconfig['enable'] = 'on'; + $pconfig['descr'] = strtoupper($i); + $pconfig['inspect_recursion_limit'] = '3000'; break; } } @@ -97,16 +108,11 @@ elseif (isset($id) && !isset($a_rule[$id])) { } } -if (isset($_GET['dup'])) - unset($id); - // Set defaults for any empty key parameters if (empty($pconfig['blockoffendersip'])) $pconfig['blockoffendersip'] = "both"; if (empty($pconfig['max_pending_packets'])) $pconfig['max_pending_packets'] = "1024"; -if (empty($pconfig['inspect_recursion_limit'])) - $pconfig['inspect_recursion_limit'] = "3000"; if (empty($pconfig['detect_eng_profile'])) $pconfig['detect_eng_profile'] = "medium"; if (empty($pconfig['mpm_algo'])) @@ -136,18 +142,60 @@ if (empty($pconfig['max_pcap_log_size'])) if (empty($pconfig['max_pcap_log_files'])) $pconfig['max_pcap_log_files'] = "1000"; -if ($_POST["Submit"]) { - if (!$_POST['interface']) +if ($_POST["save"]) { + // If the interface is not enabled, stop any running Suricata + // instance on it, save the new state and exit. + if (!isset($_POST['enable'])) { + if (isset($id) && $a_rule[$id]) { + $a_rule[$id]['enable'] = 'off'; + $a_rule[$id]['interface'] = htmlspecialchars($_POST['interface']); + $a_rule[$id]['descr'] = htmlspecialchars($_POST['descr']); + suricata_stop($a_rule[$id], get_real_interface($a_rule[$id]['interface'])); + + // Save configuration changes + write_config(); + + // Update suricata.conf and suricata.sh files for this interface + sync_suricata_package_config(); + + header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); + header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); + header( 'Cache-Control: no-store, no-cache, must-revalidate' ); + header( 'Cache-Control: post-check=0, pre-check=0', false ); + header( 'Pragma: no-cache' ); + header("Location: /suricata/suricata_interfaces.php"); + exit; + } + } + + // Validate inputs + if (!isset($_POST['interface'])) $input_errors[] = gettext("Choosing an Interface is mandatory!"); - if ($_POST['max_pending_packets'] < 1 || $_POST['max_pending_packets'] > 65535) - $input_errors[] = gettext("The value for Maximum-Pending-Packets must be between 1 and 65,535!"); + if (isset($_POST['stats_upd_interval']) && !is_numericint($_POST['stats_upd_interval'])) + $input_errors[] = gettext("The value for Stats Update Interval must contain only digits and evaluate to an integer."); + + if ($_POST['max_pending_packets'] < 1 || $_POST['max_pending_packets'] > 65000) + $input_errors[] = gettext("The value for Maximum-Pending-Packets must be between 1 and 65,000!"); - if (!empty($_POST['max_pcap_log_size']) && !is_numeric($_POST['max_pcap_log_size'])) + if (isset($_POST['max_pcap_log_size']) && !is_numeric($_POST['max_pcap_log_size'])) $input_errors[] = gettext("The value for 'Max Packet Log Size' must be numbers only. Do not include any alphabetic characters."); - if (!empty($_POST['max_pcap_log_files']) && !is_numeric($_POST['max_pcap_log_files'])) - $input_errors[] = gettext("The value for 'Max Packet Log Files' must be numbers only."); + if (isset($_POST['max_pcap_log_files']) && !is_numeric($_POST['max_pcap_log_files'])) + $input_errors[] = gettext("The value for 'Max Packet Log Files' must be numbers only."); + + if (!empty($_POST['inspect_recursion_limit']) && !is_numeric($_POST['inspect_recursion_limit'])) + $input_errors[] = gettext("The value for Inspect Recursion Limit can either be blank or contain only digits evaluating to an integer greater than or equal to 0."); + + /* See if assigned interface is already in use */ + if (isset($_POST['interface'])) { + foreach ($a_rule as $k => $v) { + if (($v['interface'] == $_POST['interface']) && ($id <> $k)) { + $input_errors[] = gettext("The '{$_POST['interface']}' interface is already assigned to another Suricata instance."); + break; + } + } + } // if no errors write to suricata.yaml if (!$input_errors) { @@ -156,21 +204,12 @@ if ($_POST["Submit"]) { $natent['enable'] = $_POST['enable'] ? 'on' : 'off'; $natent['uuid'] = $pconfig['uuid']; - // See if the HOME_NET, EXTERNAL_NET, or SUPPRESS LIST values were changed - $suricata_reload = false; - if ($_POST['homelistname'] && ($_POST['homelistname'] <> $natent['homelistname'])) - $suricata_reload = true; - if ($_POST['externallistname'] && ($_POST['externallistname'] <> $natent['externallistname'])) - $suricata_reload = true; - if ($_POST['suppresslistname'] && ($_POST['suppresslistname'] <> $natent['suppresslistname'])) - $suricata_reload = true; - - if ($_POST['descr']) $natent['descr'] = $_POST['descr']; else $natent['descr'] = strtoupper($natent['interface']); + if ($_POST['descr']) $natent['descr'] = htmlspecialchars($_POST['descr']); else $natent['descr'] = strtoupper($natent['interface']); if ($_POST['max_pcap_log_size']) $natent['max_pcap_log_size'] = $_POST['max_pcap_log_size']; else unset($natent['max_pcap_log_size']); if ($_POST['max_pcap_log_files']) $natent['max_pcap_log_files'] = $_POST['max_pcap_log_files']; else unset($natent['max_pcap_log_files']); if ($_POST['enable_stats_log'] == "on") { $natent['enable_stats_log'] = 'on'; }else{ $natent['enable_stats_log'] = 'off'; } if ($_POST['append_stats_log'] == "on") { $natent['append_stats_log'] = 'on'; }else{ $natent['append_stats_log'] = 'off'; } - if ($_POST['stats_upd_interval']) $natent['stats_upd_interval'] = $_POST['stats_upd_interval']; else $natent['stats_upd_interval'] = "10"; + if ($_POST['stats_upd_interval'] >= 1) $natent['stats_upd_interval'] = $_POST['stats_upd_interval']; else $natent['stats_upd_interval'] = "10"; if ($_POST['enable_http_log'] == "on") { $natent['enable_http_log'] = 'on'; }else{ $natent['enable_http_log'] = 'off'; } if ($_POST['append_http_log'] == "on") { $natent['append_http_log'] = 'on'; }else{ $natent['append_http_log'] = 'off'; } if ($_POST['enable_tls_log'] == "on") { $natent['enable_tls_log'] = 'on'; }else{ $natent['enable_tls_log'] = 'off'; } @@ -182,30 +221,37 @@ if ($_POST["Submit"]) { if ($_POST['enable_tracked_files_md5'] == "on") { $natent['enable_tracked_files_md5'] = 'on'; }else{ $natent['enable_tracked_files_md5'] = 'off'; } if ($_POST['enable_file_store'] == "on") { $natent['enable_file_store'] = 'on'; }else{ $natent['enable_file_store'] = 'off'; } if ($_POST['max_pending_packets']) $natent['max_pending_packets'] = $_POST['max_pending_packets']; else unset($natent['max_pending_packets']); - if ($_POST['inspect_recursion_limit']) $natent['inspect_recursion_limit'] = $_POST['inspect_recursion_limit']; else unset($natent['inspect_recursion_limit']); + if ($_POST['inspect_recursion_limit'] >= '0') $natent['inspect_recursion_limit'] = $_POST['inspect_recursion_limit']; else unset($natent['inspect_recursion_limit']); if ($_POST['detect_eng_profile']) $natent['detect_eng_profile'] = $_POST['detect_eng_profile']; else unset($natent['detect_eng_profile']); if ($_POST['mpm_algo']) $natent['mpm_algo'] = $_POST['mpm_algo']; else unset($natent['mpm_algo']); if ($_POST['sgh_mpm_context']) $natent['sgh_mpm_context'] = $_POST['sgh_mpm_context']; else unset($natent['sgh_mpm_context']); if ($_POST['blockoffenders'] == "on") $natent['blockoffenders'] = 'on'; else $natent['blockoffenders'] = 'off'; if ($_POST['blockoffenderskill'] == "on") $natent['blockoffenderskill'] = 'on'; else unset($natent['blockoffenderskill']); if ($_POST['blockoffendersip']) $natent['blockoffendersip'] = $_POST['blockoffendersip']; else unset($natent['blockoffendersip']); - if ($_POST['whitelistname']) $natent['whitelistname'] = $_POST['whitelistname']; else unset($natent['whitelistname']); + if ($_POST['passlistname']) $natent['passlistname'] = $_POST['passlistname']; else unset($natent['passlistname']); if ($_POST['homelistname']) $natent['homelistname'] = $_POST['homelistname']; else unset($natent['homelistname']); if ($_POST['externallistname']) $natent['externallistname'] = $_POST['externallistname']; else unset($natent['externallistname']); if ($_POST['suppresslistname']) $natent['suppresslistname'] = $_POST['suppresslistname']; else unset($natent['suppresslistname']); if ($_POST['alertsystemlog'] == "on") { $natent['alertsystemlog'] = 'on'; }else{ $natent['alertsystemlog'] = 'off'; } + if ($_POST['delayed_detect'] == "on") { $natent['delayed_detect'] = 'on'; }else{ $natent['delayed_detect'] = 'off'; } if ($_POST['configpassthru']) $natent['configpassthru'] = base64_encode($_POST['configpassthru']); else unset($natent['configpassthru']); $if_real = get_real_interface($natent['interface']); if (isset($id) && $a_rule[$id]) { + // See if moving an existing Suricata instance to another physical interface if ($natent['interface'] != $a_rule[$id]['interface']) { $oif_real = get_real_interface($a_rule[$id]['interface']); - suricata_stop($a_rule[$id], $oif_real); - exec("rm -r /var/log/suricata_{$oif_real}" . $a_rule[$id]['uuid']); - exec("mv -f {$suricatadir}/suricata_" . $a_rule[$id]['uuid'] . "_{$oif_real} {$suricatadir}/suricata_" . $a_rule[$id]['uuid'] . "_{$if_real}"); + if (suricata_is_running($a_rule[$id]['uuid'], $oif_real)) { + suricata_stop($a_rule[$id], $oif_real); + $suricata_start = true; + } + else + $suricata_start = false; + exec("mv -f {$suricatalogdir}suricata_{$oif_real}" . $a_rule[$id]['uuid'] . " {$suricatalogdir}suricata_{$if_real}" . $a_rule[$id]['uuid']); + conf_mount_rw(); + exec("mv -f {$suricatadir}suricata_" . $a_rule[$id]['uuid'] . "_{$oif_real} {$suricatadir}suricata_" . $a_rule[$id]['uuid'] . "_{$if_real}"); + conf_mount_ro(); } - // Edits don't require a rules rebuild, so turn it "off" - $rebuild_rules = false; $a_rule[$id] = $natent; } else { // Adding new interface, so set interface configuration parameter defaults @@ -247,6 +293,7 @@ if ($_POST["Submit"]) { $natent['reassembly_to_client_chunk'] = '2560'; $natent['enable_midstream_sessions'] = 'off'; $natent['enable_async_sessions'] = 'off'; + $natent['delayed_detect'] = 'off'; $natent['asn1_max_frames'] = '256'; @@ -263,7 +310,7 @@ if ($_POST["Submit"]) { $natent['libhtp_policy']['item'][] = $default; // Enable the basic default rules for the interface - $natent['rulesets'] = "decoder-events.rules||files.rules||http-events.rules||smtp-events.rules||stream-events.rules"; + $natent['rulesets'] = "decoder-events.rules||files.rules||http-events.rules||smtp-events.rules||stream-events.rules||tls-events.rules"; // Adding a new interface, so set flag to build new rules $rebuild_rules = true; @@ -282,15 +329,6 @@ if ($_POST["Submit"]) { // Update suricata.conf and suricata.sh files for this interface sync_suricata_package_config(); - /*******************************************************/ - /* Signal Suricata to reload configuration if we changed */ - /* HOME_NET, EXTERNAL_NET or Suppress list values. */ - /* The function only signals a running Suricata instance */ - /* to safely reload these parameters. */ - /*******************************************************/ - if ($suricata_reload == true) - suricata_reload_config($natent, "USR2"); - header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); header( 'Cache-Control: no-store, no-cache, must-revalidate' ); @@ -309,19 +347,14 @@ include_once("head.inc"); <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> -<?php include("fbegin.inc"); ?> - -<?if($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';}?> - -<?php - /* Display Alert message */ - if ($input_errors) { - print_input_errors($input_errors); - } - - if ($savemsg) { - print_info_box($savemsg); - } +<?php include("fbegin.inc"); +/* Display Alert message */ +if ($input_errors) { + print_input_errors($input_errors); +} +if ($savemsg) { + print_info_box($savemsg); +} ?> <form action="suricata_interfaces_edit.php<?php echo "?id=$id";?>" method="post" name="iform" id="iform"> @@ -329,13 +362,16 @@ include_once("head.inc"); <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; $tab_array = array(); @@ -347,7 +383,7 @@ include_once("head.inc"); $tab_array[] = array($menu_iface . gettext("App Parsers"), false, "/suricata/suricata_app_parsers.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Variables"), false, "/suricata/suricata_define_vars.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Barnyard2"), false, "/suricata/suricata_barnyard.php?id={$id}"); - display_top_tabs($tab_array); + display_top_tabs($tab_array, true); ?> </td></tr> <tr><td><div id="mainarea"> @@ -374,13 +410,13 @@ include_once("head.inc"); <?php endforeach; ?> </select> <span class="vexpl"><?php echo gettext("Choose which interface this Suricata instance applies to."); ?><br/> - <span class="red"><?php echo gettext("Hint:"); ?></span> <?php echo gettext("In most cases, you'll want to use WAN here."); ?></span><br/></td> + <span class="red"><?php echo gettext("Hint:"); ?></span> <?php echo gettext("In most cases, you'll want to use WAN here if this is the first Suricata-configured interface."); ?></span><br/></td> </tr> <tr> <td width="22%" valign="top" class="vncellreq"><?php echo gettext("Description"); ?></td> <td width="78%" class="vtable"><input name="descr" type="text" class="formfld unknown" id="descr" size="40" value="<?=htmlspecialchars($pconfig['descr']); ?>"/> <br/> - <span class="vexpl"><?php echo gettext("Enter a meaningful description here for your reference."); ?></span><br/></td> + <span class="vexpl"><?php echo gettext("Enter a meaningful description here for your reference. The default is the interface name."); ?></span><br/></td> </tr> <tr> <td colspan="2" class="listtopic"><?php echo gettext("Logging Settings"); ?></td> @@ -390,7 +426,6 @@ include_once("head.inc"); <td width="78%" class="vtable"><input name="alertsystemlog" type="checkbox" value="on" <?php if ($pconfig['alertsystemlog'] == "on") echo "checked"; ?>/> <?php echo gettext("Suricata will send Alerts to the firewall's system log."); ?></td> </tr> - <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable Stats Log"); ?></td> <td width="78%" class="vtable"><input name="enable_stats_log" type="checkbox" value="on" <?php if ($pconfig['enable_stats_log'] == "on") echo "checked"; ?> @@ -466,8 +501,6 @@ include_once("head.inc"); gettext("This will consume a significant amount of disk space on a busy network when enabled!"); ?></div> </td> </tr> - - <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable Packet Log"); ?></td> <td width="78%" class="vtable"><input name="enable_pcap_log" id="enable_pcap_log" type="checkbox" value="on" <?php if ($pconfig['enable_pcap_log'] == "on") echo "checked"; ?> @@ -484,7 +517,6 @@ include_once("head.inc"); <?php echo gettext("Enter maximum size in ") . "<strong>" . gettext("MB") . "</strong>" . gettext(" for a packet log file. Default is ") . "<strong>" . gettext("32") . "</strong>."; ?><br/><br/><?php echo gettext("When the packet log file size reaches the set limit, it will be rotated and a new one created.") ?></td> </tr> - </tr> <tr id="pcap_log_max_row"> <td width="22%" valign="top" class="vncell"><?php echo gettext("Max Packet Log Files"); ?></td> <td width="78%" class="vtable"><input name="max_pcap_log_files" type="text" @@ -492,8 +524,6 @@ include_once("head.inc"); <?php echo gettext("Enter maximum number of packet log files to maintain. Default is ") . "<strong>" . gettext("1000") . "</strong>."; ?><br/><br/><?php echo gettext("When the number of packet log files reaches the set limit, the oldest file will be overwritten.") ?></td> </tr> - -<!-- <tr> <td colspan="2" class="listtopic"><?php echo gettext("Alert Settings"); ?></td> </tr> @@ -529,8 +559,6 @@ include_once("head.inc"); <span class="red"><?php echo gettext("Hint:") . "</span> " . gettext("Choosing BOTH is suggested, and it is the default value."); ?></span><br/></td> </td> </tr> ---> - <tr> <td colspan="2" class="listtopic"><?php echo gettext("Detection Engine Settings"); ?></td> </tr> @@ -539,7 +567,9 @@ include_once("head.inc"); <td width="78%" class="vtable"><input name="max_pending_packets" type="text" class="formfld unknown" id="max_pending_packets" size="8" value="<?=htmlspecialchars($pconfig['max_pending_packets']); ?>"/> <?php echo gettext("Enter number of simultaneous packets to process. Default is ") . "<strong>" . - gettext("1024") . "</strong>."; ?><br/><br/><?php echo gettext("Minimum value is 1 and the maximum value is 65,535.") ?></td> + gettext("1024") . "</strong>."; ?><br/><br/><?php echo gettext("This controls the number simultaneous packets the engine can handle. ") . + gettext("Setting this higher generally keeps the threads more busy. The minimum value is 1 and the maximum value is 65,000. ") . "<br/><span class='red'><strong>" . + gettext("Warning: ") . "</strong></span>" . gettext("Setting this too high can lead to degradation and a possible system crash by exhausting available memory.") ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Detect-Engine Profile"); ?></td> @@ -575,7 +605,7 @@ include_once("head.inc"); </select> <?php echo gettext("Choose a multi-pattern matcher (MPM) algorithm. ") . "<strong>" . gettext("Default") . "</strong>" . gettext(" is ") . "<strong>" . gettext("AC") . "</strong>"; ?>.<br/><br/> - <?php echo gettext("AC is recommended for most systems. "); ?> + <?php echo gettext("AC is the default, and is the best choice for almost all systems."); ?> <br/></td> </tr> <tr> @@ -605,7 +635,15 @@ include_once("head.inc"); gettext("3000") . "</strong>."; ?><br/><br/><?php echo gettext("When set to 0 an internal default is used. When left blank there is no recursion limit.") ?></td> </tr> <tr> - <td colspan="2" class="listtopic"><?php echo gettext("Networks " . "Suricata Should Inspect and Whitelist"); ?></td> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Delayed Detect"); ?></td> + <td width="78%" class="vtable"> + <input name="delayed_detect" id="delayed_detect" type="checkbox" value="on" + <?php if ($pconfig['delayed_detect'] == "on") echo " checked"; ?>/> + <?php echo gettext("Suricata will build list of signatures after packet capture threads have started. Default is ") . + "<strong>" . gettext("Not Checked") . "</strong>."; ?></td> + </tr> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("Networks " . "Suricata Should Inspect and Protect"); ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Home Net"); ?></td> @@ -666,15 +704,15 @@ include_once("head.inc"); </td> </tr> <tr> - <td width="22%" valign="top" class="vncell"><?php echo gettext("Whitelist"); ?></td> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Pass List"); ?></td> <td width="78%" class="vtable"> - <select name="whitelistname" class="formselect" id="whitelistname"> + <select name="passlistname" class="formselect" id="passlistname"> <?php - /* find whitelist names and filter by type, make sure to track by uuid */ + /* find passlist names and filter by type, make sure to track by uuid */ echo "<option value='default' >default</option>\n"; - if (is_array($suricataglob['whitelist']['item'])) { - foreach ($suricataglob['whitelist']['item'] as $value) { - if ($value['name'] == $pconfig['whitelistname']) + if (is_array($suricataglob['passlist']['item'])) { + foreach ($suricataglob['passlist']['item'] as $value) { + if ($value['name'] == $pconfig['passlistname']) echo "<option value='{$value['name']}' selected>"; else echo "<option value='{$value['name']}'>"; @@ -683,14 +721,13 @@ include_once("head.inc"); } ?> </select> - <input type="button" class="formbtns" value="View List" onclick="viewList('<?=$id;?>','whitelistname','whitelist')" - id="btnWhitelist" title="<?php echo gettext("Click to view currently selected Whitelist contents"); ?>"/> + <input type="button" class="formbtns" value="View List" onclick="viewList('<?=$id;?>','passlistname','passlist')" + id="btnPasslist" title="<?php echo gettext("Click to view currently selected Pass List contents"); ?>"/> <br/> - <?php echo gettext("Choose the whitelist you want this interface to " . - "use."); ?> <br/><br/> + <?php echo gettext("Choose the Pass List you want this interface to use."); ?> <br/><br/> <span class="red"><?php echo gettext("Note:"); ?></span> <?php echo gettext("This option will only be used when block offenders is on."); ?><br/> <span class="red"><?php echo gettext("Hint:"); ?></span> <?php echo gettext("Default " . - "whitelist adds local networks, WAN IPs, Gateways, VPNs and VIPs. Create an Alias to customize."); ?> + "Pass List adds local networks, WAN IPs, Gateways, VPNs and VIPs. Create an Alias to customize."); ?> </td> </tr> <tr> @@ -734,15 +771,13 @@ include_once("head.inc"); </td> </tr> <tr> - <td width="22%" valign="top"></td> - <td width="78%"><input name="Submit" type="submit" class="formbtn" value="Save" title="<?php echo + <td colspan="2" align="center" valign="middle"><input name="save" type="submit" class="formbtn" value="Save" title="<?php echo gettext("Click to save settings and exit"); ?>"/> <input name="id" type="hidden" value="<?=$id;?>"/> </td> </tr> <tr> - <td width="22%" valign="top"> </td> - <td width="78%"><span class="vexpl"><span class="red"><strong><?php echo gettext("Note: ") . "</strong></span></span>" . + <td colspan="2" align="center" valign="middle"><span class="vexpl"><span class="red"><strong><?php echo gettext("Note: ") . "</strong></span></span>" . gettext("Please save your settings before you attempt to start Suricata."); ?> </td> </tr> @@ -755,11 +790,11 @@ include_once("head.inc"); <script language="JavaScript"> function enable_blockoffenders() { -// var endis = !(document.iform.blockoffenders.checked); -// document.iform.blockoffenderskill.disabled=endis; -// document.iform.blockoffendersip.disabled=endis; -// document.iform.whitelistname.disabled=endis; -// document.iform.btnWhitelist.disabled=endis; + var endis = !(document.iform.blockoffenders.checked); + document.iform.blockoffenderskill.disabled=endis; + document.iform.blockoffendersip.disabled=endis; + document.iform.passlistname.disabled=endis; + document.iform.btnPasslist.disabled=endis; } function toggle_stats_log() { @@ -854,19 +889,20 @@ function enable_change(enable_change) { document.iform.mpm_algo.disabled = endis; document.iform.sgh_mpm_context.disabled = endis; document.iform.inspect_recursion_limit.disabled = endis; -// document.iform.blockoffenders.disabled = endis; -// document.iform.blockoffendersip.disabled=endis; -// document.iform.blockoffenderskill.disabled=endis; + document.iform.blockoffenders.disabled = endis; + document.iform.blockoffendersip.disabled=endis; + document.iform.blockoffenderskill.disabled=endis; document.iform.alertsystemlog.disabled = endis; document.iform.externallistname.disabled = endis; document.iform.homelistname.disabled = endis; - document.iform.whitelistname.disabled=endis; + document.iform.passlistname.disabled=endis; document.iform.suppresslistname.disabled = endis; document.iform.configpassthru.disabled = endis; document.iform.btnHomeNet.disabled=endis; - document.iform.btnWhitelist.disabled=endis; + document.iform.btnPasslist.disabled=endis; document.iform.btnSuppressList.disabled=endis; -} +} document.iform.delayed_detect.disabled=endis; + function wopen(url, name, w, h) { // Fudge factors for window decoration space. @@ -889,15 +925,16 @@ function getSelectedValue(elemID) { function viewList(id, elemID, elemType) { if (typeof elemType == "undefined") { - elemType = "whitelist"; + elemType = "passlist"; } var url = "suricata_list_view.php?id=" + id + "&wlist="; url = url + getSelectedValue(elemID) + "&type=" + elemType; - wopen(url, 'WhitelistViewer', 640, 480); + url = url + "&time=" + new Date().getTime(); + wopen(url, 'PassListViewer', 640, 480); } enable_change(false); -enable_blockoffenders(); +//enable_blockoffenders(); toggle_stats_log(); toggle_http_log(); toggle_tls_log(); diff --git a/config/suricata/suricata_libhtp_policy_engine.php b/config/suricata/suricata_libhtp_policy_engine.php index e7cf4135..7e6ffd6d 100644 --- a/config/suricata/suricata_libhtp_policy_engine.php +++ b/config/suricata/suricata_libhtp_policy_engine.php @@ -1,12 +1,24 @@ <?php /* * suricata_libhtp_policy_engine.php + * + * Portions of this code are based on original work done for the + * Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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. * @@ -26,159 +38,34 @@ * POSSIBILITY OF SUCH DAMAGE. */ -require_once("guiconfig.inc"); -require_once("/usr/local/pkg/suricata/suricata.inc"); - -global $g; - -// Grab the incoming QUERY STRING or POST variables -$id = $_GET['id']; -$eng_id = $_GET['eng_id']; -if (isset($_POST['id'])) - $id = $_POST['id']; -if (isset($_POST['eng_id'])) - $eng_id = $_POST['eng_id']; - -if (is_null($id)) { - header("Location: /suricata/suricata_interfaces.php"); - exit; -} - -if (!is_array($config['installedpackages']['suricata']['rule'])) - $config['installedpackages']['suricata']['rule'] = array(); -if (!is_array($config['installedpackages']['suricata']['rule'][$id]['libhtp_policy']['item'])) - $config['installedpackages']['suricata']['rule'][$id]['libhtp_policy']['item'] = array(); -$a_nat = &$config['installedpackages']['suricata']['rule'][$id]['libhtp_policy']['item']; - -$pconfig = array(); -if (empty($a_nat[$eng_id])) { - $def = array( "name" => "engine_{$eng_id}", "bind_to" => "", "personality" => "IDS", - "request-body-limit" => "4096", "response-body-limit" => "4096", - "double-decode-path" => "no", "double-decode-query" => "no" ); - - // See if this is initial entry and set to "default" if true - if ($eng_id < 1) { - $def['name'] = "default"; - $def['bind_to'] = "all"; - } - $pconfig = $def; -} -else { - $pconfig = $a_nat[$eng_id]; - - // Check for any empty values and set sensible defaults - if (empty($pconfig['personality'])) - $pconfig['personality'] = "IDS"; -} - -if ($_POST['Cancel']) { - header("Location: /suricata/suricata_app_parsers.php?id={$id}"); - exit; -} - -// Check for returned "selected alias" if action is import -if ($_GET['act'] == "import") { - if ($_GET['varname'] == "bind_to" && !empty($_GET['varvalue'])) - $pconfig[$_GET['varname']] = $_GET['varvalue']; -} - -if ($_POST['Submit']) { - - /* Grab all the POST values and save in new temp array */ - $engine = array(); - if ($_POST['policy_name']) { $engine['name'] = trim($_POST['policy_name']); } else { $engine['name'] = "default"; } - if ($_POST['policy_bind_to']) { - if (is_alias($_POST['policy_bind_to'])) - $engine['bind_to'] = $_POST['policy_bind_to']; - elseif (strtolower(trim($_POST['policy_bind_to'])) == "all") - $engine['bind_to'] = "all"; - else - $input_errors[] = gettext("You must provide a valid Alias or the reserved keyword 'all' for the 'Bind-To IP Address' value."); - } - else { - $input_errors[] = gettext("The 'Bind-To IP Address' value cannot be blank. Provide a valid Alias or the reserved keyword 'all'."); - } - - if ($_POST['personality']) { $engine['personality'] = $_POST['personality']; } else { $engine['personality'] = "IDS"; } - if (is_numeric($_POST['req_body_limit']) && $_POST['req_body_limit'] >= 0) - $engine['request-body-limit'] = $_POST['req_body_limit']; - else - $input_errors[] = gettext("The value for 'Request Body Limit' must be all numbers and greater than or equal to zero."); - - if (is_numeric($_POST['resp_body_limit']) && $_POST['resp_body_limit'] >= 0) - $engine['response-body-limit'] = $_POST['resp_body_limit']; - else - $input_errors[] = gettext("The value for 'Response Body Limit' must be all numbers and greater than or equal to zero."); - - if ($_POST['enable_double_decode_path']) { $engine['double-decode-path'] = 'yes'; }else{ $engine['double-decode-path'] = 'no'; } - if ($_POST['enable_double_decode_query']) { $engine['double-decode-query'] = 'yes'; }else{ $engine['double-decode-query'] = 'no'; } - - /* Can only have one "all" Bind_To address */ - if ($engine['bind_to'] == "all" && $engine['name'] <> "default") { - $input_errors[] = gettext("Only one default HTTP Server Policy Engine can be bound to all addresses."); - $pconfig = $engine; - } - - /* if no errors, write new entry to conf */ - if (!$input_errors) { - if (isset($eng_id) && $a_nat[$eng_id]) { - $a_nat[$eng_id] = $engine; - } - else - $a_nat[] = $engine; - - /* Reorder the engine array to ensure the */ - /* 'bind_to=all' entry is at the bottom */ - /* if it contains more than one entry. */ - if (count($a_nat) > 1) { - $i = -1; - foreach ($a_nat as $f => $v) { - if ($v['bind_to'] == "all") { - $i = $f; - break; - } - } - /* Only relocate the entry if we */ - /* found it, and it's not already */ - /* at the end. */ - if ($i > -1 && ($i < (count($a_nat) - 1))) { - $tmp = $a_nat[$i]; - unset($a_nat[$i]); - $a_nat[] = $tmp; - } - } - - /* Now write the new engine array to conf */ - write_config(); - - header("Location: /suricata/suricata_app_parsers.php?id={$id}"); - exit; - } -} - -$if_friendly = convert_friendly_interface_to_friendly_descr($config['installedpackages']['suricata']['rule'][$id]['interface']); -$pgtitle = gettext("Suricata: Interface {$if_friendly} HTTP Server Policy Engine"); -include_once("head.inc"); - +/************************************************************************************** + This file contains code for adding/editing an existing Libhtp Policy Engine. + It is included and injected inline as needed into the suricata_app_parsers.php + page to provide the edit functionality for Host OS Policy Engines. + + The following variables are assumed to exist and must be initialized + as necessary in order to utilize this page. + + $g --> system global variables array + $config --> global variable pointing to configuration information + $pengcfg --> array containing current Libhtp Policy engine configuration + + Information is returned from this page via the following form fields: + + policy_name --> Unique Name for the Libhtp Policy Engine + policy_bind_to --> Alias name representing "bind_to" IP address for engine + personality --> Operating system chosen for engine policy + select_alias --> Submit button for select alias operation + req_body_limit --> Request Body Limit size + resp_body_limit --> Response Body Limit size + enable_double_decode_path --> double-decode path part of URI + enable_double_decode_query --> double-decode query string part of URI + save_libhtp_policy --> Submit button for save operation and exit + cancel_libhtp_policy --> Submit button to cancel operation and exit + **************************************************************************************/ ?> -<body link="#0000CC" vlink="#0000CC" alink="#0000CC" > - -<?php -include("fbegin.inc"); -if ($input_errors) print_input_errors($input_errors); -if ($savemsg) - print_info_box($savemsg); -?> - -<form action="suricata_libhtp_policy_engine.php" method="post" name="iform" id="iform"> -<input name="id" type="hidden" value="<?=$id?>"> -<input name="eng_id" type="hidden" value="<?=$eng_id?>"> -<div id="boxarea"> -<table width="100%" border="0" cellpadding="0" cellspacing="0"> -<tr> -<td class="tabcont"> -<table width="100%" border="0" cellpadding="6" cellspacing="0"> +<table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> <tr> <td colspan="2" valign="middle" class="listtopic"><?php echo gettext("Suricata Target-Based HTTP Server Policy Configuration"); ?></td> </tr> @@ -186,8 +73,8 @@ if ($savemsg) <td valign="top" class="vncell"><?php echo gettext("Engine Name"); ?></td> <td class="vtable"> <input name="policy_name" type="text" class="formfld unknown" id="policy_name" size="25" maxlength="25" - value="<?=htmlspecialchars($pconfig['name']);?>"<?php if (htmlspecialchars($pconfig['name']) == "default") echo "readonly";?>> - <?php if (htmlspecialchars($pconfig['name']) <> "default") + value="<?=htmlspecialchars($pengcfg['name']);?>"<?php if (htmlspecialchars($pengcfg['name']) == "default") echo "readonly";?>> + <?php if (htmlspecialchars($pengcfg['name']) <> "default") echo gettext("Name or description for this engine. (Max 25 characters)"); else echo "<span class=\"red\">" . gettext("The name for the 'default' engine is read-only.") . "</span>";?><br/> @@ -198,13 +85,13 @@ if ($savemsg) <tr> <td valign="top" class="vncell"><?php echo gettext("Bind-To IP Address Alias"); ?></td> <td class="vtable"> - <?php if ($pconfig['name'] <> "default") : ?> + <?php if ($pengcfg['name'] <> "default") : ?> <table width="95%" border="0" cellpadding="2" cellspacing="0"> <tr> <td class="vexpl"><input name="policy_bind_to" type="text" class="formfldalias" id="policy_bind_to" size="32" - value="<?=htmlspecialchars($pconfig['bind_to']);?>" title="<?=trim(filter_expand_alias($pconfig['bind_to']));?>" autocomplete="off"> + value="<?=htmlspecialchars($pengcfg['bind_to']);?>" title="<?=trim(filter_expand_alias($pengcfg['bind_to']));?>" autocomplete="off"> <?php echo gettext("IP List to bind this engine to. (Cannot be blank)"); ?></td> - <td class="vexpl" align="right"><input type="button" class="formbtns" value="Aliases" onclick="parent.location='suricata_select_alias.php?id=<?=$id;?>&eng_id=<?=$eng_id;?>&type=host|network&varname=bind_to&act=import&multi_ip=yes&returl=<?=urlencode($_SERVER['PHP_SELF']);?>'" + <td class="vexpl" align="right"><input type="submit" class="formbtns" name="select_alias" value="Aliases" title="<?php echo gettext("Select an existing IP alias");?>"/></td> </tr> <tr> @@ -214,7 +101,7 @@ if ($savemsg) <br/><span class="red"><strong><?php echo gettext("Note: ") . "</strong></span>" . gettext("Supplied value must be a pre-configured Alias or the keyword 'all'.");?> <?php else : ?> <input name="policy_bind_to" type="text" class="formfldalias" id="policy_bind_to" size="32" - value="<?=htmlspecialchars($pconfig['bind_to']);?>" autocomplete="off" readonly> + value="<?=htmlspecialchars($pengcfg['bind_to']);?>" autocomplete="off" readonly> <?php echo "<span class=\"red\">" . gettext("IP List for the default engine is read-only and must be 'all'.") . "</span>";?><br/> <?php echo gettext("The default engine is required and will apply for packets with destination addresses not matching other engine IP Lists.");?><br/> <?php endif ?> @@ -228,7 +115,7 @@ if ($savemsg) $profile = array( 'Apache', 'Apache_2_2', 'Generic', 'IDS', 'IIS_4_0', 'IIS_5_0', 'IIS_5_1', 'IIS_6_0', 'IIS_7_0', 'IIS_7_5', 'Minimal' ); foreach ($profile as $val): ?> <option value="<?=$val;?>" - <?php if ($val == $pconfig['personality']) echo "selected"; ?>> + <?php if ($val == $pengcfg['personality']) echo "selected"; ?>> <?=gettext($val);?></option> <?php endforeach; ?> </select> <?php echo gettext("Choose the web server personality appropriate for the protected hosts. The default is ") . @@ -243,7 +130,7 @@ if ($savemsg) <td width="22%" valign="top" class="vncell"><?php echo gettext("Request Body Limit"); ?></td> <td width="78%" class="vtable"> <input name="req_body_limit" type="text" class="formfld unknown" id="req_body_limit" size="9" - value="<?=htmlspecialchars($pconfig['request-body-limit']);?>"> + value="<?=htmlspecialchars($pengcfg['request-body-limit']);?>"> <?php echo gettext("Maximum number of HTTP request body bytes to inspect. Default is ") . "<strong>" . gettext("4,096") . "</strong>" . gettext(" bytes."); ?><br/><br/> <?php echo gettext("HTTP request bodies are often big, so they take a lot of time to process which has a significant impact ") . @@ -255,7 +142,7 @@ if ($savemsg) <td width="22%" valign="top" class="vncell"><?php echo gettext("Response Body Limit"); ?></td> <td width="78%" class="vtable"> <input name="resp_body_limit" type="text" class="formfld unknown" id="resp_body_limit" size="9" - value="<?=htmlspecialchars($pconfig['response-body-limit']);?>"> + value="<?=htmlspecialchars($pengcfg['response-body-limit']);?>"> <?php echo gettext("Maximum number of HTTP response body bytes to inspect. Default is ") . "<strong>" . gettext("4,096") . "</strong>" . gettext(" bytes."); ?><br/><br/> <?php echo gettext("HTTP response bodies are often big, so they take a lot of time to process which has a significant impact ") . @@ -268,31 +155,25 @@ if ($savemsg) </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Double-Decode Path"); ?></td> - <td width="78%" class="vtable"><input name="enable_double_decode_path" type="checkbox" value="on" <?php if ($pconfig['double-decode-path'] == "yes") echo "checked"; ?>> + <td width="78%" class="vtable"><input name="enable_double_decode_path" type="checkbox" value="yes" <?php if ($pengcfg['double-decode-path'] == "yes") echo "checked"; ?>> <?php echo gettext("Suricata will double-decode path section of the URI. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>."; ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Double-Decode Query"); ?></td> - <td width="78%" class="vtable"><input name="enable_double_decode_query" type="checkbox" value="on" <?php if ($pconfig['double-decode-query'] == "yes") echo "checked"; ?>> + <td width="78%" class="vtable"><input name="enable_double_decode_query" type="checkbox" value="yes" <?php if ($pengcfg['double-decode-query'] == "yes") echo "checked"; ?>> <?php echo gettext("Suricata will double-decode query string section of the URI. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>."; ?></td> </tr> <tr> <td width="22%" valign="bottom"> </td> <td width="78%" valign="bottom"> - <input name="Submit" id="submit" type="submit" class="formbtn" value=" Save " title="<?php echo + <input name="save_libhtp_policy" id="save_libhtp_policy" type="submit" class="formbtn" value=" Save " title="<?php echo gettext("Save web server policy engine settings and return to App Parsers tab"); ?>"> - <input name="Cancel" id="cancel" type="submit" class="formbtn" value="Cancel" title="<?php echo + <input name="cancel_libhtp_policy" id="cancel_libhtp_policy" type="submit" class="formbtn" value="Cancel" title="<?php echo gettext("Cancel changes and return to App Parsers tab"); ?>"></td> </tr> </table> -</td> -</tr> -</table> -</div> -</form> -<?php include("fend.inc"); ?> -</body> + <script type="text/javascript" src="/javascript/autosuggest.js"> </script> <script type="text/javascript" src="/javascript/suggestions.js"> @@ -311,4 +192,3 @@ setTimeout("createAutoSuggest();", 500); </script> -</html> diff --git a/config/suricata/suricata_list_view.php b/config/suricata/suricata_list_view.php index 2ff121f2..722bf47a 100644 --- a/config/suricata/suricata_list_view.php +++ b/config/suricata/suricata_list_view.php @@ -2,29 +2,29 @@ /* * suricata_list_view.php * - Copyright (C) 2014 Bill Meeks - 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 (C) 2014 Bill Meeks + * 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"); @@ -34,23 +34,29 @@ global $g, $config; $contents = ''; -$id = $_GET['id']; -$wlist = $_GET['wlist']; -$type = $_GET['type']; +if (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); + +$wlist = htmlspecialchars($_GET['wlist']); +$type = htmlspecialchars($_GET['type']); +$title = "List"; if (isset($id) && isset($wlist)) { - $a_rule = $config['installedpackages']['suricata']['rule'][$id]; + $a_rule = $config['installedpackages']['suricataglobal']['rule'][$id]; if ($type == "homenet") { $list = suricata_build_list($a_rule, $wlist); $contents = implode("\n", $list); + $title = "HOME_NET"; } - elseif ($type == "whitelist") { + elseif ($type == "passlist") { $list = suricata_build_list($a_rule, $wlist, true); $contents = implode("\n", $list); + $title = "Pass List"; } elseif ($type == "suppress") { $list = suricata_find_list($wlist, $type); $contents = str_replace("\r", "", base64_decode($list['suppresspassthru'])); + $title = "Suppress List"; } else $contents = gettext("\n\nERROR -- Requested List Type entity is not valid!"); @@ -58,35 +64,32 @@ if (isset($id) && isset($wlist)) { else $contents = gettext("\n\nERROR -- Supplied interface or List entity is not valid!"); -$pgtitle = array(gettext("Suricata"), gettext(ucfirst($type) . " Viewer")); +$pgtitle = array(gettext("Suricata"), gettext($title . " Viewer")); ?> <?php include("head.inc");?> <body link="#000000" vlink="#000000" alink="#000000"> -<?php if ($savemsg) print_info_box($savemsg); ?> -<?php // include("fbegin.inc");?> -<form action="suricata_list_view.php" method="post"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> <td class="tabcont"> <table width="100%" cellpadding="0" cellspacing="6" bgcolor="#eeeeee"> <tr> - <td class="pgtitle" colspan="2">Suricata: <?php echo gettext(ucfirst($type) . " Viewer"); ?></td> + <td class="pgtitle" colspan="2">Snort: <?php echo gettext($title . " Viewer"); ?></td> </tr> <tr> <td align="left" width="20%"> <input type="button" class="formbtn" value="Return" onclick="window.close()"> </td> <td align="right"> - <b><?php echo gettext(ucfirst($type) . ": ") . '</b> ' . $_GET['wlist']; ?> + <b><?php echo gettext($title . ": ") . '</b> ' . htmlspecialchars($_GET['wlist']); ?> </td> </tr> <tr> <td colspan="2" valign="top" class="label"> <div style="background: #eeeeee; width:100%; height:100%;" id="textareaitem"><!-- NOTE: The opening *and* the closing textarea tag must be on the same line. --> - <textarea style="width:100%; height:100%;" readonly wrap="off" rows="25" cols="80" name="code2"><?=$contents;?></textarea> + <textarea style="width:100%; height:100%;" readonly wrap="off" rows="25" cols="80" name="code2"><?=htmlspecialchars($contents);?></textarea> </div> </td> </tr> @@ -94,7 +97,5 @@ $pgtitle = array(gettext("Suricata"), gettext(ucfirst($type) . " Viewer")); </td> </tr> </table> -</form> -<?php // include("fend.inc");?> </body> </html> diff --git a/config/suricata/suricata_logs_browser.php b/config/suricata/suricata_logs_browser.php index 38310b9f..04edf373 100644 --- a/config/suricata/suricata_logs_browser.php +++ b/config/suricata/suricata_logs_browser.php @@ -1,37 +1,50 @@ <?php /* - suricata_logs_browser.php - - Copyright (C) 2014 Bill Meeks - 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. + * suricata_logs_browser.php + * + * Portions of this code are based on original work done for the + * Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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"); require_once("/usr/local/pkg/suricata/suricata.inc"); -if ($_POST['instance']) +if (isset($_POST['instance']) && is_numericint($_POST['instance'])) $instanceid = $_POST['instance']; +elseif (isset($_GET['instance']) && is_numericint($_GET['instance'])) + $instanceid = htmlspecialchars($_GET['instance']); if (empty($instanceid)) $instanceid = 0; @@ -127,9 +140,12 @@ if ($input_errors) { $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); $tab_array[] = array(gettext("Logs Browser"), true, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); ?> </td> </tr> @@ -148,7 +164,7 @@ if ($input_errors) { $selected = ""; if ($id == $instanceid) $selected = "selected"; - echo "<option value='{$id}' {$selected}> (" . convert_friendly_interface_to_friendly_descr($instance['interface']) . "){$instance['descr']}</option>\n"; + echo "<option value='{$id}' {$selected}> (" . convert_friendly_interface_to_friendly_descr($instance['interface']) . ") {$instance['descr']}</option>\n"; } ?> </select> <?php echo gettext('Choose which instance logs you want to view.'); ?> @@ -159,7 +175,7 @@ if ($input_errors) { <td width="78%" class="vtable"> <select name="logFile" id="logFile" class="formselect" onChange="loadFile();"> <?php - $logs = array( "alerts.log", "files-json.log", "http.log", "stats.log", "suricata.log", "tls.log" ); + $logs = array( "alerts.log", "block.log", "files-json.log", "http.log", "stats.log", "suricata.log", "tls.log" ); foreach ($logs as $log) { $selected = ""; if ($log == basename($logfile)) diff --git a/config/suricata/suricata_logs_mgmt.php b/config/suricata/suricata_logs_mgmt.php new file mode 100644 index 00000000..16376c5b --- /dev/null +++ b/config/suricata/suricata_logs_mgmt.php @@ -0,0 +1,489 @@ +<?php +/* + * suricata_logs_mgmt.php + * + * Portions of this code are based on original work done for the + * Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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"); +require_once("/usr/local/pkg/suricata/suricata.inc"); + +global $g; + +$suricatadir = SURICATADIR; + +$pconfig = array(); + +// Grab saved settings from configuration +$pconfig['enable_log_mgmt'] = $config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] == 'on' ? 'on' : 'off'; +$pconfig['clearlogs'] = $config['installedpackages']['suricata']['config'][0]['clearlogs']; +$pconfig['suricataloglimit'] = $config['installedpackages']['suricata']['config'][0]['suricataloglimit']; +$pconfig['suricataloglimitsize'] = $config['installedpackages']['suricata']['config'][0]['suricataloglimitsize']; +$pconfig['alert_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['alert_log_limit_size']; +$pconfig['alert_log_retention'] = $config['installedpackages']['suricata']['config'][0]['alert_log_retention']; +$pconfig['block_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['block_log_limit_size']; +$pconfig['block_log_retention'] = $config['installedpackages']['suricata']['config'][0]['block_log_retention']; +$pconfig['files_json_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['files_json_log_limit_size']; +$pconfig['files_json_log_retention'] = $config['installedpackages']['suricata']['config'][0]['files_json_log_retention']; +$pconfig['http_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['http_log_limit_size']; +$pconfig['http_log_retention'] = $config['installedpackages']['suricata']['config'][0]['http_log_retention']; +$pconfig['stats_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['stats_log_limit_size']; +$pconfig['stats_log_retention'] = $config['installedpackages']['suricata']['config'][0]['stats_log_retention']; +$pconfig['tls_log_limit_size'] = $config['installedpackages']['suricata']['config'][0]['tls_log_limit_size']; +$pconfig['tls_log_retention'] = $config['installedpackages']['suricata']['config'][0]['tls_log_retention']; +$pconfig['unified2_log_limit'] = $config['installedpackages']['suricata']['config'][0]['unified2_log_limit']; +$pconfig['u2_archive_log_retention'] = $config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention']; +$pconfig['file_store_retention'] = $config['installedpackages']['suricata']['config'][0]['file_store_retention']; + +// Load up some arrays with selection values (we use these later). +// The keys in the $retentions array are the retention period +// converted to hours. The keys in the $log_sizes array are +// the file size limits in KB. +$retentions = array( '0' => gettext('KEEP ALL'), '24' => gettext('1 DAY'), '168' => gettext('7 DAYS'), '336' => gettext('14 DAYS'), + '720' => gettext('30 DAYS'), '1080' => gettext("45 DAYS"), '2160' => gettext('90 DAYS'), '4320' => gettext('180 DAYS'), + '8766' => gettext('1 YEAR'), '26298' => gettext("3 YEARS") ); +$log_sizes = array( '0' => gettext('NO LIMIT'), '50' => gettext('50 KB'), '150' => gettext('150 KB'), '250' => gettext('250 KB'), + '500' => gettext('500 KB'), '750' => gettext('750 KB'), '1000' => gettext('1 MB'), '2000' => gettext('2 MB'), + '5000' => gettext("5 MB"), '10000' => gettext("10 MB") ); + +// Set sensible defaults for any unset parameters +if (empty($pconfig['suricataloglimit'])) + $pconfig['suricataloglimit'] = 'on'; +if (empty($pconfig['suricataloglimitsize'])) { + // Set limit to 20% of slice that is unused */ + $pconfig['suricataloglimitsize'] = round(exec('df -k /var | grep -v "Filesystem" | awk \'{print $4}\'') * .20 / 1024); +} + +// Set default retention periods for rotated logs +if (empty($pconfig['alert_log_retention'])) + $pconfig['alert_log_retention'] = "336"; +if (empty($pconfig['block_log_retention'])) + $pconfig['block_log_retention'] = "336"; +if (empty($pconfig['files_json_log_retention'])) + $pconfig['files_json_log_retention'] = "168"; +if (empty($pconfig['http_log_retention'])) + $pconfig['http_log_retention'] = "168"; +if (empty($pconfig['stats_log_retention'])) + $pconfig['stats_log_retention'] = "168"; +if (empty($pconfig['tls_log_retention'])) + $pconfig['tls_log_retention'] = "336"; +if (empty($pconfig['u2_archive_log_retention'])) + $pconfig['u2_archive_log_retention'] = "168"; +if (empty($pconfig['file_store_retention'])) + $pconfig['file_store_retention'] = "168"; + +// Set default log file size limits +if (empty($pconfig['alert_log_limit_size'])) + $pconfig['alert_log_limit_size'] = "500"; +if (empty($pconfig['block_log_limit_size'])) + $pconfig['block_log_limit_size'] = "500"; +if (empty($pconfig['files_json_log_limit_size'])) + $pconfig['files_json_log_limit_size'] = "1000"; +if (empty($pconfig['http_log_limit_size'])) + $pconfig['http_log_limit_size'] = "1000"; +if (empty($pconfig['stats_log_limit_size'])) + $pconfig['stats_log_limit_size'] = "500"; +if (empty($pconfig['tls_log_limit_size'])) + $pconfig['tls_log_limit_size'] = "500"; +if (empty($pconfig['unified2_log_limit'])) + $pconfig['unified2_log_limit'] = "32"; + +if ($_POST["save"]) { + if ($_POST['suricataloglimit'] == 'on') { + if (!is_numericint($_POST['suricataloglimitsize']) || $_POST['suricataloglimitsize'] < 1) + $input_errors[] = gettext("The 'Log Directory Size Limit' must be an integer value greater than zero."); + } + + // Validate unified2 log file limit + if (!is_numericint($_POST['unified2_log_limit']) || $_POST['unified2_log_limit'] < 1) + $input_errors[] = gettext("The value for 'Unified2 Log Limit' must be an integer value greater than zero."); + + if (!$input_errors) { + $config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] = $_POST['enable_log_mgmt'] ? 'on' :'off'; + $config['installedpackages']['suricata']['config'][0]['clearlogs'] = $_POST['clearlogs'] ? 'on' : 'off'; + $config['installedpackages']['suricata']['config'][0]['suricataloglimit'] = $_POST['suricataloglimit']; + $config['installedpackages']['suricata']['config'][0]['suricataloglimitsize'] = $_POST['suricataloglimitsize']; + $config['installedpackages']['suricata']['config'][0]['alert_log_limit_size'] = $_POST['alert_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['alert_log_retention'] = $_POST['alert_log_retention']; + $config['installedpackages']['suricata']['config'][0]['block_log_limit_size'] = $_POST['block_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['block_log_retention'] = $_POST['block_log_retention']; + $config['installedpackages']['suricata']['config'][0]['files_json_log_limit_size'] = $_POST['files_json_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['files_json_log_retention'] = $_POST['files_json_log_retention']; + $config['installedpackages']['suricata']['config'][0]['http_log_limit_size'] = $_POST['http_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['http_log_retention'] = $_POST['http_log_retention']; + $config['installedpackages']['suricata']['config'][0]['stats_log_limit_size'] = $_POST['stats_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['stats_log_retention'] = $_POST['stats_log_retention']; + $config['installedpackages']['suricata']['config'][0]['tls_log_limit_size'] = $_POST['tls_log_limit_size']; + $config['installedpackages']['suricata']['config'][0]['tls_log_retention'] = $_POST['tls_log_retention']; + $config['installedpackages']['suricata']['config'][0]['unified2_log_limit'] = $_POST['unified2_log_limit']; + $config['installedpackages']['suricata']['config'][0]['u2_archive_log_retention'] = $_POST['u2_archive_log_retention']; + $config['installedpackages']['suricata']['config'][0]['file_store_retention'] = $_POST['file_store_retention']; + + write_config(); + sync_suricata_package_config(); + + /* forces page to reload new settings */ + header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); + header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); + header( 'Cache-Control: no-store, no-cache, must-revalidate' ); + header( 'Cache-Control: post-check=0, pre-check=0', false ); + header( 'Pragma: no-cache' ); + header("Location: /suricata/suricata_logs_mgmt.php"); + exit; + } +} + +$pgtitle = gettext("Suricata: Logs Management"); +include_once("head.inc"); + +?> + +<body link="#000000" vlink="#000000" alink="#000000"> + +<?php +include_once("fbegin.inc"); + +/* Display Alert message, under form tag or no refresh */ +if ($input_errors) + print_input_errors($input_errors); + +?> + +<form action="suricata_logs_mgmt.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tr><td> +<?php + $tab_array = array(); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); + $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); + $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs Mgmt"), true, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); +?> +</td></tr> +<tr> + <td> + <div id="mainarea"> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> +<tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Settings"); ?></td> +</tr> +<tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Remove Suricata Log Files During Package Uninstall"); ?></td> + <td width="78%" class="vtable"><input name="clearlogs" id="clearlogs" type="checkbox" value="yes" + <?php if ($config['installedpackages']['suricata']['config'][0]['clearlogs']=="on") echo " checked"; ?>/> + <?php echo gettext("Suricata log files will be removed when the Suricata package is uninstalled."); ?></td> +</tr> +<tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Auto Log Management"); ?></td> + <td width="78%" class="vtable"><input name="enable_log_mgmt" id="enable_log_mgmt" type="checkbox" value="on" + <?php if ($config['installedpackages']['suricata']['config'][0]['enable_log_mgmt']=="on") echo " checked"; ?> onClick="enable_change();"/> + <?php echo gettext("Enable automatic unattended management of Suricata logs using parameters specified below."); ?><br/> + <span class="red"><strong><?=gettext("Note: ") . "</strong></span>" . gettext("This must be be enabled in order to set Log Size and Retention Limits below.");?> + </td> +</tr> +<tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Logs Directory Size Limit"); ?></td> +</tr> +<tr> +<?php $suricatalogCurrentDSKsize = round(exec('df -k /var | grep -v "Filesystem" | awk \'{print $4}\'') / 1024); ?> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Log Directory Size " . + "Limit"); ?><br/><br/><br/><br/><br/><br/><br/> + <span class="red"><strong><?php echo gettext("Note:"); ?></strong></span><br/> + <?php echo gettext("Available space is"); ?> <strong><?php echo $suricatalogCurrentDSKsize; ?> MB</strong></td> + <td width="78%" class="vtable"> + <table cellpadding="0" cellspacing="0"> + <tr> + <td colspan="2" class="vexpl"><input name="suricataloglimit" type="radio" id="suricataloglimit_on" value="on" + <?php if($pconfig['suricataloglimit']=='on') echo 'checked'; ?> onClick="enable_change_dirSize();"/> + <strong><?php echo gettext("Enable"); ?></strong> <?php echo gettext("directory size limit"); ?> (<strong><?php echo gettext("Default"); ?></strong>)</td> + </tr> + <tr> + <td colspan="2" class="vexpl"><input name="suricataloglimit" type="radio" id="suricataloglimit_off" value="off" + <?php if($pconfig['suricataloglimit']=='off') echo 'checked'; ?> onClick="enable_change_dirSize();"/> + <strong><?php echo gettext("Disable"); ?></strong> + <?php echo gettext("directory size limit"); ?><br/> + <br/><span class="red"><strong><?=gettext("Note: ");?></strong></span><?=gettext("this setting imposes a hard-limit on the combined log directory size of all Suricata interfaces. ") . + gettext("When the size limit set is reached, rotated logs for all interfaces will be removed, and any active logs pruned to zero-length.");?> + <br/><br/> + <span class="red"><strong><?php echo gettext("Warning:"); ?></strong></span> <?php echo gettext("NanoBSD " . + "should use no more than 10MB of space."); ?></td> + </tr> + </table> + <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tr> + <td class="vexpl"><?php echo gettext("Size in ") . "<strong>" . gettext("MB:") . "</strong>";?> + <input name="suricataloglimitsize" type="text" class="formfld unknown" id="suricataloglimitsize" size="10" value="<?=htmlspecialchars($pconfig['suricataloglimitsize']);?>"/> + <?php echo gettext("Default is ") . "<strong>" . gettext("20%") . "</strong>" . gettext(" of available space.");?></td> + </tr> + </table> + </td> +</tr> +<tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Log Size and Retention Limits"); ?></td> +</tr> +<tr> + <td class="vncell" valign="top" width="22%"><?php echo gettext("Text Log Settings");?></td> + <td class="vtable" width="78%"> + <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <colgroup> + <col style="width: 15%;"> + <col style="width: 18%;"> + <col style="width: 20%;"> + <col> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?=gettext("Log Name");?></th> + <th class="listhdrr"><?=gettext("Max Size");?></th> + <th class="listhdrr"><?=gettext("Retention");?></th> + <th class="listhdrr"><?=gettext("Log Description");?></th> + </tr> + </thead> + <tbody> + <tr> + <td class="listbg">alerts</td> + <td class="listr" align="center"><select name="alert_log_limit_size" class="formselect" id="alert_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['alert_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="alert_log_retention" class="formselect" id="alert_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['alert_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("Suricata alerts and event details");?></td> + </tr> + <tr> + <td class="listbg">block</td> + <td class="listr" align="center"><select name="block_log_limit_size" class="formselect" id="block_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['block_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="block_log_retention" class="formselect" id="block_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['block_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("Suricata blocked IPs and event details");?></td> + </tr> + <tr> + <td class="listbg">files-json</td> + <td class="listr" align="center"><select name="files_json_log_limit_size" class="formselect" id="files_json_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['files_json_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="files_json_log_retention" class="formselect" id="files_json_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['files_json_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("Captured files info in JSON format");?></td> + </tr> + <tr> + <td class="listbg">http</td> + <td class="listr" align="center"><select name="http_log_limit_size" class="formselect" id="http_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['http_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="http_log_retention" class="formselect" id="http_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['http_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("Captured HTTP events and session info");?></td> + </tr> + <tr> + <td class="listbg">stats</td> + <td class="listr" align="center"><select name="stats_log_limit_size" class="formselect" id="stats_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['stats_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="stats_log_retention" class="formselect" id="stats_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['stats_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("Suricata performance statistics");?></td> + </tr> + <tr> + <td class="listbg">tls</td> + <td class="listr" align="center"><select name="tls_log_limit_size" class="formselect" id="tls_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['tls_log_limit_size']) echo "selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="tls_log_retention" class="formselect" id="tls_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['tls_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("SMTP TLS handshake details");?></td> + </tr> + </tbody> + </table> + <br/><?=gettext("Settings will be ignored for any log in the list above not enabled on the Interface Settings tab. ") . + gettext("When a log reaches the Max Size limit, it will be rotated and tagged with a timestamp. The Retention period determines ") . + gettext("how long rotated logs are kept before they are automatically deleted.");?> + </td> +</tr> +<tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Unified2 Log Limit"); ?></td> + <td width="78%" class="vtable"> + <input name="unified2_log_limit" type="text" class="formfld unknown" + id="unified2_log_limit" size="10" value="<?=htmlspecialchars($pconfig['unified2_log_limit']);?>"/> + <?php echo gettext("Log file size limit in megabytes (MB). Default is "); ?><strong><?=gettext("32 MB.");?></strong><br/> + <?php echo gettext("This sets the maximum size for a unified2 log file before it is rotated and a new one created."); ?> + </td> +</tr> +<tr> + <td class="vncell" width="22%" valign="top"><?=gettext("Unified2 Archived Log Retention Period");?></td> + <td width="78%" class="vtable"><select name="u2_archive_log_retention" class="formselect" id="u2_archive_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['u2_archive_log_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> <?=gettext("Choose retention period for archived Barnyard2 binary log files. Default is ") . "<strong>" . gettext("7 days."). "</strong>";?><br/><br/> + <?=gettext("When Barnyard2 output is enabled, Suricata writes event data to a binary format file that Barnyard2 reads and processes. ") . + gettext("When finished processing a file, Barnyard2 moves it to an archive folder. This setting determines how long files ") . + gettext("remain in the archive folder before they are automatically deleted.");?> + </td> +</tr> +<tr> + <td class="vncell" width="22%" valign="top"><?=gettext("Captured Files Retention Period");?></td> + <td width="78%" class="vtable"><select name="file_store_retention" class="formselect" id="file_store_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['file_store_retention']) echo "selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> <?=gettext("Choose retention period for captured files in File Store. Default is ") . "<strong>" . gettext("7 days."). "</strong>";?><br/><br/> + <?=gettext("When file capture and store is enabled, Suricata captures downloaded files from HTTP sessions and stores them, along with metadata, ") . + gettext("for later analysis. This setting determines how long files remain in the File Store folder before they are automatically deleted.");?> + </td> +</tr> +<tr> + <td width="22%"></td> + <td width="78%" class="vexpl"><input name="save" type="submit" class="formbtn" value="Save"/><br/> + <br/><span class="red"><strong><?php echo gettext("Note:");?></strong> + </span><?php echo gettext("Changing any settings on this page will affect all Suricata-configured interfaces.");?></td> +</tr> + </table> +</div><br/> +</td></tr> +</table> +</form> + +<script language="JavaScript"> +function enable_change() { + var endis = !(document.iform.enable_log_mgmt.checked); + document.iform.alert_log_limit_size.disabled = endis; + document.iform.alert_log_retention.disabled = endis; + document.iform.block_log_limit_size.disabled = endis; + document.iform.block_log_retention.disabled = endis; + document.iform.files_json_log_limit_size.disabled = endis; + document.iform.files_json_log_retention.disabled = endis; + document.iform.http_log_limit_size.disabled = endis; + document.iform.http_log_retention.disabled = endis; + document.iform.stats_log_limit_size.disabled = endis; + document.iform.stats_log_retention.disabled = endis; + document.iform.tls_log_limit_size.disabled = endis; + document.iform.tls_log_retention.disabled = endis; + document.iform.unified2_log_limit.disabled = endis; + document.iform.u2_archive_log_retention.disabled = endis; + document.iform.file_store_retention.disabled = endis; +} + +function enable_change_dirSize() { + var endis = !(document.getElementById('suricataloglimit_on').checked); + document.getElementById('suricataloglimitsize').disabled = endis; +} + +enable_change(); +enable_change_dirSize(); +</script> + +<?php include("fend.inc"); ?> + +</body> +</html> diff --git a/config/suricata/suricata_os_policy_engine.php b/config/suricata/suricata_os_policy_engine.php index 61918e65..869d940c 100644 --- a/config/suricata/suricata_os_policy_engine.php +++ b/config/suricata/suricata_os_policy_engine.php @@ -1,12 +1,24 @@ <?php /* * suricata_os_policy_engine.php + * + * Portions of this code are based on original work done for the + * Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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. * @@ -26,153 +38,39 @@ * POSSIBILITY OF SUCH DAMAGE. */ -require_once("guiconfig.inc"); -require_once("/usr/local/pkg/suricata/suricata.inc"); - -global $g; - -// Grab the incoming QUERY STRING or POST variables -$id = $_GET['id']; -$eng_id = $_GET['eng_id']; -if (isset($_POST['id'])) - $id = $_POST['id']; -if (isset($_POST['eng_id'])) - $eng_id = $_POST['eng_id']; - -if (is_null($id)) { - header("Location: /suricata/suricata_interfaces.php"); - exit; -} - -if (!is_array($config['installedpackages']['suricata']['rule'])) - $config['installedpackages']['suricata']['rule'] = array(); -if (!is_array($config['installedpackages']['suricata']['rule'][$id]['host_os_policy']['item'])) - $config['installedpackages']['suricata']['rule'][$id]['host_os_policy']['item'] = array(); -$a_nat = &$config['installedpackages']['suricata']['rule'][$id]['host_os_policy']['item']; - -$pconfig = array(); -if (empty($a_nat[$eng_id])) { - $def = array( "name" => "engine_{$eng_id}", "bind_to" => "", "policy" => "bsd" ); - // See if this is initial entry and set to "default" if true - if ($eng_id < 1) { - $def['name'] = "default"; - $def['bind_to'] = "all"; - } - $pconfig = $def; -} -else { - $pconfig = $a_nat[$eng_id]; - - // Check for any empty values and set sensible defaults - if (empty($pconfig['policy'])) - $pconfig['policy'] = "bsd"; -} - -if ($_POST['Cancel']) { - header("Location: /suricata/suricata_flow_stream.php?id={$id}"); - exit; -} - -// Check for returned "selected alias" if action is import -if ($_GET['act'] == "import") { - if ($_GET['varname'] == "bind_to" && !empty($_GET['varvalue'])) - $pconfig[$_GET['varname']] = $_GET['varvalue']; -} - -if ($_POST['Submit']) { +/************************************************************************************** + This file contains code for adding/editing an existing Host OS Policy Engine. + It is included and injected inline as needed into the suricata_stream_flow.php + page to provide the edit functionality for Host OS Policy Engines. - /* Grab all the POST values and save in new temp array */ - $engine = array(); - if ($_POST['policy_name']) { $engine['name'] = trim($_POST['policy_name']); } else { $engine['name'] = "default"; } - if ($_POST['policy_bind_to']) { - if (is_alias($_POST['policy_bind_to'])) - $engine['bind_to'] = $_POST['policy_bind_to']; - elseif (strtolower(trim($_POST['policy_bind_to'])) == "all") - $engine['bind_to'] = "all"; - else - $input_errors[] = gettext("You must provide a valid Alias or the reserved keyword 'all' for the 'Bind-To IP Address' value."); - } - else { - $input_errors[] = gettext("The 'Bind-To IP Address' value cannot be blank. Provide a valid Alias or the reserved keyword 'all'."); - } + The following variables are assumed to exist and must be initialized + as necessary in order to utilize this page. - if ($_POST['policy']) { $engine['policy'] = $_POST['policy']; } else { $engine['policy'] = "bsd"; } + $g --> system global variables array + $config --> global variable pointing to configuration information + $pengcfg --> array containing current Host OS Policy engine configuration - /* Can only have one "all" Bind_To address */ - if ($engine['bind_to'] == "all" && $engine['name'] <> "default") { - $input_errors[] = gettext("Only one default OS-Policy Engine can be bound to all addresses."); - $pconfig = $engine; - } - - /* if no errors, write new entry to conf */ - if (!$input_errors) { - if (isset($eng_id) && $a_nat[$eng_id]) { - $a_nat[$eng_id] = $engine; - } - else - $a_nat[] = $engine; - - /* Reorder the engine array to ensure the */ - /* 'bind_to=all' entry is at the bottom */ - /* if it contains more than one entry. */ - if (count($a_nat) > 1) { - $i = -1; - foreach ($a_nat as $f => $v) { - if ($v['bind_to'] == "all") { - $i = $f; - break; - } - } - /* Only relocate the entry if we */ - /* found it, and it's not already */ - /* at the end. */ - if ($i > -1 && ($i < (count($a_nat) - 1))) { - $tmp = $a_nat[$i]; - unset($a_nat[$i]); - $a_nat[] = $tmp; - } - } - - /* Now write the new engine array to conf */ - write_config(); - - header("Location: /suricata/suricata_flow_stream.php?id={$id}"); - exit; - } -} - -$if_friendly = convert_friendly_interface_to_friendly_descr($config['installedpackages']['suricata']['rule'][$id]['interface']); -$pgtitle = gettext("Suricata: Interface {$if_friendly} Operating System Policy Engine"); -include_once("head.inc"); + Information is returned from this page via the following form fields: + policy_name --> Unique Name for the Host OS Policy Engine + policy_bind_to --> Alias name representing "bind_to" IP address for engine + policy --> Operating system chosen for engine policy + select_alias --> Submit button for select alias operation + save_os_policy --> Submit button for save operation and exit + cancel_os_policy --> Submit button to cancel operation and exit + **************************************************************************************/ ?> -<body link="#0000CC" vlink="#0000CC" alink="#0000CC" > - -<?php -include("fbegin.inc"); -if ($input_errors) print_input_errors($input_errors); -if ($savemsg) - print_info_box($savemsg); -?> - -<form action="suricata_os_policy_engine.php" method="post" name="iform" id="iform"> -<input name="id" type="hidden" value="<?=$id?>"> -<input name="eng_id" type="hidden" value="<?=$eng_id?>"> -<div id="boxarea"> -<table width="100%" border="0" cellpadding="0" cellspacing="0"> -<tr> -<td class="tabcont"> -<table width="100%" border="0" cellpadding="6" cellspacing="0"> +<table class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> <tr> - <td colspan="2" valign="middle" class="listtopic"><?php echo gettext("Suricata Target-Based OS Policy Engine Configuration"); ?></td> + <td colspan="2" align="center" class="listtopic"><?php echo gettext("Suricata Target-Based Host OS Policy Engine Configuration"); ?></td> </tr> <tr> - <td valign="top" class="vncell"><?php echo gettext("Engine Name"); ?></td> + <td valign="top" class="vncell"><?php echo gettext("Policy Name"); ?></td> <td class="vtable"> <input name="policy_name" type="text" class="formfld unknown" id="policy_name" size="25" maxlength="25" - value="<?=htmlspecialchars($pconfig['name']);?>"<?php if (htmlspecialchars($pconfig['name']) == "default") echo "readonly";?>> - <?php if (htmlspecialchars($pconfig['name']) <> "default") + value="<?=htmlspecialchars($pengcfg['name']);?>"<?php if (htmlspecialchars($pengcfg['name']) == "default") echo "readonly";?>/> + <?php if (htmlspecialchars($pengcfg['name']) <> "default") echo gettext("Name or description for this engine. (Max 25 characters)"); else echo "<span class=\"red\">" . gettext("The name for the 'default' engine is read-only.") . "</span>";?><br/> @@ -183,13 +81,13 @@ if ($savemsg) <tr> <td valign="top" class="vncell"><?php echo gettext("Bind-To IP Address Alias"); ?></td> <td class="vtable"> - <?php if ($pconfig['name'] <> "default") : ?> + <?php if ($pengcfg['name'] <> "default") : ?> <table width="95%" border="0" cellpadding="2" cellspacing="0"> <tr> <td class="vexpl"><input name="policy_bind_to" type="text" class="formfldalias" id="policy_bind_to" size="32" - value="<?=htmlspecialchars($pconfig['bind_to']);?>" title="<?=trim(filter_expand_alias($pconfig['bind_to']));?>" autocomplete="off"> + value="<?=htmlspecialchars($pengcfg['bind_to']);?>" title="<?=trim(filter_expand_alias($pengcfg['bind_to']));?>" autocomplete="off"/> <?php echo gettext("IP List to bind this engine to. (Cannot be blank)"); ?></td> - <td class="vexpl" align="right"><input type="button" class="formbtns" value="Aliases" onclick="parent.location='suricata_select_alias.php?id=<?=$id;?>&eng_id=<?=$eng_id;?>&type=host|network&varname=bind_to&act=import&multi_ip=yes&returl=<?=urlencode($_SERVER['PHP_SELF']);?>'" + <td class="vexpl" align="right"><input type="submit" class="formbtns" name="select_alias" value="Aliases" title="<?php echo gettext("Select an existing IP alias");?>"/></td> </tr> <tr> @@ -200,7 +98,7 @@ if ($savemsg) <?php else : ?> <input name="policy_bind_to" type="text" class="formfldalias" id="policy_bind_to" size="32" - value="<?=htmlspecialchars($pconfig['bind_to']);?>" autocomplete="off" readonly> + value="<?=htmlspecialchars($pengcfg['bind_to']);?>" autocomplete="off" readonly> <?php echo "<span class=\"red\">" . gettext("IP List for the default engine is read-only and must be 'all'.") . "</span>";?><br/> <?php echo gettext("The default engine is required and will apply for packets with destination addresses not matching other engine IP Lists.");?><br/> <?php endif ?> @@ -214,7 +112,7 @@ if ($savemsg) $profile = array( 'BSD', 'BSD-Right', 'HPUX10', 'HPUX11', 'Irix', 'Linux', 'Mac-OS', 'Old-Linux', 'Old-Solaris', 'Solaris', 'Vista', 'Windows', 'Windows2k3' ); foreach ($profile as $val): ?> <option value="<?=strtolower($val);?>" - <?php if (strtolower($val) == $pconfig['policy']) echo "selected"; ?>> + <?php if (strtolower($val) == $pengcfg['policy']) echo "selected"; ?>> <?=gettext($val);?></option> <?php endforeach; ?> </select> <?php echo gettext("Choose the OS target policy appropriate for the protected hosts. The default is ") . @@ -225,20 +123,13 @@ if ($savemsg) <tr> <td width="22%" valign="bottom"> </td> <td width="78%" valign="bottom"> - <input name="Submit" id="submit" type="submit" class="formbtn" value=" Save " title="<?php echo + <input name="save_os_policy" id="save_os_policy" type="submit" class="formbtn" value=" Save " title="<?php echo gettext("Save OS policy engine settings and return to Flow/Stream tab"); ?>"> - <input name="Cancel" id="cancel" type="submit" class="formbtn" value="Cancel" title="<?php echo + <input name="cancel_os_policy" id="cancel_os_policy" type="submit" class="formbtn" value="Cancel" title="<?php echo gettext("Cancel changes and return to Flow/Stream tab"); ?>"></td> </tr> </table> -</td> -</tr> -</table> -</div> -</form> -<?php include("fend.inc"); ?> -</body> <script type="text/javascript" src="/javascript/autosuggest.js"> </script> <script type="text/javascript" src="/javascript/suggestions.js"> @@ -258,4 +149,3 @@ setTimeout("createAutoSuggest();", 500); </script> -</html> diff --git a/config/suricata/suricata_passlist.php b/config/suricata/suricata_passlist.php new file mode 100644 index 00000000..fc7c60e2 --- /dev/null +++ b/config/suricata/suricata_passlist.php @@ -0,0 +1,206 @@ +<?php +/* + * suricata_passlist.php + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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"); +require_once("/usr/local/pkg/suricata/suricata.inc"); + +if (!is_array($config['installedpackages']['suricata']['passlist'])) + $config['installedpackages']['suricata']['passlist'] = array(); +if (!is_array($config['installedpackages']['suricata']['passlist']['item'])) + $config['installedpackages']['suricata']['passlist']['item'] = array(); +$a_passlist = &$config['installedpackages']['suricata']['passlist']['item']; + +// Calculate the next Pass List index ID +if (isset($config['installedpackages']['suricata']['passlist']['item'])) + $id_gen = count($config['installedpackages']['suricata']['passlist']['item']); +else + $id_gen = '0'; + +function suricata_is_passlist_used($list) { + + /********************************************** + * This function tests the provided Pass List * + * to determine if it is assigned to an * + * interface. * + * * + * On Entry: $list -> Pass List name to test * + * * + * Returns: TRUE if Pass List is in use or * + * FALSE if not in use * + **********************************************/ + + global $config; + + if (!is_array($config['installedpackages']['suricata']['rule'])) + return FALSE; + + foreach($config['installedpackages']['suricata']['rule'] as $v) { + if (isset($v['passlistname']) && $v['passlistname'] == $list) + return TRUE; + } + return FALSE; +} + +if ($_POST['del'] && is_numericint($_POST['list_id'])) { + if ($a_passlist[$_POST['list_id']]) { + /* make sure list is not being referenced by any interface */ + if (suricata_is_passlist_used($a_passlist[$_POST['list_id']]['name'])) { + $input_errors[] = gettext("This Pass List is currently assigned to a Suricata interface and cannot be deleted. Unassign it from all Suricata interfaces first."); + } + if (!$input_errors) { + unset($a_passlist[$_POST['list_id']]); + write_config("Suricata pkg: deleted PASS LIST."); + sync_suricata_package_config(); + header("Location: /suricata/suricata_passlist.php"); + exit; + } + } +} + +$pgtitle = gettext("Suricata: Pass Lists"); +include_once("head.inc"); +?> + +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> + +<?php +include_once("fbegin.inc"); + +/* Display Alert message */ +if ($input_errors) { + print_input_errors($input_errors); +} +if ($savemsg) { + print_info_box($savemsg); +} +?> + +<form action="/suricata/suricata_passlist.php" method="post"> +<input type="hidden" name="list_id" id="list_id" value=""/> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tr><td> + <?php + $tab_array = array(); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); + $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), true, "/suricata/suricata_passlist.php"); + $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); + ?> + </td> +</tr> +<tr> + <td><div id="mainarea"> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr> + <td width="25%" class="listhdrr">List Name</td> + <td width="30%" class="listhdrr">Assigned Alias</td> + <td class="listhdr">Description</td> + <td width="40px" class="list"></td> + </tr> + <?php foreach ($a_passlist as $i => $list): ?> + <tr> + <td class="listlr" + ondblclick="document.location='suricata_passlist_edit.php?id=<?=$i;?>';"> + <?=htmlspecialchars($list['name']);?></td> + <td class="listr" + ondblclick="document.location='suricata_passlist_edit.php?id=<?=$i;?>';" + title="<?=filter_expand_alias($list['address']);?>"> + <?php echo gettext($list['address']);?></td> + <td class="listbg" + ondblclick="document.location='suricata_passlist_edit.php?id=<?=$i;?>';"> + <font color="#FFFFFF"> <?=htmlspecialchars($list['descr']);?> + </td> + <td valign="middle" nowrap class="list"> + <table border="0" cellspacing="0" cellpadding="1"> + <tr> + <td valign="middle"><a href="suricata_passlist_edit.php?id=<?=$i;?>"> + <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0" title="<?php echo gettext("Edit pass list"); ?>"></a> + </td> + <td><input type="image" name="del[]" onclick="document.getElementById('list_id').value='<?=$i;?>';return confirm('<?=gettext("Do you really want to delete this pass list? Click OK to continue or CANCEL to quit.)!");?>');" + src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0" title="<?php echo gettext("Delete pass list"); ?>"/> + </td> + </tr> + </table> + </td> + </tr> + <?php endforeach; ?> + <tr> + <td class="list" colspan="3"></td> + <td class="list"> + <table border="0" cellspacing="0" cellpadding="1"> + <tr> + <td valign="middle" width="17"> </td> + <td valign="middle"><a href="suricata_passlist_edit.php?id=<?php echo $id_gen;?> "> + <img src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" + width="17" height="17" border="0" title="<?php echo gettext("add a new pass list"); ?>"/></a> + </td> + </tr> + </table> + </td> + </tr> + </table> + </div> + </td> + </tr> +</table> +<br> +<table width="100%" border="0" cellpadding="1" + cellspacing="1"> + <tr> + <td width="100%"><span class="vexpl"><span class="red"><strong><?php echo gettext("Notes:"); ?></strong></span> + <p><?php echo gettext("1. Here you can create Pass List files for your Suricata package rules. Hosts on a Pass List are never blocked by Suricata."); ?><br/> + <?php echo gettext("2. Add all the IP addresses or networks (in CIDR notation) you want to protect against Suricata block decisions."); ?><br/> + <?php echo gettext("3. The default Pass List includes the WAN IP and gateway, defined DNS servers, VPNs and locally-attached networks."); ?><br/> + <?php echo gettext("4. Be careful, it is very easy to get locked out of your system by altering the default settings."); ?></p></span></td> + </tr> + <tr> + <td width="100%"><span class="vexpl"><?php echo gettext("Remember you must restart Suricata on the interface for changes to take effect!"); ?></span></td> + </tr> +</table> +</form> +<?php include("fend.inc"); ?> +</body> +</html> diff --git a/config/suricata/suricata_passlist_edit.php b/config/suricata/suricata_passlist_edit.php new file mode 100644 index 00000000..35c7b66e --- /dev/null +++ b/config/suricata/suricata_passlist_edit.php @@ -0,0 +1,329 @@ +<?php +/* + * suricata_passlist_edit.php + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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"); +require_once("/usr/local/pkg/suricata/suricata.inc"); + +if ($_POST['cancel']) { + header("Location: /suricata/suricata_passlist.php"); + exit; +} + +if (!is_array($config['installedpackages']['suricata']['passlist'])) + $config['installedpackages']['suricata']['passlist'] = array(); +if (!is_array($config['installedpackages']['suricata']['passlist']['item'])) + $config['installedpackages']['suricata']['passlist']['item'] = array(); +$a_passlist = &$config['installedpackages']['suricata']['passlist']['item']; + +if (isset($_POST['id']) && is_numericint($_POST['id'])) + $id = $_POST['id']; +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); + +/* Should never be called without identifying list index, so bail */ +if (is_null($id)) { + header("Location: /suricata/suricata_interfaces_passlist.php"); + exit; +} + +/* If no entry for this passlist, then create a UUID and treat it like a new list */ +if (!isset($a_passlist[$id]['uuid'])) { + $passlist_uuid = 0; + while ($passlist_uuid > 65535 || $passlist_uuid == 0) { + $passlist_uuid = mt_rand(1, 65535); + $pconfig['uuid'] = $passlist_uuid; + $pconfig['name'] = "passlist_{$passlist_uuid}"; + } +} else + $passlist_uuid = $a_passlist[$id]['uuid']; + +/* returns true if $name is a valid name for a pass list file name or ip */ +function is_validpasslistname($name) { + if (!is_string($name)) + return false; + + if (!preg_match("/[^a-zA-Z0-9\_\.\/]/", $name)) + return true; + + return false; +} + +if (isset($id) && $a_passlist[$id]) { + /* old settings */ + $pconfig = array(); + $pconfig['name'] = $a_passlist[$id]['name']; + $pconfig['uuid'] = $a_passlist[$id]['uuid']; + $pconfig['detail'] = $a_passlist[$id]['detail']; + $pconfig['address'] = $a_passlist[$id]['address']; + $pconfig['descr'] = html_entity_decode($a_passlist[$id]['descr']); + $pconfig['localnets'] = $a_passlist[$id]['localnets']; + $pconfig['wanips'] = $a_passlist[$id]['wanips']; + $pconfig['wangateips'] = $a_passlist[$id]['wangateips']; + $pconfig['wandnsips'] = $a_passlist[$id]['wandnsips']; + $pconfig['vips'] = $a_passlist[$id]['vips']; + $pconfig['vpnips'] = $a_passlist[$id]['vpnips']; +} + +// Check for returned "selected alias" if action is import +if ($_GET['act'] == "import") { + if ($_GET['varname'] == "address" && isset($_GET['varvalue'])) + $pconfig[$_GET['varname']] = htmlspecialchars($_GET['varvalue']); +} + +if ($_POST['save']) { + unset($input_errors); + $pconfig = $_POST; + + /* input validation */ + $reqdfields = explode(" ", "name"); + $reqdfieldsn = explode(",", "Name"); + do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors); + + if(strtolower($_POST['name']) == "defaultpasslist") + $input_errors[] = gettext("Pass List file names may not be named defaultpasslist."); + + if (is_validpasslistname($_POST['name']) == false) + $input_errors[] = gettext("Pass List file name may only consist of the characters \"a-z, A-Z, 0-9 and _\". Note: No Spaces or dashes. Press Cancel to reset."); + + /* check for name conflicts */ + foreach ($a_passlist as $w_list) { + if (isset($id) && ($a_passlist[$id]) && ($a_passlist[$id] === $w_list)) + continue; + + if ($w_list['name'] == $_POST['name']) { + $input_errors[] = gettext("A Pass List file name with this name already exists."); + break; + } + } + + if ($_POST['address']) + if (!is_alias($_POST['address'])) + $input_errors[] = gettext("A valid alias must be provided"); + + if (!$input_errors) { + $w_list = array(); + /* post user input */ + $w_list['name'] = $_POST['name']; + $w_list['uuid'] = $passlist_uuid; + $w_list['localnets'] = $_POST['localnets']? 'yes' : 'no'; + $w_list['wanips'] = $_POST['wanips']? 'yes' : 'no'; + $w_list['wangateips'] = $_POST['wangateips']? 'yes' : 'no'; + $w_list['wandnsips'] = $_POST['wandnsips']? 'yes' : 'no'; + $w_list['vips'] = $_POST['vips']? 'yes' : 'no'; + $w_list['vpnips'] = $_POST['vpnips']? 'yes' : 'no'; + + $w_list['address'] = $_POST['address']; + $w_list['descr'] = mb_convert_encoding($_POST['descr'],"HTML-ENTITIES","auto"); + $w_list['detail'] = $final_address_details; + + if (isset($id) && $a_passlist[$id]) + $a_passlist[$id] = $w_list; + else + $a_passlist[] = $w_list; + + write_config("Snort pkg: modified PASS LIST {$w_list['name']}."); + + /* create pass list and homenet file, then sync files */ + sync_suricata_package_config(); + + header("Location: /suricata/suricata_passlist.php"); + exit; + } +} + +$pgtitle = gettext("Suricata: Pass List Edit - {$pconfig['name']}"); +include_once("head.inc"); +?> + +<body link="#0000CC" vlink="#0000CC" alink="#0000CC" > + +<?php +include("fbegin.inc"); +if ($input_errors) + print_input_errors($input_errors); +if ($savemsg) + print_info_box($savemsg); +?> +<script type="text/javascript" src="/javascript/autosuggest.js"> +</script> +<script type="text/javascript" src="/javascript/suggestions.js"> +</script> +<form action="suricata_passlist_edit.php" method="post" name="iform" id="iform"> +<input name="id" type="hidden" value="<?=$id;?>" /> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tr><td> +<?php + $tab_array = array(); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); + $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), true, "/suricata/suricata_passlist.php"); + $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); +?> + </td> +</tr> +<tr><td><div id="mainarea"> +<table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Add the name and " . + "description of the file."); ?></td> + </tr> + <tr> + <td valign="top" class="vncellreq"><?php echo gettext("Name"); ?></td> + <td class="vtable"><input name="name" type="text" id="name" class="formfld unknown" + size="40" value="<?=htmlspecialchars($pconfig['name']);?>" /> <br /> + <span class="vexpl"> <?php echo gettext("The list name may only consist of the " . + "characters \"a-z, A-Z, 0-9 and _\"."); ?> <span class="red"><?php echo gettext("Note:"); ?> </span> + <?php echo gettext("No Spaces or dashes."); ?> </span></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Description"); ?></td> + <td width="78%" class="vtable"><input name="descr" type="text" class="formfld unknown" + id="descr" size="40" value="<?=$pconfig['descr'];?>" /> <br /> + <span class="vexpl"> <?php echo gettext("You may enter a description here for your " . + "reference (not parsed)."); ?> </span></td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Add auto-generated IP Addresses."); ?></td> + </tr> + + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Local Networks"); ?></td> + <td width="78%" class="vtable"><input name="localnets" type="checkbox" + id="localnets" size="40" value="yes" + <?php if($pconfig['localnets'] == 'yes'){ echo "checked";} if($pconfig['localnets'] == ''){ echo "checked";} ?> /> + <span class="vexpl"> <?php echo gettext("Add firewall Local Networks to the list (excluding WAN)."); ?> </span></td> + </tr> + + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("WAN IPs"); ?></td> + <td width="78%" class="vtable"><input name="wanips" type="checkbox" + id="wanips" size="40" value="yes" + <?php if($pconfig['wanips'] == 'yes'){ echo "checked";} if($pconfig['wanips'] == ''){ echo "checked";} ?> /> + <span class="vexpl"> <?php echo gettext("Add WAN interface IPs to the list."); ?> </span></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("WAN Gateways"); ?></td> + <td width="78%" class="vtable"><input name="wangateips" + type="checkbox" id="wangateips" size="40" value="yes" + <?php if($pconfig['wangateips'] == 'yes'){ echo "checked";} if($pconfig['wangateips'] == ''){ echo "checked";} ?> /> + <span class="vexpl"> <?php echo gettext("Add WAN Gateways to the list."); ?> </span></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("WAN DNS servers"); ?></td> + <td width="78%" class="vtable"><input name="wandnsips" + type="checkbox" id="wandnsips" size="40" value="yes" + <?php if($pconfig['wandnsips'] == 'yes'){ echo "checked";} if($pconfig['wandnsips'] == ''){ echo "checked";} ?> /> + <span class="vexpl"> <?php echo gettext("Add WAN DNS servers to the list."); ?> </span></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Virtual IP Addresses"); ?></td> + <td width="78%" class="vtable"><input name="vips" type="checkbox" + id="vips" size="40" value="yes" + <?php if($pconfig['vips'] == 'yes'){ echo "checked";} if($pconfig['vips'] == ''){ echo "checked";} ?> /> + <span class="vexpl"> <?php echo gettext("Add Virtual IP Addresses to the list."); ?> </span></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("VPNs"); ?></td> + <td width="78%" class="vtable"><input name="vpnips" type="checkbox" + id="vpnips" size="40" value="yes" + <?php if($pconfig['vpnips'] == 'yes'){ echo "checked";} if($pconfig['vpnips'] == ''){ echo "checked";} ?> /> + <span class="vexpl"> <?php echo gettext("Add VPN Addresses to the list."); ?> </span></td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Add custom IP Addresses from configured Aliases."); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"> + <?php echo gettext("Assigned Aliases:"); ?> + </td> + <td width="78%" class="vtable"> + <input autocomplete="off" name="address" type="text" class="formfldalias" id="address" size="30" value="<?=htmlspecialchars($pconfig['address']);?>" + title="<?=trim(filter_expand_alias($pconfig['address']));?>"/> + <input type="button" class="formbtns" value="Aliases" onclick="parent.location='suricata_select_alias.php?id=0&type=host|network&varname=address&act=import&multi_ip=yes&returl=<?=urlencode($_SERVER['PHP_SELF']);?>'" + title="<?php echo gettext("Select an existing IP alias");?>"/> + </td> + </tr> + <tr> + <td width="22%" valign="top"> </td> + <td width="78%"> + <input id="save" name="save" type="submit" class="formbtn" value="Save" /> + <input id="cancel" name="cancel" type="submit" class="formbtn" value="Cancel" /> + </td> + </tr> +</table> +</div> +</td></tr> +</table> +</form> +<script type="text/javascript"> +<?php + $isfirst = 0; + $aliases = ""; + $addrisfirst = 0; + $aliasesaddr = ""; + if(isset($config['aliases']['alias']) && is_array($config['aliases']['alias'])) + foreach($config['aliases']['alias'] as $alias_name) { + if ($alias_name['type'] != "host" && $alias_name['type'] != "network") + continue; + if($addrisfirst == 1) $aliasesaddr .= ","; + $aliasesaddr .= "'" . $alias_name['name'] . "'"; + $addrisfirst = 1; + } +?> + var addressarray=new Array(<?php echo $aliasesaddr; ?>); + +function createAutoSuggest() { +<?php + echo "objAlias = new AutoSuggestControl(document.getElementById('address'), new StateSuggestions(addressarray));\n"; +?> +} + +setTimeout("createAutoSuggest();", 500); + +</script> +<?php include("fend.inc"); ?> +</body> +</html> diff --git a/config/suricata/suricata_post_install.php b/config/suricata/suricata_post_install.php index 653f47fd..c44b392f 100644 --- a/config/suricata/suricata_post_install.php +++ b/config/suricata/suricata_post_install.php @@ -2,13 +2,23 @@ /* * suricata_post_install.php * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks - * part of pfSense * 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. * @@ -50,14 +60,14 @@ if(is_process_running("suricata")) { killbyname("suricata"); sleep(2); // Delete any leftover suricata PID files in /var/run - array_map('@unlink', glob("/var/run/suricata_*.pid")); + unlink_if_exists("/var/run/suricata_*.pid"); } // Hard kill any running Barnyard2 processes if(is_process_running("barnyard")) { killbyname("barnyard2"); sleep(2); // Delete any leftover barnyard2 PID files in /var/run - array_map('@unlink', glob("/var/run/barnyard2_*.pid")); + unlink_if_exists("/var/run/barnyard2_*.pid"); } // Set flag for post-install in progress @@ -87,6 +97,17 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = foreach ($suriconf as $value) { $if_real = get_real_interface($value['interface']); + // ## BETA pkg bug fix-up -- be sure default rules enabled ## + $rules = explode("||", $value['rulesets']); + foreach (array( "decoder-events.rules", "files.rules", "http-events.rules", "smtp-events.rules", "stream-events.rules", "tls-events.rules" ) as $r){ + if (!in_array($r, $rules)) + $rules[] = $r; + } + natcasesort($rules); + $value['rulesets'] = implode("||", $rules); + write_config(); + // ## end of BETA pkg bug fix-up ## + // create a suricata.yaml file for interface suricata_generate_yaml($value); @@ -99,13 +120,19 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = suricata_create_rc(); // Set Log Limit, Block Hosts Time and Rules Update Time - suricata_loglimit_install_cron($config['installedpackages']['suricata']['config'][0]['suricataloglimit'] == 'on' ? true : false); -// suricata_rm_blocked_install_cron($config['installedpackages']['suricata']['config'][0]['rm_blocked'] != "never_b" ? true : false); + suricata_loglimit_install_cron(true); + suricata_rm_blocked_install_cron($config['installedpackages']['suricata']['config'][0]['rm_blocked'] != "never_b" ? true : false); suricata_rules_up_install_cron($config['installedpackages']['suricata']['config'][0]['autoruleupdate'] != "never_up" ? true : false); // Add the recurring jobs created above to crontab configure_cron(); + // Restore the Dashboard Widget if it was previously enabled and saved + if (!empty($config['installedpackages']['suricata']['config'][0]['dashboard_widget']) && !empty($config['widgets']['sequence'])) + $config['widgets']['sequence'] .= "," . $config['installedpackages']['suricata']['config'][0]['dashboard_widget']; + if (!empty($config['installedpackages']['suricata']['config'][0]['dashboard_widget_rows']) && !empty($config['widgets'])) + $config['widgets']['widget_suricata_display_lines'] = $config['installedpackages']['suricata']['config'][0]['dashboard_widget_rows']; + $rebuild_rules = false; update_output_window(gettext("Finished rebuilding Suricata configuration files...")); log_error(gettext("[Suricata] Finished rebuilding installation from saved settings...")); @@ -121,7 +148,7 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = } // Update Suricata package version in configuration -$config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "0.1-BETA"; +$config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "v1.0.1"; write_config(); // Done with post-install, so clear flag diff --git a/config/suricata/suricata_rules.php b/config/suricata/suricata_rules.php index b848b4e8..82bb33eb 100644 --- a/config/suricata/suricata_rules.php +++ b/config/suricata/suricata_rules.php @@ -2,19 +2,30 @@ /* * suricata_rules.php * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -27,7 +38,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ - require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); @@ -35,38 +45,25 @@ global $g, $rebuild_rules; $suricatadir = SURICATADIR; $rules_map = array(); +$pconfig = array(); if (!is_array($config['installedpackages']['suricata']['rule'])) $config['installedpackages']['suricata']['rule'] = array(); $a_rule = &$config['installedpackages']['suricata']['rule']; -$id = $_GET['id']; -if (isset($_POST['id'])) +if (isset($_POST['id']) && is_numericint($_POST['id'])) $id = $_POST['id']; +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); + if (is_null($id)) { - header("Location: /suricata/suricata_interfaces.php"); - exit; + $id = 0; } if (isset($id) && $a_rule[$id]) { - $pconfig['enable'] = $a_rule[$id]['enable']; $pconfig['interface'] = $a_rule[$id]['interface']; $pconfig['rulesets'] = $a_rule[$id]['rulesets']; - if (!empty($a_rule[$id]['customrules'])) - $pconfig['customrules'] = base64_decode($a_rule[$id]['customrules']); -} - -function truncate($string, $length) { - - /******************************** - * This function truncates the * - * passed string to the length * - * specified adding ellipsis if * - * truncation was necessary. * - ********************************/ - if (strlen($string) > $length) - $string = substr($string, 0, ($length - 2)) . "..."; - return $string; + $pconfig['customrules'] = base64_decode($a_rule[$id]['customrules']); } function add_title_attribute($tag, $title) { @@ -110,9 +107,15 @@ $emergingdownload = $config['installedpackages']['suricata']['config'][0]['enabl $etpro = $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules']; $categories = explode("||", $pconfig['rulesets']); +// Add any previously saved rules files to the categories array +if (!empty($pconfig['rulesets'])) + $categories = explode("||", $pconfig['rulesets']); + if ($_GET['openruleset']) - $currentruleset = $_GET['openruleset']; -else if ($_POST['openruleset']) + $currentruleset = htmlspecialchars($_GET['openruleset'], ENT_QUOTES | ENT_HTML401); +elseif ($_POST['selectbox']) + $currentruleset = $_POST['selectbox']; +elseif ($_POST['openruleset']) $currentruleset = $_POST['openruleset']; else $currentruleset = $categories[0]; @@ -149,13 +152,11 @@ if ($currentruleset != 'custom.rules') { $enablesid = suricata_load_sid_mods($a_rule[$id]['rule_sid_on']); $disablesid = suricata_load_sid_mods($a_rule[$id]['rule_sid_off']); -if ($_GET['act'] == "toggle" && $_GET['ids'] && !empty($rules_map)) { - - // Get the GID tag embedded in the clicked rule icon. - $gid = $_GET['gid']; +if ($_POST['toggle'] && is_numeric($_POST['sid']) && is_numeric($_POST['gid']) && !empty($rules_map)) { - // Get the SID tag embedded in the clicked rule icon. - $sid= $_GET['ids']; + // Get the GID:SID tags embedded in the clicked rule icon. + $gid = $_POST['gid']; + $sid = $_POST['sid']; // See if the target SID is in our list of modified SIDs, // and toggle it back to default if present; otherwise, @@ -199,11 +200,9 @@ if ($_GET['act'] == "toggle" && $_GET['ids'] && !empty($rules_map)) { /* Update the config.xml file. */ write_config(); - $_GET['openruleset'] = $currentruleset; $anchor = "rule_{$gid}_{$sid}"; } - -if ($_GET['act'] == "disable_all" && !empty($rules_map)) { +elseif ($_POST['disable_all'] && !empty($rules_map)) { // Mark all rules in the currently selected category "disabled". foreach (array_keys($rules_map) as $k1) { @@ -240,13 +239,8 @@ if ($_GET['act'] == "disable_all" && !empty($rules_map)) { unset($a_rule[$id]['rule_sid_off']); write_config(); - - $_GET['openruleset'] = $currentruleset; - header("Location: /suricata/suricata_rules.php?id={$id}&openruleset={$currentruleset}"); - exit; } - -if ($_GET['act'] == "enable_all" && !empty($rules_map)) { +elseif ($_POST['enable_all'] && !empty($rules_map)) { // Mark all rules in the currently selected category "enabled". foreach (array_keys($rules_map) as $k1) { @@ -282,13 +276,8 @@ if ($_GET['act'] == "enable_all" && !empty($rules_map)) { unset($a_rule[$id]['rule_sid_off']); write_config(); - - $_GET['openruleset'] = $currentruleset; - header("Location: /suricata/suricata_rules.php?id={$id}&openruleset={$currentruleset}"); - exit; } - -if ($_GET['act'] == "resetcategory" && !empty($rules_map)) { +elseif ($_POST['resetcategory'] && !empty($rules_map)) { // Reset any modified SIDs in the current rule category to their defaults. foreach (array_keys($rules_map) as $k1) { @@ -326,13 +315,8 @@ if ($_GET['act'] == "resetcategory" && !empty($rules_map)) { unset($a_rule[$id]['rule_sid_off']); write_config(); - - $_GET['openruleset'] = $currentruleset; - header("Location: /suricata/suricata_rules.php?id={$id}&openruleset={$currentruleset}"); - exit; } - -if ($_GET['act'] == "resetall" && !empty($rules_map)) { +elseif ($_POST['resetall'] && !empty($rules_map)) { // Remove all modified SIDs from config.xml and save the changes. unset($a_rule[$id]['rule_sid_on']); @@ -340,46 +324,32 @@ if ($_GET['act'] == "resetall" && !empty($rules_map)) { /* Update the config.xml file. */ write_config(); - - $_GET['openruleset'] = $currentruleset; - header("Location: /suricata/suricata_rules.php?id={$id}&openruleset={$currentruleset}"); - exit; } - -if ($_POST['clear']) { +elseif ($_POST['clear']) { unset($a_rule[$id]['customrules']); write_config(); $rebuild_rules = true; suricata_generate_yaml($a_rule[$id]); $rebuild_rules = false; - header("Location: /suricata/suricata_rules.php?id={$id}&openruleset={$currentruleset}"); - exit; + $pconfig['customrules'] = ''; } - -if ($_POST['customrules']) { - $a_rule[$id]['customrules'] = base64_encode($_POST['customrules']); +elseif ($_POST['cancel']) { + $pconfig['customrules'] = base64_decode($a_rule[$id]['customrules']); +} +elseif ($_POST['save']) { + $pconfig['customrules'] = $_POST['customrules']; + if ($_POST['customrules']) + $a_rule[$id]['customrules'] = base64_encode($_POST['customrules']); + else + unset($a_rule[$id]['customrules']); write_config(); $rebuild_rules = true; suricata_generate_yaml($a_rule[$id]); $rebuild_rules = false; - $output = ""; - $retcode = ""; -// exec("/usr/local/bin/snort -T -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf 2>&1", $output, $retcode); -// if (intval($retcode) != 0) { -// $error = ""; -// $start = count($output); -// $end = $start - 4; -// for($i = $start; $i > $end; $i--) -// $error .= $output[$i]; -// $input_errors[] = "Custom rules have errors:\n {$error}"; -// } -// else { -// header("Location: /snort/snort_rules.php?id={$id}&openruleset={$currentruleset}"); -// exit; -// } + /* Signal Suricata to "live reload" the rules */ + suricata_reload_config($a_rule[$id]); } - -else if ($_POST['apply']) { +elseif ($_POST['apply']) { /* Save new configuration */ write_config(); @@ -394,16 +364,6 @@ else if ($_POST['apply']) { /* Signal Suricata to "live reload" the rules */ suricata_reload_config($a_rule[$id]); - - /* Return to this same page */ - header("Location: /suricata/suricata_rules.php?id={$id}&openruleset={$currentruleset}"); - exit; -} -else if ($_POST['cancel']) { - - /* Return to this same page */ - header("Location: /suricata/suricata_rules.php?id={$id}"); - exit; } require_once("guiconfig.inc"); @@ -416,9 +376,7 @@ $pgtitle = gettext("Suricata: Interface {$if_friendly} - Rules: {$currentruleset <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); -if ($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';} - -/* Display message */ +/* Display error or save messages if present */ if ($input_errors) { print_input_errors($input_errors); // TODO: add checks } @@ -429,18 +387,25 @@ if ($savemsg) { ?> -<form action="/suricata/suricata_rules.php" method="post" name="iform" id="iform"> +<form action='/suricata/suricata_rules.php' method='post' name='iform' id='iform'> +<input type='hidden' name='id' id='id' value='<?=$id;?>'/> +<input type='hidden' name='openruleset' id='openruleset' value='<?=$currentruleset;?>'/> +<input type='hidden' name='sid' id='sid' value=''/> +<input type='hidden' name='gid' id='gid' value=''/> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; $menu_iface=($if_friendly?substr($if_friendly,0,5)." ":"Iface ");; @@ -452,7 +417,7 @@ if ($savemsg) { $tab_array[] = array($menu_iface . gettext("App Parsers"), false, "/suricata/suricata_app_parsers.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Variables"), false, "/suricata/suricata_define_vars.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Barnyard2"), false, "/suricata/suricata_barnyard.php?id={$id}"); - display_top_tabs($tab_array); + display_top_tabs($tab_array, true); ?> </td></tr> <tr><td><div id="mainarea"> @@ -460,31 +425,31 @@ if ($savemsg) { <tr> <td class="listtopic"><?php echo gettext("Available Rule Categories"); ?></td> </tr> - <tr> - <td class="vncell" height="30px"><strong><?php echo gettext("Category:"); ?></strong> <select id="selectbox" name="selectbox" class="formselect" onChange="go()"> - <option value='?id=<?=$id;?>&openruleset=custom.rules'>custom.rules</option> + <td class="vncell" height="30px"><strong><?php echo gettext("Category:"); ?></strong> + <select id="selectbox" name="selectbox" class="formselect" onChange="go();"> + <option value='custom.rules'>custom.rules</option> <?php - $files = explode("||", $pconfig['rulesets']); - if ($a_rule[$id]['ips_policy_enable'] == 'on') - $files[] = "IPS Policy - " . ucfirst($a_rule[$id]['ips_policy']); - if ($a_rule[$id]['autoflowbitrules'] == 'on') - $files[] = "Auto-Flowbit Rules"; - natcasesort($files); - foreach ($files as $value) { - if ($snortdownload != 'on' && substr($value, 0, mb_strlen(VRT_FILE_PREFIX)) == VRT_FILE_PREFIX) - continue; - if ($emergingdownload != 'on' && substr($value, 0, mb_strlen(ET_OPEN_FILE_PREFIX)) == ET_OPEN_FILE_PREFIX) - continue; - if ($etpro != 'on' && substr($value, 0, mb_strlen(ET_PRO_FILE_PREFIX)) == ET_PRO_FILE_PREFIX) - continue; - if (empty($value)) - continue; - echo "<option value='?id={$id}&openruleset={$value}' "; - if ($value == $currentruleset) - echo "selected"; - echo ">{$value}</option>\n"; - } + $files = explode("||", $pconfig['rulesets']); + if ($a_rule[$id]['ips_policy_enable'] == 'on') + $files[] = "IPS Policy - " . ucfirst($a_rule[$id]['ips_policy']); + if ($a_rule[$id]['autoflowbitrules'] == 'on') + $files[] = "Auto-Flowbit Rules"; + natcasesort($files); + foreach ($files as $value) { + if ($snortdownload != 'on' && substr($value, 0, mb_strlen(VRT_FILE_PREFIX)) == VRT_FILE_PREFIX) + continue; + if ($emergingdownload != 'on' && substr($value, 0, mb_strlen(ET_OPEN_FILE_PREFIX)) == ET_OPEN_FILE_PREFIX) + continue; + if ($etpro != 'on' && substr($value, 0, mb_strlen(ET_PRO_FILE_PREFIX)) == ET_PRO_FILE_PREFIX) + continue; + if (empty($value)) + continue; + echo "<option value='{$value}' "; + if ($value == $currentruleset) + echo "selected"; + echo ">{$value}</option>\n"; + } ?> </select> <?php echo gettext("Select the rule category to view"); ?> </td> @@ -496,15 +461,13 @@ if ($savemsg) { </tr> <tr> <td valign="top" class="vtable"> - <input type='hidden' name='openruleset' value='custom.rules'> - <input type='hidden' name='id' value='<?=$id;?>'> <textarea wrap="soft" cols="90" rows="40" name="customrules"><?=$pconfig['customrules'];?></textarea> </td> </tr> <tr> <td> - <input name="Submit" type="submit" class="formbtn" id="submit" value="<?php echo gettext(" Save "); ?>" title=" <?php echo gettext("Save custom rules"); ?>"/> - <input name="cancel" type="submit" class="formbtn" id="cancel" value="<?php echo gettext("Cancel"); ?>" title="<?php echo gettext("Cancel changes and return to last page"); ?>"/> + <input name="save" type="submit" class="formbtn" id="save" value="<?php echo gettext(" Save "); ?>" title=" <?php echo gettext("Save custom rules"); ?>"/> + <input name="cancel" type="submit" class="formbtn" id="cancel" value="<?php echo gettext("Cancel"); ?>" title="<?php echo gettext("Cancel all changes made prior to last save"); ?>"/> <input name="clear" type="submit" class="formbtn" id="clear" value="<?php echo gettext("Clear"); ?>" onclick="return confirm('<?php echo gettext("This will erase all custom rules for the interface. Are you sure?"); ?>')" title="<?php echo gettext("Deletes all custom rules"); ?>"/> </td> </tr> @@ -517,43 +480,40 @@ if ($savemsg) { <table width="100%" align="center" border="0" cellpadding="0" cellspacing="0"> <tr> <td rowspan="5" width="48%" valign="middle"><input type="submit" name="apply" id="apply" value="<?php echo gettext("Apply"); ?>" class="formbtn" - title="<?php echo gettext("Click to rebuild the rules with your changes"); ?>"/> - <input type='hidden' name='id' value='<?=$id;?>'/> - <input type='hidden' name='openruleset' value='<?=$currentruleset;?>'/><br/><br/> + title="<?php echo gettext("Click to rebuild the rules with your changes"); ?>"/><br/><br/> <span class="vexpl"><span class="red"><strong><?php echo gettext("Note: ") . "</strong></span>" . - gettext("Suricata must be restarted to activate any SID enable/disable changes made on this tab."); ?></span></td> - <td class="vexpl" valign="middle"><?php echo "<a href='?id={$id}&openruleset={$currentruleset}&act=resetcategory'> - <img src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"15\" height=\"15\" + gettext("When finished, click APPLY to send any SID enable/disable changes made on this tab to the running Suricata process."); ?></span></td> + <td class="vexpl" valign="middle"><?php echo "<input type='image' name='resetcategory[]' + src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"15\" height=\"15\" onmouseout='this.src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"' onmouseover='this.src=\"../themes/{$g['theme']}/images/icons/icon_x_mo.gif\"' border='0' - title='" . gettext("Click to remove enable/disable changes for rules in the selected category only") . "'></a>"?> + title='" . gettext("Click to remove enable/disable changes for rules in the selected category only") . "'/>"?> <?php echo gettext("Remove Enable/Disable changes in the current Category"); ?></td> </tr> <tr> - <td class="vexpl" valign="middle"><?php echo "<a href='?id={$id}&openruleset={$currentruleset}&act=resetall'> - <img src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"15\" height=\"15\" + <td class="vexpl" valign="middle"><?php echo "<input type='image' name='resetall[]' + src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"15\" height=\"15\" onmouseout='this.src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"' onmouseover='this.src=\"../themes/{$g['theme']}/images/icons/icon_x_mo.gif\"' border='0' - title='" . gettext("Click to remove all enable/disable changes for rules in all categories") . "'></a>"?> + title='" . gettext("Click to remove all enable/disable changes for rules in all categories") . "'/>"?> <?php echo gettext("Remove all Enable/Disable changes in all Categories"); ?></td> </tr> <tr> - <td class="vexpl" valign="middle"><?php echo "<a href='?id={$id}&openruleset={$currentruleset}&act=disable_all'> - <img src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"15\" height=\"15\" + <td class="vexpl" valign="middle"><?php echo "<input type='image' name='disable_all[]' + src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\" width=\"15\" height=\"15\" onmouseout='this.src=\"../themes/{$g['theme']}/images/icons/icon_x.gif\"' onmouseover='this.src=\"../themes/{$g['theme']}/images/icons/icon_x_mo.gif\"' border='0' - title='" . gettext("Click to disable all rules in the selected category") . "'></a>"?> + title='" . gettext("Click to disable all rules in the selected category") . "'/>"?> <?php echo gettext("Disable all rules in the current Category"); ?></td> </tr> <tr> - <td class="vexpl" valign="middle"><?php echo "<a href='?id={$id}&openruleset={$currentruleset}&act=enable_all'> - <img src=\"../themes/{$g['theme']}/images/icons/icon_plus.gif\" width=\"15\" height=\"15\" + <td class="vexpl" valign="middle"><?php echo "<input type='image' name='enable_all[]' + src=\"../themes/{$g['theme']}/images/icons/icon_plus.gif\" width=\"15\" height=\"15\" onmouseout='this.src=\"../themes/{$g['theme']}/images/icons/icon_plus.gif\"' onmouseover='this.src=\"../themes/{$g['theme']}/images/icons/icon_plus_mo.gif\"' border='0' - title='" . gettext("Click to enable all rules in the selected category") . "'></a>"?> + title='" . gettext("Click to enable all rules in the selected category") . "'/>"?> <?php echo gettext("Enable all rules in the current Category"); ?></td> </tr> - <tr> <td class="vexpl" valign="middle"><a href="javascript: void(0)" onclick="wopen('suricata_rules_edit.php?id=<?=$id;?>&openruleset=<?=$currentruleset;?>','FileViewer',800,600)"> @@ -563,7 +523,6 @@ if ($savemsg) { title="<?php echo gettext("Click to view full text of all the category rules"); ?>" width="17" height="17" border="0"></a> <?php echo gettext("View full file contents for the current Category"); ?></td> </tr> - <?php if ($currentruleset == 'Auto-Flowbit Rules'): ?> <tr> <td colspan="3"> </td> @@ -578,7 +537,6 @@ if ($savemsg) { </table> </td> </tr> - <tr> <td class="listtopic"><?php echo gettext("Selected Category's Rules"); ?></td> </tr> @@ -588,13 +546,12 @@ if ($savemsg) { <colgroup> <col width="14" align="left" valign="middle"> <col width="6%" align="center" axis="number"> - <col width="8%" align="center" axis="number"> - <col width="54" align="center" axis="string"> + <col width="9%" align="center" axis="number"> <col width="52" align="center" axis="string"> - <col width="12%" align="center" axis="string"> - <col width="9%" align="center" axis="string"> - <col width="12%" align="center" axis="string"> - <col width="9%" align="center" axis="string"> + <col width="14%" align="center" axis="string"> + <col width="10%" align="center" axis="string"> + <col width="14%" align="center" axis="string"> + <col width="10%" align="center" axis="string"> <col axis="string"> </colgroup> <thead> @@ -602,12 +559,11 @@ if ($savemsg) { <th class="list"> </th> <th class="listhdrr"><?php echo gettext("GID"); ?></th> <th class="listhdrr"><?php echo gettext("SID"); ?></th> - <th class="listhdrr"><?php echo gettext("Action"); ?></th> <th class="listhdrr"><?php echo gettext("Proto"); ?></th> <th class="listhdrr"><?php echo gettext("Source"); ?></th> - <th class="listhdrr"><?php echo gettext("Port"); ?></th> + <th class="listhdrr"><?php echo gettext("SPort"); ?></th> <th class="listhdrr"><?php echo gettext("Destination"); ?></th> - <th class="listhdrr"><?php echo gettext("Port"); ?></th> + <th class="listhdrr"><?php echo gettext("DPort"); ?></th> <th class="listhdrr"><?php echo gettext("Message"); ?></th> </tr> </thead> @@ -653,53 +609,50 @@ if ($savemsg) { $tmp = trim(preg_replace('/^\s*#+\s*/', '', $tmp)); $rule_content = preg_split('/[\s]+/', $tmp); - // Create custom <span> tags for the fields we truncate so we can + // Create custom <span> tags for some of the fields so we can // have a "title" attribute for tooltips to show the full string. $srcspan = add_title_attribute($textss, $rule_content[2]); $srcprtspan = add_title_attribute($textss, $rule_content[3]); $dstspan = add_title_attribute($textss, $rule_content[5]); $dstprtspan = add_title_attribute($textss, $rule_content[6]); $protocol = $rule_content[1]; //protocol field - $source = truncate($rule_content[2], 14); //source field - $source_port = truncate($rule_content[3], 10); //source port field - $destination = truncate($rule_content[5], 14); //destination field - $destination_port = truncate($rule_content[6], 10); //destination port field + $source = $rule_content[2]; //source field + $source_port = $rule_content[3]; //source port field + $destination = $rule_content[5]; //destination field + $destination_port = $rule_content[6]; //destination port field $message = suricata_get_msg($v['rule']); $sid_tooltip = gettext("View the raw text for this rule"); - echo "<tr><td class=\"listt\" align=\"left\" valign=\"middle\">{$textss} - <a href='?id={$id}&openruleset={$currentruleset}&act=toggle&ids={$sid}'> - <img src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" - width=\"11\" height=\"11\" border=\"0\" - title='{$title}' id=\"rule_{$gid}_{$sid}\"></a>{$textse} + echo "<tr><td class=\"listt\" align=\"left\" valign=\"middle\" sorttable_customkey=\"\">{$textss} + <a id=\"rule_{$gid}_{$sid}\" href='#'><input type=\"image\" onClick=\"document.getElementById('sid').value='{$sid}'; + document.getElementById('gid').value='{$gid}';\" + src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" + title='{$title}' name=\"toggle[]\"/></a>{$textse} </td> - <td class=\"listlr\" align=\"center\" style=\"font-size: 10px;\"> + <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$textss}{$gid}{$textse} </td> - <td class=\"listlr\" align=\"center\" style=\"font-size: 10px;\"> + <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> <a href=\"javascript: void(0)\" - onclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&ids={$sid}&gid={$gid}','FileViewer',800,600)\" + onclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\" title='{$sid_tooltip}'>{$textss}{$sid}{$textse}</a> </td> - <td class=\"listlr\" align=\"center\" style=\"font-size: 10px;\"> - {$textss}{$v['action']}{$textse} - </td> - <td class=\"listlr\" align=\"center\" style=\"font-size: 10px;\"> + <td class=\"listr\" style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$textss}{$protocol}{$textse} </td> - <td class=\"listlr\" align=\"center\" style=\"font-size: 10px;\"> + <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$srcspan}{$source}</span> </td> - <td class=\"listlr\" align=\"center\" style=\"font-size: 10px;\"> + <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$srcprtspan}{$source_port}</span> </td> - <td class=\"listlr\" align=\"center\" style=\"font-size: 10px;\"> + <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$dstspan}{$destination}</span> </td> - <td class=\"listlr\" align=\"center\" style=\"font-size: 10px;\"> + <td class=\"listr ellipsis\" nowrap style=\"text-align:center;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$dstprtspan}{$destination_port}</span> </td> - <td class=\"listbg\" style=\"word-wrap:break-word; whitespace:pre-line; font-size: 10px; font-color: white;\"> + <td class=\"listbg\" style=\"word-wrap:break-word; whitespace:pre-line;\" ondblclick=\"wopen('suricata_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$textss}{$message}{$textse} </td> </tr>"; @@ -752,15 +705,14 @@ if ($savemsg) { </tr> </table> </form> -<?php include("fend.inc"); ?> - <script language="javascript" type="text/javascript"> function go() { - var box = document.iform.selectbox; - destination = box.options[box.selectedIndex].value; - if (destination) - location.href = destination; + var box = document.getElementById("selectbox"); + var ruleset = box.options[box.selectedIndex].value; + if (ruleset) + document.getElementById("openruleset").value = ruleset; + document.getElementById("iform").submit(); } function wopen(url, name, w, h) @@ -784,7 +736,8 @@ function wopen(url, name, w, h) window.scrollBy(0,-60); <?php endif;?> - </script> +<?php include("fend.inc"); ?> + </body> </html> diff --git a/config/suricata/suricata_rules_edit.php b/config/suricata/suricata_rules_edit.php index 0dc4c57b..0a4bd62a 100644 --- a/config/suricata/suricata_rules_edit.php +++ b/config/suricata/suricata_rules_edit.php @@ -2,19 +2,30 @@ /* * suricata_rules_edit.php * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -33,28 +44,29 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); $flowbit_rules_file = FLOWBITS_FILENAME; $suricatadir = SURICATADIR; -if (!is_array($config['installedpackages']['suricata']['rule'])) { - $config['installedpackages']['suricata']['rule'] = array(); -} -$a_rule = &$config['installedpackages']['suricata']['rule']; +if (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); -$id = $_GET['id']; +// If we were not passed a valid index ID, close the pop-up and exit if (is_null($id)) { - header("Location: /suricata/suricata_interfaces.php"); + echo '<html><body link="#000000" vlink="#000000" alink="#000000">'; + echo '<script language="javascript" type="text/javascript">'; + echo 'window.close();</script>'; + echo '</body></html>'; exit; } -if (isset($id) && $a_rule[$id]) { - $pconfig['enable'] = $a_rule[$id]['enable']; - $pconfig['interface'] = $a_rule[$id]['interface']; - $pconfig['rulesets'] = $a_rule[$id]['rulesets']; +if (!is_array($config['installedpackages']['suricata']['rule'])) { + $config['installedpackages']['suricata']['rule'] = array(); } -/* convert fake interfaces to real */ -$if_real = suricata_get_real_interface($pconfig['interface']); +$a_rule = &$config['installedpackages']['suricata']['rule']; + +$if_real = get_real_interface($a_rule[$id]['interface']); $suricata_uuid = $a_rule[$id]['uuid']; -$suricatacfgdir = "{$suricatadir}suricata_{$suricata_uuid}_{$if_real}"; -$file = $_GET['openruleset']; +$suricatacfgdir = "{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/"; + +$file = htmlspecialchars($_GET['openruleset'], ENT_QUOTES | ENT_HTML401); $contents = ''; $wrap_flag = "off"; @@ -69,13 +81,13 @@ else // a standard rules file, or a complete file name. // Test for the special case of an IPS Policy file. if (substr($file, 0, 10) == "IPS Policy") { - $rules_map = suricata_load_vrt_policy($a_rule[$id]['ips_policy']); - if (isset($_GET['ids'])) { - $contents = $rules_map[$_GET['gid']][trim($_GET['ids'])]['rule']; + $rules_map = suricata_load_vrt_policy(strtolower(trim(substr($file, strpos($file, "-")+1)))); + if (isset($_GET['sid']) && is_numericint($_GET['sid']) && isset($_GET['gid']) && is_numericint($_GET['gid'])) { + $contents = $rules_map[$_GET['gid']][trim($_GET['sid'])]['rule']; $wrap_flag = "soft"; } else { - $contents = "# Suricata IPS Policy - " . ucfirst($a_rule[$id]['ips_policy']) . "\n\n"; + $contents = "# Suricata IPS Policy - " . ucfirst(trim(substr($file, strpos($file, "-")+1))) . "\n\n"; foreach (array_keys($rules_map) as $k1) { foreach (array_keys($rules_map[$k1]) as $k2) { $contents .= "# Category: " . $rules_map[$k1][$k2]['category'] . " SID: {$k2}\n"; @@ -86,33 +98,26 @@ if (substr($file, 0, 10) == "IPS Policy") { unset($rules_map); } // Is it a SID to load the rule text from? -elseif (isset($_GET['ids'])) { +elseif (isset($_GET['sid']) && is_numericint($_GET['sid']) && isset($_GET['gid']) && is_numericint($_GET['gid'])) { // If flowbit rule, point to interface-specific file if ($file == "Auto-Flowbit Rules") $rules_map = suricata_load_rules_map("{$suricatacfgdir}rules/" . FLOWBITS_FILENAME); else $rules_map = suricata_load_rules_map("{$suricatadir}rules/{$file}"); - $contents = $rules_map[$_GET['gid']][trim($_GET['ids'])]['rule']; + $contents = $rules_map[$_GET['gid']][trim($_GET['sid'])]['rule']; $wrap_flag = "soft"; } - // Is it our special flowbit rules file? elseif ($file == "Auto-Flowbit Rules") $contents = file_get_contents("{$suricatacfgdir}rules/{$flowbit_rules_file}"); // Is it a rules file in the ../rules/ directory? elseif (file_exists("{$suricatadir}rules/{$file}")) $contents = file_get_contents("{$suricatadir}rules/{$file}"); -// Is it a fully qualified path and file? -elseif (file_exists($file)) - if (substr(realpath($file), 0, strlen(SURICATALOGDIR)) != SURICATALOGDIR) - $contents = gettext("\n\nERROR -- File: {$file} can not be viewed!"); - else - $contents = file_get_contents($file); // It is not something we can display, so exit. else $input_errors[] = gettext("Unable to open file: {$displayfile}"); -$pgtitle = array(gettext("Suricata"), gettext("File Viewer")); +$pgtitle = array(gettext("Suricata"), gettext("Rules File Viewer")); ?> <?php include("head.inc");?> @@ -131,7 +136,7 @@ $pgtitle = array(gettext("Suricata"), gettext("File Viewer")); </tr> <tr> <td width="20%"> - <input type="button" class="formbtn" value="Return" onclick="window.close()"> + <input type="button" class="formbtn" value="Close" onclick="window.close()"/> </td> <td align="right"> <b><?php echo gettext("Rules File: ") . '</b> ' . $displayfile; ?> diff --git a/config/suricata/suricata_rules_flowbits.php b/config/suricata/suricata_rules_flowbits.php index ca424344..c5193a8b 100644 --- a/config/suricata/suricata_rules_flowbits.php +++ b/config/suricata/suricata_rules_flowbits.php @@ -1,19 +1,31 @@ <?php /* * suricata_rules_flowbits.php + * + * Portions of this code are based on original work done for the + * Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -41,34 +53,34 @@ if (!is_array($config['installedpackages']['suricata']['rule'])) { } $a_nat = &$config['installedpackages']['suricata']['rule']; -// Set who called us so we can return to the correct page with -// the RETURN button. We will just trust this User-Agent supplied -// string for now. -session_start(); -if(!isset($_SESSION['org_referer'])) - $_SESSION['org_referer'] = $_SERVER['HTTP_REFERER']; -$referrer = $_SESSION['org_referer']; +if (isset($_POST['id']) && is_numericint($_POST['id'])) + $id = $_POST['id']; +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); -if ($_POST['cancel']) { - session_start(); - unset($_SESSION['org_referer']); - session_write_close(); - header("Location: {$referrer}"); +if (is_null($id)) { + header("Location: /suricata/suricata_interfaces.php"); exit; } -$id = $_GET['id']; -if (isset($_POST['id'])) - $id = $_POST['id']; -if (is_null($id)) { - session_start(); - unset($_SESSION['org_referer']); - session_write_close(); - header("Location: /suricata/suricata_interfaces.php"); +// Set who called us so we can return to the correct page with +// the RETURN ('cancel') button. +if ($_POST['referrer']) + $referrer = $_POST['referrer']; +else + $referrer = $_SERVER['HTTP_REFERER']; + +// Make sure a rule index ID is appended to the return URL +if (strpos($referrer, "?id={$id}") === FALSE) + $referrer .= "?id={$id}"; + +// If RETURN button clicked, exit to original calling page +if ($_POST['cancel']) { + header("Location: {$referrer}"); exit; } -$if_real = suricata_get_real_interface($a_nat[$id]['interface']); +$if_real = get_real_interface($a_nat[$id]['interface']); $suricata_uuid = $a_nat[$id]['uuid']; /* We should normally never get to this page if Auto-Flowbits are disabled, but just in case... */ @@ -83,12 +95,13 @@ if ($a_nat[$id]['autoflowbitrules'] == 'on') { else $input_errors[] = gettext("Auto-Flowbit rule generation is disabled for this interface!"); -if ($_GET['act'] == "addsuppress" && is_numeric($_GET['sidid']) && is_numeric($_GET['gen_id'])) { - $descr = suricata_get_msg($rules_map[$_GET['gen_id']][$_GET['sidid']]['rule']); +if ($_POST['addsuppress'] && is_numeric($_POST['sid']) && is_numeric($_POST['gid'])) { + $descr = suricata_get_msg($rules_map[$_POST['gid']][$_POST['sid']]['rule']); + $suppress = gettext("## -- This rule manually suppressed from the Auto-Flowbits list. -- ##\n"); if (empty($descr)) - $suppress = "suppress gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}\n"; + $suppress .= "suppress gen_id {$_POST['gid']}, sig_id {$_POST['sid']}\n"; else - $suppress = "# {$descr}\nsuppress gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}\n"; + $suppress .= "# {$descr}\nsuppress gen_id {$_POST['gid']}, sig_id {$_POST['sid']}\n"; if (!is_array($config['installedpackages']['suricata']['suppress'])) $config['installedpackages']['suricata']['suppress'] = array(); if (!is_array($config['installedpackages']['suricata']['suppress']['item'])) @@ -128,7 +141,7 @@ if ($_GET['act'] == "addsuppress" && is_numeric($_GET['sidid']) && is_numeric($_ $rebuild_rules = false; sync_suricata_package_config(); suricata_reload_config($a_nat[$id]); - $savemsg = gettext("An entry to suppress the Alert for 'gen_id {$_GET['gen_id']}, sig_id {$_GET['sidid']}' has been added to Suppress List '{$a_nat[$id]['suppresslistname']}'."); + $savemsg = gettext("An entry to suppress the Alert for 'gen_id {$_POST['gid']}, sig_id {$_POST['sid']}' has been added to Suppress List '{$a_nat[$id]['suppresslistname']}'."); } else { /* We did not find the defined list, so notify the user with an error */ @@ -136,23 +149,10 @@ if ($_GET['act'] == "addsuppress" && is_numeric($_GET['sidid']) && is_numeric($_ } } -function truncate($string, $length) { - - /******************************** - * This function truncates the * - * passed string to the length * - * specified adding ellipsis if * - * truncation was necessary. * - ********************************/ - if (strlen($string) > $length) - $string = substr($string, 0, ($length - 3)) . "..."; - return $string; -} - /* Load up an array with the current Suppression List GID,SID values */ $supplist = suricata_load_suppress_sigs($a_nat[$id]); -$if_friendly = suricata_get_friendly_interface($a_nat[$id]['interface']); +$if_friendly = convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface']); $pgtitle = gettext("Suricata: Interface {$if_friendly} - Flowbit Rules"); include_once("head.inc"); @@ -162,12 +162,15 @@ include_once("head.inc"); <?php include("fbegin.inc"); -if($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';} if ($input_errors) print_input_errors($input_errors); if ($savemsg) print_info_box($savemsg); ?> <form action="suricata_rules_flowbits.php" method="post" name="iform" id="iform"> +<input type="hidden" name="id" value="<?=$id;?>"/> +<input type="hidden" name="referrer" value="<?=$referrer;?>"/> +<input type="hidden" name="sid" id="sid" value=""/> +<input type="hidden" name="gid" id="gid" value=""/> <div id="boxarea"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> @@ -214,13 +217,13 @@ if ($savemsg) </tr> <tr> <td> - <table id="myTable" width="100%" class="sortable" border="1" cellpadding="0" cellspacing="0"> + <table id="myTable" width="100%" class="sortable" style="table-layout: fixed;" border="0" cellpadding="0" cellspacing="0"> <colgroup> <col width="11%" axis="number"> - <col width="10%" axis="string"> + <col width="52" axis="string"> <col width="14%" axis="string"> <col width="14%" axis="string"> - <col width="20%" axis="string"> + <col width="24%" axis="string"> <col axis="string"> </colgroup> <thead> @@ -248,18 +251,19 @@ if ($savemsg) $rule_content = preg_split('/[\s]+/', $tmp); $protocol = $rule_content[1]; //protocol - $source = truncate($rule_content[2], 14); //source - $destination = truncate($rule_content[5], 14); //destination + $source = $rule_content[2]; //source + $destination = $rule_content[5]; //destination $message = suricata_get_msg($v['rule']); $flowbits = implode("; ", suricata_get_flowbits($v['rule'])); if (strstr($flowbits, "noalert")) $supplink = ""; else { if (!isset($supplist[$gid][$sid])) { - $supplink = "<a href=\"?id={$id}&act=addsuppress&sidid={$sid}&gen_id={$gid}\">"; - $supplink .= "<img src=\"../themes/{$g['theme']}/images/icons/icon_plus.gif\" "; + $supplink = "<input type=\"image\" name=\"addsuppress[]\" onClick=\"document.getElementById('sid').value='{$sid}';"; + $supplink .= "document.getElementById('gid').value='{$gid}';\" "; + $supplink .= "src=\"../themes/{$g['theme']}/images/icons/icon_plus.gif\" "; $supplink .= "width='12' height='12' border='0' title='"; - $supplink .= gettext("Click to add to Suppress List") . "'/></a>"; + $supplink .= gettext("Click to add to Suppress List") . "'/>"; } else { $supplink = "<img src=\"../themes/{$g['theme']}/images/icons/icon_plus_d.gif\" "; @@ -270,12 +274,12 @@ if ($savemsg) // Use "echo" to write the table HTML row-by-row. echo "<tr>" . - "<td class=\"listr\">{$sid} {$supplink}</td>" . - "<td class=\"listr\">{$protocol}</td>" . - "<td class=\"listr\"><span title=\"{$rule_content[2]}\">{$source}</span></td>" . - "<td class=\"listr\"><span title=\"{$rule_content[5]}\">{$destination}</span></td>" . + "<td class=\"listr\" sorttable_customkey=\"{$sid}\">{$sid} {$supplink}</td>" . + "<td class=\"listr\" style=\"text-align:center;\">{$protocol}</td>" . + "<td class=\"listr ellipsis\" nowrap style=\"text-align:center;\"><span title=\"{$rule_content[2]}\">{$source}</span></td>" . + "<td class=\"listr ellipsis\" nowrap style=\"text-align:center;\"><span title=\"{$rule_content[5]}\">{$destination}</span></td>" . "<td class=\"listr\" style=\"word-wrap:break-word; word-break:normal;\">{$flowbits}</td>" . - "<td class=\"listr\" style=\"word-wrap:break-word; word-break:normal;\">{$message}</td>" . + "<td class=\"listbg\" style=\"word-wrap:break-word; word-break:normal;\">{$message}</td>" . "</tr>"; $count++; } @@ -291,7 +295,6 @@ if ($savemsg) <td align="center" valign="middle"> <input id="cancel" name="cancel" type="submit" class="formbtn" <?php echo "value=\"" . gettext("Return") . "\" title=\"" . gettext("Return to previous page") . "\""; ?>/> - <input name="id" type="hidden" value="<?=$id;?>" /> </td> </tr> <?php endif; ?> diff --git a/config/suricata/suricata_rulesets.php b/config/suricata/suricata_rulesets.php index a1609d6c..c939ef25 100644 --- a/config/suricata/suricata_rulesets.php +++ b/config/suricata/suricata_rulesets.php @@ -2,19 +2,30 @@ /* * suricata_rulesets.php * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: * Copyright (C) 2014 Bill Meeks * 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 @@ -35,18 +46,21 @@ global $g, $rebuild_rules; $suricatadir = SURICATADIR; $flowbit_rules_file = FLOWBITS_FILENAME; +// Array of default events rules for Suricata +$default_rules = array( "decoder-events.rules", "files.rules", "http-events.rules", + "smtp-events.rules", "stream-events.rules", "tls-events.rules" ); + if (!is_array($config['installedpackages']['suricata']['rule'])) { $config['installedpackages']['suricata']['rule'] = array(); } $a_nat = &$config['installedpackages']['suricata']['rule']; -$id = $_GET['id']; -if (isset($_POST['id'])) +if (isset($_POST['id']) && is_numericint($_POST['id'])) $id = $_POST['id']; -if (is_null($id)) { - header("Location: /suricata/suricata_interfaces.php"); - exit; -} +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); +if (is_null($id)) + $id = 0; if (isset($id) && $a_nat[$id]) { $pconfig['enable'] = $a_nat[$id]['enable']; @@ -89,17 +103,6 @@ if (!file_exists("{$suricatadir}rules/" . GPL_FILE_PREFIX . "community.rules")) if (($snortdownload != 'on') || ($a_nat[$id]['ips_policy_enable'] != 'on')) $policy_select_disable = "disabled"; -if ($a_nat[$id]['autoflowbitrules'] == 'on') { - if (file_exists("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}") && - filesize("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}") > 0) { - $btn_view_flowb_rules = " title=\"" . gettext("View flowbit-required rules") . "\""; - } - else - $btn_view_flowb_rules = " disabled"; -} -else - $btn_view_flowb_rules = " disabled"; - // If a Snort VRT policy is enabled and selected, remove all Snort VRT // rules from the configured rule sets to allow automatic selection. if ($a_nat[$id]['ips_policy_enable'] == 'on') { @@ -117,9 +120,7 @@ if ($a_nat[$id]['ips_policy_enable'] == 'on') { else $disable_vrt_rules = ""; -/* alert file */ -if ($_POST["Submit"]) { - +if ($_POST["save"]) { if ($_POST['ips_policy_enable'] == "on") { $a_nat[$id]['ips_policy_enable'] = 'on'; $a_nat[$id]['ips_policy'] = $_POST['ips_policy']; @@ -129,11 +130,12 @@ if ($_POST["Submit"]) { unset($a_nat[$id]['ips_policy']); } - $enabled_items = ""; + // Always start with the default events and files rules + $enabled_items = implode("||", $default_rules); if (is_array($_POST['toenable'])) - $enabled_items = implode("||", $_POST['toenable']); + $enabled_items .= "||" . implode("||", $_POST['toenable']); else - $enabled_items = $_POST['toenable']; + $enabled_items .= "||{$_POST['toenable']}"; $a_nat[$id]['rulesets'] = $enabled_items; @@ -155,12 +157,12 @@ if ($_POST["Submit"]) { suricata_generate_yaml($a_nat[$id]); $rebuild_rules = false; - header("Location: /suricata/suricata_rulesets.php?id=$id"); - exit; + /* Signal Suricata to "live reload" the rules */ + suricata_reload_config($a_nat[$id]); } - -if ($_POST['unselectall']) { - $a_nat[$id]['rulesets'] = ""; +elseif ($_POST['unselectall']) { + // Remove all but the default events and files rules + $a_nat[$id]['rulesets'] = implode("||", $default_rules); if ($_POST['ips_policy_enable'] == "on") { $a_nat[$id]['ips_policy_enable'] = 'on'; @@ -173,13 +175,10 @@ if ($_POST['unselectall']) { write_config(); sync_suricata_package_config(); - - header("Location: /suricata/suricata_rulesets.php?id=$id"); - exit; } - -if ($_POST['selectall']) { - $rulesets = array(); +elseif ($_POST['selectall']) { + // Start with the required default events and files rules + $rulesets = $default_rules; if ($_POST['ips_policy_enable'] == "on") { $a_nat[$id]['ips_policy_enable'] = 'on'; @@ -218,10 +217,20 @@ if ($_POST['selectall']) { write_config(); sync_suricata_package_config(); +} - header("Location: /suricata/suricata_rulesets.php?id=$id"); - exit; +// See if we have any Auto-Flowbit rules and enable +// the VIEW button if we do. +if ($a_nat[$id]['autoflowbitrules'] == 'on') { + if (file_exists("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}") && + filesize("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}") > 0) { + $btn_view_flowb_rules = " title=\"" . gettext("View flowbit-required rules") . "\""; + } + else + $btn_view_flowb_rules = " disabled"; } +else + $btn_view_flowb_rules = " disabled"; $enabled_rulesets_array = explode("||", $a_nat[$id]['rulesets']); @@ -234,7 +243,6 @@ include_once("head.inc"); <?php include("fbegin.inc"); -if($pfsense_stable == 'yes'){echo '<p class="pgtitle">' . $pgtitle . '</p>';} /* Display message */ if ($input_errors) { @@ -253,13 +261,16 @@ if ($savemsg) { <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Suricata Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), false, "/suricata/suricata_suppress.php"); - $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; $menu_iface=($if_friendly?substr($if_friendly,0,5)." ":"Iface "); @@ -271,7 +282,7 @@ if ($savemsg) { $tab_array[] = array($menu_iface . gettext("App Parsers"), false, "/suricata/suricata_app_parsers.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Variables"), false, "/suricata/suricata_define_vars.php?id={$id}"); $tab_array[] = array($menu_iface . gettext("Barnyard2"), false, "/suricata/suricata_barnyard.php?id={$id}"); - display_top_tabs($tab_array); + display_top_tabs($tab_array, true); ?> </td></tr> <tr> @@ -282,9 +293,8 @@ if ($savemsg) { $isrulesfolderempty = glob("{$suricatadir}rules/*.rules"); $iscfgdirempty = array(); if (file_exists("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/custom.rules")) - $iscfgdirempty = (array)("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/custom.rules"); - if (empty($isrulesfolderempty)): -?> + $iscfgdirempty = (array)("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/custom.rules"); ?> +<?php if (empty($isrulesfolderempty)): ?> <tr> <td class="vexpl"><br/> <?php printf(gettext("# The rules directory is empty: %s%srules%s"), '<strong>',$suricatadir,'</strong>'); ?> <br/><br/> @@ -294,14 +304,7 @@ if ($savemsg) { '</strong></a>' . gettext(" tab."); ?> </td> </tr> -<?php else: - $colspan = 4; - if ($emergingdownload != 'on') - $colspan -= 2; - if ($snortdownload != 'on') - $colspan -= 2; - -?> +<?php else: ?> <tr> <td> <table width="100%" border="0" @@ -393,7 +396,7 @@ if ($savemsg) { <tr height="45px"> <td valign="middle"><input value="Select All" class="formbtns" type="submit" name="selectall" id="selectall" title="<?php echo gettext("Add all to enforcing rules"); ?>"/></td> <td valign="middle"><input value="Unselect All" class="formbtns" type="submit" name="unselectall" id="unselectall" title="<?php echo gettext("Remove all from enforcing rules"); ?>"/></td> - <td valign="middle"><input value=" Save " class="formbtns" type="submit" name="Submit" id="Submit" title="<?php echo gettext("Save changes to enforcing rules and rebuild"); ?>"/></td> + <td valign="middle"><input value=" Save " class="formbtns" type="submit" name="save" id="save" title="<?php echo gettext("Save changes to enforcing rules and rebuild"); ?>"/></td> <td valign="middle"><span class="vexpl"><?php echo gettext("Click to save changes and auto-resolve flowbit rules (if option is selected above)"); ?></span></td> </tr> </table> @@ -531,7 +534,7 @@ if ($savemsg) { </tr> <tr> <td colspan="4" align="center" valign="middle"> - <input value="Save" type="submit" name="Submit" id="Submit" class="formbtn" title=" <?php echo gettext("Click to Save changes and rebuild rules"); ?>"/></td> + <input value="Save" type="submit" name="save" id="save" class="formbtn" title=" <?php echo gettext("Click to Save changes and rebuild rules"); ?>"/></td> </tr> <?php endif; ?> </table> @@ -581,7 +584,7 @@ function enable_change() for (var i = 0; i < document.iform.elements.length; i++) { if (document.iform.elements[i].type == 'checkbox') { var str = document.iform.elements[i].value; - if (str.substr(0,6) == "suricata_") + if (str.substr(0,6) == "snort_") document.iform.elements[i].disabled = !(endis); } } diff --git a/config/suricata/suricata_select_alias.php b/config/suricata/suricata_select_alias.php index f1fd4b93..527412d1 100644 --- a/config/suricata/suricata_select_alias.php +++ b/config/suricata/suricata_select_alias.php @@ -42,22 +42,29 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); // overwrite it on subsequent POST-BACKs to this page. if (!isset($_POST['org_querystr'])) $querystr = $_SERVER['QUERY_STRING']; +else + $querystr = $_POST['org_querystr']; // Retrieve any passed QUERY STRING or POST variables -$type = $_GET['type']; -$varname = $_GET['varname']; -$multi_ip = $_GET['multi_ip']; -$referrer = urldecode($_GET['returl']); if (isset($_POST['type'])) $type = $_POST['type']; +elseif (isset($_GET['type'])) + $type = htmlspecialchars($_GET['type']); + if (isset($_POST['varname'])) $varname = $_POST['varname']; +elseif (isset($_GET['varname'])) + $varname = htmlspecialchars($_GET['varname']); + if (isset($_POST['multi_ip'])) $multi_ip = $_POST['multi_ip']; +elseif (isset($_GET['multi_ip'])) + $multi_ip = htmlspecialchars($_GET['multi_ip']); + if (isset($_POST['returl'])) $referrer = urldecode($_POST['returl']); -if (isset($_POST['org_querystr'])) - $querystr = $_POST['org_querystr']; +elseif (isset($_GET['returl'])) + $referrer = urldecode($_GET['returl']); // Make sure we have a valid VARIABLE name // and ALIAS TYPE, or else bail out. @@ -122,11 +129,11 @@ include("head.inc"); <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> <form action="suricata_select_alias.php" method="post"> -<input type="hidden" name="varname" value="<?=$varname;?>"> -<input type="hidden" name="type" value="<?=$type;?>"> -<input type="hidden" name="multi_ip" value="<?=$multi_ip;?>"> -<input type="hidden" name="returl" value="<?=$referrer;?>"> -<input type="hidden" name="org_querystr" value="<?=$querystr;?>"> +<input type="hidden" name="varname" value="<?=$varname;?>"/> +<input type="hidden" name="type" value="<?=$type;?>"/> +<input type="hidden" name="multi_ip" value="<?=$multi_ip;?>"/> +<input type="hidden" name="returl" value="<?=$referrer;?>"/> +<input type="hidden" name="org_querystr" value="<?=$querystr;?>"/> <?php if ($input_errors) print_input_errors($input_errors); ?> <div id="boxarea"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> @@ -155,6 +162,14 @@ include("head.inc"); <?php $i = 0; foreach ($a_aliases as $alias): ?> <?php if (!in_array($alias['type'], $a_types)) continue; + if ( ($alias['type'] == "network" || $alias['type'] == "host") && + $multi_ip != "yes" && + !suricata_is_single_addr_alias($alias['name'])) { + $textss = "<span class=\"gray\">"; + $textse = "</span>"; + $disable = true; + $tooltip = gettext("Aliases resolving to multiple address entries cannot be used with the destination target."); + } elseif (($alias['type'] == "network" || $alias['type'] == "host") && trim(filter_expand_alias($alias['name'])) == "") { $textss = "<span class=\"gray\">"; diff --git a/config/suricata/suricata_suppress.php b/config/suricata/suricata_suppress.php index 58839dce..4f2e8d0d 100644 --- a/config/suricata/suricata_suppress.php +++ b/config/suricata/suricata_suppress.php @@ -1,30 +1,41 @@ <?php /* - suricata_suppress.php - - Copyright (C) 2014 Bill Meeks - 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. + * suricata_suppress.php + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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"); @@ -61,6 +72,28 @@ function suricata_suppresslist_used($supplist) { return false; } +function suricata_find_suppresslist_interface($supplist) { + + /****************************************************************/ + /* This function finds the first (if more than one) interface */ + /* configured to use the passed Suppress List and returns the */ + /* index of the interface in the ['rule'] config array. */ + /* */ + /* Returns: index of interface in ['rule'] config array or */ + /* FALSE if no interface found. */ + /****************************************************************/ + + global $config; + $suricataconf = $config['installedpackages']['suricata']['rule']; + if (empty($suricataconf)) + return false; + foreach ($suricataconf as $rule => $value) { + if ($value['suppresslistname'] == $supplist) + return $rule; + } + return false; +} + if ($_GET['act'] == "del") { if ($a_suppress[$_GET['id']]) { // make sure list is not being referenced by any Suricata-configured interface @@ -100,62 +133,85 @@ if ($input_errors) { $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); - $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), true, "/suricata/suricata_suppress.php"); $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); ?> </td> </tr> <tr><td><div id="mainarea"> -<table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> -<tr> - <td width="30%" class="listhdrr"><?php echo gettext("File Name"); ?></td> - <td width="60%" class="listhdr"><?php echo gettext("Description"); ?></td> - <td width="10%" class="list"></td> -</tr> -<?php $i = 0; foreach ($a_suppress as $list): ?> -<tr> - <td class="listlr" - ondblclick="document.location='suricata_suppress_edit.php?id=<?=$i;?>';"> - <?=htmlspecialchars($list['name']);?></td> - <td class="listbg" - ondblclick="document.location='suricata_suppress_edit.php?id=<?=$i;?>';"> - <font color="#FFFFFF"> <?=htmlspecialchars($list['descr']);?> </font> - </td> - - <td valign="middle" nowrap class="list"> - <table border="0" cellspacing="0" cellpadding="1"> - <tr> - <td valign="middle"><a - href="suricata_suppress_edit.php?id=<?=$i;?>"><img - src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" - width="17" height="17" border="0" title="<?php echo gettext("edit Suppress List"); ?>"></a></td> - <td><a - href="/suricata/suricata_suppress.php?act=del&id=<?=$i;?>" - onclick="return confirm('<?php echo gettext("Do you really want to delete this Suppress List?"); ?>')"><img - src="/themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" - width="17" height="17" border="0" title="<?php echo gettext("delete Suppress List"); ?>"></a></td> - </tr> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> + <thead> + <tr> + <th width="30%" class="listhdrr"><?php echo gettext("Suppress List Name"); ?></th> + <th width="60%" class="listhdr"><?php echo gettext("Description"); ?></th> + <th width="10%" class="list"></th> + </tr> + </thead> + <tbody> + <?php $i = 0; foreach ($a_suppress as $list): ?> + <?php + if (suricata_suppresslist_used($list['name'])) { + $icon = "<img src=\"/themes/{$g['theme']}/images/icons/icon_frmfld_pwd.png\" " . + "width=\"16\" height=\"16\" border=\"0\" title=\"" . gettext("List is in use by an instance") . "\"/>"; + } + else + $icon = ""; + ?> + <tr> + <td height="20px" class="listlr" + ondblclick="document.location='suricata_suppress_edit.php?id=<?=$i;?>';"> + <?=htmlspecialchars($list['name']);?> <?=$icon;?></td> + <td height="20px" class="listbg" + ondblclick="document.location='suricata_suppress_edit.php?id=<?=$i;?>';"> + <font color="#FFFFFF"> <?=htmlspecialchars($list['descr']);?> </font> + </td> + <td height="20px" valign="middle" nowrap class="list"> + <table border="0" cellspacing="0" cellpadding="1"> + <tr> + <td valign="middle"><a + href="suricata_suppress_edit.php?id=<?=$i;?>"><img + src="/themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" + width="17" height="17" border="0" title="<?php echo gettext("edit Suppress List"); ?>"></a></td> + <?php if (suricata_suppresslist_used($list['name'])) : ?> + <td><img src="/themes/<?=$g['theme'];?>/images/icons/icon_x_d.gif" + width="17" height="17" border="0" title="<?php echo gettext("Assigned Suppress Lists cannot be deleted");?>"/></td> + <td><a href="/suricata/suricata_interfaces_edit.php?id=<?=suricata_find_suppresslist_interface($list['name']);?>"> + <img src="/themes/<?=$g['theme'];?>/images/icons/icon_right.gif" + width="17" height="17" border="0" title="<?php echo gettext("Goto first instance associated with this Suppress List");?>"/></a> + </td> + <?php else : ?> + <td><a href="/suricata/suricata_suppress.php?act=del&id=<?=$i;?>" + onclick="return confirm('<?php echo gettext("Do you really want to delete this Suppress List?"); ?>')"><img + src="/themes/<?=$g['theme'];?>/images/icons/icon_x.gif" + width="17" height="17" border="0" title="<?php echo gettext("delete Suppress List"); ?>"></a></td> + <td> </td> + <?php endif; ?> + </tr> + </table> + </td> + </tr> + <?php $i++; endforeach; ?> + <tr> + <td class="list" colspan="2"></td> + <td class="list"> + <table border="0" cellspacing="0" cellpadding="1"> + <tr> + <td valign="middle" width="17"> </td> + <td valign="middle"><a + href="suricata_suppress_edit.php?id=<?php echo $id_gen;?> "><img + src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" + width="17" height="17" border="0" title="<?php echo gettext("add a new list"); ?>"></a></td> + </tr> + </table> + </td> + </tr> + </tbody> </table> - </td> -</tr> -<?php $i++; endforeach; ?> -<tr> - <td class="list" colspan="2"></td> - <td class="list"> - <table border="0" cellspacing="0" cellpadding="1"> - <tr> - <td valign="middle" width="17"> </td> - <td valign="middle"><a - href="suricata_suppress_edit.php?id=<?php echo $id_gen;?> "><img - src="/themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" - width="17" height="17" border="0" title="<?php echo gettext("add a new list"); ?>"></a></td> - </tr> - </table> - </td> -</tr> -</table> </div> </td></tr> <tr> @@ -163,7 +219,10 @@ if ($input_errors) { <p><?php echo gettext("Here you can create event filtering and " . "suppression for your Suricata package rules."); ?><br/><br/> <?php echo gettext("Please note that you must restart a running Interface so that changes can " . - "take effect."); ?></p></span></td> + "take effect."); ?><br/><br/> + <?php echo gettext("You cannot delete a Suppress List that is currently assigned to a Suricata interface (instance).") . "<br/>" . + gettext("You must first unassign the Suppress List on the Interface Edit tab."); ?> + </p></span></td> </tr> </table> </form> diff --git a/config/suricata/suricata_suppress_edit.php b/config/suricata/suricata_suppress_edit.php index c2c23f10..a46e9e99 100644 --- a/config/suricata/suricata_suppress_edit.php +++ b/config/suricata/suricata_suppress_edit.php @@ -1,29 +1,41 @@ <?php /* * suricata_suppress_edit.php - Copyright (C) 2014 Bill Meeks - 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. + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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"); @@ -40,9 +52,10 @@ if (!is_array($config['installedpackages']['suricata']['suppress']['item'])) $config['installedpackages']['suricata']['suppress']['item'] = array(); $a_suppress = &$config['installedpackages']['suricata']['suppress']['item']; -$id = $_GET['id']; -if (isset($_POST['id'])) +if (isset($_POST['id']) && is_numericint($_POST['id'])) $id = $_POST['id']; +elseif (isset($_GET['id']) && is_numericint($_GET['id'])) + $id = htmlspecialchars($_GET['id']); /* returns true if $name is a valid name for a whitelist file name or ip */ function is_validwhitelistname($name) { @@ -69,7 +82,7 @@ if (isset($id) && $a_suppress[$id]) { $pconfig['uuid'] = uniqid(); } -if ($_POST['submit']) { +if ($_POST['save']) { unset($input_errors); $pconfig = $_POST; @@ -139,12 +152,16 @@ if ($savemsg) <tr><td> <?php $tab_array = array(); - $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Suricata Interfaces"), false, "/suricata/suricata_interfaces.php"); $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); $tab_array[] = array(gettext("Update Rules"), false, "/suricata/suricata_download_updates.php"); - $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$instanceid}"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php"); + $tab_array[] = array(gettext("Blocked"), false, "/suricata/suricata_blocked.php"); + $tab_array[] = array(gettext("Pass Lists"), false, "/suricata/suricata_passlist.php"); $tab_array[] = array(gettext("Suppress"), true, "/suricata/suricata_suppress.php"); - display_top_tabs($tab_array); + $tab_array[] = array(gettext("Logs Browser"), false, "/suricata/suricata_logs_browser.php"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + display_top_tabs($tab_array, true); ?> </td></tr> <tr><td><div id="mainarea"> @@ -193,7 +210,7 @@ if ($savemsg) </td> </tr> <tr> - <td colspan="2"><input id="submit" name="submit" type="submit" + <td colspan="2"><input id="save" name="save" type="submit" class="formbtn" value="Save" /> <input id="cancelbutton" name="cancelbutton" type="button" class="formbtn" value="Cancel" onclick="history.back();"/> <?php if (isset($id) && $a_suppress[$id]): ?> diff --git a/config/suricata/suricata_uninstall.php b/config/suricata/suricata_uninstall.php index 071a89a4..2317578e 100644 --- a/config/suricata/suricata_uninstall.php +++ b/config/suricata/suricata_uninstall.php @@ -1,30 +1,41 @@ <?php /* - suricata_uninstall.php - - Copyright (C) 2014 Bill Meeks - 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. + * suricata_uninstall.php + * + * Significant portions of this code are based on original work done + * for the Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * All rights reserved. + * + * Adapted for Suricata by: + * Copyright (C) 2014 Bill Meeks + * 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("/usr/local/pkg/suricata/suricata.inc"); @@ -35,6 +46,7 @@ $suricatadir = SURICATADIR; $suricatalogdir = SURICATALOGDIR; $rcdir = RCFILEPREFIX; $suricata_rules_upd_log = RULES_UPD_LOGFILE; +$suri_pf_table = SURICATA_PF_TABLE; log_error(gettext("[Suricata] Suricata package uninstall in progress...")); @@ -64,6 +76,7 @@ mwexec('/usr/sbin/pw userdel suricata; /usr/sbin/pw groupdel suricata', true); /* Remove the Suricata cron jobs. */ install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/www/suricata/suricata_check_for_rule_updates.php", false); install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_check_cron_misc.inc", false); +install_cron_job("pfctl -t {$suri_pf_table} -T expire" , false); /* See if we are to keep Suricata log files on uninstall */ if ($config['installedpackages']['suricata']['config'][0]['clearlogs'] == 'on') { @@ -73,8 +86,33 @@ if ($config['installedpackages']['suricata']['config'][0]['clearlogs'] == 'on') } /* Remove the Suricata GUI app directories */ -@unlink("/usr/local/pkg/suricata"); -@unlink("/usr/local/www/suricata"); +mwexec("/bin/rm -rf /usr/local/pkg/suricata"); +mwexec("/bin/rm -rf /usr/local/www/suricata"); + +/* Remove our associated Dashboard widget config and files. */ +/* If "save settings" is enabled, then save old widget */ +/* container settings so we can restore them later. */ +$widgets = $config['widgets']['sequence']; +if (!empty($widgets)) { + $widgetlist = explode(",", $widgets); + foreach ($widgetlist as $key => $widget) { + if (strstr($widget, "suricata_alerts-container")) { + if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] == 'on') { + $config['installedpackages']['suricata']['config'][0]['dashboard_widget'] = $widget; + if ($config['widgets']['widget_suricata_display_lines']) { + $config['installedpackages']['suricata']['config'][0]['dashboard_widget_rows'] = $config['widgets']['widget_suricata_display_lines']; + unset($config['widgets']['widget_suricata_display_lines']); + } + } + unset($widgetlist[$key]); + } + } + $config['widgets']['sequence'] = implode(",", $widgetlist); + write_config(); +} +@unlink("/usr/local/www/widgets/include/widget-suricata.inc"); +@unlink("/usr/local/www/widgets/widgets/suricata_alerts.widget.php"); +@unlink("/usr/local/www/widgets/javascript/suricata_alerts.js"); /* Keep this as a last step */ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] != 'on') { @@ -83,7 +121,6 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] ! unset($config['installedpackages']['suricatasync']); @unlink("{$suricata_rules_upd_log}"); mwexec("/bin/rm -rf {$suricatalogdir}"); - @unlink(SURICATALOGDIR); log_error(gettext("[Suricata] The package has been removed from this system...")); } diff --git a/config/suricata/suricata_yaml_template.inc b/config/suricata/suricata_yaml_template.inc index e62c48eb..c20ca8db 100644 --- a/config/suricata/suricata_yaml_template.inc +++ b/config/suricata/suricata_yaml_template.inc @@ -29,6 +29,14 @@ default-log-dir: {$suricatalogdir}suricata_{$if_real}{$suricata_uuid} # Configure the type of alert (and other) logging. outputs: + # alert_pf blocking plugin + - alert-pf: + enabled: {$suri_blockoffenders} + kill-state: {$suri_killstates} + pass-list: {$suri_passlist} + block-ip: {$suri_blockip} + pf-table: {$suri_pf_table} + # a line based alerts log similar to Snort's fast.log - fast: enabled: yes @@ -40,9 +48,8 @@ outputs: - unified2-alert: enabled: {$barnyard2_enabled} filename: unified2.alert - limit: 32mb - # Sensor ID field of unified2 alerts. - sensor-id: 0 + limit: {$unified2_log_limit} + sensor-id: {$unified2_sensor_id} - http-log: enabled: {$http_log_enabled} @@ -100,7 +107,7 @@ outputs: force-md5: {$json_log_md5} # Magic file. The extension .mgc is added to the value here. -magic-file: {$suricatacfgdir}/magic +magic-file: /usr/share/misc/magic # Specify a threshold config file threshold-file: {$suricatacfgdir}/threshold.config @@ -110,7 +117,7 @@ detect-engine: - sgh-mpm-context: {$sgh_mpm_ctx} - inspection-recursion-limit: {$inspection_recursion_limit} - rule-reload: true - - delayed-detect: yes + - delayed-detect: {$delayed_detect} # Suricata is multi-threaded. Here the threading can be influenced. threading: diff --git a/config/suricata/widget-suricata.inc b/config/suricata/widget-suricata.inc new file mode 100644 index 00000000..48424588 --- /dev/null +++ b/config/suricata/widget-suricata.inc @@ -0,0 +1,8 @@ +<?php +require_once("config.inc"); + +//set variable for custom title +$suricata_alerts_title = "Suricata Alerts"; +$suricata_alerts_title_link = "suricata/suricata_alerts.php"; + +?> |