diff --git a/fail2ban/server/strptime.py b/fail2ban/server/strptime.py index 643984d3..cdfe0e0e 100644 --- a/fail2ban/server/strptime.py +++ b/fail2ban/server/strptime.py @@ -41,7 +41,7 @@ def _getYearCentRE(cent=(0,3), distance=3, now=(MyTime.now(), MyTime.alternateNo #todo: implement literal time zone support like CET, PST, PDT, etc (via pytz): #timeRE['z'] = r"%s?(?PZ|[+-]\d{2}(?::?[0-5]\d)?|[A-Z]{3})?" % timeRE['Z'] timeRE['Z'] = r"(?P[A-Z]{3,5})" -timeRE['z'] = r"(?PZ|[+-]\d{2}(?::?[0-5]\d)?)" +timeRE['z'] = r"(?PZ|UTC|GMT|[+-]\d{2}(?::?[0-5]\d)?)" # Extend build-in TimeRE with some exact patterns # exact two-digit patterns: @@ -183,7 +183,7 @@ def reGroupDictStrptime(found_dict, msec=False): week_of_year_start = 0 elif key == 'z': z = val - if z == "Z": + if z in ("Z", "UTC", "GMT"): tzoffset = 0 else: tzoffset = int(z[1:3]) * 60 # Hours... @@ -191,6 +191,10 @@ def reGroupDictStrptime(found_dict, msec=False): tzoffset += int(z[-2:]) # ...and minutes if z.startswith("-"): tzoffset = -tzoffset + elif key == 'Z': + z = val + if z in ("UTC", "GMT"): + tzoffset = 0 # Fail2Ban will assume it's this year assume_year = False diff --git a/fail2ban/tests/datedetectortestcase.py b/fail2ban/tests/datedetectortestcase.py index fdb7ec71..695f099c 100644 --- a/fail2ban/tests/datedetectortestcase.py +++ b/fail2ban/tests/datedetectortestcase.py @@ -378,6 +378,11 @@ class CustomDateFormatsTest(unittest.TestCase): ("20031230010203", "{^LN-BEG}%ExY%Exm%Exd%ExH%ExM%ExS**", "#2003123001020320030101000000"), ("20031230010203", "{^LN-BEG}%ExY%Exm%Exd%ExH%ExM%ExS**", "##2003123001020320030101000000"), ("20031230010203", "{^LN-BEG}%ExY%Exm%Exd%ExH%ExM%ExS", "[20031230010203]20030101000000"), + # UTC/GMT time zone offset (with %z and %Z): + (1072746123.0 - 3600, "{^LN-BEG}%ExY-%Exm-%Exd %ExH:%ExM:%ExS(?: %z)?", "[2003-12-30 01:02:03] server ..."), + (1072746123.0 - 3600, "{^LN-BEG}%ExY-%Exm-%Exd %ExH:%ExM:%ExS(?: %Z)?", "[2003-12-30 01:02:03] server ..."), + (1072746123.0, "{^LN-BEG}%ExY-%Exm-%Exd %ExH:%ExM:%ExS(?: %z)?", "[2003-12-30 01:02:03 UTC] server ..."), + (1072746123.0, "{^LN-BEG}%ExY-%Exm-%Exd %ExH:%ExM:%ExS(?: %Z)?", "[2003-12-30 01:02:03 UTC] server ..."), ): logSys.debug('== test: %r', (matched, dp, line)) if dp is None: @@ -388,7 +393,10 @@ class CustomDateFormatsTest(unittest.TestCase): date = dd.getTime(line) if matched: self.assertTrue(date) - self.assertEqual(matched, date[1].group(1)) + if isinstance(matched, basestring): + self.assertEqual(matched, date[1].group(1)) + else: + self.assertEqual(matched, date[0]) else: self.assertEqual(date, None) diff --git a/fail2ban/tests/files/logs/zzz-generic-example b/fail2ban/tests/files/logs/zzz-generic-example index 2044c387..d0c31740 100644 --- a/fail2ban/tests/files/logs/zzz-generic-example +++ b/fail2ban/tests/files/logs/zzz-generic-example @@ -46,6 +46,14 @@ Jun 22 20:37:04 server test-demo[402]: writeToStorage plist={ # failJSON: { "time": "2005-06-22T20:37:04", "match": true , "host": "192.0.2.2" } 0000-12-30 00:00:00 server test-demo[47831]: F2B: failure from 192.0.2.2 +# -- test no zone and UTC/GMT named zone "2005-06-21T14:55:10 UTC" == "2005-06-21T16:55:10 CEST" (diff +2h in CEST): +# failJSON: { "time": "2005-06-21T16:55:09", "match": true , "host": "192.0.2.09" } +2005-06-21 16:55:09 machine test-demo(pam_unix)[13709] F2B: error from 192.0.2.09 +# failJSON: { "time": "2005-06-21T16:55:10", "match": true , "host": "192.0.2.10" } +2005-06-21 14:55:10 UTC machine test-demo(pam_unix)[13709] F2B: error from 192.0.2.10 +# failJSON: { "time": "2005-06-21T16:55:11", "match": true , "host": "192.0.2.11" } +2005-06-21 14:55:11 GMT machine test-demo(pam_unix)[13709] F2B: error from 192.0.2.11 + # failJSON: { "time": "2005-06-21T16:56:02", "match": true , "host": "192.0.2.250" } [Jun 21 16:56:02] machine test-demo(pam_unix)[13709] F2B: error from 192.0.2.250 # failJSON: { "match": false, "desc": "test 1st ignoreregex" }