diff options
author | bmeeks8 <bmeeks8@bellsouth.net> | 2014-09-09 20:26:22 -0400 |
---|---|---|
committer | bmeeks8 <bmeeks8@bellsouth.net> | 2014-09-09 20:26:22 -0400 |
commit | 70d22674fde78a35662fe1a210ecaca4baa984cb (patch) | |
tree | affab8ffbc0641811383a82f3e4ecf72a7fce95c | |
parent | 8c84e29191b2bf66d4ba8c389947032434f3f026 (diff) | |
download | pfsense-packages-70d22674fde78a35662fe1a210ecaca4baa984cb.tar.gz pfsense-packages-70d22674fde78a35662fe1a210ecaca4baa984cb.tar.bz2 pfsense-packages-70d22674fde78a35662fe1a210ecaca4baa984cb.zip |
Add new SID MGMT functionality to Snort package.
-rwxr-xr-x | config/snort/snort.inc | 938 | ||||
-rwxr-xr-x | config/snort/snort_rules.php | 140 | ||||
-rwxr-xr-x | config/snort/snort_rulesets.php | 116 | ||||
-rw-r--r-- | config/snort/snort_sid_mgmt.php | 596 |
4 files changed, 1740 insertions, 50 deletions
diff --git a/config/snort/snort.inc b/config/snort/snort.inc index e442755a..abe2f9ad 100755 --- a/config/snort/snort.inc +++ b/config/snort/snort.inc @@ -41,7 +41,7 @@ require_once("pkg-utils.inc"); require_once("filter.inc"); // Snort GUI needs some extra PHP memory space to manipulate large rules arrays -ini_set("memory_limit", "192M"); +ini_set("memory_limit", "256M"); // Explicitly declare this as global so it works through function call includes global $rebuild_rules, $pfSense_snort_version; @@ -82,6 +82,7 @@ define("GPL_FILE_PREFIX", "GPLv2_"); define("ET_OPEN_FILE_PREFIX", "emerging-"); define("ET_PRO_FILE_PREFIX", "etpro-"); define("IPREP_PATH", "/var/db/snort/iprep/"); +define('SID_MODS_PATH', '/var/db/snort/sidmods/'); /* Rebuild Rules Flag -- if "true", rebuild enforcing rules and flowbit-rules files */ $rebuild_rules = false; @@ -1157,11 +1158,11 @@ function snort_load_rules_map($rules_path) { if (empty($rules_path)) return $map_ref; - /*************************************************************** + /************************************************************************************ * Read all the rules into the map array. * The structure of the map array is: * - * map[gid][sid]['rule']['category']['disabled']['action']['flowbits'] + * map[gid][sid]['rule']['category']['action']['disabled']['managed']['flowbits'] * * where: * gid = Generator ID from rule, or 1 if general text @@ -1169,12 +1170,14 @@ function snort_load_rules_map($rules_path) { * sid = Signature ID from rule * rule = Complete rule text * category = File name of file containing the rule + * action = alert, drop, reject or pass * disabled = 1 if rule is disabled (commented out), 0 if * rule is enabled - * action = alert|log|pass|drop|reject|sdrop + * managed = 1 if rule is auto-managed by SID MGMT process, + * 0 if not auto-managed * flowbits = Array of applicable flowbits if rule contains * flowbits options - ***************************************************************/ + ************************************************************************************/ /* First check if we were passed a directory, a single file */ /* or an array of filenames to read. Set our $rule_files */ @@ -1697,6 +1700,854 @@ function snort_write_enforcing_rules_file($rule_map, $rule_path) { } } +function snort_parse_sidconf_file($sidconf_file) { + + /**********************************************/ + /* This function loads and processes the file */ + /* specified by '$sidconf_file'. The file is */ + /* assumed to contain valid instructions for */ + /* matching rule SIDs as supported by the */ + /* Oinkmaster and PulledPork utilities. */ + /* */ + /* $sidconf_file ==> full path and name of */ + /* file to process */ + /* */ + /* Returns ==> an array containing */ + /* SID modifier tokens */ + /**********************************************/ + + $buf = ""; + $sid_mods = array(); + + $fd = fopen("{$sidconf_file}", "r"); + if ($fd == FALSE) { + log_error("[Snort] Failed to open SID MGMT file '{$sidconf_file}' for processing."); + return $sid_mods; + } + + // Read and parse the conf file line-by-line + while (($buf = fgets($fd)) !== FALSE) { + $line = array(); + + // Skip any lines that may be just spaces. + if (trim($buf, " \r\n") == "") + continue; + + // Skip line with leading "#" since it's a comment + if (preg_match('/^\s*#/', $buf)) + continue; + + // Trim off any trailing comment + $line = explode("#", $buf); + + // Trim leading and trailing spaces plus newline and any carriage returns + $buf = trim($line[0], ' \r\n'); + + // Now split the SID mod arguments at the commas, if more than one + // per line, and add to our $sid_mods array. + $line = explode(",", $buf); + foreach ($line as $ent) + $sid_mods[] = trim($ent); + } + + // Close the file, release unneeded memory and return + // the array of SID mod tokens parsed from the file. + fclose($fd); + unset($line, $buf); + return $sid_mods; +} + +function snort_sid_mgmt_auto_categories($snortcfg, $log_results = FALSE) { + + /****************************************************/ + /* This function parses any auto-SID conf files */ + /* configured for the interface and returns an */ + /* array of rule categories adjusted from the */ + /* ['enabled_rulesets'] element in the config for */ + /* the interface in accordance with the contents */ + /* of the SID Mgmt conf files. */ + /* */ + /* The returned array shows which files should be */ + /* removed and which should be added to the list */ + /* used when building the enforcing ruleset. */ + /* */ + /* $snortcfg ==> pointer to interface */ + /* configuration info */ + /* $log_results ==> [optional] log results to */ + /* 'sid_changes.log' in the */ + /* interface directory in */ + /* /var/log/snort when TRUE */ + /* */ + /* Returns ==> array of category file names */ + /* for the interface. The keys */ + /* are category file names and */ + /* the corresponding values show */ + /* if the file should be added */ + /* or removed from the enabled */ + /* rulesets list. */ + /* */ + /* Example - */ + /* $changes[file] = 'enabled' */ + /* */ + /****************************************************/ + + global $config; + $snort_sidmods_dir = SID_MODS_PATH; + $sid_mods = array(); + $enables = array(); + $disables = array(); + + // Check if auto-mgmt of SIDs is enabled, exit if not + if ($config['installedpackages']['snortglobal']['auto_manage_sids'] != 'on') + return array(); + if (empty($snortcfg['disable_sid_file']) && empty($snortcfg['enable_sid_file'])) + return array(); + + // Configure the interface's logging subdirectory if log results is enabled + if ($log_results == TRUE) + $log_file = SNORTLOGDIR . "/snort_" . get_real_interface($snortcfg['interface']) . "{$snortcfg['uuid']}/sid_changes.log"; + else + $log_file = NULL; + + // Get the list of currently enabled categories for the interface + if (!empty($snortcfg['rulesets'])) + $enabled_cats = explode("||", $snortcfg['rulesets']); + + if ($log_results == TRUE) { + error_log(gettext("********************************************************\n"), 3, $log_file); + error_log(gettext("Starting auto RULE CATEGORY management for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']) ."\n"), 3, $log_file); + error_log(gettext("Start Time: " . date("Y-m-d H:i:s") . "\n"), 3, $log_file); + } + + switch ($snortcfg['sid_state_order']) { + case "disable_enable": + if (!empty($snortcfg['disable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing disable_sid file: {$snortcfg['disable_sid_file']}\n"), 3, $log_file); + + // Attempt to open the 'disable_sid_file' for the interface + if (!file_exists("{$snort_sidmods_dir}{$snortcfg['disable_sid_file']}")) { + log_error(gettext("[Snort] Error - unable to open 'disable_sid_file' \"{$snortcfg['disable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + if ($log_results == TRUE) + error_log(gettext("Unable to open disable_sid file \"{$snortcfg['disable_sid_file']}\".\n"), 3, $log_file); + } + else + $sid_mods = snort_parse_sidconf_file("{$snort_sidmods_dir}{$snortcfg['disable_sid_file']}"); + + if (!empty($sid_mods)) + $disables = snort_get_auto_category_mods($enabled_cats, $sid_mods, "disable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$snortcfg['disable_sid_file']}\".\n"), 3, $log_file); + } + } + if (!empty($snortcfg['enable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing enable_sid file: {$snortcfg['enable_sid_file']}\n"), 3, $log_file); + + // Attempt to open the 'enable_sid_file' for the interface + if (!file_exists("{$snort_sidmods_dir}{$snortcfg['enable_sid_file']}")) { + log_error(gettext("[Snort] Error - unable to open 'enable_sid_file' \"{$snortcfg['enable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + if ($log_results == TRUE) + error_log(gettext("Unable to open enable_sid file \"{$snortcfg['enable_sid_file']}\".\n"), 3, $log_file); + } + else + $sid_mods = snort_parse_sidconf_file("{$snort_sidmods_dir}{$snortcfg['enable_sid_file']}"); + + if (!empty($sid_mods)) + $enables = snort_get_auto_category_mods($enabled_cats, $sid_mods, "enable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$snortcfg['enable_sid_file']}\".\n"), 3, $log_file); + } + } + break; + + case "enable_disable": + if (!empty($snortcfg['enable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing enable_sid file: {$snortcfg['enable_sid_file']}\n"), 3, $log_file); + + // Attempt to open the 'enable_sid_file' for the interface + if (!file_exists("{$snort_sidmods_dir}{$snortcfg['enable_sid_file']}")) { + log_error(gettext("[Snort] Error - unable to open 'enable_sid_file' \"{$snortcfg['enable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + if ($log_results == TRUE) + error_log(gettext("Unable to open enable_sid file \"{$snortcfg['enable_sid_file']}\".\n"), 3, $log_file); + } + else + $sid_mods = snort_parse_sidconf_file("{$snort_sidmods_dir}{$snortcfg['enable_sid_file']}"); + + if (!empty($sid_mods)) + $enables = snort_get_auto_category_mods($enabled_cats, $sid_mods, "enable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$snortcfg['enable_sid_file']}\".\n"), 3, $log_file); + } + } + if (!empty($snortcfg['disable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing disable_sid file: {$snortcfg['disable_sid_file']}\n"), 3, $log_file); + + // Attempt to open the 'disable_sid_file' for the interface + if (!file_exists("{$snort_sidmods_dir}{$snortcfg['disable_sid_file']}")) { + log_error(gettext("[Snort] Error - unable to open 'disable_sid_file' \"{$snortcfg['disable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + if ($log_results == TRUE) + error_log(gettext("Unable to open disable_sid file \"{$snortcfg['disable_sid_file']}\".\n"), 3, $log_file); + } + else + $sid_mods = snort_parse_sidconf_file("{$snort_sidmods_dir}{$snortcfg['disable_sid_file']}"); + + if (!empty($sid_mods)) + $disables = snort_get_auto_category_mods($enabled_cats, $sid_mods, "disable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$snortcfg['disable_sid_file']}\".\n"), 3, $log_file); + } + } + break; + + default: + log_error(gettext("[Snort] Unrecognized 'sid_state_order' value. Skipping auto CATEGORY mgmt step for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + if ($log_results == TRUE) { + error_log(gettext("ERROR: unrecognized 'sid_state_order' value. Skipping auto CATEGORY mgmt step for ") . convert_friendly_interface_to_friendly_descr($snortcfg['interface']). ".\n", 3, $log_file); + } + } + + if ($log_results == TRUE) { + error_log(gettext("End Time: " . date("Y-m-d H:i:s") . "\n"), 3, $log_file); + error_log(gettext("********************************************************\n\n"), 3, $log_file); + } + + // Return the required rule category modifications as an array; + return array_merge($enables, $disables); +} + +function snort_get_auto_category_mods($categories, $sid_mods, $action, $log_results = FALSE, $log_file = NULL) { + + /****************************************************/ + /* This function parses the provided SID mod tokens */ + /* in $sid_mods and returns an array of category */ + /* files that must be added ('enabled') or removed */ + /* ('disabled') from the provided $categories list */ + /* of enabled rule categories as determined by the */ + /* content of the SID Mgmt tokens in $sid_mods. */ + /* */ + /* The returned array shows which files should be */ + /* removed and which should be added to the list */ + /* used when building the enforcing ruleset. */ + /* */ + /* $categories ==> array of currently enabled */ + /* ruleset categories */ + /* $sid_mods ==> array of SID modification */ + /* tokens */ + /* $action ==> modification action for */ + /* matching category targets: */ + /* 'enable' or 'disable' */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename of log */ + /* file to write to */ + /* */ + /* Returns ==> array of category file names */ + /* for the interface. The keys */ + /* are category file names and */ + /* the corresponding values show */ + /* if the file should be added */ + /* or removed from the enabled */ + /* rulesets list. */ + /* */ + /* Example - */ + /* $changes[file] = 'enabled' */ + /* */ + /****************************************************/ + + $snortdir = SNORTDIR; + $all_cats = array(); + $changes = array(); + $counter = 0; + $matchcount = 0; + + // Get a list of all possible categories by loading all rules files + foreach (array( VRT_FILE_PREFIX, ET_OPEN_FILE_PREFIX, ET_PRO_FILE_PREFIX, GPL_FILE_PREFIX ) as $prefix) { + $files = glob("{$snortdir}/rules/{$prefix}*.rules"); + foreach ($files as $file) + $all_cats[] = basename($file); + } + + // Walk the SID mod tokens and decode looking for rule + // category enable/disable changes. + foreach ($sid_mods as $tok) { + $matches = array(); + // Test the SID token for a GID:SID range and skip if true + if (preg_match('/^(\d+):(\d+)-\1:(\d+)/', $tok)) + continue; + // Test the token for a single GID:SID and skip if true + elseif (preg_match('/^(\d+):(\d+)$/', $tok)) + continue; + // Test the token for the PCRE: keyword and skip if true + elseif (preg_match('/(^pcre\:)(.+)/i', $tok)) + continue; + // Test the token for the MS reference keyword and skip if true + elseif (preg_match('/^MS\d+-.+/i', $tok)) + continue; + // Test the token for other keywords delimited with a colon and skip if true + elseif (preg_match('/^[a-xA-X]+\:.+/', $tok)) + continue; + // Test the SID token for a rule category name. Anything that + // failed to match above is considered a potential category name. + elseif (preg_match('/[a-xA-X]+(-|\w).*/', $tok, $matches)) { + $counter++; + $regex = "/" . preg_quote(trim($matches[0]), '/') . "/i"; + // Search through the $all_cats array for any matches to the regex + $matches = preg_grep($regex, $all_cats); + + // See if any matches are in the $categories array + foreach ($matches as $cat) { + switch ($action) { + case 'enable': + if (!isset($changes[$cat])) { + $changes[$cat] = 'enabled'; + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext(" Enabled rule category: {$cat}\n"), 3, $log_file); + $matchcount++; + } + break; + + case 'disable': + if (!isset($changes[$cat])) { + $changes[$cat] = 'disabled'; + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext(" Disabled rule category: {$cat}\n"), 3, $log_file); + $matchcount++; + } + break; + + default: + break; + } + } + } + else { + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext("WARNING: unrecognized token '{$tok}' encountered while processing an automatic SID MGMT file.\n"), 3, $log_file); + } + } + + if ($log_results == TRUE && !empty($log_file)) { + error_log(gettext(" Parsed {$counter} potential Rule Categories to match from the list of tokens.\n"), 3, $log_file); + error_log(gettext(" " . ucfirst($action) . "d {$matchcount} matching Rule Categories.\n"), 3, $log_file); + } + + // Release memory no longer needed + unset($all_cats, $matches); + + // Return array of rule category file changes + return $changes; +} + +function snort_modify_sid_state(&$rule_map, $sid_mods, $action, $log_results = FALSE, $log_file = NULL) { + + /**********************************************/ + /* This function walks the provided array of */ + /* SID modification tokens and locates the */ + /* target SID or SIDs in the $rule_map array. */ + /* It then performs the change specified by */ + /* $action on the target SID or SIDs. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $sid_mods ==> array of SID modification */ + /* tokens */ + /* $action ==> modification action for */ + /* matching SID targets: */ + /* 'enable' or 'disable' */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> $rule_map array modified */ + /* by changing state for */ + /* matching SIDs. */ + /* */ + /* Returns a two-dimension */ + /* array of matching GID:SID */ + /* pairs. */ + /**********************************************/ + + $sids = array(); + + // If no rules in $rule_map or mods in $sid_mods, + // then nothing to do. + if (empty($rule_map) || empty($sid_mods)) + return $sids; + + // Validate the action keyword as we only accept + // 'enable' and 'disable' as valid. + switch ($action) { + + case "enable": + break; + + case "disable": + break; + + default: + log_error(gettext("[Snort] Error - unknown action '{$action}' supplied to snort_modify_sid_state() function...no SIDs modified.")); + return $sids; + } + + // Walk the SID mod tokens and decode each one + foreach ($sid_mods as $tok) { + $matches = array(); + // Test the SID token for a GID:SID range + if (preg_match('/^(\d+):(\d+)-\1:(\d+)/', $tok, $matches)) { + // It was a range, so find all the intervening SIDs + $gid = trim($matches[1]); + $lsid = trim($matches[2]); + $usid = trim($matches[3]); + $sids[$gid][$lsid] = $action; + while ($lsid < $usid) { + $lsid++; + $sids[$gid][$lsid] = $action; + } + } + // Test the SID token for a single GID:SID + elseif (preg_match('/^(\d+):(\d+)$/', $tok, $matches)) { + // It's a single GID:SID, so grab it + $sids[$matches[1]][$matches[2]] = $action; + } + // Test the SID token for the PCRE: keyword + elseif (preg_match('/(^pcre\:)(.+)/i', $tok, $matches)) { + $regex = '/' . preg_quote($matches[2], '/') . '/i'; + + // Now search through the $rule_map in the 'rule' + // element for any matches to the regex and get + // the GID:SID. + foreach ($rule_map as $k1 => $rulem) { + foreach ($rulem as $k2 => $v) { + if (preg_match($regex, $v['rule'])) { + $sids[$k1][$k2] = $action; + } + } + } + } + // Test the SID token for the MS reference keyword + elseif (preg_match('/^MS\d+-.+/i', $tok, $matches)) { + $regex = "/" . preg_quote($matches[0], '/') . "/i"; + + // Now search through the $rule_map in the 'rule' + // element for any matches to the regex and get + // the GID:SID. + foreach ($rule_map as $k1 => $rulem) { + foreach ($rulem as $k2 => $v) { + if (preg_match($regex, $v['rule'])) { + $sids[$k1][$k2] = $action; + } + } + } + } + // Test the SID token for other keywords delimited with a colon + elseif (preg_match('/^[a-xA-X]+\:.+/', $tok, $matches)) { + $regex = "/" . str_replace(':', ",", preg_quote($matches[0], '/')) . "/i"; + + // Now search through the $rule_map in the 'rule' + // element for any matches to the regex and get + // the GID:SID. + foreach ($rule_map as $k1 => $rulem) { + foreach ($rulem as $k2 => $v) { + if (preg_match($regex, $v['rule'])) { + $sids[$k1][$k2] = $action; + } + } + } + } + // Test the SID token for a rule category name. Anything that + // failed to match above is considered a potential category name. + elseif (preg_match('/[a-xA-X]+(-|\w).*/', $tok, $matches)) { + $regex = "/" . preg_quote(trim($matches[0]), '/') . "/i"; + // Now search through the $rule_map in the 'category' + // element for any matches to the regex and get + // the GID:SID. + foreach ($rule_map as $k1 => $rulem) { + foreach ($rulem as $k2 => $v) { + if (preg_match($regex, $v['category'] . ".rules")) { + $sids[$k1][$k2] = $action; + } + } + } + } + else { + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext("WARNING: unrecognized token '{$tok}' encountered while processing an automatic SID MGMT file.\n"), 3, $log_file); + } + } + + // Change state of all the matching GID:SID pairs we found + // above in the $rule_map array passed to us. + $modcount = $changecount = 0; + $counter = count($sids, COUNT_RECURSIVE) - count($sids); + + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext(" Parsed {$counter} potential SIDs to match from the provided list of tokens.\n"), 3, $log_file); + + foreach (array_keys($sids) as $k1) { + foreach (array_keys($sids[$k1]) as $k2) { + if (isset($rule_map[$k1][$k2])) { + if ($action == 'enable' && $rule_map[$k1][$k2]['disabled'] == 1) { + $rule_map[$k1][$k2]['rule'] = ltrim($rule_map[$k1][$k2]['rule'], " \t#"); + $rule_map[$k1][$k2]['disabled'] = 0; + $rule_map[$k1][$k2]['managed'] = 1; + $changecount++; + $modcount++; + } + elseif ($action == 'disable' && $rule_map[$k1][$k2]['disabled'] == 0) { + $rule_map[$k1][$k2]['rule'] = "# " . $rule_map[$k1][$k2]['rule']; + $rule_map[$k1][$k2]['disabled'] = 1; + $rule_map[$k1][$k2]['managed'] = 1; + $changecount++; + $modcount++; + } + } + } + } + + if ($log_results == TRUE && !empty($log_file)) { + error_log(gettext(" Found {$modcount} matching SIDs in the active rules.\n"), 3, $log_file); + error_log(gettext(" Changed state for {$changecount} SIDs to '{$action}d'.\n"), 3, $log_file); + } + + // Return the array of matching SIDs + return $sids; +} + +function snort_modify_sid_content(&$rule_map, $sid_mods, $log_results = FALSE, $log_file = NULL) { + + /************************************************/ + /* This function walks the provided array of */ + /* SID modification tokens and locates the */ + /* target SID or SIDs in the $rule_map array. */ + /* It then modifies the content of the target */ + /* SID or SIDs. Modifications are only valid */ + /* for normal GID=1 text rules. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $sid_mods ==> array of SID modification */ + /* tokens */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> $rule_map array modified */ + /* by changing content for */ + /* matching SIDs. */ + /* */ + /* Returns a two-dimension */ + /* array of matching */ + /* GID:SID pairs. */ + /************************************************/ + + $sids = array(); + $tokencounter = $modcount = $modifiedcount = 0; + + // If no rules in $rule_map or mods in $sid_mods, + // then nothing to do. + if (empty($rule_map) || empty($sid_mods)) + return $sids; + + // Walk the SID mod tokens and decode each one + foreach ($sid_mods as $tok) { + $matches = array(); + if (preg_match('/([\d+|,|\*]*)\s+"(.+)"\s+"(.*)"/', $tok, $matches)) { + $tokencounter++; + $sidlist = explode(",", $matches[1]); + $from = '/' . preg_quote($matches[2], '/') . '/'; + $to = $matches[3]; + $count = 0; + + // Now walk the provided rule map and make the modifications + if ($matches[1] == "*") { + // If wildcard '*' provided for SID, then check them all + foreach ($rule_map[1] as $rulem) { + foreach ($rulem as $k2 => $v) { + $modcount++; + $rule_map[1][$k2]['rule'] = preg_replace($from, $to, $v['rule'], -1, $count); + if ($count > 0) { + $rule_map[1][$k2]['managed'] = 1; + $sids[1][$k2] = 'modify'; + $modifiedcount++; + } + } + } + } + else { + // Otherwise just check the provided SIDs + foreach ($sidlist as $sid) { + if (isset($rule_map[1][$sid])) { + $modcount++; + $rule_map[1][$sid]['rule'] = preg_replace($from, $to, $rule_map[1][$sid]['rule'], -1, $count); + if ($count > 0) { + $rule_map[1][$sid]['managed'] = 1; + $sids[1][$sid] = 'modify'; + $modifiedcount++; + } + } + } + } + } + else { + if ($log_results == TRUE && !empty($log_file)) + error_log(gettext("WARNING: unrecognized token '{$tok}' encountered while processing an automatic SID MGMT file.\n"), 3, $log_file); + } + } + + if ($log_results == TRUE && !empty($log_file)) { + error_log(gettext(" Parsed {$tokencounter} potential SIDs to match from the provided list of tokens.\n"), 3, $log_file); + error_log(gettext(" Found {$modcount} matching SIDs in the active rules.\n"), 3, $log_file); + error_log(gettext(" Modified rule text for {$modifiedcount} SIDs.\n"), 3, $log_file); + } + + // Return the array of matching SIDs + return $sids; +} + +function snort_process_enablesid(&$rule_map, $snortcfg, $log_results = FALSE, $log_file = NULL) { + + /**********************************************/ + /* This function loads and processes the file */ + /* specified by 'enable_sid_file' for the */ + /* interface. The file is assumed to be a */ + /* valid enablesid.conf file containing */ + /* instructions for enabling matching rule */ + /* SIDs. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $snortcfg ==> interface config params */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> suitably modified */ + /* $rule_map array */ + /**********************************************/ + + $snort_sidmods_dir = SID_MODS_PATH; + $snortlogdir = SNORTLOGDIR; + $sid_mods = array(); + + // If no rules in $rule_map, then nothing to do + if (empty($rule_map)) + return; + + // Attempt to open the 'enable_sid_file' for the interface + if (!file_exists("{$snort_sidmods_dir}{$snortcfg['enable_sid_file']}")) { + log_error(gettext("[Snort] Error - unable to open 'enable_sid_file' \"{$snortcfg['enable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + return; + } + else + $sid_mods = snort_parse_sidconf_file("{$snort_sidmods_dir}{$snortcfg['enable_sid_file']}"); + + if (!empty($sid_mods)) + snort_modify_sid_state($rule_map, $sid_mods, "enable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$snortcfg['enable_sid_file']}\".\n"), 3, $log_file); + } + + unset($sid_mods); +} + +function snort_process_disablesid(&$rule_map, $snortcfg, $log_results = FALSE, $log_file = NULL) { + + /**********************************************/ + /* This function loads and processes the file */ + /* specified by 'disable_sid_file' for the */ + /* interface. The file is assumed to be a */ + /* valid disablesid.conf file containing */ + /* instructions for disabling matching rule */ + /* SIDs. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $snortcfg ==> interface config params */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> suitably modified */ + /* $rule_map array */ + /**********************************************/ + + $snort_sidmods_dir = SID_MODS_PATH; + $snortlogdir = SNORTLOGDIR; + $sid_mods = array(); + + // If no rules in $rule_map, then nothing to do + if (empty($rule_map)) + return; + + // Attempt to open the 'disable_sid_file' for the interface + if (!file_exists("{$snort_sidmods_dir}{$snortcfg['disable_sid_file']}")) { + log_error(gettext("[Snort] Error - unable to open 'disable_sid_file' \"{$snortcfg['disable_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + return; + } + else + $sid_mods = snort_parse_sidconf_file("{$snort_sidmods_dir}{$snortcfg['disable_sid_file']}"); + + if (!empty($sid_mods)) + snort_modify_sid_state($rule_map, $sid_mods, "disable", $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$snortcfg['disable_sid_file']}\".\n"), 3, $log_file); + } + + unset($sid_mods); +} + +function snort_process_modifysid(&$rule_map, $snortcfg, $log_results = FALSE, $log_file = NULL) { + + /**********************************************/ + /* This function loads and processes the file */ + /* specified by 'modify_sid_file' for the */ + /* interface. The file is assumed to be a */ + /* valid modifysid.conf file containing */ + /* instructions for modifying matching rule */ + /* SIDs. */ + /* */ + /* $rule_map ==> reference to array of */ + /* current rules */ + /* $snortcfg ==> interface config params */ + /* $log_results ==> [optional] 'yes' to log */ + /* results to $log_file */ + /* $log_file ==> full path and filename */ + /* of log file to write to */ + /* */ + /* On Return ==> suitably modified */ + /* $rule_map array */ + /**********************************************/ + + $snort_sidmods_dir = SID_MODS_PATH; + $snortlogdir = SNORTLOGDIR; + $sid_mods = array(); + + // If no rules in $rule_map, then nothing to do + if (empty($rule_map)) + return; + + // Attempt to open the 'modify_sid_file' for the interface + if (!file_exists("{$snort_sidmods_dir}{$snortcfg['modify_sid_file']}")) { + log_error(gettext("[Snort] Error - unable to open 'modify_sid_file' \"{$snortcfg['modify_sid_file']}\" specified for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + return; + } + else + $sid_mods = snort_parse_sidconf_file("{$snort_sidmods_dir}{$snortcfg['modify_sid_file']}"); + + if (!empty($sid_mods)) + snort_modify_sid_content($rule_map, $sid_mods, $log_results, $log_file); + elseif ($log_results == TRUE && !empty($log_file)) { + error_log(gettext("WARNING: no valid SID match tokens found in file \"{$snortcfg['modify_sid_file']}\".\n"), 3, $log_file); + } + + unset($sid_mods); +} + +function snort_auto_sid_mgmt(&$rule_map, $snortcfg, $log_results = FALSE) { + + /**************************************************/ + /* This function modifies the rules in the */ + /* passed rule_map array based on values in the */ + /* files 'enable_sid_file', 'disable_sid_file' */ + /* and 'modify_sid_file' for the interface. */ + /* */ + /* If auto-mgmt of SIDs is enabled via the */ + /* settings on the UPDATE RULES tab, then the */ + /* rules are processed against these settings. */ + /* */ + /* $rule_map ==> array of current rules */ + /* $snortcfg ==> interface config settings */ + /* $log_results ==> [optional] log results to */ + /* 'sid_changes.log' in the */ + /* interface directory in */ + /* /var/log/snort when TRUE */ + /* */ + /* Returns ==> TRUE if rules were changed; */ + /* otherwise FALSE */ + /**************************************************/ + + global $config; + $result = FALSE; + + // Configure the interface's logging subdirectory if log results is enabled + if ($log_results == TRUE) + $log_file = SNORTLOGDIR . "/snort_" . get_real_interface($snortcfg['interface']) . "{$snortcfg['uuid']}/sid_changes.log"; + else + $log_file = NULL; + + // Check if auto-mgmt of SIDs is enabled and files are specified + // for the interface. + if ($config['installedpackages']['snortglobal']['auto_manage_sids'] == 'on' && + (!empty($snortcfg['disable_sid_file']) || !empty($snortcfg['enable_sid_file']) || + !empty($snortcfg['modify_sid_file']))) { + if ($log_results == TRUE) { + error_log(gettext("********************************************************\n"), 3, $log_file); + error_log(gettext("Starting auto SID management for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']) ."\n"), 3, $log_file); + error_log(gettext("Start Time: " . date("Y-m-d H:i:s") . "\n"), 3, $log_file); + } + + switch ($snortcfg['sid_state_order']) { + case "disable_enable": + if (!empty($snortcfg['disable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing disable_sid file: {$snortcfg['disable_sid_file']}\n"), 3, $log_file); + snort_process_disablesid($rule_map, $snortcfg, $log_results, $log_file); + } + if (!empty($snortcfg['enable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing enable_sid file: {$snortcfg['enable_sid_file']}\n"), 3, $log_file); + snort_process_enablesid($rule_map, $snortcfg, $log_results, $log_file); + } + if (!empty($snortcfg['modify_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing modify_sid file: {$snortcfg['modify_sid_file']}\n"), 3, $log_file); + snort_process_modifysid($rule_map, $snortcfg, $log_results, $log_file); + } + $result = TRUE; + break; + + case "enable_disable": + if (!empty($snortcfg['enable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing enable_sid file: {$snortcfg['enable_sid_file']}\n"), 3, $log_file); + snort_process_enablesid($rule_map, $snortcfg, $log_results, $log_file); + } + if (!empty($snortcfg['disable_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing disable_sid file: {$snortcfg['disable_sid_file']}\n"), 3, $log_file); + snort_process_disablesid($rule_map, $snortcfg, $log_results, $log_file); + } + if (!empty($snortcfg['modify_sid_file'])) { + if ($log_results == TRUE) + error_log(gettext("Processing modify_sid file: {$snortcfg['modify_sid_file']}\n"), 3, $log_file); + snort_process_modifysid($rule_map, $snortcfg, $log_results, $log_file); + } + $result = TRUE; + break; + + default: + log_error(gettext("[Snort] Unrecognized 'sid_state_order' value. Skipping auto SID mgmt step for " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']))); + if ($log_results == TRUE) { + error_log(gettext("ERROR: unrecognized 'sid_state_order' value. Skipping auto SID mgmt step for ") . convert_friendly_interface_to_friendly_descr($snortcfg['interface']). ".\n", 3, $log_file); + } + $result = FALSE; + } + + if ($log_results == TRUE) { + error_log(gettext("End Time: " . date("Y-m-d H:i:s") . "\n"), 3, $log_file); + error_log(gettext("********************************************************\n\n"), 3, $log_file); + } + } + return $result; +} + function snort_load_sid_mods($sids) { /*****************************************/ @@ -2226,6 +3077,9 @@ function snort_prepare_rule_files($snortcfg, $snortcfgdir) { $snortdir = SNORTDIR; $flowbit_rules_file = FLOWBITS_FILENAME; $snort_enforcing_rules_file = ENFORCING_RULES_FILENAME; + $enabled_files = array(); + $all_rules = array(); + $cat_mods = array(); $no_rules_defined = true; $enabled_rules = array(); @@ -2236,6 +3090,10 @@ function snort_prepare_rule_files($snortcfg, $snortcfgdir) { /* Log a message for rules rebuild in progress */ log_error(gettext("[Snort] Updating rules configuration for: " . convert_friendly_interface_to_friendly_descr($snortcfg['interface']) . " ...")); + // Get any automatic rule category enable/disable modifications + // if auto-SID Mgmt is enabled and conf files exist for the interface. + $cat_mods = snort_sid_mgmt_auto_categories($snortcfg, TRUE); + /* Enable all, some or none of the SDF rules depending on setting. */ if ($snortcfg['sensitive_data'] == 'on' && $snortcfg['protect_preproc_rules'] != 'on') { if (file_exists(SNORTDIR."/preproc_rules/sensitive-data.rules")) { @@ -2262,8 +3120,6 @@ function snort_prepare_rule_files($snortcfg, $snortcfgdir) { /* Only rebuild rules if some are selected or an IPS Policy is enabled */ if (!empty($snortcfg['rulesets']) || $snortcfg['ips_policy_enable'] == 'on') { - $enabled_files = array(); - $all_rules = array(); $no_rules_defined = false; /* Load up all the text rules into a Rules Map array. */ @@ -2279,6 +3135,28 @@ function snort_prepare_rule_files($snortcfg, $snortcfgdir) { $enabled_files[$category] = $file; } + // Now adjust the list using any required changes as + // determined by auto-SID Mgmt policy files. + if (!empty($cat_mods)) { + foreach ($cat_mods as $k => $action) { + $key = basename($k, ".rules"); + switch ($action) { + case 'enabled': + if (!isset($enabled_files[$key])) + $enabled_files[$key] = $k; + break; + + case 'disabled': + if (isset($enabled_files[$key])) + unset($enabled_files[$key]); + break; + + default: + break; + } + } + } + /****************************************************/ /* Walk the ALL_RULES map array and copy the rules */ /* matching our selected file categories to the */ @@ -2301,7 +3179,7 @@ function snort_prepare_rule_files($snortcfg, $snortcfgdir) { } /* Release memory we no longer need. */ - unset($enabled_files, $rulem, $v); + unset($enabled_files, $cat_mods, $rulem, $v); } /* Check if a pre-defined Snort VRT policy is selected. If so, */ @@ -2324,7 +3202,9 @@ function snort_prepare_rule_files($snortcfg, $snortcfgdir) { unset($policy_rules, $policy, $p); } - /* Process any enablesid or disablesid modifications for the selected rules. */ + // Process any enablesid or disablesid modifications for the selected rules. + // Do the auto-SID managment first, if enabled, then do any manual SID state changes. + snort_auto_sid_mgmt($enabled_rules, $snortcfg, TRUE); snort_modify_sids($enabled_rules, $snortcfg); /* Check for and disable any rules dependent upon disabled preprocessors if */ @@ -2357,7 +3237,45 @@ function snort_prepare_rule_files($snortcfg, $snortcfgdir) { } else /* Just put an empty file to always have the file present */ snort_write_flowbit_rules_file(array(), "{$snortcfgdir}/rules/{$flowbit_rules_file}"); - } else { + unset($all_rules); + } + // If no rule categories were enabled, then use auto-SID management if enabled, since it may enable some rules + elseif ($config['installedpackages']['snortglobal']['auto_manage_sids'] == 'on' && + (!empty($snortcfg['disable_sid_file']) || !empty($snortcfg['enable_sid_file']) || + !empty($snortcfg['modify_sid_file']))) { + + snort_auto_sid_mgmt($enabled_rules, $snortcfg, TRUE); + if (!empty($enabled_rules)) { + // Auto-SID management generated some rules, so use them + $no_rules_defined = false; + snort_modify_sids($enabled_rules, $snortcfg); + + // Write the enforcing rules file to the Suricata interface's "rules" directory. + snort_write_enforcing_rules_file($enabled_rules, "{$snortcfgdir}/rules/{$snort_enforcing_rules_file}"); + + // If auto-flowbit resolution is enabled, generate the dependent flowbits rules file. + if ($snortcfg['autoflowbitrules'] == 'on') { + log_error('[Suricata] Enabling any flowbit-required rules for: ' . convert_friendly_interface_to_friendly_descr($snortcfg['interface']) . '...'); + + // Load up all rules into a Rules Map array for flowbits assessment + $all_rules = snort_load_rules_map("{$snortdir}/rules/"); + $fbits = snort_resolve_flowbits($all_rules, $enabled_rules); + + // Check for and disable any flowbit-required rules the + // user has manually forced to a disabled state. + snort_modify_sids($fbits, $snortcfg); + snort_write_flowbit_rules_file($fbits, "{$snortcfgdir}/rules/{$flowbit_rules_file}"); + unset($all_rules, $fbits); + } else + // Just put an empty file to always have the file present + snort_write_flowbit_rules_file(array(), "{$snortcfgdir}/rules/{$flowbit_rules_file}"); + } + else { + snort_write_enforcing_rules_file(array(), "{$snortcfgdir}/rules/{$snort_enforcing_rules_file}"); + snort_write_flowbit_rules_file(array(), "{$snortcfgdir}/rules/{$flowbit_rules_file}"); + } + } + else { /* No regular rules or policy were selected, so just use the decoder and preproc rules */ snort_write_enforcing_rules_file($enabled_rules, "{$snortcfgdir}/rules/{$snort_enforcing_rules_file}"); snort_write_flowbit_rules_file(array(), "{$snortcfgdir}/rules/{$flowbit_rules_file}"); diff --git a/config/snort/snort_rules.php b/config/snort/snort_rules.php index 8d9aa6ba..013b7d84 100755 --- a/config/snort/snort_rules.php +++ b/config/snort/snort_rules.php @@ -109,6 +109,29 @@ $categories[] = "custom.rules"; $categories[] = "decoder.rules"; $categories[] = "preprocessor.rules"; $categories[] = "sensitive-data.rules"; + +// Get any automatic rule category enable/disable modifications +// if auto-SID Mgmt is enabled, and adjust the available rulesets +// in the CATEGORY drop-down box as necessary. +$cat_mods = snort_sid_mgmt_auto_categories($a_rule[$id], FALSE); +foreach ($cat_mods as $k => $v) { + switch ($v) { + case 'disabled': + if (($key = array_search($k, $categories)) !== FALSE) + unset($categories[$key]); + break; + + case 'enabled': + if (!in_array($k, $categories)) + $categories[] = $k; + break; + + default: + break; + } +} + +// Add any enabled IPS-Policy and Auto-Flowbits File if (!empty($a_rule[$id]['ips_policy'])) $categories[] = "IPS Policy - " . ucfirst($a_rule[$id]['ips_policy']); if ($a_rule[$id]['autoflowbitrules'] == 'on') @@ -146,6 +169,9 @@ if ($currentruleset != 'custom.rules') { $input_errors[] = gettext("{$currentruleset} seems to be missing!!! Please verify rules files have been downloaded, then go to the Categories tab and save the rule set again."); } +/* Process the current category rules through any auto SID MGMT changes if enabled */ +snort_auto_sid_mgmt($rules_map, $a_rule[$id], FALSE); + /* Load up our enablesid and disablesid arrays with enabled or disabled SIDs */ $enablesid = snort_load_sid_mods($a_rule[$id]['rule_sid_on']); $disablesid = snort_load_sid_mods($a_rule[$id]['rule_sid_off']); @@ -356,6 +382,9 @@ elseif ($_POST['clear']) { conf_mount_ro(); $rebuild_rules = false; $pconfig['customrules'] = ''; + + // Sync to configured CARP slaves if any are enabled + snort_sync_on_changes(); } elseif ($_POST['save']) { $pconfig['customrules'] = $_POST['customrules']; @@ -388,6 +417,9 @@ elseif ($_POST['save']) { } clear_subsystem_dirty('snort_rules'); + + // Sync to configured CARP slaves if any are enabled + snort_sync_on_changes(); } else if ($_POST['apply']) { /* Save new configuration */ @@ -408,6 +440,9 @@ else if ($_POST['apply']) { // We have saved changes and done a soft restart, so clear "dirty" flag clear_subsystem_dirty('snort_rules'); + + // Sync to configured CARP slaves if any are enabled + snort_sync_on_changes(); } include_once("head.inc"); @@ -453,7 +488,8 @@ if ($savemsg) { $tab_array[5] = array(gettext("Pass Lists"), false, "/snort/snort_passlist.php"); $tab_array[6] = array(gettext("Suppress"), false, "/snort/snort_interfaces_suppress.php"); $tab_array[7] = array(gettext("IP Lists"), false, "/snort/snort_ip_list_mgmt.php"); - $tab_array[8] = array(gettext("Sync"), false, "/pkg_edit.php?xml=snort/snort_sync.xml"); + $tab_array[8] = array(gettext("SID Mgmt"), false, "/snort/snort_sid_mgmt.php"); + $tab_array[9] = array(gettext("Sync"), false, "/pkg_edit.php?xml=snort/snort_sync.xml"); display_top_tabs($tab_array,true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -614,17 +650,35 @@ if ($savemsg) { </thead> <tbody> <?php - $counter = $enable_cnt = $disable_cnt = 0; + $counter = $enable_cnt = $disable_cnt = $user_enable_cnt = $user_disable_cnt = $managed_count = 0; foreach ($rules_map as $k1 => $rulem) { foreach ($rulem as $k2 => $v) { $sid = $k2; $gid = $k1; - - if (isset($disablesid[$gid][$sid])) { + $ruleset = $currentruleset; + $style = ""; + + if ($v['managed'] == 1) { + if ($v['disabled'] == 1) { + $textss = "<span class=\"gray\">"; + $textse = "</span>"; + $style= "style=\"opacity: 0.4; filter: alpha(opacity=40);\""; + $title = gettext("Auto-disabled by settings on SID Mgmt tab"); + } + else { + $textss = $textse = ""; + $ruleset = "suricata.rules"; + $title = gettext("Auto-managed by settings on SID Mgmt tab"); + } + $iconb = "icon_advanced.gif"; + $managed_count++; + } + elseif (isset($disablesid[$gid][$sid])) { $textss = "<span class=\"gray\">"; $textse = "</span>"; $iconb = "icon_reject_d.gif"; $disable_cnt++; + $user_disable_cnt++; $title = gettext("Disabled by user. Click to toggle to enabled state"); } elseif (($v['disabled'] == 1) && (!isset($enablesid[$gid][$sid]))) { @@ -638,6 +692,7 @@ if ($savemsg) { $textss = $textse = ""; $iconb = "icon_reject.gif"; $enable_cnt++; + $user_enable_cnt++; $title = gettext("Enabled by user. Click to toggle to disabled state"); } else { @@ -668,12 +723,18 @@ if ($savemsg) { $message = snort_get_msg($v['rule']); // description field $sid_tooltip = gettext("View the raw text for this rule"); - echo "<tr><td class=\"listt\" align=\"left\" valign=\"middle\">{$textss} - <a id=\"rule_{$gid}_{$sid}\" href=''><input type=\"image\" onClick=\"document.getElementById('sid').value='{$sid}'; - document.getElementById('gid').value='{$gid}';\" - src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" - title='{$title}' name=\"toggle[]\"/></a>{$textse} - </td> + echo "<tr><td class=\"listt\" style=\"align:center;\" valign=\"middle\">{$textss}"; + if ($v['managed'] == 1) { + echo "<img {$style} src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" + title='{$title}'/>{$textse}"; + } + else { + echo "<a id=\"rule_{$gid}_{$sid}\" href='#'><input type=\"image\" onClick=\"document.getElementById('sid').value='{$sid}'; + document.getElementById('gid').value='{$gid}';\" + src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" + title='{$title}' name=\"toggle[]\"/></a>{$textse}"; + } + echo "</td> <td class=\"listr\" align=\"center\" ondblclick=\"wopen('snort_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$textss}{$gid}{$textse} </td> @@ -734,16 +795,35 @@ if ($savemsg) { </thead> <tbody> <?php - $counter = $enable_cnt = $disable_cnt = 0; + $counter = $enable_cnt = $disable_cnt = $user_enable_cnt = $user_disable_cnt = $managed_count = 0; foreach ($rules_map as $k1 => $rulem) { foreach ($rulem as $k2 => $v) { + $ruleset = $currentruleset; + $style = ""; $sid = snort_get_sid($v['rule']); $gid = snort_get_gid($v['rule']); - if (isset($disablesid[$gid][$sid])) { + + if ($v['managed'] == 1) { + if ($v['disabled'] == 1) { + $textss = "<span class=\"gray\">"; + $textse = "</span>"; + $style= "style=\"opacity: 0.4; filter: alpha(opacity=40);\""; + $title = gettext("Auto-disabled by settings on SID Mgmt tab"); + } + else { + $textss = $textse = ""; + $ruleset = "suricata.rules"; + $title = gettext("Auto-managed by settings on SID Mgmt tab"); + } + $iconb = "icon_advanced.gif"; + $managed_count++; + } + elseif (isset($disablesid[$gid][$sid])) { $textss = "<span class=\"gray\">"; $textse = "</span>"; $iconb = "icon_reject_d.gif"; $disable_cnt++; + $user_disable_cnt++; $title = gettext("Disabled by user. Click to toggle to enabled state"); } elseif (($v['disabled'] == 1) && (!isset($enablesid[$gid][$sid]))) { @@ -757,6 +837,7 @@ if ($savemsg) { $textss = $textse = ""; $iconb = "icon_reject.gif"; $enable_cnt++; + $user_enable_cnt++; $title = gettext("Enabled by user. Click to toggle to disabled state"); } else { @@ -777,12 +858,18 @@ if ($savemsg) { else $policy = "none"; - echo "<tr><td class=\"listt\" align=\"left\" valign=\"middle\">{$textss} - <input type=\"image\" onClick=\"document.getElementById('sid').value='{$sid}'; - document.getElementById('gid').value='{$gid}';\" - src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" - title='{$title}' name=\"toggle[]\"/>{$textse} - </td> + echo "<tr><td class=\"listt\" style=\"align:center;\" valign=\"middle\">{$textss}"; + if ($v['managed'] == 1) { + echo "<img {$style} src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" + title='{$title}'/>{$textse}"; + } + else { + echo "<a id=\"rule_{$gid}_{$sid}\" href='#'><input type=\"image\" onClick=\"document.getElementById('sid').value='{$sid}'; + document.getElementById('gid').value='{$gid}';\" + src=\"../themes/{$g['theme']}/images/icons/{$iconb}\" width=\"11\" height=\"11\" border=\"0\" + title='{$title}' name=\"toggle[]\"/></a>{$textse}"; + } + echo "</td> <td class=\"listr\" align=\"center\" ondblclick=\"wopen('snort_rules_edit.php?id={$id}&openruleset={$currentruleset}&sid={$sid}&gid={$gid}','FileViewer',800,600);\"> {$textss}{$gid}{$textse} </td> @@ -824,7 +911,10 @@ if ($savemsg) { <strong><?php echo gettext("--- Category Rules Summary ---") . "</strong><br/>" . gettext("Total Rules: {$counter}") . " " . gettext("Enabled: {$enable_cnt}") . " " . - gettext("Disabled: {$disable_cnt}"); ?></td> + gettext("Disabled: {$disable_cnt}") . " " . + gettext("User Enabled: {$user_enable_cnt}") . " " . + gettext("User Disabled: {$user_disable_cnt}") . " " . + gettext("Auto-Managed: {$managed_count}"); ?></td> </tr> <tr> <td width="16"><img src="../themes/<?= $g['theme']; ?>/images/icons/icon_block.gif" @@ -846,6 +936,18 @@ if ($savemsg) { width="11" height="11"></td> <td nowrap><?php echo gettext("Rule changed to Disabled by user"); ?></td> </tr> + <?php if (!empty($cat_mods)): ?> + <tr> + <td width="16"><img src="../themes/<?= $g['theme']; ?>/images/icons/icon_advanced.gif" + width="11" height="11"></td> + <td nowrap><?php echo gettext("Rule auto-enabled by files configured on SID Mgmt tab"); ?></td> + </tr> + <tr> + <td width="16"><img style="opacity: 0.4; filter: alpha(opacity=40);" src="../themes/<?= $g['theme']; ?>/images/icons/icon_advanced.gif" + width="11" height="11"></td> + <td nowrap><?php echo gettext("Rule auto-disabled by files configured on SID Mgmt tab"); ?></td> + </tr> + <?php endif; ?> </table> </td> </tr> diff --git a/config/snort/snort_rulesets.php b/config/snort/snort_rulesets.php index 59fe6eef..23f9665b 100755 --- a/config/snort/snort_rulesets.php +++ b/config/snort/snort_rulesets.php @@ -172,6 +172,9 @@ if ($_POST["save"]) { $enabled_rulesets_array = explode("||", $enabled_items); if (snort_is_running($snort_uuid, $if_real)) $savemsg = gettext("Snort is 'live-reloading' the new rule set."); + + // Sync to configured CARP slaves if any are enabled + snort_sync_on_changes(); } if ($_POST['unselectall']) { @@ -226,6 +229,10 @@ if ($_POST['selectall']) { } } +// Get any automatic rule category enable/disable modifications +// if auto-SID Mgmt is enabled. +$cat_mods = snort_sid_mgmt_auto_categories($a_nat[$id], FALSE); + $if_friendly = convert_friendly_interface_to_friendly_descr($a_nat[$id]['interface']); $pgtitle = gettext("Snort: Interface {$if_friendly} - Categories"); include_once("head.inc"); @@ -261,7 +268,8 @@ if ($savemsg) { $tab_array[5] = array(gettext("Pass Lists"), false, "/snort/snort_passlist.php"); $tab_array[6] = array(gettext("Suppress"), false, "/snort/snort_interfaces_suppress.php"); $tab_array[7] = array(gettext("IP Lists"), false, "/snort/snort_ip_list_mgmt.php"); - $tab_array[8] = array(gettext("Sync"), false, "/pkg_edit.php?xml=snort/snort_sync.xml"); + $tab_array[8] = array(gettext("SID Mgmt"), false, "/snort/snort_sid_mgmt.php"); + $tab_array[9] = array(gettext("Sync"), false, "/pkg_edit.php?xml=snort/snort_sync.xml"); display_top_tabs($tab_array, true); echo '</td></tr>'; echo '<tr><td class="tabnavtbl">'; @@ -389,14 +397,25 @@ if ($savemsg) { </tr> <tr> <td colspan="6"> - <table width=90% align="center" border="0" cellpadding="2" cellspacing="0"> - <tr height="45px"> - <td valign="middle"><input value="Select All" class="formbtns" type="submit" name="selectall" id="selectall" title="<?php echo gettext("Add all categories to enforcing rules"); ?>"/></td> - <td valign="middle"><input value="Unselect All" class="formbtns" type="submit" name="unselectall" id="unselectall" title="<?php echo gettext("Remove categories all from enforcing rules"); ?>"/></td> - <td valign="middle"><input value=" Save " class="formbtns" type="submit" name="save" id="save" title="<?php echo gettext("Save changes to enforcing rules and rebuild"); ?>"/></td> - <td valign="middle"><span class="vexpl"><?php echo gettext("Click to save changes and auto-resolve flowbit rules (if option is selected above)"); ?></span></td> + <table width="95%" style="margin-left: auto; margin-right: auto;" border="0" cellpadding="2" cellspacing="0"> + <tbody> + <tr height="32px"> + <td style="vertical-align: middle;"><input value="Select All" class="formbtns" type="submit" name="selectall" id="selectall" title="<?php echo gettext("Add all to enforcing rules"); ?>"/></td> + <td style="vertical-align: middle;"><input value="Unselect All" class="formbtns" type="submit" name="unselectall" id="unselectall" title="<?php echo gettext("Remove all from enforcing rules"); ?>"/></td> + <td style="vertical-align: middle;"><input value=" Save " class="formbtns" type="submit" name="save" id="save" title="<?php echo gettext("Save changes to enforcing rules and rebuild"); ?>"/></td> + <td style="vertical-align: middle;"><span class="vexpl"><?php echo gettext("Click to save changes and auto-resolve flowbit rules (if option is selected above)"); ?></span></td> </tr> + <?php if (!empty($cat_mods)): ?> + <tr height="20px"> + <td colspan="4" style="vertical-align: middle;"><img style="vertical-align: text-top;" src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" /> + <?=gettext("- Category is auto-enabled by SID Mgmt conf files");?> + <img style="opacity: 0.4; filter: alpha(opacity=40); vertical-align: text-top;" src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" /> + <?=gettext("- Category is auto-disabled by SID Mgmt conf files");?></td> + </tr> + <?php endif; ?> + </tbody> </table> + </td> </tr> <?php if ($no_community_files) $msg_community = "NOTE: Snort Community Rules have not been downloaded. Perform a Rules Update to enable them."; @@ -409,22 +428,34 @@ if ($savemsg) { <td width="5%" class="listhdrr"><?php echo gettext("Enabled"); ?></td> <td colspan="5" class="listhdrr"><?php echo gettext('Ruleset: Snort GPLv2 Community Rules');?></td> </tr> - <?php if (in_array($community_rules_file, $enabled_rulesets_array)): ?> + <?php if (isset($cat_mods[$community_rules_file])): ?> + <?php if ($cat_mods[$community_rules_file] == 'enabled') : ?> + <tr> + <td width="5%" class="listr" style="text-align: center;"> + <img src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" title="<?=gettext("Auto-managed by settings on SID Mgmt tab");?>" /></td> + <td colspan="5" class="listr"><a href='suricata_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?=gettext("{$msg_community}");?></a></td> + </tr> + <?php else: ?> + <tr> + <td width="5%" class="listr" style="text-align: center;"> + <img style="opacity: 0.4; filter: alpha(opacity=40);" src="../themes/<?=$g['theme'];?>/images/icons/icon_advanced.gif" width="11" height="11" border="0" title="<?=gettext("Auto-managed by settings on SID Mgmt tab");?>" /></td> + <td colspan="5" class="listr"><?=gettext("{$msg_community}"); ?></td> + </tr> + <?php endif; ?> + <?php elseif (in_array($community_rules_file, $enabled_rulesets_array)): ?> <tr> - <td width="5" class="listr" align="center" valign="top"> + <td width="5%" class="listr" style="text-align: center;"> <input type="checkbox" name="toenable[]" value="<?=$community_rules_file;?>" checked="checked"/></td> - <td colspan="5" class="listr"><a href='snort_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?php echo gettext("{$msg_community}"); ?></a></td> + <td colspan="5" class="listr"><a href='suricata_rules.php?id=<?=$id;?>&openruleset=<?=$community_rules_file;?>'><?php echo gettext("{$msg_community}"); ?></a></td> </tr> <?php else: ?> <tr> - <td width="5" class="listr" align="center" valign="top"> + <td width="5%" class="listr" style="text-align: center;"> <input type="checkbox" name="toenable[]" value="<?=$community_rules_file;?>" <?php if ($snortcommunitydownload == 'off') echo "disabled"; ?>/></td> <td colspan="5" class="listr"><?php echo gettext("{$msg_community}"); ?></td> </tr> - <?php endif; ?> <?php endif; ?> - <?php if ($no_emerging_files && ($emergingdownload == 'on' || $etpro == 'on')) $msg_emerging = "have not been downloaded."; else @@ -489,15 +520,28 @@ if ($savemsg) { echo "<tr>\n"; if (!empty($emergingrules[$j])) { $file = $emergingrules[$j]; - echo "<td width='5%' class='listr' align=\"center\" valign=\"top\">"; + echo "<td width='5%' class='listr' align=\"center\">"; if(is_array($enabled_rulesets_array)) { - if(in_array($file, $enabled_rulesets_array)) + if(in_array($file, $enabled_rulesets_array) && !isset($cat_mods[$file])) $CHECKED = " checked=\"checked\""; else $CHECKED = ""; } else $CHECKED = ""; - echo " \n<input type='checkbox' name='toenable[]' value='$file' {$CHECKED} />\n"; + if (isset($cat_mods[$file])) { + if (in_array($file, $enabled_rulesets_array)) + echo "<input type='hidden' name='toenable[]' value='{$file}' />\n"; + if ($cat_mods[$file] == 'enabled') { + $CHECKED = "enabled"; + echo " \n<img src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-enabled by settings on SID Mgmt tab") . "\" />\n"; + } + else { + echo " \n<img style=\"opacity: 0.4; filter: alpha(opacity=40);\" src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-disabled by settings on SID Mgmt tab") . "\" />\n"; + } + } + else { + echo " \n<input type='checkbox' name='toenable[]' value='{$file}' {$CHECKED} />\n"; + } echo "</td>\n"; echo "<td class='listr' width='25%' >\n"; if (empty($CHECKED)) @@ -510,17 +554,30 @@ if ($savemsg) { if (!empty($snortrules[$j])) { $file = $snortrules[$j]; - echo "<td class='listr' width='5%' align=\"center\" valign=\"top\">"; + echo "<td class='listr' width='5%' align=\"center\">"; if(is_array($enabled_rulesets_array)) { if (!empty($disable_vrt_rules)) $CHECKED = $disable_vrt_rules; - elseif(in_array($file, $enabled_rulesets_array)) + elseif(in_array($file, $enabled_rulesets_array) && !isset($cat_mods[$file])) $CHECKED = " checked=\"checked\""; else $CHECKED = ""; } else $CHECKED = ""; - echo " \n<input type='checkbox' name='toenable[]' value='{$file}' {$CHECKED} />\n"; + if (isset($cat_mods[$file])) { + if (in_array($file, $enabled_rulesets_array)) + echo "<input type='hidden' name='toenable[]' value='{$file}' />\n"; + if ($cat_mods[$file] == 'enabled') { + $CHECKED = "enabled"; + echo " \n<img src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-enabled by settings on SID Mgmt tab") . "\" />\n"; + } + else { + echo " \n<img style=\"opacity: 0.4; filter: alpha(opacity=40);\" src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-disabled by settings on SID Mgmt tab") . "\" />\n"; + } + } + else { + echo " \n<input type='checkbox' name='toenable[]' value='{$file}' {$CHECKED} />\n"; + } echo "</td>\n"; echo "<td class='listr' width='25%' >\n"; if (empty($CHECKED) || $CHECKED == "disabled") @@ -530,22 +587,39 @@ if ($savemsg) { echo "</td>\n"; } else echo "<td class='listbggrey' width='30%' colspan='2'><br/></td>\n"; + if (!empty($snortsorules[$j])) { $file = $snortsorules[$j]; echo "<td class='listr' width='5%' align=\"center\" valign=\"top\">"; if(is_array($enabled_rulesets_array)) { if (!empty($disable_vrt_rules)) $CHECKED = $disable_vrt_rules; - elseif(in_array($file, $enabled_rulesets_array)) + elseif(in_array($file, $enabled_rulesets_array) && !isset($cat_mods[$file])) $CHECKED = " checked=\"checked\""; else $CHECKED = ""; } else $CHECKED = ""; - echo " \n<input type='checkbox' name='toenable[]' value='{$file}' {$CHECKED} />\n"; + if (isset($cat_mods[$file])) { + if (in_array($file, $enabled_rulesets_array)) + echo "<input type='hidden' name='toenable[]' value='{$file}' />\n"; + if ($cat_mods[$file] == 'enabled') { + $CHECKED = "enabled"; + echo " \n<img src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-enabled by settings on SID Mgmt tab") . "\" />\n"; + } + else { + echo " \n<img style=\"opacity: 0.4; filter: alpha(opacity=40);\" src=\"../themes/{$g['theme']}/images/icons/icon_advanced.gif\" width=\"11\" height=\"11\" border=\"0\" title=\"" . gettext("Auto-disabled by settings on SID Mgmt tab") . "\" />\n"; + } + } + else { + echo " \n<input type='checkbox' name='toenable[]' value='{$file}' {$CHECKED} />\n"; + } echo "</td>\n"; echo "<td class='listr' width='25%' >\n"; + if (empty($CHECKED) || $CHECKED == "disabled") echo $file; + else + echo "<a href='snort_rules.php?id={$id}&openruleset=" . urlencode($file) . "'>{$file}</a>\n"; echo "</td>\n"; } else echo "<td class='listbggrey' width='30%' colspan='2'><br/></td>\n"; diff --git a/config/snort/snort_sid_mgmt.php b/config/snort/snort_sid_mgmt.php new file mode 100644 index 00000000..5bc385c8 --- /dev/null +++ b/config/snort/snort_sid_mgmt.php @@ -0,0 +1,596 @@ +<?php +/* + * snort_sid_mgmt.php + * + * Portions of this code are based on original work done for the + * Snort package for pfSense from the following contributors: + * + * Copyright (C) 2005 Bill Marquette <bill.marquette@gmail.com>. + * Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>. + * Copyright (C) 2006 Scott Ullrich + * Copyright (C) 2009 Robert Zelaya Sr. Developer + * Copyright (C) 2012 Ermal Luci + * Copyright (C) 2014 Bill Meeks + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +require_once("guiconfig.inc"); +require_once("/usr/local/pkg/snort/snort.inc"); + +global $g, $config, $rebuild_rules; + +$snortdir = SNORTDIR; +$pconfig = array(); + +// Grab saved settings from configuration +if (!is_array($config['installedpackages']['snortglobal']['rule'])) + $config['installedpackages']['snortglobal']['rule'] = array(); +$a_nat = &$config['installedpackages']['snortglobal']['rule']; + +$pconfig['auto_manage_sids'] = $config['installedpackages']['snortglobal']['auto_manage_sids']; + +// Hard-code the path where SID Mods Lists are stored +// and disregard any user-supplied path element. +$sidmods_path = SID_MODS_PATH; + +// Set default to not show SID modification lists editor controls +$sidmodlist_edit_style = "display: none;"; + +if (!empty($_POST)) + $pconfig = $_POST; + +function snort_is_sidmodslist_active($sidlist) { + + /***************************************************** + * This function checks all the configured Snort * + * interfaces to see if the passed SID Mods List is * + * used by an interface. * + * * + * Returns: TRUE if List is in use * + * FALSE if List is not in use * + *****************************************************/ + + global $g, $config; + + if (!is_array($config['installedpackages']['snortglobal']['rule'])) + return FALSE; + + foreach ($config['installedpackages']['snortglobal']['rule'] as $rule) { + if ($rule['enable_sid_file'] == $sidlist) { + return TRUE; + } + if ($rule['disable_sid_file'] == $sidlist) { + return TRUE; + } + if ($rule['modify_sid_file'] == $sidlist) { + return TRUE; + } + } + return FALSE; +} + +if (isset($_POST['upload'])) { + if ($_FILES["sidmods_fileup"]["error"] == UPLOAD_ERR_OK) { + $tmp_name = $_FILES["sidmods_fileup"]["tmp_name"]; + $name = basename($_FILES["sidmods_fileup"]["name"]); + move_uploaded_file($tmp_name, "{$sidmods_path}{$name}"); + } + else + $input_errors[] = gettext("Failed to upload file {$_FILES["sidmods_fileup"]["name"]}"); +} + +if (isset($_POST['sidlist_delete']) && isset($_POST['sidlist_fname'])) { + if (!snort_is_sidmodslist_active(basename($_POST['sidlist_fname']))) + unlink_if_exists($sidmods_path . basename($_POST['sidlist_fname'])); + else + $input_errors[] = gettext("This SID Mods List is currently assigned to an interface and cannot be deleted."); +} + +if (isset($_POST['sidlist_edit']) && isset($_POST['sidlist_fname'])) { + $file = $sidmods_path . basename($_POST['sidlist_fname']); + $data = file_get_contents($file); + if ($data !== FALSE) { + $sidmodlist_data = htmlspecialchars($data); + $sidmodlist_edit_style = "display: table-row-group;"; + $sidmodlist_name = basename($_POST['sidlist_fname']); + unset($data); + } + else { + $input_errors[] = gettext("An error occurred reading the file."); + } +} + +if (isset($_POST['save']) && isset($_POST['sidlist_data'])) { + if (strlen(basename($_POST['sidlist_name'])) > 0) { + $file = $sidmods_path . basename($_POST['sidlist_name']); + $data = str_replace("\r\n", "\n", $_POST['sidlist_data']); + file_put_contents($file, $data); + unset($data); + } + else { + $input_errors[] = gettext("You must provide a valid filename for the SID Mods List."); + $sidmodlist_edit_style = "display: table-row-group;"; + } +} + +if (isset($_POST['save_auto_sid_conf'])) { + $config['installedpackages']['snortglobal']['auto_manage_sids'] = $pconfig['auto_manage_sids'] ? "on" : "off"; + + // Grab the SID Mods config for the interfaces from the form's controls array + foreach ($_POST['sid_state_order'] as $k => $v) { + $a_nat[$k]['sid_state_order'] = $v; + } + foreach ($_POST['enable_sid_file'] as $k => $v) { + if ($v == "None") { + unset($a_nat[$k]['enable_sid_file']); + continue; + } + $a_nat[$k]['enable_sid_file'] = $v; + } + foreach ($_POST['disable_sid_file'] as $k => $v) { + if ($v == "None") { + unset($a_nat[$k]['disable_sid_file']); + continue; + } + $a_nat[$k]['disable_sid_file'] = $v; + } + foreach ($_POST['modify_sid_file'] as $k => $v) { + if ($v == "None") { + unset($a_nat[$k]['modify_sid_file']); + continue; + } + $a_nat[$k]['modify_sid_file'] = $v; + } + + // Write the new configuration + write_config("Snort pkg: updated automatic SID management settings."); + + $intf_msg = ""; + + // If any interfaces were marked for restart, then do it + if (is_array($_POST['torestart'])) { + foreach ($_POST['torestart'] as $k) { + // Update the snort.conf file and + // rebuild rules for this interface. + $rebuild_rules = true; + conf_mount_rw(); + snort_generate_conf($a_nat[$k]); + conf_mount_ro(); + $rebuild_rules = false; + + // Signal Snort to "live reload" the rules + snort_reload_config($a_nat[$k]); + + $intf_msg .= convert_friendly_interface_to_friendly_descr($a_nat[$k]['interface']) . ", "; + } + $savemsg = gettext("Changes were applied to these interfaces: " . trim($intf_msg, ' ,') . " and Snort signaled to live-load the new rules."); + + // Sync to configured CARP slaves if any are enabled + snort_sync_on_changes(); + } +} + +if (isset($_POST['sidlist_dnload']) && isset($_POST['sidlist_fname'])) { + $file = $sidmods_path . basename($_POST['sidlist_fname']); + if (file_exists($file)) { + ob_start(); //important or other posts will fail + if (isset($_SERVER['HTTPS'])) { + header('Pragma: '); + header('Cache-Control: '); + } else { + header("Pragma: private"); + header("Cache-Control: private, must-revalidate"); + } + header("Content-Type: application/octet-stream"); + header("Content-length: " . filesize($file)); + header("Content-disposition: attachment; filename = " . basename($file)); + ob_end_clean(); //important or other post will fail + readfile($file); + } + else + $savemsg = gettext("Unable to locate the file specified!"); +} + +if (isset($_POST['sidlist_dnload_all_x'])) { + $save_date = exec('/bin/date "+%Y-%m-%d-%H-%M-%S"'); + $file_name = "snort_sid_conf_files_{$save_date}.tar.gz"; + exec("cd {$sidmods_path} && /usr/bin/tar -czf /tmp/{$file_name} *"); + + if (file_exists("/tmp/{$file_name}")) { + ob_start(); //important or other posts will fail + if (isset($_SERVER['HTTPS'])) { + header('Pragma: '); + header('Cache-Control: '); + } else { + header("Pragma: private"); + header("Cache-Control: private, must-revalidate"); + } + header("Content-Type: application/octet-stream"); + header("Content-length: " . filesize("/tmp/{$file_name}")); + header("Content-disposition: attachment; filename = {$file_name}"); + ob_end_clean(); //important or other post will fail + readfile("/tmp/{$file_name}"); + + // Clean up the temp file + @unlink("/tmp/{$file_name}"); + } + else + $savemsg = gettext("An error occurred while creating the gzip archive!"); +} + +// Get all files in the SID Mods Lists sub-directory as an array +// Leave this as the last thing before spewing the page HTML +// so we can pick up any changes made to files in code above. +$sidmodfiles = return_dir_as_array($sidmods_path); +$sidmodselections = array_merge(Array( "None" ), $sidmodfiles); + +$pgtitle = gettext("Snort: SID Management"); +include_once("head.inc"); + +?> + +<body link="#000000" vlink="#000000" alink="#000000"> + +<?php +include_once("fbegin.inc"); + +/* Display Alert message, under form tag or no refresh */ +if ($input_errors) + print_input_errors($input_errors); +?> + +<form action="snort_sid_mgmt.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> +<input type="hidden" name="MAX_FILE_SIZE" value="100000000" /> +<input type="hidden" name="sidlist_fname" id="sidlist_fname" value=""/> + +<?php +if ($savemsg) { + /* Display save message */ + print_info_box($savemsg); +} +?> + +<table width="100%" border="0" cellpadding="0" cellspacing="0"> + <tbody> + <tr><td> + <?php + $tab_array = array(); + $tab_array[0] = array(gettext("Snort Interfaces"), false, "/snort/snort_interfaces.php"); + $tab_array[1] = array(gettext("Global Settings"), false, "/snort/snort_interfaces_global.php"); + $tab_array[2] = array(gettext("Updates"), false, "/snort/snort_download_updates.php"); + $tab_array[3] = array(gettext("Alerts"), false, "/snort/snort_alerts.php"); + $tab_array[4] = array(gettext("Blocked"), false, "/snort/snort_blocked.php"); + $tab_array[5] = array(gettext("Pass Lists"), false, "/snort/snort_passlist.php"); + $tab_array[6] = array(gettext("Suppress"), false, "/snort/snort_interfaces_suppress.php"); + $tab_array[7] = array(gettext("IP Lists"), false, "/snort/snort_ip_list_mgmt.php"); + $tab_array[8] = array(gettext("SID Mgmt"), true, "/snort/snort_sid_mgmt.php"); + $tab_array[9] = array(gettext("Sync"), false, "/pkg_edit.php?xml=snort/snort_sync.xml"); + display_top_tabs($tab_array, true); + ?> + </td></tr> + <tr><td> + <div id="mainarea"> + <table id="maintable" class="tabcont" width="100%" border="0" cellpadding="6" cellspacing="0"> + <tbody> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("General Settings"); ?></td> + </tr> + <tr> + <td width="22%" valign="top" class="vncell"><?php echo gettext("Enable Automatic SID State Management"); ?></td> + <td width="78%" class="vtable"><input type="checkbox" id="auto_manage_sids" name="auto_manage_sids" value="on" + <?php if ($pconfig['auto_manage_sids'] == 'on') echo " checked"; ?> onclick="enable_sid_conf();" /> <?=gettext("Enable automatic management of rule state ") . + gettext("and content using configuration files. Default is ") . "<strong>" . gettext("Not Checked") . "</strong>";?>.<br/><br/> + <?=gettext("Snort will automatically enable/disable/modify text rules upon each update using criteria specified in configuration files. ") . + gettext("The supported configuration file format is the same as that used in the PulledPork and Oinkmaster enablesid.conf, disablesid.conf and ") . + gettext("modifysid.conf files. You can either upload existing files or create your own."); ?> + </td> + </tr> + </tbody> + <tbody id="sid_conf_rows"> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("SID Management Configuration Files"); ?></td> + </tr> + <tr> + <td colspan="2" class="vtable" align="center" > + <table width="100%" border="0" cellpadding="4" cellspacing="0"> + <tbody id="uploader" style="display: none;"> + <tr> + <td class="list"><br/><?php echo gettext("Click BROWSE to select a file to import, and then click UPLOAD. Click CLOSE to quit."); ?></td> + </tr> + <tr> + <td class="list"><input type="file" name="sidmods_fileup" id="sidmods_fileup" class="formfld file" size="50" /> + <input type="submit" name="upload" id="upload" value="<?=gettext("Upload");?>" + title="<?=gettext("Upload selected SID mods list to firewall");?>"/> <input type="button" + value="<?=gettext("Close");?>" onClick="document.getElementById('uploader').style.display='none';" /><br/></td> + <td class="list"></td> + </tr> + </tbody> + <tbody> + <tr> + <td> + <table id="maintable" width="100%" border="0" cellpadding="4" cellspacing="0"> + <colgroup> + <col style="width: 45%;"> + <col style="width: 25%;"> + <col style="width: 15%;"> + <col style="width: 15%;"> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?php echo gettext("SID Mods List File Name"); ?></th> + <th class="listhdrr"><?php echo gettext("Last Modified Time"); ?></th> + <th class="listhdrr"><?php echo gettext("File Size"); ?></th> + <th class="list" align="left"><img style="cursor:pointer;" name="sidlist_new" id="sidlist_new" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" + height="17" border="0" title="<?php echo gettext('Create a new SID Mods List');?>" + onClick="document.getElementById('sidlist_data').value=''; document.getElementById('sidlist_name').value=''; document.getElementById('sidlist_editor').style.display='table-row-group'; document.getElementById('sidlist_name').focus();" /> + <img style="cursor:pointer;" name="sidlist_import" id="sidlist_import" + onClick="document.getElementById('uploader').style.display='table-row-group';" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_import_alias.gif" width="17" + height="17" border="0" title="<?php echo gettext('Import/Upload a SID Mods List');?>"/> + <input type="image" name="sidlist_dnload_all" id="sidlist_dnload_all" + src="../tree/page-file_play.gif" width="16" height="16" border="0" + title="<?php echo gettext('Download all SID Mods List files in a single gzip archive');?>"/> + </th> + </tr> + </thead> + <tbody> + <?php foreach ($sidmodfiles as $file): ?> + <tr> + <td class="listr"><?php echo gettext($file); ?></td> + <td class="listr"><?=date('M-d Y g:i a', filemtime("{$sidmods_path}{$file}")); ?></td> + <td class="listr"><?=format_bytes(filesize("{$sidmods_path}{$file}")); ?> </td> + <td class="list"><input type="image" name="sidlist_edit[]" id="sidlist_edit[]" + onClick="document.getElementById('sidlist_fname').value='<?=$file;?>';" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" + height="17" border="0" title="<?php echo gettext('Edit this SID Mods List');?>"/> + <input type="image" name="sidlist_delete[]" id="sidlist_delete[]" + onClick="document.getElementById('sidlist_fname').value='<?=$file;?>'; + return confirm('<?=gettext("Are you sure you want to permanently delete this file? Click OK to continue or CANCEL to quit.");?>');" + src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" + height="17" border="0" title="<?php echo gettext('Delete this SID Mods List');?>"/> + <input type="image" name="sidlist_dnload[]" id="sidlist_dnload[]" + onClick="document.getElementById('sidlist_fname').value='<?=$file;?>';" + src="../tree/page-file_play.gif" width="16" height="16" border="0" + title="<?php echo gettext('Download this SID Mods List file');?>"/> + </td> + </tr> + <?php endforeach; ?> + </tbody> + <tbody id="sidlist_editor" style="<?=$sidmodlist_edit_style;?>"> + <tr> + <td colspan="4"> </td> + </tr> + <tr> + <td colspan="4"><strong><?=gettext("File Name: ");?></strong><input type="text" size="45" class="formfld file" id="sidlist_name" name="sidlist_name" value="<?=$sidmodlist_name;?>" /> + <input type="submit" id="save" name="save" value="<?=gettext(" Save ");?>" title="<?=gettext("Save changes and close editor");?>" /> + <input type="button" id="cancel" name="cancel" value="<?=gettext("Cancel");?>" onClick="document.getElementById('sidlist_editor').style.display='none';" + title="<?=gettext("Abandon changes and quit editor");?>" /></td> + </tr> + <tr> + <td colspan="4"> </td> + </tr> + <tr> + <td colspan="4"><textarea wrap="off" cols="80" rows="20" name="sidlist_data" id="sidlist_data" + style="width:95%; height:100%;"><?=$sidmodlist_data;?></textarea> + </td> + </tr> + </tbody> + <tbody> + <tr> + <td colspan="3" class="vexpl"><br/><span class="red"><strong><?php echo gettext("Note:"); ?></strong></span> + <br/><?php echo gettext("SID Mods Lists are stored as local files on the firewall and their contents are " . + "not saved as part of the firewall configuration file."); ?></td> + <td class="list"></td> + </tr> + <tr> + <td colspan="3" class="vexpl"><br/><strong><?php echo gettext("File List Controls:"); ?></strong><br/><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_plus.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the editor window to create a new SID Mods List. You must provide a valid filename before saving.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_import_alias.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the file upload control for uploading a new SID Mods List from your local machine.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_e.gif" width="17" height="17" border="0" /> + <?=gettext("Opens the SID Mods List in a text edit control for viewing or editing its contents.");?><br/> + <img src="../themes/<?= $g['theme']; ?>/images/icons/icon_x.gif" width="17" height="17" border="0" /> + <?=gettext("Deletes the SID Mods List from the file system after confirmation.");?><br/> + <img src="../tree/page-file_play.gif" width="16" height="16" border="0" /> + <?=gettext("Downloads the SID Mods List file to your local machine.");?><br/> + </td> + <td class="list"></td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + <tr> + <td colspan="2" valign="top" class="listtopic"><?php echo gettext("Interface SID Management File Assignments"); ?></td> + </tr> + <tr> + <td colspan="2" class="vtable" align="center" > + <table width="100%" border="0" cellpadding="2" cellspacing="0"> + <tbody> + <tr> + <td> + <table width="100%" border="0" cellpadding="0" cellspacing="0"> + <colgroup> + <col width="4%" align="center"> + <col width="20" align="center"> + <col width="16%" align="center"> + <col width="20%" align="center"> + <col width="20%" align="center"> + <col width="20%" align="center"> + </colgroup> + <thead> + <tr> + <th class="listhdrr"><?=gettext("Rebuild"); ?></th> + <th class="listhdrr"><?=gettext("Interface"); ?></th> + <th class="listhdrr"><?=gettext("SID State Order"); ?></th> + <th class="listhdrr"><?=gettext("Enable SID File"); ?></th> + <th class="listhdrr"><?=gettext("Disable SID File"); ?></th> + <th class="listhdrr"><?=gettext("Modify SID File"); ?></th> + </tr> + </thead> + <tbody> + <?php foreach ($a_nat as $k => $natent): ?> + <tr> + <td class="listr" align="center"> + <input type="checkbox" name="torestart[]" id="torestart[]" value="<?=$k;?>" title="<?=gettext("Apply new configuration and rebuild rules for this interface when saving");?>" /> + </td> + <td class="listbg"><?=convert_friendly_interface_to_friendly_descr($natent['interface']); ?></td> + <td class="listr" align="center"> + <select name="sid_state_order[<?=$k?>]" class="formselect" id="sid_state_order[<?=$k?>]"> + <?php + foreach (array("disable_enable" => "Disable, Enable", "enable_disable" => "Enable, Disable") as $key => $order) { + if ($key == $natent['sid_state_order']) + echo "<option value='{$key}' selected>"; + else + echo "<option value='{$key}'>"; + echo htmlspecialchars($order) . '</option>'; + } + ?> + </select> + </td> + <td class="listr" align="center"> + <select name="enable_sid_file[<?=$k?>]" class="formselect" id="enable_sid_file[<?=$k?>]"> + <?php + foreach ($sidmodselections as $choice) { + if ($choice == $natent['enable_sid_file']) + echo "<option value='{$choice}' selected>"; + else + echo "<option value='{$choice}'>"; + echo htmlspecialchars(gettext($choice)) . '</option>'; + } + ?> + </select> + </td> + <td class="listr" align="center"> + <select name="disable_sid_file[<?=$k?>]" class="formselect" id="disable_sid_file[<?=$k?>]"> + <?php + foreach ($sidmodselections as $choice) { + if ($choice == $natent['disable_sid_file']) + echo "<option value='{$choice}' selected>"; + else + echo "<option value='{$choice}'>"; + echo htmlspecialchars(gettext($choice)) . '</option>'; + } + ?> + </select> + </td> + <td class="listr" align="center"> + <select name="modify_sid_file[<?=$k?>]" class="formselect" id="modify_sid_file[<?=$k?>]"> + <?php + foreach ($sidmodselections as $choice) { + if ($choice == $natent['modify_sid_file']) + echo "<option value='{$choice}' selected>"; + else + echo "<option value='{$choice}'>"; + echo htmlspecialchars(gettext($choice)) . '</option>'; + } + ?> + </select> + </td> + </tr> + <?php endforeach; ?> + </tbody> + </table> + </td> + </tr> + <tr> + <td class="vexpl"> + </td> + </tr> + <tr> + <td> + <table width="100%" cellpadding="2" cellspacing="2" border="0"> + <tbody> + <tr> + <td colspan="2" class="vexpl" style="text-align: bottom;"><strong><span class="red"><?=gettext("Notes:");?></span></strong></td> + </tr> + <tr> + <td class="vexpl" style="vertical-align: top;"><?=gettext("1.");?></td> + <td class="vexpl"><?=gettext("Check the box beside an interface to immediately apply new auto-SID management ") . + gettext("changes and signal Snort to live-load the new rules for the interface when clicking SAVE; ") . + gettext("otherwise only the new file assignments will be saved.");?> + </td> + </tr> + <tr> + <td class="vexpl" style="vertical-align: top;"><?=gettext("2.");?></td> + <td class="vexpl"><?=gettext("SID State Order controls the order in which enable and disable state modifications are performed. ") . + gettext("An example would be to disable an entire category and later enable only a rule or two from it. In this case you would ") . + gettext("choose 'disable,enable' for the State Order. Note that the last action performed takes priority.");?> + </td> + </tr> + <tr> + <td class="vexpl" style="vertical-align: top;"><?=gettext("3.");?></td> + <td class="vexpl"><?=gettext("The Enable SID File, Disable SID File and Modify SID File controls specify which rule modification ") . + gettext("files are run automatically for the interface. Setting a file control to 'None' disables that modification. ") . + gettext("Setting all file controls for an interface to 'None' disables automatic SID state management for the interface.");?> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + <tbody> + <tr> + <td colspan="2" class="vexpl" align="center"><input type="submit" id="save_auto_sid_conf" name="save_auto_sid_conf" class="formbtn" value="<?=gettext("Save");?>" title="<?=gettext("Save SID Management configuration");?>" /> + <?=gettext("Remember to save changes before exiting this page"); ?> + </td> + </tr> + </tbody> + </table> + </div> + </td></tr> + </tbody> +</table> +</form> + + +<?php include("fend.inc"); ?> +<script type="text/javascript"> + +function enable_sid_conf() { + var endis = !document.iform.auto_manage_sids.checked; + if (endis) { + document.getElementById("sid_conf_rows").style.display = "none"; + } + else { + document.getElementById("sid_conf_rows").style.display = ""; + } +} + +enable_sid_conf(); + +</script> +</body> +</html> |