From: Jason Ish Date: Thu, 30 Nov 2017 23:07:20 +0000 (-0600) Subject: disable rules with proto's not enabled in suricata config X-Git-Tag: 1.0.0a1~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=050b46c56e2a005d64a21f512e7b4b044da6e394;p=thirdparty%2Fsuricata-update.git disable rules with proto's not enabled in suricata config --- diff --git a/suricata/update/engine.py b/suricata/update/engine.py index 16a6b6f..c890f9e 100644 --- a/suricata/update/engine.py +++ b/suricata/update/engine.py @@ -25,6 +25,7 @@ import os.path import subprocess import re import logging +import yaml from collections import namedtuple logger = logging.getLogger() @@ -32,6 +33,51 @@ logger = logging.getLogger() SuricataVersion = namedtuple( "SuricataVersion", ["major", "minor", "patch", "full", "short", "raw"]) +class Configuration: + """An abstraction over the Suricata configuration file.""" + + def __init__(self, conf): + self.conf = conf + + def keys(self): + return self.conf.keys() + + def is_true(self, key, truthy=[]): + if not key in self.conf: + logger.warning( + "Suricata configuration key does not exist: %s" % (key)) + return False + if key in self.conf: + val = self.conf[key] + if val.lower() in ["1", "yes", "true"] + truthy: + return True + return False + + @classmethod + def load(cls, config_filename, suricata_path=None): + env = { + "SC_LOG_FORMAT": "%t - <%d> -- ", + "SC_LOG_LEVEL": "Error", + "ASAN_OPTIONS": "detect_leaks=0", + } + if not suricata_path: + suricata_path = get_path() + if not suricata_path: + raise Exception("Suricata program could not be found.") + if not os.path.exists(suricata_path): + raise Exception("Suricata program %s does not exist.", suricata_path) + configuration_dump = subprocess.check_output( + [suricata_path, "-c", config_filename, "--dump-config"], + env=env) + conf = {} + for line in configuration_dump.splitlines(): + try: + key, val = line.split(" = ") + conf[key] = val + except: + logger.warning("Failed to parse: %s", line) + return cls(conf) + def get_path(program="suricata"): """Find Suricata in the shell path.""" for path in os.environ["PATH"].split(os.pathsep): diff --git a/suricata/update/main.py b/suricata/update/main.py index 2918aba..39dea7f 100644 --- a/suricata/update/main.py +++ b/suricata/update/main.py @@ -94,6 +94,15 @@ class AllRuleMatcher(object): return cls() return None +class ProtoRuleMatcher: + """A rule matcher that matches on the protocol of a rule.""" + + def __init__(self, proto): + self.proto = proto + + def match(self, rule): + return rule.proto == self.proto + class IdRuleMatcher(object): """Matcher object to match an idstools rule object by its signature ID.""" @@ -1283,6 +1292,19 @@ def _main(): logger.info("Loading %s.", drop_conf_filename) drop_filters += load_drop_filters(drop_conf_filename) + if os.path.exists("/etc/suricata/suricata.yaml") and \ + suricata_path and os.path.exists(suricata_path): + logger.info("Loading /etc/suricata/suricata.yaml") + suriconf = suricata.update.engine.Configuration.load( + "/etc/suricata/suricata.yaml", suricata_path=suricata_path) + for key in suriconf.keys(): + if key.startswith("app-layer.protocols") and \ + key.endswith(".enabled"): + if not suriconf.is_true(key, ["detection-only"]): + proto = key.split(".")[2] + logger.info("Disabling rules with proto %s", proto) + disable_matchers.append(ProtoRuleMatcher(proto)) + # Check that the cache directory exists and is writable. if not os.path.exists(config.get_cache_dir()): try: diff --git a/suricata/update/rule.py b/suricata/update/rule.py index 3487443..72990b7 100644 --- a/suricata/update/rule.py +++ b/suricata/update/rule.py @@ -47,7 +47,7 @@ rule_pattern = re.compile( r"(?P" r"(?P
" r"(?P%s)\s*" # Action - r"[^\s]*\s*" # Protocol + r"(?P[^\s]*)\s*" # Protocol r"[^\s]*\s*" # Source address(es) r"[^\s]*\s*" # Source port r"(?P[-><]+)\s*" # Direction @@ -87,6 +87,7 @@ class Rule(dict): disabled (commented) - **action**: The action of the rule (alert, pass, etc) as a string + - **proto**: The protocol of the rule. - **direction**: The direction string of the rule. - **gid**: The gid of the rule as an integer - **sid**: The sid of the rule as an integer @@ -109,6 +110,7 @@ class Rule(dict): dict.__init__(self) self["enabled"] = enabled self["action"] = action + self["proto"] = None self["direction"] = None self["group"] = group self["gid"] = 1 @@ -229,8 +231,9 @@ def parse(buf, group=None): action=m.group("action"), group=group) - rule["direction"] = m.groupdict().get("direction", None) rule["header"] = m.groupdict().get("header", None) + rule["proto"] = m.groupdict().get("proto", None) + rule["direction"] = m.groupdict().get("direction", None) options = m.group("options")