import os.path
import logging
import argparse
-import shlex
import time
import hashlib
import fnmatch
rule as rule_mod,
sources,
util,
+ matchers as matchers_mod
)
from suricata.update.version import version
INDEX_EXPIRATION_TIME = 60 * 60 * 24 * 14
-class AllRuleMatcher(object):
- """Matcher object to match all rules. """
-
- def match(self, rule):
- return True
-
- @classmethod
- def parse(cls, buf):
- if buf.strip() == "*":
- 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."""
-
- def __init__(self, generatorId=None, signatureId=None):
- self.signatureIds = []
- if generatorId and signatureId:
- self.signatureIds.append((generatorId, signatureId))
-
- def match(self, rule):
- for (generatorId, signatureId) in self.signatureIds:
- if generatorId == rule.gid and signatureId == rule.sid:
- return True
- return False
-
- @classmethod
- def parse(cls, buf):
- matcher = cls()
-
- for entry in buf.split(","):
- entry = entry.strip()
-
- parts = entry.split(":", 1)
- if not parts:
- return None
- if len(parts) == 1:
- try:
- signatureId = int(parts[0])
- matcher.signatureIds.append((1, signatureId))
- except:
- return None
- else:
- try:
- generatorId = int(parts[0])
- signatureId = int(parts[1])
- matcher.signatureIds.append((generatorId, signatureId))
- except:
- return None
-
- return matcher
-
-class FilenameMatcher(object):
- """Matcher object to match a rule by its filename. This is similar to
- a group but has no specifier prefix.
- """
-
- def __init__(self, pattern):
- self.pattern = pattern
-
- def match(self, rule):
- if hasattr(rule, "group") and rule.group is not None:
- return fnmatch.fnmatch(rule.group, self.pattern)
- return False
-
- @classmethod
- def parse(cls, buf):
- if buf.startswith("filename:"):
- try:
- group = buf.split(":", 1)[1]
- return cls(group.strip())
- except:
- pass
- return None
-
-class GroupMatcher(object):
- """Matcher object to match an idstools rule object by its group (ie:
- filename).
-
- The group is just the basename of the rule file with or without
- extension.
-
- Examples:
- - emerging-shellcode
- - emerging-trojan.rules
-
- """
-
- def __init__(self, pattern):
- self.pattern = pattern
-
- def match(self, rule):
- if hasattr(rule, "group") and rule.group is not None:
- if fnmatch.fnmatch(os.path.basename(rule.group), self.pattern):
- return True
- # Try matching against the rule group without the file
- # extension.
- if fnmatch.fnmatch(
- os.path.splitext(
- os.path.basename(rule.group))[0], self.pattern):
- return True
- return False
-
- @classmethod
- def parse(cls, buf):
- if buf.startswith("group:"):
- try:
- logger.debug("Parsing group matcher: %s" % (buf))
- group = buf.split(":", 1)[1]
- return cls(group.strip())
- except:
- pass
- if buf.endswith(".rules"):
- return cls(buf.strip())
- return None
-
-class ReRuleMatcher(object):
- """Matcher object to match an idstools rule object by regular
- expression."""
-
- def __init__(self, pattern):
- self.pattern = pattern
-
- def match(self, rule):
- if self.pattern.search(rule.raw):
- return True
- return False
-
- @classmethod
- def parse(cls, buf):
- if buf.startswith("re:"):
- try:
- logger.debug("Parsing regex matcher: %s" % (buf))
- patternstr = buf.split(":", 1)[1].strip()
- pattern = re.compile(patternstr, re.I)
- return cls(pattern)
- except:
- pass
- return None
-
-class ModifyRuleFilter(object):
- """Filter to modify an idstools rule object.
-
- Important note: This filter does not modify the rule inplace, but
- instead returns a new rule object with the modification.
- """
-
- def __init__(self, matcher, pattern, repl):
- self.matcher = matcher
- self.pattern = pattern
- self.repl = repl
-
- def match(self, rule):
- return self.matcher.match(rule)
-
- def run(self, rule):
- modified_rule = self.pattern.sub(self.repl, rule.format())
- parsed = rule_mod.parse(modified_rule, rule.group)
- if parsed is None:
- logger.error("Modification of rule %s results in invalid rule: %s",
- rule.idstr, modified_rule)
- return rule
- return parsed
-
- @classmethod
- def parse(cls, buf):
- tokens = shlex.split(buf)
- if len(tokens) == 3:
- matchstring, a, b = tokens
- elif len(tokens) > 3 and tokens[0] == "modifysid":
- matchstring, a, b = tokens[1], tokens[2], tokens[4]
- else:
- raise Exception("Bad number of arguments.")
- matcher = parse_rule_match(matchstring)
- if not matcher:
- raise Exception("Bad match string: %s" % (matchstring))
- pattern = re.compile(a)
-
- # Convert Oinkmaster backticks to Python.
- b = re.sub("\$\{(\d+)\}", "\\\\\\1", b)
-
- return cls(matcher, pattern, b)
-
-class DropRuleFilter(object):
- """ Filter to modify an idstools rule object to a drop rule. """
-
- def __init__(self, matcher):
- self.matcher = matcher
-
- def match(self, rule):
- if rule["noalert"]:
- return False
- return self.matcher.match(rule)
-
- def run(self, rule):
- drop_rule = rule_mod.parse(re.sub("^\w+", "drop", rule.raw))
- drop_rule.enabled = rule.enabled
- return drop_rule
-
class Fetch:
def __init__(self):
files[basename] = open(filename, "rb").read()
return files
-def parse_rule_match(match):
- matcher = AllRuleMatcher.parse(match)
- if matcher:
- return matcher
-
- matcher = IdRuleMatcher.parse(match)
- if matcher:
- return matcher
-
- matcher = ReRuleMatcher.parse(match)
- if matcher:
- return matcher
-
- matcher = FilenameMatcher.parse(match)
- if matcher:
- return matcher
-
- matcher = GroupMatcher.parse(match)
- if matcher:
- return matcher
-
- return None
-
def load_filters(filename):
filters = []
line = line.rsplit(" #")[0]
line = re.sub(r'\\\$', '$', line) # needed to escape $ in pp
- rule_filter = ModifyRuleFilter.parse(line)
+ rule_filter = matchers_mod.ModifyRuleFilter.parse(line)
if rule_filter:
filters.append(rule_filter)
else:
filters = []
for matcher in matchers:
- filters.append(DropRuleFilter(matcher))
+ filters.append(matchers_mod.DropRuleFilter(matcher))
return filters
if not line or line.startswith("#"):
continue
line = line.rsplit(" #")[0]
- matcher = parse_rule_match(line)
+ matcher = matchers_mod.parse_rule_match(line)
if not matcher:
logger.warn("Failed to parse: \"%s\"" % (line))
else:
proto = m.group(1)
if not suriconf.is_true(key, ["detection-only"]):
logger.info("Disabling rules for protocol %s", proto)
- disable_matchers.append(ProtoRuleMatcher(proto))
+ disable_matchers.append(matchers_mod.ProtoRuleMatcher(proto))
elif proto == "smb" and suriconf.build_info:
# Special case for SMB rules. For versions less
# than 5, disable smb rules if Rust is not
if suriconf.build_info["version"].major < 5:
if not "RUST" in suriconf.build_info["features"]:
logger.info("Disabling rules for protocol {}".format(proto))
- disable_matchers.append(ProtoRuleMatcher(proto))
+ disable_matchers.append(matchers_mod.ProtoRuleMatcher(proto))
# Check that the cache directory exists and is writable.
if not os.path.exists(config.get_cache_dir()):
--- /dev/null
+# Copyright (C) 2017 Open Information Security Foundation
+#
+# You can copy, redistribute or modify this Program under the terms of
+# the GNU General Public License version 2 as published by the Free
+# Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# version 2 along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# This module contains functions for matching rules for disabling,
+# enabling, converting to drop or modification.
+
+import re
+import os.path
+import logging
+import shlex
+import fnmatch
+import suricata.update.rule
+
+
+logger = logging.getLogger()
+
+
+class AllRuleMatcher(object):
+ """Matcher object to match all rules. """
+
+ def match(self, rule):
+ return True
+
+ @classmethod
+ def parse(cls, buf):
+ if buf.strip() == "*":
+ 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."""
+
+ def __init__(self, generatorId=None, signatureId=None):
+ self.signatureIds = []
+ if generatorId and signatureId:
+ self.signatureIds.append((generatorId, signatureId))
+
+ def match(self, rule):
+ for (generatorId, signatureId) in self.signatureIds:
+ if generatorId == rule.gid and signatureId == rule.sid:
+ return True
+ return False
+
+ @classmethod
+ def parse(cls, buf):
+ matcher = cls()
+
+ for entry in buf.split(","):
+ entry = entry.strip()
+
+ parts = entry.split(":", 1)
+ if not parts:
+ return None
+ if len(parts) == 1:
+ try:
+ signatureId = int(parts[0])
+ matcher.signatureIds.append((1, signatureId))
+ except:
+ return None
+ else:
+ try:
+ generatorId = int(parts[0])
+ signatureId = int(parts[1])
+ matcher.signatureIds.append((generatorId, signatureId))
+ except:
+ return None
+
+ return matcher
+
+
+class FilenameMatcher(object):
+ """Matcher object to match a rule by its filename. This is similar to
+ a group but has no specifier prefix.
+ """
+
+ def __init__(self, pattern):
+ self.pattern = pattern
+
+ def match(self, rule):
+ if hasattr(rule, "group") and rule.group is not None:
+ return fnmatch.fnmatch(rule.group, self.pattern)
+ return False
+
+ @classmethod
+ def parse(cls, buf):
+ if buf.startswith("filename:"):
+ try:
+ group = buf.split(":", 1)[1]
+ return cls(group.strip())
+ except:
+ pass
+ return None
+
+
+class GroupMatcher(object):
+ """Matcher object to match an idstools rule object by its group (ie:
+ filename).
+
+ The group is just the basename of the rule file with or without
+ extension.
+
+ Examples:
+ - emerging-shellcode
+ - emerging-trojan.rules
+
+ """
+
+ def __init__(self, pattern):
+ self.pattern = pattern
+
+ def match(self, rule):
+ if hasattr(rule, "group") and rule.group is not None:
+ if fnmatch.fnmatch(os.path.basename(rule.group), self.pattern):
+ return True
+ # Try matching against the rule group without the file
+ # extension.
+ if fnmatch.fnmatch(
+ os.path.splitext(
+ os.path.basename(rule.group))[0], self.pattern):
+ return True
+ return False
+
+ @classmethod
+ def parse(cls, buf):
+ if buf.startswith("group:"):
+ try:
+ logger.debug("Parsing group matcher: %s" % (buf))
+ group = buf.split(":", 1)[1]
+ return cls(group.strip())
+ except:
+ pass
+ if buf.endswith(".rules"):
+ return cls(buf.strip())
+ return None
+
+
+class ReRuleMatcher(object):
+ """Matcher object to match an idstools rule object by regular
+ expression."""
+
+ def __init__(self, pattern):
+ self.pattern = pattern
+
+ def match(self, rule):
+ if self.pattern.search(rule.raw):
+ return True
+ return False
+
+ @classmethod
+ def parse(cls, buf):
+ if buf.startswith("re:"):
+ try:
+ logger.debug("Parsing regex matcher: %s" % (buf))
+ patternstr = buf.split(":", 1)[1].strip()
+ pattern = re.compile(patternstr, re.I)
+ return cls(pattern)
+ except:
+ pass
+ return None
+
+
+class ModifyRuleFilter(object):
+ """Filter to modify an idstools rule object.
+
+ Important note: This filter does not modify the rule inplace, but
+ instead returns a new rule object with the modification.
+ """
+
+ def __init__(self, matcher, pattern, repl):
+ self.matcher = matcher
+ self.pattern = pattern
+ self.repl = repl
+
+ def match(self, rule):
+ return self.matcher.match(rule)
+
+ def run(self, rule):
+ modified_rule = self.pattern.sub(self.repl, rule.format())
+ parsed = suricata.update.rule.parse(modified_rule, rule.group)
+ if parsed is None:
+ logger.error("Modification of rule %s results in invalid rule: %s",
+ rule.idstr, modified_rule)
+ return rule
+ return parsed
+
+ @classmethod
+ def parse(cls, buf):
+ tokens = shlex.split(buf)
+ if len(tokens) == 3:
+ matchstring, a, b = tokens
+ elif len(tokens) > 3 and tokens[0] == "modifysid":
+ matchstring, a, b = tokens[1], tokens[2], tokens[4]
+ else:
+ raise Exception("Bad number of arguments.")
+ matcher = parse_rule_match(matchstring)
+ if not matcher:
+ raise Exception("Bad match string: %s" % (matchstring))
+ pattern = re.compile(a)
+
+ # Convert Oinkmaster backticks to Python.
+ b = re.sub("\$\{(\d+)\}", "\\\\\\1", b)
+
+ return cls(matcher, pattern, b)
+
+
+class DropRuleFilter(object):
+ """ Filter to modify an idstools rule object to a drop rule. """
+
+ def __init__(self, matcher):
+ self.matcher = matcher
+
+ def match(self, rule):
+ if rule["noalert"]:
+ return False
+ return self.matcher.match(rule)
+
+ def run(self, rule):
+ drop_rule = suricata.update.rule.parse(re.sub(
+ "^\w+", "drop", rule.raw))
+ drop_rule.enabled = rule.enabled
+ return drop_rule
+
+
+def parse_rule_match(match):
+ matcher = AllRuleMatcher.parse(match)
+ if matcher:
+ return matcher
+
+ matcher = IdRuleMatcher.parse(match)
+ if matcher:
+ return matcher
+
+ matcher = ReRuleMatcher.parse(match)
+ if matcher:
+ return matcher
+
+ matcher = FilenameMatcher.parse(match)
+ if matcher:
+ return matcher
+
+ matcher = GroupMatcher.parse(match)
+ if matcher:
+ return matcher
+
+ return None
import suricata.update.rule
from suricata.update import main
import suricata.update.extract
+from suricata.update import matchers as matchers_mod
class TestRulecat(unittest.TestCase):
def test_id_match(self):
rule0 = suricata.update.rule.parse(self.rule_string)
line = '2020757 "\|0d 0a\|" "|ff ff|"'
- rule_filter = main.ModifyRuleFilter.parse(line)
+ rule_filter = matchers_mod.ModifyRuleFilter.parse(line)
self.assertTrue(rule_filter != None)
self.assertTrue(rule_filter.match(rule0))
rule1 = rule_filter.run(rule0)
def test_re_match(self):
rule0 = suricata.update.rule.parse(self.rule_string)
line = 're:classtype:trojan-activity "\|0d 0a\|" "|ff ff|"'
- rule_filter = main.ModifyRuleFilter.parse(line)
+ rule_filter = matchers_mod.ModifyRuleFilter.parse(line)
self.assertTrue(rule_filter != None)
self.assertTrue(rule_filter.match(rule0))
rule1 = rule_filter.run(rule0)
def test_re_backref_one(self):
rule0 = suricata.update.rule.parse(self.rule_string)
line = 're:classtype:trojan-activity "(alert)(.*)" "drop\\2"'
- rule_filter = main.ModifyRuleFilter.parse(line)
+ rule_filter = matchers_mod.ModifyRuleFilter.parse(line)
self.assertTrue(rule_filter != None)
self.assertTrue(rule_filter.match(rule0))
rule1 = rule_filter.run(rule0)
def test_re_backref_two(self):
rule0 = suricata.update.rule.parse(self.rule_string)
line = 're:classtype:trojan-activity "(alert)(.*)(from_server)(.*)" "drop\\2to_client\\4"'
- rule_filter = main.ModifyRuleFilter.parse(line)
+ rule_filter = matchers_mod.ModifyRuleFilter.parse(line)
self.assertTrue(rule_filter != None)
self.assertTrue(rule_filter.match(rule0))
rule1 = rule_filter.run(rule0)
rule_in = suricata.update.rule.parse(self.rule_string)
self.assertIsNotNone(rule_in)
- f = main.ModifyRuleFilter.parse(
+ f = matchers_mod.ModifyRuleFilter.parse(
'group:emerging-trojan.rules "^alert" "drop"')
self.assertIsNotNone(f)
self.assertTrue(rule_out.format().startswith("drop"))
def test_oinkmaster_backticks(self):
- f = main.ModifyRuleFilter.parse(
+ f = matchers_mod.ModifyRuleFilter.parse(
'* "^drop(.*)noalert(.*)" "alert${1}noalert${2}"')
rule_in ="""drop http $EXTERNAL_NET any -> $HOME_NET any (msg:"ET MALWARE Windows executable sent when remote host claims to send an image 2"; flow: established,to_client; content:"|0d 0a|Content-Type|3a| image/jpeg|0d 0a 0d 0a|MZ"; fast_pattern:12,20; noalert; classtype:trojan-activity; sid:2020757; rev:2;)"""
rule_out = f.run(suricata.update.rule.parse(rule_in))
self.assertEqual("""alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"ET MALWARE Windows executable sent when remote host claims to send an image 2"; flow: established,to_client; content:"|0d 0a|Content-Type|3a| image/jpeg|0d 0a 0d 0a|MZ"; fast_pattern:12,20; noalert; classtype:trojan-activity; sid:2020757; rev:2;)""", rule_out.format())
def test_oinkmaster_backticks_not_noalert(self):
- f = main.ModifyRuleFilter.parse(
+ f = matchers_mod.ModifyRuleFilter.parse(
'modifysid * "^drop(.*)noalert(.*)" | "alert${1}noalert${2}"')
rule_in ="""drop http $EXTERNAL_NET any -> $HOME_NET any (msg:"ET MALWARE Windows executable sent when remote host claims to send an image 2"; flow: established,to_client; content:"|0d 0a|Content-Type|3a| image/jpeg|0d 0a 0d 0a|MZ"; fast_pattern:12,20; classtype:trojan-activity; sid:2020757; rev:2;)"""
rule_out = f.run(suricata.update.rule.parse(rule_in))
def test_oinkmaster_modify_group_name(self):
"""Test an Oinkmaster style modification line using a group name."""
- f = main.ModifyRuleFilter.parse(
+ f = matchers_mod.ModifyRuleFilter.parse(
'modifysid botcc.rules "^alert" | "drop"')
rule_in ="""alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"ET MALWARE Windows executable sent when remote host claims to send an image 2"; flow: established,to_client; content:"|0d 0a|Content-Type|3a| image/jpeg|0d 0a 0d 0a|MZ"; fast_pattern:12,20; classtype:trojan-activity; sid:2020757; rev:2;)"""
rule = suricata.update.rule.parse(rule_in, "rules/botcc.rules")
def test_enabled_rule(self):
rule0 = suricata.update.rule.parse(self.rule_string, "rules/malware.rules")
- id_matcher = main.IdRuleMatcher.parse("2020757")
+ id_matcher = matchers_mod.IdRuleMatcher.parse("2020757")
self.assertTrue(id_matcher.match(rule0))
- drop_filter = main.DropRuleFilter(id_matcher)
+ drop_filter = matchers_mod.DropRuleFilter(id_matcher)
rule1 = drop_filter.run(rule0)
self.assertEqual("drop", rule1.action)
self.assertTrue(rule1.enabled)
def test_disabled_rule(self):
rule0 = suricata.update.rule.parse(
"# " + self.rule_string, "rules/malware.rules")
- id_matcher = main.IdRuleMatcher.parse("2020757")
+ id_matcher = matchers_mod.IdRuleMatcher.parse("2020757")
self.assertTrue(id_matcher.match(rule0))
- drop_filter = main.DropRuleFilter(id_matcher)
+ drop_filter = matchers_mod.DropRuleFilter(id_matcher)
rule1 = drop_filter.run(rule0)
self.assertEqual("drop", rule1.action)
self.assertFalse(rule1.enabled)
rule_with_noalert = """alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"ET TROJAN [CrowdStrike] ANCHOR PANDA Torn RAT Beacon Message Header Local"; flow:established, to_server; dsize:16; content:"|00 00 00 11 c8 00 00 00 00 00 00 00 00 00 00 00|"; depth:16; flowbits:set,ET.Torn.toread_header; flowbits: noalert; reference:url,blog.crowdstrike.com/whois-anchor-panda/index.html; classtype:trojan-activity; sid:2016659; rev:2; metadata:created_at 2013_03_22, updated_at 2013_03_22;)"""
rule = suricata.update.rule.parse(rule_without_noalert)
- matcher = main.IdRuleMatcher.parse("2016659")
- rule_filter = main.DropRuleFilter(matcher)
+ matcher = matchers_mod.IdRuleMatcher.parse("2016659")
+ rule_filter = matchers_mod.DropRuleFilter(matcher)
self.assertTrue(rule_filter.match(rule))
rule = suricata.update.rule.parse(rule_with_noalert)
- matcher = main.IdRuleMatcher.parse("2016659")
- rule_filter = main.DropRuleFilter(matcher)
+ matcher = matchers_mod.IdRuleMatcher.parse("2016659")
+ rule_filter = matchers_mod.DropRuleFilter(matcher)
self.assertFalse(rule_filter.match(rule))
import suricata.update.rule
from suricata.update import main
import suricata.update.extract
+from suricata.update import matchers as matchers_mod
class GroupMatcherTestCase(unittest.TestCase):
def test_match(self):
rule = suricata.update.rule.parse(self.rule_string, "rules/malware.rules")
- matcher = main.parse_rule_match("group: malware.rules")
+ matcher = matchers_mod.parse_rule_match("group: malware.rules")
self.assertEqual(
- matcher.__class__, suricata.update.main.GroupMatcher)
+ matcher.__class__, matchers_mod.GroupMatcher)
self.assertTrue(matcher.match(rule))
# Test match of just the group basename.
- matcher = main.parse_rule_match("group: malware")
+ matcher = matchers_mod.parse_rule_match("group: malware")
self.assertEqual(
- matcher.__class__, suricata.update.main.GroupMatcher)
+ matcher.__class__, matchers_mod.GroupMatcher)
self.assertTrue(matcher.match(rule))
class FilenameMatcherTestCase(unittest.TestCase):
def test_match(self):
rule = suricata.update.rule.parse(self.rule_string, "rules/trojan.rules")
- matcher = main.parse_rule_match("filename: */trojan.rules")
+ matcher = matchers_mod.parse_rule_match("filename: */trojan.rules")
self.assertEqual(
- matcher.__class__, suricata.update.main.FilenameMatcher)
+ matcher.__class__, matchers_mod.FilenameMatcher)
self.assertTrue(matcher.match(rule))
class LoadMatchersTestCase(unittest.TestCase):
1:100 # Trailing comment.
"""))
self.assertEqual(
- matchers[0].__class__, suricata.update.main.FilenameMatcher)
+ matchers[0].__class__, matchers_mod.FilenameMatcher)
self.assertEqual(
- matchers[1].__class__, suricata.update.main.ReRuleMatcher)
+ matchers[1].__class__, matchers_mod.ReRuleMatcher)
self.assertEqual(
- matchers[2].__class__, suricata.update.main.IdRuleMatcher)
+ matchers[2].__class__, matchers_mod.IdRuleMatcher)
class IdRuleMatcherTestCase(unittest.TestCase):
def test_parse_single_sid(self):
- matcher = main.IdRuleMatcher.parse("123")
+ matcher = matchers_mod.IdRuleMatcher.parse("123")
self.assertIsNotNone(matcher)
self.assertEqual(1, len(matcher.signatureIds))
def test_parse_single_gidsid(self):
- matcher = main.IdRuleMatcher.parse("1:123")
+ matcher = matchers_mod.IdRuleMatcher.parse("1:123")
self.assertIsNotNone(matcher)
self.assertEqual(1, len(matcher.signatureIds))
def test_parse_multi_sid(self):
- matcher = main.IdRuleMatcher.parse("1,2,3")
+ matcher = matchers_mod.IdRuleMatcher.parse("1,2,3")
self.assertIsNotNone(matcher)
self.assertEqual(3, len(matcher.signatureIds))
def test_parse_multi_gidsid(self):
- matcher = main.IdRuleMatcher.parse("1:1000,2:2000, 3:3000, 4:4000")
+ matcher = matchers_mod.IdRuleMatcher.parse("1:1000,2:2000, 3:3000, 4:4000")
self.assertIsNotNone(matcher)
self.assertEqual(4, len(matcher.signatureIds))
def test_parse_multi_mixed(self):
- matcher = main.IdRuleMatcher.parse("1:1000, 2000, 3:3000, 4000")
+ matcher = matchers_mod.IdRuleMatcher.parse("1:1000, 2000, 3:3000, 4000")
self.assertIsNotNone(matcher)
self.assertEqual(4, len(matcher.signatureIds))
def test_parse_invalid(self):
- matcher = main.IdRuleMatcher.parse("a")
+ matcher = matchers_mod.IdRuleMatcher.parse("a")
self.assertIsNone(matcher)
- matcher = main.IdRuleMatcher.parse("1, a")
+ matcher = matchers_mod.IdRuleMatcher.parse("1, a")
self.assertIsNone(matcher)
- matcher = main.IdRuleMatcher.parse("1a")
+ matcher = matchers_mod.IdRuleMatcher.parse("1a")
self.assertIsNone(matcher)
- matcher = main.IdRuleMatcher.parse("1:a")
+ matcher = matchers_mod.IdRuleMatcher.parse("1:a")
self.assertIsNone(matcher)