"""Matcher object to match an idstools rule object by its signature
ID."""
- def __init__(self, generatorId, signatureId):
- self.generatorId = generatorId
- self.signatureId = signatureId
+ def __init__(self, generatorId=None, signatureId=None):
+ self.signatureIds = []
+ if generatorId and signatureId:
+ self.signatureIds.append((generatorId, signatureId))
def match(self, rule):
- return self.generatorId == rule.gid and self.signatureId == rule.sid
+ for (generatorId, signatureId) in self.signatureIds:
+ if generatorId == rule.gid and signatureId == rule.sid:
+ return True
+ return False
@classmethod
def parse(cls, buf):
- logger.debug("Parsing ID matcher: %s" % (buf))
- try:
- signatureId = int(buf)
- return cls(1, signatureId)
- except:
- pass
- try:
- generatorString, signatureString = buf.split(":")
- generatorId = int(generatorString)
- signatureId = int(signatureString)
- return cls(generatorId, signatureId)
- except:
- pass
- return None
+ 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
matchers[1].__class__, suricata.update.main.ReRuleMatcher)
self.assertEquals(
matchers[2].__class__, suricata.update.main.IdRuleMatcher)
+
+class IdRuleMatcherTestCase(unittest.TestCase):
+
+ def test_parse_single_sid(self):
+ matcher = main.IdRuleMatcher.parse("123")
+ self.assertIsNotNone(matcher)
+ self.assertEquals(1, len(matcher.signatureIds))
+
+ def test_parse_single_gidsid(self):
+ matcher = main.IdRuleMatcher.parse("1:123")
+ self.assertIsNotNone(matcher)
+ self.assertEquals(1, len(matcher.signatureIds))
+
+ def test_parse_multi_sid(self):
+ matcher = main.IdRuleMatcher.parse("1,2,3")
+ self.assertIsNotNone(matcher)
+ self.assertEquals(3, len(matcher.signatureIds))
+
+ def test_parse_multi_gidsid(self):
+ matcher = main.IdRuleMatcher.parse("1:1000,2:2000, 3:3000, 4:4000")
+ self.assertIsNotNone(matcher)
+ self.assertEquals(4, len(matcher.signatureIds))
+
+ def test_parse_multi_mixed(self):
+ matcher = main.IdRuleMatcher.parse("1:1000, 2000, 3:3000, 4000")
+ self.assertIsNotNone(matcher)
+ self.assertEquals(4, len(matcher.signatureIds))
+
+ def test_parse_invalid(self):
+ matcher = main.IdRuleMatcher.parse("a")
+ self.assertIsNone(matcher)
+
+ matcher = main.IdRuleMatcher.parse("1, a")
+ self.assertIsNone(matcher)
+
+ matcher = main.IdRuleMatcher.parse("1a")
+ self.assertIsNone(matcher)
+
+ matcher = main.IdRuleMatcher.parse("1:a")
+ self.assertIsNone(matcher)