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/server/strptime.py b/fail2ban/server/strptime.py index 6e412d86..12be163a 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() diff --git a/fail2ban/tests/fail2banregextestcase.py b/fail2ban/tests/fail2banregextestcase.py index 32acc0ae..26b40abb 100644 --- a/fail2ban/tests/fail2banregextestcase.py +++ b/fail2ban/tests/fail2banregextestcase.py @@ -408,7 +408,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)