Skip to content

Commit

Permalink
matching: allow a rule revision to be matched as well
Browse files Browse the repository at this point in the history
A rule ID can now be matched with a revision given the following
format of:

<gid>:<sid>:<rev>

The <gid> has to be specified for a revision match, as a specifier
with 2 components is read as "gid" and "rev".

Ticket: https://redmine.openinfosecfoundation.org/issues/7425
  • Loading branch information
jasonish committed Jan 15, 2025
1 parent 737b2d8 commit d86d201
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 9 deletions.
4 changes: 4 additions & 0 deletions suricata/update/configs/disable.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
# 1:2019401
# 2019401

# A rule revision can also be provided, but the GID must also be
# specified.
#1:3321408:2

# Example of disabling a rule by regular expression.
# - All regular expression matches are case insensitive.
# re:heartbleed
Expand Down
4 changes: 4 additions & 0 deletions suricata/update/configs/enable.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
# 1:2019401
# 2019401

# A rule revision can also be provided, but the GID must also be
# specified.
#1:3321408:2

# Example of enabling a rule by regular expression.
# - All regular expression matches are case insensitive.
# re:heartbleed
Expand Down
11 changes: 9 additions & 2 deletions suricata/update/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,15 @@ def parse_matchers(fileobj):
else:
# If matcher is an IdRuleMatcher
if isinstance(matcher, matchers_mod.IdRuleMatcher):
for (gid, sid) in matcher.signatureIds:
id_set_matcher.add(gid, sid)
for sig in matcher.signatureIds:
if len(sig) == 2:
# The "set" matcher only supports gid:sid.
id_set_matcher.add(sig[0], sig[1])
elif len(sig) == 3:
# This must also have a rev, don't add to set,
# but add as its own IdSetRuleMatcher.
matchers.append(
matchers_mod.IdRuleMatcher(sig[0], sig[1], sig[2]))
else:
matchers.append(matcher)

Expand Down
28 changes: 21 additions & 7 deletions suricata/update/matchers.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,21 @@ class IdRuleMatcher(object):
"""Matcher object to match an idstools rule object by its signature
ID."""

def __init__(self, generatorId=None, signatureId=None):
def __init__(self, generatorId=None, signatureId=None, rev=None):
self.signatureIds = []
if generatorId and signatureId:
if generatorId and signatureId and rev:
self.signatureIds.append((generatorId, signatureId, rev))
elif 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
for sig in self.signatureIds:
if len(sig) == 3:
if sig[0] == rule.gid and sig[1] == rule.sid and sig[2] == rule.rev:
return True
elif len(sig) == 2:
if sig[0] == rule.gid and sig[1] == rule.sid:
return True
return False

@classmethod
Expand All @@ -92,7 +98,7 @@ def parse(cls, buf):
for entry in buf.split(","):
entry = entry.strip()

parts = entry.split(":", 1)
parts = entry.split(":")
if not parts:
return None
if len(parts) == 1:
Expand All @@ -101,13 +107,21 @@ def parse(cls, buf):
matcher.signatureIds.append((1, signatureId))
except:
return None
else:
elif len(parts) == 2:
try:
generatorId = int(parts[0])
signatureId = int(parts[1])
matcher.signatureIds.append((generatorId, signatureId))
except:
return None
elif len(parts) == 3:
try:
generatorId = int(parts[0])
signatureId = int(parts[1])
rev = int(parts[2])
matcher.signatureIds.append((generatorId, signatureId, rev))
except:
return None

return matcher

Expand Down

0 comments on commit d86d201

Please sign in to comment.