diff options
Diffstat (limited to 'config')
62 files changed, 2987 insertions, 732 deletions
diff --git a/config/ntopng/ntopng.xml b/config/ntopng/ntopng.xml index 5428d205..45b68bdc 100644 --- a/config/ntopng/ntopng.xml +++ b/config/ntopng/ntopng.xml @@ -182,8 +182,8 @@ $redis_path = "/usr/pbi/ntopng-" . php_uname("m") . "/bin"; } - $start = "ldconfig -m /usr/pbi/ntopng-i386/lib\n"; - $start .= "\t{$redis_path}/redis-server &\n"; + $start = "ldconfig -m /usr/pbi/ntopng-" . php_uname("m") . "/lib\n"; + $start .= "\t{$redis_path}/redis-server --dir /var/db/ntopng/ --dbfilename ntopng.rdb &\n"; // TODO: // Add support for --data-dir /somewhere, --httpdocs-dir /somewhereelse, // --dump-timeline (on/off) --http-port, --https-port @@ -207,6 +207,7 @@ $ntopng_config['password'] = "admin"; $password = md5($ntopng_config['password']); mwexec_bg("{$redis_path}/redis-cli SET user.admin.password " . escapeshellarg($password)); + mwexec_bg("{$redis_path}/redis-cli save"); conf_mount_ro(); config_unlock(); } diff --git a/config/snort/snort.inc b/config/snort/snort.inc index 5c113d27..ed1e64be 100755 --- a/config/snort/snort.inc +++ b/config/snort/snort.inc @@ -36,9 +36,8 @@ require_once("config.inc"); require_once("functions.inc"); require_once("service-utils.inc"); require_once("pkg-utils.inc"); - -// Needed on 2.0 because of filter_get_vpns_list() require_once("filter.inc"); +require("/usr/local/pkg/snort/snort_defs.inc"); // Snort GUI needs some extra PHP memory space to manipulate large rules arrays ini_set("memory_limit", "256M"); @@ -48,47 +47,12 @@ global $g, $config, $rebuild_rules, $pfSense_snort_version; // Grab the Snort binary version programmatically, but if that fails use a safe default $snortver = array(); -exec("/usr/local/bin/snort -V 2>&1 |/usr/bin/grep Version | /usr/bin/cut -c20-26", $snortver); - -/* Used to indicate latest version of this include file has been loaded */ -$pfSense_snort_version = "3.1.5"; +$snortbindir = SNORT_PBI_BINDIR; +exec("{$snortbindir}snort -V 2>&1 |/usr/bin/grep Version | /usr/bin/cut -c20-26", $snortver); /* get installed package version for display */ $snort_package_version = "Snort {$config['installedpackages']['package'][get_pkg_id("snort")]['version']}"; -// Define SNORTDIR and SNORTLIBDIR constants according to pfSense version -$pfs_version=substr(trim(file_get_contents("/etc/version")),0,3); -if ($pfs_version >= 2.2) { - define("SNORTDIR", "/usr/pbi/snort-" . php_uname("m") . "/local/etc/snort"); - define("SNORTLIBDIR", "/usr/pbi/snort-" . php_uname("m") . "/local/lib/snort"); -} -else { - define("SNORTDIR", "/usr/pbi/snort-" . php_uname("m") . "/etc/snort"); - define("SNORTLIBDIR", "/usr/pbi/snort-" . php_uname("m") . "/lib/snort"); -} - -/* Define some useful constants for Snort */ -/* Be sure to include trailing slash on the URL defines */ -define("SNORTLOGDIR", "{$g['varlog_path']}/snort"); -define("SNORT_BIN_VERSION", "2.9.6.2"); -define("SNORT_ET_DNLD_FILENAME", "emerging.rules.tar.gz"); -define("SNORT_ETPRO_DNLD_FILENAME", "etpro.rules.tar.gz"); -define("SNORT_GPLV2_DNLD_FILENAME", "community-rules.tar.gz"); -define("SNORT_ENFORCING_RULES_FILENAME", "snort.rules"); -define("SNORT_RULES_UPD_LOGFILE", SNORTLOGDIR . "/snort_rules_update.log"); -define("SNORT_IPREP_PATH", "{$g['vardb_path']}/snort/iprep/"); -define('SNORT_SID_MODS_PATH', "{$g['vardb_path']}/snort/sidmods/"); -if (!defined("FLOWBITS_FILENAME")) - define("FLOWBITS_FILENAME", "flowbit-required.rules"); -if (!defined("VRT_FILE_PREFIX")) - define("VRT_FILE_PREFIX", "snort_"); -if (!defined("GPL_FILE_PREFIX")) - define("GPL_FILE_PREFIX", "GPLv2_"); -if (!defined("ET_OPEN_FILE_PREFIX")) - define("ET_OPEN_FILE_PREFIX", "emerging-"); -if (!defined("ET_PRO_FILE_PREFIX")) - define("ET_PRO_FILE_PREFIX", "etpro-"); - /* Rebuild Rules Flag -- if "true", rebuild enforcing rules and flowbit-rules files */ $rebuild_rules = false; @@ -599,13 +563,14 @@ function snort_barnyard_start($snortcfg, $if_real, $background=FALSE) { $snortdir = SNORTDIR; $snortlogdir = SNORTLOGDIR; $snort_uuid = $snortcfg['uuid']; + $snortbindir = SNORT_PBI_BINDIR; if ($snortcfg['barnyard_enable'] == 'on' && !isvalidpid("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid")) { log_error("[Snort] Barnyard2 START for " . convert_real_interface_to_friendly_descr($if_real) . "({$if_real})..."); if ($background) - mwexec_bg("/usr/local/bin/barnyard2 -r {$snort_uuid} -f \"snort_{$snort_uuid}_{$if_real}.u2\" --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d {$snortlogdir}/snort_{$if_real}{$snort_uuid} -D -q"); + mwexec_bg("{$snortbindir}barnyard2 -r {$snort_uuid} -f \"snort_{$snort_uuid}_{$if_real}.u2\" --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d {$snortlogdir}/snort_{$if_real}{$snort_uuid} -D -q"); else - mwexec("/usr/local/bin/barnyard2 -r {$snort_uuid} -f \"snort_{$snort_uuid}_{$if_real}.u2\" --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d {$snortlogdir}/snort_{$if_real}{$snort_uuid} -D -q"); + mwexec("{$snortbindir}barnyard2 -r {$snort_uuid} -f \"snort_{$snort_uuid}_{$if_real}.u2\" --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d {$snortlogdir}/snort_{$if_real}{$snort_uuid} -D -q"); } } @@ -615,13 +580,19 @@ function snort_start($snortcfg, $if_real, $background=FALSE) { $snortdir = SNORTDIR; $snortlogdir = SNORTLOGDIR; $snort_uuid = $snortcfg['uuid']; + $snortbindir = SNORT_PBI_BINDIR; + + if ($config['installedpackages']['snortglobal']['verbose_logging'] == "on") + $quiet = ""; + else + $quiet = "-q --suppress-config-log"; if ($snortcfg['enable'] == 'on' && !isvalidpid("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid")) { log_error("[Snort] Snort START for " . convert_real_interface_to_friendly_descr($if_real) . "({$if_real})..."); if ($background) - mwexec_bg("/usr/local/bin/snort -R {$snort_uuid} -D -q -l {$snortlogdir}/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}"); + mwexec_bg("{$snortbindir}snort -R {$snort_uuid} -D {$quiet} -l {$snortlogdir}/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}"); else - mwexec("/usr/local/bin/snort -R {$snort_uuid} -D -q -l {$snortlogdir}/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}"); + mwexec("{$snortbindir}snort -R {$snort_uuid} -D {$quiet} -l {$snortlogdir}/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real}"); snort_barnyard_start($snortcfg, $if_real, $background); } } @@ -2735,11 +2706,12 @@ function snort_load_sid_mods($sids) { if (preg_match('/(\d+)\s*:\s*(\d+)/', $v, $match)) { if (!is_array($result[$match[1]])) $result[$match[1]] = array(); + if (!is_array($result[$match[1]][$match[2]])) + $result[$match[1]][$match[2]] = array(); $result[$match[1]][$match[2]] = "{$match[1]}:{$match[2]}"; } } unset($tmp); - return $result; } @@ -2804,6 +2776,7 @@ function snort_create_rc() { $snortdir = SNORTDIR; $snortlogdir = SNORTLOGDIR; + $snortbindir = SNORT_PBI_BINDIR; $rcdir = RCFILEPREFIX; $snortconf = $config['installedpackages']['snortglobal']['rule']; @@ -2814,6 +2787,12 @@ function snort_create_rc() { return; } + // See whether or not to enable detailed startup logging + if ($config['installedpackages']['snortglobal']['verbose_logging'] == "on") + $quiet = ""; + else + $quiet = "-q --suppress-config-log"; + // At least one interface is configured, so OK $start_snort_iface_start = array(); $start_snort_iface_stop = array(); @@ -2837,7 +2816,7 @@ function snort_create_rc() { fi if [ -z \$pid ]; then /usr/bin/logger -p daemon.info -i -t SnortStartup "Barnyard2 START for {$value['descr']}({$snort_uuid}_{$if_real})..." - /usr/local/bin/barnyard2 -r {$snort_uuid} -f snort_{$snort_uuid}_{$if_real}.u2 --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d {$snortlogdir}/snort_{$if_real}{$snort_uuid} -D -q > /dev/null 2>&1 + {$snortbindir}barnyard2 -r {$snort_uuid} -f snort_{$snort_uuid}_{$if_real}.u2 --pid-path {$g['varrun_path']} --nolock-pidfile -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/barnyard2.conf -d {$snortlogdir}/snort_{$if_real}{$snort_uuid} -D -q > /dev/null 2>&1 fi EOE; $stop_barnyard2 = <<<EOE @@ -2888,7 +2867,7 @@ EOE; if [ -z \$pid ]; then /usr/bin/logger -p daemon.info -i -t SnortStartup "Snort START for {$value['descr']}({$snort_uuid}_{$if_real})..." - /usr/local/bin/snort -R {$snort_uuid} -D -q -l {$snortlogdir}/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real} > /dev/null 2>&1 + {$snortbindir}snort -R {$snort_uuid} -D {$quiet} -l {$snortlogdir}/snort_{$if_real}{$snort_uuid} --pid-path {$g['varrun_path']} --nolock-pidfile -G {$snort_uuid} -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf -i {$if_real} > /dev/null 2>&1 fi {$start_barnyard2} @@ -3106,7 +3085,7 @@ function snort_deinstall() { global $config, $g; $snortdir = SNORTDIR; - $snortlibdir = SNORTLIBDIR; + $snortlibdir = "/usr/pbi/snort-" . php_uname("m") . "/lib"; $snortlogdir = SNORTLOGDIR; $rcdir = RCFILEPREFIX; $snort_rules_upd_log = SNORT_RULES_UPD_LOGFILE; @@ -3205,6 +3184,8 @@ function snort_deinstall() { rmdir_recursive("/usr/local/www/snort"); rmdir_recursive("/usr/local/etc/snort"); rmdir_recursive("/usr/local/lib/snort"); + rmdir_recursive("/usr/local/lib/snort_dynamicengine"); + rmdir_recursive("/usr/local/lib/snort_dynamicpreprocessor"); } /* Keep this as a last step */ @@ -3518,10 +3499,9 @@ function snort_filter_preproc_rules($snortcfg, &$active_rules, $persist_log = fa * Format of array is: * * "rule_option" => "dependent_preprocessor" * * * - * Last Update: 04/05/2013 * + * Last Update: 10/30/2014 * * * - * Added: http_inspect content modifiers and * - * various "service" metadata values. * + * Added: appid: detection option * * * ***************************************************/ $rule_opts_preprocs = array("ssl_version:" => "ssl_preproc","ssl_state:" => "ssl_preproc", @@ -3544,7 +3524,8 @@ function snort_filter_preproc_rules($snortcfg, &$active_rules, $persist_log = fa "uricontent:" => "http_inspect", "urilen:" => "http_inspect", "http_encode;" => "http_inspect", "service http" => "http_inspect", "service imap" => "imap_preproc", "service pop2" => "pop_preproc", - "service pop3" => "pop_preproc", "service smtp" => "smtp_preprocessor"); + "service pop3" => "pop_preproc", "service smtp" => "smtp_preprocessor", + "appid:" => "appid_preproc" ); /*************************************************** * Iterate the enabled rules, and check for rule * @@ -3650,7 +3631,7 @@ function snort_generate_conf($snortcfg) { return; $snortdir = SNORTDIR; - $snortlibdir = SNORTLIBDIR; + $snortlibdir = SNORT_PBI_BASEDIR . "lib"; $snortlogdir = SNORTLOGDIR; $flowbit_rules_file = FLOWBITS_FILENAME; $snort_enforcing_rules_file = SNORT_ENFORCING_RULES_FILENAME; diff --git a/config/snort/snort.priv.inc b/config/snort/snort.priv.inc index 1af0e783..928ecb52 100644 --- a/config/snort/snort.priv.inc +++ b/config/snort/snort.priv.inc @@ -11,6 +11,7 @@ $priv_list['page-services-snort']['match'][] = "snort/snort_barnyard.php*"; $priv_list['page-services-snort']['match'][] = "snort/snort_blocked.php*"; $priv_list['page-services-snort']['match'][] = "snort/snort_check_for_rule_updates.php*"; $priv_list['page-services-snort']['match'][] = "snort/snort_define_servers.php*"; +$priv_list['page-services-snort']['match'][] = "snort/snort_defs.inc*"; $priv_list['page-services-snort']['match'][] = "snort/snort_download_rules.php*"; $priv_list['page-services-snort']['match'][] = "snort/snort_download_updates.php*"; $priv_list['page-services-snort']['match'][] = "snort/snort_edit_hat_data.php*"; diff --git a/config/snort/snort.xml b/config/snort/snort.xml index 91d42532..fd0a8d41 100755 --- a/config/snort/snort.xml +++ b/config/snort/snort.xml @@ -46,8 +46,8 @@ <requirements>None</requirements> <faq>Currently there are no FAQ items provided.</faq> <name>Snort</name> - <version>2.9.6.2</version> - <title>Services:2.9.6.2 pkg v3.1.5</title> + <version>2.9.7.0</version> + <title>Services:2.9.7.0 pkg v3.2.1</title> <include_file>/usr/local/pkg/snort/snort.inc</include_file> <menu> <name>Snort</name> @@ -129,6 +129,11 @@ <item>https://packages.pfsense.org/packages/config/snort/snort_check_for_rule_updates.php</item> </additional_files_needed> <additional_files_needed> + <prefix>/usr/local/pkg/snort/</prefix> + <chmod>077</chmod> + <item>https://packages.pfsense.org/packages/config/snort/snort_defs.inc</item> + </additional_files_needed> + <additional_files_needed> <prefix>/usr/local/www/snort/</prefix> <chmod>077</chmod> <item>https://packages.pfsense.org/packages/config/snort/snort_interfaces.php</item> diff --git a/config/snort/snort_check_cron_misc.inc b/config/snort/snort_check_cron_misc.inc index b39d8d1c..a2688b58 100644 --- a/config/snort/snort_check_cron_misc.inc +++ b/config/snort/snort_check_cron_misc.inc @@ -75,16 +75,21 @@ function snort_check_dir_size_limit($snortloglimitsize) { @file_put_contents("{$snort_log_dir}/alert", ""); } - // Cleanup any rotated perfmon stats logs + // Cleanup any perfmon stats logs $files = array(); $list = glob("{$snort_log_dir}/*"); foreach ($list as $file) { - if (preg_match('/(^\d{4}-\d{2}-\d{2}[\.]?[\d+]?)/', basename($file), $matches)) + if (preg_match('/(^\d{4}-\d{2}-\d{2}[\.\d+]*)/', basename($file), $matches)) $files[] = $snort_log_dir . "/" . $matches[1]; } foreach ($files as $file) unlink_if_exists($file); + // Cleanup any AppID stats logs + $files = glob("{$snort_log_dir}/appid-stats.log.*"); + foreach ($files as $file) + unlink_if_exists($file); + // This is needed if snort is run as snort user mwexec('/bin/chmod 660 {$snort_log_dir}/*', true); @@ -214,7 +219,7 @@ if ($config['installedpackages']['snortglobal']['enable_log_mgmt'] == 'on') { $files = array(); $list = glob("{$snort_log_dir}/*"); foreach ($list as $file) { - if (preg_match('/(^\d{4}-\d{2}-\d{2}[\.]?[\d+]?)/', basename($file), $matches)) + if (preg_match('/(^\d{4}-\d{2}-\d{2}[\.\d+]*)/', basename($file), $matches)) $files[] = $snort_log_dir . "/" . $matches[1]; } $prune_count = 0; @@ -228,6 +233,22 @@ if ($config['installedpackages']['snortglobal']['enable_log_mgmt'] == 'on') { if ($prune_count > 0) log_error(gettext("[Snort] perfmon stats logs cleanup job removed {$prune_count} file(s) from {$snort_log_dir}/...")); } + + // Prune any aged-out AppID stats logs if any exist + if ($value['appid_stats_log_retention'] > 0) { + $now = time(); + $files = glob("{$snort_log_dir}/app-stats.log.*"); + $prune_count = 0; + foreach ($files as $f) { + if (($now - filemtime($f)) > ($value['appid_stats_log_retention'] * 3600)) { + $prune_count++; + unlink_if_exists($f); + } + } + unset($files); + if ($prune_count > 0) + log_error(gettext("[Snort] AppID stats logs cleanup job removed {$prune_count} file(s) from {$snort_log_dir}/...")); + } } } diff --git a/config/snort/snort_check_for_rule_updates.php b/config/snort/snort_check_for_rule_updates.php index edf99dc8..3106cb7b 100755 --- a/config/snort/snort_check_for_rule_updates.php +++ b/config/snort/snort_check_for_rule_updates.php @@ -32,46 +32,16 @@ require_once("functions.inc"); require_once("service-utils.inc"); -require_once "/usr/local/pkg/snort/snort.inc"; +require_once("/usr/local/pkg/snort/snort.inc"); +require("/usr/local/pkg/snort/snort_defs.inc"); global $g, $config, $pkg_interface, $snort_gui_include, $rebuild_rules; -if (!defined("VRT_DNLD_URL")) - define("VRT_DNLD_URL", "https://www.snort.org/rules/"); -if (!defined("SNORT_BIN_VERSION")) - define("SNORT_BIN_VERSION", "2.9.6.2"); -if (!defined("ET_VERSION")) - define("ET_VERSION", "2.9.0"); -if (!defined("ET_BASE_DNLD_URL")) - define("ET_BASE_DNLD_URL", "http://rules.emergingthreats.net/"); -if (!defined("ETPRO_BASE_DNLD_URL")) - define("ETPRO_BASE_DNLD_URL", "https://rules.emergingthreatspro.com/"); -if (!defined("SNORT_ET_DNLD_FILENAME")) - define("SNORT_ET_DNLD_FILENAME", "emerging.rules.tar.gz"); -if (!defined("SNORT_ETPRO_DNLD_FILENAME")) - define("SNORT_ETPRO_DNLD_FILENAME", "etpro.rules.tar.gz"); -if (!defined("SNORT_GPLV2_DNLD_FILENAME")) - define("SNORT_GPLV2_DNLD_FILENAME", "community-rules.tar.gz"); -if (!defined("GPLV2_DNLD_URL")) - define("GPLV2_DNLD_URL", "https://s3.amazonaws.com/snort-org/www/rules/community/"); -if (!defined("SNORT_RULES_UPD_LOGFILE")) - define("SNORT_RULES_UPD_LOGFILE", SNORTLOGDIR . "/snort_rules_update.log"); -if (!defined("VRT_FILE_PREFIX")) - define("VRT_FILE_PREFIX", "snort_"); -if (!defined("GPL_FILE_PREFIX")) - define("GPL_FILE_PREFIX", "GPLv2_"); -if (!defined("ET_OPEN_FILE_PREFIX")) - define("ET_OPEN_FILE_PREFIX", "emerging-"); -if (!defined("ET_PRO_FILE_PREFIX")) - define("ET_PRO_FILE_PREFIX", "etpro-"); -if (!defined("SNORT_IPREP_PATH")) - define("SNORT_IPREP_PATH", "{$g['vardb_path']}/snort/iprep/"); - $snortdir = SNORTDIR; -$snortlibdir = SNORTLIBDIR; +$snortlibdir = "/usr/pbi/snort-" . php_uname("m") . "/lib"; $snortlogdir = SNORTLOGDIR; $snortiprepdir = SNORT_IPREP_PATH; -$snort_rules_upd_log = SNORT_RULES_UPD_LOGFILE; +$snortbindir = SNORT_PBI_BINDIR; $mounted_rw = FALSE; /* Save the state of $pkg_interface so we can restore it */ @@ -89,6 +59,7 @@ $emergingthreats = $config['installedpackages']['snortglobal']['emergingthreats' $etpro = $config['installedpackages']['snortglobal']['emergingthreats_pro'] == 'on' ? 'on' : 'off'; $snortcommunityrules = $config['installedpackages']['snortglobal']['snortcommunityrules'] == 'on' ? 'on' : 'off'; $vrt_enabled = $config['installedpackages']['snortglobal']['snortdownload'] == 'on' ? 'on' : 'off'; +$openappid_detectors = $config['installedpackages']['snortglobal']['openappid_detectors'] == 'on' ? 'on' : 'off'; /* Working directory for downloaded rules tarballs and extraction */ $tmpfname = "{$g['tmp_path']}/snort_rules_up"; @@ -97,7 +68,7 @@ $tmpfname = "{$g['tmp_path']}/snort_rules_up"; /* the proper Snort VRT rules tarball and md5 filenames. Fallback to a */ /* default in the event we fail. */ $snortver = array(); -exec("/usr/local/bin/snort -V 2>&1 |/usr/bin/grep Version | /usr/bin/cut -c20-26", $snortver); +exec("{$snortbindir}snort -V 2>&1 |/usr/bin/grep Version | /usr/bin/cut -c20-26", $snortver); // Save the version with decimal delimiters for use in extracting the rules $snort_version = $snortver[0]; if (empty($snort_version)) @@ -143,6 +114,11 @@ $snort_community_rules_filename = SNORT_GPLV2_DNLD_FILENAME; $snort_community_rules_filename_md5 = SNORT_GPLV2_DNLD_FILENAME . ".md5"; $snort_community_rules_url = GPLV2_DNLD_URL; +/* Snort OpenAppID detectors filename and URL */ +$snort_openappid_filename = SNORT_OPENAPPID_DNLD_FILENAME; +$snort_openappid_filename_md5 = SNORT_OPENAPPID_DNLD_FILENAME . ".md5"; +$snort_openappid_url = SNORT_OPENAPPID_DNLD_URL; + function snort_download_file_url($url, $file_out) { /************************************************/ @@ -293,21 +269,21 @@ function snort_check_rule_md5($file_url, $file_dst, $desc = "") { /* error occurred. */ /**********************************************************/ - global $pkg_interface, $snort_rules_upd_log, $last_curl_error, $update_errors; + global $pkg_interface, $last_curl_error, $update_errors; $snortdir = SNORTDIR; $filename_md5 = basename($file_dst); if ($pkg_interface <> "console") update_status(gettext("Downloading {$desc} md5 file...")); - error_log(gettext("\tDownloading {$desc} md5 file {$filename_md5}...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tDownloading {$desc} md5 file {$filename_md5}...\n"), 3, SNORT_RULES_UPD_LOGFILE); $rc = snort_download_file_url($file_url, $file_dst); // See if download from URL was successful if ($rc === true) { if ($pkg_interface <> "console") update_status(gettext("Done downloading {$filename_md5}.")); - error_log("\tChecking {$desc} md5 file...\n", 3, $snort_rules_upd_log); + error_log("\tChecking {$desc} md5 file...\n", 3, SNORT_RULES_UPD_LOGFILE); // check md5 hash in new file against current file to see if new download is posted if (file_exists("{$snortdir}/{$filename_md5}")) { @@ -317,7 +293,7 @@ function snort_check_rule_md5($file_url, $file_dst, $desc = "") { if ($pkg_interface <> "console") update_status(gettext("{$desc} are up to date...")); log_error(gettext("[Snort] {$desc} are up to date...")); - error_log(gettext("\t{$desc} are up to date.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\t{$desc} are up to date.\n"), 3, SNORT_RULES_UPD_LOGFILE); return false; } else @@ -326,7 +302,7 @@ function snort_check_rule_md5($file_url, $file_dst, $desc = "") { return true; } else { - error_log(gettext("\t{$desc} md5 download failed.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\t{$desc} md5 download failed.\n"), 3, SNORT_RULES_UPD_LOGFILE); $snort_err_msg = gettext("Server returned error code {$rc}."); if ($pkg_interface <> "console") { update_status(gettext("{$desc} md5 error ... Server returned error code {$rc} ...")); @@ -334,9 +310,9 @@ function snort_check_rule_md5($file_url, $file_dst, $desc = "") { } log_error(gettext("[Snort] {$desc} md5 download failed...")); log_error(gettext("[Snort] Server returned error code {$rc}...")); - error_log(gettext("\t{$snort_err_msg}\n"), 3, $snort_rules_upd_log); - error_log(gettext("\tServer error message was: {$last_curl_error}\n"), 3, $snort_rules_upd_log); - error_log(gettext("\t{$desc} will not be updated.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\t{$snort_err_msg}\n"), 3, SNORT_RULES_UPD_LOGFILE); + error_log(gettext("\tServer error message was: {$last_curl_error}\n"), 3, SNORT_RULES_UPD_LOGFILE); + error_log(gettext("\t{$desc} will not be updated.\n"), 3, SNORT_RULES_UPD_LOGFILE); $update_errors = true; return false; } @@ -361,7 +337,7 @@ function snort_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { /* FALSE if download was not successful. */ /**********************************************************/ - global $pkg_interface, $snort_rules_upd_log, $last_curl_error, $update_errors; + global $pkg_interface, $last_curl_error, $update_errors; $snortdir = SNORTDIR; $filename = basename($file_dst); @@ -369,8 +345,8 @@ function snort_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { if ($pkg_interface <> "console") update_status(gettext("There is a new set of {$desc} posted. Downloading...")); log_error(gettext("[Snort] There is a new set of {$desc} posted. Downloading {$filename}...")); - error_log(gettext("\tThere is a new set of {$desc} posted.\n"), 3, $snort_rules_upd_log); - error_log(gettext("\tDownloading file '{$filename}'...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tThere is a new set of {$desc} posted.\n"), 3, SNORT_RULES_UPD_LOGFILE); + error_log(gettext("\tDownloading file '{$filename}'...\n"), 3, SNORT_RULES_UPD_LOGFILE); $rc = snort_download_file_url($file_url, $file_dst); // See if the download from the URL was successful @@ -378,7 +354,7 @@ function snort_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { if ($pkg_interface <> "console") update_status(gettext("Done downloading {$desc} file.")); log_error("[Snort] {$desc} file update downloaded successfully"); - error_log(gettext("\tDone downloading rules file.\n"),3, $snort_rules_upd_log); + error_log(gettext("\tDone downloading rules file.\n"),3, SNORT_RULES_UPD_LOGFILE); // Test integrity of the rules file. Turn off update if file has wrong md5 hash if ($file_md5 != trim(md5_file($file_dst))){ @@ -387,10 +363,10 @@ function snort_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { log_error(gettext("[Snort] {$desc} file download failed. Bad MD5 checksum...")); log_error(gettext("[Snort] Downloaded File MD5: " . md5_file($file_dst))); log_error(gettext("[Snort] Expected File MD5: {$file_md5}")); - error_log(gettext("\t{$desc} file download failed. Bad MD5 checksum.\n"), 3, $snort_rules_upd_log); - error_log(gettext("\tDownloaded {$desc} file MD5: " . md5_file($file_dst) . "\n"), 3, $snort_rules_upd_log); - error_log(gettext("\tExpected {$desc} file MD5: {$file_md5}\n"), 3, $snort_rules_upd_log); - error_log(gettext("\t{$desc} file download failed. {$desc} will not be updated.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\t{$desc} file download failed. Bad MD5 checksum.\n"), 3, SNORT_RULES_UPD_LOGFILE); + error_log(gettext("\tDownloaded {$desc} file MD5: " . md5_file($file_dst) . "\n"), 3, SNORT_RULES_UPD_LOGFILE); + error_log(gettext("\tExpected {$desc} file MD5: {$file_md5}\n"), 3, SNORT_RULES_UPD_LOGFILE); + error_log(gettext("\t{$desc} file download failed. {$desc} will not be updated.\n"), 3, SNORT_RULES_UPD_LOGFILE); $update_errors = true; return false; } @@ -400,9 +376,9 @@ function snort_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { if ($pkg_interface <> "console") update_output_window(gettext("{$desc} file download failed...")); log_error(gettext("[Snort] {$desc} file download failed... server returned error '{$rc}'...")); - error_log(gettext("\t{$desc} file download failed. Server returned error {$rc}.\n"), 3, $snort_rules_upd_log); - error_log(gettext("\tThe error text was: {$last_curl_error}\n"), 3, $snort_rules_upd_log); - error_log(gettext("\t{$desc} will not be updated.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\t{$desc} file download failed. Server returned error {$rc}.\n"), 3, SNORT_RULES_UPD_LOGFILE); + error_log(gettext("\tThe error text was: {$last_curl_error}\n"), 3, SNORT_RULES_UPD_LOGFILE); + error_log(gettext("\t{$desc} will not be updated.\n"), 3, SNORT_RULES_UPD_LOGFILE); $update_errors = true; return false; } @@ -422,18 +398,18 @@ safe_mkdir("{$snortdir}/rules"); safe_mkdir("{$snortdir}/signatures"); safe_mkdir("{$snortdir}/preproc_rules"); safe_mkdir("{$tmpfname}"); -safe_mkdir("{$snortlibdir}/dynamicrules"); +safe_mkdir("{$snortlibdir}/snort_dynamicrules"); safe_mkdir("{$snortlogdir}"); safe_mkdir("{$snortiprepdir}"); /* See if we need to automatically clear the Update Log based on 1024K size limit */ -if (file_exists($snort_rules_upd_log)) { - if (1048576 < filesize($snort_rules_upd_log)) - unlink_if_exists("{$snort_rules_upd_log}"); +if (file_exists(SNORT_RULES_UPD_LOGFILE)) { + if (1048576 < filesize(SNORT_RULES_UPD_LOGFILE)) + unlink_if_exists("{SNORT_RULES_UPD_LOGFILE}"); } /* Log start time for this rules update */ -error_log(gettext("Starting rules update... Time: " . date("Y-m-d H:i:s") . "\n"), 3, $snort_rules_upd_log); +error_log(gettext("Starting rules update... Time: " . date("Y-m-d H:i:s") . "\n"), 3, SNORT_RULES_UPD_LOGFILE); $last_curl_error = ""; $update_errors = false; @@ -449,9 +425,22 @@ if ($snortdownload == 'on') { $snortdownload = 'off'; } +/* Check for and download any new Snort OpenAppID detectors */ +if ($openappid_detectors == 'on') { + if (snort_check_rule_md5("{$snort_openappid_url}{$snort_openappid_filename}/md5", "{$tmpfname}/{$snort_openappid_filename_md5}", "Snort OpenAppID detectors")) { + $file_md5 = trim(file_get_contents("{$tmpfname}/{$snort_openappid_filename_md5}")); + file_put_contents("{$tmpfname}/{$snort_openappid_filename_md5}", $file_md5); + /* download snort-openappid file */ + if (!snort_fetch_new_rules("{$snort_openappid_url}{$snort_openappid_filename}", "{$tmpfname}/{$snort_openappid_filename}", $file_md5, "Snort OpenAppID detectors")) + $openappid_detectors = 'off'; + } + else + $openappid_detectors = 'off'; +} + /* Check for and download any new Snort GPLv2 Community Rules sigs */ if ($snortcommunityrules == 'on') { - if (snort_check_rule_md5("{$snort_community_rules_url}{$snort_community_rules_filename_md5}", "{$tmpfname}/{$snort_community_rules_filename_md5}", "Snort GPLv2 Community Rules")) { + if (snort_check_rule_md5("{$snort_community_rules_url}{$snort_community_rules_filename}/md5", "{$tmpfname}/{$snort_community_rules_filename_md5}", "Snort GPLv2 Community Rules")) { /* download Snort GPLv2 Community Rules file */ $file_md5 = trim(file_get_contents("{$tmpfname}/{$snort_community_rules_filename_md5}")); if (!snort_fetch_new_rules("{$snort_community_rules_url}{$snort_community_rules_filename}", "{$tmpfname}/{$snort_community_rules_filename}", $file_md5, "Snort GPLv2 Community Rules")) @@ -492,7 +481,7 @@ if ($snortdownload == 'on') { update_status(gettext("Extracting Snort VRT rules...")); update_output_window(gettext("Installing Sourcefire VRT rules...")); } - error_log(gettext("\tExtracting and installing Snort VRT rules...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tExtracting and installing Snort VRT rules...\n"), 3, SNORT_RULES_UPD_LOGFILE); /* extract snort.org rules and add VRT_FILE_PREFIX prefix to all snort.org files */ safe_mkdir("{$tmpfname}/snortrules"); exec("/usr/bin/tar xzf {$tmpfname}/{$snort_filename} -C {$tmpfname}/snortrules rules/"); @@ -507,7 +496,7 @@ if ($snortdownload == 'on') { $newfile = basename($file); @copy($file, "{$snortdir}/rules/{$newfile}"); } - exec("rm -r {$tmpfname}/snortrules"); + rmdir_recursive("{$tmpfname}/snortrules"); /* Extract the Snort preprocessor rules */ if ($pkg_interface <> "console") update_output_window(gettext("Extracting preprocessor rules files...")); @@ -517,22 +506,21 @@ if ($snortdownload == 'on') { $newfile = basename($file); @copy($file, "{$snortdir}/preproc_rules/{$newfile}"); } - exec("rm -r {$tmpfname}/preproc_rules"); + rmdir_recursive("{$tmpfname}/preproc_rules"); /* extract so rules */ if ($pkg_interface <> "console") { update_status(gettext("Extracting Snort VRT Shared Objects rules...")); update_output_window(gettext("Installing precompiled Shared Objects rules for {$freebsd_version_so}...")); } - exec("/bin/mkdir -p {$snortlibdir}/dynamicrules/"); - error_log(gettext("\tUsing Snort VRT precompiled SO rules for {$freebsd_version_so} ...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tUsing Snort VRT precompiled SO rules for {$freebsd_version_so} ...\n"), 3, SNORT_RULES_UPD_LOGFILE); $snort_arch = php_uname("m"); $nosorules = false; if ($snort_arch == 'i386'){ exec("/usr/bin/tar xzf {$tmpfname}/{$snort_filename} -C {$tmpfname} so_rules/precompiled/{$freebsd_version_so}/i386/{$snort_version}/"); - exec("/bin/cp {$tmpfname}/so_rules/precompiled/{$freebsd_version_so}/i386/{$snort_version}/*.so {$snortlibdir}/dynamicrules/"); + exec("/bin/cp {$tmpfname}/so_rules/precompiled/{$freebsd_version_so}/i386/{$snort_version}/*.so {$snortlibdir}/snort_dynamicrules/"); } elseif ($snort_arch == 'amd64') { exec("/usr/bin/tar xzf {$tmpfname}/{$snort_filename} -C {$tmpfname} so_rules/precompiled/{$freebsd_version_so}/x86-64/{$snort_version}/"); - exec("/bin/cp {$tmpfname}/so_rules/precompiled/{$freebsd_version_so}/x86-64/{$snort_version}/*.so {$snortlibdir}/dynamicrules/"); + exec("/bin/cp {$tmpfname}/so_rules/precompiled/{$freebsd_version_so}/x86-64/{$snort_version}/*.so {$snortlibdir}/snort_dynamicrules/"); } else $nosorules = true; rmdir_recursive("{$tmpfname}/so_rules/"); @@ -558,7 +546,7 @@ if ($snortdownload == 'on') { if (file_exists("{$tmpfname}/etc/{$file}")) @copy("{$tmpfname}/etc/{$file}", "{$tmpfname}/VRT_{$file}"); } - exec("rm -r {$tmpfname}/etc"); + rmdir_recursive("{$tmpfname}/etc"); if (file_exists("{$tmpfname}/{$snort_filename_md5}")) { if ($pkg_interface <> "console") update_status(gettext("Copying md5 signature to snort directory...")); @@ -568,7 +556,30 @@ if ($snortdownload == 'on') { update_status(gettext("Extraction of Snort VRT rules completed...")); update_output_window(gettext("Installation of Sourcefire VRT rules completed...")); } - error_log(gettext("\tInstallation of Snort VRT rules completed.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tInstallation of Snort VRT rules completed.\n"), 3, SNORT_RULES_UPD_LOGFILE); + } +} + +/* Untar Snort OpenAppID detectors file to SNORT_APPID_ODP_PATH */ +if ($openappid_detectors == 'on') { + // If we have a valid downloaded file, then first cleanup the old directory + if (file_exists("{$tmpfname}/{$snort_openappid_filename}")) { + $snort_openappid_path = SNORT_APPID_ODP_PATH; + rmdir_recursive("{$snort_openappid_path}odp"); + error_log(gettext("\tExtracting and installing Snort OpenAppID detectors...\n"), 3, SNORT_RULES_UPD_LOGFILE); + safe_mkdir(SNORT_APPID_ODP_PATH); + exec("/usr/bin/tar oxzf {$tmpfname}/{$snort_openappid_filename} -C {$snort_openappid_path}"); + if (file_exists("{$tmpfname}/{$snort_openappid_filename_md5}")) { + if ($pkg_interface <> "console") + update_status(gettext("Copying md5 signature to snort directory...")); + @copy("{$tmpfname}/{$snort_openappid_filename_md5}", "{$snortdir}/{$snort_openappid_filename_md5}"); + } + if ($pkg_interface <> "console") { + update_status(gettext("Extraction of Snort OpenAppID detectors completed...")); + update_output_window(gettext("Installation of Snort OpenAppID detectors completed...")); + } + unlink_if_exists("{$tmpfname}/{$snort_openappid_filename}"); + error_log(gettext("\tInstallation of Snort OpenAppID detectors completed.\n"), 3, SNORT_RULES_UPD_LOGFILE); } } @@ -580,7 +591,7 @@ if ($snortcommunityrules == 'on') { update_status(gettext("Extracting Snort GPLv2 Community Rules...")); update_output_window(gettext("Installing Snort GPLv2 Community Rules...")); } - error_log(gettext("\tExtracting and installing Snort GPLv2 Community Rules...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tExtracting and installing Snort GPLv2 Community Rules...\n"), 3, SNORT_RULES_UPD_LOGFILE); exec("/usr/bin/tar xzf {$tmpfname}/{$snort_community_rules_filename} -C {$tmpfname}/community/"); $files = glob("{$tmpfname}/community/community-rules/*.rules"); @@ -603,7 +614,7 @@ if ($snortcommunityrules == 'on') { update_status(gettext("Extraction of Snort GPLv2 Community Rules completed...")); update_output_window(gettext("Installation of Snort GPLv2 Community Rules file completed...")); } - error_log(gettext("\tInstallation of Snort GPLv2 Community Rules completed.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tInstallation of Snort GPLv2 Community Rules completed.\n"), 3, SNORT_RULES_UPD_LOGFILE); rmdir_recursive("{$tmpfname}/community/"); } } @@ -616,7 +627,7 @@ if ($emergingthreats == 'on') { update_status(gettext("Extracting {$et_name} rules...")); update_output_window(gettext("Installing {$et_name} rules...")); } - error_log(gettext("\tExtracting and installing {$et_name} rules...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tExtracting and installing {$et_name} rules...\n"), 3, SNORT_RULES_UPD_LOGFILE); exec("/usr/bin/tar xzf {$tmpfname}/{$emergingthreats_filename} -C {$tmpfname}/emerging rules/"); /* Remove the old Emerging Threats rules files */ @@ -664,7 +675,7 @@ if ($emergingthreats == 'on') { update_status(gettext("Extraction of {$et_name} rules completed...")); update_output_window(gettext("Installation of {$et_name} rules completed...")); } - error_log(gettext("\tInstallation of {$et_name} rules completed.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tInstallation of {$et_name} rules completed.\n"), 3, SNORT_RULES_UPD_LOGFILE); rmdir_recursive("{$tmpfname}/emerging/"); } } @@ -698,7 +709,7 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = if ($pkg_interface <> "console") update_status(gettext('Copying new config and map files...')); - error_log(gettext("\tCopying new config and map files...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tCopying new config and map files...\n"), 3, SNORT_RULES_UPD_LOGFILE); /******************************************************************/ /* Build the classification.config and reference.config files */ @@ -757,8 +768,8 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = safe_mkdir("{$snortdir}/snort_{$value['uuid']}_{$if_real}/rules"); if (!is_dir("{$snortdir}/snort_{$value['uuid']}_{$if_real}/preproc_rules")) safe_mkdir("{$snortdir}/snort_{$value['uuid']}_{$if_real}/preproc_rules"); - if (!is_dir("{$snortdir}/snort_{$value['uuid']}_{$if_real}/dynamicpreprocessor")) - safe_mkdir("{$snortdir}/snort_{$value['uuid']}_{$if_real}/dynamicpreprocessor"); + if (!is_dir("{$snortdir}/snort_{$value['uuid']}_{$if_real}/snort_dynamicpreprocessor")) + safe_mkdir("{$snortdir}/snort_{$value['uuid']}_{$if_real}/snort_dynamicpreprocessor"); snort_apply_customizations($value, $if_real); @@ -768,7 +779,7 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = $tmp .= gettext("\tPreprocessor text rules flagged as protected and not updated for "); $tmp .= convert_friendly_interface_to_friendly_descr($value['interface']) . "...\n"; } - error_log($tmp, 3, $snort_rules_upd_log); + error_log($tmp, 3, SNORT_RULES_UPD_LOGFILE); } } else { @@ -776,7 +787,7 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = update_output_window(gettext("Warning: No interfaces configured for Snort were found...")); update_output_window(gettext("No interfaces currently have Snort configured and enabled on them...")); } - error_log(gettext("\tWarning: No interfaces configured for Snort were found...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tWarning: No interfaces configured for Snort were found...\n"), 3, SNORT_RULES_UPD_LOGFILE); } /* Clear the rebuild rules flag. */ @@ -788,7 +799,7 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = update_status(gettext('Restarting Snort to activate the new set of rules...')); update_output_window(gettext("Please wait ... restarting Snort will take some time...")); } - error_log(gettext("\tRestarting Snort to activate the new set of rules...\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tRestarting Snort to activate the new set of rules...\n"), 3, SNORT_RULES_UPD_LOGFILE); touch("{$g['varrun_path']}/snort_pkg_starting.lck"); snort_restart_all_interfaces(TRUE); sleep(3); @@ -796,7 +807,32 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = if ($pkg_interface <> "console") update_output_window(gettext("Snort has restarted with your new set of rules...")); log_error(gettext("[Snort] Snort has restarted with your new set of rules...")); - error_log(gettext("\tSnort has restarted with your new set of rules.\n"), 3, $snort_rules_upd_log); + error_log(gettext("\tSnort has restarted with your new set of rules.\n"), 3, SNORT_RULES_UPD_LOGFILE); + } + else { + if ($pkg_interface <> "console") + update_output_window(gettext("The rules update task is complete...")); + } +} +elseif ($openappid_detectors == 'on') { + /**************************************************************************************/ + /* Only updated OpenAppID detectors, so do not need to rebuild all interface rules. */ + /* Restart snort if running, and not in post-install, so as to pick up the detectors. */ + /**************************************************************************************/ + if (!$g['snort_postinstall'] && is_service_running("snort") && count($config['installedpackages']['snortglobal']['rule']) > 0) { + if ($pkg_interface <> "console") { + update_status(gettext('Restarting Snort to activate the new OpenAppID detectors...')); + update_output_window(gettext("Please wait ... restarting Snort will take some time...")); + } + error_log(gettext("\tRestarting Snort to activate the new OpenAppID detectors...\n"), 3, SNORT_RULES_UPD_LOGFILE); + touch("{$g['varrun_path']}/snort_pkg_starting.lck"); + snort_restart_all_interfaces(TRUE); + sleep(2); + unlink_if_exists("{$g['varrun_path']}/snort_pkg_starting.lck"); + if ($pkg_interface <> "console") + update_output_window(gettext("Snort has restarted with your new set of OpenAppID detectors...")); + log_error(gettext("[Snort] Snort has restarted with your new set of OpenAppID detectors...")); + error_log(gettext("\tSnort has restarted with your new set of OpenAppID detectors.\n"), 3, SNORT_RULES_UPD_LOGFILE); } else { if ($pkg_interface <> "console") @@ -812,7 +848,7 @@ if (is_dir("{$tmpfname}")) { if ($pkg_interface <> "console") update_status(gettext("The Rules update has finished...")); log_error(gettext("[Snort] The Rules update has finished.")); -error_log(gettext("The Rules update has finished. Time: " . date("Y-m-d H:i:s"). "\n\n"), 3, $snort_rules_upd_log); +error_log(gettext("The Rules update has finished. Time: " . date("Y-m-d H:i:s"). "\n\n"), 3, SNORT_RULES_UPD_LOGFILE); /* Remount filesystem read-only if we changed it in this module */ if ($mounted_rw == TRUE) diff --git a/config/snort/snort_conf_template.inc b/config/snort/snort_conf_template.inc index e1b11acc..6b362ce5 100644 --- a/config/snort/snort_conf_template.inc +++ b/config/snort/snort_conf_template.inc @@ -24,9 +24,6 @@ var RULE_PATH {$snortcfgdir}/rules # Define Server Ports # {$portvardef} -# Configure quiet startup mode # -config quiet - # Configure the snort decoder # config checksum_mode: {$cksumcheck} config disable_decode_alerts diff --git a/config/snort/snort_defs.inc b/config/snort/snort_defs.inc new file mode 100644 index 00000000..43ecada6 --- /dev/null +++ b/config/snort/snort_defs.inc @@ -0,0 +1,101 @@ +<?php +/* + * snort_defs.inc + * + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009-2010 Robert Zelaya + * Copyright (C) 2011-2012 Ermal Luci + * Copyright (C) 2013,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. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +global $g, $config; + +/* Define some useful constants for Snort */ +if (!defined("SNORT_PBI_BASEDIR")) + define("SNORT_PBI_BASEDIR", "/usr/pbi/snort-" . php_uname("m") . "/"); +if (!defined("SNORT_PBI_BINDIR")) + define("SNORT_PBI_BINDIR", SNORT_PBI_BASEDIR . "bin/"); +if (!defined("SNORTDIR")) + define("SNORTDIR", SNORT_PBI_BASEDIR . "etc/snort"); +if (!defined("SNORTLOGDIR")) + define("SNORTLOGDIR", "{$g['varlog_path']}/snort"); +if (!defined("SNORT_BIN_VERSION")) { + // Grab the Snort binary version programmatically + $snortver = array(); + $snortbindir = SNORT_PBI_BINDIR; + mwexec("{$snortbindir}/snort -V 2>&1 |/usr/bin/grep Version | /usr/bin/cut -c20-26", $snortver); + if (!empty($snortver[0])) + define("SNORT_BIN_VERSION", $snortver[0]); + else + define("SNORT_BIN_VERSION", "2.9.7.0"); +} +if (!defined("SNORT_SID_MODS_PATH")) + define('SNORT_SID_MODS_PATH', "{$g['vardb_path']}/snort/sidmods/"); +if (!defined("SNORT_IPREP_PATH")) + define("SNORT_IPREP_PATH", "{$g['vardb_path']}/snort/iprep/"); +if (!defined('SNORT_APPID_ODP_PATH')) + define('SNORT_APPID_ODP_PATH', SNORTDIR . "/appid/"); + +// Rules filenames, download URLs and prefixes. +// Be sure to include the trailing backslash on URLs. +if (!defined("SNORT_ENFORCING_RULES_FILENAME")) + define("SNORT_ENFORCING_RULES_FILENAME", "snort.rules"); +if (!defined("FLOWBITS_FILENAME")) + define("FLOWBITS_FILENAME", "flowbit-required.rules"); +if (!defined("SNORT_RULES_UPD_LOGFILE")) + define("SNORT_RULES_UPD_LOGFILE", SNORTLOGDIR . "/snort_rules_update.log"); +if (!defined("VRT_DNLD_URL")) + define("VRT_DNLD_URL", "https://www.snort.org/rules/"); +if (!defined("ET_VERSION")) + define("ET_VERSION", "2.9.0"); +if (!defined("ET_BASE_DNLD_URL")) + define("ET_BASE_DNLD_URL", "http://rules.emergingthreats.net/"); +if (!defined("ETPRO_BASE_DNLD_URL")) + define("ETPRO_BASE_DNLD_URL", "https://rules.emergingthreatspro.com/"); +if (!defined("SNORT_ET_DNLD_FILENAME")) + define("SNORT_ET_DNLD_FILENAME", "emerging.rules.tar.gz"); +if (!defined("SNORT_ETPRO_DNLD_FILENAME")) + define("SNORT_ETPRO_DNLD_FILENAME", "etpro.rules.tar.gz"); +if (!defined("SNORT_GPLV2_DNLD_FILENAME")) + define("SNORT_GPLV2_DNLD_FILENAME", "community-rules.tar.gz"); +if (!defined("GPLV2_DNLD_URL")) + define("GPLV2_DNLD_URL", "https://www.snort.org/downloads/community/"); +if (!defined("SNORT_OPENAPPID_DNLD_URL")) + define("SNORT_OPENAPPID_DNLD_URL", "https://www.snort.org/downloads/openappid/"); +if (!defined("SNORT_OPENAPPID_DNLD_FILENAME")) + define("SNORT_OPENAPPID_DNLD_FILENAME", "snort-openappid.tar.gz"); +if (!defined("SNORT_RULES_UPD_LOGFILE")) + define("SNORT_RULES_UPD_LOGFILE", SNORTLOGDIR . "/snort_rules_update.log"); +if (!defined("VRT_FILE_PREFIX")) + define("VRT_FILE_PREFIX", "snort_"); +if (!defined("GPL_FILE_PREFIX")) + define("GPL_FILE_PREFIX", "GPLv2_"); +if (!defined("ET_OPEN_FILE_PREFIX")) + define("ET_OPEN_FILE_PREFIX", "emerging-"); +if (!defined("ET_PRO_FILE_PREFIX")) + define("ET_PRO_FILE_PREFIX", "etpro-"); + +?> diff --git a/config/snort/snort_download_updates.php b/config/snort/snort_download_updates.php index e74a9ce6..3f34cb7e 100755 --- a/config/snort/snort_download_updates.php +++ b/config/snort/snort_download_updates.php @@ -39,24 +39,18 @@ require_once("/usr/local/pkg/snort/snort.inc"); /* Define some locally required variables from Snort constants */ $snortdir = SNORTDIR; $snort_rules_upd_log = SNORT_RULES_UPD_LOGFILE; +$snortbinver = SNORT_BIN_VERSION; +$snortbinver = str_replace(".", "", $snortbinver); -/* Grab the Snort binary version programmatically and */ -/* use it to construct the proper Snort VRT rules */ -/* tarball filename. Fallback to a safe default if */ -/* we fail. */ -$snortver = array(); -exec("/usr/local/bin/snort -V 2>&1 |/usr/bin/grep Version | /usr/bin/cut -c20-26", $snortver); -if (empty($snortver[0])) - $snortver[0] = SNORT_BIN_VERSION; -$snortver[0] = str_replace(".", "", $snortver[0]); - -$snort_rules_file = "snortrules-snapshot-{$snortver[0]}.tar.gz"; +$snort_rules_file = "snortrules-snapshot-{$snortbinver}.tar.gz"; $snort_community_rules_filename = SNORT_GPLV2_DNLD_FILENAME; +$snort_openappid_filename = SNORT_OPENAPPID_DNLD_FILENAME; $snortdownload = $config['installedpackages']['snortglobal']['snortdownload']; $emergingthreats = $config['installedpackages']['snortglobal']['emergingthreats']; $etpro = $config['installedpackages']['snortglobal']['emergingthreats_pro']; $snortcommunityrules = $config['installedpackages']['snortglobal']['snortcommunityrules']; +$openappid_detectors = $config['installedpackages']['snortglobal']['openappid_detectors']; /* Get last update information if available */ if (!empty($config['installedpackages']['snortglobal']['last_rule_upd_time'])) @@ -70,21 +64,21 @@ else if ($etpro == "on") { $emergingthreats_filename = SNORT_ETPRO_DNLD_FILENAME; - $et_name = "Emerging Threats Pro Rules"; + $et_name = gettext("Emerging Threats Pro Rules"); } else { $emergingthreats_filename = SNORT_ET_DNLD_FILENAME; - $et_name = "Emerging Threats Open Rules"; + $et_name = gettext("Emerging Threats Open Rules"); } /* quick md5 chk of downloaded rules */ if ($snortdownload == 'on') { - $snort_org_sig_chk_local = 'Not Downloaded'; - $snort_org_sig_date = 'Not Downloaded'; + $snort_org_sig_chk_local = gettext("Not Downloaded"); + $snort_org_sig_date = gettext("Not Downloaded"); } else { - $snort_org_sig_chk_local = 'Not Enabled'; - $snort_org_sig_date = 'Not Enabled'; + $snort_org_sig_chk_local = gettext("Not Enabled"); + $snort_org_sig_date = gettext("Not Enabled"); } if (file_exists("{$snortdir}/{$snort_rules_file}.md5") && $snortdownload == 'on') { $snort_org_sig_chk_local = file_get_contents("{$snortdir}/{$snort_rules_file}.md5"); @@ -92,12 +86,12 @@ if (file_exists("{$snortdir}/{$snort_rules_file}.md5") && $snortdownload == 'on' } if ($etpro == "on" || $emergingthreats == "on") { - $emergingt_net_sig_chk_local = 'Not Downloaded'; - $emergingt_net_sig_date = 'Not Downloaded'; + $emergingt_net_sig_chk_local = gettext("Not Downloaded"); + $emergingt_net_sig_date = gettext("Not Downloaded"); } else { - $emergingt_net_sig_chk_local = 'Not Enabled'; - $emergingt_net_sig_date = 'Not Enabled'; + $emergingt_net_sig_chk_local = gettext("Not Enabled"); + $emergingt_net_sig_date = gettext("Not Enabled"); } if (file_exists("{$snortdir}/{$emergingthreats_filename}.md5") && ($etpro == "on" || $emergingthreats == "on")) { $emergingt_net_sig_chk_local = file_get_contents("{$snortdir}/{$emergingthreats_filename}.md5"); @@ -105,16 +99,29 @@ if (file_exists("{$snortdir}/{$emergingthreats_filename}.md5") && ($etpro == "on } if ($snortcommunityrules == 'on') { - $snort_community_sig_chk_local = 'Not Downloaded'; - $snort_community_sig_sig_date = 'Not Downloaded'; + $snort_community_sig_chk_local = gettext("Not Downloaded"); + $snort_community_sig_date = gettext("Not Downloaded"); } else { - $snort_community_sig_chk_local = 'Not Enabled'; - $snort_community_sig_sig_date = 'Not Enabled'; + $snort_community_sig_chk_local = gettext("Not Enabled"); + $snort_community_sig_date = gettext("Not Enabled"); } if (file_exists("{$snortdir}/{$snort_community_rules_filename}.md5") && $snortcommunityrules == 'on') { $snort_community_sig_chk_local = file_get_contents("{$snortdir}/{$snort_community_rules_filename}.md5"); - $snort_community_sig_sig_date = date(DATE_RFC850, filemtime("{$snortdir}/{$snort_community_rules_filename}.md5")); + $snort_community_sig_date = date(DATE_RFC850, filemtime("{$snortdir}/{$snort_community_rules_filename}.md5")); +} + +if ($openappid_detectors == 'on') { + $openappid_detectors_sig_chk_local = gettext("Not Downloaded"); + $openappid_detectors_sig_date = gettext("Not Downloaded"); +} +else { + $openappid_detectors_sig_chk_local = gettext("Not Enabled"); + $openappid_detectors_sig_date = gettext("Not Enabled"); +} +if (file_exists("{$snortdir}/{$snort_openappid_filename}.md5") && $openappid_detectors == 'on') { + $openappid_detectors_sig_chk_local = file_get_contents("{$snortdir}/{$snort_openappid_filename}.md5"); + $openappid_detectors_sig_date = date(DATE_RFC850, filemtime("{$snortdir}/{$snort_openappid_filename}.md5")); } /* Check for postback to see if we should clear the update log file. */ @@ -122,7 +129,7 @@ if (isset($_POST['clear'])) { unlink_if_exists($snort_rules_upd_log); } -if (isset($_POST['check'])) { +if (isset($_POST['update'])) { header("Location: /snort/snort_download_rules.php"); exit; } @@ -135,6 +142,7 @@ if ($_POST['force']) { unlink_if_exists("{$snortdir}/{$emergingthreats_filename}.md5"); unlink_if_exists("{$snortdir}/{$snort_community_rules_filename}.md5"); unlink_if_exists("{$snortdir}/{$snort_rules_file}.md5"); + unlink_if_exists("{$snortdir}/{$snort_openappid_filename}.md5"); // Revert file system to R/O. conf_mount_ro(); @@ -204,20 +212,25 @@ include_once("head.inc"); </tr> </thead> <tr> - <td align="center" class="vncell vexpl"><b>Snort VRT Rules</b></td> + <td align="center" class="vncell vexpl"><b><?=gettext("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> <tr> - <td align="center" class="vncell vexpl"><b>Snort GPLv2 Community Rules</b></td> + <td align="center" class="vncell vexpl"><b><?=gettext("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> + <td align="center" class="vncell vexpl"><?php echo gettext($snort_community_sig_date);?></td> </tr> <tr> <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="center" class="vncell vexpl"><b><?=gettext("Snort OpenAppID Detectors");?></b></td> + <td align="center" class="vncell vexpl"><? echo trim($openappid_detectors_sig_chk_local);?></td> + <td align="center" class="vncell vexpl"><?php echo gettext($openappid_detectors_sig_date);?></td> + </tr> </table><br/> </td> </tr> @@ -253,8 +266,8 @@ include_once("head.inc"); <br/></p> <?php else: ?> <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("Update");?>" name="update" id="update" class="formbtn" + title="<?php echo gettext("Check for and apply new update 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 enabled rule sets. Click OK to continue or CANCEL to quit");?>');"/> diff --git a/config/snort/snort_generate_conf.php b/config/snort/snort_generate_conf.php index fb5c750f..1d56fc13 100644 --- a/config/snort/snort_generate_conf.php +++ b/config/snort/snort_generate_conf.php @@ -64,9 +64,9 @@ $snort_dirs = array( $snortdir, $snortcfgdir, "{$snortcfgdir}/rules", "{$snortlogdir}/snort_{$if_real}{$snort_uuid}", "{$snortlogdir}/snort_{$if_real}{$snort_uuid}/barnyard2", "{$snortcfgdir}/preproc_rules", - "dynamicrules" => "{$snortlibdir}/dynamicrules", - "dynamicengine" => "{$snortlibdir}/dynamicengine", - "dynamicpreprocessor" => "{$snortcfgdir}/dynamicpreprocessor" + "dynamicrules" => "{$snortlibdir}/snort_dynamicrules", + "dynamicengine" => "{$snortlibdir}/snort_dynamicengine", + "dynamicpreprocessor" => "{$snortcfgdir}/snort_dynamicpreprocessor" ); foreach ($snort_dirs as $dir) { if (!is_dir($dir)) @@ -82,7 +82,7 @@ foreach ($snort_dirs as $dir) { /* put in place by the rules update process. */ /********************************************************************/ $snort_files = array("gen-msg.map", "classification.config", "reference.config", "attribute_table.dtd", - "sid-msg.map", "unicode.map", "threshold.conf", "preproc_rules/preprocessor.rules", + "sid-msg.map", "unicode.map", "file_magic.conf", "threshold.conf", "preproc_rules/preprocessor.rules", "preproc_rules/decoder.rules", "preproc_rules/sensitive-data.rules" ); foreach ($snort_files as $file) { @@ -126,6 +126,10 @@ if ($snortcfg['barnyard_enable'] == "on") { $snortunifiedlog_type .= ", vlan_event_types"; if ($snortcfg['barnyard_log_mpls_events'] == 'on') $snortunifiedlog_type .= ", mpls_event_types"; + + // If AppID detector is enabled, add it to unified2 logging + if ($snortcfg['appid_preproc'] == 'on' ) + $snortunifiedlog_type .= ", appid_event_types"; } /* define spoink */ @@ -889,6 +893,23 @@ preprocessor reputation: \ EOD; +/* def AppID preprocessor */ +$appid_memcap = $snortcfg['sf_appid_mem_cap'] * 1024 * 1024; +$appid_params = "app_detector_dir " . SNORT_APPID_ODP_PATH . ", \\\n\tmemcap {$appid_memcap}"; +if ($snortcfg['sf_appid_statslog'] == "on") { + $appid_params .= ", \\\n\tapp_stats_filename app-stats.log"; + $appid_params .= ", \\\n\tapp_stats_period {$snortcfg['sf_appid_stats_period']}"; + $appid_params .= ", \\\n\tapp_stats_rollover_size " . strval($config['installedpackages']['snortglobal']['appid_stats_log_limit_size'] * 1024); + $appid_params .= ", \\\n\tapp_stats_rollover_time 86400"; +} + +$appid_preproc = <<<EOD +# AppID preprocessor # +preprocessor appid: \ + {$appid_params} + +EOD; + /***************************************/ /* end of preprocessor string var code */ /***************************************/ @@ -920,14 +941,14 @@ $snort_preproc_libs = array( "dce_rpc_2" => "dce2_preproc", "dns_preprocessor" => "dns_preproc", "ftp_preprocessor" => "ftptelnet_preproc", "imap_preproc" => "imap_preproc", "pop_preproc" => "pop_preproc", "reputation_preproc" => "reputation_preproc", "sensitive_data" => "sdf_preproc", "sip_preproc" => "sip_preproc", "gtp_preproc" => "gtp_preproc", "smtp_preprocessor" => "smtp_preproc", "ssh_preproc" => "ssh_preproc", - "ssl_preproc" => "ssl_preproc", "dnp3_preproc" => "dnp3_preproc", "modbus_preproc" => "modbus_preproc" + "ssl_preproc" => "ssl_preproc", "dnp3_preproc" => "dnp3_preproc", "modbus_preproc" => "modbus_preproc", "appid_preproc" => "appid_preproc" ); $snort_preproc = array ( "perform_stat", "other_preprocs", "ftp_preprocessor", "smtp_preprocessor", "ssl_preproc", "sip_preproc", "gtp_preproc", "ssh_preproc", "sf_portscan", - "dce_rpc_2", "dns_preprocessor", "sensitive_data", "pop_preproc", "imap_preproc", "dnp3_preproc", "modbus_preproc", "reputation_preproc" + "dce_rpc_2", "dns_preprocessor", "sensitive_data", "pop_preproc", "imap_preproc", "dnp3_preproc", "modbus_preproc", "reputation_preproc", "appid_preproc" ); $default_disabled_preprocs = array( - "sf_portscan", "gtp_preproc", "sensitive_data", "dnp3_preproc", "modbus_preproc", "reputation_preproc", "perform_stat" + "sf_portscan", "gtp_preproc", "sensitive_data", "dnp3_preproc", "modbus_preproc", "reputation_preproc", "perform_stat", "appid_preproc" ); $snort_preprocessors = ""; foreach ($snort_preproc as $preproc) { @@ -941,8 +962,8 @@ foreach ($snort_preproc as $preproc) { if (!empty($snort_preproc_libs[$preproc])) { $preproclib = "libsf_" . $snort_preproc_libs[$preproc]; if (!file_exists($snort_dirs['dynamicpreprocessor'] . "{$preproclib}.so")) { - if (file_exists("{$snortlibdir}/dynamicpreprocessor/{$preproclib}.so")) { - @copy("{$snortlibdir}/dynamicpreprocessor/{$preproclib}.so", "{$snort_dirs['dynamicpreprocessor']}/{$preproclib}.so"); + if (file_exists("{$snortlibdir}/snort_dynamicpreprocessor/{$preproclib}.so")) { + @copy("{$snortlibdir}/snort_dynamicpreprocessor/{$preproclib}.so", "{$snort_dirs['dynamicpreprocessor']}/{$preproclib}.so"); $snort_preprocessors .= $$preproc; $snort_preprocessors .= "\n"; } else diff --git a/config/snort/snort_interface_logs.php b/config/snort/snort_interface_logs.php index ba8215ca..c8c4c24c 100644 --- a/config/snort/snort_interface_logs.php +++ b/config/snort/snort_interface_logs.php @@ -54,15 +54,29 @@ $if_real = get_real_interface($a_instance[$id]['interface']); // Construct a pointer to the instance's logging subdirectory $snortlogdir = SNORTLOGDIR . "/snort_{$if_real}{$snort_uuid}/"; +// Construct a pointer to the PBI_BIN directory +$snortbindir = SNORT_PBI_BINDIR; + // Limit all file access to just the currently selected interface's logging subdirectory $logfile = htmlspecialchars($snortlogdir . basename($_POST['file'])); if ($_POST['action'] == 'load') { + // If viewing the app-stats log, then grab only the most recent one + if (strpos(basename($logfile), "app-stats.log") !== FALSE) { + $appid_statlogs = glob("{$snortlogdir}app-stats.log.*"); + $logfile = array_pop($appid_statlogs); + } + if(!is_file($logfile)) { echo "|3|" . gettext("Log file does not exist or that logging feature is not enabled") . ".|"; } else { - $data = file_get_contents($logfile); + // Test for special unified2 format app-stats file because + // we have to use a Snort binary tool to display its contents. + if (strpos(basename($_POST['file']), "app-stats.log") !== FALSE) + $data = shell_exec("{$snortbindir}u2openappid {$logfile} 2>&1"); + else + $data = file_get_contents($logfile); if($data === false) { echo "|1|" . gettext("Failed to read log file") . ".|"; } else { @@ -178,7 +192,7 @@ if ($input_errors) { <td width="78%" class="vtable"> <select name="logFile" id="logFile" class="formselect" onChange="loadFile();"> <?php - $logs = array( "alert", "{$if_real}.stats" , "sid_changes.log" ); + $logs = array( "alert", "app-stats.log", "{$if_real}.stats" , "sid_changes.log" ); foreach ($logs as $log) { $selected = ""; if ($log == basename($logfile)) diff --git a/config/snort/snort_interfaces_edit.php b/config/snort/snort_interfaces_edit.php index 14b54b34..0d41c7db 100755 --- a/config/snort/snort_interfaces_edit.php +++ b/config/snort/snort_interfaces_edit.php @@ -365,9 +365,15 @@ if ($_POST["save"] && !$input_errors) { if (!is_array($natent['stream5_tcp_engine']['item'])) $natent['stream5_tcp_engine']['item'] = array(); $natent['stream5_tcp_engine']['item'][] = $stream5_eng; + $natent['alertsystemlog_facility'] = "log_auth"; $natent['alertsystemlog_priority'] = "log_alert"; + $natent['appid_preproc'] = "off"; + $natent['sf_appid_mem_cap'] = "256"; + $natent['sf_appid_statslog'] = "on"; + $natent['sf_appid_stats_period'] = "300"; + $a_rule[] = $natent; } diff --git a/config/snort/snort_interfaces_global.php b/config/snort/snort_interfaces_global.php index fb36d192..6c1d56ac 100644 --- a/config/snort/snort_interfaces_global.php +++ b/config/snort/snort_interfaces_global.php @@ -41,19 +41,26 @@ require_once("/usr/local/pkg/snort/snort.inc"); global $g; $snortdir = SNORTDIR; - -/* make things short */ -$pconfig['snortdownload'] = $config['installedpackages']['snortglobal']['snortdownload'] == "on" ? 'on' : 'off'; -$pconfig['oinkmastercode'] = $config['installedpackages']['snortglobal']['oinkmastercode']; -$pconfig['etpro_code'] = $config['installedpackages']['snortglobal']['etpro_code']; -$pconfig['emergingthreats'] = $config['installedpackages']['snortglobal']['emergingthreats'] == "on" ? 'on' : 'off'; -$pconfig['emergingthreats_pro'] = $config['installedpackages']['snortglobal']['emergingthreats_pro'] == "on" ? 'on' : 'off'; -$pconfig['rm_blocked'] = $config['installedpackages']['snortglobal']['rm_blocked']; -$pconfig['autorulesupdate7'] = $config['installedpackages']['snortglobal']['autorulesupdate7']; -$pconfig['rule_update_starttime'] = $config['installedpackages']['snortglobal']['rule_update_starttime']; -$pconfig['forcekeepsettings'] = $config['installedpackages']['snortglobal']['forcekeepsettings'] == "on" ? 'on' : 'off'; -$pconfig['snortcommunityrules'] = $config['installedpackages']['snortglobal']['snortcommunityrules'] == "on" ? 'on' : 'off'; -$pconfig['clearblocks'] = $config['installedpackages']['snortglobal']['clearblocks'] == "on" ? 'on' : 'off'; +$snort_openappdir = SNORT_APPID_ODP_PATH; + +// Grab any previous input values if doing a SAVE operation +if ($_POST['save']) + $pconfig = $_POST; +else { + $pconfig['snortdownload'] = $config['installedpackages']['snortglobal']['snortdownload'] == "on" ? 'on' : 'off'; + $pconfig['oinkmastercode'] = $config['installedpackages']['snortglobal']['oinkmastercode']; + $pconfig['etpro_code'] = $config['installedpackages']['snortglobal']['etpro_code']; + $pconfig['emergingthreats'] = $config['installedpackages']['snortglobal']['emergingthreats'] == "on" ? 'on' : 'off'; + $pconfig['emergingthreats_pro'] = $config['installedpackages']['snortglobal']['emergingthreats_pro'] == "on" ? 'on' : 'off'; + $pconfig['rm_blocked'] = $config['installedpackages']['snortglobal']['rm_blocked']; + $pconfig['autorulesupdate7'] = $config['installedpackages']['snortglobal']['autorulesupdate7']; + $pconfig['rule_update_starttime'] = $config['installedpackages']['snortglobal']['rule_update_starttime']; + $pconfig['forcekeepsettings'] = $config['installedpackages']['snortglobal']['forcekeepsettings'] == "on" ? 'on' : 'off'; + $pconfig['snortcommunityrules'] = $config['installedpackages']['snortglobal']['snortcommunityrules'] == "on" ? 'on' : 'off'; + $pconfig['clearblocks'] = $config['installedpackages']['snortglobal']['clearblocks'] == "on" ? 'on' : 'off'; + $pconfig['verbose_logging'] = $config['installedpackages']['snortglobal']['verbose_logging'] == "on" ? 'on' : 'off'; + $pconfig['openappid_detectors'] = $config['installedpackages']['snortglobal']['openappid_detectors'] == "on" ? 'on' : 'off'; +} /* Set sensible values for any empty default params */ if (!isset($pconfig['rule_update_starttime'])) @@ -61,6 +68,16 @@ if (!isset($pconfig['rule_update_starttime'])) if (!isset($config['installedpackages']['snortglobal']['forcekeepsettings'])) $pconfig['forcekeepsettings'] = 'on'; +/* Grab OpenAppID version info if enabled and downloaded */ +if ($pconfig['openappid_detectors'] == "on") { + if (file_exists("{$snort_openappdir}odp/version.conf")) { + $openappid_ver = gettext("Installed Detection Package "); + $openappid_ver .= gettext(ucfirst(strtolower(file_get_contents("{$snort_openappdir}odp/version.conf")))); + } + else + $openappid_ver = gettext("N/A (Not Downloaded)"); +} + if ($_POST['rule_update_starttime']) { if (!preg_match('/^([01]?[0-9]|2[0-3]):?([0-5][0-9])$/', $_POST['rule_update_starttime'])) $input_errors[] = "Invalid Rule Update Start Time! Please supply a value in 24-hour format as 'HH:MM'."; @@ -81,6 +98,8 @@ if (!$input_errors) { $config['installedpackages']['snortglobal']['emergingthreats'] = $_POST['emergingthreats'] ? 'on' : 'off'; $config['installedpackages']['snortglobal']['emergingthreats_pro'] = $_POST['emergingthreats_pro'] ? 'on' : 'off'; $config['installedpackages']['snortglobal']['clearblocks'] = $_POST['clearblocks'] ? 'on' : 'off'; + $config['installedpackages']['snortglobal']['verbose_logging'] = $_POST['verbose_logging'] ? 'on' : 'off'; + $config['installedpackages']['snortglobal']['openappid_detectors'] = $_POST['openappid_detectors'] ? 'on' : 'off'; // If any rule sets are being turned off, then remove them // from the active rules section of each interface. Start @@ -137,13 +156,13 @@ if (!$input_errors) { $retval = 0; + write_config("Snort pkg: modified global settings."); + /* create whitelist and homenet file, then sync files */ conf_mount_rw(); sync_snort_package_config(); conf_mount_ro(); - write_config("Snort pkg: modified global settings."); - /* 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' ); @@ -206,7 +225,7 @@ if ($input_errors) <table width="100%" border="0" cellpadding="2" cellspacing="0"> <tr> <td><input name="snortdownload" type="checkbox" id="snortdownload" value="on" onclick="enable_snort_vrt();" - <?php if($pconfig['snortdownload']=='on') echo 'checked'; ?>></td> + <?php if($pconfig['snortdownload']=='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> @@ -224,9 +243,9 @@ if ($input_errors) </tr> <tr> <td valign="top"><span class="vexpl"><strong><?php echo gettext("Code:"); ?></strong></span></td> - <td><input name="oinkmastercode" type="text" - class="formfld unknown" id="oinkmastercode" size="52" - value="<?=htmlspecialchars($pconfig['oinkmastercode']);?>"><br/> + <td><input name="oinkmastercode" type="text" + class="formfld unknown" id="oinkmastercode" size="52" + value="<?=htmlspecialchars($pconfig['oinkmastercode']);?>" /><br/> <?php echo gettext("Obtain a snort.org Oinkmaster code and paste it here."); ?></td> </tr> </table> @@ -236,8 +255,8 @@ if ($input_errors) <td width="78%" class="vtable"> <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']['snortglobal']['snortcommunityrules']=="on") echo "checked";?> ></td> + <td valign="top" width="8%"><input name="snortcommunityrules" type="checkbox" value="on" + <?php if ($pconfig['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>" . @@ -252,13 +271,13 @@ if ($input_errors) <table width="100%" border="0" cellpadding="2" cellspacing="0"> <tr> <td valign="top" width="8%"><input name="emergingthreats" type="checkbox" value="on" onclick="enable_et_rules();" - <?php if ($config['installedpackages']['snortglobal']['emergingthreats']=="on") echo "checked"; ?>></td> + <?php if ($pconfig['emergingthreats']=="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="emergingthreats_pro" type="checkbox" value="on" onclick="enable_etpro_rules();" - <?php if ($config['installedpackages']['snortglobal']['emergingthreats_pro']=="on") echo "checked"; ?>></td> + <?php if ($pconfig['emergingthreats_pro']=="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> @@ -282,13 +301,38 @@ if ($input_errors) <td valign="top"><span class="vexpl"><strong><?php echo gettext("Code:"); ?></strong></span></td> <td><input name="etpro_code" type="text" class="formfld unknown" id="etpro_code" size="52" - value="<?=htmlspecialchars($pconfig['etpro_code']);?>"><br/> + value="<?=htmlspecialchars($pconfig['etpro_code']);?>"/><br/> <?php echo gettext("Obtain an ETPro subscription code and paste it here."); ?></td> </tr> </table> </td> </tr> - +<tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Install ") . "<strong>" . gettext("OpenAppID") . "</strong>" . gettext(" detectors");?></td> + <td width="78%" class="vtable"> + <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tr> + <td valign="top" width="8%"><input name="openappid_detectors" type="checkbox" value="on" onclick="enable_openappid_dnload();" + <?php if ($pconfig['openappid_detectors']=="on") echo "checked";?> /></td> + <td class="vexpl"><?php echo gettext("The OpenAppID package contains the application signatures required by " . + "the AppID preprocessor.");?> + <br/><br/><?php echo "<span class=\"red\"><strong>" . gettext("Note: ") . "</strong></span>" . + gettext("You must enable download of the OpenAppID detectors package in order to utilize the Application ID ") . + gettext("preprocessor and any user-provided application detection rules. Once enabled, go to the ") . + "<a href='/snort/snort_download_updates.php'>" . gettext("UPDATES") . "</a>" . gettext(" tab and click to download updates.");?></td> + </tr> + <tbody id="openappid_rows"> + <tr> + <td class="vexpl" colspan="2"><br/><strong><?=gettext("OpenAppID Detection Package");?></strong></td> + </tr> + <tr> + <td class="vexpl" valign="top"><strong><?=gettext("VER:");?></strong></td> + <td class="vexpl"><?=htmlspecialchars($openappid_ver);?></td> + </tr> + </tbody> + </table> + </td> +</tr> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Rules Update Settings"); ?></td> </tr> @@ -300,7 +344,7 @@ if ($input_errors) $interfaces3 = array('never_up' => gettext('NEVER'), '6h_up' => gettext('6 HOURS'), '12h_up' => gettext('12 HOURS'), '1d_up' => gettext('1 DAY'), '4d_up' => gettext('4 DAYS'), '7d_up' => gettext('7 DAYS'), '28d_up' => gettext('28 DAYS')); foreach ($interfaces3 as $iface3 => $ifacename3): ?> <option value="<?=$iface3;?>" - <?php if ($iface3 == $pconfig['autorulesupdate7']) echo "selected"; ?>> + <?php if ($iface3 == $pconfig['autorulesupdate7']) echo "selected"; ?> /> <?=htmlspecialchars($ifacename3);?></option> <?php endforeach; ?> </select><span class="vexpl"> <?php echo gettext("Please select the interval for rule updates. Choosing ") . @@ -310,7 +354,7 @@ if ($input_errors) <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="rule_update_starttime" id="rule_update_starttime" size="4" - maxlength="5" value="<?=htmlspecialchars($pconfig['rule_update_starttime']);?>" <?php if ($pconfig['autorulesupdate7'] == "never_up") {echo "disabled";} ?>><span class="vexpl"> + maxlength="5" value="<?=htmlspecialchars($pconfig['rule_update_starttime']);?>" <?php if ($pconfig['autorulesupdate7'] == "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:05") . "</strong></span>"; ?>.<br/><br/> <?php echo gettext("Rules will update at the interval chosen above starting at the time specified here. For example, using the default " . @@ -327,7 +371,7 @@ if ($input_errors) $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"; ?>> + <?php if ($iface3 == $pconfig['rm_blocked']) echo "selected"; ?> /> <?=htmlspecialchars($ifacename3);?></option> <?php endforeach; ?> </select> @@ -336,21 +380,29 @@ if ($input_errors) </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Remove Blocked Hosts After Deinstall"); ?></td> - <td width="78%" class="vtable"><input name="clearblocks" id="clearblocks" type="checkbox" value="yes" - <?php if ($config['installedpackages']['snortglobal']['clearblocks']=="on") echo " checked"; ?>/> + <td width="78%" class="vtable"><input name="clearblocks" id="clearblocks" type="checkbox" value="yes" + <?php if ($pconfig['clearblocks']=="on") echo " checked"; ?> /> <?php echo gettext("All blocked hosts added by Snort will be removed during package deinstallation."); ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Keep Snort Settings After Deinstall"); ?></td> <td width="78%" class="vtable"><input name="forcekeepsettings" - id="forcekeepsettings" type="checkbox" value="yes" - <?php if ($pconfig['forcekeepsettings']=="on") echo "checked"; ?> - > <?php echo gettext("Settings will not be removed during package deinstallation."); ?></td> + id="forcekeepsettings" type="checkbox" value="yes" + <?php if ($pconfig['forcekeepsettings']=="on") echo "checked"; ?> /> + <?php echo gettext("Settings will not be removed during package deinstallation."); ?></td> +</tr> +<tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Startup/Shutdown Logging"); ?></td> + <td width="78%" class="vtable"><input name="verbose_logging" + id="verbose_logging" type="checkbox" value="yes" + <?php if ($pconfig['verbose_logging']=="on") echo "checked"; ?> /> + <?php echo gettext("Output detailed messages to the system log when Snort is starting and stopping. Default is ") . + "<strong>" . gettext("Not Checked") . "</strong>" . gettext("."); ?></td> </tr> <tr> <td width="22%" valign="top"> <td width="78%"> - <input name="save" type="submit" class="formbtn" value="Save" > + <input name="save" type="submit" class="formbtn" value="Save" /> </td> </tr> <tr> @@ -403,11 +455,20 @@ function enable_change_rules_upd() { document.iform.rule_update_starttime.disabled=""; } +function enable_openappid_dnload() { + var endis = document.iform.openappid_detectors.checked; + if (endis) + document.getElementById("openappid_rows").style.display = ""; + else + document.getElementById("openappid_rows").style.display = "none"; +} + // Initialize the form controls state based on saved settings enable_snort_vrt(); enable_et_rules(); enable_etpro_rules(); enable_change_rules_upd(); +enable_openappid_dnload(); //--> </script> diff --git a/config/snort/snort_ip_list_mgmt.php b/config/snort/snort_ip_list_mgmt.php index 8311ea1c..20d486c6 100644 --- a/config/snort/snort_ip_list_mgmt.php +++ b/config/snort/snort_ip_list_mgmt.php @@ -152,6 +152,7 @@ if ($savemsg) <input type="hidden" name="MAX_FILE_SIZE" value="100000000" /> <input type="hidden" name="iplist_fname" id="iplist_fname" value=""/> <table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> <tr><td> <?php $tab_array = array(); @@ -170,21 +171,19 @@ if ($savemsg) ?> </td> </tr> -<tbody id="uploader" style="display: none;" class="tabcont"> - <tr> - <td colspan="4" class="list"><br/><?php echo gettext("Click BROWSE to select a file to import, and then click UPLOAD. Click CLOSE to quit."); ?></td> - </tr> - <tr> - <td colspan="4" class="list"><input type="file" name="iprep_fileup" id="iprep_fileup" class="formfld file" size="50" /> - <input type="submit" name="upload" id="upload" value="<?=gettext("Upload");?>" - title="<?=gettext("Upload selected IP list to firewall");?>"/> <input type="button" - value="<?=gettext("Close");?>" onClick="document.getElementById('uploader').style.display='none';" /><br/></td> - <td class="list"></td> - </tr> -</tbody> <tr> <td> <div id="mainarea"> + + <?php if ($g['platform'] == "nanobsd") : ?> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("IP Reputation is not supported on NanoBSD installs"); ?></td> + </tr> + </tbody> + </table> + <?php else: ?> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> <colgroup> <col style="width: 50%;"> @@ -223,6 +222,18 @@ if ($savemsg) height="17" border="0" title="<?php echo gettext('Delete this IP List');?>"/></td> </tr> <?php endforeach; ?> + <tbody id="uploader" style="display: none;"> + <tr> + <td colspan="4" class="list"><br/><?php echo gettext("Click BROWSE to select a file to import, and then click UPLOAD. Click CLOSE to quit."); ?></td> + </tr> + <tr> + <td colspan="4" class="list"><input type="file" name="iprep_fileup" id="iprep_fileup" class="formfld file" size="50" /> + <input type="submit" name="upload" id="upload" value="<?=gettext("Upload");?>" + title="<?=gettext("Upload selected IP list to firewall");?>"/> <input type="button" + value="<?=gettext("Close");?>" onClick="document.getElementById('uploader').style.display='none';" /><br/></td> + <td colspan="4" class="list"></td> + </tr> + </tbody> <tbody id="iplist_editor" style="<?=$iplist_edit_style;?>"> <tr> <td colspan="4"> </td> @@ -267,9 +278,11 @@ if ($savemsg) <td class="list"></td> </tr> </table> + <?php endif; ?> </div> </td> </tr> +</tbody> </table> </form> <?php include("fend.inc"); ?> diff --git a/config/snort/snort_ip_reputation.php b/config/snort/snort_ip_reputation.php index 891f3773..4c3065a0 100644 --- a/config/snort/snort_ip_reputation.php +++ b/config/snort/snort_ip_reputation.php @@ -204,6 +204,7 @@ if ($savemsg) <?php endif; ?> <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> <tr> <td> <?php @@ -239,6 +240,12 @@ if ($savemsg) <tr> <td><div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> + <?php if ($g['platform'] == "nanobsd") : ?> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("IP Reputation is not supported on NanoBSD installs"); ?></td> + </tr> + <?php else: ?> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("IP Reputation Preprocessor Configuration"); ?></td> </tr> @@ -368,9 +375,9 @@ if ($savemsg) <td width="22%" valign='top' class='vncell'><?php echo gettext("Whitelist Files"); ?> </td> <td width="78%" class="vtable"> - <table width="95%" border="0" cellpadding="2" cellspacing="0"> <!-- wlist_chooser --> <div id="wlistChooser" name="wlistChooser" style="display:none; border:1px dashed gray; width:98%;"></div> + <table width="95%" border="0" cellpadding="2" cellspacing="0"> <colgroup> <col style="text-align:left;"> <col style="width: 30%; text-align:left;"> @@ -411,12 +418,16 @@ if ($savemsg) </table> </td> </tr> + <?php endif; ?> + </tbody> </table> </div> </td> </tr> + </tbody> </table> +<?php if ($g['platform'] != "nanobsd") : ?> <script type="text/javascript"> Event.observe( window, "load", @@ -504,6 +515,7 @@ function wlistComplete(req) { } </script> +<?php endif; ?> </form> <?php include("fend.inc"); ?> diff --git a/config/snort/snort_log_mgmt.php b/config/snort/snort_log_mgmt.php index 0e38afc2..33d94a04 100644 --- a/config/snort/snort_log_mgmt.php +++ b/config/snort/snort_log_mgmt.php @@ -57,6 +57,8 @@ $pconfig['sid_changes_log_limit_size'] = $config['installedpackages']['snortglob $pconfig['sid_changes_log_retention'] = $config['installedpackages']['snortglobal']['sid_changes_log_retention']; $pconfig['event_pkts_log_limit_size'] = '0'; $pconfig['event_pkts_log_retention'] = $config['installedpackages']['snortglobal']['event_pkts_log_retention']; +$pconfig['appid_stats_log_limit_size'] = $config['installedpackages']['snortglobal']['appid_stats_log_limit_size']; +$pconfig['appid_stats_log_retention'] = $config['installedpackages']['snortglobal']['appid_stats_log_retention']; // Load up some arrays with selection values (we use these later). // The keys in the $retentions array are the retention period @@ -86,6 +88,8 @@ if (!isset($pconfig['sid_changes_log_retention'])) $pconfig['sid_changes_log_retention'] = "336"; if (!isset($pconfig['event_pkts_log_retention'])) $pconfig['event_pkts_log_retention'] = "336"; +if (!isset($pconfig['appid_stats_log_retention'])) + $pconfig['appid_stats_log_retention'] = "168"; // Set default log file size limits if (!isset($pconfig['alert_log_limit_size'])) @@ -94,6 +98,8 @@ if (!isset($pconfig['stats_log_limit_size'])) $pconfig['stats_log_limit_size'] = "500"; if (!isset($pconfig['sid_changes_log_limit_size'])) $pconfig['sid_changes_log_limit_size'] = "250"; +if (!isset($pconfig['appid_stats_log_limit_size'])) + $pconfig['appid_stats_log_limit_size'] = "1000"; if ($_POST['ResetAll']) { @@ -102,11 +108,13 @@ if ($_POST['ResetAll']) { $pconfig['stats_log_retention'] = "168"; $pconfig['sid_changes_log_retention'] = "336"; $pconfig['event_pkts_log_retention'] = "336"; + $pconfig['appid_stats_log_retention'] = "168"; $pconfig['alert_log_limit_size'] = "500"; $pconfig['stats_log_limit_size'] = "500"; $pconfig['sid_changes_log_limit_size'] = "250"; $pconfig['event_pkts_log_limit_size'] = "0"; + $pconfig['appid_stats_log_limit_size'] = "1000"; /* Log a message at the top of the page to inform the user */ $savemsg = gettext("All log management settings on this page have been reset to their defaults. Click APPLY if you wish to keep these new settings."); @@ -148,6 +156,8 @@ if ($_POST["save"] || $_POST['apply']) { $config['installedpackages']['snortglobal']['sid_changes_log_retention'] = $_POST['sid_changes_log_retention']; $config['installedpackages']['snortglobal']['event_pkts_log_limit_size'] = $_POST['event_pkts_log_limit_size']; $config['installedpackages']['snortglobal']['event_pkts_log_retention'] = $_POST['event_pkts_log_retention']; + $config['installedpackages']['snortglobal']['appid_stats_log_limit_size'] = $_POST['appid_stats_log_limit_size']; + $config['installedpackages']['snortglobal']['appid_stats_log_retention'] = $_POST['appid_stats_log_retention']; write_config("Snort pkg: saved updated configuration for LOGS MGMT."); conf_mount_rw(); @@ -307,7 +317,26 @@ if ($savemsg) { </td> <td class="listbg"><?=gettext("Snort alerts and event details");?></td> </tr> - + <tr> + <td class="listbg">appid-stats</td> + <td class="listr" align="center"><select name="appid_stats_log_limit_size" class="formselect" id="appid_stats_log_limit_size"> + <?php foreach ($log_sizes as $k => $l): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['appid_stats_log_limit_size']) echo " selected"; ?>> + <?=htmlspecialchars($l);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listr" align="center"><select name="appid_stats_log_retention" class="formselect" id="appid_stats_log_retention"> + <?php foreach ($retentions as $k => $p): ?> + <option value="<?=$k;?>" + <?php if ($k == $pconfig['appid_stats_log_retention']) echo " selected"; ?>> + <?=htmlspecialchars($p);?></option> + <?php endforeach; ?> + </select> + </td> + <td class="listbg"><?=gettext("Application ID statistics");?></td> + </tr> <tr> <td class="listbg">event pcaps</td> <td class="listr" align="center"><select name="event_pkts_log_limit_size" class="formselect" id="event_pkts_log_limit_size"> @@ -324,7 +353,6 @@ if ($savemsg) { </td> <td class="listbg"><?=gettext("Snort alert related packet captures");?></td> </tr> - <tr> <td class="listbg">sid_changes</td> <td class="listr" align="center"><select name="sid_changes_log_limit_size" class="formselect" id="sid_changes_log_limit_size"> diff --git a/config/snort/snort_migrate_config.php b/config/snort/snort_migrate_config.php index a722d52b..12ae5d19 100644 --- a/config/snort/snort_migrate_config.php +++ b/config/snort/snort_migrate_config.php @@ -73,27 +73,52 @@ if (empty($config['installedpackages']['snortglobal']['snort_config_ver']) && /**********************************************************/ /* Create new Auto SID Mgmt settings if not set */ /**********************************************************/ - if (empty($config['installedpackages']['snortglobal']['auto_manage_sids'])) { - $config['installedpackages']['snortglobal']['auto_manage_sids'] = "off"; - $updated_cfg = true; - } +if (empty($config['installedpackages']['snortglobal']['auto_manage_sids'])) { + $config['installedpackages']['snortglobal']['auto_manage_sids'] = "off"; + $updated_cfg = true; +} /**********************************************************/ /* Create new LOG MGMT settings if not set */ /**********************************************************/ - if (empty($config['installedpackages']['snortglobal']['enable_log_mgmt'])) { - $config['installedpackages']['snortglobal']['enable_log_mgmt'] = "on"; - $config['installedpackages']['snortglobal']['alert_log_limit_size'] = "500"; - $config['installedpackages']['snortglobal']['alert_log_retention'] = "336"; - $config['installedpackages']['snortglobal']['event_pkts_log_limit_size'] = "0"; - $config['installedpackages']['snortglobal']['event_pkts_log_retention'] = "336"; - $config['installedpackages']['snortglobal']['sid_changes_log_limit_size'] = "250"; - $config['installedpackages']['snortglobal']['sid_changes_log_retention'] = "336"; - $config['installedpackages']['snortglobal']['stats_log_limit_size'] = "500"; - $config['installedpackages']['snortglobal']['stats_log_retention'] = "168"; - $updated_cfg = true; +if (empty($config['installedpackages']['snortglobal']['enable_log_mgmt'])) { + $config['installedpackages']['snortglobal']['enable_log_mgmt'] = "on"; + $config['installedpackages']['snortglobal']['alert_log_limit_size'] = "500"; + $config['installedpackages']['snortglobal']['alert_log_retention'] = "336"; + $config['installedpackages']['snortglobal']['appid_stats_log_limit_size'] = "1000"; + $config['installedpackages']['snortglobal']['appid_stats_log_retention'] = "168"; + $config['installedpackages']['snortglobal']['event_pkts_log_limit_size'] = "0"; + $config['installedpackages']['snortglobal']['event_pkts_log_retention'] = "336"; + $config['installedpackages']['snortglobal']['sid_changes_log_limit_size'] = "250"; + $config['installedpackages']['snortglobal']['sid_changes_log_retention'] = "336"; + $config['installedpackages']['snortglobal']['stats_log_limit_size'] = "500"; + $config['installedpackages']['snortglobal']['stats_log_retention'] = "168"; + $updated_cfg = true; +} +if (empty($config['installedpackages']['snortglobal']['appid_stats_log_limit_size'])) + $config['installedpackages']['snortglobal']['appid_stats_log_limit_size'] = "1000"; +if (empty($config['installedpackages']['snortglobal']['appid_stats_log_retention'])) + $config['installedpackages']['snortglobal']['appid_stats_log_retention'] = "168"; + +/**********************************************************/ +/* Create new VERBOSE_LOGGING setting if not set */ +/**********************************************************/ +if (empty($config['installedpackages']['snortglobal']['verbose_logging'])) { + $config['installedpackages']['snortglobal']['verbose_logging'] = "off"; + $updated_cfg = true; } +/**********************************************************/ +/* Create new OpenAppID settings if not set */ +/**********************************************************/ +if (empty($config['installedpackages']['snortglobal']['openappid_detectors'])) { + $config['installedpackages']['snortglobal']['openappid_detectors'] = "off"; + $updated_cfg = true; +} + +/**********************************************************/ +/* Migrate per interface settings if required. */ +/**********************************************************/ foreach ($rule as &$r) { // Initialize arrays for supported preprocessors if necessary if (!is_array($r['frag3_engine']['item'])) @@ -482,6 +507,24 @@ foreach ($rule as &$r) { $updated_cfg = true; } + // Default any unconfigured AppID preprocessor settings + if (empty($pconfig['appid_preproc'])) { + $pconfig['appid_preproc'] = 'off'; + $updated_cfg = true; + } + if (empty($pconfig['sf_appid_mem_cap'])) { + $pconfig['sf_appid_mem_cap'] = '256'; + $updated_cfg = true; + } + if (empty($pconfig['sf_appid_statslog'])) { + $pconfig['sf_appid_statslog'] = 'on'; + $updated_cfg = true; + } + if (empty($pconfig['sf_appid_stats_period'])) { + $pconfig['sf_appid_stats_period'] = '300'; + $updated_cfg = true; + } + // Save the new configuration data into the $config array pointer $r = $pconfig; } @@ -490,8 +533,7 @@ unset($r); // Log a message if we changed anything if ($updated_cfg) { - $config['installedpackages']['snortglobal']['snort_config_ver'] = "3.1.5"; - log_error("[Snort] Saving configuration settings in new format..."); + $config['installedpackages']['snortglobal']['snort_config_ver'] = "3.2"; log_error("[Snort] Settings successfully migrated to new configuration format..."); } else diff --git a/config/snort/snort_post_install.php b/config/snort/snort_post_install.php index 5009a8b3..57e92ce5 100644 --- a/config/snort/snort_post_install.php +++ b/config/snort/snort_post_install.php @@ -41,35 +41,12 @@ require_once("config.inc"); require_once("functions.inc"); require_once("/usr/local/pkg/snort/snort.inc"); +require("/usr/local/pkg/snort/snort_defs.inc"); global $config, $g, $rebuild_rules, $pkg_interface, $snort_gui_include; -/**************************************** - * Define any new constants here that * - * may not be yet defined in the old * - * "snort.inc" include file that might * - * be cached and used by the package * - * manager installation code. * - * * - * This is a hack to work around the * - * fact the old version of suricata.inc * - * is cached and used instead of the * - * updated version icluded with the * - * updated GUI package. * - ****************************************/ -if (!defined('SNORT_SID_MODS_PATH')) - define('SNORT_SID_MODS_PATH', "{$g['vardb_path']}/snort/sidmods/"); - -if (!defined('SNORT_ENFORCING_RULES_FILENAME')) - define("SNORT_ENFORCING_RULES_FILENAME", "snort.rules"); - -/**************************************** - * End of PHP caching workaround * - ****************************************/ - $snortdir = SNORTDIR; $snortlogdir = SNORTLOGDIR; -$snortlibdir = SNORTLIBDIR; $rcdir = RCFILEPREFIX; $flowbit_rules_file = FLOWBITS_FILENAME; $snort_enforcing_rules_file = SNORT_ENFORCING_RULES_FILENAME; @@ -101,6 +78,7 @@ conf_mount_rw(); @rename("{$snortdir}/threshold.conf-sample", "{$snortdir}/threshold.conf"); @rename("{$snortdir}/sid-msg.map-sample", "{$snortdir}/sid-msg.map"); @rename("{$snortdir}/unicode.map-sample", "{$snortdir}/unicode.map"); +@rename("{$snortdir}/file_magic.conf-sample", "{$snortdir}/file_magic.conf"); @rename("{$snortdir}/classification.config-sample", "{$snortdir}/classification.config"); @rename("{$snortdir}/generators-sample", "{$snortdir}/generators"); @rename("{$snortdir}/reference.config-sample", "{$snortdir}/reference.config"); @@ -123,6 +101,7 @@ unlink_if_exists("{$rcdir}barnyard2"); safe_mkdir(SNORTLOGDIR); safe_mkdir(SNORT_IPREP_PATH); safe_mkdir(SNORT_SID_MODS_PATH); +safe_mkdir(SNORT_APPID_ODP_PATH); /* If installed, absorb the Snort Dashboard Widget into this package */ /* by removing it as a separately installed package. */ @@ -263,8 +242,8 @@ if (stristr($config['widgets']['sequence'], "snort_alerts-container") === FALSE) $config['widgets']['sequence'] .= ",{$snort_widget_container}"; /* Update Snort package version in configuration */ -$config['installedpackages']['snortglobal']['snort_config_ver'] = "3.1.5"; -write_config("Snort pkg v3.1.5: post-install configuration saved."); +$config['installedpackages']['snortglobal']['snort_config_ver'] = "3.2"; +write_config("Snort pkg v3.2: post-install configuration saved."); /* Done with post-install, so clear flag */ unset($g['snort_postinstall']); diff --git a/config/snort/snort_preprocessors.php b/config/snort/snort_preprocessors.php index 75e4902d..9f6879ef 100755 --- a/config/snort/snort_preprocessors.php +++ b/config/snort/snort_preprocessors.php @@ -341,6 +341,10 @@ if ($_POST['ResetAll']) { $pconfig['smtp_log_rcpt_to'] = 'on'; $pconfig['smtp_log_filename'] = 'on'; $pconfig['smtp_log_email_hdrs'] = 'on'; + $pconfig['appid_preproc'] = "off"; + $pconfig['sf_appid_mem_cap'] = "256"; + $pconfig['sf_appid_statslog'] = "on"; + $pconfig['sf_appid_stats_period'] = "300"; $pconfig['sf_portscan'] = "off"; $pconfig['pscan_protocol'] = "all"; $pconfig['pscan_type'] = "all"; @@ -439,6 +443,14 @@ if ($_POST['save']) { $input_errors[] = gettext("The value for SMTP Decoder E-Mail Headers Log Depth must be between 0 and 20,480."); } + // Validate AppID parameter values if AppID Detector is enabled + if ($_POST['appid_preproc'] == 'on') { + if ($_POST['sf_appid_mem_cap'] < 32 || $_POST['sf_appid_mem_cap'] > 3000) + $input_errors[] = gettext("The value for Application ID Memory Cap must be between 32 and 3000."); + if ($_POST['sf_appid_stats_period'] < 60 || $_POST['sf_appid_stats_period'] > 3600) + $input_errors[] = gettext("The value for Application ID Stats Period must be between 60 and 3600."); + } + /* if no errors write to conf */ if (!$input_errors) { /* post new options */ @@ -481,6 +493,8 @@ if ($_POST['save']) { if ($_POST['smtp_bitenc_decode_depth'] != "") { $natent['smtp_bitenc_decode_depth'] = $_POST['smtp_bitenc_decode_depth']; }else{ $natent['smtp_bitenc_decode_depth'] = "0"; } if ($_POST['smtp_uu_decode_depth'] != "") { $natent['smtp_uu_decode_depth'] = $_POST['smtp_uu_decode_depth']; }else{ $natent['smtp_uu_decode_depth'] = "0"; } if ($_POST['smtp_email_hdrs_log_depth'] != "") { $natent['smtp_email_hdrs_log_depth'] = $_POST['smtp_email_hdrs_log_depth']; }else{ $natent['smtp_email_hdrs_log_depth'] = "1464"; } + if ($_POST['sf_appid_mem_cap'] != "") { $natent['sf_appid_mem_cap'] = $_POST['sf_appid_mem_cap']; }else{ $natent['sf_appid_mem_cap'] = "256"; } + if ($_POST['sf_appid_stats_period'] != "") { $natent['sf_appid_stats_period'] = $_POST['sf_appid_stats_period']; }else{ $natent['sf_appid_stats_period'] = "300"; } // Set SDF inspection types $natent['sdf_alert_data_type'] = implode(",",$_POST['sdf_alert_data_type']); @@ -525,6 +539,8 @@ if ($_POST['save']) { $natent['stream5_track_tcp'] = $_POST['stream5_track_tcp'] ? 'on' : 'off'; $natent['stream5_track_udp'] = $_POST['stream5_track_udp'] ? 'on' : 'off'; $natent['stream5_track_icmp'] = $_POST['stream5_track_icmp'] ? 'on' : 'off'; + $natent['appid_preproc'] = $_POST['appid_preproc'] ? 'on' : 'off'; + $natent['sf_appid_statslog'] = $_POST['sf_appid_statslog'] ? 'on' : 'off'; if (isset($id) && isset($a_nat[$id])) { $a_nat[$id] = $natent; @@ -685,14 +701,14 @@ if ($savemsg) { <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable Performance Stats"); ?></td> <td width="78%" class="vtable"><input name="perform_stat" type="checkbox" value="on" - <?php if ($pconfig['perform_stat']=="on") echo "checked"; ?>> + <?php if ($pconfig['perform_stat']=="on") echo "checked"; ?>/> <?php echo gettext("Collect Performance Statistics for this interface."); ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Protect Customized Preprocessor Rules"); ?></td> <td width="78%" class="vtable"><input name="protect_preproc_rules" type="checkbox" value="on" <?php if ($pconfig['protect_preproc_rules']=="on") echo "checked "; - if ($vrt_enabled <> 'on') echo "disabled"; ?>> + if ($vrt_enabled <> 'on') echo "disabled"; ?>/> <?php echo gettext("Check this box if you maintain customized preprocessor text rules files for this interface."); ?> <table width="100%" border="0" cellpadding="2" cellpadding="2"> <tr> @@ -709,7 +725,7 @@ if ($savemsg) { <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Auto Rule Disable"); ?></td> <td width="78%" class="vtable"><input name="preproc_auto_rule_disable" type="checkbox" value="on" - <?php if ($pconfig['preproc_auto_rule_disable']=="on") echo "checked"; ?>> + <?php if ($pconfig['preproc_auto_rule_disable']=="on") echo "checked"; ?>/> <?php echo gettext("Auto-disable text rules dependent on disabled preprocessors for this interface. "); echo gettext("Default is ") . '<strong>' . gettext("Not Checked"); ?></strong>.<br/> <table width="100%" border="0" cellpadding="2" cellpadding="2"> @@ -739,7 +755,7 @@ if ($savemsg) { <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable"); ?></td> <td width="78%" class="vtable"><input name="host_attribute_table" type="checkbox" value="on" id="host_attribute_table" onclick="host_attribute_table_enable_change();" - <?php if ($pconfig['host_attribute_table']=="on") echo "checked"; ?>> + <?php if ($pconfig['host_attribute_table']=="on") echo "checked"; ?>/> <?php echo gettext("Use a Host Attribute Table file to auto-configure applicable preprocessors. " . "Default is "); ?><strong><?php echo gettext("Not Checked"); ?></strong>.</td> </tr> @@ -823,7 +839,7 @@ if ($savemsg) { <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable"); ?></td> <td width="78%" class="vtable"><input name="http_inspect" type="checkbox" value="on" id="http_inspect" onclick="http_inspect_enable_change();" - <?php if ($pconfig['http_inspect']=="on" || empty($pconfig['http_inspect'])) echo "checked";?>> + <?php if ($pconfig['http_inspect']=="on" || empty($pconfig['http_inspect'])) echo "checked";?>/> <?php echo gettext("Use HTTP Inspect to Normalize/Decode and detect HTTP traffic and protocol anomalies. Default is ");?> <strong><?php echo gettext("Checked"); ?></strong>.</td> </tr> @@ -831,7 +847,7 @@ if ($savemsg) { <td width="22%" valign="top" class="vncell"><?php echo gettext("Proxy Alert"); ?></td> <td width="78%" class="vtable"><input name="http_inspect_proxy_alert" type="checkbox" value="on" id="http_inspect_proxy_alert" - <?php if ($pconfig['http_inspect_proxy_alert']=="on") echo "checked";?>> + <?php if ($pconfig['http_inspect_proxy_alert']=="on") echo "checked";?>/> <?php echo gettext("Enable global alerting on HTTP server proxy usage. Default is ");?> <strong><?php echo gettext("Not Checked"); ?></strong>.<br/><br/><span class="red"><strong> <?php echo gettext("Note: ") . "</strong></span>" . gettext("By adding Server Configurations below and enabling " . @@ -916,7 +932,7 @@ if ($savemsg) { <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable");?></td> <td width="78%" class="vtable"><input name="frag3_detection" type="checkbox" value="on" onclick="frag3_enable_change();" - <?php if ($pconfig['frag3_detection']=="on") echo "checked";?>> + <?php if ($pconfig['frag3_detection']=="on") echo "checked";?>/> <?php echo gettext("Use Frag3 Engine to detect IDS evasion attempts via target-based IP packet fragmentation. Default is ") . "<strong>" . gettext("Checked") . "</strong>.";?></td> </tr> @@ -984,14 +1000,14 @@ if ($savemsg) { <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable"); ?></td> <td width="78%" class="vtable"><input name="stream5_reassembly" type="checkbox" value="on" onclick="stream5_enable_change();" - <?php if ($pconfig['stream5_reassembly']=="on") echo "checked"; ?>> + <?php if ($pconfig['stream5_reassembly']=="on") echo "checked"; ?>/> <?php echo gettext("Use Stream5 session reassembly for TCP, UDP and/or ICMP traffic. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> <tr id="stream5_flushonalert_row"> <td width="22%" valign="top" class="vncell"><?php echo gettext("Flush On Alert"); ?></td> <td width="78%" class="vtable"><input name="stream5_flush_on_alert" type="checkbox" value="on" - <?php if ($pconfig['stream5_flush_on_alert']=="on") echo "checked"; ?>> + <?php if ($pconfig['stream5_flush_on_alert']=="on") echo "checked"; ?>/> <?php echo gettext("Flush a TCP stream when an alert is generated on that stream. Default is ") . "<strong>" . gettext("Not Checked") . "</strong><br/><span class=\"red\"><strong>" . gettext("Note: ") . "</strong></span>" . gettext("This parameter is for backwards compatibility.");?></td> @@ -1135,6 +1151,53 @@ if ($savemsg) { </table> </td> </tr> + + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Application ID Detection"); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable"); ?></td> + <td width="78%" class="vtable"><input name="appid_preproc" onclick="appid_preproc_enable_change();" + type="checkbox" value="on" id="appid_preproc" + <?php if ($pconfig['appid_preproc']=="on") echo "checked"; ?>/> + <?php echo gettext("Use OpenAppID to detect various applications. Default is ") . + "<strong>" . gettext("Not Checked") . "</strong>"; ?>.</td> + </tr> + <tbody id="appid_rows"> + <tr> + <td valign="top" class="vncell"><?php echo gettext("Memory Cap"); ?></td> + <td class="vtable"> + <input name="sf_appid_mem_cap" type="text" class="formfld unknown" id="sf_appid_mem_cap" size="9" + value="<?=htmlspecialchars($pconfig['sf_appid_mem_cap']);?>"> + <?php echo gettext("Memory for App ID structures. Min is ") . "<strong>" . gettext("32") . "</strong>" . + gettext(" (32 MB) and Max is ") . "<strong>" . gettext("3000") . "</strong>" . + gettext(" (3 GB) bytes.");?><br/> + <?php echo gettext("The memory cap in megabytes used by AppID internal structures " . + "in RAM. Default value is ") . "<strong>" . gettext("256") . "</strong>" . gettext(" (256 MB)."); ?><br/> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("AppID Stats Logging"); ?></td> + <td width="78%" class="vtable"> + <input name="sf_appid_statslog" type="checkbox" value="on" id="sf_appid_statslog" + <?php if ($pconfig['sf_appid_statslog']=="on") echo "checked"; ?>/> + <?php echo gettext("Enable OpenAppID statistics logging. Default is ") . + "<strong>" . gettext("Checked") . "</strong>" . gettext("."); ?><br/><br/> + <span class="red"><strong><?php echo gettext("Note: ") . "</strong></span>" . gettext("log size and retention limits for AppID Stats Logging") . + gettext(" can be set on the ") . "<a href='/snort/snort_log_mgmt.php'>" . gettext("LOG MGMT") . "</a>" . gettext(" tab.");?> </td> + </tr> + <tr> + <td valign="top" class="vncell"><?php echo gettext("AppID Stats Period"); ?></td> + <td class="vtable"> + <input name="sf_appid_stats_period" type="text" class="formfld unknown" id="sf_appid_stats_period" size="9" + value="<?=htmlspecialchars($pconfig['sf_appid_stats_period']);?>"> + <?php echo gettext("Bucket size in seconds for AppID stats. Min is ") . "<strong>" . gettext("60") . "</strong>" . + gettext(" (1 minute) and Max is ") . "<strong>" . gettext("3600") . "</strong>" . gettext(" (1 hour).");?><br/> + <?php echo gettext("The bucket size in seconds used to collecxt AppID statistics. " . + "Default value is ") . "<strong>" . gettext("300") . "</strong>" . gettext(" (5 minutes)."); ?><br/> + </td> + </tr> + </tbody> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Portscan Detection"); ?></td> </tr> @@ -1142,7 +1205,7 @@ if ($savemsg) { <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable"); ?></td> <td width="78%" class="vtable"><input name="sf_portscan" onclick="sf_portscan_enable_change();" type="checkbox" value="on" id="sf_portscan" - <?php if ($pconfig['sf_portscan']=="on") echo "checked"; ?>> + <?php if ($pconfig['sf_portscan']=="on") echo "checked"; ?>/> <?php echo gettext("Use Portscan Detection to detect various types of port scans and sweeps. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>"; ?>.</td> </tr> @@ -1287,14 +1350,14 @@ if ($savemsg) { <tr id="ftp_telnet_row_encrypted_check"> <td width="22%" valign="top" class="vncell"><?php echo gettext("Check Encrypted Traffic"); ?></td> <td width="78%" class="vtable"><input name="ftp_telnet_check_encrypted" type="checkbox" value="on" - <?php if ($pconfig['ftp_telnet_check_encrypted']=="on") echo "checked"; ?>> + <?php if ($pconfig['ftp_telnet_check_encrypted']=="on") echo "checked"; ?>/> <?php echo gettext("Continue to check an encrypted session for subsequent command to cease encryption. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> <tr id="ftp_telnet_row_encrypted_alert"> <td width="22%" valign="top" class="vncell"><?php echo gettext("Alert on Encrypted Commands"); ?></td> <td width="78%" class="vtable"><input name="ftp_telnet_alert_encrypted" type="checkbox" value="on" - <?php if ($pconfig['ftp_telnet_alert_encrypted']=="on") echo "checked"; ?>> + <?php if ($pconfig['ftp_telnet_alert_encrypted']=="on") echo "checked"; ?>/> <?php echo gettext("Alert on encrypted FTP and Telnet command channels. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>"; ?>.</td> </tr> @@ -1304,14 +1367,14 @@ if ($savemsg) { <tr id="ftp_telnet_row_normalize"> <td width="22%" valign="top" class="vncell"><?php echo gettext("Normalization"); ?></td> <td width="78%" class="vtable"><input name="ftp_telnet_normalize" type="checkbox" value="on" - <?php if ($pconfig['ftp_telnet_normalize']=="on") echo "checked"; ?>> + <?php if ($pconfig['ftp_telnet_normalize']=="on") echo "checked"; ?>/> <?php echo gettext("Normalize Telnet traffic by eliminating Telnet escape sequences. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> <tr id="ftp_telnet_row_detect_anomalies"> <td width="22%" valign="top" class="vncell"><?php echo gettext("Detect Anomalies"); ?></td> <td width="78%" class="vtable"><input name="ftp_telnet_detect_anomalies" type="checkbox" value="on" - <?php if ($pconfig['ftp_telnet_detect_anomalies']=="on") echo "checked"; ?>> + <?php if ($pconfig['ftp_telnet_detect_anomalies']=="on") echo "checked"; ?>/> <?php echo gettext("Alert on Telnet subnegotiation begin without corresponding subnegotiation end. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> @@ -1423,7 +1486,7 @@ if ($savemsg) { echo "checked"; elseif ($vrt_enabled == "off") echo "disabled"; - ?>> + ?>/> <?php echo gettext("Sensitive data searches for credit card numbers, Social Security numbers and e-mail addresses in data."); ?> <br/> <span class="red"><strong><?php echo gettext("Note: "); ?></strong></span><?php echo gettext("To enable this preprocessor, you must select the Snort VRT rules on the ") . @@ -1458,7 +1521,7 @@ if ($savemsg) { <input name="sdf_mask_output" type="checkbox" value="on" <?php if ($pconfig['sdf_mask_output'] == "on") echo "checked"; - ?>> + ?>/> <?php echo gettext("Replace all but last 4 digits of PII with \"X\"s on credit card and Social Security Numbers. ") . gettext("Default is ") . "<strong>" . gettext("Not Checked") . "</strong>."; ?> </td> @@ -1756,40 +1819,40 @@ if ($savemsg) { <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable RPC Decode and Back Orifice detector"); ?></td> <td width="78%" class="vtable"><input name="other_preprocs" type="checkbox" value="on" - <?php if ($pconfig['other_preprocs']=="on") echo "checked"; ?>> + <?php if ($pconfig['other_preprocs']=="on") echo "checked"; ?>/> <?php echo gettext("Normalize/Decode RPC traffic and detects Back Orifice traffic on the network. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable DCE/RPC2 Detection"); ?></td> <td width="78%" class="vtable"><input name="dce_rpc_2" type="checkbox" value="on" - <?php if ($pconfig['dce_rpc_2']=="on") echo "checked"; ?>> + <?php if ($pconfig['dce_rpc_2']=="on") echo "checked"; ?>/> <?php echo gettext("The DCE/RPC preprocessor detects and decodes SMB and DCE/RPC traffic. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable SIP Detection"); ?></td> <td width="78%" class="vtable"><input name="sip_preproc" type="checkbox" value="on" - <?php if ($pconfig['sip_preproc']=="on") echo "checked"; ?>> + <?php if ($pconfig['sip_preproc']=="on") echo "checked"; ?>/> <?php echo gettext("The SIP preprocessor decodes SIP traffic and detects vulnerabilities. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable GTP Detection"); ?></td> <td width="78%" class="vtable"><input name="gtp_preproc" type="checkbox" value="on" - <?php if ($pconfig['gtp_preproc']=="on") echo "checked"; ?>> + <?php if ($pconfig['gtp_preproc']=="on") echo "checked"; ?>/> <?php echo gettext("The GTP preprocessor decodes GPRS Tunneling Protocol traffic and detects intrusion attempts."); ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable SSH Detection"); ?></td> <td width="78%" class="vtable"><input name="ssh_preproc" type="checkbox" value="on" - <?php if ($pconfig['ssh_preproc']=="on") echo "checked"; ?>> + <?php if ($pconfig['ssh_preproc']=="on") echo "checked"; ?>/> <?php echo gettext("The SSH preprocessor detects various Secure Shell exploit attempts."); ?></td> </tr> <tr> <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable DNS Detection"); ?></td> <td width="78%" class="vtable"><input name="dns_preprocessor" type="checkbox" value="on" - <?php if ($pconfig['dns_preprocessor']=="on") echo "checked"; ?>> + <?php if ($pconfig['dns_preprocessor']=="on") echo "checked"; ?>/> <?php echo gettext("The DNS preprocessor decodes DNS response traffic and detects vulnerabilities. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> @@ -1797,7 +1860,7 @@ if ($savemsg) { <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable SSL Data"); ?></td> <td width="78%" class="vtable"> <input name="ssl_preproc" type="checkbox" value="on" - <?php if ($pconfig['ssl_preproc']=="on") echo "checked"; ?>> + <?php if ($pconfig['ssl_preproc']=="on") echo "checked"; ?>/> <?php echo gettext("SSL data searches for irregularities during SSL protocol exchange. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?>.</td> </tr> @@ -1808,7 +1871,7 @@ if ($savemsg) { <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable Modbus Detection"); ?></td> <td width="78%" class="vtable"> <input name="modbus_preproc" type="checkbox" value="on" - <?php if ($pconfig['modbus_preproc']=="on") echo "checked"; ?>> + <?php if ($pconfig['modbus_preproc']=="on") echo "checked"; ?>/> <?php echo gettext("Modbus is a protocol used in SCADA networks. The default port is TCP 502.") . "<br/>" . "<span class=\"red\"><strong>" . gettext("Note: ") . "</strong></span>" . gettext("If your network does not contain Modbus-enabled devices, you can leave this preprocessor disabled."); ?> @@ -1818,7 +1881,7 @@ if ($savemsg) { <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable DNP3 Detection"); ?></td> <td width="78%" class="vtable"> <input name="dnp3_preproc" type="checkbox" value="on" - <?php if ($pconfig['dnp3_preproc']=="on") echo "checked"; ?>> + <?php if ($pconfig['dnp3_preproc']=="on") echo "checked"; ?>/> <?php echo gettext("DNP3 is a protocol used in SCADA networks. The default port is TCP 20000.") . "<br/>" . "<span class=\"red\"><strong>" . gettext("Note: ") . "</strong></span>" . gettext("If your network does not contain DNP3-enabled devices, you can leave this preprocessor disabled."); ?> @@ -1833,7 +1896,7 @@ if ($savemsg) { <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 preprocessor settings to their defaults. Click OK to continue or CANCEL to quit.") . - "');\""; ?>></td> + "');\""; ?>/></td> </tr> <tr> <td width="22%" valign="top"> </td> @@ -1978,12 +2041,20 @@ function http_inspect_enable_change() { var endis = !(document.iform.http_inspect.checked); document.iform.http_inspect_memcap.disabled=endis; - // Hide the "icmp session timeout " row if stream5_track_icmp disabled - if (endis) { - document.getElementById("httpinspect_memcap_row").style.display="none"; - document.getElementById("httpinspect_maxgzipmem_row").style.display="none"; - document.getElementById("httpinspect_proxyalert_row").style.display="none"; - document.getElementById("httpinspect_engconf_row").style.display="none"; + if (!document.iform.http_inspect.checked) { + var msg = "WARNING: Disabling the http_inspect preprocessor is not recommended!\n\n"; + msg = msg + "Snort may fail to start because of other dependent preprocessors or "; + msg = msg + "rule options. Are you sure you want to disable it?\n\n"; + msg = msg + "Click OK to disable http_inspect, or CANCEL to quit."; + if (!confirm(msg)) { + document.iform.http_inspect.checked=true; + } + else { + document.getElementById("httpinspect_memcap_row").style.display="none"; + document.getElementById("httpinspect_maxgzipmem_row").style.display="none"; + document.getElementById("httpinspect_proxyalert_row").style.display="none"; + document.getElementById("httpinspect_engconf_row").style.display="none"; + } } else { document.getElementById("httpinspect_memcap_row").style.display="table-row"; @@ -2013,6 +2084,16 @@ function sf_portscan_enable_change() { } } +function appid_preproc_enable_change() { + var endis = !(document.iform.appid_preproc.checked); + + // Hide the AppID configuration rows if appid_preproc disabled + if (endis) + document.getElementById("appid_rows").style.display="none"; + else + document.getElementById("appid_rows").style.display=""; +} + function stream5_enable_change() { if (!document.iform.stream5_reassembly.checked) { var msg = "WARNING: Stream5 is a critical preprocessor, and disabling it is not recommended! "; @@ -2020,7 +2101,8 @@ function stream5_enable_change() { msg = msg + " SMTP\t\tPOP\t\tSIP\n"; msg = msg + " SENSITIVE_DATA\tSF_PORTSCAN\tDCE/RPC 2\n"; msg = msg + " IMAP\t\tDNS\t\tSSL\n"; - msg = msg + " GTP\t\tDNP3\t\tMODBUS\n\n"; + msg = msg + " GTP\t\tDNP3\t\tMODBUS\n"; + msg = msg + " APP_ID\n\n"; msg = msg + "Snort may fail to start because of other preprocessors or rule options dependent on Stream5. "; msg = msg + "Are you sure you want to disable it?\n\n"; msg = msg + "Click OK to disable Stream5, or CANCEL to quit."; @@ -2039,6 +2121,7 @@ function stream5_enable_change() { document.iform.dns_preprocessor.checked=false; document.iform.modbus_preproc.checked=false; document.iform.dnp3_preproc.checked=false; + document.iform.appid_preproc.checked=false; document.iform.sf_portscan.checked=false; sf_portscan_enable_change(); } @@ -2147,6 +2230,7 @@ function smtp_enable_change() { function enable_change_all() { http_inspect_enable_change(); sf_portscan_enable_change(); + appid_preproc_enable_change(); // -- Enable/Disable Host Attribute Table settings -- host_attribute_table_enable_change(); diff --git a/config/snort/snort_rules.php b/config/snort/snort_rules.php index 681c691f..b9050b35 100755 --- a/config/snort/snort_rules.php +++ b/config/snort/snort_rules.php @@ -36,6 +36,7 @@ require_once("/usr/local/pkg/snort/snort.inc"); global $g, $rebuild_rules; $snortdir = SNORTDIR; +$snortbindir = SNORT_PBI_BINDIR; $rules_map = array(); $categories = array(); $pconfig = array(); @@ -400,7 +401,7 @@ elseif ($_POST['save']) { $rebuild_rules = false; $output = ""; $retcode = ""; - exec("/usr/local/bin/snort -T -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf 2>&1", $output, $retcode); + exec("{$snortbindir}snort -T -c {$snortdir}/snort_{$snort_uuid}_{$if_real}/snort.conf 2>&1", $output, $retcode); if (intval($retcode) != 0) { $error = ""; $start = count($output); @@ -412,8 +413,7 @@ elseif ($_POST['save']) { else { /* Soft-restart Snort to live-load new rules */ snort_reload_config($a_rule[$id]); - $savemsg = gettext("Custom rules validated successfully and have been saved to the Snort configuration files. "); - $savemsg .= gettext("Any active Snort process on this interface has been signalled to live-load the new rules."); + $savemsg = gettext("Custom rules validated successfully and any active Snort process on this interface has been signalled to live-load the new rules."); } clear_subsystem_dirty('snort_rules'); @@ -443,6 +443,9 @@ else if ($_POST['apply']) { // Sync to configured CARP slaves if any are enabled snort_sync_on_changes(); + + if (snort_is_running($snort_uuid, $if_real)) + $savemsg = gettext("Snort is 'live-reloading' the new rule set."); } include_once("head.inc"); diff --git a/config/snort/snort_sid_mgmt.php b/config/snort/snort_sid_mgmt.php index ea1a5b99..016cc96d 100644 --- a/config/snort/snort_sid_mgmt.php +++ b/config/snort/snort_sid_mgmt.php @@ -294,6 +294,11 @@ if ($savemsg) { <div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> <tbody> + <?php if ($g['platform'] == "nanobsd") : ?> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("SID auto-management is not supported on NanoBSD installs"); ?></td> + </tr> + <?php else: ?> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Settings"); ?></td> </tr> @@ -568,6 +573,7 @@ if ($savemsg) { <?=gettext("Remember to save changes before exiting this page"); ?> </td> </tr> + <?php endif; ?> </tbody> </table> </div> @@ -576,8 +582,9 @@ if ($savemsg) { </table> </form> - <?php include("fend.inc"); ?> + +<?php if ($g['platform'] != "nanobsd") : ?> <script type="text/javascript"> function enable_sid_conf() { @@ -593,5 +600,7 @@ function enable_sid_conf() { enable_sid_conf(); </script> +<?php endif; ?> + </body> </html> diff --git a/config/squid3/34/squid.inc b/config/squid3/34/squid.inc index 87232c2b..a2917515 100755 --- a/config/squid3/34/squid.inc +++ b/config/squid3/34/squid.inc @@ -42,14 +42,12 @@ if(!function_exists("filter_configure")) require_once("filter.inc"); $shortcut_section = "squid"; -$pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); if (is_dir('/usr/pbi/squid-' . php_uname("m"))) { - if ($pfs_version == 2.2) - define('SQUID_LOCALBASE', '/usr/pbi/squid-' . php_uname("m")."/local"); - else - define('SQUID_LOCALBASE', '/usr/pbi/squid-' . php_uname("m")); + define('SQUID_BASE', '/usr/pbi/squid-' . php_uname("m")); + define('SQUID_LOCALBASE', SQUID_BASE . "/local"); } else { - define('SQUID_LOCALBASE','/usr/local'); + define('SQUID_BASE', '/usr/local'); + define('SQUID_LOCALBASE', '/usr/local'); } define('SQUID_CONFBASE', SQUID_LOCALBASE .'/etc/squid'); @@ -138,12 +136,12 @@ function squid_dash_z($cache_action='none') { if(!is_dir($cachedir.'/00/')) { log_error("Creating squid cache subdirs in $cachedir"); - mwexec(SQUID_LOCALBASE. "/sbin/squid -k shutdown -f " . SQUID_CONFFILE); + mwexec(SQUID_BASE. "/sbin/squid -k shutdown -f " . SQUID_CONFFILE); sleep(5); - mwexec(SQUID_LOCALBASE. "/sbin/squid -k kill -f " . SQUID_CONFFILE); + mwexec(SQUID_BASE. "/sbin/squid -k kill -f " . SQUID_CONFFILE); // Double check permissions here, should be safe to recurse cache dir if it's small here. mwexec("/usr/sbin/chown -R proxy:proxy $cachedir"); - mwexec(SQUID_LOCALBASE. "/sbin/squid -z -f " . SQUID_CONFFILE); + mwexec(SQUID_BASE. "/sbin/squid -z -f " . SQUID_CONFFILE); } if(file_exists("/var/squid/cache/swap.state")) { @@ -347,11 +345,11 @@ function squid_install_command() { if (!is_service_running('squid')) { update_status("Starting... One moment please..."); log_error("Starting Squid"); - mwexec_bg(SQUID_LOCALBASE. "/sbin/squid -f " . SQUID_CONFFILE); + mwexec_bg(SQUID_BASE. "/sbin/squid -f " . SQUID_CONFFILE); } else { update_status("Reloading Squid for configuration sync... One moment please..."); log_error("Reloading Squid for configuration sync"); - mwexec_bg(SQUID_LOCALBASE. "/sbin/squid -k reconfigure -f " . SQUID_CONFFILE); + mwexec_bg(SQUID_BASE. "/sbin/squid -k reconfigure -f " . SQUID_CONFFILE); } /* restart proxy alarm scripts */ @@ -736,7 +734,7 @@ function squid_install_cron($should_install) { $rotate_job_id=-1; $swapstate_job_id=-1; $cron_cmd=($settings['clear_cache']=='on' ? "/usr/local/pkg/swapstate_check.php clean; " : ""); - $cron_cmd .= SQUID_LOCALBASE."/sbin/squid -k rotate -f " . SQUID_CONFFILE; + $cron_cmd .= SQUID_BASE."/sbin/squid -k rotate -f " . SQUID_CONFFILE; $need_write = false; foreach($config['cron']['item'] as $item) { if(strstr($item['task_name'], "squid_rotate_logs")) { @@ -1342,7 +1340,7 @@ function squid_resync_antivirus(){ #fix perl path on clwarn.cgi $clwarn_file_new=file_get_contents($clwarn_file); $c_pattern[]="@/usr/\S+/perl@"; - $c_replacement[]=SQUID_LOCALBASE."/bin/perl"; + $c_replacement[]=SQUID_BASE."/bin/perl"; /*$c_pattern[]="@redirect \S+/clwarn.cgi@"; $gui_proto=$config['system']['webgui']['protocol']; $gui_port=$config['system']['webgui']['port']; @@ -1440,15 +1438,12 @@ EOF; #Check clamav database if (count(glob("/var/db/clamav/*d"))==0){ log_error("Squid - Missing /var/db/clamav/*.cvd or *.cld files. Running freshclam on background."); - mwexec_bg(SQUID_LOCALBASE."/bin/freshclam"); - } - #check startup scripts on pfsense > 2.1 - if (preg_match("/usr.pbi/",SQUID_LOCALBASE)){ - $rcd_files = scandir(SQUID_LOCALBASE."/etc/rc.d"); - foreach($rcd_files as $rcd_file) - if (!file_exists("/usr/local/etc/rc.d/{$rcd_file}")) - symlink (SQUID_LOCALBASE."/etc/rc.d/{$rcd_file}","/usr/local/etc/rc.d/{$rcd_file}"); + mwexec_bg(SQUID_BASE."/bin/freshclam"); } + $rcd_files = scandir(SQUID_LOCALBASE."/etc/rc.d"); + foreach($rcd_files as $rcd_file) + if (!file_exists("/usr/local/etc/rc.d/{$rcd_file}")) + symlink (SQUID_LOCALBASE."/etc/rc.d/{$rcd_file}","/usr/local/etc/rc.d/{$rcd_file}"); #write advanced icap config files file_put_contents(SQUID_LOCALBASE."/etc/c-icap/squidclamav.conf",base64_decode($antivirus_config['squidclamav']),LOCK_EX); @@ -1898,12 +1893,12 @@ function squid_resync($via_rpc="no") { if (!is_service_running('squid')) { log_error("Starting Squid"); - mwexec(SQUID_LOCALBASE . "/sbin/squid -f " . SQUID_CONFFILE); + mwexec(SQUID_BASE . "/sbin/squid -f " . SQUID_CONFFILE); } else { if (!isset($boot_process)){ log_error("Reloading Squid for configuration sync"); - mwexec(SQUID_LOCALBASE . "/sbin/squid -k reconfigure -f " . SQUID_CONFFILE); + mwexec(SQUID_BASE . "/sbin/squid -k reconfigure -f " . SQUID_CONFFILE); } } @@ -2268,18 +2263,18 @@ function squid_write_rcfile() { /* Declare a variable for the SQUID_CONFFILE constant. */ /* Then the variable can be referenced easily in the Heredoc text that generates the rc file. */ $squid_conffile_var = SQUID_CONFFILE; - $squid_local_base = SQUID_LOCALBASE; + $squid_base = SQUID_BASE; $rc = array(); $rc['file'] = 'squid.sh'; $rc['start'] = <<<EOD if [ -z "`ps auxw | grep "[s]quid "|awk '{print $2}'`" ];then - {$squid_local_base}/sbin/squid -f {$squid_conffile_var} + {$squid_base}/sbin/squid -f {$squid_conffile_var} fi EOD; $rc['stop'] = <<<EOD -{$squid_local_base}/sbin/squid -k shutdown -f {$squid_conffile_var} +{$squid_base}/sbin/squid -k shutdown -f {$squid_conffile_var} # Just to be sure... sleep 5 @@ -2294,9 +2289,9 @@ killall pinger 2>/dev/null EOD; $rc['restart'] = <<<EOD if [ -z "`ps auxw | grep "[s]quid "|awk '{print $2}'`" ];then - {$squid_local_base}/sbin/squid -f {$squid_conffile_var} + {$squid_base}/sbin/squid -f {$squid_conffile_var} else - {$squid_local_base}/sbin/squid -k reconfigure -f {$squid_conffile_var} + {$squid_base}/sbin/squid -k reconfigure -f {$squid_conffile_var} fi EOD; diff --git a/config/squid3/34/swapstate_check.php b/config/squid3/34/swapstate_check.php index b9f51ec1..7a7ccd27 100644 --- a/config/squid3/34/swapstate_check.php +++ b/config/squid3/34/swapstate_check.php @@ -30,17 +30,6 @@ require_once('config.inc'); require_once('util.inc'); require_once('squid.inc'); -$pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); -if (is_dir('/usr/pbi/squid-' . php_uname("m"))) { - if ($pfs_version == 2.2) - define('SQUID_LOCALBASE', '/usr/pbi/squid-' . php_uname("m")."/local"); - else - define('SQUID_LOCALBASE', '/usr/pbi/squid-' . php_uname("m")); -} else { - define('SQUID_LOCALBASE','/usr/local'); -} - - $settings = $config['installedpackages']['squidcache']['config'][0]; // Only check the cache if Squid is actually caching. // If there is no cache then quietly do nothing. diff --git a/config/suricata/suricata.inc b/config/suricata/suricata.inc index af0b0da2..66c1e799 100644 --- a/config/suricata/suricata.inc +++ b/config/suricata/suricata.inc @@ -44,47 +44,13 @@ require_once("services.inc"); require_once("service-utils.inc"); require_once("pkg-utils.inc"); require_once("filter.inc"); +require("/usr/local/pkg/suricata/suricata_defs.inc"); global $g, $config; // Suricata GUI needs some extra PHP memory space to manipulate large rules arrays ini_set("memory_limit", "256M"); -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 -$pf_version=substr(trim(file_get_contents("/etc/version")),0,3); -if ($pf_version >= 2.2) - define('SURICATADIR', '/usr/pbi/suricata-' . php_uname("m") . '/local/etc/suricata/'); -else - define('SURICATADIR', '/usr/pbi/suricata-' . php_uname("m") . '/etc/suricata/'); - -define('SURICATALOGDIR', '/var/log/suricata/'); -define('RULES_UPD_LOGFILE', SURICATALOGDIR . 'suricata_rules_update.log'); -define('ENFORCING_RULES_FILENAME', 'suricata.rules'); -define('FLOWBITS_FILENAME', 'flowbit-required.rules'); -define('SID_MODS_PATH', '/var/db/suricata/sidmods/'); -define('IPREP_PATH', '/var/db/suricata/iprep/'); - -// Rule set download filenames and prefixes -define('ET_DNLD_FILENAME', 'emerging.rules.tar.gz'); -define('ETPRO_DNLD_FILENAME', 'etpro.rules.tar.gz'); -define('GPLV2_DNLD_FILENAME', 'community-rules.tar.gz'); -define('VRT_FILE_PREFIX', 'snort_'); -define('GPL_FILE_PREFIX', 'GPLv2_'); -define('ET_OPEN_FILE_PREFIX', 'emerging-'); -define('ET_PRO_FILE_PREFIX', 'etpro-'); - function suricata_generate_id() { global $config; @@ -139,10 +105,11 @@ function suricata_barnyard_start($suricatacfg, $if_real) { $suricata_uuid = $suricatacfg['uuid']; $suricatadir = SURICATADIR . "suricata_{$suricata_uuid}_{$if_real}"; $suricatalogdir = SURICATALOGDIR . "suricata_{$if_real}{$suricata_uuid}"; + $suricatabindir = SURICATA_PBI_BINDIR; if ($suricatacfg['barnyard_enable'] == 'on') { log_error("[Suricata] Barnyard2 START for {$suricatacfg['descr']}({$if_real})..."); - 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"); + mwexec_bg("{$suricatabindir}barnyard2 -r {$suricata_uuid} -f unified2.alert --pid-path {$g['varrun_path']} --nolock-pidfile -c {$suricatadir}/barnyard2.conf -d {$suricatalogdir} -D -q"); } } @@ -151,10 +118,11 @@ function suricata_start($suricatacfg, $if_real) { $suricatadir = SURICATADIR; $suricata_uuid = $suricatacfg['uuid']; + $suricatabindir = SURICATA_PBI_BINDIR; if ($suricatacfg['enable'] == 'on') { log_error("[Suricata] Suricata START for {$suricatacfg['descr']}({$if_real})..."); - 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"); + mwexec_bg("{$suricatabindir}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; @@ -163,6 +131,61 @@ function suricata_start($suricatacfg, $if_real) { suricata_barnyard_start($suricatacfg, $if_real); } +function suricata_start_all_interfaces($background=FALSE) { + + /*************************************************************/ + /* This function starts all configured and enabled Suricata */ + /* interfaces. */ + /*************************************************************/ + + global $g, $config; + + /* do nothing if no Suricata interfaces active */ + if (!is_array($config['installedpackages']['suricata']['rule'])) + return; + + foreach ($config['installedpackages']['suricata']['rule'] as $suricatacfg) { + if ($suricatacfg['enable'] != 'on') + continue; + suricata_start($suricatacfg, get_real_interface($suricatacfg['interface'])); + } +} + +function suricata_stop_all_interfaces() { + + /*************************************************************/ + /* This function stops all configured Suricata interfaces. */ + /*************************************************************/ + + global $g, $config; + + /* do nothing if no Suricata interfaces active */ + if (!is_array($config['installedpackages']['suricata']['rule'])) + return; + + foreach ($config['installedpackages']['suricata']['rule'] as $suricatacfg) { + suricata_stop($suricatacfg, get_real_interface($suricatacfg['interface'])); + } +} + +function suricata_restart_all_interfaces() { + + /*************************************************************/ + /* This function stops all configured Suricata interfaces */ + /* and restarts enabled Suricata interfaces. */ + /*************************************************************/ + + global $g, $config; + + /* do nothing if no Suricata interfaces active */ + if (!is_array($config['installedpackages']['suricata']['rule'])) + return; + + suricata_stop_all_interfaces(); + sleep(2); + suricata_start_all_interfaces(TRUE); +} + function suricata_reload_config($suricatacfg, $signal="USR2") { /**************************************************************/ @@ -492,17 +515,61 @@ function suricata_build_list($suricatacfg, $listname = "", $passlist = false, $e return $valresult; } -function suricata_rules_up_install_cron($should_install=true) { +function suricata_cron_job_exists($crontask, $match_time=FALSE, $minute="0", $hour="*", $monthday="*", $month="*", $weekday="*", $who="root") { + + /************************************************************ + * This function iterates the cron[] array in the config * + * to determine if the passed $crontask entry exists. It * + * returns TRUE if the $crontask already exists, or FALSE * + * if there is no match. * + * * + * The $match_time flag, when set, causes a test of the * + * configured task execution times along with the task * + * when checking for a match. * + * * + * We use this to prevent unneccessary config writes if * + * the $crontask already exists. * + ************************************************************/ + global $config, $g; - // Remove any existing job first - install_cron_job("suricata_check_for_rule_updates.php", false); + if (!is_array($config['cron'])) + $config['cron'] = array(); + if (!is_array($config['cron']['item'])) + $config['cron']['item'] = array(); + + foreach($config['cron']['item'] as $item) { + if(strpos($item['command'], $crontask) !== FALSE) { + if ($match_time) { + if ($item['minute'] != $minute) + return FALSE; + if ($item['hour'] != $hour) + return FALSE; + if ($item['mday'] != $monthday) + return FALSE; + if ($item['month'] != $month) + return FALSE; + if ($item['wday'] != $weekday) + return FALSE; + if ($item['who'] != $who) + return FALSE; + } + return TRUE; + } + } + return FALSE; +} - // If called with FALSE as argument, then we're done - if ($should_install == FALSE) - return; +function suricata_rules_up_install_cron($should_install=true) { + global $config, $g; - $command = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_check_for_rule_updates.php"; + // If called with FALSE as argument, then we're removing + // the existing job. + if ($should_install == FALSE) { + if (suricata_cron_job_exists("suricata_check_for_rule_updates.php", FALSE)) + install_cron_job("suricata_check_for_rule_updates.php", false); + return; + } // Get auto-rule update parameter from configuration $suricata_rules_up_info_ck = $config['installedpackages']['suricata']['config'][0]['autoruleupdate']; @@ -568,12 +635,32 @@ function suricata_rules_up_install_cron($should_install=true) { $suricata_rules_up_wday = "*"; } - // System call to manage the cron job. - 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"); + // Construct the basic cron command task + $command = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_check_for_rule_updates.php"; + + // If there are no changes in the cron job command string from the existing job, then exit + if (suricata_cron_job_exists($command, TRUE, $suricata_rules_up_min, $suricata_rules_up_hr, $suricata_rules_up_mday, $suricata_rules_up_month, $suricata_rules_up_wday, "root")) + return; + + // Else install the new or updated cron job + if ($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=true) { + // See if simply removing existing "loglimit" job for Suricata + if ($should_install == FALSE) { + if (suricata_cron_job_exists("suricata/suricata_check_cron_misc.inc", FALSE)) + install_cron_job("suricata_check_cron_misc.inc", false); + return; + } + + // If there are no changes in the cron job command string from the existing job, then exit. + if ($should_install && suricata_cron_job_exists("/usr/local/pkg/suricata/suricata_check_cron_misc.inc", TRUE, "*/5")) + return; + + // Else install the new or updated cron job install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_check_cron_misc.inc", $should_install, "*/5"); } @@ -581,6 +668,13 @@ function suricata_rm_blocked_install_cron($should_install) { global $config, $g; $suri_pf_table = SURICATA_PF_TABLE; + // See if simply removing existing "expiretable" job for Suricata + if ($should_install == FALSE) { + if (suricata_cron_job_exists("{$suri_pf_table}", FALSE)) + install_cron_job("{$suri_pf_table}", false); + return; + } + $suricata_rm_blocked_info_ck = $config['installedpackages']['suricata']['config'][0]['rm_blocked']; if ($suricata_rm_blocked_info_ck == "15m_b") { @@ -664,13 +758,15 @@ function suricata_rm_blocked_install_cron($should_install) { $suricata_rm_blocked_expire = "2419200"; } - // First, remove any existing cron task for "rm_blocked" hosts - install_cron_job("{$suri_pf_table}", false); + // Construct the basic cron command task + $command = "/usr/bin/nice -n20 /sbin/pfctl -q -t {$suri_pf_table} -T expire {$suricata_rm_blocked_expire}"; - // Now add or update the cron task for "rm_blocked" hosts - // if enabled. + // If there are no changes in the cron job command string from the existing job, then exit. + if (suricata_cron_job_exists($command, TRUE, $suricata_rm_blocked_min, $suricata_rm_blocked_hr, $suricata_rm_blocked_mday, $suricata_rm_blocked_month, $suricata_rm_blocked_wday, "root")) + return; + + // Else install the new or updated cron job if ($should_install) { - $command = "/usr/bin/nice -n20 /sbin/pfctl -q -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"); } } @@ -681,25 +777,22 @@ function sync_suricata_package_config() { $suricatadir = SURICATADIR; $rcdir = RCFILEPREFIX; - conf_mount_rw(); - // Do not start config build if there are no Suricata-configured interfaces - if (!is_array($config['installedpackages']['suricata']) || !is_array($config['installedpackages']['suricata']['rule'])) { - @unlink("{$rcdir}suricata.sh"); - conf_mount_ro(); + if (!is_array($config['installedpackages']['suricata']['rule']) || count($config['installedpackages']['suricata']['rule']) < 1) return; - } $suricataconf = $config['installedpackages']['suricata']['rule']; foreach ($suricataconf as $value) { - $if_real = get_real_interface($value['interface']); + /* Skip configuration of any disabled interface */ + if ($value['enable'] != 'on') + continue; // create a suricata.yaml file for interface suricata_generate_yaml($value); // create barnyard2.conf file for interface if ($value['barnyard_enable'] == 'on') - suricata_generate_barnyard2_conf($value, $if_real); + suricata_generate_barnyard2_conf($value, get_real_interface($value['interface'])); } // create suricata bootup file suricata.sh @@ -707,18 +800,16 @@ function sync_suricata_package_config() { // setup the log directory size check job if enabled suricata_loglimit_install_cron(true); + // setup the suricata rules update job if enabled 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); - configure_cron(); - // Do not attempt package sync if reinstalling package or booting if (!isset($g['suricata_postinstall']) && !$g['booting']) suricata_sync_on_changes(); - - conf_mount_ro(); } function suricata_load_suppress_sigs($suricatacfg, $track_by=false) { @@ -853,19 +944,19 @@ function suricata_post_delete_logs($suricata_uuid = 0) { // Keep most recent file unset($filelist[count($filelist) - 1]); foreach ($filelist as $file) - @unlink($file); + unlink_if_exists($file); /* Clean-up Barnyard2 archived files if any exist */ $filelist = glob("{$suricata_log_dir}/barnyard2/archive/unified2.alert.*"); foreach ($filelist as $file) - @unlink($file); + unlink_if_exists($file); /* Clean-up packet capture files if any exist */ $filelist = glob("{$suricata_log_dir}/log.pcap.*"); // Keep most recent file unset($filelist[count($filelist) - 1]); foreach ($filelist as $file) - @unlink($file); + unlink_if_exists($file); unset($filelist); } } @@ -1693,7 +1784,7 @@ function suricata_sid_mgmt_auto_categories($suricatacfg, $log_results = FALSE) { /****************************************************/ global $config; - $suricata_sidmods_dir = SID_MODS_PATH; + $suricata_sidmods_dir = SURICATA_SID_MODS_PATH; $sid_mods = array(); $enables = array(); $disables = array(); @@ -2232,7 +2323,7 @@ function suricata_process_enablesid(&$rule_map, $suricatacfg, $log_results = FAL /* $rule_map array */ /**********************************************/ - $suricata_sidmods_dir = SID_MODS_PATH; + $suricata_sidmods_dir = SURICATA_SID_MODS_PATH; $suricatalogdir = SURICATALOGDIR; $sid_mods = array(); @@ -2279,7 +2370,7 @@ function suricata_process_disablesid(&$rule_map, $suricatacfg, $log_results = FA /* $rule_map array */ /**********************************************/ - $suricata_sidmods_dir = SID_MODS_PATH; + $suricata_sidmods_dir = SURICATA_SID_MODS_PATH; $suricatalogdir = SURICATALOGDIR; $sid_mods = array(); @@ -2326,7 +2417,7 @@ function suricata_process_modifysid(&$rule_map, $suricatacfg, $log_results = FAL /* $rule_map array */ /**********************************************/ - $suricata_sidmods_dir = SID_MODS_PATH; + $suricata_sidmods_dir = SURICATA_SID_MODS_PATH; $suricatalogdir = SURICATALOGDIR; $sid_mods = array(); @@ -2550,7 +2641,7 @@ function suricata_prepare_rule_files($suricatacfg, $suricatacfgdir) { $suricatadir = SURICATADIR; $flowbit_rules_file = FLOWBITS_FILENAME; - $suricata_enforcing_rules_file = ENFORCING_RULES_FILENAME; + $suricata_enforcing_rules_file = SURICATA_ENFORCING_RULES_FILENAME; $enabled_rules = array(); $enabled_files = array(); $all_rules = array(); @@ -2749,7 +2840,7 @@ function suricata_write_enforcing_rules_file($rule_map, $rule_path) { /* rules file will be written. */ /************************************************/ - $rule_file = "/" . ENFORCING_RULES_FILENAME; + $rule_file = "/" . SURICATA_ENFORCING_RULES_FILENAME; // See if we were passed a directory or full // filename to write the rules to, and adjust @@ -2798,6 +2889,7 @@ function suricata_create_rc() { $suricatadir = SURICATADIR; $suricatalogdir = SURICATALOGDIR; + $suricatabindir = SURICATA_PBI_BINDIR; $rcdir = RCFILEPREFIX; // If no interfaces are configured for Suricata, exit @@ -2815,7 +2907,7 @@ function suricata_create_rc() { // the shell script. foreach ($suricataconf as $value) { // Skip disabled Suricata interfaces - if ($value['enable'] <> 'on') + if ($value['enable'] != 'on') continue; $suricata_uuid = $value['uuid']; $if_real = get_real_interface($value['interface']); @@ -2828,14 +2920,10 @@ function suricata_create_rc() { 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 SOFT RESTART for {$value['descr']}({$suricata_uuid}_{$if_real})..." - /bin/pkill -HUP \$pid - else + if [ -z \$pid ]; then /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 + {$suricatabindir}/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 > /dev/null 2>&1 fi - EOE; $stop_barnyard2 = <<<EOE @@ -2851,8 +2939,8 @@ EOE; break fi done - if [ -f /var/run/barnyard2_{$if_real}{$suricata_uuid}.pid ]; then - /bin/rm /var/run/barnyard2_{$if_real}{$suricata_uuid}.pid + if [ -f {$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid ]; then + /bin/rm {$g['varrun_path']}/barnyard2_{$if_real}{$suricata_uuid}.pid fi else pid=`/bin/pgrep -fn "barnyard2 -r {$suricata_uuid} "` @@ -2868,7 +2956,6 @@ EOE; done fi fi - EOE; if ($value['barnyard_enable'] == 'on') $start_barnyard2 = $start_barnyard; @@ -2877,25 +2964,20 @@ EOE; $start_suricata_iface_start[] = <<<EOE -###### For Each Iface - # Start suricata and barnyard2 + ## Start suricata on {$value['descr']} ({$if_real}) ## if [ ! -f {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid ]; then pid=`/bin/pgrep -fn "suricata -i {$if_real} "` else pid=`/bin/pgrep -F {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid` fi - if [ ! -z \$pid ]; then - /usr/bin/logger -p daemon.info -i -t SuricataStartup "Suricata SOFT RESTART for {$value['descr']}({$suricata_uuid}_{$if_real})..." - /bin/pkill -USR2 \$pid - else + if [ -z \$pid ]; then /usr/bin/logger -p daemon.info -i -t SuricataStartup "Suricata START for {$value['descr']}({$suricata_uuid}_{$if_real})..." - /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 + {$suricatabindir}suricata -i {$if_real} -D -c {$suricatadir}suricata_{$suricata_uuid}_{$if_real}/suricata.yaml --pidfile {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid > /dev/null 2>&1 fi - sleep 2 + sleep 1 {$start_barnyard2} - EOE; $start_suricata_iface_stop[] = <<<EOE @@ -2912,8 +2994,8 @@ EOE; break fi done - if [ -f /var/run/suricata_{$if_real}{$suricata_uuid}.pid ]; then - /bin/rm /var/run/suricata_{$if_real}{$suricata_uuid}.pid + if [ -f {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid ]; then + /bin/rm {$g['varrun_path']}/suricata_{$if_real}{$suricata_uuid}.pid fi else pid=`/bin/pgrep -fn "suricata -i {$if_real} "` @@ -2931,9 +3013,8 @@ EOE; fi fi - sleep 2 + sleep 1 {$stop_barnyard2} - EOE; } @@ -2948,7 +3029,15 @@ EOE; ######## Start of main suricata.sh rc_start() { + + ### Lock out other start signals until we are done + /usr/bin/touch {$g['varrun_path']}/suricata_pkg_starting.lck {$rc_start} + + ### Remove the lock since we have started all interfaces + if [ -f {$g['varrun_path']}/suricata_pkg_starting.lck ]; then + /bin/rm {$g['varrun_path']}/suricata_pkg_starting.lck + fi } rc_stop() { @@ -2957,7 +3046,11 @@ rc_stop() { case $1 in start) - rc_start + if [ ! -f {$g['varrun_path']}/suricata_pkg_starting.lck ]; then + rc_start + else + /usr/bin/logger -p daemon.info -i -t SuricataStartup "Ignoring additional START command since Suricata is already starting..." + fi ;; stop) rc_stop @@ -3108,7 +3201,7 @@ function suricata_generate_yaml($suricatacfg) { $suricatadir = SURICATADIR; $suricatalogdir = SURICATALOGDIR; $flowbit_rules_file = FLOWBITS_FILENAME; - $suricata_enforcing_rules_file = ENFORCING_RULES_FILENAME; + $suricata_enforcing_rules_file = SURICATA_ENFORCING_RULES_FILENAME; $if_real = get_real_interface($suricatacfg['interface']); $suricata_uuid = $suricatacfg['uuid']; $suricatacfgdir = "{$suricatadir}suricata_{$suricata_uuid}_{$if_real}"; @@ -3237,7 +3330,7 @@ function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $userna /*************************************************/ /* Send over any auto-SID management files */ /*************************************************/ - $sid_files = glob(SID_MODS_PATH . '*'); + $sid_files = glob(SURICATA_SID_MODS_PATH . '*'); foreach ($sid_files as $file) { $content = base64_encode(file_get_contents($file)); $payload = "@file_put_contents('{$file}', base64_decode('{$content}'));"; @@ -3332,7 +3425,9 @@ function suricata_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $port, $userna unset(\$g["suricata_postinstall"]); log_error(gettext("[suricata] XMLRPC pkg CARP sync: Generating suricata.yaml file using Master Host settings...")); \$rebuild_rules = true; + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); \$rebuild_rules = false; {$suricatastart} log_error(gettext("[suricata] XMLRPC pkg CARP sync process on this host is complete...")); diff --git a/config/suricata/suricata.priv.inc b/config/suricata/suricata.priv.inc index efa71366..84ede368 100644 --- a/config/suricata/suricata.priv.inc +++ b/config/suricata/suricata.priv.inc @@ -36,10 +36,16 @@ $priv_list['page-services-suricata']['match'][] = "suricata/suricata_rules_flowb $priv_list['page-services-suricata']['match'][] = "suricata/suricata_rulesets.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'][] = "suricata/suricata_ip_list_mgmt.php*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_ip_reputation.php*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_iprep_list_browser.php*"; $priv_list['page-services-suricata']['match'][] = "pkg_edit.php?xml=suricata/suricata.xml*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_check_cron_misc.inc*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata_yaml_template.inc*"; $priv_list['page-services-suricata']['match'][] = "suricata/suricata.inc*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_defs.inc*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_geoipupdate.php*"; +$priv_list['page-services-suricata']['match'][] = "suricata/suricata_etiqrisk_update.php*"; $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*"; diff --git a/config/suricata/suricata.xml b/config/suricata/suricata.xml index 995ed900..3b3bf723 100644 --- a/config/suricata/suricata.xml +++ b/config/suricata/suricata.xml @@ -42,7 +42,7 @@ <description>Suricata IDS/IPS Package</description> <requirements>None</requirements> <name>suricata</name> - <version>2.0.3 pkg v2.0.2</version> + <version>2.0.4 pkg v2.1</version> <title>Services: Suricata IDS</title> <include_file>/usr/local/pkg/suricata/suricata.inc</include_file> <menu> @@ -108,6 +108,21 @@ <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_defs.inc</item> + <prefix>/usr/local/pkg/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_geoipupdate.php</item> + <prefix>/usr/local/pkg/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_etiqrisk_update.php</item> + <prefix>/usr/local/pkg/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> <item>https://packages.pfsense.org/packages/config/suricata/suricata_download_updates.php</item> <prefix>/usr/local/www/suricata/</prefix> <chmod>0755</chmod> @@ -223,6 +238,21 @@ <chmod>0755</chmod> </additional_files_needed> <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_ip_list_mgmt.php</item> + <prefix>/usr/local/www/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_ip_reputation.php</item> + <prefix>/usr/local/www/suricata/</prefix> + <chmod>0755</chmod> + </additional_files_needed> + <additional_files_needed> + <item>https://packages.pfsense.org/packages/config/suricata/suricata_iprep_list_browser.php</item> + <prefix>/usr/local/www/suricata/</prefix> + <chmod>0755</chmod> + </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> diff --git a/config/suricata/suricata_alerts.js b/config/suricata/suricata_alerts.js index b6a5d3c3..e56b586d 100644 --- a/config/suricata/suricata_alerts.js +++ b/config/suricata/suricata_alerts.js @@ -18,7 +18,7 @@ function suricata_alerts_fetch_new_rules_callback(callback_data) { 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>'; + line += '<td class="listMRr"><div style="display: fixed; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2em; max-height: 2.4em; overflow: hidden; text-overflow: ellipsis;" title="' + row_split[4] + '">' + row_split[4] + '</div></td>'; new_data_to_add[new_data_to_add.length] = line; } suricata_alerts_update_div_rows(new_data_to_add); diff --git a/config/suricata/suricata_alerts.php b/config/suricata/suricata_alerts.php index 57ccbe27..f151e173 100644 --- a/config/suricata/suricata_alerts.php +++ b/config/suricata/suricata_alerts.php @@ -43,6 +43,7 @@ require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); +global $g, $config; $supplist = array(); $suri_pf_table = SURICATA_PF_TABLE; $filterlogentries = FALSE; @@ -127,7 +128,9 @@ function suricata_add_supplist_entry($suppress) { /* and return true; otherwise return false. */ if ($found_list) { write_config(); + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); return true; } else @@ -232,6 +235,7 @@ if ($_POST['filterlogentries_submit']) { if ($_POST['filterlogentries_clear']) { $filterfieldsarray = array(); + $filterlogentries = TRUE; } if ($_POST['save']) { @@ -377,11 +381,11 @@ if ($_POST['delete']) { } if ($_POST['download']) { - $save_date = exec('/bin/date "+%Y-%m-%d-%H-%M-%S"'); + $save_date = date("Y-m-d-H-i-s"); $file_name = "suricata_logs_{$save_date}_{$if_real}.tar.gz"; - exec("cd {$suricatalogdir}suricata_{$if_real}{$suricata_uuid} && /usr/bin/tar -czf /tmp/{$file_name} *"); + exec("cd {$suricatalogdir}suricata_{$if_real}{$suricata_uuid} && /usr/bin/tar -czf {$g['tmp_path']}/{$file_name} *"); - if (file_exists("/tmp/{$file_name}")) { + if (file_exists("{$g['tmp_path']}/{$file_name}")) { ob_start(); //important or other posts will fail if (isset($_SERVER['HTTPS'])) { header('Pragma: '); @@ -391,13 +395,13 @@ if ($_POST['download']) { header("Cache-Control: private, must-revalidate"); } header("Content-Type: application/octet-stream"); - header("Content-length: " . filesize("/tmp/{$file_name}")); + header("Content-length: " . filesize("{$g['tmp_path']}/{$file_name}")); header("Content-disposition: attachment; filename = {$file_name}"); ob_end_clean(); //important or other post will fail - readfile("/tmp/{$file_name}"); + readfile("{$g['tmp_path']}/{$file_name}"); // Clean up the temp file - @unlink("/tmp/{$file_name}"); + unlink_if_exists("{$g['tmp_path']}/{$file_name}"); } else $savemsg = gettext("An error occurred while creating archive"); @@ -451,6 +455,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td></tr> @@ -578,7 +583,7 @@ if ($savemsg) { </table> </td> </tr> - <?php if ($filterlogentries) : ?> + <?php if ($filterlogentries && count($filterfieldsarray)) : ?> <tr> <td colspan="2" class="listtopic"><?php printf(gettext("Last %s Alert Entries"), $anentries); ?> <?php echo gettext("(Most recent listed first) ** FILTERED VIEW ** clear filter to see all entries"); ?></td> @@ -622,9 +627,9 @@ if ($savemsg) { <?php /* 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{$suricata_uuid}"); - if (file_exists("/tmp/alerts_suricata{$suricata_uuid}")) { +if (file_exists("{$g['varlog_path']}/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log")) { + exec("tail -{$anentries} -r {$g['varlog_path']}/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.log > {$g['tmp_path']}/alerts_suricata{$suricata_uuid}"); + if (file_exists("{$g['tmp_path']}/alerts_suricata{$suricata_uuid}")) { $tmpblocked = array_flip(suricata_get_blocked_ips()); $counter = 0; @@ -638,7 +643,7 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo /* 0 1 2 3 4 5 6 7 */ /************** *************************************************************************************************************************/ - $fd = fopen("/tmp/alerts_suricata{$suricata_uuid}", "r"); + $fd = fopen("{$g['tmp_path']}/alerts_suricata{$suricata_uuid}", "r"); $buf = ""; while (($buf = fgets($fd)) !== FALSE) { $fields = array(); @@ -834,7 +839,7 @@ if (file_exists("/var/log/suricata/suricata_{$if_real}{$suricata_uuid}/alerts.lo } unset($fields, $buf, $tmp); fclose($fd); - @unlink("/tmp/alerts_suricata{$suricata_uuid}"); + unlink_if_exists("{$g['tmp_path']}/alerts_suricata{$suricata_uuid}"); } } ?> diff --git a/config/suricata/suricata_alerts.widget.php b/config/suricata/suricata_alerts.widget.php index bc7a0e2a..81d17c2e 100644 --- a/config/suricata/suricata_alerts.widget.php +++ b/config/suricata/suricata_alerts.widget.php @@ -81,7 +81,7 @@ if (isset($_GET['getNewAlerts'])) { $counter = 0; foreach ($suri_alerts as $a) { $response .= $a['instanceid'] . " " . $a['dateonly'] . "||" . $a['timeonly'] . "||" . $a['src'] . "||"; - $response .= $a['dst'] . "||" . $a['priority'] . "||" . $a['category'] . "\n"; + $response .= $a['dst'] . "||" . $a['msg'] . "\n"; $counter++; if($counter >= $suri_nentries) break; @@ -116,7 +116,7 @@ function suricata_widget_get_alerts() { /*************** FORMAT without CSV patch -- ALERT -- ***********************************************************************************/ /* Line format: timestamp action[**] [gid:sid:rev] msg [**] [Classification: class] [Priority: pri] {proto} src:srcport -> dst:dstport */ - /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 */ /****************************************************************************************************************************************/ /**************** FORMAT without CSV patch -- DECODER EVENT -- **************************************************************************/ @@ -134,37 +134,41 @@ function suricata_widget_get_alerts() { $fields[0] = substr($buf, 0, strpos($buf, ' ')); // The regular expression match below returns an array as follows: - // [1] => CLASSIFICATION, [2] = PRIORITY - preg_match('/\s\[Classification:\s(.*)\]\s\[Priority:\s(\d+)\]\s/', $buf, $tmp); - $fields[6] = trim($tmp[1]); - $fields[7] = trim($tmp[2]); + // [2] => GID, [3] => SID, [4] => REV, [5] => MSG, [6] => CLASSIFICATION, [7] = PRIORITY + preg_match('/\[\*{2}\]\s\[((\d+):(\d+):(\d+))\]\s(.*)\[\*{2}\]\s\[Classification:\s(.*)\]\s\[Priority:\s(\d+)\]\s/', $buf, $tmp); + $fields['gid'] = trim($tmp[2]); + $fields['sid'] = trim($tmp[3]); + $fields['rev'] = trim($tmp[4]); + $fields['msg'] = trim($tmp[5]); + $fields['class'] = trim($tmp[6]); + $fields['priority'] = trim($tmp[7]); // The regular expression match below looks for the PROTO, SRC and DST fields // and returns an array as follows: // [1] = PROTO, [2] => SRC:SPORT [3] => DST:DPORT if (preg_match('/\{(.*)\}\s(.*)\s->\s(.*)/', $buf, $tmp)) { // Get SRC - $fields[9] = trim(substr($tmp[2], 0, strrpos($tmp[2], ':'))); - if (is_ipaddrv6($fields[9])) - $fields[9] = inet_ntop(inet_pton($fields[9])); + $fields['src'] = trim(substr($tmp[2], 0, strrpos($tmp[2], ':'))); + if (is_ipaddrv6($fields['src'])) + $fields['src'] = inet_ntop(inet_pton($fields['src'])); // Get SPORT - $fields[10] = trim(substr($tmp[2], strrpos($tmp[2], ':') + 1)); + $fields['sport'] = trim(substr($tmp[2], strrpos($tmp[2], ':') + 1)); // Get DST - $fields[11] = trim(substr($tmp[3], 0, strrpos($tmp[3], ':'))); - if (is_ipaddrv6($fields[11])) - $fields[11] = inet_ntop(inet_pton($fields[11])); + $fields['dst'] = trim(substr($tmp[3], 0, strrpos($tmp[3], ':'))); + if (is_ipaddrv6($fields['dst'])) + $fields['dst'] = inet_ntop(inet_pton($fields['dst'])); // Get DPORT - $fields[12] = trim(substr($tmp[3], strrpos($tmp[3], ':') + 1)); + $fields['dport'] = trim(substr($tmp[3], strrpos($tmp[3], ':') + 1)); } else { // If no PROTO and IP ADDR, then this is a DECODER EVENT - $fields[9] = gettext("Decoder Event"); - $fields[10] = ""; - $fields[11] = ""; - $fields[12] = ""; + $fields['src'] = gettext("Decoder Event"); + $fields['sport'] = ""; + $fields['dst'] = ""; + $fields['dport'] = ""; } // Create a DateTime object from the event timestamp that @@ -173,31 +177,30 @@ function suricata_widget_get_alerts() { // Check the 'CATEGORY' field for the text "(null)" and // substitute "No classtype defined". - if ($fields[6] == "(null)") - $fields[6] = "No classtype assigned"; + if ($fields['class'] == "(null)") + $fields['class'] = "No classtype assigned"; $suricata_alerts[$counter]['instanceid'] = strtoupper(convert_friendly_interface_to_friendly_descr($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"); + $suricata_alerts[$counter]['msg'] = $fields['msg']; // Add square brackets around any IPv6 address - if (is_ipaddrv6($fields[9])) - $suricata_alerts[$counter]['src'] = "[" . $fields[9] . "]"; + if (is_ipaddrv6($fields['src'])) + $suricata_alerts[$counter]['src'] = "[" . $fields['src'] . "]"; else - $suricata_alerts[$counter]['src'] = $fields[9]; + $suricata_alerts[$counter]['src'] = $fields['src']; // Add the SRC PORT if not null - if (!empty($fields[10]) || $fields[10] == '0') - $suricata_alerts[$counter]['src'] .= ":" . $fields[10]; + if (!empty($fields['sport']) || $fields['sport'] == '0') + $suricata_alerts[$counter]['src'] .= ":" . $fields['sport']; // Add square brackets around any IPv6 address - if (is_ipaddrv6($fields[11])) - $suricata_alerts[$counter]['dst'] = "[" . $fields[11] . "]"; + if (is_ipaddrv6($fields['dst'])) + $suricata_alerts[$counter]['dst'] = "[" . $fields['dst'] . "]"; else - $suricata_alerts[$counter]['dst'] = $fields[11]; + $suricata_alerts[$counter]['dst'] = $fields['dst']; // Add the DST PORT if not null - if (!empty($fields[12]) || $fields[12] == '0') - $suricata_alerts[$counter]['dst'] .= ":" . $fields[12]; - $suricata_alerts[$counter]['priority'] = $fields[7]; - $suricata_alerts[$counter]['category'] = $fields[6]; + if (!empty($fields['dport']) || $fields['dport'] == '0') + $suricata_alerts[$counter]['dst'] .= ":" . $fields['dport']; $counter++; }; fclose($fd); @@ -238,7 +241,7 @@ function suricata_widget_get_alerts() { <tr> <th class="listhdrr"><?=gettext("IF/Date");?></th> <th class="listhdrr"><?=gettext("Src/Dst Address");?></th> - <th class="listhdrr"><?=gettext("Priority/Class");?></th> + <th class="listhdrr"><?=gettext("Description");?></th> </tr> </thead> <tbody id="suricata-alert-entries"> @@ -251,7 +254,7 @@ function suricata_widget_get_alerts() { 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>"); + <td class='listMRr'><div style='display: fixed; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.2em; max-height: 2.4em; overflow: hidden; text-overflow: ellipsis;' title='{$alert['msg']}'>" . $alert['msg'] . "</div></td></tr>"); $counter++; if($counter >= $suri_nentries) break; diff --git a/config/suricata/suricata_app_parsers.php b/config/suricata/suricata_app_parsers.php index 51514ee5..cfa34a54 100644 --- a/config/suricata/suricata_app_parsers.php +++ b/config/suricata/suricata_app_parsers.php @@ -475,6 +475,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td>'; @@ -487,6 +488,7 @@ if ($savemsg) { $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}"); + $tab_array[] = array($menu_iface . gettext("IP Rep"), false, "/suricata/suricata_ip_reputation.php?id={$id}"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_barnyard.php b/config/suricata/suricata_barnyard.php index 987055fd..2938136f 100644 --- a/config/suricata/suricata_barnyard.php +++ b/config/suricata/suricata_barnyard.php @@ -89,6 +89,29 @@ if (isset($id) && $a_nat[$id]) { } if ($_POST['save']) { + + // If disabling Barnyard2 on the interface, stop any + // currently running instance, then save the disabled + // state and exit so as to preserve settings. + if ($_POST['barnyard_enable'] != 'on') { + $a_nat[$id]['barnyard_enable'] = 'off'; + write_config("Suricata pkg: modified Barnyard2 settings."); + suricata_barnyard_stop($a_nat[$id], get_real_interface($a_nat[$id]['interface'])); + + // No need to rebuild rules for Barnyard2 changes + $rebuild_rules = false; + conf_mount_rw(); + sync_suricata_package_config(); + conf_mount_ro(); + 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_barnyard.php"); + exit; + } + // Check that at least one output plugin is enabled if ($_POST['barnyard_mysql_enable'] != 'on' && $_POST['barnyard_syslog_enable'] != 'on' && $_POST['barnyard_bro_ids_enable'] != 'on' && $_POST['barnyard_enable'] == "on") @@ -167,11 +190,13 @@ if ($_POST['save']) { if ($_POST['barnconfigpassthru']) $natent['barnconfigpassthru'] = base64_encode(str_replace("\r\n", "\n", $_POST['barnconfigpassthru'])); else unset($natent['barnconfigpassthru']); $a_nat[$id] = $natent; - write_config(); + write_config("Suricata pkg: modified Barnyard2 settings."); // No need to rebuild rules for Barnyard2 changes $rebuild_rules = false; + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); // If disabling Barnyard2 on the interface, stop any // currently running instance. If an instance is @@ -234,6 +259,7 @@ include_once("head.inc"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -246,6 +272,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}"); + $tab_array[] = array($menu_iface . gettext("IP Rep"), false, "/suricata/suricata_ip_reputation.php?id={$id}"); display_top_tabs($tab_array, true); ?> </td></tr> @@ -606,11 +633,11 @@ function enable_change(enable_change) { document.iform.barnconfigpassthru.disabled = endis; } -enable_change(false); toggle_mySQL(); toggle_syslog(); toggle_local_syslog(); toggle_bro_ids(); +enable_change(false); </script> diff --git a/config/suricata/suricata_blocked.php b/config/suricata/suricata_blocked.php index 842d4073..4f4bf095 100644 --- a/config/suricata/suricata_blocked.php +++ b/config/suricata/suricata_blocked.php @@ -42,6 +42,8 @@ require_once("guiconfig.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); +global $g, $config; + $suricatalogdir = SURICATALOGDIR; $suri_pf_table = SURICATA_PF_TABLE; @@ -94,22 +96,22 @@ if ($_POST['download']) 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"'); + $save_date = date("Y-m-d-H-i-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", ""); + safe_mkdir("{$g['tmp_path']}/suricata_blocked"); + file_put_contents("{$g['tmp_path']}/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); + file_put_contents("{$g['tmp_path']}/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"); + exec("/usr/bin/tar -czf {$g['tmp_path']}/{$file_name} -C{$g['tmp_path']}/suricata_blocked suricata_block.pf"); // If we successfully created the archive, send it to the browser. - if(file_exists("/tmp/{$file_name}")) { + if(file_exists("{$g['tmp_path']}/{$file_name}")) { ob_start(); //important or other posts will fail if (isset($_SERVER['HTTPS'])) { header('Pragma: '); @@ -119,14 +121,14 @@ if ($_POST['download']) header("Cache-Control: private, must-revalidate"); } header("Content-Type: application/octet-stream"); - header("Content-length: " . filesize("/tmp/{$file_name}")); + header("Content-length: " . filesize("{$g['tmp_path']}/{$file_name}")); header("Content-disposition: attachment; filename = {$file_name}"); ob_end_clean(); //important or other post will fail - readfile("/tmp/{$file_name}"); + readfile("{$g['tmp_path']}/{$file_name}"); // Clean up the temp files and directory - @unlink("/tmp/{$file_name}"); - exec("/bin/rm -fr /tmp/suricata_blocked"); + unlink_if_exists("{$g['tmp_path']}/{$file_name}"); + rmdir_recursive("{$g['tmp_path']}/suricata_blocked"); } else $savemsg = gettext("An error occurred while creating archive"); } else @@ -191,6 +193,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td> @@ -257,19 +260,67 @@ if ($savemsg) { 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) { - log_error("[suricata] ERROR: block.log entry failed to parse correctly with too many or not enough CSV entities, skipping this entry..."); - log_error("[suricata] Failed block.log entry fields are: " . print_r($fields, true)); - continue; + + /*************** FORMAT for file -- BLOCK -- **************************************************************************/ + /* Line format: timestamp action [**] [gid:sid:rev] msg [**] [Classification: class] [Priority: pri] {proto} ip:port */ + /* 0 1 2 3 4 5 6 7 8 9 10 */ + /**********************************************************************************************************************/ + + $buf = ""; + while (($buf = fgets($fd)) !== FALSE) { + $fields = array(); + $tmp = array(); + + /***************************************************************/ + /* Parse block log entry to find the parts we want to display. */ + /* We parse out all the fields even though we currently use */ + /* just a few of them. */ + /***************************************************************/ + + // Field 0 is the event timestamp + $fields['time'] = substr($buf, 0, strpos($buf, ' ')); + + // Field 1 is the action + if (strpos($buf, '[') !== FALSE && strpos($buf, ']') !== FALSE) + $fields['action'] = substr($buf, strpos($buf, '[') + 1, strpos($buf, ']') - strpos($buf, '[') - 1); + else + $fields['action'] = null; + + // The regular expression match below returns an array as follows: + // [2] => GID, [3] => SID, [4] => REV, [5] => MSG, [6] => CLASSIFICATION, [7] = PRIORITY + preg_match('/\[\*{2}\]\s\[((\d+):(\d+):(\d+))\]\s(.*)\[\*{2}\]\s\[Classification:\s(.*)\]\s\[Priority:\s(\d+)\]\s/', $buf, $tmp); + $fields['gid'] = trim($tmp[2]); + $fields['sid'] = trim($tmp[3]); + $fields['rev'] = trim($tmp[4]); + $fields['msg'] = trim($tmp[5]); + $fields['class'] = trim($tmp[6]); + $fields['priority'] = trim($tmp[7]); + + // The regular expression match below looks for the PROTO, IP and PORT fields + // and returns an array as follows: + // [1] = PROTO, [2] => IP:PORT + if (preg_match('/\{(.*)\}\s(.*)/', $buf, $tmp)) { + // Get PROTO + $fields['proto'] = trim($tmp[1]); + + // Get IP + $fields['ip'] = trim(substr($tmp[2], 0, strrpos($tmp[2], ':'))); + if (is_ipaddrv6($fields['ip'])) + $fields['ip'] = inet_ntop(inet_pton($fields['ip'])); + + // Get PORT + $fields['port'] = trim(substr($tmp[2], strrpos($tmp[2], ':') + 1)); } - $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); + + // In the unlikely event we read an old log file and fail to parse + // out an IP address, just skip the record since we can't use it. + if (empty($fields['ip'])) + continue; + $fields['ip'] = inet_pton($fields['ip']); + if (isset($tmpblocked[$fields['ip']])) { + if (!is_array($src_ip_list[$fields['ip']])) + $src_ip_list[$fields['ip']] = array(); + $src_ip_list[$fields['ip']][$fields['msg']] = "{$fields['msg']} - " . substr($fields['time'], 0, -7); } } fclose($fd); diff --git a/config/suricata/suricata_check_cron_misc.inc b/config/suricata/suricata_check_cron_misc.inc index 70394a23..eb1ba2d0 100644 --- a/config/suricata/suricata_check_cron_misc.inc +++ b/config/suricata/suricata_check_cron_misc.inc @@ -66,9 +66,9 @@ function suricata_check_dir_size_limit($suricataloglimitsize) { conf_mount_rw(); // Truncate the Rules Update Log file if it exists - if (file_exists(RULES_UPD_LOGFILE)) { + if (file_exists(SURICATA_RULES_UPD_LOGFILE)) { log_error(gettext("[Suricata] Truncating the Rules Update Log file...")); - @file_put_contents(RULES_UPD_LOGFILE, ""); + @file_put_contents(SURICATA_RULES_UPD_LOGFILE, ""); } // Initialize an array of the log files we want to prune @@ -93,6 +93,14 @@ function suricata_check_dir_size_limit($suricataloglimitsize) { } } + // Cleanup any rotated logs + log_error(gettext("[Suricata] Deleting any rotated log files for {$value['descr']} ({$if_real})...")); + unlink_if_exists("{$suricata_log_dir}/*.log.*"); + + // Cleanup any rotated pcap logs + log_error(gettext("[Suricata] Deleting any rotated pcap log files for {$value['descr']} ({$if_real})...")); + unlink_if_exists("{$suricata_log_dir}/log.pcap.*"); + // Check for any captured stored files and clean them up unlink_if_exists("{$suricata_log_dir}/files/*"); @@ -217,6 +225,7 @@ if ($config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] == $config['installedpackages']['suricata']['config'][0]['file_store_retention'] > 0) { $now = time(); $files = glob("{$suricata_log_dir}/files/file.*"); + $prune_count = 0; foreach ($files as $f) { if (($now - filemtime($f)) > ($config['installedpackages']['suricata']['config'][0]['file_store_retention'] * 3600)) { $prune_count++; @@ -227,6 +236,25 @@ if ($config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] == log_error(gettext("[Suricata] File Store cleanup job removed {$prune_count} file(s) from {$suricata_log_dir}/files/...")); unset($files); } + + // Prune any pcap log files over configured limit + $files = glob("{$suricata_log_dir}/log.pcap.*"); + if (count($files) > $value['max_pcap_log_files']) { + $over = count($files) - $value['max_pcap_log_files']; + $remove_files = array(); + while ($over > 0) { + $remove_files[] = array_shift($files); + $over--; + } + $prune_count = 0; + foreach ($remove_files as $f) { + $prune_count++; + unlink_if_exists($f); + } + if ($prune_count > 0) + log_error(gettext("[Suricata] Packet Capture log cleanup job removed {$prune_count} file(s) from {$suricata_log_dir}/...")); + unset($files, $remove_files); + } } } diff --git a/config/suricata/suricata_check_for_rule_updates.php b/config/suricata/suricata_check_for_rule_updates.php index eeb7be6c..0fa4fb2d 100644 --- a/config/suricata/suricata_check_for_rule_updates.php +++ b/config/suricata/suricata_check_for_rule_updates.php @@ -41,39 +41,13 @@ require_once("functions.inc"); require_once("service-utils.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); +require_once("/usr/local/pkg/suricata/suricata_defs.inc"); global $g, $pkg_interface, $suricata_gui_include, $rebuild_rules; -if (!defined("VRT_DNLD_URL")) - define("VRT_DNLD_URL", "https://www.snort.org/rules/"); -if (!defined("ET_VERSION")) - define("ET_VERSION", "2.9.0"); -if (!defined("ET_BASE_DNLD_URL")) - define("ET_BASE_DNLD_URL", "http://rules.emergingthreats.net/"); -if (!defined("ETPRO_BASE_DNLD_URL")) - define("ETPRO_BASE_DNLD_URL", "https://rules.emergingthreatspro.com/"); -if (!defined("ET_DNLD_FILENAME")) - define("ET_DNLD_FILENAME", "emerging.rules.tar.gz"); -if (!defined("ETPRO_DNLD_FILENAME")) - define("ETPRO_DNLD_FILENAME", "etpro.rules.tar.gz"); -if (!defined("GPLV2_DNLD_FILENAME")) - define("GPLV2_DNLD_FILENAME", "community-rules.tar.gz"); -if (!defined("GPLV2_DNLD_URL")) - define("GPLV2_DNLD_URL", "https://s3.amazonaws.com/snort-org/www/rules/community/"); -if (!defined("RULES_UPD_LOGFILE")) - define("RULES_UPD_LOGFILE", SURICATALOGDIR . "/suricata_rules_update.log"); -if (!defined("VRT_FILE_PREFIX")) - define("VRT_FILE_PREFIX", "snort_"); -if (!defined("GPL_FILE_PREFIX")) - define("GPL_FILE_PREFIX", "GPLv2_"); -if (!defined("ET_OPEN_FILE_PREFIX")) - define("ET_OPEN_FILE_PREFIX", "emerging-"); -if (!defined("ET_PRO_FILE_PREFIX")) - define("ET_PRO_FILE_PREFIX", "etpro-"); - $suricatadir = SURICATADIR; $suricatalogdir = SURICATALOGDIR; -$suricata_rules_upd_log = RULES_UPD_LOGFILE; +$mounted_rw = FALSE; /* Save the state of $pkg_interface so we can restore it */ $pkg_interface_orig = $pkg_interface; @@ -93,7 +67,7 @@ $vrt_enabled = $config['installedpackages']['suricata']['config'][0]['enable_vrt $snortcommunityrules = $config['installedpackages']['suricata']['config'][0]['snortcommunityrules'] == 'on' ? 'on' : 'off'; /* Working directory for downloaded rules tarballs */ -$tmpfname = "/tmp/suricata_rules_up"; +$tmpfname = "{$g['tmp_path']}/suricata_rules_up"; /* Snort VRT Rules filenames and URL */ $snort_filename_md5 = "{$snort_filename}.md5"; @@ -105,7 +79,10 @@ $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(); +if (!is_subsystem_dirty('mount')) { + conf_mount_rw(); + $mounted_rw = TRUE; +} /* Set up Emerging Threats rules filenames and URL */ if ($etpro == "on") { @@ -115,7 +92,7 @@ if ($etpro == "on") { $emergingthreats_url .= "{$etproid}/suricata/"; $et_name = "Emerging Threats Pro"; $et_md5_remove = ET_DNLD_FILENAME . ".md5"; - @unlink("{$suricatadir}{$et_md5_remove}"); + unlink_if_exists("{$suricatadir}{$et_md5_remove}"); } else { $emergingthreats_filename = ET_DNLD_FILENAME; @@ -126,7 +103,7 @@ else { $emergingthreats_url .= "suricata/"; $et_name = "Emerging Threats Open"; $et_md5_remove = ETPRO_DNLD_FILENAME . ".md5"; - @unlink("{$suricatadir}{$et_md5_remove}"); + unlink_if_exists("{$suricatadir}{$et_md5_remove}"); } // Set a common flag for all Emerging Threats rules (open and pro). @@ -209,7 +186,9 @@ function suricata_download_file_url($url, $file_out) { curl_setopt($ch, CURLOPT_FILE, $fout); // NOTE: required to suppress errors from XMLRPC due to progress bar output - if ($g['suricata_sync_in_progress']) + // and to prevent useless spam from rules update cron job execution. This + // prevents progress bar output during package sync and rules update cron task. + if ($g['suricata_sync_in_progress'] || $pkg_interface == "console") curl_setopt($ch, CURLOPT_HEADER, false); else { curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header'); @@ -283,21 +262,21 @@ function suricata_check_rule_md5($file_url, $file_dst, $desc = "") { /* error occurred. */ /**********************************************************/ - global $pkg_interface, $suricata_rules_upd_log, $last_curl_error, $update_errors; + global $pkg_interface, $last_curl_error, $update_errors; $suricatadir = SURICATADIR; $filename_md5 = basename($file_dst); if ($pkg_interface <> "console") update_status(gettext("Downloading {$desc} md5 file...")); - error_log(gettext("\tDownloading {$desc} md5 file {$filename_md5}...\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tDownloading {$desc} md5 file {$filename_md5}...\n"), 3, SURICATA_RULES_UPD_LOGFILE); $rc = suricata_download_file_url($file_url, $file_dst); // See if download from URL was successful if ($rc === true) { if ($pkg_interface <> "console") update_status(gettext("Done downloading {$filename_md5}.")); - error_log("\tChecking {$desc} md5 file...\n", 3, $suricata_rules_upd_log); + error_log("\tChecking {$desc} md5 file...\n", 3, SURICATA_RULES_UPD_LOGFILE); // check md5 hash in new file against current file to see if new download is posted if (file_exists("{$suricatadir}{$filename_md5}")) { @@ -307,7 +286,7 @@ function suricata_check_rule_md5($file_url, $file_dst, $desc = "") { if ($pkg_interface <> "console") update_status(gettext("{$desc} are up to date...")); log_error(gettext("[Suricata] {$desc} are up to date...")); - error_log(gettext("\t{$desc} are up to date.\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\t{$desc} are up to date.\n"), 3, SURICATA_RULES_UPD_LOGFILE); return false; } else @@ -316,7 +295,7 @@ function suricata_check_rule_md5($file_url, $file_dst, $desc = "") { return true; } else { - error_log(gettext("\t{$desc} md5 download failed.\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\t{$desc} md5 download failed.\n"), 3, SURICATA_RULES_UPD_LOGFILE); $suricata_err_msg = gettext("Server returned error code {$rc}."); if ($pkg_interface <> "console") { update_status(gettext("{$desc} md5 error ... Server returned error code {$rc} ...")); @@ -324,10 +303,10 @@ function suricata_check_rule_md5($file_url, $file_dst, $desc = "") { } log_error(gettext("[Suricata] {$desc} md5 download failed...")); log_error(gettext("[Suricata] Server returned error code {$rc}...")); - error_log(gettext("\t{$suricata_err_msg}\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\t{$suricata_err_msg}\n"), 3, SURICATA_RULES_UPD_LOGFILE); 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); + error_log(gettext("\tServer error message was: {$last_curl_error}\n"), 3, SURICATA_RULES_UPD_LOGFILE); + error_log(gettext("\t{$desc} will not be updated.\n"), 3, SURICATA_RULES_UPD_LOGFILE); $update_errors = true; return false; } @@ -352,7 +331,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, $update_errors; + global $pkg_interface, $last_curl_error, $update_errors; $suricatadir = SURICATADIR; $filename = basename($file_dst); @@ -360,8 +339,8 @@ function suricata_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { if ($pkg_interface <> "console") update_status(gettext("There is a new set of {$desc} posted. Downloading...")); log_error(gettext("[Suricata] There is a new set of {$desc} posted. Downloading {$filename}...")); - error_log(gettext("\tThere is a new set of {$desc} posted.\n"), 3, $suricata_rules_upd_log); - error_log(gettext("\tDownloading file '{$filename}'...\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tThere is a new set of {$desc} posted.\n"), 3, SURICATA_RULES_UPD_LOGFILE); + error_log(gettext("\tDownloading file '{$filename}'...\n"), 3, SURICATA_RULES_UPD_LOGFILE); $rc = suricata_download_file_url($file_url, $file_dst); // See if the download from the URL was successful @@ -369,7 +348,7 @@ function suricata_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { if ($pkg_interface <> "console") update_status(gettext("Done downloading {$desc} file.")); log_error("[Suricata] {$desc} file update downloaded successfully"); - error_log(gettext("\tDone downloading rules file.\n"),3, $suricata_rules_upd_log); + error_log(gettext("\tDone downloading rules file.\n"),3, SURICATA_RULES_UPD_LOGFILE); // Test integrity of the rules file. Turn off update if file has wrong md5 hash if ($file_md5 != trim(md5_file($file_dst))){ @@ -378,10 +357,10 @@ function suricata_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { log_error(gettext("[Suricata] {$desc} file download failed. Bad MD5 checksum...")); log_error(gettext("[Suricata] Downloaded File MD5: " . md5_file($file_dst))); log_error(gettext("[Suricata] Expected File MD5: {$file_md5}")); - error_log(gettext("\t{$desc} file download failed. Bad MD5 checksum.\n"), 3, $suricata_rules_upd_log); - 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); + error_log(gettext("\t{$desc} file download failed. Bad MD5 checksum.\n"), 3, SURICATA_RULES_UPD_LOGFILE); + error_log(gettext("\tDownloaded {$desc} file MD5: " . md5_file($file_dst) . "\n"), 3, SURICATA_RULES_UPD_LOGFILE); + error_log(gettext("\tExpected {$desc} file MD5: {$file_md5}\n"), 3, SURICATA_RULES_UPD_LOGFILE); + error_log(gettext("\t{$desc} file download failed. {$desc} will not be updated.\n"), 3, SURICATA_RULES_UPD_LOGFILE); $update_errors = true; return false; } @@ -391,10 +370,10 @@ function suricata_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { if ($pkg_interface <> "console") update_output_window(gettext("{$desc} file download failed...")); log_error(gettext("[Suricata] {$desc} file download failed... server returned error '{$rc}'...")); - error_log(gettext("\t{$desc} file download failed. Server returned error {$rc}.\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\t{$desc} file download failed. Server returned error {$rc}.\n"), 3, SURICATA_RULES_UPD_LOGFILE); 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); + error_log(gettext("\tThe error text was: {$last_curl_error}\n"), 3, SURICATA_RULES_UPD_LOGFILE); + error_log(gettext("\t{$desc} will not be updated.\n"), 3, SURICATA_RULES_UPD_LOGFILE); $update_errors = true; return false; } @@ -405,21 +384,21 @@ function suricata_fetch_new_rules($file_url, $file_dst, $file_md5, $desc = "") { /* remove old $tmpfname files if present */ if (is_dir("{$tmpfname}")) - exec("/bin/rm -r {$tmpfname}"); + rmdir_recursive("{$tmpfname}"); /* Make sure required suricatadirs exsist */ -exec("/bin/mkdir -p {$suricatadir}rules"); -exec("/bin/mkdir -p {$tmpfname}"); -exec("/bin/mkdir -p {$suricatalogdir}"); +safe_mkdir("{$suricatadir}rules"); +safe_mkdir("{$tmpfname}"); +safe_mkdir("{$suricatalogdir}"); /* See if we need to automatically clear the Update Log based on 1024K size limit */ -if (file_exists($suricata_rules_upd_log)) { - if (1048576 < filesize($suricata_rules_upd_log)) - exec("/bin/rm -r {$suricata_rules_upd_log}"); +if (file_exists(SURICATA_RULES_UPD_LOGFILE)) { + if (1048576 < filesize(SURICATA_RULES_UPD_LOGFILE)) + unlink_if_exists("{SURICATA_RULES_UPD_LOGFILE}"); } /* 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); +error_log(gettext("Starting rules update... Time: " . date("Y-m-d H:i:s") . "\n"), 3, SURICATA_RULES_UPD_LOGFILE); $last_curl_error = ""; $update_errors = false; @@ -439,7 +418,7 @@ if ($emergingthreats == 'on') { if ($snortdownload == 'on') { if (empty($snort_filename)) { log_error(gettext("No snortrules-snapshot filename has been set on Snort pkg GLOBAL SETTINGS tab. Snort VRT rules cannot be updated.")); - error_log(gettext("\tWARNING-- No snortrules-snapshot filename set on GLOBAL SETTINGS tab. Snort VRT rules cannot be updated!\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tWARNING-- No snortrules-snapshot filename set on GLOBAL SETTINGS tab. Snort VRT rules cannot be updated!\n"), 3, SURICATA_RULES_UPD_LOGFILE); $snortdownload = 'off'; } elseif (suricata_check_rule_md5("{$snort_rule_url}{$snort_filename_md5}?oinkcode={$oinkid}", "{$tmpfname}/{$snort_filename_md5}", "Snort VRT rules")) { @@ -454,7 +433,7 @@ if ($snortdownload == 'on') { /* Check for and download any new Snort GPLv2 Community Rules sigs */ if ($snortcommunityrules == 'on') { - if (suricata_check_rule_md5("{$snort_community_rules_url}{$snort_community_rules_filename_md5}", "{$tmpfname}/{$snort_community_rules_filename_md5}", "Snort GPLv2 Community Rules")) { + if (suricata_check_rule_md5("{$snort_community_rules_url}{$snort_community_rules_filename}/md5", "{$tmpfname}/{$snort_community_rules_filename_md5}", "Snort GPLv2 Community Rules")) { /* download Snort GPLv2 Community Rules file */ $file_md5 = trim(file_get_contents("{$tmpfname}/{$snort_community_rules_filename_md5}")); if (!suricata_fetch_new_rules("{$snort_community_rules_url}{$snort_community_rules_filename}", "{$tmpfname}/{$snort_community_rules_filename}", $file_md5, "Snort GPLv2 Community Rules")) @@ -472,7 +451,7 @@ if ($emergingthreats == 'on') { update_status(gettext("Extracting {$et_name} rules...")); update_output_window(gettext("Installing {$et_name} rules...")); } - error_log(gettext("\tExtracting and installing {$et_name} rules...\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tExtracting and installing {$et_name} rules...\n"), 3, SURICATA_RULES_UPD_LOGFILE); exec("/usr/bin/tar xzf {$tmpfname}/{$emergingthreats_filename} -C {$tmpfname}/emerging rules/"); /* Remove the old Emerging Threats rules files */ @@ -530,8 +509,8 @@ if ($emergingthreats == 'on') { update_status(gettext("Extraction of {$et_name} rules completed...")); update_output_window(gettext("Installation of {$et_name} rules completed...")); } - error_log(gettext("\tInstallation of {$et_name} rules completed.\n"), 3, $suricata_rules_upd_log); - exec("rm -r {$tmpfname}/emerging"); + error_log(gettext("\tInstallation of {$et_name} rules completed.\n"), 3, SURICATA_RULES_UPD_LOGFILE); + rmdir_recursive("{$tmpfname}/emerging"); } } @@ -546,7 +525,7 @@ if ($snortdownload == 'on') { update_status(gettext("Extracting Snort VRT rules...")); update_output_window(gettext("Installing Sourcefire VRT rules...")); } - error_log(gettext("\tExtracting and installing Snort VRT rules...\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tExtracting and installing Snort VRT rules...\n"), 3, SURICATA_RULES_UPD_LOGFILE); /* extract snort.org rules and add prefix to all snort.org files */ safe_mkdir("{$tmpfname}/snortrules"); @@ -563,7 +542,7 @@ if ($snortdownload == 'on') { $newfile = basename($file); @copy($file, "{$suricatadir}rules/{$newfile}"); } - exec("rm -r {$tmpfname}/snortrules"); + rmdir_recursive("{$tmpfname}/snortrules"); /* extract base etc files */ if ($pkg_interface <> "console") { @@ -575,7 +554,7 @@ if ($snortdownload == 'on') { if (file_exists("{$tmpfname}/etc/{$file}")) @copy("{$tmpfname}/etc/{$file}", "{$tmpfname}/VRT_{$file}"); } - exec("rm -r {$tmpfname}/etc"); + rmdir_recursive("{$tmpfname}/etc"); if (file_exists("{$tmpfname}/{$snort_filename_md5}")) { if ($pkg_interface <> "console") update_status(gettext("Copying md5 signature to Suricata directory...")); @@ -585,7 +564,7 @@ if ($snortdownload == 'on') { update_status(gettext("Extraction of Snort VRT rules completed...")); update_output_window(gettext("Installation of Sourcefire VRT rules completed...")); } - error_log(gettext("\tInstallation of Snort VRT rules completed.\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tInstallation of Snort VRT rules completed.\n"), 3, SURICATA_RULES_UPD_LOGFILE); } } @@ -597,7 +576,7 @@ if ($snortcommunityrules == 'on') { update_status(gettext("Extracting Snort GPLv2 Community Rules...")); update_output_window(gettext("Installing Snort GPLv2 Community Rules...")); } - error_log(gettext("\tExtracting and installing Snort GPLv2 Community Rules...\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tExtracting and installing Snort GPLv2 Community Rules...\n"), 3, SURICATA_RULES_UPD_LOGFILE); exec("/usr/bin/tar xzf {$tmpfname}/{$snort_community_rules_filename} -C {$tmpfname}/community/"); $files = glob("{$tmpfname}/community/community-rules/*.rules"); @@ -620,8 +599,8 @@ if ($snortcommunityrules == 'on') { update_status(gettext("Extraction of Snort GPLv2 Community Rules completed...")); update_output_window(gettext("Installation of Snort GPLv2 Community Rules file completed...")); } - error_log(gettext("\tInstallation of Snort GPLv2 Community Rules completed.\n"), 3, $suricata_rules_upd_log); - exec("rm -r {$tmpfname}/community"); + error_log(gettext("\tInstallation of Snort GPLv2 Community Rules completed.\n"), 3, SURICATA_RULES_UPD_LOGFILE); + rmdir_recursive("{$tmpfname}/community"); } } @@ -643,7 +622,7 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = if ($pkg_interface <> "console") update_status(gettext('Copying new config and map files...')); - error_log(gettext("\tCopying new config and map files...\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tCopying new config and map files...\n"), 3, SURICATA_RULES_UPD_LOGFILE); /******************************************************************/ /* Build the classification.config and reference.config files */ @@ -672,10 +651,14 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = /* Start the rules rebuild proccess for each configured interface */ if (is_array($config['installedpackages']['suricata']['rule']) && - !empty($config['installedpackages']['suricata']['rule'])) { + count($config['installedpackages']['suricata']['rule']) > 0) { - /* Set the flag to force rule rebuilds since we downloaded new rules */ - $rebuild_rules = true; + /* Set the flag to force rule rebuilds since we downloaded new rules, */ + /* except when in post-install mode. Post-install does its own rebuild. */ + if ($g['suricata_postinstall']) + $rebuild_rules = false; + else + $rebuild_rules = true; /* Create configuration for each active Suricata interface */ foreach ($config['installedpackages']['suricata']['rule'] as $value) { @@ -693,7 +676,7 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = } suricata_apply_customizations($value, $if_real); $tmp = "\t" . $tmp . "\n"; - error_log($tmp, 3, $suricata_rules_upd_log); + error_log($tmp, 3, SURICATA_RULES_UPD_LOGFILE); } } else { @@ -701,44 +684,43 @@ if ($snortdownload == 'on' || $emergingthreats == 'on' || $snortcommunityrules = update_output_window(gettext("Warning: No interfaces configured for Suricata were found...")); update_output_window(gettext("No interfaces currently have Suricata configured and enabled on them...")); } - error_log(gettext("\tWarning: No interfaces configured for Suricata were found...\n"), 3, $suricata_rules_upd_log); + error_log(gettext("\tWarning: No interfaces configured for Suricata were found...\n"), 3, SURICATA_RULES_UPD_LOGFILE); } /* Clear the rebuild rules flag. */ $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'] && - !empty($config['installedpackages']['suricata']['rule'])) { + /* Restart Suricata if already running and we are not in post-install, so as to pick up the new rules. */ + if (is_process_running("suricata") && !$g['suricata_postinstall'] && + count($config['installedpackages']['suricata']['rule']) > 0) { // 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_status(gettext('Signaling 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); + error_log(gettext("\tLive-Reload of updated rules is enabled...\n"), 3, SURICATA_RULES_UPD_LOGFILE); 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); + error_log(gettext("\tLive swap of updated rules requested for " . convert_friendly_interface_to_friendly_descr($value['interface']) . ".\n"), 3, SURICATA_RULES_UPD_LOGFILE); } 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); + error_log(gettext("\tLive-Reload of the updated rules is complete.\n"), 3, SURICATA_RULES_UPD_LOGFILE); } 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); + error_log(gettext("\tRestarting Suricata to activate the new set of rules...\n"), 3, SURICATA_RULES_UPD_LOGFILE); 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("\tSuricata has restarted with your new set of rules.\n"), 3, SURICATA_RULES_UPD_LOGFILE); } } else { @@ -753,7 +735,7 @@ if (is_dir("{$tmpfname}")) { update_status(gettext("Cleaning up after rules extraction...")); update_output_window(gettext("Removing {$tmpfname} directory...")); } - exec("/bin/rm -r {$tmpfname}"); + rmdir_recursive("{$tmpfname}"); } if ($pkg_interface <> "console") { @@ -761,11 +743,10 @@ if ($pkg_interface <> "console") { 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); +error_log(gettext("The Rules update has finished. Time: " . date("Y-m-d H:i:s"). "\n\n"), 3, SURICATA_RULES_UPD_LOGFILE); -// Remount filesystem read-only unless we are in package post-install. -// The post-install code will remount read-only when it completes. -if (!$g['suricata_postinstall']) +/* Remount filesystem read-only if we changed it in this module */ +if ($mounted_rw == TRUE) conf_mount_ro(); // Restore the state of $pkg_interface @@ -777,6 +758,6 @@ if ($update_errors) else $config['installedpackages']['suricata']['config'][0]['last_rule_upd_status'] = gettext("success"); $config['installedpackages']['suricata']['config'][0]['last_rule_upd_time'] = time(); -write_config("Suricata pkg: updated status for updated rules package(s) check."); +write_config("Suricata pkg: updated status for updated rules package(s) check.", FALSE); ?> diff --git a/config/suricata/suricata_define_vars.php b/config/suricata/suricata_define_vars.php index 040244b0..b94292c3 100644 --- a/config/suricata/suricata_define_vars.php +++ b/config/suricata/suricata_define_vars.php @@ -187,6 +187,7 @@ if ($savemsg) $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -199,6 +200,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}"); + $tab_array[] = array($menu_iface . gettext("IP Rep"), false, "/suricata/suricata_ip_reputation.php?id={$id}"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_defs.inc b/config/suricata/suricata_defs.inc new file mode 100644 index 00000000..7758a9f0 --- /dev/null +++ b/config/suricata/suricata_defs.inc @@ -0,0 +1,117 @@ +<?php +/* + * suricata_defs.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("pkg-utils.inc"); + +/*************************************************************************/ +/* This file contains definitions for various CONSTANTS used throughout */ +/* the Suricata package. It is included via a "require_once()" call in */ +/* the "suricata.inc" and "suricata_post_install.php" files. */ +/*************************************************************************/ + +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 +if (!defined('SURICATA_PKG_VER')) + define('SURICATA_PKG_VER', $suricata_package_version); + +// Define the PBI base directory +if (!defined('SURICATA_PBI_BASEDIR')) + define('SURICATA_PBI_BASEDIR', '/usr/pbi/suricata-' . php_uname("m") . '/'); + +// Define the PBI binary wrapper directory +if (!defined('SURICATA_PBI_BINDIR')) + define('SURICATA_PBI_BINDIR', SURICATA_PBI_BASEDIR . 'bin/'); + +// Define the name of the pf table used for IP blocks +if (!defined('SURICATA_PF_TABLE')) + define('SURICATA_PF_TABLE', 'snort2c'); + +// Create some other useful defines +if (!defined('SURICATADIR')) + define('SURICATADIR', SURICATA_PBI_BASEDIR . 'etc/suricata/'); +if (!defined('SURICATALOGDIR')) + define('SURICATALOGDIR', "{$g['varlog_path']}/suricata/"); +if (!defined('SURICATA_RULES_UPD_LOGFILE')) + define('SURICATA_RULES_UPD_LOGFILE', SURICATALOGDIR . 'suricata_rules_update.log'); +if (!defined('SURICATA_SID_MODS_PATH')) + define('SURICATA_SID_MODS_PATH', "{$g['vardb_path']}/suricata/sidmods/"); +if (!defined('SURICATA_IPREP_PATH')) + define('SURICATA_IPREP_PATH', "{$g['vardb_path']}/suricata/iprep/"); + +// Rule set download URLs, filenames and prefixes +if (!defined("VRT_DNLD_URL")) + define("VRT_DNLD_URL", "https://www.snort.org/rules/"); +if (!defined("ET_VERSION")) + define("ET_VERSION", "2.9.0"); +if (!defined("ET_BASE_DNLD_URL")) + define("ET_BASE_DNLD_URL", "http://rules.emergingthreats.net/"); +if (!defined("ETPRO_BASE_DNLD_URL")) + define("ETPRO_BASE_DNLD_URL", "https://rules.emergingthreatspro.com/"); +if (!defined("ET_DNLD_FILENAME")) + define("ET_DNLD_FILENAME", "emerging.rules.tar.gz"); +if (!defined("ETPRO_DNLD_FILENAME")) + define("ETPRO_DNLD_FILENAME", "etpro.rules.tar.gz"); +if (!defined("ET_IQRISK_DNLD_URL")) + define("ET_IQRISK_DNLD_URL", "https://rules.emergingthreatspro.com/_xxx_/reputation/"); +if (!defined("GPLV2_DNLD_FILENAME")) + define("GPLV2_DNLD_FILENAME", "community-rules.tar.gz"); +if (!defined("GPLV2_DNLD_URL")) + define("GPLV2_DNLD_URL", "https://www.snort.org/downloads/community/"); +if (!defined("VRT_FILE_PREFIX")) + define("VRT_FILE_PREFIX", "snort_"); +if (!defined("GPL_FILE_PREFIX")) + define("GPL_FILE_PREFIX", "GPLv2_"); +if (!defined("ET_OPEN_FILE_PREFIX")) + define("ET_OPEN_FILE_PREFIX", "emerging-"); +if (!defined("ET_PRO_FILE_PREFIX")) + define("ET_PRO_FILE_PREFIX", "etpro-"); +if (!defined('SURICATA_ENFORCING_RULES_FILENAME')) + define('SURICATA_ENFORCING_RULES_FILENAME', 'suricata.rules'); +if (!defined('FLOWBITS_FILENAME')) + define('FLOWBITS_FILENAME', 'flowbit-required.rules'); + +?> diff --git a/config/suricata/suricata_download_updates.php b/config/suricata/suricata_download_updates.php index 89e959c9..1abb32d6 100644 --- a/config/suricata/suricata_download_updates.php +++ b/config/suricata/suricata_download_updates.php @@ -44,7 +44,7 @@ require_once("/usr/local/pkg/suricata/suricata.inc"); /* Define some locally required variables from Suricata constants */ $suricatadir = SURICATADIR; -$suricata_rules_upd_log = RULES_UPD_LOGFILE; +$suricata_rules_upd_log = SURICATA_RULES_UPD_LOGFILE; $snortdownload = $config['installedpackages']['suricata']['config'][0]['enable_vrt_rules']; $emergingthreats = $config['installedpackages']['suricata']['config'][0]['enable_etopen_rules']; @@ -116,7 +116,7 @@ if ($snortcommunityrules == 'on' && file_exists("{$suricatadir}{$snort_community /* Check for postback to see if we should clear the update log file. */ if ($_POST['clear']) { if (file_exists("{$suricata_rules_upd_log}")) - mwexec("/bin/rm -f {$suricata_rules_upd_log}"); + unlink_if_exists("{$suricata_rules_upd_log}"); } if ($_POST['update']) { @@ -130,12 +130,9 @@ if ($_POST['force']) { 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"); + unlink_if_exists("{$suricatadir}{$emergingthreats_filename}.md5"); + unlink_if_exists("{$suricatadir}{$snort_community_rules_filename}.md5"); + unlink_if_exists("{$suricatadir}{$snort_rules_file}.md5"); // Revert file system to R/O. conf_mount_ro(); @@ -195,6 +192,7 @@ include_once("head.inc"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_etiqrisk_update.php b/config/suricata/suricata_etiqrisk_update.php new file mode 100644 index 00000000..6723ce99 --- /dev/null +++ b/config/suricata/suricata_etiqrisk_update.php @@ -0,0 +1,211 @@ +<?php +/* + * suricata_etiqrisk_update.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("config.inc"); +require_once("functions.inc"); +require_once("/usr/local/pkg/suricata/suricata.inc"); + +/************************************************************************* + * Hack for backwards compatibility with older 2.1.x pfSense versions * + * that did not contain the new "download_file()" utility function * + * present in 2.2 and higher. * + *************************************************************************/ +if(!function_exists("download_file")) { + function download_file($url, $destination, $verify_ssl = false, $connect_timeout = 60, $timeout = 0) { + global $config, $g; + + $fp = fopen($destination, "wb"); + + if (!$fp) + return false; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl); + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout); + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version"))); + + if (!empty($config['system']['proxyurl'])) { + curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']); + if (!empty($config['system']['proxyport'])) + curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']); + if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) { + @curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE); + curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}"); + } + } + + @curl_exec($ch); + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + fclose($fp); + curl_close($ch); + return ($http_code == 200) ? true : $http_code; + } +} + +function suricata_check_iprep_md5($filename) { + + /**********************************************************/ + /* This function attempts to download the MD5 hash for */ + /* the passed file and compare its contents to the */ + /* currently stored hash file to see if a new file has */ + /* been posted. */ + /* */ + /* On Entry: $filename = IPREP file to check ('md5sum' */ + /* is auto-appended to the supplied */ + /* filename.) */ + /* */ + /* Returns: TRUE if new rule file download required. */ + /* FALSE if rule download not required or an */ + /* error occurred. */ + /**********************************************************/ + + global $et_iqrisk_url, $iqRisk_tmppath, $iprep_path; + $new_md5 = $old_md5 = ""; + + if (download_file("{$et_iqrisk_url}{$filename}.md5sum", "{$iqRisk_tmppath}{$filename}.md5") == true) { + if (file_exists("{$iqRisk_tmppath}{$filename}.md5")) + $new_md5 = file_get_contents("{$iqRisk_tmppath}{$filename}.md5"); + if (file_exists("{$iprep_path}{$filename}.md5")) + $old_md5 = file_get_contents("{$iprep_path}{$filename}.md5"); + if ($new_md5 != $old_md5) + return TRUE; + else + log_error(gettext("[Suricata] IPREP file '{$filename}' is up to date.")); + } + else + log_error(gettext("[Suricata] An error occurred downloading {$filename}.md5sum for IPREP. Update of {$filename} file will be skipped.")); + + return FALSE; +} + +/********************************************************************** + * Start of main code * + **********************************************************************/ +global $g, $config; +$iprep_path = SURICATA_IPREP_PATH; +$iqRisk_tmppath = "{$g['tmp_path']}/IQRisk/"; +$success = FALSE; + +// If auto-updates of ET IQRisk are disabled, then exit +if ($config['installedpackages']['suricata']['config'][0]['et_iqrisk_enable'] == "off") + return(0); +else + log_error(gettext("[Suricata] Updating the Emerging Threats IQRisk IP List...")); + +// Construct the download URL using the saved ET IQRisk Subscriber Code +if (!empty($config['installedpackages']['suricata']['config'][0]['iqrisk_code'])) { + $et_iqrisk_url = str_replace("_xxx_", $config['installedpackages']['suricata']['config'][0]['iqrisk_code'], ET_IQRISK_DNLD_URL); +} +else { + log_error(gettext("[Suricata] No IQRisk subscriber code found! Aborting scheduled update of Emerging Threats IQRisk IP List.")); + return(0); +} + +// Download the IP List files to a temporary location +safe_mkdir("$iqRisk_tmppath"); + +// Test the posted MD5 checksum file against our local copy +// to see if an update has been posted for 'categories.txt'. +if (suricata_check_iprep_md5("categories.txt")) { + log_error(gettext("[Suricata] An updated IPREP 'categories.txt' file is available...downloading new file.")); + if (download_file("{$et_iqrisk_url}categories.txt", "{$iqRisk_tmppath}categories.txt") != true) + log_error(gettext("[Suricata] An error occurred downloading the 'categories.txt' file for IQRisk.")); + else { + // If the files downloaded successfully, unpack them and store + // the list files in the SURICATA_IPREP_PATH directory. + if (file_exists("{$iqRisk_tmppath}categories.txt") && file_exists("{$iqRisk_tmppath}categories.txt.md5")) { + $new_md5 = file_get_contents("{$iqRisk_tmppath}categories.txt.md5"); + if ($new_md5 == trim(md5_file("{$iqRisk_tmppath}categories.txt"))) { + @rename("{$iqRisk_tmppath}categories.txt", "{$iprep_path}categories.txt"); + @rename("{$iqRisk_tmppath}categories.txt.md5", "{$iprep_path}categories.txt.md5"); + $success = TRUE; + log_error(gettext("[Suricata] Successfully updated IPREP file 'categories.txt'.")); + } + else + log_error(gettext("[Suricata] MD5 integrity check of downloaded 'categories.txt' file failed! Skipping update of this IPREP file.")); + } + } +} + +// Test the posted MD5 checksum file against our local copy +// to see if an update has been posted for 'iprepdata.txt.gz'. +if (suricata_check_iprep_md5("iprepdata.txt.gz")) { + log_error(gettext("[Suricata] An updated IPREP 'iprepdata.txt' file is available...downloading new file.")); + if (download_file("{$et_iqrisk_url}iprepdata.txt.gz", "{$iqRisk_tmppath}iprepdata.txt.gz") != true) + log_error(gettext("[Suricata] An error occurred downloading the 'iprepdata.txt.gz' file for IQRisk.")); + else { + // If the files downloaded successfully, unpack them and store + // the list files in the SURICATA_IPREP_PATH directory. + if (file_exists("{$iqRisk_tmppath}iprepdata.txt.gz") && file_exists("{$iqRisk_tmppath}iprepdata.txt.gz.md5")) { + $new_md5 = file_get_contents("{$iqRisk_tmppath}iprepdata.txt.gz.md5"); + if ($new_md5 == trim(md5_file("{$iqRisk_tmppath}iprepdata.txt.gz"))) { + mwexec("/usr/bin/gunzip -f {$iqRisk_tmppath}iprepdata.txt.gz"); + @rename("{$iqRisk_tmppath}iprepdata.txt", "{$iprep_path}iprepdata.txt"); + @rename("{$iqRisk_tmppath}iprepdata.txt.gz.md5", "{$iprep_path}iprepdata.txt.gz.md5"); + $success = TRUE; + log_error(gettext("[Suricata] Successfully updated IPREP file 'iprepdata.txt'.")); + } + else + log_error(gettext("[Suricata] MD5 integrity check of downloaded 'iprepdata.txt.gz' file failed! Skipping update of this IPREP file.")); + } + } +} + +// Cleanup the tmp directory path +rmdir_recursive("$iqRisk_tmppath"); + +log_error(gettext("[Suricata] Emerging Threats IQRisk IP List update finished.")); + +// If successful, signal any running Suricata process to live reload the rules and IP lists +if ($success == TRUE && is_process_running("suricata")) { + foreach ($config['installedpackages']['suricata']['rule'] as $value) { + if ($value['enable_iprep'] == "on") { + suricata_reload_config($value); + sleep(2); + } + } +} + +?> diff --git a/config/suricata/suricata_flow_stream.php b/config/suricata/suricata_flow_stream.php index 53c4e010..9467ea7c 100644 --- a/config/suricata/suricata_flow_stream.php +++ b/config/suricata/suricata_flow_stream.php @@ -467,6 +467,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td>'; @@ -479,6 +480,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}"); + $tab_array[] = array($menu_iface . gettext("IP Rep"), false, "/suricata/suricata_ip_reputation.php?id={$id}"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_generate_yaml.php b/config/suricata/suricata_generate_yaml.php index 8e3e538c..328702b9 100644 --- a/config/suricata/suricata_generate_yaml.php +++ b/config/suricata/suricata_generate_yaml.php @@ -53,13 +53,6 @@ foreach ($config_files as $file) { @copy("{$suricatadir}{$file}", "{$suricatacfgdir}/{$file}"); } -// Create required files if they don't exist -$suricata_files = array( "{$suricatacfgdir}/magic" ); -foreach ($suricata_files as $file) { - if (!file_exists($file)) - file_put_contents($file, "\n"); -} - // Read the configuration parameters for the passed interface // and construct appropriate string variables for use in the // suricata.yaml template include file. @@ -540,9 +533,10 @@ else // Add the OS-specific host policies if configured, otherwise // just set default to BSD for all networks. +$host_os_policy = ""; if (!is_array($suricatacfg['host_os_policy']['item'])) $suricatacfg['host_os_policy']['item'] = array(); -if (empty($suricatacfg['host_os_policy']['item'])) +if (count($suricatacfg['host_os_policy']['item']) < 1) $host_os_policy = "bsd: [0.0.0.0/0]"; else { foreach ($suricatacfg['host_os_policy']['item'] as $k => $v) { @@ -580,10 +574,12 @@ else { // Add the HTTP Server-specific policies if configured, otherwise // just set default to IDS for all networks. +$http_hosts_policy = ""; +$http_hosts_default_policy = ""; if (!is_array($suricatacfg['libhtp_policy']['item'])) $suricatacfg['libhtp_policy']['item'] = array(); -if (empty($suricatacfg['libhtp_policy']['item'])) { - $http_hosts_default_policy = "default-config:\n personality: IDS\n request-body-limit: 4096\n response-body-limit: 4096\n"; +if (count($suricatacfg['libhtp_policy']['item']) < 1) { + $http_hosts_default_policy = " personality: IDS\n request-body-limit: 4096\n response-body-limit: 4096\n"; $http_hosts_default_policy .= " double-decode-path: no\n double-decode-query: no\n uri-include-all: no\n"; } else { @@ -705,15 +701,41 @@ else $http_parser_memcap = "67108864"; /* Configure the IP REP section */ -$iprep_path = rtrim(IPREP_PATH, '/'); +$iprep_path = rtrim(SURICATA_IPREP_PATH, '/'); +$iprep_config = "# IP Reputation\n"; +if ($suricatacfg['enable_iprep'] == "on") { + $iprep_config .= "default-reputation-path: {$iprep_path}\n"; + $iprep_config .= "reputation-categories-file: {$iprep_path}/{$suricatacfg['iprep_catlist']}\n"; + $iprep_config .= "reputation-files:"; + + if (!is_array($suricatacfg['iplist_files']['item'])) + $suricatacfg['iplist_files']['item'] = array(); + + foreach ($suricatacfg['iplist_files']['item'] as $f) + $iprep_config .= "\n - $f"; +} + +/* Configure Host Table settings */ +if (!empty($suricatacfg['host_memcap'])) + $host_memcap = $suricatacfg['host_memcap']; +else + $host_memcap = "16777216"; +if (!empty($suricatacfg['host_hash_size'])) + $host_hash_size = $suricatacfg['host_hash_size']; +else + $host_hash_size = "4096"; +if (!empty($suricatacfg['host_prealloc'])) + $host_prealloc = $suricatacfg['host_prealloc']; +else + $host_prealloc = "1000"; // Create the rules files and save in the interface directory suricata_prepare_rule_files($suricatacfg, $suricatacfgdir); // Check and configure only non-empty rules files for the interface $rules_files = ""; -if (filesize("{$suricatacfgdir}/rules/".ENFORCING_RULES_FILENAME) > 0) - $rules_files .= ENFORCING_RULES_FILENAME; +if (filesize("{$suricatacfgdir}/rules/".SURICATA_ENFORCING_RULES_FILENAME) > 0) + $rules_files .= SURICATA_ENFORCING_RULES_FILENAME; if (filesize("{$suricatacfgdir}/rules/".FLOWBITS_FILENAME) > 0) $rules_files .= "\n - " . FLOWBITS_FILENAME; if (filesize("{$suricatacfgdir}/rules/custom.rules") > 0) diff --git a/config/suricata/suricata_geoipupdate.php b/config/suricata/suricata_geoipupdate.php new file mode 100644 index 00000000..46e1177e --- /dev/null +++ b/config/suricata/suricata_geoipupdate.php @@ -0,0 +1,137 @@ +<?php +/* + * suricata_geoipupdate.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. +*/ + +/* This product includes GeoLite data created by MaxMind, available from + * http://www.maxmind.com +*/ + +require_once("config.inc"); +require_once("functions.inc"); +require("/usr/local/pkg/suricata/suricata_defs.inc"); + +/************************************************************************* + * Hack for backwards compatibility with older 2.1.x pfSense versions * + * that did not contain the new "download_file()" utility function * + * present in 2.2 and higher. * + *************************************************************************/ +if(!function_exists("download_file")) { + function download_file($url, $destination, $verify_ssl = false, $connect_timeout = 60, $timeout = 0) { + global $config, $g; + + $fp = fopen($destination, "wb"); + + if (!$fp) + return false; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_ssl); + curl_setopt($ch, CURLOPT_FILE, $fp); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $connect_timeout); + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version"))); + + if (!empty($config['system']['proxyurl'])) { + curl_setopt($ch, CURLOPT_PROXY, $config['system']['proxyurl']); + if (!empty($config['system']['proxyport'])) + curl_setopt($ch, CURLOPT_PROXYPORT, $config['system']['proxyport']); + if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) { + @curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_ANY | CURLAUTH_ANYSAFE); + curl_setopt($ch, CURLOPT_PROXYUSERPWD, "{$config['system']['proxyuser']}:{$config['system']['proxypass']}"); + } + } + + @curl_exec($ch); + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + fclose($fp); + curl_close($ch); + return ($http_code == 200) ? true : $http_code; + } +} + +/********************************************************************** + * Start of main code * + **********************************************************************/ +global $g, $config; +$suricata_geoip_dbdir = SURICATA_PBI_BASEDIR . 'share/GeoIP/'; +$geoip_tmppath = "{$g['tmp_path']}/geoipup/"; + +// If auto-updates of GeoIP are disabled, then exit +if ($config['installedpackages']['suricata']['config'][0]['autogeoipupdate'] == "off") + exit(0); +else + log_error(gettext("[Suricata] Updating the GeoIP country database files...")); + + +// Download the free GeoIP Legacy country name databases for IPv4 and IPv6 +// to a temporary location. +safe_mkdir("$geoip_tmppath"); +if (download_file("http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz", "{$geoip_tmppath}GeoIP.dat.gz") != true) + log_error(gettext("[Suricata] An error occurred downloading the 'GeoIP.dat.gz' update file for GeoIP.")); +if (download_file("http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz", "{$geoip_tmppath}GeoIPv6.dat.gz") != true) + log_error(gettext("[Suricata] An error occurred downloading the 'GeoIPv6.dat.gz' update file for GeoIP.")); + +// Mount filesystem read-write since we need to write +// the extracted databases to PBI_BASE/share/GeoIP. +conf_mount_rw(); + +// If the files downloaded successfully, unpack them and store +// the DB files in the PBI_BASE/share/GeoIP directory. +if (file_exists("{$geoip_tmppath}GeoIP.dat.gz")) { + mwexec("/usr/bin/gunzip -f {$geoip_tmppath}GeoIP.dat.gz"); + @rename("{$geoip_tmppath}GeoIP.dat", "{$suricata_geoip_dbdir}GeoIP.dat"); +} + +if (file_exists("{$geoip_tmppath}GeoIPv6.dat.gz")) { + mwexec("/usr/bin/gunzip -f {$geoip_tmppath}GeoIPv6.dat.gz"); + @rename("{$geoip_tmppath}GeoIPv6.dat", "{$suricata_geoip_dbdir}GeoIPv6.dat"); +} + +// Finished with filesystem mods, so remount read-only +conf_mount_ro(); + +// Cleanup the tmp directory path +rmdir_recursive("$geoip_tmppath"); + +log_error(gettext("[Suricata] GeoIP database update finished.")); + +?> diff --git a/config/suricata/suricata_global.php b/config/suricata/suricata_global.php index 5f01a660..eb657465 100644 --- a/config/suricata/suricata_global.php +++ b/config/suricata/suricata_global.php @@ -66,6 +66,7 @@ else { $pconfig['forcekeepsettings'] = $config['installedpackages']['suricata']['config'][0]['forcekeepsettings']; $pconfig['snortcommunityrules'] = $config['installedpackages']['suricata']['config'][0]['snortcommunityrules']; $pconfig['snort_rules_file'] = $config['installedpackages']['suricata']['config'][0]['snort_rules_file']; + $pconfig['autogeoipupdate'] = $config['installedpackages']['suricata']['config'][0]['autogeoipupdate']; } // Do input validation on parameters @@ -97,6 +98,7 @@ if (!$input_errors) { $config['installedpackages']['suricata']['config'][0]['snortcommunityrules'] = $_POST['snortcommunityrules'] ? 'on' : 'off'; $config['installedpackages']['suricata']['config'][0]['enable_etopen_rules'] = $_POST['enable_etopen_rules'] ? 'on' : 'off'; $config['installedpackages']['suricata']['config'][0]['enable_etpro_rules'] = $_POST['enable_etpro_rules'] ? 'on' : 'off'; + $config['installedpackages']['suricata']['config'][0]['autogeoipupdate'] = $_POST['autogeoipupdate'] ? 'on' : 'off'; // If any rule sets are being turned off, then remove them // from the active rules section of each interface. Start @@ -140,12 +142,14 @@ if (!$input_errors) { $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 */ - $pos = strpos($_POST['autoruleupdatetime'], ":"); - if ($pos === false) { - $tmp = str_pad($_POST['autoruleupdatetime'], 4, "0", STR_PAD_LEFT); - $_POST['autoruleupdatetime'] = substr($tmp, 0, 2) . ":" . substr($tmp, -2); + if ($_POST['autoruleupdatetime']) { + $pos = strpos($_POST['autoruleupdatetime'], ":"); + if ($pos === false) { + $tmp = str_pad($_POST['autoruleupdatetime'], 4, "0", STR_PAD_LEFT); + $_POST['autoruleupdatetime'] = substr($tmp, 0, 2) . ":" . substr($tmp, -2); + } + $config['installedpackages']['suricata']['config'][0]['autoruleupdatetime'] = str_pad($_POST['autoruleupdatetime'], 4, "0", STR_PAD_LEFT); } - $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]['log_to_systemlog_facility'] = $_POST['log_to_systemlog_facility']; $config['installedpackages']['suricata']['config'][0]['live_swap_updates'] = $_POST['live_swap_updates'] ? 'on' : 'off'; @@ -153,10 +157,20 @@ if (!$input_errors) { $retval = 0; + write_config("Suricata pkg: modified global settings."); + + /* Toggle cron task for GeoIP database updates if setting was changed */ + if ($config['installedpackages']['suricata']['config'][0]['autogeoipupdate'] == 'on' && !suricata_cron_job_exists("/usr/local/pkg/suricata/suricata_geoipupdate.php")) { + include("/usr/local/pkg/suricata/suricata_geoipupdate.php"); + install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_geoipupdate.php", TRUE, 0, 0, 8, "*", "*", "root"); + } + elseif ($config['installedpackages']['suricata']['config'][0]['autogeoipupdate'] == 'off' && suricata_cron_job_exists("/usr/local/pkg/suricata/suricata_geoipupdate.php")) + install_cron_job("/usr/local/pkg/suricata/suricata_geoipupdate.php", FALSE); + /* create passlist and homenet file, then sync files */ + conf_mount_rw(); sync_suricata_package_config(); - - write_config("Suricata pkg: modified global settings."); + conf_mount_ro(); /* forces page to reload new settings */ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); @@ -202,6 +216,7 @@ if ($input_errors) $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td></tr> @@ -348,6 +363,15 @@ if ($input_errors) "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> + <td width="22%" valign="top" class="vncell"><?php echo gettext("GeoIP DB Update"); ?></td> + <td width="78%" class="vtable"><input name="autogeoipupdate" id="autogeoipupdate" type="checkbox" value="yes" + <?php if ($config['installedpackages']['suricata']['config'][0]['autogeoipupdate']=="on") echo " checked"; ?>/> + <?php echo gettext("Enable downloading of free GeoIP Country Database updates. Default is ") . "<strong>" . gettext("Checked") . "</strong>"; ?><br/><br/> + <?php echo gettext("When enabled, Suricata will automatically download updates for the free legacy GeoIP country database on the 8th of each month at midnight.") . + "<br/><br/>" . gettext("If you have a subscription for more current GeoIP updates, uncheck this option and instead create your own process to place the required database files in " . + SURICATA_PBI_BASEDIR . "share/GeoIP/."); ?></td> +</tr> +<tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Settings"); ?></td> </tr> <tr> diff --git a/config/suricata/suricata_interfaces.php b/config/suricata/suricata_interfaces.php index 3d093d45..e996a24f 100644 --- a/config/suricata/suricata_interfaces.php +++ b/config/suricata/suricata_interfaces.php @@ -68,8 +68,8 @@ if ($_POST['del_x']) { $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}"); + rmdir_recursive("{$suricatalogdir}suricata_{$if_real}{$suricata_uuid}"); + rmdir_recursive("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}"); unset($a_nat[$rulei]); } conf_mount_ro(); @@ -81,16 +81,9 @@ if ($_POST['del_x']) { write_config("Suricata pkg: deleted one or more Suricata interfaces."); sleep(2); - /* if there are no ifaces remaining do not create suricata.sh */ - if (!empty($config['installedpackages']['suricata']['rule'])) - suricata_create_rc(); - else { - conf_mount_rw(); - @unlink("{$rcdir}suricata.sh"); - conf_mount_ro(); - } - + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); @@ -110,7 +103,9 @@ if ($_POST['bartoggle']) { if (!suricata_is_running($suricatacfg['uuid'], $if_real, 'barnyard2')) { log_error("Toggle (barnyard starting) for {$if_friendly}({$suricatacfg['descr']})..."); + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); suricata_barnyard_start($suricatacfg, $if_real); } else { log_error("Toggle (barnyard stopping) for {$if_friendly}({$suricatacfg['descr']})..."); @@ -135,7 +130,9 @@ if ($_POST['toggle']) { log_error("Toggle (suricata starting) for {$if_friendly}({$suricatacfg['descr']})..."); // set flag to rebuild interface rules before starting Snort $rebuild_rules = true; + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); $rebuild_rules = false; suricata_start($suricatacfg, $if_real); } @@ -185,6 +182,7 @@ include_once("head.inc"); $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td> diff --git a/config/suricata/suricata_interfaces_edit.php b/config/suricata/suricata_interfaces_edit.php index c4a1775a..13526031 100644 --- a/config/suricata/suricata_interfaces_edit.php +++ b/config/suricata/suricata_interfaces_edit.php @@ -223,7 +223,9 @@ if ($_POST["save"] && !$input_errors) { suricata_stop($a_rule[$id], get_real_interface($a_rule[$id]['interface'])); write_config("Suricata pkg: disabled Suricata on " . convert_friendly_interface_to_friendly_descr($a_rule[$id]['interface'])); $rebuild_rules = false; + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); 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' ); @@ -316,9 +318,9 @@ if ($_POST["save"] && !$input_errors) { } else $suricata_start = false; - exec("mv -f {$suricatalogdir}suricata_{$oif_real}" . $a_rule[$id]['uuid'] . " {$suricatalogdir}suricata_{$if_real}" . $a_rule[$id]['uuid']); + @rename("{$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}"); + @rename("{$suricatadir}suricata_{$a_rule[$id]['uuid']}_{$oif_real}", "{$suricatadir}suricata_{$a_rule[$id]['uuid']}_{$if_real}"); conf_mount_ro(); } $a_rule[$id] = $natent; @@ -392,6 +394,11 @@ if ($_POST["save"] && !$input_errors) { $natent['smb_parser'] = "yes"; $natent['msn_parser'] = "detection-only"; + $natent['enable_iprep'] = "off"; + $natent['host_memcap'] = "16777216"; + $natent['host_hash_size'] = "4096"; + $natent['host_prealloc'] = "1000"; + $default = array( "name" => "default", "bind_to" => "all", "policy" => "bsd" ); if (!is_array($natent['host_os_policy']['item'])) $natent['host_os_policy']['item'] = array(); @@ -423,7 +430,9 @@ if ($_POST["save"] && !$input_errors) { write_config("Suricata pkg: modified interface configuration for " . convert_friendly_interface_to_friendly_descr($natent['interface'])); // Update suricata.conf and suricata.sh files for this interface + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' ); @@ -473,6 +482,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -485,6 +495,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}"); + $tab_array[] = array($menu_iface . gettext("IP Rep"), false, "/suricata/suricata_ip_reputation.php?id={$id}"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_ip_list_mgmt.php b/config/suricata/suricata_ip_list_mgmt.php new file mode 100644 index 00000000..ee3a7009 --- /dev/null +++ b/config/suricata/suricata_ip_list_mgmt.php @@ -0,0 +1,393 @@ +<?php +/* + * suricata_ip_list_mgmt.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"); + +global $config, $g; + +if (!is_array($config['installedpackages']['suricata']['rule'])) + $config['installedpackages']['suricata']['rule'] = array(); + +// Hard-code the path where IP Lists are stored +// and disregard any user-supplied path element. +$iprep_path = SURICATA_IPREP_PATH; + +// Set default to not show IP List editor controls +$iplist_edit_style = "display: none;"; + +function suricata_is_iplist_active($iplist) { + + /*************************************************** + * This function checks all configured Suricata * + * interfaces to see if the passed IP List is used * + * as a whitelist or blacklist by an interface. * + * * + * Returns: TRUE if IP List is in use * + * FALSE if IP List is not in use * + ***************************************************/ + + global $g, $config; + + if (!is_array($config['installedpackages']['suricata']['rule'])) + return FALSE; + + foreach ($config['installedpackages']['suricata']['rule'] as $rule) { + if (is_array($rule['iplist_files']['item'])) { + foreach ($rule['iplist_files']['item'] as $file) { + if ($file == $iplist) + return TRUE; + } + } + } + return FALSE; +} + +// If doing a postback, used typed values, else load from stored config +if (!empty($_POST)) { + $pconfig = $_POST; +} +else { + $pconfig['et_iqrisk_enable'] = $config['installedpackages']['suricata']['config'][0]['et_iqrisk_enable']; + $pconfig['iqrisk_code'] = $config['installedpackages']['suricata']['config'][0]['iqrisk_code']; +} + +// Validate IQRisk settings if enabled and saving them +if ($_POST['save']) { + if ($pconfig['et_iqrisk_enable'] == 'on' && empty($pconfig['iqrisk_code'])) + $input_errors[] = gettext("You must provide a valid IQRisk subscription code when IQRisk downloads are enabled!"); + + if (!$input_errors) { + $config['installedpackages']['suricata']['config'][0]['et_iqrisk_enable'] = $_POST['et_iqrisk_enable'] ? 'on' : 'off'; + $config['installedpackages']['suricata']['config'][0]['iqrisk_code'] = $_POST['iqrisk_code']; + write_config("Suricata pkg: modified IP Lists settings."); + + /* Toggle cron task for ET IQRisk updates if setting was changed */ + if ($config['installedpackages']['suricata']['config'][0]['et_iqrisk_enable'] == 'on' && !suricata_cron_job_exists("/usr/local/pkg/suricata/suricata_etiqrisk_update.php")) { + include("/usr/local/pkg/suricata/suricata_etiqrisk_update.php"); + install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_etiqrisk_update.php", TRUE, 0, 0, "*", "*", "*", "root"); + } + elseif ($config['installedpackages']['suricata']['config'][0]['et_iqrisk_enable'] == 'off' && suricata_cron_job_exists("/usr/local/pkg/suricata/suricata_etiqrisk_update.php")) + install_cron_job("/usr/local/pkg/suricata/suricata_etiqrisk_update.php", FALSE); + } +} + +if (isset($_POST['upload'])) { + if ($_FILES["iprep_fileup"]["error"] == UPLOAD_ERR_OK) { + $tmp_name = $_FILES["iprep_fileup"]["tmp_name"]; + $name = $_FILES["iprep_fileup"]["name"]; + move_uploaded_file($tmp_name, "{$iprep_path}{$name}"); + } + else + $input_errors[] = gettext("Failed to upload file {$_FILES["iprep_fileup"]["name"]}"); +} + +if (isset($_POST['iplist_delete']) && isset($_POST['iplist_fname'])) { + if (!suricata_is_iplist_active($_POST['iplist_fname'])) + unlink_if_exists("{$iprep_path}{$_POST['iplist_fname']}"); + else + $input_errors[] = gettext("This IP List is currently assigned to an interface and cannot be deleted until it is removed from the configured interface."); +} + +if (isset($_POST['iplist_edit']) && isset($_POST['iplist_fname'])) { + $file = $iprep_path . basename($_POST['iplist_fname']); + $data = file_get_contents($file); + if ($data !== FALSE) { + $iplist_data = htmlspecialchars($data); + $iplist_edit_style = "display: table-row-group;"; + $iplist_name = basename($_POST['iplist_fname']); + unset($data); + } + else { + $input_errors[] = gettext("An error occurred reading the file."); + } +} + +if (isset($_POST['iplist_edit_save']) && isset($_POST['iplist_data'])) { + if (strlen(basename($_POST['iplist_name'])) > 0) { + $file = $iprep_path . basename($_POST['iplist_name']); + $data = str_replace("\r\n", "\n", $_POST['iplist_data']); + file_put_contents($file, $data); + unset($data); + } + else { + $input_errors[] = gettext("You must provide a valid filename for the IP List."); + $iplist_edit_style = "display: table-row-group;"; + } +} + +// Get all files in the IP Lists sub-directory as an array +// Leave this as the last thing before spewing the page HTML +// so we can pick up any changes made to files in code above. +$ipfiles = return_dir_as_array($iprep_path); + +$pgtitle = gettext("Suricata: IP Reputation Lists"); +include_once("head.inc"); + +?> + +<body link="#000000" vlink="#000000" alink="#000000"> + +<?php +include_once("fbegin.inc"); +if ($input_errors) { + print_input_errors($input_errors); +} + +if ($savemsg) + print_info_box($savemsg); +?> + +<form action="/suricata/suricata_ip_list_mgmt.php" enctype="multipart/form-data" method="post" name="iform" id="iform"> +<input type="hidden" name="MAX_FILE_SIZE" value="100000000" /> +<input type="hidden" name="iplist_fname" id="iplist_fname" value=""/> +<table width="100%" border="0" cellpadding="0" cellspacing="0"> +<tbody> +<tr><td> +<?php + $tab_array = array(); + $tab_array[] = array(gettext("Interfaces"), false, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocks"), 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 View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), true, "/suricata/suricata_ip_list_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"> + <tbody> + <?php if ($g['platform'] == "nanobsd") : ?> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("IP Reputation is not supported on NanoBSD installs"); ?></td> + </tr> + <?php else: ?> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("Emerging Threats IQRisk Settings"); ?></td> + </tr> + <tr> + <td width="22%" valign="top"><?php echo gettext("Enable"); ?></td> + <td width="78%"> + <input id="et_iqrisk_enable" name="et_iqrisk_enable" type="checkbox" value="on" <?php if ($pconfig['et_iqrisk_enable'] == "on") echo "checked"; ?> onclick="IQRisk_enablechange();"/> + <?php echo gettext("Checking this box enables auto-download of IQRisk List updates with a valid subscription code."); ?> + </td> + </tr> + <tr> + <td width="22%"></td> + <td width="78%"> + <table id="iqrisk_code_tbl" width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> + <tr> + <td colspan="2" class="vexpl"><?=gettext("IQRisk IP lists will auto-update nightly at midnight. Visit ") . + "<a href='http://emergingthreats.net/products/iqrisk-rep-list/' target='_blank'>" . gettext("http://emergingthreats.net/products/iqrisk-rep-list/") . "</a>" . + gettext(" for more information or to purchase a subscription.");?><br/><br/></td> + </tr> + <tr> + <td colspan="2" valign="top"><b><span class="vexpl"><?php echo gettext("IQRisk Subscription Configuration"); ?></span></b></td> + </tr> + <tr> + <td valign="top"><span class="vexpl"><strong><?php echo gettext("Code:"); ?></strong></span></td> + <td><input name="iqrisk_code" type="text" class="formfld unknown" id="iqrisk_code" size="52" + value="<?=htmlspecialchars($pconfig['iqrisk_code']);?>"/><br/> + <?php echo gettext("Obtain an Emerging Threats IQRisk List subscription code and paste it here."); ?></td> + </tr> + </tbody> + </table> + </td> + </tr> + <tr> + <td colspan="2" align="center"><input name="save" id="save" type="submit" class="formbtn" value="Save" title="<?=gettext("Save IQRisk settings");?>"/></td> + </tr> + <tr> + <td colspan="2" class="vtable"></td> + </tr> + <tr> + <td colspan="2" class="listtopic"><?=gettext("IP Reputation List Files Management");?> + </td> + </tr> + <tbody id="uploader" style="display: none;"> + <tr> + <td colspan="2" class="list"><br/><?php echo gettext("Click BROWSE to select a file to import, and then click UPLOAD. Click CLOSE to quit."); ?></td> + </tr> + <tr> + <td colspan="2" class="list"><input type="file" name="iprep_fileup" id="iprep_fileup" class="formfld file" size="50" /> + <input type="submit" name="upload" id="upload" value="<?=gettext("Upload");?>" + title="<?=gettext("Upload selected IP list to firewall");?>"/> <input type="button" + value="<?=gettext("Close");?>" onClick="document.getElementById('uploader').style.display='none';" /></td> + </tr> + </tbody> + <tr> + <td colspan="2"> + <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0"> + <colgroup> + <col style="width: 50%;"> + <col style="width: 25%;"> + <col style="width: 15%;"> + <col style="width: 10%;"> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?php echo gettext("IP List File Name"); ?></th> + <th class="listhdrr"><?php echo gettext("Last Modified Time"); ?></th> + <th class="listhdrr"><?php echo gettext("File Size"); ?></th> + <th class="list" align="left"><img style="cursor:pointer;" name="iplist_new" id="iplist_new" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" + height="17" border="0" title="<?php echo gettext('Create a new IP List');?>" + onClick="document.getElementById('iplist_data').value=''; document.getElementById('iplist_name').value=''; document.getElementById('iplist_editor').style.display='table-row-group'; document.getElementById('iplist_name').focus();" /> + <img style="cursor:pointer;" name="iplist_import" id="iplist_import" + onClick="document.getElementById('uploader').style.display='table-row-group';" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_import_alias.gif" width="17" + height="17" border="0" title="<?php echo gettext('Import/Upload an IP List');?>"/></th> + </tr> + </thead> + <?php foreach ($ipfiles as $file): ?> + <tr> + <td class="listr"><?php echo gettext($file); ?></td> + <td class="listr"><?=date('M-d Y g:i a', filemtime("{$iprep_path}{$file}")); ?></td> + <td class="listr"><?=format_bytes(filesize("{$iprep_path}{$file}")); ?> </td> + <td class="list"><input type="image" name="iplist_edit[]" id="iplist_edit[]" + onClick="document.getElementById('iplist_fname').value='<?=$file;?>';" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" + height="17" border="0" title="<?php echo gettext('Edit this IP List');?>"/> + <input type="image" name="iplist_delete[]" id="iplist_delete[]" + onClick="document.getElementById('iplist_fname').value='<?=$file;?>'; + return confirm('<?=gettext("Are you sure you want to permanently delete this IP List file? 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 this IP List');?>"/></td> + </tr> + <?php endforeach; ?> + <tbody id="iplist_editor" style="<?=$iplist_edit_style;?>"> + <tr> + <td colspan="4"> </td> + </tr> + <tr> + <td colspan="4"><strong><?=gettext("File Name: ");?></strong><input type="text" size="45" class="formfld file" id="iplist_name" name="iplist_name" value="<?=$iplist_name;?>" /> + <input type="submit" id="iplist_edit_save" name="iplist_edit_save" value="<?=gettext(" Save ");?>" title="<?=gettext("Save changes and close editor");?>" /> + <input type="button" id="cancel" name="cancel" value="<?=gettext("Cancel");?>" onClick="document.getElementById('iplist_editor').style.display='none';" + title="<?=gettext("Abandon changes and quit editor");?>" /></td> + </tr> + <tr> + <td colspan="4"> </td> + </tr> + <tr> + <td colspan="4"><textarea wrap="off" cols="80" rows="20" name="iplist_data" id="iplist_data" + style="width:95%; height:100%;"><?=$iplist_data;?></textarea> + </td> + </tr> + </tbody> + <tbody> + <tr> + <td colspan="3" class="vexpl"><br/><span class="red"><strong><?php echo gettext("Notes:"); ?></strong></span> + <br/><?php echo gettext("1. A Categories file is required and contains CSV fields for Category Number, Short Name " . + "and Description per line."); ?></td> + <td class="list"></td> + </tr> + <tr> + <td colspan="3" class="vexpl"><?php echo gettext("2. IP Lists are CSV format text files " . + "with an IP address, category code and reputation score per line."); ?></td> + <td class="list"></td> + </tr> + <tr> + <td colspan="3" class="vexpl"><?php echo gettext("3. IP Lists are stored as local files " . + "on the firewall and their contents are not saved as part of the firewall configuration file."); ?></td> + <td class="list"></td> + </tr> + <tr> + <td colspan="3" class="vexpl"><?php echo gettext("4. Visit ") . + "<a href='https://redmine.openinfosecfoundation.org/projects/suricata/wiki/IPReputationFormat' target='_blank'>" . + gettext("https://redmine.openinfosecfoundation.org/projects/suricata/wiki/IPReputationFormat") . "</a>" . + gettext(" for IP Reputation file formats."); ?><br/></td> + <td class="list"></td> + </tr> + <tr> + <td colspan="3" class="vexpl"><br/><strong><?php echo gettext("IP List Controls:"); ?></strong><br/><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the editor window to create a new IP List. You must provide a valid filename before saving.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_import_alias.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the file upload control for uploading a new IP List from your local machine.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the IP List in a text edit control for viewing or editing its contents.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0" /> + <?=gettext("Deletes the IP List from the file system after confirmation.");?></td> + <td class="list"></td> + </tr> + </tbody> + </table> + </td> + </tr> + <?php endif; ?> + </tbody> + </table> + </div> + </td> +</tr> +</tbody> +</table> +</form> +<?php include("fend.inc"); ?> + +<script language="JavaScript"> +<!-- + +function IQRisk_enablechange() { + var endis = !(document.iform.et_iqrisk_enable.checked); + if (endis) + document.getElementById("iqrisk_code_tbl").style.display = "none"; + else + document.getElementById("iqrisk_code_tbl").style.display = "table"; +} + +// Initialize the form controls state based on saved settings +IQRisk_enablechange(); + +//--> +</script> +</body> +</html> diff --git a/config/suricata/suricata_ip_reputation.php b/config/suricata/suricata_ip_reputation.php new file mode 100644 index 00000000..4615923a --- /dev/null +++ b/config/suricata/suricata_ip_reputation.php @@ -0,0 +1,482 @@ +<?php +/* + * suricata_ip_reputation.php + * part of 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: + * + * 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, $rebuild_rules; + +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; +} + +if (!is_array($config['installedpackages']['suricata']['rule'])) { + $config['installedpackages']['suricata']['rule'] = array(); +} +if (!is_array($config['installedpackages']['suricata']['rule'][$id]['iplist_files']['item'])) { + $config['installedpackages']['suricata']['rule'][$id]['iplist_files']['item'] = array(); +} + +$a_nat = &$config['installedpackages']['suricata']['rule']; + +// If doing a postback, used typed values, else load from stored config +if (!empty($_POST)) { + $pconfig = $_POST; +} +else { + $pconfig = $a_nat[$id]; +} + +$iprep_path = SURICATA_IPREP_PATH; +$if_real = get_real_interface($a_nat[$id]['interface']); +$suricata_uuid = $config['installedpackages']['suricata']['rule'][$id]['uuid']; + +if ($_POST['mode'] == 'iprep_catlist_add' && isset($_POST['iplist'])) { + $pconfig = $_POST; + + // Test the supplied IP List file to see if it exists + if (file_exists($_POST['iplist'])) { + if (!$input_errors) { + $a_nat[$id]['iprep_catlist'] = basename($_POST['iplist']); + write_config("Suricata pkg: added new IP Rep Categories file for IP REPUTATION preprocessor."); + mark_subsystem_dirty('suricata_iprep'); + } + } + else + $input_errors[] = gettext("The file '{$_POST['iplist']}' could not be found."); + + $pconfig['iprep_catlist'] = $a_nat[$id]['iprep_catlist']; + $pconfig['iplist_files'] = $a_nat[$id]['iplist_files']; +} + +if ($_POST['mode'] == 'iplist_add' && isset($_POST['iplist'])) { + $pconfig = $_POST; + + // Test the supplied IP List file to see if it exists + if (file_exists($_POST['iplist'])) { + // See if the file is already assigned to the interface + foreach ($a_nat[$id]['iplist_files']['item'] as $f) { + if ($f == basename($_POST['iplist'])) { + $input_errors[] = gettext("The file {$f} is already assigned as a whitelist file."); + break; + } + } + if (!$input_errors) { + $a_nat[$id]['iplist_files']['item'][] = basename($_POST['iplist']); + write_config("Suricata pkg: added new whitelist file for IP REPUTATION preprocessor."); + mark_subsystem_dirty('suricata_iprep'); + } + } + else + $input_errors[] = gettext("The file '{$_POST['iplist']}' could not be found."); + + $pconfig['iprep_catlist'] = $a_nat[$id]['iprep_catlist']; + $pconfig['iplist_files'] = $a_nat[$id]['iplist_files']; +} + +if ($_POST['iprep_catlist_del']) { + $pconfig = $_POST; + unset($a_nat[$id]['iprep_catlist']); + write_config("Suricata pkg: deleted blacklist file for IP REPUTATION preprocessor."); + mark_subsystem_dirty('suricata_iprep'); + $pconfig['iprep_catlist'] = $a_nat[$id]['iprep_catlist']; + $pconfig['iplist_files'] = $a_nat[$id]['iplist_files']; +} + +if ($_POST['iplist_del'] && is_numericint($_POST['list_id'])) { + $pconfig = $_POST; + unset($a_nat[$id]['iplist_files']['item'][$_POST['list_id']]); + write_config("Suricata pkg: deleted whitelist file for IP REPUTATION preprocessor."); + mark_subsystem_dirty('suricata_iprep'); + $pconfig['iplist_files'] = $a_nat[$id]['iplist_files']; + $pconfig['iprep_catlist'] = $a_nat[$id]['iprep_catlist']; +} + +if ($_POST['save'] || $_POST['apply']) { + + $pconfig['iprep_catlist'] = $a_nat[$id]['iprep_catlist']; + $pconfig['iplist_files'] = $a_nat[$id]['iplist_files']; + + // Validate HOST TABLE values + if ($_POST['host_memcap'] < 1000000 || !is_numericint($_POST['host_memcap'])) + $input_errors[] = gettext("The value for 'Host Memcap' must be a numeric integer greater than 1MB (1,048,576!"); + if ($_POST['host_hash_size'] < 1024 || !is_numericint($_POST['host_hash_size'])) + $input_errors[] = gettext("The value for 'Host Hash Size' must be a numeric integer greater than 1024!"); + if ($_POST['host_prealloc'] < 10 || !is_numericint($_POST['host_prealloc'])) + $input_errors[] = gettext("The value for 'Host Preallocations' must be a numeric integer greater than 10!"); + + // Validate CATEGORIES FILE + if ($_POST['enable_iprep'] == 'on') { + if (empty($a_nat[$id]['iprep_catlist'])) + $input_errors[] = gettext("Assignment of a 'Categories File' is required when IP Reputation is enabled!"); + } + + // If no errors write to conf + if (!$input_errors) { + + $a_nat[$id]['enable_iprep'] = $_POST['enable_iprep'] ? 'on' : 'off'; + $a_nat[$id]['host_memcap'] = str_replace(",", "", $_POST['host_memcap']); + $a_nat[$id]['host_hash_size'] = str_replace(",", "", $_POST['host_hash_size']); + $a_nat[$id]['host_prealloc'] = str_replace(",", "", $_POST['host_prealloc']); + + write_config("Suricata pkg: modified IP REPUTATION preprocessor settings for {$a_nat[$id]['interface']}."); + + // Update the suricata conf file for this interface + $rebuild_rules = false; + conf_mount_rw(); + suricata_generate_yaml($a_nat[$id]); + conf_mount_ro(); + + // Soft-restart Suricata to live-load new variables + suricata_reload_config($a_nat[$id]); + + // We have saved changes and done a soft restart, so clear "dirty" flag + clear_subsystem_dirty('suricata_iprep'); + } +} + +$if_friendly = convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface']); +$pgtitle = gettext("Suricata: Interface {$if_friendly} IP Reputation Preprocessor"); +include_once("head.inc"); + +?> +<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> + +<?php +include("fbegin.inc"); +/* Display Alert message */ +if ($input_errors) + print_input_errors($input_errors); +if ($savemsg) + print_info_box($savemsg); +?> + +<form action="suricata_ip_reputation.php" method="post" name="iform" id="iform" > +<input name="id" type="hidden" value="<?=$id;?>" /> +<input type="hidden" id="mode" name="mode" value="" /> +<input name="iplist" id="iplist" type="hidden" value="" /> +<input name="list_id" id="list_id" type="hidden" value="" /> + +<?php if (is_subsystem_dirty('suricata_iprep') && !$input_errors): ?><p> +<?php print_info_box_np(gettext("A change has been made to IP List file assignments.") . "<br/>" . gettext("You must apply the change in order for it to take effect."));?> +<?php endif; ?> + +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr> + <td> + <?php + $tab_array = array(); + $tab_array[] = array(gettext("Interfaces"), true, "/suricata/suricata_interfaces.php"); + $tab_array[] = array(gettext("Global Settings"), false, "/suricata/suricata_global.php"); + $tab_array[] = array(gettext("Updates"), false, "/suricata/suricata_download_updates.php"); + $tab_array[] = array(gettext("Alerts"), false, "/suricata/suricata_alerts.php?instance={$id}"); + $tab_array[] = array(gettext("Blocks"), 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 View"), false, "/suricata/suricata_logs_browser.php?instance={$id}"); + $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); + $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); + $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); + display_top_tabs($tab_array, true); + echo '</td></tr>'; + echo '<tr><td class="tabnavtbl">'; + $tab_array = array(); + $menu_iface=($if_friendly?substr($if_friendly,0,5)." ":"Iface "); + $tab_array[] = array($menu_iface . gettext("Settings"), false, "/suricata/suricata_interfaces_edit.php?id={$id}"); + $tab_array[] = array($menu_iface . gettext("Categories"), false, "/suricata/suricata_rulesets.php?id={$id}"); + $tab_array[] = array($menu_iface . gettext("Rules"), false, "/suricata/suricata_rules.php?id={$id}"); + $tab_array[] = array($menu_iface . gettext("Flow/Stream"), false, "/suricata/suricata_flow_stream.php?id={$id}"); + $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}"); + $tab_array[] = array($menu_iface . gettext("IP Rep"), true, "/suricata/suricata_ip_reputation.php?id={$id}"); + 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"> + <tbody> + <?php if ($g['platform'] == "nanobsd") : ?> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("IP Reputation is not supported on NanoBSD installs"); ?></td> + </tr> + <?php else: ?> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("IP Reputation Configuration"); ?></td> + </tr> + <tr> + <td width="22%" valign='top' class='vncell'><?php echo gettext("Enable"); ?> + </td> + <td width="78%" class="vtable"><input name="enable_iprep" type="checkbox" value="on" <?php if ($pconfig['enable_iprep'] == "on") echo "checked"; ?>/> + <?php echo gettext("Use IP Reputation Lists on this interface. Default is ") . "<strong>" . gettext("Not Checked.") . "</strong>"; ?> + </td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Host Memcap"); ?></td> + <td width="78%" class="vtable"><input name="host_memcap" type="text" + class="formfld unknown" id="host_memcap" size="8" value="<?=htmlspecialchars($pconfig['host_memcap']); ?>"/> + <?php echo gettext("Host table memory cap in bytes. Default is ") . "<strong>" . + gettext("16777216") . "</strong>" . gettext(" (16 MB). Min value is 1048576 (1 MB)."); ?><br/><br/><?php echo gettext("When using large IP Reputation Lists, this value may need to be increased " . + "to avoid exhausting Host Table memory.") ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Host Hash Size"); ?></td> + <td width="78%" class="vtable"><input name="host_hash_size" type="text" + class="formfld unknown" id="host_hash_size" size="8" value="<?=htmlspecialchars($pconfig['host_hash_size']); ?>"/> + <?php echo gettext("Host Hash Size in bytes. Default is ") . "<strong>" . + gettext("4096") . "</strong>" . gettext(". Min value is 1024."); ?><br/><br/><?php echo gettext("When using large IP Reputation Lists, this value may need to be increased."); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Host Preallocations"); ?></td> + <td width="78%" class="vtable"><input name="host_prealloc" type="text" + class="formfld unknown" id="host_prealloc" size="8" value="<?=htmlspecialchars($pconfig['host_prealloc']); ?>"/> + <?php echo gettext("Number of Host Table entries to preallocate. Default is ") . "<strong>" . + gettext("1000") . "</strong>" . gettext(". Min value is 10."); ?><br/><br/><?php echo gettext("Increasing this value may slightly improve performance when using large IP Reputation Lists."); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"> </td> + <td width="78%" class="vtable"> + <input name="save" type="submit" class="formbtn" value="Save" title="<?=gettext("Save IP Reputation configuration");?>" /> + <?=gettext("Click to save configuration settings and live-reload the running Suricata configuration.");?> + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Assign Categories File"); ?></td> + </tr> + <tr> + <td width="22%" valign='top' class='vncell'><?php echo gettext("Categories File"); ?> + </td> + <td width="78%" class="vtable"> + <!-- iprep_catlist_chooser --> + <div id="iprep_catlistChooser" name="iprep_catlistChooser" style="display:none; border:1px dashed gray; width:98%;"></div> + <table width="95%" border="0" cellpadding="2" cellspacing="0"> + <colgroup> + <col style="text-align:left;"> + <col style="width: 30%; text-align:left;"> + <col style="width: 17px;"> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?php echo gettext("Categories Filename"); ?></th> + <th class="listhdrr"><?php echo gettext("Modification Time"); ?></th> + <th class="list" align="left" valign="middle"><img style="cursor:pointer;" name="iprep_catlist_add" id="iprep_catlist_add" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" + height="17" border="0" title="<?php echo gettext('Assign a Categories file');?>"/></th> + </tr> + </thead> + <tbody> + <?php if (!empty($pconfig['iprep_catlist'])) : + $class = "listr"; + if (!file_exists("{$iprep_path}{$pconfig['iprep_catlist']}")) { + $filedate = gettext("Unknown -- file missing"); + $class .= " red"; + } + else + $filedate = date('M-d Y g:i a', filemtime("{$iprep_path}{$pconfig['iprep_catlist']}")); + ?> + <tr> + <td class="<?=$class;?>"><?=htmlspecialchars($pconfig['iprep_catlist']);?></td> + <td class="<?=$class;?>" align="center"><?=$filedate;?></td> + <td class="list"><input type="image" name="iprep_catlist_del[]" id="iprep_catlist_del[]" onClick="document.getElementById('list_id').value='0';" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" + border="0" title="<?php echo gettext('Remove this Categories file');?>"/></td> + </tr> + <?php endif; ?> + <tr> + <td colspan="2" class="vexpl"><span class="red"><strong><?=gettext("Note: ");?></strong></span> + <?=gettext("change to Categories File assignment is immediately saved.");?></td> + </tr> + </tbody> + </table> + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Assign IP Reputation Lists"); ?></td> + </tr> + <tr> + <td width="22%" valign='top' class='vncell'><?php echo gettext("IP Reputation Files"); ?> + </td> + <td width="78%" class="vtable"> + <table width="95%" border="0" cellpadding="2" cellspacing="0"> + <!-- iplist_chooser --> + <div id="iplistChooser" name="iplistChooser" style="display:none; border:1px dashed gray; width:98%;"></div> + <colgroup> + <col style="text-align:left;"> + <col style="width: 30%; text-align:left;"> + <col style="width: 17px;"> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?php echo gettext("IP Reputation List Filename"); ?></th> + <th class="listhdrr"><?php echo gettext("Modification Time"); ?></th> + <th class="list" align="left" valign="middle"><img style="cursor:pointer;" name="iplist_add" id="iplist_add" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" + border="0" title="<?php echo gettext('Assign a whitelist file');?>"/></th> + </tr> + </thead> + <tbody> + <?php foreach($pconfig['iplist_files']['item'] as $k => $f): + $class = "listr"; + if (!file_exists("{$iprep_path}{$f}")) { + $filedate = gettext("Unknown -- file missing"); + $class .= " red"; + } + else + $filedate = date('M-d Y g:i a', filemtime("{$iprep_path}{$f}")); + ?> + <tr> + <td class="<?=$class;?>"><?=htmlspecialchars($f);?></td> + <td class="<?=$class;?>" align="center"><?=$filedate;?></td> + <td class="list"><input type="image" name="iplist_del[]" id="iplist_del[]" onClick="document.getElementById('list_id').value='<?=$k;?>';" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" + border="0" title="<?php echo gettext('Remove this whitelist file');?>"/></td> + </tr> + <?php endforeach; ?> + <tr> + <td colspan="2" class="vexpl"><span class="red"><strong><?=gettext("Note: ");?></strong></span> + <?=gettext("changes to IP Reputation List assignments are immediately saved.");?></td> + </tr> + </tbody> + </table> + </td> + </tr> + <?php endif; ?> + </tbody> + </table> + </div> + </td> + </tr> + </tbody> +</table> + +<?php if ($g['platform'] != "nanobsd") : ?> +<script type="text/javascript"> +Event.observe( + window, "load", + function() { + Event.observe( + "iprep_catlist_add", "click", + function() { + Effect.Appear("iprep_catlistChooser", { duration: 0.25 }); + iprep_catlistChoose(); + } + ); + + Event.observe( + "iplist_add", "click", + function() { + Effect.Appear("iplistChooser", { duration: 0.25 }); + iplistChoose(); + } + ); + } +); + +function iprep_catlistChoose() { + Effect.Appear("iprep_catlistChooser", { duration: 0.25 }); + if($("fbCurrentDir")) + $("fbCurrentDir").innerHTML = "Loading ..."; + + new Ajax.Request( + "/suricata/suricata_iprep_list_browser.php?container=iprep_catlistChooser&target=iplist&val=" + new Date().getTime(), + { method: "get", onComplete: iprep_catlistComplete } + ); +} + +function iplistChoose() { + Effect.Appear("iplistChooser", { duration: 0.25 }); + if($("fbCurrentDir")) + $("fbCurrentDir").innerHTML = "Loading ..."; + + new Ajax.Request( + "/suricata/suricata_iprep_list_browser.php?container=iplistChooser&target=iplist&val=" + new Date().getTime(), + { method: "get", onComplete: iplistComplete } + ); +} + +function iprep_catlistComplete(req) { + $("iprep_catlistChooser").innerHTML = req.responseText; + + var actions = { + fbClose: function() { $("iprep_catlistChooser").hide(); }, + fbFile: function() { $("iplist").value = this.id; + $("mode").value = 'iprep_catlist_add'; + document.getElementById('iform').submit(); + } + } + + for(var type in actions) { + var elem = $("iprep_catlistChooser"); + var list = elem.getElementsByClassName(type); + for (var i=0; i<list.length; i++) { + Event.observe(list[i], "click", actions[type]); + list[i].style.cursor = "pointer"; + } + } +} + +function iplistComplete(req) { + $("iplistChooser").innerHTML = req.responseText; + + var actions = { + fbClose: function() { $("iplistChooser").hide(); }, + fbFile: function() { $("iplist").value = this.id; + $("mode").value = 'iplist_add'; + document.getElementById('iform').submit(); + } + } + + for(var type in actions) { + var elem = $("iplistChooser"); + var list = elem.getElementsByClassName(type); + for (var i=0; i<list.length; i++) { + Event.observe(list[i], "click", actions[type]); + list[i].style.cursor = "pointer"; + } + } +} + +</script> +<?php endif; ?> + +</form> +<?php include("fend.inc"); ?> +</body> +</html> diff --git a/config/suricata/suricata_iprep_list_browser.php b/config/suricata/suricata_iprep_list_browser.php new file mode 100644 index 00000000..9dd65311 --- /dev/null +++ b/config/suricata/suricata_iprep_list_browser.php @@ -0,0 +1,99 @@ +<?php + +require_once("guiconfig.inc"); +require_once("/usr/local/pkg/suricata/suricata.inc"); + +// Fetch a list of files inside a given directory +function get_content($dir) { + $files = array(); + + clearstatcache(); + $fd = @opendir($dir); + while($entry = @readdir($fd)) { + if($entry == ".") continue; + if($entry == "..") continue; + + if(is_dir("{$dir}/{$entry}")) + continue; + else + array_push($files, $entry); + } + @closedir($fd); + natsort($files); + return $files; +} + +$path = SURICATA_IPREP_PATH; +$container = htmlspecialchars($_GET['container']); +$target = htmlspecialchars($_GET['target']); + +// ----- header ----- +?> +<table width="100%"> + <tr> + <td width="25px" align="left"> + <img src="/filebrowser/images/icon_home.gif" alt="Home" title="Home" /> + </td> + <td><b><?=$path;?></b></td> + <td class="fbClose" align="right"> + <img onClick="$('<?=$container;?>').hide();" border="0" src="/filebrowser/images/icon_cancel.gif" alt="Close" title="Close" /> + </td> + </tr> + <tr> + <td id="fbCurrentDir" colspan="3" class="vexpl" align="left"> + </td> + </tr> +<?php +$files = get_content($path); + +// ----- files ----- +foreach($files as $file): + $ext = strrchr($file, "."); + + if($ext == ".css" ) $type = "code"; + elseif($ext == ".html") $type = "code"; + elseif($ext == ".xml" ) $type = "code"; + elseif($ext == ".rrd" ) $type = "database"; + elseif($ext == ".gif" ) $type = "image"; + elseif($ext == ".jpg" ) $type = "image"; + elseif($ext == ".png" ) $type = "image"; + elseif($ext == ".js" ) $type = "js"; + elseif($ext == ".pdf" ) $type = "pdf"; + elseif($ext == ".inc" ) $type = "php"; + elseif($ext == ".php" ) $type = "php"; + elseif($ext == ".conf") $type = "system"; + elseif($ext == ".pid" ) $type = "system"; + elseif($ext == ".sh" ) $type = "system"; + elseif($ext == ".bz2" ) $type = "zip"; + elseif($ext == ".gz" ) $type = "zip"; + elseif($ext == ".tgz" ) $type = "zip"; + elseif($ext == ".zip" ) $type = "zip"; + else $type = "generic"; + + $fqpn = "{$path}/{$file}"; + + if(is_file($fqpn)) { + $fqpn = realpath($fqpn); + $size = sprintf("%.2f KiB", filesize($fqpn) / 1024); + } + else + $size = ""; +?> + <tr> + <td></td> + <td class="fbFile vexpl" id="<?=$fqpn;?>" align="left"> + <?php $filename = str_replace("//","/", "{$path}/{$file}"); ?> + <div onClick="$('<?=$target;?>').value='<?=$filename?>'; $('<?=$container;?>').hide();"> + <img src="/filebrowser/images/file_<?=$type;?>.gif" alt="" title=""> + <?=$file;?> + </div> + </td> + <td align="right" class="vexpl"> + <?=$size;?> + </td> + </tr> +<?php +endforeach; +?> +</table> + diff --git a/config/suricata/suricata_logs_browser.php b/config/suricata/suricata_logs_browser.php index d4475625..320ba23f 100644 --- a/config/suricata/suricata_logs_browser.php +++ b/config/suricata/suricata_logs_browser.php @@ -151,6 +151,7 @@ if ($input_errors) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td> diff --git a/config/suricata/suricata_logs_mgmt.php b/config/suricata/suricata_logs_mgmt.php index fec2d149..aa353d6f 100644 --- a/config/suricata/suricata_logs_mgmt.php +++ b/config/suricata/suricata_logs_mgmt.php @@ -173,7 +173,9 @@ if ($_POST["save"] || $_POST['apply']) { if ($_POST['enable_log_mgmt'] != 'on') { $config['installedpackages']['suricata']['config'][0]['enable_log_mgmt'] = $_POST['enable_log_mgmt'] ? 'on' :'off'; write_config("Suricata pkg: saved updated configuration for LOGS MGMT."); + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); /* forces page to reload new settings */ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); @@ -222,7 +224,9 @@ if ($_POST["save"] || $_POST['apply']) { $config['installedpackages']['suricata']['config'][0]['sid_changes_log_retention'] = $_POST['sid_changes_log_retention']; write_config("Suricata pkg: saved updated configuration for LOGS MGMT."); + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); /* forces page to reload new settings */ header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' ); @@ -274,6 +278,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), true, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_migrate_config.php b/config/suricata/suricata_migrate_config.php index 4729109b..75e13315 100644 --- a/config/suricata/suricata_migrate_config.php +++ b/config/suricata/suricata_migrate_config.php @@ -71,12 +71,28 @@ if ($config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] /**********************************************************/ /* Create new Auto SID Mgmt settings if not set */ /**********************************************************/ - if (empty($config['installedpackages']['suricata']['config'][0]['auto_manage_sids'])) { - $config['installedpackages']['suricata']['config'][0]['auto_manage_sids'] = "off"; - $config['installedpackages']['suricata']['config'][0]['sid_changes_log_limit_size'] = "250"; - $config['installedpackages']['suricata']['config'][0]['sid_changes_log_retention'] = "336"; - $updated_cfg = true; - } +if (empty($config['installedpackages']['suricata']['config'][0]['auto_manage_sids'])) { + $config['installedpackages']['suricata']['config'][0]['auto_manage_sids'] = "off"; + $config['installedpackages']['suricata']['config'][0]['sid_changes_log_limit_size'] = "250"; + $config['installedpackages']['suricata']['config'][0]['sid_changes_log_retention'] = "336"; + $updated_cfg = true; +} + +/**********************************************************/ +/* Create new Auto GeoIP update setting if not set */ +/**********************************************************/ +if (empty($config['installedpackages']['suricata']['config'][0]['autogeoipupdate'])) { + $config['installedpackages']['suricata']['config'][0]['autogeoipupdate'] = "on"; + $updated_cfg = true; +} + +/**********************************************************/ +/* Create new ET IQRisk IP Reputation setting if not set */ +/**********************************************************/ +if (empty($config['installedpackages']['suricata']['config'][0]['et_iqrisk_enable'])) { + $config['installedpackages']['suricata']['config'][0]['et_iqrisk_enable'] = "off"; + $updated_cfg = true; +} // Now process the interface-specific settings foreach ($rule as &$r) { @@ -336,6 +352,26 @@ foreach ($rule as &$r) { $updated_cfg = true; } + /**********************************************************/ + /* Create interface IP Reputation settings if not set */ + /**********************************************************/ + if (empty($pconfig['enable_iprep'])) { + $pconfig['enable_iprep'] = "off"; + $updated_cfg = true; + } + if (empty($pconfig['host_memcap'])) { + $pconfig['host_memcap'] = "16777216"; + $updated_cfg = true; + } + if (empty($pconfig['host_hash_size'])) { + $pconfig['host_hash_size'] = "4096"; + $updated_cfg = true; + } + if (empty($pconfig['host_prealloc'])) { + $pconfig['host_prealloc'] = "1000"; + $updated_cfg = true; + } + // Save the new configuration data into the $config array pointer $r = $pconfig; } @@ -343,12 +379,8 @@ foreach ($rule as &$r) { unset($r); // Write out the new configuration to disk if we changed anything -if ($updated_cfg) { - $config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "2.0.2"; - log_error("[Suricata] Saving configuration settings in new format..."); - write_config("Suricata pkg: migrate existing settings to new format during package upgrade."); +if ($updated_cfg) log_error("[Suricata] Settings successfully migrated to new configuration format..."); -} else log_error("[Suricata] Configuration version is current..."); diff --git a/config/suricata/suricata_passlist.php b/config/suricata/suricata_passlist.php index 02aa4a3d..af1c4ff5 100644 --- a/config/suricata/suricata_passlist.php +++ b/config/suricata/suricata_passlist.php @@ -87,7 +87,9 @@ if ($_POST['del'] && is_numericint($_POST['list_id'])) { if (!$input_errors) { unset($a_passlist[$_POST['list_id']]); write_config("Suricata pkg: deleted PASS LIST."); + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); header("Location: /suricata/suricata_passlist.php"); exit; } @@ -130,6 +132,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td> diff --git a/config/suricata/suricata_passlist_edit.php b/config/suricata/suricata_passlist_edit.php index 3e1502f3..5bfeb8b9 100644 --- a/config/suricata/suricata_passlist_edit.php +++ b/config/suricata/suricata_passlist_edit.php @@ -182,7 +182,9 @@ if ($_POST['save']) { write_config("Suricata pkg: modified PASS LIST {$p_list['name']}."); /* create pass list and homenet file, then sync files */ + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); header("Location: /suricata/suricata_passlist.php"); exit; @@ -224,6 +226,7 @@ if ($savemsg) $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td> diff --git a/config/suricata/suricata_post_install.php b/config/suricata/suricata_post_install.php index 42f72eca..f4a66b0b 100644 --- a/config/suricata/suricata_post_install.php +++ b/config/suricata/suricata_post_install.php @@ -48,36 +48,36 @@ require_once("config.inc"); require_once("functions.inc"); require_once("/usr/local/pkg/suricata/suricata.inc"); +require("/usr/local/pkg/suricata/suricata_defs.inc"); global $config, $g, $rebuild_rules, $pkg_interface, $suricata_gui_include; /**************************************** * Define any new constants here that * * may not be yet defined in the old * - * "suricata.inc" include file that * - * might be cached and used by the * - * package manager installation code. * + * "suricata_defs.inc" include file * + * that might be cached and used by * + * the package manager installation * + * code. * * * * This is a hack to work around the * - * fact the old version of suricata.inc * + * fact the old version of the inc file * * is cached and used instead of the * - * updated version icluded with the * + * updated version included with the * * updated GUI package. * ****************************************/ -if (!defined('SID_MODS_PATH')) - define('SID_MODS_PATH', '/var/db/suricata/sidmods/'); -if (!defined('IPREP_PATH')) - define('IPREP_PATH', '/var/db/suricata/iprep/'); +if (!defined('SURICATA_PBI_BASEDIR')) + define('SURICATA_PBI_BASEDIR', '/usr/pbi/suricata-' . php_uname("m")); /**************************************** - * End of PHP cachine workaround * + * End of PHP caching workaround * ****************************************/ // Initialize some common values from defined constants $suricatadir = SURICATADIR; $suricatalogdir = SURICATALOGDIR; $flowbit_rules_file = FLOWBITS_FILENAME; -$suricata_enforcing_rules_file = ENFORCING_RULES_FILENAME; +$suricata_enforcing_rules_file = SURICATA_ENFORCING_RULES_FILENAME; $rcdir = RCFILEPREFIX; // Hard kill any running Suricata process that may have been started by any @@ -103,14 +103,28 @@ $g['suricata_postinstall'] = true; conf_mount_rw(); // Remove any previously installed script since we rebuild it -@unlink("{$rcdir}suricata.sh"); +unlink_if_exists("{$rcdir}suricata.sh"); // Create the top-tier log directory safe_mkdir(SURICATALOGDIR); // Create the IP Rep and SID Mods lists directory -safe_mkdir(SID_MODS_PATH); -safe_mkdir(IPREP_PATH); +safe_mkdir(SURICATA_SID_MODS_PATH); +safe_mkdir(SURICATA_IPREP_PATH); + +// Download the latest GeoIP DB updates and create cron task if the feature is not disabled +if ($config['installedpackages']['suricata']['config'][0]['autogeoipupdate'] != 'off') { + log_error(gettext("[Suricata] Installing free GeoIP country database files...")); + include("/usr/local/pkg/suricata/suricata_geoipupdate.php"); + install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_geoipupdate.php", TRUE, 0, 0, 8, "*", "*", "root"); +} + +// Download the latest ET IQRisk updates and create cron task if the feature is not disabled +if ($config['installedpackages']['suricata']['config'][0]['et_iqrisk_enable'] == 'on') { + log_error(gettext("[Suricata] Installing Emerging Threats IQRisk IP List...")); + include("/usr/local/pkg/suricata/suricata_etiqrisk_update.php"); + install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/suricata/suricata_etiqrisk_update.php", TRUE, 0, 0, "*", "*", "*", "root"); +} // remake saved settings if previously flagged if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] == 'on') { @@ -149,7 +163,6 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = log_error(gettext("[Suricata] updated UUID for interface " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . " from {$old_uuid} to {$new_uuid}.")); } } - write_config("Suricata pkg: updated interface UUIDs to eliminate duplicates."); unset($uuids, $rulesets); } /****************************************************************/ @@ -167,6 +180,7 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = include('/usr/local/pkg/suricata/suricata_check_for_rule_updates.php'); update_status(gettext("Generating suricata.yaml configuration file from saved settings...")); $rebuild_rules = true; + conf_mount_rw(); // Create the suricata.yaml files for each enabled interface $suriconf = $config['installedpackages']['suricata']['rule']; @@ -174,6 +188,7 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = $if_real = get_real_interface($suricatacfg['interface']); $suricata_uuid = $suricatacfg['uuid']; $suricatacfgdir = "{$suricatadir}suricata_{$suricata_uuid}_{$if_real}"; + update_output_window(gettext("Generating configuration for " . convert_friendly_interface_to_friendly_descr($suricatacfg['interface']) . "...")); // Pull in the PHP code that generates the suricata.yaml file // variables that will be substituted further down below. @@ -202,9 +217,6 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = 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'])) { if (strpos($config['widgets']['sequence'], "suricata_alerts-container") === FALSE) @@ -216,16 +228,20 @@ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] = } $rebuild_rules = false; - update_output_window(gettext("Finished rebuilding Suricata configuration files...")); + if ($pkg_interface <> "console") + update_output_window(gettext("Finished rebuilding Suricata configuration files...")); log_error(gettext("[Suricata] Finished rebuilding installation from saved settings...")); // Only try to start Suricata if not in reboot if (!$g['booting']) { - update_status(gettext("Starting Suricata using rebuilt configuration...")); - update_output_window(gettext("Please wait... while Suricata is started...")); - log_error(gettext("[Suricata] Starting Suricata using rebuilt configuration...")); - mwexec_bg("{$rcdir}suricata.sh start"); - update_output_window(gettext("Suricata has been started using the rebuilt configuration...")); + if ($pkg_interface <> "console") { + update_status(gettext("Starting Suricata using rebuilt configuration...")); + update_output_window(gettext("Please wait while Suricata is started...")); + mwexec("{$rcdir}suricata.sh start"); + update_output_window(gettext("Suricata has been started using the rebuilt configuration...")); + } + else + mwexec_bg("{$rcdir}suricata.sh start"); } } @@ -238,8 +254,8 @@ if (empty($config['installedpackages']['suricata']['config'][0]['forcekeepsettin conf_mount_ro(); // Update Suricata package version in configuration -$config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "2.0.2"; -write_config("Suricata pkg: updated GUI package version number."); +$config['installedpackages']['suricata']['config'][0]['suricata_config_ver'] = "2.1"; +write_config("Suricata pkg v2.1: post-install configuration saved."); // Done with post-install, so clear flag unset($g['suricata_postinstall']); diff --git a/config/suricata/suricata_rules.php b/config/suricata/suricata_rules.php index 539a1daf..480bf3dc 100644 --- a/config/suricata/suricata_rules.php +++ b/config/suricata/suricata_rules.php @@ -473,6 +473,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -485,6 +486,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}"); + $tab_array[] = array($menu_iface . gettext("IP Rep"), false, "/suricata/suricata_ip_reputation.php?id={$id}"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_rules_flowbits.php b/config/suricata/suricata_rules_flowbits.php index b16353cb..1bb945d8 100644 --- a/config/suricata/suricata_rules_flowbits.php +++ b/config/suricata/suricata_rules_flowbits.php @@ -139,7 +139,9 @@ if ($_POST['addsuppress'] && is_numeric($_POST['sid']) && is_numeric($_POST['gid if ($found_list) { write_config(); $rebuild_rules = false; + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); suricata_reload_config($a_nat[$id]); $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']}'."); } diff --git a/config/suricata/suricata_rulesets.php b/config/suricata/suricata_rulesets.php index 7ea672b1..7f591b6c 100644 --- a/config/suricata/suricata_rulesets.php +++ b/config/suricata/suricata_rulesets.php @@ -142,8 +142,7 @@ if ($_POST["save"]) { $a_nat[$id]['autoflowbitrules'] = 'on'; else { $a_nat[$id]['autoflowbitrules'] = 'off'; - if (file_exists("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}")) - @unlink("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}"); + unlink_if_exists("{$suricatadir}suricata_{$suricata_uuid}_{$if_real}/rules/{$flowbit_rules_file}"); } write_config("Suricata pkg: save enabled rule categories for {$a_nat[$id]['interface']}."); @@ -170,17 +169,43 @@ if ($_POST["save"]) { suricata_sync_on_changes(); } elseif ($_POST['unselectall']) { + if ($_POST['ips_policy_enable'] == "on") { + $a_nat[$id]['ips_policy_enable'] = 'on'; + $a_nat[$id]['ips_policy'] = $_POST['ips_policy']; + } + else { + $a_nat[$id]['ips_policy_enable'] = 'off'; + unset($a_nat[$id]['ips_policy']); + } + + $pconfig['autoflowbits'] = $_POST['autoflowbits']; + $pconfig['ips_policy_enable'] = $_POST['ips_policy_enable']; + $pconfig['ips_policy'] = $_POST['ips_policy']; + // Remove all but the default events and files rules $enabled_rulesets_array = array(); $enabled_rulesets_array = implode("||", $default_rules); $savemsg = gettext("All rule categories have been de-selected. "); - if ($_POST['ips_policy_enable']) + if ($_POST['ips_policy_enable'] == "on") $savemsg .= gettext("Only the rules included in the selected IPS Policy will be used."); else $savemsg .= gettext("There currently are no inspection rules enabled for this Suricata instance!"); } elseif ($_POST['selectall']) { + if ($_POST['ips_policy_enable'] == "on") { + $a_nat[$id]['ips_policy_enable'] = 'on'; + $a_nat[$id]['ips_policy'] = $_POST['ips_policy']; + } + else { + $a_nat[$id]['ips_policy_enable'] = 'off'; + unset($a_nat[$id]['ips_policy']); + } + + $pconfig['autoflowbits'] = $_POST['autoflowbits']; + $pconfig['ips_policy_enable'] = $_POST['ips_policy_enable']; + $pconfig['ips_policy'] = $_POST['ips_policy']; + // Start with the required default events and files rules $enabled_rulesets_array = $default_rules; @@ -265,6 +290,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -277,6 +303,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}"); + $tab_array[] = array($menu_iface . gettext("IP Rep"), false, "/suricata/suricata_ip_reputation.php?id={$id}"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_sid_mgmt.php b/config/suricata/suricata_sid_mgmt.php index 2224e81a..c2d58af8 100644 --- a/config/suricata/suricata_sid_mgmt.php +++ b/config/suricata/suricata_sid_mgmt.php @@ -55,7 +55,7 @@ $pconfig['auto_manage_sids'] = $config['installedpackages']['suricata']['config' // Hard-code the path where SID Mods Lists are stored // and disregard any user-supplied path element. -$sidmods_path = SID_MODS_PATH; +$sidmods_path = SURICATA_SID_MODS_PATH; // Set default to not show SID modification lists editor controls $sidmodlist_edit_style = "display: none;"; @@ -216,7 +216,7 @@ if (isset($_POST['sidlist_dnload']) && isset($_POST['sidlist_fname'])) { } if (isset($_POST['sidlist_dnload_all_x'])) { - $save_date = exec('/bin/date "+%Y-%m-%d-%H-%M-%S"'); + $save_date = date("Y-m-d-H-i-s"); $file_name = "suricata_sid_conf_files_{$save_date}.tar.gz"; exec("cd {$sidmods_path} && /usr/bin/tar -czf /tmp/{$file_name} *"); @@ -236,7 +236,7 @@ if (isset($_POST['sidlist_dnload_all_x'])) { readfile("/tmp/{$file_name}"); // Clean up the temp file - @unlink("/tmp/{$file_name}"); + unlink_if_exists("/tmp/{$file_name}"); } else $savemsg = gettext("An error occurred while creating the gzip archive!"); @@ -290,6 +290,7 @@ if ($savemsg) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), true, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td></tr> @@ -297,6 +298,11 @@ if ($savemsg) { <div id="mainarea"> <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> <tbody> + <?php if ($g['platform'] == "nanobsd") : ?> + <tr> + <td colspan="2" class="listtopic"><?php echo gettext("SID auto-management is not supported on NanoBSD installs"); ?></td> + </tr> + <?php else: ?> <tr> <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Settings"); ?></td> </tr> @@ -571,6 +577,7 @@ if ($savemsg) { <?=gettext("Remember to save changes before exiting this page"); ?> </td> </tr> + <?php endif; ?> </tbody> </table> </div> @@ -581,6 +588,8 @@ if ($savemsg) { <?php include("fend.inc"); ?> + +<?php if ($g['platform'] != "nanobsd") : ?> <script type="text/javascript"> function enable_sid_conf() { @@ -596,5 +605,7 @@ function enable_sid_conf() { enable_sid_conf(); </script> +<?php endif; ?> + </body> </html> diff --git a/config/suricata/suricata_suppress.php b/config/suricata/suricata_suppress.php index 80249724..8fcb3dd5 100644 --- a/config/suricata/suricata_suppress.php +++ b/config/suricata/suricata_suppress.php @@ -103,7 +103,9 @@ if ($_POST['del'] && is_numericint($_POST['list_id'])) { else { unset($a_suppress[$_POST['list_id']]); write_config("Suricata pkg: deleted SUPPRESS LIST."); + conf_mount_rw(); sync_suricata_package_config(); + conf_mount_ro(); header("Location: /suricata/suricata_suppress.php"); exit; } @@ -144,6 +146,7 @@ if ($input_errors) { $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td> diff --git a/config/suricata/suricata_suppress_edit.php b/config/suricata/suricata_suppress_edit.php index 24572789..8814d3db 100644 --- a/config/suricata/suricata_suppress_edit.php +++ b/config/suricata/suricata_suppress_edit.php @@ -168,6 +168,7 @@ if ($savemsg) $tab_array[] = array(gettext("Logs Mgmt"), false, "/suricata/suricata_logs_mgmt.php"); $tab_array[] = array(gettext("SID Mgmt"), false, "/suricata/suricata_sid_mgmt.php"); $tab_array[] = array(gettext("Sync"), false, "/pkg_edit.php?xml=suricata/suricata_sync.xml"); + $tab_array[] = array(gettext("IP Lists"), false, "/suricata/suricata_ip_list_mgmt.php"); display_top_tabs($tab_array, true); ?> </td></tr> diff --git a/config/suricata/suricata_sync.xml b/config/suricata/suricata_sync.xml index a85a3d63..28083d8d 100644 --- a/config/suricata/suricata_sync.xml +++ b/config/suricata/suricata_sync.xml @@ -110,6 +110,11 @@ POSSIBILITY OF SUCH DAMAGE. <no_drop_down/> <active/> </tab> + <tab> + <text>IP Lists</text> + <url>/suricata/suricata_ip_list_mgmt.php</url> + <no_drop_down/> + </tab> </tabs> <fields> <field> diff --git a/config/suricata/suricata_uninstall.php b/config/suricata/suricata_uninstall.php index 280e2394..c8048a1c 100644 --- a/config/suricata/suricata_uninstall.php +++ b/config/suricata/suricata_uninstall.php @@ -44,11 +44,12 @@ global $config, $g; $suricatadir = SURICATADIR; $suricatalogdir = SURICATALOGDIR; -$sidmodspath = SID_MODS_PATH; -$iprep_path = IPREP_PATH; +$sidmodspath = SURICATA_SID_MODS_PATH; +$iprep_path = SURICATA_IPREP_PATH; $rcdir = RCFILEPREFIX; -$suricata_rules_upd_log = RULES_UPD_LOGFILE; +$suricata_rules_upd_log = SURICATA_RULES_UPD_LOGFILE; $suri_pf_table = SURICATA_PF_TABLE; +$mounted_rw = FALSE; log_error(gettext("[Suricata] Suricata package uninstall in progress...")); @@ -76,20 +77,29 @@ unlink_if_exists("{$g['varrun_path']}/barnyard2_*.pid"); install_cron_job("suricata_check_for_rule_updates.php", false); install_cron_job("suricata_check_cron_misc.inc", false); install_cron_job("{$suri_pf_table}" , false); +install_cron_job("suricata_geoipupdate.php" , false); +install_cron_job("suricata_etiqrisk_update.php", false); /* See if we are to keep Suricata log files on uninstall */ if ($config['installedpackages']['suricata']['config'][0]['clearlogs'] == 'on') { log_error(gettext("[Suricata] Clearing all Suricata-related log files...")); - @unlink("{$suricata_rules_upd_log}"); - mwexec("/bin/rm -rf {$suricatalogdir}"); + unlink_if_exists("{$suricata_rules_upd_log}"); + rmdir_recursive("{$suricatalogdir}"); } -// Mount filesystem read-write to remove our files -conf_mount_rw(); +/**************************************************/ +/* If not already, set Suricata conf partition to */ +/* read-write so we can make changes there */ +/**************************************************/ +if (!is_subsystem_dirty('mount')) { + conf_mount_rw(); + $mounted_rw = TRUE; +} /* Remove the Suricata GUI app directories */ -mwexec("/bin/rm -rf /usr/local/pkg/suricata"); -mwexec("/bin/rm -rf /usr/local/www/suricata"); +rmdir_recursive("/usr/local/pkg/suricata"); +rmdir_recursive("/usr/local/www/suricata"); +rmdir_recursive("/usr/local/etc/suricata"); /* Remove our associated Dashboard widget config and files. */ /* If "save settings" is enabled, then save old widget */ @@ -110,24 +120,26 @@ if (!empty($widgets)) { } } $config['widgets']['sequence'] = implode(",", $widgetlist); - write_config("Suricata pkg: remove Suricata Dashboard Widget on package deinstall."); } -@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"); +unlink_if_exists("/usr/local/www/widgets/include/widget-suricata.inc"); +unlink_if_exists("/usr/local/www/widgets/widgets/suricata_alerts.widget.php"); +unlink_if_exists("/usr/local/www/widgets/javascript/suricata_alerts.js"); -// Finished with filesystem mods so remount it read-only -conf_mount_ro(); +/*******************************************************/ +/* We're finished with conf partition mods, return to */ +/* read-only if we changed it */ +/*******************************************************/ +if ($mounted_rw == TRUE) + conf_mount_ro(); /* Keep this as a last step */ if ($config['installedpackages']['suricata']['config'][0]['forcekeepsettings'] != 'on') { log_error(gettext("Not saving settings... all Suricata configuration info and logs deleted...")); unset($config['installedpackages']['suricata']); unset($config['installedpackages']['suricatasync']); - @unlink("{$suricata_rules_upd_log}"); - mwexec("/bin/rm -rf {$suricatalogdir}"); - mwexec("/bin/rm -rf {$sidmodspath}"); - mwexec("/bin/rm -rf {$iprep_path}"); + unlink_if_exists("{$suricata_rules_upd_log}"); + rmdir_recursive("{$suricatalogdir}"); + rmdir_recursive("{$g['vardb_path']}/suricata"); 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 82c449d3..a8b06ebe 100644 --- a/config/suricata/suricata_yaml_template.inc +++ b/config/suricata/suricata_yaml_template.inc @@ -225,9 +225,9 @@ reassembly: # Host table is used by tagging and per host thresholding subsystems. host: - hash-size: 4096 - prealloc: 1000 - memcap: 16777216 + hash-size: {$host_hash_size} + prealloc: {$host_prealloc} + memcap: {$host_memcap} # Host specific policies for defragmentation and TCP stream reassembly. host-os-policy: @@ -286,18 +286,14 @@ vars: port-groups: {$port_vars} -# Set the order of alerts bassed on actions +# Set the order of alerts based on actions action-order: - pass - drop - reject - alert -# IP Reputation -#reputation-categories-file: {$iprep_path}/categories.txt -#default-reputation-path: {$iprep_path} -#reputation-files: -# - reputation.list +{$iprep_config} # Limit for the maximum number of asn1 frames to decode (default 256) asn1-max-frames: {$asn1_max_frames} |