From 2918849f9e781fc27a0fd0ba052c1a97d96d02bc Mon Sep 17 00:00:00 2001 From: sebres Date: Fri, 7 May 2021 01:10:26 +0200 Subject: [PATCH 1/2] fixes precise year pattern %ExY - accept years 20xx up to current century (using almost the same pattern in tests and production now) --- fail2ban/server/strptime.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/fail2ban/server/strptime.py b/fail2ban/server/strptime.py index 69514b20..6f88add1 100644 --- a/fail2ban/server/strptime.py +++ b/fail2ban/server/strptime.py @@ -104,14 +104,14 @@ def _updateTimeRE(): # more precise year patterns, within same century of last year and # the next 3 years (for possible long uptime of fail2ban); thereby - # respect possible run in the test-cases (alternate date used there): - if MyTime.alternateNowTime != 0: - timeRE['ExY'] = r"(?P%s\d)" % _getYearCentRE(cent=(0,3), distance=3) - timeRE['Exy'] = r"(?P%s\d)" % _getYearCentRE(cent=(2,3), distance=3) - else: # accept years: 19xx|2xxx up to current century - timeRE['ExY'] = r"(?P(?:19\d{2}|%s\d))" % _getYearCentRE(cent=(0,3), distance=3, - now=(MyTime.now(), datetime.datetime.fromtimestamp(978393600))) - timeRE['Exy'] = r"(?P\d{2})" + # consider possible run in the test-cases (alternate date used there), + # so accept years: 20xx (from test-date or 2001 up to current century) + timeRE['ExY'] = r"(?P%s\d)" % _getYearCentRE(cent=(0,3), distance=3, + now=(datetime.datetime.now(), datetime.datetime.fromtimestamp( + min(MyTime.alternateNowTime or 978393600, 978393600)) + ) + ) + timeRE['Exy'] = r"(?P\d{2})" _updateTimeRE() From ef5c826c74c160d33d4b79b23d564f944d16a9dd Mon Sep 17 00:00:00 2001 From: sebres Date: Fri, 7 May 2021 01:16:48 +0200 Subject: [PATCH 2/2] fixes search for the best datepattern (gh-3020) - e. g. if line is too short, boundaries check for previously known unprecise pattern may fail on incomplete lines (logging break-off, no flush, etc) --- fail2ban/server/datedetector.py | 4 ++-- fail2ban/tests/fail2banregextestcase.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/fail2ban/server/datedetector.py b/fail2ban/server/datedetector.py index ecc9d935..b90e1b26 100644 --- a/fail2ban/server/datedetector.py +++ b/fail2ban/server/datedetector.py @@ -365,10 +365,10 @@ class DateDetector(object): # with space or some special char), otherwise possible collision/pattern switch: if (( line[distance-1:distance] == self.__lastPos[1] or - (line[distance] == self.__lastPos[2] and not self.__lastPos[2].isalnum()) + (line[distance:distance+1] == self.__lastPos[2] and not self.__lastPos[2].isalnum()) ) and ( line[endpos:endpos+1] == self.__lastEndPos[2] or - (line[endpos-1] == self.__lastEndPos[1] and not self.__lastEndPos[1].isalnum()) + (line[endpos-1:endpos] == self.__lastEndPos[1] and not self.__lastEndPos[1].isalnum()) )): # search in line part only: log(logLevel-1, " boundaries are correct, search in part %r", line[distance:endpos]) diff --git a/fail2ban/tests/fail2banregextestcase.py b/fail2ban/tests/fail2banregextestcase.py index 85fe4f15..1c55e227 100644 --- a/fail2ban/tests/fail2banregextestcase.py +++ b/fail2ban/tests/fail2banregextestcase.py @@ -384,7 +384,17 @@ class Fail2banRegexTest(LogCaptureTestCase): "Found a match but no valid date/time found", "Match without a timestamp:", all=True) - self.pruneLog() + def testIncompleteDateTime(self): + # datepattern in followed lines doesn't match previously known pattern + line is too short + # (logging break-off, no flush, etc): + self.assertTrue(_test_exec( + '-o', 'Found-ADDR:', + '192.0.2.1 - - [02/May/2021:18:40:55 +0100] "GET / HTTP/1.1" 302 328 "-" "Mozilla/5.0" "-"\n' + '192.0.2.2 - - [02/May/2021:18:40:55 +0100\n' + '192.0.2.3 - - [02/May/2021:18:40:55', + '^')) + self.assertLogged( + "Found-ADDR:192.0.2.1", "Found-ADDR:192.0.2.2", "Found-ADDR:192.0.2.3", all=True) def testFrmtOutputWrapML(self): unittest.F2B.SkipIfCfgMissing(stock=True)