From bc888e07533bcebd81a9fedf7ce846d86851d63b Mon Sep 17 00:00:00 2001 From: sebres Date: Fri, 24 Mar 2017 12:05:51 +0100 Subject: [PATCH] Regex compiled in multi-line parsing mode only if `maxlines` > 1 (buffering), if however expected - prefix `(?m)` could be used in regex to enable it; Removed warning "Mutliline regex set for jail ... but maxlines not greater than 1", because can be expected situation now: non multi-line entry from systemd-filter containing new-lines (that should be ignored by anchors resp. entry parsed as single string); small code review; --- fail2ban/server/failregex.py | 8 +------- fail2ban/server/filter.py | 6 ------ fail2ban/tests/filtertestcase.py | 6 +++--- fail2ban/tests/samplestestcase.py | 2 +- 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/fail2ban/server/failregex.py b/fail2ban/server/failregex.py index c1e7107a..d5c9345f 100644 --- a/fail2ban/server/failregex.py +++ b/fail2ban/server/failregex.py @@ -111,9 +111,8 @@ class Regex: # if regex.lstrip() == '': raise RegexException("Cannot add empty regex") - flags = re.MULTILINE if (multiline or "\n" in regex or r"\n" in regex) else 0 try: - self._regexObj = re.compile(regex, flags) + self._regexObj = re.compile(regex, re.MULTILINE if multiline else 0) self._regex = regex except sre_constants.error: raise RegexException("Unable to compile regular expression '%s'" % @@ -122,11 +121,6 @@ class Regex: def __str__(self): return "%s(%r)" % (self.__class__.__name__, self._regex) - @property - def flags(self): - """Returns the regex matching flags combination of the compiled regex object""" - return self._regexObj.flags - ## # Replaces "", "", "", "" with default regular expression for host # diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index ed50e8c1..75536d57 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -166,12 +166,6 @@ class Filter(JailThread): regex = FailRegex(value, prefRegex=self.__prefRegex, multiline=multiLine, useDns=self.__useDns) self.__failRegex.append(regex) - regexExpr = regex.getRegex() - # check new lines present in regex (was compiled as multiline), incorrect by `maxlines=1`: - if (regex.flags & re.MULTILINE) and not multiLine: - logSys.warning( - "Mutliline regex set for jail %r " - "but maxlines not greater than 1", self.jailName) except RegexException as e: logSys.error(e) raise e diff --git a/fail2ban/tests/filtertestcase.py b/fail2ban/tests/filtertestcase.py index 10310a5d..ce665e72 100644 --- a/fail2ban/tests/filtertestcase.py +++ b/fail2ban/tests/filtertestcase.py @@ -1479,8 +1479,8 @@ class GetFailures(LogCaptureTestCase): output = [("192.0.43.10", 2, 1124013599.0), ("192.0.43.11", 1, 1124013598.0)] self.filter.addLogPath(GetFailures.FILENAME_MULTILINE, autoSeek=False) - self.filter.addFailRegex("^.*rsyncd\[(?P\d+)\]: connect from .+ \(\)$^.+ rsyncd\[(?P=pid)\]: rsync error: .*$") self.filter.setMaxLines(100) + self.filter.addFailRegex("^.*rsyncd\[(?P\d+)\]: connect from .+ \(\)$^.+ rsyncd\[(?P=pid)\]: rsync error: .*$") self.filter.setMaxRetry(1) self.filter.getFailures(GetFailures.FILENAME_MULTILINE) @@ -1497,9 +1497,9 @@ class GetFailures(LogCaptureTestCase): def testGetFailuresMultiLineIgnoreRegex(self): output = [("192.0.43.10", 2, 1124013599.0)] self.filter.addLogPath(GetFailures.FILENAME_MULTILINE, autoSeek=False) + self.filter.setMaxLines(100) self.filter.addFailRegex("^.*rsyncd\[(?P\d+)\]: connect from .+ \(\)$^.+ rsyncd\[(?P=pid)\]: rsync error: .*$") self.filter.addIgnoreRegex("rsync error: Received SIGINT") - self.filter.setMaxLines(100) self.filter.setMaxRetry(1) self.filter.getFailures(GetFailures.FILENAME_MULTILINE) @@ -1513,9 +1513,9 @@ class GetFailures(LogCaptureTestCase): ("192.0.43.11", 1, 1124013598.0), ("192.0.43.15", 1, 1124013598.0)] self.filter.addLogPath(GetFailures.FILENAME_MULTILINE, autoSeek=False) + self.filter.setMaxLines(100) self.filter.addFailRegex("^.*rsyncd\[(?P\d+)\]: connect from .+ \(\)$^.+ rsyncd\[(?P=pid)\]: rsync error: .*$") self.filter.addFailRegex("^.* sendmail\[.*, msgid=<(?P[^>]+).*relay=\[\].*$^.+ spamd: result: Y \d+ .*,mid=<(?P=msgid)>(,bayes=[.\d]+)?(,autolearn=\S+)?\s*$") - self.filter.setMaxLines(100) self.filter.setMaxRetry(1) self.filter.getFailures(GetFailures.FILENAME_MULTILINE) diff --git a/fail2ban/tests/samplestestcase.py b/fail2ban/tests/samplestestcase.py index fb6812cb..121c1c5c 100644 --- a/fail2ban/tests/samplestestcase.py +++ b/fail2ban/tests/samplestestcase.py @@ -40,7 +40,7 @@ TEST_CONFIG_DIR = os.path.join(os.path.dirname(__file__), "config") TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") # regexp to test greedy catch-all should be not-greedy: -RE_HOST = Regex('').getRegex() +RE_HOST = Regex._resolveHostTag('') RE_WRONG_GREED = re.compile(r'\.[+\*](?!\?)[^\$\^]*' + re.escape(RE_HOST) + r'.*(?:\.[+\*].*|[^\$])$')