aboutsummaryrefslogtreecommitdiffstats
path: root/config/snort/snort.inc
diff options
context:
space:
mode:
Diffstat (limited to 'config/snort/snort.inc')
-rwxr-xr-xconfig/snort/snort.inc1463
1 files changed, 1126 insertions, 337 deletions
diff --git a/config/snort/snort.inc b/config/snort/snort.inc
index c36fc873..44dd133e 100755
--- a/config/snort/snort.inc
+++ b/config/snort/snort.inc
@@ -33,21 +33,58 @@
require_once("pfsense-utils.inc");
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");
+// Snort GUI needs some extra PHP memory space to manipulate large rules arrays
+ini_set("memory_limit", "192M");
+
+// Explicitly declare these as global so they work through function call includes
+global $snort_rules_file, $snort_version, $emerging_threats_version, $snort_rules_upd_log;
+global $all_rules, $flowbit_rules_file, $snort_enforcing_rules_file, $rebuild_rules, $is_postinstall;
+global $snort_community_rules_filename, $snort_community_rules_url, $emergingthreats_filename;
+
/* package version */
-$snort_version = "2.9.2.3";
-$pfSense_snort_version = "2.5.4";
+$snort_version = "2.9.4.1";
+$pfSense_snort_version = "2.5.8";
$snort_package_version = "Snort {$snort_version} pkg v. {$pfSense_snort_version}";
-$snort_rules_file = "snortrules-snapshot-2923.tar.gz";
-$emerging_threats_version = "2.9.3";
+
+// Define SNORTDIR and SNORTLIBDIR constants according to FreeBSD version (PBI support or no PBI)
+if (floatval(php_uname("r")) >= 8.3) {
+ exec("/usr/local/sbin/pbi_info | grep 'snort-{$snort_version}' | xargs /usr/local/sbin/pbi_info | awk '/Prefix/ {print $2}'",$pbidirarray);
+ $snort_pbidir = "{$pbidirarray[0]}";
+ /* In case this is an initial Snort install and pbi_info() above returned null, set a sane default value */
+ if (empty($snort_pbidir))
+ $snort_pbidir = "/usr/pbi/snort-" . php_uname("m");
+ define("SNORTDIR", "{$snort_pbidir}/etc/snort");
+ define("SNORTLIBDIR", "{$snort_pbidir}/lib/snort");
+}
+else {
+ define("SNORTDIR", "/usr/local/etc/snort");
+ define("SNORTLIBDIR", "/usr/local/lib/snort");
+}
+
+define("SNORTLOGDIR", "/var/log/snort");
+
+/* Important file definitions */
+$snort_rules_file = "snortrules-snapshot-2941.tar.gz";
+$emerging_threats_version = "2.9.0";
+$emergingthreats_filename = "emerging.rules.tar.gz";
+$snort_community_rules_url = "https://s3.amazonaws.com/snort-org/www/rules/community/";
+$snort_community_rules_filename = "community-rules.tar.gz";
$flowbit_rules_file = "flowbit-required.rules";
$snort_enforcing_rules_file = "snort.rules";
+$snort_rules_upd_log = SNORTLOGDIR;
+$snort_rules_upd_log .= "/snort_rules_update.log";
-define("SNORTDIR", "/usr/local/etc/snort");
-define("SNORTLOGDIR", "/var/log/snort");
+/* Rebuild Rules Flag -- if "on", rebuild enforcing rules and flowbit-rules files */
+$rebuild_rules = "off";
+
+/* Post-install Flag -- normally "false" except during post-install of package */
+$is_postinstall = false;
if (!is_array($config['installedpackages']['snortglobal']))
$config['installedpackages']['snortglobal'] = array();
@@ -99,6 +136,55 @@ function snort_generate_id() {
return $snort_uuid;
}
+function snort_load_suppress_sigs($snortcfg) {
+
+ global $config;
+
+ /**********************************************************/
+ /* This function loads the GEN_ID and SIG_ID for all the */
+ /* suppressed alert entries from the Suppression List of */
+ /* the passed Snort interface. The results are returned */
+ /* in an array with GEN_ID and SIG_ID as the keys. */
+ /**********************************************************/
+
+ $suppress = array();
+
+ if (!is_array($config['installedpackages']['snortglobal']))
+ return;
+ if (!is_array($config['installedpackages']['snortglobal']['suppress']))
+ return;
+ if (!is_array($config['installedpackages']['snortglobal']['suppress']['item']))
+ return;
+ $a_suppress = $config['installedpackages']['snortglobal']['suppress']['item'];
+
+ foreach ($a_suppress as $a_id => $alist) {
+ if ($alist['name'] == $snortcfg['suppresslistname']) {
+ if (!empty($alist['suppresspassthru'])) {
+ $tmplist = str_replace("\r", "", base64_decode($alist['suppresspassthru']));
+ $tmp = explode("\n", $tmplist);
+ foreach ($tmp as $line) {
+ // Skip any blank lines
+ if (trim($line, " \n") == "")
+ continue;
+ // Skip any comment lines
+ if (preg_match('/^\s*#/', $line))
+ continue;
+ if (preg_match('/gen_id\b\s*(\d+),\s*sig_id\b\s*(\d+)/i', $line, $matches)) {
+ $genid = $matches[1];
+ $sigid = $matches[2];
+ if (!empty($genid) && !empty($sigid))
+ $suppress[$genid][$sigid] = "suppress";
+ }
+ }
+ unset($tmp);
+ }
+ break;
+ }
+ }
+ unset($alist);
+ return $suppress;
+}
+
/* func builds custom white lists */
function snort_find_list($find_name, $type = 'whitelist') {
global $config;
@@ -117,117 +203,120 @@ function snort_find_list($find_name, $type = 'whitelist') {
return array();
}
-/* func builds custom whitelests */
+/* func builds custom whitelists and the HOME_NET variable */
function snort_build_list($snortcfg, $listname = "", $whitelist = false) {
global $config, $g;
-
- /* Add loopback to whitelist (ftphelper) */
- $home_net = "127.0.0.1 ";
+ global $aliastable, $filterdns;
+ $home_net = array();
if ($listname == 'default' || empty($listname)) {
- $wanip = 'yes'; $wangw = 'yes'; $wandns = 'yes'; $vips = 'yes'; $vpns = 'yes';
+ $localnet = 'yes'; $wanip = 'yes'; $wangw = 'yes'; $wandns = 'yes'; $vips = 'yes'; $vpns = 'yes';
} else {
$list = snort_find_list($listname);
if (empty($list))
return $list;
+ $localnet = $list['localnets'];
$wanip = $list['wanips'];
$wangw = $list['wangateips'];
$wandns = $list['wandnsips'];
$vips = $list['vips'];
$vpns = $list['vpnips'];
if (!empty($list['address']) && is_alias($list['address'])) {
- $home_net .= trim(filter_expand_alias($list['address']));
- $home_net .= " ";
+ $home_net = explode(" ", trim(filter_expand_alias($list['address'])));
}
}
- /* Always put snort running interface in the list */
+ /* Always add loopback to HOME_NET and whitelist (ftphelper) */
+ if (!in_array("127.0.0.1", $home_net))
+ $home_net[] = "127.0.0.1";
+
+ /********************************************************************/
+ /* Always put the interface running Snort in HOME_NET and whitelist */
+ /* unless it's the WAN. WAN options are handled further down. */
+ /********************************************************************/
$snortip = get_interface_ip($snortcfg['interface']);
- if (is_ipaddr($snortip))
- $home_net .= "{$snortip} ";
+ if (is_ipaddr($snortip)) {
+ if ($snortcfg['interface'] <> "wan") {
+ $sn = get_interface_subnet($snortcfg['interface']);
+ $ip = gen_subnet($snortip, $sn) . "/{$sn}";
+ if (!in_array($ip, $home_net))
+ $home_net[] = $ip;
+ }
+ }
+
if (function_exists('get_interface_ipv6')) {
$snortip = get_interface_ipv6($snortcfg['interface']);
if (is_ipaddrv6($snortip)) {
- if ($whitelist === false) {
+ if ($snortcfg['interface'] <> "wan") {
$sn = get_interface_subnetv6($snortcfg['interface']);
- $home_net .= "{$snortip}/{$sn} ";
- } else
- $home_net .= "{$snortip} ";
+ $ip = gen_subnetv6($snortip, $sn). "/{$sn}";
+ if (!in_array($ip, $home_net))
+ $home_net[] = $ip;
+ }
}
}
-
- /* iterate through interface list and write out whitelist items
- * and also compile a home_net list for snort.
- */
- if ($wanip == 'yes') {
- /* build an interface array list */
- if (function_exists('get_configured_interface_list'))
- $int_array = get_configured_interface_list();
- else {
- $int_array = array('wan', 'lan');
- for ($j = 1; isset ($config['interfaces']['opt' . $j]); $j++)
- if(isset($config['interfaces']['opt' . $j]['enable']))
- $int_array[] = "opt{$j}";
- }
+ if ($localnet == 'yes') {
+ /*************************************************************************/
+ /* Iterate through the interface list and write out whitelist items and */
+ /* also compile a HOME_NET list of all the local interfaces for snort. */
+ /* Skip the WAN interface as we do not typically want that whole subnet */
+ /* whitelisted (just the interface IP itself). */
+ /*************************************************************************/
+ $int_array = get_configured_interface_list();
foreach ($int_array as $int) {
- /* calculate interface subnet information */
- if (function_exists('get_interface_ip')) {
- if (!interface_has_gateway($int))
+ if ($int == "wan")
+ continue;
+ $subnet = get_interface_ip($int);
+ if (is_ipaddr($subnet)) {
+ $sn = get_interface_subnet($int);
+ $ip = gen_subnet($subnet, $sn) . "/{$sn}";
+ if (!in_array($ip, $home_net))
+ $home_net[] = $ip;
+ }
+ if (function_exists("get_interface_ipv6")) {
+ if ($int == "wan")
continue;
- $subnet = get_interface_ip($int);
- if (is_ipaddr($subnet)) {
- if ($whitelist === false) {
- $sn = get_interface_subnet($int);
- $home_net .= "{$subnet}/{$sn} ";
- } else
- $home_net .= "{$subnet} ";
- }
- if (function_exists("get_interface_ipv6")) {
- if (!interface_has_gatewayv6($int))
- continue;;
- $subnet = get_interface_ipv6($int);
- if (is_ipaddrv6($subnet)) {
- if ($whitelist === false) {
- $sn = get_interface_subnetv6($int);
- $home_net .= "{$subnet}/{$sn} ";
- } else
- $home_net .= "{$subnet} ";
- }
- }
- } else {
- $ifcfg = $config['interfaces'][$int];
- switch ($ifcfg['ipaddr']) {
- case "pppoe":
- case "pptp":
- case "l2tp":
- $subnet = find_interface_ip("ng0");
- if (is_ipaddr($subnet))
- $home_net .= "{$subnet} ";
- break;
- case "dhcp":
- $subnet = find_interface_ip(snort_get_real_interface($int));
- if (is_ipaddr($subnet))
- $home_net .= "{$subnet} ";
- break;
- default:
- if (is_ipaddr($ifcfg['ipaddr'])) {
- $home_net .= "{$ifcfg['ipaddr']} ";
- }
- break;
+ $subnet = get_interface_ipv6($int);
+ if (is_ipaddrv6($subnet)) {
+ $sn = get_interface_subnetv6($int);
+ $ip = gen_subnetv6($subnet, $sn). "/{$sn}";
+ if (!in_array($ip, $home_net))
+ $home_net[] = $ip;
}
}
}
}
+ if ($wanip == 'yes') {
+ $ip = get_interface_ip("wan");
+ if (is_ipaddr($ip)) {
+ if (!in_array($ip, $home_net))
+ $home_net[] = $ip;
+ }
+ if (function_exists("get_interface_ipv6")) {
+ $ip = get_interface_ipv6("wan");
+ if (is_ipaddrv6($ip)) {
+ if (!in_array($ip, $home_net))
+ $home_net[] = $ip;
+ }
+ }
+ }
+
if ($wangw == 'yes') {
+ /* Grab the default gateway if set */
+ $default_gw = exec("/sbin/route -n get default |grep 'gateway:' | /usr/bin/awk '{ print $2 }'");
+ if (is_ipaddr($default_gw) && !in_array($default_gw, $home_net))
+ $home_net[] = $default_gw;
+
+ /* Get any other interface gateway and put in $HOME_NET if not there already */
$gw = get_interface_gateway($snortcfg['interface']);
- if (is_ipaddr($gw))
- $home_net .= "{$gw} ";
+ if (is_ipaddr($gw) && !in_array($gw, $home_net))
+ $home_net[] = $gw;
if (function_exists("get_interface_gatewayv6")) {
$gw = get_interface_gatewayv6($snortcfg['interface']);
- if (is_ipaddrv6($gw))
- $home_net .= "{$gw} ";
+ if (is_ipaddrv6($gw) && !in_array($gw, $home_net))
+ $home_net[] = $gw;
}
}
@@ -235,8 +324,8 @@ function snort_build_list($snortcfg, $listname = "", $whitelist = false) {
/* Add DNS server for WAN interface to whitelist */
$dns_servers = get_dns_servers();
foreach ($dns_servers as $dns) {
- if ($dns)
- $home_net .= "{$dns} ";
+ if ($dns && !in_array($dns, $home_net))
+ $home_net[] = $dns;
}
}
@@ -245,10 +334,8 @@ function snort_build_list($snortcfg, $listname = "", $whitelist = false) {
if (is_array($config['virtualip']) && is_array($config['virtualip']['vip'])) {
foreach($config['virtualip']['vip'] as $vip) {
if ($vip['subnet'] && $vip['mode'] != 'proxyarp') {
- if ($whitelist === false)
- $home_net .= "{$vip['subnet']}/{$vip['subnet_bits']} ";
- else
- $home_net .= "{$vip['subnet']} ";
+ if (!in_array("{$vip['subnet']}/{$vip['subnet_bits']}", $home_net))
+ $home_net[] = "{$vip['subnet']}/{$vip['subnet_bits']}";
}
}
}
@@ -256,27 +343,31 @@ function snort_build_list($snortcfg, $listname = "", $whitelist = false) {
/* grab a list of vpns and whitelist if user desires added by nestorfish 954 */
if ($vpns == 'yes') {
- if ($config['version'] <= 6) // chk what pfsense version were on
- $vpns_list = get_vpns_list();
- else
- $vpns_list = filter_get_vpns_list();
-
- if (!empty($vpns_list))
- $home_net .= "{$vpns_list} ";
+ $vpns_list = filter_get_vpns_list();
+ if (!empty($vpns_list)) {
+ /* Convert the returned space-delimited string to an array */
+ /* and then add each VPN address to our HOME_NET array. */
+ $vpns = explode(" ", $vpns_list);
+ foreach ($vpns as $vpn)
+ $home_net[] = trim($vpn);
+ unset($vpns, $vpns_list);
+ }
}
- $home_net = trim($home_net);
- $validator = explode(" ", $home_net);
$valresult = array();
- foreach ($validator as $vald) {
+ foreach ($home_net as $vald) {
if (empty($vald))
continue;
$vald = trim($vald);
if (empty($valresult[$vald]))
$valresult[$vald] = $vald;
}
- unset($home_net, $validator);
+ /* Release memory no longer required */
+ unset($home_net);
+
+ /* Sort the list and return it */
+ natsort($valresult);
return $valresult;
}
@@ -295,8 +386,8 @@ function snort_barnyard_stop($snortcfg, $if_real) {
$snort_uuid = $snortcfg['uuid'];
if (file_exists("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid") && isvalidpid("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid")) {
+ log_error("[Snort] Barnyard2 STOP for {$snortcfg['descr']}({$if_real})...");
killbypid("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid");
- @unlink("{$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid");
}
}
@@ -305,13 +396,11 @@ function snort_stop($snortcfg, $if_real) {
$snort_uuid = $snortcfg['uuid'];
if (file_exists("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid") && isvalidpid("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid")) {
+ log_error("[Snort] Snort STOP for {$snortcfg['descr']}({$if_real})...");
killbypid("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid");
- exec("/bin/rm {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid");
}
snort_barnyard_stop($snortcfg, $if_real);
-
- log_error("Interface Rule STOP for {$snortcfg['descr']}({$if_real})...");
}
function snort_barnyard_start($snortcfg, $if_real) {
@@ -321,9 +410,10 @@ function snort_barnyard_start($snortcfg, $if_real) {
$snort_uuid = $snortcfg['uuid'];
/* define snortbarnyardlog_chk */
- if ($snortcfg['barnyard_enable'] == 'on' && !empty($snortcfg['barnyard_mysql']))
+ if ($snortcfg['barnyard_enable'] == 'on' && !empty($snortcfg['barnyard_mysql'])) {
+ log_error("[Snort] Barnyard2 START for {$snortcfg['descr']}({$if_real})...");
exec("/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 /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q");
-
+ }
}
function snort_start($snortcfg, $if_real) {
@@ -332,14 +422,37 @@ function snort_start($snortcfg, $if_real) {
$snortdir = SNORTDIR;
$snort_uuid = $snortcfg['uuid'];
- if ($snortcfg['enable'] == 'on')
+ if ($snortcfg['enable'] == 'on') {
+ log_error("[Snort] Snort START for {$snortcfg['descr']}({$if_real})...");
exec("/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/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
return;
snort_barnyard_start($snortcfg, $if_real);
+}
+
+/**************************************************************/
+/* This function sends a SIGHUP to the Snort instance on the */
+/* passed interface to cause Snort to reload and parse the */
+/* running configuration without stopping packet processing. */
+/* It also executes the reload as a background process and */
+/* returns control immediately to the caller. */
+/**************************************************************/
+function snort_reload_config($snortcfg, $if_real) {
+ global $config, $g;
+
+ $snortdir = SNORTDIR;
+ $snort_uuid = $snortcfg['uuid'];
- log_error("Interface Rule START for {$snortcfg['descr']}({$if_real})...");
+ /******************************************************/
+ /* Only send the SIGHUP if Snort is running and we */
+ /* can find a valid PID for the process. */
+ /******************************************************/
+ if (file_exists("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid") && isvalidpid("{$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid")) {
+ log_error("[Snort] Snort RELOAD CONFIG for {$snortcfg['descr']}({$if_real})...");
+ exec("/bin/pkill -SIGHUP -F {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid 2>&1 &");
+ }
}
function snort_get_friendly_interface($interface) {
@@ -394,8 +507,7 @@ function snort_get_real_interface($interface) {
this code block is for deleteing logs while keeping the newest file,
snort is linked to these files while running, do not take the easy way out
by touch and rm, snort will lose sync and not log.
-
- */
+*/
function snort_post_delete_logs($snort_uuid = 0) {
global $config, $g;
@@ -427,9 +539,15 @@ function snort_post_delete_logs($snort_uuid = 0) {
}
function snort_postinstall() {
- global $config, $g;
+ global $config, $g, $snort_rules_file, $emerging_threats_version;
+ global $snort_version, $rebuild_rules, $is_postinstall;
$snortdir = SNORTDIR;
+ $snortlibdir = SNORTLIBDIR;
+ $rcdir = RCFILEPREFIX;
+
+ /* Set flag for post-install in progress */
+ $is_postinstall = true;
/* cleanup default files */
@rename("{$snortdir}/snort.conf-sample", "{$snortdir}/snort.conf");
@@ -440,25 +558,55 @@ function snort_postinstall() {
@rename("{$snortdir}/generators-sample", "{$snortdir}/generators");
@rename("{$snortdir}/reference.config-sample", "{$snortdir}/reference.config");
@rename("{$snortdir}/gen-msg.map-sample", "{$snortdir}/gen-msg.map");
- @unlink("{$snortdir}/sid");
- @unlink("/usr/local/etc/rc.d/snort");
- @unlink("/usr/local/etc/rc.d/barnyard2");
- /* remove example files */
- if (file_exists('/usr/local/lib/snort/dynamicrules/lib_sfdynamic_example_rule.so.0'))
- exec('rm /usr/local/lib/snort/dynamicrules/lib_sfdynamic_example*');
+ /* fix up the preprocessor rules filenames from a PBI package install */
+ $preproc_rules = array("decoder.rules", "preprocessor.rules", "sensitive-data.rules");
+ foreach ($preproc_rules as $file) {
+ if (file_exists("{$snortdir}/preproc_rules/{$file}-sample"))
+ @rename("{$snortdir}/preproc_rules/{$file}-sample", "{$snortdir}/preproc_rules/{$file}");
+ }
- if (file_exists('/usr/local/lib/snort/dynamicpreprocessor/lib_sfdynamic_preprocessor_example.so'))
- exec('/bin/rm /usr/local/lib/snort/dynamicpreprocessor/lib_sfdynamic_preprocessor_example*');
+ /* Remove any previously installed scripts since we rebuild them */
+ @unlink("{$snortdir}/sid");
+ @unlink("{$rcdir}/snort.sh");
+ @unlink("{$rcdir}/barnyard2");
+
+ /* remove example library files */
+ $files = glob("{$snortlibdir}/dynamicrules/*_example*");
+ foreach ($files as $f)
+ @unlink($f);
+ $files = glob("{$snortlibdir}/dynamicpreprocessor/*_example*");
+ foreach ($files as $f)
+ @unlink($f);
/* remake saved settings */
if ($config['installedpackages']['snortglobal']['forcekeepsettings'] == 'on') {
+ log_error(gettext("[Snort] Saved settings detected... rebuilding installation with saved settings..."));
update_status(gettext("Saved settings detected..."));
- update_output_window(gettext("Please wait... rebuilding files..."));
+ update_output_window(gettext("Please wait... rebuilding installation with saved settings..."));
+ log_error(gettext("[Snort] Downloading and updating configured rule types..."));
+ update_output_window(gettext("Please wait... downloading and updating configured rule types..."));
@include_once("/usr/local/pkg/snort/snort_check_for_rule_updates.php");
+ update_status(gettext("Generating snort.conf configuration file from saved settings..."));
+ $rebuild_rules = "on";
sync_snort_package_config();
- update_output_window(gettext("Finnished Rebuilding files..."));
+ $rebuild_rules = "off";
+ update_output_window(gettext("Finished rebuilding files..."));
+ log_error(gettext("[Snort] Finished rebuilding installation from saved settings..."));
+
+ /* Only try to start Snort if not in reboot */
+ if (!$g['booting']) {
+ update_status(gettext("Starting Snort using rebuilt configuration..."));
+ update_output_window(gettext("Please wait... while Snort is started..."));
+ log_error(gettext("[Snort] Starting Snort using rebuilt configuration..."));
+ update_output_window(gettext("Snort has been started using the rebuilt configuration..."));
+ start_service("snort");
+ }
}
+
+ /* Done with post-install, so clear flag */
+ $is_postinstall = false;
+ log_error(gettext("[Snort] Package post-installation tasks completed..."));
}
function snort_Getdirsize($node) {
@@ -592,17 +740,20 @@ function snort_rm_blocked_install_cron($should_install) {
}
switch($should_install) {
case true:
- if(!$is_installed) {
- $cron_item = array();
- $cron_item['minute'] = "$snort_rm_blocked_min";
- $cron_item['hour'] = "$snort_rm_blocked_hr";
- $cron_item['mday'] = "$snort_rm_blocked_mday";
- $cron_item['month'] = "$snort_rm_blocked_month";
- $cron_item['wday'] = "$snort_rm_blocked_wday";
- $cron_item['who'] = "root";
- $cron_item['command'] = "/usr/bin/nice -n20 /usr/local/sbin/expiretable -t $snort_rm_blocked_expire snort2c";
+ $cron_item = array();
+ $cron_item['minute'] = "$snort_rm_blocked_min";
+ $cron_item['hour'] = "$snort_rm_blocked_hr";
+ $cron_item['mday'] = "$snort_rm_blocked_mday";
+ $cron_item['month'] = "$snort_rm_blocked_month";
+ $cron_item['wday'] = "$snort_rm_blocked_wday";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "/usr/bin/nice -n20 /usr/local/sbin/expiretable -t $snort_rm_blocked_expire snort2c";
+
+ /* Add cron job if not already installed, else just update the existing one */
+ if (!$is_installed)
$config['cron']['item'][] = $cron_item;
- }
+ elseif ($is_installed)
+ $config['cron']['item'][$x] = $cron_item;
break;
case false:
if ($is_installed == true)
@@ -672,17 +823,20 @@ function snort_rules_up_install_cron($should_install) {
}
switch($should_install) {
case true:
- if(!$is_installed) {
- $cron_item = array();
- $cron_item['minute'] = "$snort_rules_up_min";
- $cron_item['hour'] = "$snort_rules_up_hr";
- $cron_item['mday'] = "$snort_rules_up_mday";
- $cron_item['month'] = "$snort_rules_up_month";
- $cron_item['wday'] = "$snort_rules_up_wday";
- $cron_item['who'] = "root";
- $cron_item['command'] = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/snort/snort_check_for_rule_updates.php >> /tmp/snort_update.log";
+ $cron_item = array();
+ $cron_item['minute'] = "$snort_rules_up_min";
+ $cron_item['hour'] = "$snort_rules_up_hr";
+ $cron_item['mday'] = "$snort_rules_up_mday";
+ $cron_item['month'] = "$snort_rules_up_month";
+ $cron_item['wday'] = "$snort_rules_up_wday";
+ $cron_item['who'] = "root";
+ $cron_item['command'] = "/usr/bin/nice -n20 /usr/local/bin/php -f /usr/local/pkg/snort/snort_check_for_rule_updates.php";
+
+ /* Add cron job if not already installed, else just update the existing one */
+ if (!$is_installed)
$config['cron']['item'][] = $cron_item;
- }
+ elseif ($is_installed)
+ $config['cron']['item'][$x] = $cron_item;
break;
case false:
if($is_installed == true)
@@ -693,13 +847,17 @@ function snort_rules_up_install_cron($should_install) {
/* Only run when all ifaces needed to sync. Expects filesystem rw */
function sync_snort_package_config() {
- global $config, $g;
+ global $config, $g, $flowbit_rules_file, $snort_enforcing_rules_file;
+ global $snort_version, $rebuild_rules, $is_postinstall;
+
+ $snortdir = SNORTDIR;
+ $rcdir = RCFILEPREFIX;
conf_mount_rw();
- /* do not start config build if rules is empty */
- if (!is_array($config['installedpackages']['snortglobal']) && !is_array($config['installedpackages']['snortglobal']['rule'])) {
- exec('/bin/rm /usr/local/etc/rc.d/snort.sh');
+ /* do not start config build if rules is empty or there are no Snort settings */
+ if (!is_array($config['installedpackages']['snortglobal']) || !is_array($config['installedpackages']['snortglobal']['rule'])) {
+ @unlink("{$rcdir}/snort.sh");
conf_mount_ro();
return;
}
@@ -708,10 +866,10 @@ function sync_snort_package_config() {
foreach ($snortconf as $value) {
$if_real = snort_get_real_interface($value['interface']);
- /* create snort configuration file */
+ /* create a snort.conf file for interface */
snort_generate_conf($value);
- /* create barnyard2 configuration file */
+ /* create barnyard2.conf file for interface */
if ($value['barnyard_enable'] == 'on')
snort_create_barnyard2_conf($value, $if_real);
}
@@ -730,7 +888,11 @@ function sync_snort_package_config() {
snort_rules_up_install_cron($snortglob['autorulesupdate7'] != "never_up" ? true : false);
configure_cron();
-
+
+ /* Do not attempt package sync if reinstalling package or booting */
+ if (!$is_postinstall && !$g['booting'])
+ snort_sync_on_changes();
+
conf_mount_ro();
}
@@ -748,7 +910,7 @@ function snort_build_sid_msg_map($rules_path, $sid_file) {
/* First check if we were passed a directory, a single file */
/* or an array of filenames to read. Set our $rule_files */
/* variable accordingly. If we can't figure it out, return */
- /* an empty rules map array. */
+ /* and don't write a sid_msg_map file. */
if (is_string($rules_path)) {
if (is_dir($rules_path))
$rule_files = glob($rules_path . "*.rules");
@@ -858,11 +1020,19 @@ function snort_merge_reference_configs($cfg_in, $cfg_out) {
/* Sort the new reference map. */
uksort($outMap,'strnatcasecmp');
+ /**********************************************************/
+ /* Do NOT write an empty references.config file, just */
+ /* exit instead. */
+ /**********************************************************/
+ if (empty($outMap))
+ return false;
+
/* Format and write it to the supplied output file. */
$format = "config reference: %-12s %s\n";
foreach ($outMap as $key=>$value)
$outMap[$key] = sprintf($format, $key, $value);
@file_put_contents($cfg_out, array_values($outMap));
+ return true;
}
function snort_merge_classification_configs($cfg_in, $cfg_out) {
@@ -895,11 +1065,19 @@ function snort_merge_classification_configs($cfg_in, $cfg_out) {
/* Sort the new classification map. */
uksort($outMap,'strnatcasecmp');
+ /**********************************************************/
+ /* Do NOT write an empty classification.config file, just */
+ /* exit instead. */
+ /**********************************************************/
+ if (empty($outMap))
+ return false;
+
/* Format and write it to the supplied output file. */
$format = "config classification: %s,%s\n";
foreach ($outMap as $key=>$value)
$outMap[$key] = sprintf($format, $key, $value);
@file_put_contents($cfg_out, array_values($outMap));
+ return true;
}
function snort_load_rules_map($rules_path) {
@@ -1013,8 +1191,13 @@ function snort_load_rules_map($rules_path) {
}
$gid = snort_get_gid($rule);
+ if (!is_array($map_ref[$gid]))
+ $map_ref[$gid] = array();
+ if (!is_array($map_ref[$gid][$sid]))
+ $map_ref[$gid][$sid] = array();
$map_ref[$gid][$sid]['rule'] = $rule;
$map_ref[$gid][$sid]['category'] = basename($file, ".rules");
+
if (preg_match('/^\s*\#+/', $rule))
$map_ref[$gid][$sid]['disabled'] = 1;
else
@@ -1077,20 +1260,35 @@ function snort_get_flowbits($rule) {
/*************************************************************/
/* This will pull out "flowbits:" options from the rule text */
- /* and return them in an array. */
+ /* and return them in an array (minus the "flowbits:" part). */
/*************************************************************/
$flowbits = array();
- if (preg_match_all('/flowbits\b:\s*(set|setx|unset|toggle|isset|isnotset)\s*,([^;]+)/i', $rule, $matches)) {
+
+ /* Grab any "flowbits:set, setx, unset, isset or toggle" options first. */
+ /* Examine flowbits targets for logical operators to capture all targets */
+ if (preg_match_all('/flowbits\b\s*:\s*(set|setx|unset|toggle|isset|isnotset)\s*,([^;]+)/i', $rule, $matches)) {
$i = -1;
while (++$i < count($matches[1])) {
- $flowbits[] = trim($matches[1][$i]) ."," . trim($matches[2][$i]);
+ $action = trim($matches[1][$i]);
+ $target = preg_split('/[&|]/', $matches[2][$i]);
+ foreach ($target as $t)
+ $flowbits[] = "{$action}," . trim($t);
}
}
+
+ /* Include the "flowbits:noalert or reset" options, if present. */
+ if (preg_match_all('/flowbits\b\s*:\s*(noalert|reset)\b/i', $rule, $matches)) {
+ $i = -1;
+ while (++$i < count($matches[1])) {
+ $flowbits[] = trim($matches[1][$i]);
+ }
+ }
+
return $flowbits;
}
-function snort_get_checked_flowbits(&$rules_map) {
+function snort_get_checked_flowbits($rules_map) {
/*************************************************************/
/* This function checks all the currently enabled rules to */
@@ -1114,11 +1312,16 @@ function snort_get_checked_flowbits(&$rules_map) {
foreach ($rulem2['flowbits'] as $flowbit) {
if (empty($flowbit))
continue;
- $action = substr($flowbit, 0, strpos($flowbit, ","));
- if (preg_match('/is(not)?set/i', $action)) {
- $tmp = substr($flowbit, strpos($flowbit, ",") +1 );
- if (!empty($tmp) && !in_array($tmp, $checked_flowbits))
- $checked_flowbits[] = $tmp;
+ /* If no comma in flowbits option, then skip it. */
+ $pos = strpos($flowbit, ",");
+ if ($pos === false)
+ continue;
+ $action = substr(strtolower($flowbit), 0, $pos);
+ if ($action == "isset" || $action == "isnotset") {
+ $target = preg_split('/[&|]/', substr($flowbit, $pos + 1));
+ foreach ($target as $t)
+ if (!empty($t) && !isset($checked_flowbits[$t]))
+ $checked_flowbits[$t] = $action;
}
}
}
@@ -1128,7 +1331,7 @@ function snort_get_checked_flowbits(&$rules_map) {
return $checked_flowbits;
}
-function snort_get_set_flowbits(&$rules_map) {
+function snort_get_set_flowbits($rules_map) {
/*********************************************************/
/* This function checks all the currently enabled rules */
@@ -1150,11 +1353,16 @@ function snort_get_set_flowbits(&$rules_map) {
foreach ($rulem2['flowbits'] as $flowbit) {
if (empty($flowbit))
continue;
- $action = substr($flowbit, 0, strpos($flowbit, ","));
- if (preg_match('/^set/i', $action)) {
- $tmp = substr($flowbit, strpos($flowbit, ",") +1 );
- if (!empty($tmp) && !in_array($tmp, $set_flowbits))
- $set_flowbits[] = $tmp;
+ /* If no comma in flowbits option, then skip it. */
+ $pos = strpos($flowbit, ",");
+ if ($pos === false)
+ continue;
+ $action = substr(strtolower($flowbit), 0, $pos);
+ if ($action == "set" || $action == "toggle" || $action == "setx") {
+ $target = preg_split('/[&|]/', substr($flowbit, $pos + 1));
+ foreach ($target as $t)
+ if (!empty($t) && !isset($set_flowbits[$t]))
+ $set_flowbits[$t] = $action;
}
}
}
@@ -1164,7 +1372,7 @@ function snort_get_set_flowbits(&$rules_map) {
return $set_flowbits;
}
-function snort_find_flowbit_required_rules(&$all_rules, &$unchecked_flowbits) {
+function snort_find_flowbit_required_rules($all_rules, $unchecked_flowbits) {
/********************************************************/
/* This function finds all rules that must be enabled */
@@ -1188,7 +1396,7 @@ function snort_find_flowbit_required_rules(&$all_rules, &$unchecked_flowbits) {
$action = substr($flowbit, 0, strpos($flowbit, ","));
if (!strcasecmp(substr($action, 0, 3), "set")) {
$tmp = substr($flowbit, strpos($flowbit, ",") +1 );
- if (!empty($tmp) && in_array($tmp, $unchecked_flowbits)) {
+ if (!empty($tmp) && isset($unchecked_flowbits[$tmp])) {
if (!is_array($required_flowbits_rules[$k1]))
$required_flowbits_rules[$k1] = array();
if (!is_array($required_flowbits_rules[$k1][$k2]))
@@ -1212,7 +1420,7 @@ function snort_find_flowbit_required_rules(&$all_rules, &$unchecked_flowbits) {
return $required_flowbits_rules;
}
-function snort_resolve_flowbits($rule_path) {
+function snort_resolve_flowbits($active_rules) {
/******************************************************/
/* This function auto-resolves flowbit requirements */
@@ -1222,31 +1430,32 @@ function snort_resolve_flowbits($rule_path) {
/* enabled. For any that are not enabled, they are */
/* copied to an array, enabled, and returned. */
/* */
- /* $rule_path --> rules files of the interface */
- /* to resolve flowbit dependencies */
- /* for. This can be either of the */
- /* following: */
- /* - directory of *.rules files */
- /* - array of *.rules filenames */
- /* - a single *.rules filename */
+ /* $active_rules --> Rules Map array containing */
+ /* the current rules for the */
+ /* interface to resolve flowbit */
+ /* dependencies for. */
+ /* */
+ /* NOTE: this function assumes the global variable */
+ /* $all_rules is populated with all the rules */
+ /* currently downloaded. */
/******************************************************/
+ global $all_rules;
$snortdir = SNORTDIR;
- /* First, load up all the enabled rules. */
- $rules_map = snort_load_rules_map($rule_path);
-
- /* Next, find all the "checked" and "set" flowbits. */
- $checked_flowbits = snort_get_checked_flowbits($rules_map);
- $set_flowbits = snort_get_set_flowbits($rules_map);
+ /* Check $all_rules array to be sure it is filled. */
+ if (empty($all_rules)) {
+ log_error(gettext("[Snort] WARNING: Flowbit resolution not done - no rules in {$snortdir}/rules/ ..."));
+ return array();
+ }
- /* We're done with the first rules array, so cleanup */
- /* to conserve memory. */
- unset($rules_map);
+ /* First, find all the "checked" and "set" flowbits. */
+ $checked_flowbits = snort_get_checked_flowbits($active_rules);
+ $set_flowbits = snort_get_set_flowbits($active_rules);
/* Next find any "checked" flowbits without matching */
/* "set" flowbit rules in the enabled rule set. */
- $delta_flowbits = array_diff($checked_flowbits, $set_flowbits);
+ $delta_flowbits = array_diff_key($checked_flowbits, $set_flowbits);
/* Cleanup and release the memory we no longer need. */
unset($checked_flowbits);
@@ -1254,11 +1463,9 @@ function snort_resolve_flowbits($rule_path) {
/* Now find all the needed "set flowbit" rules from */
/* the master list of all rules. */
- $all_rules_map = snort_load_rules_map("{$snortdir}/rules/");
- $required_rules = snort_find_flowbit_required_rules($all_rules_map, $delta_flowbits);
+ $required_rules = snort_find_flowbit_required_rules($all_rules, $delta_flowbits);
/* Cleanup and release memory we no longer need. */
- unset($all_rules_map);
unset($delta_flowbits);
return $required_rules;
@@ -1272,11 +1479,13 @@ function snort_write_flowbit_rules_file($flowbit_rules, $rule_file) {
/* given. */
/************************************************/
+ global $flowbit_rules_file;
+
/* See if we were passed a directory or full */
/* filename to write the rules to, and adjust */
/* the destination argument accordingly. */
if (is_dir($rule_file))
- $rule_file = rtrim($rule_file, '/').'/flowbit-required.rules';
+ $rule_file = rtrim($rule_file, '/')."/{$flowbit_rules_file}";
if (empty($flowbit_rules)) {
@file_put_contents($rule_file, "");
@@ -1302,7 +1511,7 @@ function snort_write_flowbit_rules_file($flowbit_rules, $rule_file) {
}
}
-function snort_load_vrt_policy($policy) {
+function snort_load_vrt_policy($policy, $load_rules_map=true) {
/************************************************/
/* This function returns an array of all rules */
@@ -1312,23 +1521,32 @@ function snort_load_vrt_policy($policy) {
/* 1. connectivity */
/* 2. balanced */
/* 3. security */
+ /* */
+ /* $load_rules --> load a local copy of all */
+ /* the rules if true. If */
+ /* false, assume the global */
+ /* $all_rules array is valid. */
/************************************************/
+ global $all_rules;
$snortdir = SNORTDIR;
$vrt_policy_rules = array();
- /* Create regular expression for searching. */
- $policy_pcre = "/policy\\s" . $policy . "/i";
-
- /* First, load up all the rules we have. */
- $all_rules_map = snort_load_rules_map("{$snortdir}/rules/");
+ /* Refresh the map of all the rules if flag */
+ /* is set. */
+ if ($load_rules_map) {
+ /* Since only Snort VRT rules have IPS Policy metadata, */
+ /* limit our search to just those files. */
+ $snort_vrt_files = glob("{$snortdir}/rules/snort_*.rules");
+ $all_rules = array();
+ $all_rules = snort_load_rules_map($snort_vrt_files);
+ }
- /* Now walk the rules list and find all those */
- /* that are defined as active for the chosen */
- /* security policy. */
- foreach ($all_rules_map as $k1 => $arulem) {
+ /* Now walk the rules list and find all those that are defined */
+ /* defined as active for the chosen security policy. */
+ foreach ($all_rules as $k1 => $arulem) {
foreach ($arulem as $k2 => $arulem2) {
- if (preg_match($policy_pcre, $arulem2['rule'])) {
+ if (strripos($arulem2['rule'], "policy {$policy}-ips") !== false) {
if (!preg_match('/flowbits\s*:\s*noalert/i', $arulem2['rule'])) {
if (!is_array($vrt_policy_rules[$k1]))
$vrt_policy_rules[$k1] = array();
@@ -1347,7 +1565,12 @@ function snort_load_vrt_policy($policy) {
}
/* Release memory we no longer need. */
- unset($all_rules_map, $arulem, $arulem2);
+ unset($arulem, $arulem2);
+
+ /* If we loaded the ALL_RULES map, */
+ /* then release the global memory. */
+ if ($load_rules_map == true)
+ unset($GLOBALS['all_rules']);
/* Return all the rules that match the policy. */
return $vrt_policy_rules;
@@ -1363,7 +1586,7 @@ function snort_write_enforcing_rules_file($rule_map, $rule_path) {
global $snort_enforcing_rules_file;
- $rule_file = "/snort.rules";
+ $rule_file = "/{$snort_enforcing_rules_file}";
/* See if we were passed a directory or full */
/* filename to write the rules to, and adjust */
@@ -1389,6 +1612,9 @@ function snort_write_enforcing_rules_file($rule_map, $rule_path) {
@fwrite($fp, "# to the rules in this file.\n\n");
foreach ($rule_map as $rulem) {
foreach ($rulem as $rulem2) {
+ /* No reason to write disabled rules to enforcing file, so skip them. */
+ if ($rulem2['disabled'] == 1)
+ continue;
@fwrite($fp, $rulem2['rule']);
}
}
@@ -1402,9 +1628,17 @@ function snort_load_sid_mods($sids, $value) {
/* This function parses the string of */
/* SID values in $sids and returns an */
/* array with the SID as the key and */
- /* passed $value as the value. The SID */
- /* values in $sids are assumed to be */
- /* delimited by "||". */
+ /* value. The SID values in $sids are */
+ /* assumed to be delimited by "||". */
+ /* */
+ /* $sids ==> string of SID values from */
+ /* saved config file. */
+ /* */
+ /* $value ==> type of mod (enable or */
+ /* disable). Not currently */
+ /* utilized, but maintained */
+ /* so as not to break legacy */
+ /* code elsewhere. */
/*****************************************/
$result = array();
@@ -1413,7 +1647,7 @@ function snort_load_sid_mods($sids, $value) {
$tmp = explode("||", $sids);
foreach ($tmp as $v) {
if (preg_match('/\s\d+/', $v, $match))
- $result[trim($match[0])] = $value;
+ $result[trim($match[0])] = trim($match[0]);
}
unset($tmp);
@@ -1458,14 +1692,13 @@ function snort_modify_sids(&$rule_map, $snortcfg) {
if (!empty($disablesid)) {
foreach ($rule_map as $k1 => $rulem) {
foreach ($rulem as $k2 => $v) {
- if (in_array($k2, $disablesid) && $v['disabled'] == 0) {
+ if (in_array($k2, $disablesid) && $v['disabled'] == 0) {
$rule_map[$k1][$k2]['rule'] = "# " . $v['rule'];
$rule_map[$k1][$k2]['disabled'] = 1;
}
}
}
}
-
unset($enablesid, $disablesid);
}
@@ -1475,6 +1708,7 @@ function snort_create_rc() {
global $config, $g;
$snortdir = SNORTDIR;
+ $rcdir = RCFILEPREFIX;
if (!is_array($config['installedpackages']['snortglobal']['rule']))
return;
@@ -1493,23 +1727,59 @@ function snort_create_rc() {
$start_barnyard = <<<EOE
if [ ! -f {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid ]; then
- /bin/pgrep -xf '/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 /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q' > {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid
- fi
- /bin/pgrep -F {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid
- if [ $? = 0 ]; then
- /bin/pkill -HUP -F {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid -a
+ pid=`/bin/pgrep -xf '/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 /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q' > {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid`
else
- /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 /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q
+ pid=`/bin/pgrep -F {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid`
fi
+ if [ ! -z \$pid ]; then
+ /usr/bin/logger -p daemon.info -i -t SnortStartup "Barnyard2 STOP for {$value['descr']}({$snort_uuid}_{$if_real})..."
+ /bin/pkill $pid -a
+ time=0 timeout=30
+ while kill -0 \$pid 2>/dev/null; do
+ sleep 1
+ time=\$((time+1))
+ if [ \$time -gt \$timeout ]; then
+ break
+ fi
+ done
+ if [ -f /var/run/barnyard2_{$if_real}{$snort_uuid}.pid ]; then
+ /bin/rm /var/run/barnyard2_{$if_real}{$snort_uuid}.pid
+ fi
+ fi
+ /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 /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q
EOE;
$stop_barnyard2 = <<<EOE
if [ -f {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid ]; then
+ /usr/bin/logger -p daemon.info -i -t SnortStartup "Barnyard2 STOP for {$value['descr']}({$snort_uuid}_{$if_real})..."
+ pid=`/bin/pgrep -F {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid`
/bin/pkill -F {$g['varrun_path']}/barnyard2_{$if_real}{$snort_uuid}.pid -a
- /bin/rm /var/run/barnyard2_{$if_real}{$snort_uuid}.pid
+ time=0 timeout=30
+ while kill -0 \$pid 2>/dev/null; do
+ sleep 1
+ time=\$((time+1))
+ if [ \$time -gt \$timeout ]; then
+ break
+ fi
+ done
+ if [ -f /var/run/barnyard2_{$if_real}{$snort_uuid}.pid ]; then
+ /bin/rm /var/run/barnyard2_{$if_real}{$snort_uuid}.pid
+ fi
else
- /bin/pkill -xf '/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 /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q'
+ pid=`/bin/pgrep -xf '/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 /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q'`
+ if [ ! -z \$pid ]; then
+ /bin/pkill -xf '/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 /var/log/snort/snort_{$if_real}{$snort_uuid} -D -q'
+ time=0 timeout=30
+ while kill -0 \$pid 2>/dev/null; do
+ sleep 1
+ time=\$((time+1))
+ if [ \$time -gt \$timeout ]; then
+ break
+ fi
+ done
+ fi
fi
EOE;
@@ -1521,19 +1791,18 @@ EOE;
$start_snort_iface_start[] = <<<EOE
###### For Each Iface
-#### Only try to restart if snort is running on Iface
+ # Start snort and barnyard2
if [ ! -f {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid ]; then
- /bin/pgrep -xf '/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/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}' > {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid
+ pid=`/bin/pgrep -xf '/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/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
+ pid=`/bin/pgrep -F {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid`
fi
- /bin/pgrep -nF {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid
- if [ $? = 0 ]; then
- /bin/pkill -HUP -F {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid -a
- /usr/bin/logger -p daemon.info -i -t SnortStartup "Snort SOFT START For {$value['descr']}({$snort_uuid}_{$if_real})..."
+ if [ ! -z \$pid ]; then
+ /usr/bin/logger -p daemon.info -i -t SnortStartup "Snort SOFT RESTART for {$value['descr']}({$snort_uuid}_{$if_real})..."
+ /bin/pkill -HUP \$pid
else
- # Start snort and barnyard2
- /bin/rm {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid
+ /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 /var/log/snort/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}
- /usr/bin/logger -p daemon.info -i -t SnortStartup "Snort START For {$value['descr']}({$snort_uuid}_{$if_real})..."
fi
sleep 2
@@ -1543,12 +1812,35 @@ EOE;
$start_snort_iface_stop[] = <<<EOE
- /usr/bin/logger -p daemon.info -i -t SnortStartup "Snort STOP For {$value['descr']}({$snort_uuid}_{$if_real})..."
if [ -f {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid ]; then
+ pid=`/bin/pgrep -F {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid`
+ /usr/bin/logger -p daemon.info -i -t SnortStartup "Snort STOP for {$value['descr']}({$snort_uuid}_{$if_real})..."
/bin/pkill -F {$g['varrun_path']}/snort_{$if_real}{$snort_uuid}.pid -a
- /bin/rm /var/run/snort_{$if_real}{$snort_uuid}.pid
- else
- /bin/pkill -xf '/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/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}'
+ time=0 timeout=30
+ while kill -0 \$pid 2>/dev/null; do
+ sleep 1
+ time=\$((time+1))
+ if [ \$time -gt \$timeout ]; then
+ break
+ fi
+ done
+ if [ -f /var/run/snort_{$if_real}{$snort_uuid}.pid ]; then
+ /bin/rm /var/run/snort_{$if_real}{$snort_uuid}.pid
+ fi
+ else
+ pid=`/bin/pgrep -xf '/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/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}'`
+ if [ ! -z \$pid ]; then
+ /usr/bin/logger -p daemon.info -i -t SnortStartup "Snort STOP for {$value['descr']}({$snort_uuid}_{$if_real})..."
+ /bin/pkill -xf '/usr/local/bin/snort -R {$snort_uuid} -D -q -l /var/log/snort/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}'
+ time=0 timeout=30
+ while kill -0 \$pid 2>/dev/null; do
+ sleep 1
+ time=\$((time+1))
+ if [ \$time -gt \$timeout ]; then
+ break
+ fi
+ done
+ fi
fi
sleep 2
@@ -1584,6 +1876,7 @@ case $1 in
rc_stop
;;
restart)
+ rc_stop
rc_start
;;
esac
@@ -1591,11 +1884,11 @@ esac
EOD;
/* write out snort.sh */
- if (!@file_put_contents("/usr/local/etc/rc.d/snort.sh", $snort_sh_text)) {
- log_error("Could not open /usr/local/etc/rc.d/snort.sh for writing.");
+ if (!@file_put_contents("{$rcdir}/snort.sh", $snort_sh_text)) {
+ log_error("Could not open {$rcdir}/snort.sh for writing.");
return;
}
- @chmod("/usr/local/etc/rc.d/snort.sh", 0755);
+ @chmod("{$rcdir}/snort.sh", 0755);
}
/* open barnyard2.conf for writing */
@@ -1642,13 +1935,16 @@ function snort_generate_barnyard2_conf($snortcfg, $if_real) {
config reference_file: {$snortdir}/snort_{$snort_uuid}_{$if_real}/reference.config
config classification_file: {$snortdir}/snort_{$snort_uuid}_{$if_real}/classification.config
config gen_file: {$snortdir}/snort_{$snort_uuid}_{$if_real}/gen-msg.map
-config sid_file: {$snortdir}/snort_{$snort_uuid}_{$if_real}/sid-msg.map
+config sid_file: {$snortdir}/snort_{$snort_uuid}_{$if_real}/sid-msg.map
config hostname: $snortbarnyardlog_hostname_info_chk
config interface: {$if_real}
config decode_data_link
config waldo_file: /var/log/snort/snort_{$if_real}{$snort_uuid}/barnyard2/{$snort_uuid}_{$if_real}.waldo
+# Show year in timestamps
+config show_year
+
## START user pass through ##
{$snortbarnyardlog_config_pass_thru}
@@ -1671,23 +1967,38 @@ EOD;
}
function snort_deinstall() {
- global $config, $g;
+
+ global $config, $g, $snort_rules_upd_log;
$snortdir = SNORTDIR;
+ $snortlibdir = SNORTLIBDIR;
$snortlogdir = SNORTLOGDIR;
+ $rcdir = RCFILEPREFIX;
+
+ log_error(gettext("[Snort] Snort package uninstall in progress..."));
- /* decrease bpf buffers back to 4096, from 20480 */
+ /* Make sure all active Snort processes are terminated */
+ /* Log a message only if a running process is detected */
+ if (is_service_running("snort"))
+ log_error(gettext("[Snort] Snort STOP for all interfaces..."));
mwexec('/usr/bin/killall snort', true);
sleep(2);
mwexec('/usr/bin/killall -9 snort', true);
sleep(2);
+
+ /* Make sure all active Barnyard2 processes are terminated */
+ /* Log a message only if a running process is detected */
+ if (is_service_running("barnyard2"))
+ log_error(gettext("[Snort] Barnyard2 STOP for all interfaces..."));
mwexec('/usr/bin/killall barnyard2', true);
sleep(2);
mwexec('/usr/bin/killall -9 barnyard2', true);
sleep(2);
+
+ /* Remove the snort user and group */
mwexec('/usr/sbin/pw userdel snort; /usr/sbin/pw groupdel snort', true);
- /* Remove snort cron entries Ugly code needs smoothness*/
+ /* Remove snort cron entries Ugly code needs smoothness */
if (!function_exists('snort_deinstall_cron')) {
function snort_deinstall_cron($crontask) {
global $config, $g;
@@ -1709,52 +2020,106 @@ function snort_deinstall() {
}
}
- mwexec("/bin/rm {$snortdir}/*.md5; /bin/rm -r {$snortdir}/snort_*");
+ /* Remove all the Snort cron jobs. */
snort_deinstall_cron("snort2c");
snort_deinstall_cron("snort_check_for_rule_updates.php");
snort_deinstall_cron("snort_check_cron_misc.inc");
configure_cron();
+ /**********************************************************/
+ /* Test for existence of library backup tarballs in /tmp. */
+ /* If these are present, then a package "delete" */
+ /* operation is in progress and we need to wipe out the */
+ /* configuration files. Otherwise we leave the binary- */
+ /* side configuration intact since only a GUI files */
+ /* deinstall and reinstall operation is in progress. */
+ /* */
+ /* XXX: hopefully a better method presents itself in */
+ /* future versions of pfSense. */
+ /**********************************************************/
+ if (file_exists("/tmp/pkg_libs.tgz") || file_exists("/tmp/pkg_bins.tgz")) {
+ log_error(gettext("[Snort] Package deletion requested... removing all files..."));
+ mwexec("/bin/rm -rf {$snortdir}");
+ mwexec("/bin/rm -rf {$snortlibdir}/dynamicrules");
+ mwexec("/bin/rm -f {$rcdir}/snort.sh");
+ mwexec("/bin/rm -rf /usr/local/pkg/snort");
+ mwexec("/bin/rm -rf /usr/local/www/snort");
+ mwexec("/bin/rm -rf /usr/local/etc/snort");
+ }
+
/* Keep this as a last step */
- if ($config['installedpackages']['snortglobal']['forcekeepsettings'] != 'on')
+ if ($config['installedpackages']['snortglobal']['forcekeepsettings'] != 'on') {
+ log_error(gettext("Not saving settings... all Snort configuration info and logs deleted..."));
unset($config['installedpackages']['snortglobal']);
+ unset($config['installedpackages']['snortsync']);
+ @unlink("{$snort_rules_upd_log}");
+ mwexec("/bin/rm -rf {$snortlogdir}");
+ log_error(gettext("[Snort] The package has been removed from this system..."));
+ }
}
function snort_prepare_rule_files($snortcfg, $snortcfgdir) {
- global $snort_enforcing_rules_file, $flowbit_rules_file;
+
+ global $snort_enforcing_rules_file, $flowbit_rules_file, $rebuild_rules, $all_rules;
$snortdir = SNORTDIR;
+ $no_rules_defined = true;
+
+ /* If there is no reason to rebuild the rules, exit to save time. */
+ if ($rebuild_rules == "off")
+ return;
+ /* Log a message for rules rebuild in progress */
+ log_error(gettext("[Snort] Updating rules configuration for: " . snort_get_friendly_interface($snortcfg['interface']) . " ..."));
+
+ /* Only rebuild rules if some are selected or an IPS Policy is enabled */
if (!empty($snortcfg['rulesets']) || $snortcfg['ips_policy_enable'] == 'on') {
$enabled_rules = array();
$enabled_files = array();
+ $no_rules_defined = false;
+
+ /* Load up all the rules into a Rules Map array. */
+ $all_rules = array();
+ $all_rules = snort_load_rules_map("{$snortdir}/rules/");
- /* Create an array with the full path filenames of the enabled */
- /* rule category files if we have any. */
+ /* Create an array with the filenames of the enabled */
+ /* rule category files if we have any. */
if (!empty($snortcfg['rulesets'])) {
- foreach (explode("||", $snortcfg['rulesets']) as $file) {
- if (file_exists("{$snortdir}/rules/{$file}"))
- $enabled_files[] = "{$snortdir}/rules/{$file}";
+ foreach (explode("||", $snortcfg['rulesets']) as $file){
+ $category = basename($file, ".rules");
+ if (!is_array($enabled_files[$category]))
+ $enabled_files[$category] = array();
+ $enabled_files[$category] = $file;
}
- /* Load our rules map in preparation for writing the enforcing rules file. */
- $enabled_rules = snort_load_rules_map($enabled_files);
- }
+ /****************************************************/
+ /* Walk the ALL_RULES map array and copy the rules */
+ /* matching our selected file categories to the */
+ /* ENABLED_RULES map array. */
+ /****************************************************/
+ foreach ($all_rules as $k1 => $rulem) {
+ foreach ($rulem as $k2 => $v) {
+ if (isset($enabled_files[$v['category']])) {
+ if (!is_array($enabled_rules[$k1]))
+ $enabled_rules[$k1] = array();
+ if (!is_array($enabled_rules[$k1][$k2]))
+ $enabled_rules[$k1][$k2] = array();
+ $enabled_rules[$k1][$k2]['rule'] = $v['rule'];
+ $enabled_rules[$k1][$k2]['category'] = $v['category'];
+ $enabled_rules[$k1][$k2]['disabled'] = $v['disabled'];
+ $enabled_rules[$k1][$k2]['flowbits'] = $v['flowbits'];
+ }
+ }
+ }
- /* Remove any existing rules files (except custom rules) prior to building a new set. */
- foreach (glob("{$snortcfgdir}/rules/*.rules") as $file) {
- $tmpfile = basename($file);
- if (in_array("{$snortdir}/rules/{$tmpfile}", $enabled_files))
- continue;
- if ($tmpfile != "custom.rules" && $tmpfile != $flowbit_rules_file &&
- $tmpfile != $snort_enforcing_rules_file)
- @unlink($file);
+ /* Release memory we no longer need. */
+ unset($enabled_files, $rulem, $v);
}
/* Check if a pre-defined Snort VRT policy is selected. If so, */
/* add all the VRT policy rules to our enforcing rule set. */
if (!empty($snortcfg['ips_policy'])) {
- $policy_rules = snort_load_vrt_policy($snortcfg['ips_policy']);
+ $policy_rules = snort_load_vrt_policy($snortcfg['ips_policy'], false);
foreach ($policy_rules as $k1 => $policy) {
foreach ($policy as $k2 => $p) {
if (!is_array($enabled_rules[$k1]))
@@ -1767,46 +2132,63 @@ function snort_prepare_rule_files($snortcfg, $snortcfgdir) {
$enabled_rules[$k1][$k2]['flowbits'] = $p['flowbits'];
}
}
- unset($policy_rules);
+ unset($policy_rules, $policy, $p);
}
/* Process any enablesid or disablesid modifications for the selected rules. */
snort_modify_sids($enabled_rules, $snortcfg);
- /* Check for and disable any rules dependent upon disabled preprocessors. */
- log_error('Checking for and disabling any rules dependent upon disabled preprocessors for ' . snort_get_friendly_interface($snortcfg['interface']) . '...');
- snort_filter_preproc_rules($snortcfg, $enabled_rules);
+ /* Check for and disable any rules dependent upon disabled preprocessors if */
+ /* this option is enabled for the interface. */
+ if ($snortcfg['preproc_auto_rule_disable'] == "on") {
+ log_error('[Snort] Checking for rules dependent on disabled preprocessors for: ' . snort_get_friendly_interface($snortcfg['interface']) . '...');
+ snort_filter_preproc_rules($snortcfg, $enabled_rules);
+ }
/* Write the enforcing rules file to the Snort interface's "rules" directory. */
snort_write_enforcing_rules_file($enabled_rules, "{$snortcfgdir}/rules/{$snort_enforcing_rules_file}");
- unset($enabled_rules);
/* If auto-flowbit resolution is enabled, generate the dependent flowbits rules file. */
if ($snortcfg['autoflowbitrules'] == 'on') {
- log_error('Resolving and auto-enabling flowbit required rules for ' . snort_get_friendly_interface($snortcfg['interface']) . '...');
- $enabled_files[] = "{$snortcfgdir}/rules/{$snort_enforcing_rules_file}";
- snort_write_flowbit_rules_file(snort_resolve_flowbits($enabled_files), "{$snortcfgdir}/rules/{$flowbit_rules_file}");
+ log_error('[Snort] Enabling any flowbit-required rules for: ' . snort_get_friendly_interface($snortcfg['interface']) . '...');
+ $fbits = snort_resolve_flowbits($enabled_rules);
+
+ /* Check for and disable any flowbit-required rules dependent upon */
+ /* disabled preprocessors if this option is enabled for the interface. */
+ if ($snortcfg['preproc_auto_rule_disable'] == "on") {
+ log_error('[Snort] Checking flowbit rules dependent on disabled preprocessors for: ' . snort_get_friendly_interface($snortcfg['interface']) . '...');
+ snort_filter_preproc_rules($snortcfg, $fbits, true);
+ }
+ snort_write_flowbit_rules_file($fbits, "{$snortcfgdir}/rules/{$flowbit_rules_file}");
+ unset($fbits);
} else
/* Just put an empty file to always have the file present */
snort_write_flowbit_rules_file(array(), "{$snortcfgdir}/rules/{$flowbit_rules_file}");
- unset($enabled_files);
+ unset($GLOBALS['all_rules']);
} else {
snort_write_enforcing_rules_file(array(), "{$snortcfgdir}/rules/{$snort_enforcing_rules_file}");
snort_write_flowbit_rules_file(array(), "{$snortcfgdir}/rules/{$flowbit_rules_file}");
}
- if (!empty($snortcfg['customrules']))
+ if (!empty($snortcfg['customrules'])) {
@file_put_contents("{$snortcfgdir}/rules/custom.rules", base64_decode($snortcfg['customrules']));
+ $no_rules_defined = false;
+ }
else
@file_put_contents("{$snortcfgdir}/rules/custom.rules", "");
+ /* Log a warning if the interface has no rules defined or enabled */
+ if ($no_rules_defined)
+ log_error(gettext("[Snort] Warning - no text rules selected for: " . snort_get_friendly_interface($snortcfg['interface']) . " ..."));
+
/* Build a new sid-msg.map file from the enabled */
/* rules and copy it to the interface directory. */
+ log_error(gettext("[Snort] Building new sig-msg.map file for " . snort_get_friendly_interface($snortcfg['interface']) . "..."));
snort_build_sid_msg_map("{$snortcfgdir}/rules/", "{$snortcfgdir}/sid-msg.map");
}
-function snort_filter_preproc_rules($snortcfg, &$active_rules) {
+function snort_filter_preproc_rules($snortcfg, &$active_rules, $persist_log = false) {
/**************************************************/
/* This function checks the $active_rules array */
@@ -1819,11 +2201,22 @@ function snort_filter_preproc_rules($snortcfg, &$active_rules) {
/* the interface */
/* $active_rules -> rules_map array of enabled */
/* rules for the interface */
+ /* */
+ /* NOTE: This feature must be enabled in the GUI */
+ /* by the user. Use of this feature can */
+ /* severely degrade Snort's ability to */
+ /* detect threats by disabling potentially */
+ /* crucial detection rules. */
/**************************************************/
global $config;
- if (empty($active_rules))
+ $snortlogdir = SNORTLOGDIR;
+ $disabled_count = 0;
+ $log_msg = array();
+
+ /* Check if no rules or if this option is disabled */
+ if (empty($active_rules) || $snortcfg['preproc_auto_rule_disable'] <> 'on')
return;
/***************************************************
@@ -1833,8 +2226,20 @@ function snort_filter_preproc_rules($snortcfg, &$active_rules) {
* IMPORTANT -- Keep this part of the code current *
* with changes to preprocessor rule options in *
* Snort VRT rules. *
+ * *
+ * *
+ * Format of array is: *
+ * "rule_option" => "dependent_preprocessor" *
+ * *
+ * Last Update: 04/05/2013 *
+ * *
+ * Added: http_inspect content modifiers and *
+ * various "service" metadata values. *
+ * *
***************************************************/
$rule_opts_preprocs = array("ssl_version:" => "ssl_preproc","ssl_state:" => "ssl_preproc",
+ "service ssl" => "ssl_preproc", "service ftp" => "ftp_preprocessor",
+ "service telnet" => "ftp_preprocessor", "service dns" => "dns_preprocessor",
"dce_iface:" => "dce_rpc_2", "dce_opnum:" => "dce_rpc_2",
"dce_stub_data;" => "dce_rpc_2", "sd_pattern:" => "sensitive_data",
"sip_method:" => "sip_preproc", "sip_stat_code:" => "sip_preproc",
@@ -1843,7 +2248,16 @@ function snort_filter_preproc_rules($snortcfg, &$active_rules) {
"gtp_version:" => "gtp_preproc", "modbus_func:" => "modbus_preproc",
"modbus_unit:" => "modbus_preproc", "modbus_data;" => "modbus_preproc",
"dnp3_func:" => "dnp3_preproc", "dnp3_obj:" => "dnp3_preproc",
- "dnp3_ind:" => "dnp3_preproc", "dnp3_data;" => "dnp3_preproc");
+ "dnp3_ind:" => "dnp3_preproc", "dnp3_data;" => "dnp3_preproc",
+ "http_client_body;" => "http_inspect", "http_cookie;" => "http_inspect",
+ "http_raw_cookie;" => "http_inspect", "http_header;" => "http_inspect",
+ "http_raw_header;" => "http_inspect", "http_method;" => "http_inspect",
+ "http_uri;" => "http_inspect", "http_raw_uri;" => "http_inspect",
+ "http_stat_code;" => "http_inspect", "http_stat_msg;" => "http_inspect",
+ "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");
/***************************************************
* Iterate the enabled rules, and check for rule *
@@ -1855,31 +2269,102 @@ function snort_filter_preproc_rules($snortcfg, &$active_rules) {
***************************************************/
foreach ($active_rules as $k1 => $rulem) {
foreach ($rulem as $k2 => $v) {
- if ($v['disabled'] == 0)
+
+ /* If rule is already disabled, skip it. */
+ if ($v['disabled'] == 1)
continue;
+
foreach ($rule_opts_preprocs as $opt => $preproc) {
- $pcre = "/\s*\b" . $opt . "/i";
+ $pcre = "/\s*\b" . preg_quote($opt) . "/i";
if (($snortcfg[$preproc] != 'on') && preg_match($pcre, $v['rule'])) {
$active_rules[$k1][$k2]['rule'] = "# " . $v['rule'];
$active_rules[$k1][$k2]['disabled'] = 1;
+ $disabled_count++;
+
+ /* Accumulate auto-disabled rules for logging */
+ $tmp = $active_rules[$k1][$k2]['category'] . ",";
+ $tmp .= "{$k1}:{$k2},{$preproc},{$opt}";
+ $log_msg[] = $tmp;
break;
}
}
}
}
+
+ /* Release memory we no longer need. */
+ unset($rulem, $v, $preproc);
+
+ /***************************************************************/
+ /* If we are persisting the log from the last pass, then open */
+ /* the log file in append mode. Otherwise open in overwrite */
+ /* to clear the log in case we have zero disabled rules. */
+ /* */
+ /* Typically "persist log" mode is used on the second pass */
+ /* when flowbit-required rules are being assessed after the */
+ /* primary enforcing rules have been evaluated. */
+ /***************************************************************/
+ $iface = snort_get_friendly_interface($snortcfg['interface']);
+ $file = "{$snortlogdir}/{$iface}_disabled_preproc_rules.log";
+ if ($persist_log)
+ $fp = fopen($file, 'a');
+ else
+ $fp = fopen($file, 'w');
+
+ /***************************************************/
+ /* Log a warning if we auto-disabled any rules */
+ /* just so the user is aware protection is less */
+ /* than optimal with the preprocessors disabled. */
+ /***************************************************/
+ if ($disabled_count > 0) {
+ log_error(gettext("[Snort] Warning: auto-disabled {$disabled_count} rules due to disabled preprocessor dependencies."));
+ natcasesort($log_msg);
+ if ($fp) {
+ /* Only write the header when not persisting the log */
+ if (!$persist_log) {
+ @fwrite($fp, "#\n# Run Time: " . date("Y-m-d H:i:s") . "\n#\n");
+ @fwrite($fp, "#\n# These rules were auto-disabled because they contain options or operators\n");
+ @fwrite($fp, "# dependent on preprocessors that are currently NOT ENABLED on the Preprocessors\n");
+ @fwrite($fp, "# tab. Without these dependent preprocessors enabled, Snort would fail to start\n");
+ @fwrite($fp, "# if the rules listed below were enabled. Therefore the listed rules have been\n");
+ @fwrite($fp, "# automatically disabled. This behavior is controlled by the Auto-Rule Disable\n");
+ @fwrite($fp, "# feature on the Preprocessors tab.\n#\n");
+ @fwrite($fp, "# WARNING: Using the auto-disable rule feature is not recommended because it can\n");
+ @fwrite($fp, "# significantly reduce the threat detection capabilities of Snort!\n#");
+ @fwrite($fp, "\n# In the list below, the PREPROCESSOR column is the disabled preprocessor that\n");
+ @fwrite($fp, "# triggered the auto-disable of the rule represented by GID:SID. The RULE OPTION\n");
+ @fwrite($fp, "# column shows the specific rule option or content modifier contained within\n");
+ @fwrite($fp, "# the rule text that requires the preprocessor be enabled in order to execute.\n#");
+ @fwrite($fp, "\n# RULE CATEGORY GID:SID PREPROCESSOR RULE OPTION\n");
+ }
+ foreach ($log_msg as $m) {
+ $tmp = explode(",", $m);
+ @fwrite($fp, sprintf("%-30s %-10s %-20s %s", $tmp[0], $tmp[1], $tmp[2], $tmp[3]) . "\n");
+ }
+ }
+ log_error(gettext("[Snort] See '{$file}' for list of auto-disabled rules."));
+ unset($log_msg);
+ }
+ if ($fp)
+ fclose($fp);
}
function snort_generate_conf($snortcfg) {
- global $config, $g;
+
+ global $config, $g, $flowbit_rules_file, $snort_enforcing_rules_file, $rebuild_rules;
$snortdir = SNORTDIR;
+ $snortlibdir = SNORTLIBDIR;
$snortlogdir = SNORTLOGDIR;
- $flowbit_rules_file = "flowbit-required.rules";
- $snort_enforcing_rules_file = "snort.rules";
if (!is_array($config['installedpackages']['snortglobal']['rule']))
return;
+ /* See if we should protect and not modify the preprocessor rules files */
+ if (!empty($snortcfg['protect_preproc_rules']))
+ $protect_preproc_rules = $snortcfg['protect_preproc_rules'];
+ else
+ $protect_preproc_rules = "off";
+
$if_real = snort_get_real_interface($snortcfg['interface']);
$snort_uuid = $snortcfg['uuid'];
$snortcfgdir = "{$snortdir}/snort_{$snort_uuid}_{$if_real}";
@@ -1902,8 +2387,8 @@ function snort_generate_conf($snortcfg) {
"{$snortlogdir}/snort_{$if_real}{$snort_uuid}",
"{$snortlogdir}/snort_{$if_real}{$snort_uuid}/barnyard2",
"{$snortcfgdir}/preproc_rules",
- "dynamicrules" => "/usr/local/lib/snort/dynamicrules",
- "dynamicengine" => "/usr/local/lib/snort/dynamicengine",
+ "dynamicrules" => "{$snortlibdir}/dynamicrules",
+ "dynamicengine" => "{$snortlibdir}/dynamicengine",
"dynamicpreprocessor" => "{$snortcfgdir}/dynamicpreprocessor"
);
foreach ($snort_dirs as $dir) {
@@ -1911,13 +2396,24 @@ function snort_generate_conf($snortcfg) {
safe_mkdir($dir);
}
+ /********************************************************************/
+ /* For fail-safe on an initial startup following installation, and */
+ /* before a rules update has occurred, copy the default config */
+ /* files to the interface directory. If files already exist in */
+ /* the interface directory, or they are newer, that means a rule */
+ /* update has been done and we should leave the customized files */
+ /* put in place by the rules update process. */
+ /********************************************************************/
$snort_files = array("gen-msg.map", "classification.config", "reference.config",
"sid-msg.map", "unicode.map", "threshold.conf", "preproc_rules/preprocessor.rules",
"preproc_rules/decoder.rules", "preproc_rules/sensitive-data.rules"
);
foreach ($snort_files as $file) {
- if (file_exists("{$snortdir}/{$file}"))
- @copy("{$snortdir}/{$file}", "{$snortcfgdir}/{$file}");
+ if (file_exists("{$snortdir}/{$file}")) {
+ $ftime = filemtime("{$snortdir}/{$file}");
+ if (!file_exists("{$snortcfgdir}/{$file}") || ($ftime > filemtime("{$snortcfgdir}/{$file}")))
+ @copy("{$snortdir}/{$file}", "{$snortcfgdir}/{$file}");
+ }
}
/* define alertsystemlog */
@@ -1936,8 +2432,7 @@ function snort_generate_conf($snortcfg) {
$pfkill = "";
if ($snortcfg['blockoffenderskill'] == "on")
$pfkill = "kill";
- /* No subnets to default addresses */
- $spoink_wlist = snort_build_list($snortcfg, $snortcfg['whitelistname'], true);
+ $spoink_wlist = snort_build_list($snortcfg, $snortcfg['whitelistname']);
/* write whitelist */
@file_put_contents("{$snortcfgdir}/{$snortcfg['whitelistname']}", implode("\n", $spoink_wlist));
$spoink_type = "output alert_pf: {$snortcfgdir}/{$snortcfg['whitelistname']},snort2c,{$snortcfg['blockoffendersip']},{$pfkill}";
@@ -1968,7 +2463,7 @@ function snort_generate_conf($snortcfg) {
"telnet_ports" => "23","snmp_ports" => "161", "ftp_ports" => "21",
"ssh_ports" => $ssh_port, "pop2_ports" => "109", "pop3_ports" => "110",
"imap_ports" => "143", "sip_proxy_ports" => "5060:5090,16384:32768",
- "sip_ports" => "5060, 5061", "auth_ports" => "113", "finger_ports" => "79",
+ "sip_ports" => "5060,5061", "auth_ports" => "113", "finger_ports" => "79",
"irc_ports" => "6665,6666,6667,6668,6669,7000", "smb_ports" => "139,445",
"nntp_ports" => "119", "rlogin_ports" => "513", "rsh_ports" => "514",
"ssl_ports" => "443,465,563,636,989,990,992,993,994,995",
@@ -1985,7 +2480,7 @@ function snort_generate_conf($snortcfg) {
foreach ($snort_ports as $alias => $avalue) {
if (!empty($snortcfg["def_{$alias}"]) && is_alias($snortcfg["def_{$alias}"]))
$snort_ports[$alias] = filter_expand_alias($snortcfg["def_{$alias}"]);
- $snort_ports[$alias] = str_replace(" ", ",", trim($snort_ports[$alias]));
+ $snort_ports[$alias] = preg_replace('/\s+/', ',', trim($snort_ports[$alias]));
$portvardef .= "portvar " . strtoupper($alias) . " [" . $snort_ports[$alias] . "]\n";
}
@@ -1999,41 +2494,53 @@ preprocessor perfmonitor: time 300 file {$snortlogdir}/snort_{$if_real}{$snort_u
EOD;
- $def_server_flow_depth_type = '300';
- if ((!empty($snortcfg['server_flow_depth'])) || ($snortcfg['server_flow_depth'] == '0'))
- $def_server_flow_depth_type = $snortcfg['server_flow_depth'];
+ /* Pull in the user-configurable HTTP_INSPECT global preprocessor options */
+ $http_inspect_memcap = "150994944";
+ if (!empty($snortcfg['http_inspect_memcap']))
+ $http_inspect_memcap = $snortcfg['http_inspect_memcap'];
+ /* Pull in the user-configurable HTTP_INSPECT server preprocessor options */
+ $server_flow_depth = '300';
+ if ((!empty($snortcfg['server_flow_depth'])) || ($snortcfg['server_flow_depth'] == '0'))
+ $server_flow_depth = $snortcfg['server_flow_depth'];
$http_server_profile = "all";
if (!empty($snortcfg['http_server_profile']))
$http_server_profile = $snortcfg['http_server_profile'];
-
- $def_client_flow_depth_type = '300';
+ $client_flow_depth = '300';
if ((!empty($snortcfg['client_flow_depth'])) || ($snortcfg['client_flow_depth'] == '0'))
- $def_client_flow_depth_type = $snortcfg['client_flow_depth'];
-
- if ($snortcfg['noalert_http_inspect'] == 'on')
- $noalert_http_inspect = "no_alerts ";
+ $client_flow_depth = $snortcfg['client_flow_depth'];
+ if ($snortcfg['noalert_http_inspect'] == 'on' || empty($snortcfg['noalert_http_inspect']))
+ $noalert_http_inspect = "no_alerts";
else
$noalert_http_inspect = "";
+ $http_inspect_server_opts = "enable_cookie \\\n\textended_response_inspection \\\n\tnormalize_javascript \\\n";
+ $http_inspect_server_opts .= "\tinspect_gzip \\\n\tnormalize_utf \\\n\tunlimited_decompress \\\n";
+ $http_inspect_server_opts .= "\tnormalize_headers \\\n\tnormalize_cookies";
+ if ($snortcfg['http_inspect_enable_xff'] == "on")
+ $http_inspect_server_opts .= " \\\n\tenable_xff";
+
+ /* If Stream5 is enabled, then we can enable the "log_uri" and "log_hostname" options */
+ if ($snortcfg['stream5_reassembly'] == "on") {
+ if ($snortcfg['http_inspect_log_uri'] == "on")
+ $http_inspect_server_opts .= " \\\n\tlog_uri";
+ if ($snortcfg['http_inspect_log_hostname'] == "on")
+ $http_inspect_server_opts .= " \\\n\tlog_hostname";
+ }
$http_ports = str_replace(",", " ", $snort_ports['http_ports']);
+
/* def http_inspect */
$http_inspect = <<<EOD
-# HTTP Inspect #
-preprocessor http_inspect: global iis_unicode_map unicode.map 1252 compress_depth 65535 decompress_depth 65535
+# HTTP Inspect #
+preprocessor http_inspect: global iis_unicode_map unicode.map 1252 compress_depth 65535 decompress_depth 65535 memcap {$http_inspect_memcap}
-preprocessor http_inspect_server: server default profile {$http_server_profile} {$noalert_http_inspect}\
- ports { {$http_ports} } \
+preprocessor http_inspect_server: server default profile {$http_server_profile} {$noalert_http_inspect} \
+ ports { {$http_ports} } \
http_methods { GET POST PUT SEARCH MKCOL COPY MOVE LOCK UNLOCK NOTIFY POLL BCOPY BDELETE BMOVE LINK UNLINK OPTIONS HEAD DELETE TRACE TRACK CONNECT SOURCE SUBSCRIBE UNSUBSCRIBE PROPFIND PROPPATCH BPROPFIND BPROPPATCH RPC_CONNECT PROXY_SUCCESS BITS_POST CCM_POST SMS_POST RPC_IN_DATA RPC_OUT_DATA RPC_ECHO_DATA } \
- server_flow_depth {$def_server_flow_depth_type} \
- client_flow_depth {$def_client_flow_depth_type} \
- enable_cookie \
- extended_response_inspection \
- inspect_gzip \
- normalize_utf \
- unlimited_decompress \
- normalize_javascript
-
+ server_flow_depth {$server_flow_depth} \
+ client_flow_depth {$client_flow_depth} \
+ {$http_inspect_server_opts}
+
EOD;
/* def ftp_preprocessor */
@@ -2136,28 +2643,35 @@ PIPELINING CHUNKING DATA DSN RSET QUIT ONEX QUEU STARTTLS TICK TIME TURNME VERB
log_filename \
qp_decode_depth 0 \
b64_decode_depth 0 \
- bitenc_decode_depth 0
+ bitenc_decode_depth 0 \
+ uu_decode_depth 0
EOD;
/* def sf_portscan */
+ $sf_pscan_protocol = "all";
+ if (!empty($snortcfg['pscan_protocol']))
+ $sf_pscan_protocol = $snortcfg['pscan_protocol'];
+ $sf_pscan_type = "all";
+ if (!empty($snortcfg['pscan_type']))
+ $sf_pscan_type = $snortcfg['pscan_type'];
+ $sf_pscan_memcap = "10000000";
+ if (!empty($snortcfg['pscan_memcap']))
+ $sf_pscan_memcap = $snortcfg['pscan_memcap'];
+ $sf_pscan_sense_level = "medium";
if (!empty($snortcfg['pscan_sense_level']))
$sf_pscan_sense_level = $snortcfg['pscan_sense_level'];
- else
- $sf_pscan_sense_level = "medium";
-
+ $sf_pscan_ignore_scanners = "\$HOME_NET";
if (!empty($snortcfg['pscan_ignore_scanners']) && is_alias($snortcfg['pscan_ignore_scanners'])) {
$sf_pscan_ignore_scanners = filter_expand_alias($snortcfg['pscan_ignore_scanners']);
$sf_pscan_ignore_scanners = preg_replace('/\s+/', ',', trim($sf_pscan_ignore_scanners));
}
- else
- $sf_pscan_ignore_scanners = "\$HOME_NET";
$sf_portscan = <<<EOD
# sf Portscan #
-preprocessor sfportscan: scan_type { all } \
- proto { all } \
- memcap { 10000000 } \
+preprocessor sfportscan: scan_type { {$sf_pscan_type} } \
+ proto { {$sf_pscan_protocol} } \
+ memcap { {$sf_pscan_memcap} } \
sense_level { {$sf_pscan_sense_level} } \
ignore_scanners { {$sf_pscan_ignore_scanners} }
@@ -2243,18 +2757,16 @@ EOD;
$sensitive_data = "preprocessor sensitive_data:\n";
- /* stream5 queued settings */
- $def_max_queued_bytes_type = '';
- if ((!empty($snortcfg['max_queued_bytes'])) || ($snortcfg['max_queued_bytes'] == '0'))
- $def_max_queued_bytes_type = ", max_queued_bytes {$snortcfg['max_queued_bytes']}";
-
- $def_max_queued_segs_type = '';
- if ((!empty($snortcfg['max_queued_segs'])) || ($snortcfg['max_queued_segs'] == '0'))
- $def_max_queued_segs_type = ", max_queued_segs {$snortcfg['max_queued_segs']}";
-
- $def_stream5_mem_cap = '';
- if (!empty($snortcfg['stream5_mem_cap']))
- $def_stream5_mem_cap = ", memcap {$snortcfg['stream5_mem_cap']}";
+ /**************************************************************/
+ /* Default the HTTP_INSPECT preprocessor to "on" if not set. */
+ /* The preprocessor is required by hundreds of Snort rules, */
+ /* and without it Snort may not start and/or the number of */
+ /* rules required to be disabled reduces Snort's capability. */
+ /* Alerts from the HTTP_INSPECT preprocessor default to "off" */
+ /* unless a specific value has been set by the user. */
+ /**************************************************************/
+ if (empty($snortcfg['http_inspect']))
+ $snortcfg['http_inspect'] = 'on';
/* define servers and ports snortdefservers */
$snort_servers = array (
@@ -2287,15 +2799,23 @@ EOD;
"perform_stat", "http_inspect", "other_preprocs", "ftp_preprocessor", "smtp_preprocessor", "ssl_preproc", "sip_preproc", "gtp_preproc",
"sf_portscan", "dce_rpc_2", "dns_preprocessor", "sensitive_data", "pop_preproc", "imap_preproc", "dnp3_preproc", "modbus_preproc"
);
+ $default_disabled_preprocs = array(
+ "sf_portscan", "gtp_preproc", "sensitive_data", "dnp3_preproc", "modbus_preproc"
+ );
$snort_preprocessors = "";
foreach ($snort_preproc as $preproc) {
- if ($snortcfg[$preproc] == 'on') {
- /* NOTE: The $$ is not a bug. Its a advanced feature of php */
+ if ($snortcfg[$preproc] == 'on' || empty($snortcfg[$preproc]) ) {
+
+ /* If preprocessor is not explicitly "on" or "off", then default to "off" if in our default disabled list */
+ if (empty($snortcfg[$preproc]) && in_array($preproc, $default_disabled_preprocs))
+ continue;
+
+ /* NOTE: The $$ is not a bug. It is an advanced feature of php */
if (!empty($snort_preproc_libs[$preproc])) {
$preproclib = "libsf_" . $snort_preproc_libs[$preproc];
if (!file_exists($snort_dirs['dynamicpreprocessor'] . "{$preproclib}.so")) {
- if (file_exists("/usr/local/lib/snort/dynamicpreprocessor/{$preproclib}.so")) {
- @copy("/usr/local/lib/snort/dynamicpreprocessor/{$preproclib}.so", "{$snort_dirs['dynamicpreprocessor']}/{$preproclib}.so");
+ if (file_exists("{$snortlibdir}/dynamicpreprocessor/{$preproclib}.so")) {
+ @copy("{$snortlibdir}/dynamicpreprocessor/{$preproclib}.so", "{$snort_dirs['dynamicpreprocessor']}/{$preproclib}.so");
$snort_preprocessors .= $$preproc;
$snort_preprocessors .= "\n";
} else
@@ -2317,28 +2837,32 @@ EOD;
if (file_exists("{$snortcfgdir}/classification.config"))
$snort_misc_include_rules .= "include {$snortcfgdir}/classification.config\n";
if (is_dir("{$snortcfgdir}/preproc_rules")) {
- if ($snortcfg['sensitive_data'] == 'on') {
+ if ($snortcfg['sensitive_data'] == 'on' && $protect_preproc_rules == "off") {
$sedcmd = '/^#alert.*classtype:sdf/s/^#//';
if (file_exists("{$snortcfgdir}/preproc_rules/sensitive-data.rules"))
$snort_misc_include_rules .= "include \$PREPROC_RULE_PATH/sensitive-data.rules\n";
} else
$sedcmd = '/^alert.*classtype:sdf/s/^/#/';
if (file_exists("{$snortcfgdir}/preproc_rules/decoder.rules") &&
- file_exists("{$snortcfgdir}/preproc_rules/preprocessor.rules")) {
+ file_exists("{$snortcfgdir}/preproc_rules/preprocessor.rules") && $protect_preproc_rules == "off") {
@file_put_contents("{$g['tmp_path']}/sedcmd", $sedcmd);
mwexec("/usr/bin/sed -I '' -f {$g['tmp_path']}/sedcmd {$snortcfgdir}/preproc_rules/preprocessor.rules");
mwexec("/usr/bin/sed -I '' -f {$g['tmp_path']}/sedcmd {$snortcfgdir}/preproc_rules/decoder.rules");
@unlink("{$g['tmp_path']}/sedcmd");
-
$snort_misc_include_rules .= "include \$PREPROC_RULE_PATH/decoder.rules\n";
$snort_misc_include_rules .= "include \$PREPROC_RULE_PATH/preprocessor.rules\n";
- } else {
+ } else if (file_exists("{$snortcfgdir}/preproc_rules/decoder.rules") &&
+ file_exists("{$snortcfgdir}/preproc_rules/preprocessor.rules") && $protect_preproc_rules == "on") {
+ $snort_misc_include_rules .= "include \$PREPROC_RULE_PATH/decoder.rules\n";
+ $snort_misc_include_rules .= "include \$PREPROC_RULE_PATH/preprocessor.rules\n";
+ }
+ else {
$snort_misc_include_rules .= "config autogenerate_preprocessor_decoder_rules\n";
- log_error("Seems preprocessor/decoder rules are missing, enabling autogeneration of them");
+ log_error("[Snort] Seems preprocessor/decoder rules are missing, enabling autogeneration of them");
}
} else {
$snort_misc_include_rules .= "config autogenerate_preprocessor_decoder_rules\n";
- log_error("Seems preprocessor/decoder rules are missing, enabling autogeneration of them");
+ log_error("[Snort] Seems preprocessor/decoder rules are missing, enabling autogeneration of them");
}
/* generate rule sections to load */
@@ -2346,12 +2870,84 @@ EOD;
$selected_rules_sections = "include \$RULE_PATH/{$snort_enforcing_rules_file}\n";
$selected_rules_sections .= "include \$RULE_PATH/{$flowbit_rules_file}\n";
$selected_rules_sections .= "include \$RULE_PATH/custom.rules\n";
+
+ /* Create the actual rules files and save in the interface directory */
snort_prepare_rule_files($snortcfg, $snortcfgdir);
$cksumcheck = "all";
if ($snortcfg['cksumcheck'] == 'on')
$cksumcheck = "none";
+ /* Pull in user-configurable options for Frag3 preprocessor settings */
+ $frag3_disabled = "";
+ if ($snortcfg['frag3_detection'] == "off")
+ $frag3_disabled = ", disabled";
+ $frag3_memcap = "memcap 4194304";
+ if (!empty($snortcfg['frag3_memcap']) || $snortcfg['frag3_memcap'] == "0")
+ $frag3_memcap = "memcap {$snortcfg['frag3_memcap']}";
+ $frag3_max_frags = "max_frags 8192";
+ if (!empty($snortcfg['frag3_max_frags']))
+ $frag3_max_frags = "max_frags {$snortcfg['frag3_max_frags']}";
+ $frag3_overlap_limit = "overlap_limit 0";
+ if (!empty($snortcfg['frag3_overlap_limit']))
+ $frag3_overlap_limit = "overlap_limit {$snortcfg['frag3_overlap_limit']}";
+ $frag3_min_frag_len = "min_fragment_length 0";
+ if (!empty($snortcfg['frag3_min_frag_len']))
+ $frag3_min_frag_len = "min_fragment_length {$snortcfg['frag3_min_frag_len']}";
+ $frag3_timeout = "timeout 60";
+ if (!empty($snortcfg['frag3_timeout']))
+ $frag3_timeout = "timeout {$snortcfg['frag3_timeout']}";
+ $frag3_policy = "policy bsd";
+ if (!empty($snortcfg['frag3_policy']))
+ $frag3_policy = "policy {$snortcfg['frag3_policy']}";
+
+ /* Pull in user-configurable options for Stream5 preprocessor settings */
+ $stream5_reassembly = "";
+ if ($snortcfg['stream5_reassembly'] == "off")
+ $stream5_reassembly = "disabled,";
+ $stream5_track_tcp = "yes";
+ if ($snortcfg['stream5_track_tcp'] =="off")
+ $stream5_track_tcp = "no";
+ $stream5_track_udp = "yes";
+ if ($snortcfg['stream5_track_udp'] =="off")
+ $stream5_track_udp = "no";
+ $stream5_track_icmp = "no";
+ if ($snortcfg['stream5_track_icmp'] =="on")
+ $stream5_track_icmp = "yes";
+ $stream5_require_3whs = "";
+ if ($snortcfg['stream5_require_3whs'] == "on")
+ $stream5_require_3whs = ", require_3whs 0";
+ $stream5_no_reassemble_async = "";
+ if ($snortcfg['stream5_no_reassemble_async'] == "on")
+ $stream5_no_reassemble_async = ", dont_reassemble_async";
+ $stream5_dont_store_lg_pkts = "";
+ if ($snortcfg['stream5_dont_store_lg_pkts'] == "on")
+ $stream5_dont_store_lg_pkts = ", dont_store_large_packets";
+ $stream5_max_queued_bytes_type = "";
+ if ((!empty($snortcfg['max_queued_bytes'])) || ($snortcfg['max_queued_bytes'] == '0'))
+ $stream5_max_queued_bytes_type = ", max_queued_bytes {$snortcfg['max_queued_bytes']}";
+ $stream5_max_queued_segs_type = "";
+ if ((!empty($snortcfg['max_queued_segs'])) || ($snortcfg['max_queued_segs'] == '0'))
+ $stream5_max_queued_segs_type = ", max_queued_segs {$snortcfg['max_queued_segs']}";
+ $stream5_mem_cap = "";
+ if (!empty($snortcfg['stream5_mem_cap']))
+ $stream5_mem_cap = ", memcap {$snortcfg['stream5_mem_cap']}";
+ $stream5_overlap_limit = "overlap_limit 0";
+ if (!empty($snortcfg['stream5_overlap_limit']))
+ $stream5_overlap_limit = "overlap_limit {$snortcfg['stream5_overlap_limit']}";
+ $stream5_policy = "policy bsd";
+ if (!empty($snortcfg['stream5_policy']))
+ $stream5_policy = "policy {$snortcfg['stream5_policy']}";
+ $stream5_tcp_timeout = "timeout 30";
+ if (!empty($snortcfg['stream5_tcp_timeout']))
+ $stream5_tcp_timeout = "timeout {$snortcfg['stream5_tcp_timeout']}";
+ $stream5_udp_timeout = "timeout 30";
+ if (!empty($snortcfg['stream5_udp_timeout']))
+ $stream5_udp_timeout = "timeout {$snortcfg['stream5_udp_timeout']}";
+ $stream5_icmp_timeout = "timeout 30";
+ if (!empty($snortcfg['stream5_icmp_timeout']))
+ $stream5_icmp_timeout = "timeout {$snortcfg['stream5_icmp_timeout']}";
+
/* build snort configuration file */
$snort_conf_text = <<<EOD
@@ -2393,6 +2989,9 @@ config pcre_match_limit_recursion: 1500
config detection: search-method {$snort_performance} search-optimize max-pattern-len 20 max_queue_events 5
config event_queue: max_queue 8 log 5 order_events content_length
+# Configure to show year in timestamps
+config show_year
+
# Configure protocol aware flushing #
# For more information see README.stream5 #
config paf_max: 16000
@@ -2410,12 +3009,13 @@ preprocessor normalize_ip6
preprocessor normalize_icmp6
# Flow and stream #
-preprocessor frag3_global: max_frags 65536
-preprocessor frag3_engine: policy bsd detect_anomalies overlap_limit 10 min_fragment_length 100 timeout 180
+preprocessor frag3_global: {$frag3_memcap}, {$frag3_max_frags}{$frag3_disabled}
+preprocessor frag3_engine: {$frag3_policy} detect_anomalies {$frag3_timeout} {$frag3_overlap_limit} {$frag3_min_frag_len}
-preprocessor stream5_global: track_tcp yes, track_udp yes, track_icmp no, max_tcp 262144, max_udp 131072, max_active_responses 2, min_response_seconds 5{$def_stream5_mem_cap}
-preprocessor stream5_tcp: policy BSD, overlap_limit 10, timeout 180, ports both all{$def_max_queued_bytes_type}{$def_max_queued_segs_type}
-preprocessor stream5_udp: timeout 180
+preprocessor stream5_global:{$stream5_reassembly} track_tcp {$stream5_track_tcp}, track_udp {$stream5_track_udp}, track_icmp {$stream5_track_icmp}, max_tcp 262144, max_udp 131072, max_active_responses 2, min_response_seconds 5{$stream5_mem_cap}
+preprocessor stream5_tcp: {$stream5_policy}, {$stream5_overlap_limit}, {$stream5_tcp_timeout}, ports both all{$stream5_max_queued_bytes_type}{$stream5_max_queued_segs_type}{$stream5_require_3whs}{$stream5_no_reassemble_async}$stream5_dont_store_lg_pkts
+preprocessor stream5_udp: {$stream5_udp_timeout}
+preprocessor stream5_icmp: {$stream5_icmp_timeout}
{$snort_preprocessors}
@@ -2450,4 +3050,193 @@ EOD;
unset($home_net, $external_net, $vardef, $portvardef);
}
+/* Uses XMLRPC to synchronize the changes to a remote node */
+function snort_sync_on_changes() {
+ global $config, $g, $is_postinstall;
+
+ /* Do not attempt a package sync while booting up or installing package */
+ if ($g['booting'] || $is_postinstall)
+ return;
+
+ if (is_array($config['installedpackages']['snortsync']['config'])){
+ $snort_sync=$config['installedpackages']['snortsync']['config'][0];
+ $synconchanges = $snort_sync['varsynconchanges'];
+ $synctimeout = $snort_sync['varsynctimeout'];
+ $syncdownloadrules = $snort_sync['vardownloadrules'];
+ switch ($synconchanges){
+ case "manual":
+ if (is_array($snort_sync[row])){
+ $rs=$snort_sync[row];
+ }
+ else{
+ log_error("[snort] xmlrpc sync is enabled but there are no hosts configured as replication targets.");
+ return;
+ }
+ break;
+ case "auto":
+ if (is_array($config['installedpackages']['carpsettings']) && is_array($config['installedpackages']['carpsettings']['config'])){
+ $system_carp=$config['installedpackages']['carpsettings']['config'][0];
+ $rs[0]['varsyncipaddress']=$system_carp['synchronizetoip'];
+ $rs[0]['varsyncusername']=$system_carp['username'];
+ $rs[0]['varsyncpassword']=$system_carp['password'];
+ $rs[0]['varsyncsnortstart']="no";
+ if ($system_carp['synchronizetoip'] ==""){
+ log_error("[snort] xmlrpc sync is enabled but there are no system backup hosts configured as replication targets.");
+ return;
+ }
+ }
+ else{
+ log_error("[snort] xmlrpc sync is enabled but there are no system backup hosts configured as replication targets.");
+ return;
+ }
+ break;
+ default:
+ return;
+ break;
+ }
+ if (is_array($rs)){
+ log_error("[snort] Snort pkg xmlrpc sync is starting.");
+ foreach($rs as $sh){
+ if ($sh['varsyncsnortstart'])
+ $syncstartsnort = $sh['varsyncsnortstart'];
+ else
+ $syncstartsnort = "OFF";
+ $sync_to_ip = $sh['varsyncipaddress'];
+ $password = $sh['varsyncpassword'];
+ if($sh['varsyncusername'])
+ $username = $sh['varsyncusername'];
+ else
+ $username = 'admin';
+ if($password && $sync_to_ip)
+ snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $username, $password, $synctimeout, $syncstartsnort);
+ }
+ log_error("[snort] Snort pkg xmlrpc sync completed.");
+ }
+ }
+}
+
+/* Do the actual XMLRPC sync */
+function snort_do_xmlrpc_sync($syncdownloadrules, $sync_to_ip, $username, $password, $synctimeout, $syncstartsnort) {
+ global $config, $g, $is_postinstall;
+
+ /* Do not attempt a package sync while booting up or installing package */
+ if ($g['booting'] || $is_postinstall)
+ return;
+
+ if(!$username || !$password || !$sync_to_ip) {
+ log_error("[snort] A required XMLRPC sync parameter (user, host IP or password) is empty ... aborting pkg sync");
+ return;
+ }
+
+ /* Test key variables and set defaults if empty */
+ if(!$synctimeout)
+ $synctimeout=150;
+
+ $xmlrpc_sync_neighbor = $sync_to_ip;
+ if($config['system']['webgui']['protocol'] != "") {
+ $synchronizetoip = $config['system']['webgui']['protocol'];
+ $synchronizetoip .= "://";
+ }
+ $port = $config['system']['webgui']['port'];
+ /* if port is empty lets rely on the protocol selection */
+ if($port == "") {
+ if($config['system']['webgui']['protocol'] == "http")
+ $port = "80";
+ else
+ $port = "443";
+ }
+ $synchronizetoip .= $sync_to_ip;
+
+ /* xml will hold the sections to sync */
+ $xml = array();
+ $xml['snortglobal'] = $config['installedpackages']['snortglobal'];
+ /* assemble xmlrpc payload */
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($xml)
+ );
+
+ /* set a few variables needed for sync code borrowed from filter.inc */
+ $url = $synchronizetoip;
+ log_error("[snort] Beginning Snort pkg configuration XMLRPC sync to {$url}:{$port}.");
+ $method = 'pfsense.merge_installedpackages_section_xmlrpc';
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials($username, $password);
+
+ /* send our XMLRPC message and timeout after defined sync timeout value*/
+ $resp = $cli->send($msg, $synctimeout);
+ if(!$resp) {
+ $error = "A communications error occurred while attempting snort XMLRPC sync with {$url}:{$port}.";
+ log_error($error);
+ file_notice("sync_settings", $error, "snort Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $error = "An error code was received while attempting snort XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "snort Settings Sync", "");
+ } else {
+ log_error("[snort] Snort pkg configuration XMLRPC sync successfully completed with {$url}:{$port}.");
+ }
+
+ $downloadrulescmd = "";
+ if ($syncdownloadrules == "yes") {
+ $downloadrulescmd = "log_error(gettext(\"[snort] XMLRPC pkg sync: Update of downloaded rule sets requested...\"));\n";
+ $downloadrulescmd .= "include_once(\"/usr/local/pkg/snort/snort_check_for_rule_updates.php\");\n";
+ }
+ $snortstart = "";
+ if ($syncstartsnort == "ON") {
+ $snortstart = "log_error(gettext(\"[snort] XMLRPC pkg sync: Checking Snort status...\"));\n";
+ $snortstart .= "if (!is_process_running(\"snort\")) {\n";
+ $snortstart .= "log_error(gettext(\"[snort] XMLRPC pkg sync: Snort not running. Sending a start command...\"));\n";
+ $snortstart .= "exec(\"/usr/local/etc/rc.d/snort.sh start 2>&1 &\");\n}\n";
+ $snortstart .= "else {log_error(gettext(\"[snort] XMLRPC pkg sync: Snort is running...\"));\n}\n";
+ }
+
+ /* Build a series of commands for the secondary host to execute that will load the new settings. */
+ $execcmd = <<<EOD
+ require_once("/usr/local/pkg/snort/snort.inc");
+ require_once("service-utils.inc");
+ global \$g, \$rebuild_rules, \$snort_gui_include, \$is_postinstall, \$pkg_interface;
+ \$orig_pkg_interface = \$pkg_interface;
+ \$is_postinstall = true;
+ \$snort_gui_include = false;
+ \$pkg_interface = "console";
+ {$downloadrulescmd}
+ \$is_postinstall = false;
+ log_error(gettext("[snort] XMLRPC pkg sync: Generating snort.conf file using Master Host's settings..."));
+ \$rebuild_rules = "on";
+ sync_snort_package_config();
+ \$rebuild_rules = "off";
+ {$snortstart}
+ log_error(gettext("[snort] XMLRPC pkg sync process on this host is complete..."));
+ \$pkg_interface = \$orig_pkg_interface;
+ return true;
+
+EOD;
+
+ /* assemble xmlrpc payload */
+ $method = 'pfsense.exec_php';
+ $params = array(
+ XML_RPC_encode($password),
+ XML_RPC_encode($execcmd)
+ );
+
+ log_error("[snort] Snort XMLRPC sending reload configuration cmd to {$url}:{$port}.");
+ $msg = new XML_RPC_Message($method, $params);
+ $cli = new XML_RPC_Client('/xmlrpc.php', $url, $port);
+ $cli->setCredentials($username, $password);
+ $resp = $cli->send($msg, $synctimeout);
+ if(!$resp) {
+ $error = "A communications error occurred while attempting snort XMLRPC sync with {$url}:{$port} (pfsense.exec_php).";
+ log_error($error);
+ file_notice("sync_settings", $error, "snort Settings Sync", "");
+ } elseif($resp->faultCode()) {
+ $error = "An error code was received while attempting snort XMLRPC sync with {$url}:{$port} - Code " . $resp->faultCode() . ": " . $resp->faultString();
+ log_error($error);
+ file_notice("sync_settings", $error, "snort Settings Sync", "");
+ } else {
+ log_error("[snort] Snort pkg XMLRPC reload configuration success with {$url}:{$port} (pfsense.exec_php).");
+ }
+}
+
?>