From b598d47d2fbfa37eb73f7d301a855558fe1b14df Mon Sep 17 00:00:00 2001 From: lostcontrol Date: Tue, 5 Sep 2006 21:17:35 +0000 Subject: [PATCH] - Added date detector git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@326 a942ae1a-1317-0410-a47c-b1dcaea8d605 --- MANIFEST | 2 + server/datedetector.py | 103 ++++++++++++++++++++++++++++++ server/datetemplate.py | 74 +++++++++++++++++++++ testcases/datedetectortestcase.py | 52 +++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 server/datedetector.py create mode 100644 server/datetemplate.py create mode 100644 testcases/datedetectortestcase.py diff --git a/MANIFEST b/MANIFEST index bb31b743..7e43bf11 100644 --- a/MANIFEST +++ b/MANIFEST @@ -17,6 +17,8 @@ client/csocket.py server/ssocket.py server/banticket.py server/filter.py +server/datedetector.py +server/datetemplate.py server/server.py server/failticket.py server/actions.py diff --git a/server/datedetector.py b/server/datedetector.py new file mode 100644 index 00000000..5b52326e --- /dev/null +++ b/server/datedetector.py @@ -0,0 +1,103 @@ +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Author: Cyril Jaquier +# +# $Revision: 321 $ + +__author__ = "Cyril Jaquier" +__version__ = "$Revision: 321 $" +__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $" +__copyright__ = "Copyright (c) 2004 Cyril Jaquier" +__license__ = "GPL" + +import time + +from datetemplate import DateTemplate + +class DateDetector: + + def __init__(self): + self.templates = list() + self.defTemplate = DateTemplate() + + def addDefaultTemplate(self): + template = DateTemplate() + template.setRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}") + template.setPattern("%b %d %H:%M:%S") + self.templates.append(template) + + template = DateTemplate() + template.setRegex("\S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}") + template.setPattern("%a %b %d %H:%M:%S %Y") + self.templates.append(template) + + def setDefaultRegex(self, value): + self.defTemplate.setRegex(value) + + def getDefaultRegex(self): + return self.defTemplate.getRegex() + + def setDefaultPattern(self, value): + self.defTemplate.setPattern(value) + + def getDefaultPattern(self): + return self.defTemplate.getPattern() + + #def addTemplate(self, template): + # self.templates.append(template) + + def matchTime(self, line): + if self.defTemplate.isValid(): + return self.defTemplate.matchDate(line) + else: + # TODO Should be called from outside. Add locking + for template in self.templates: + match = template.matchDate(line) + if match <> None: + return match + return None + + def getTime(self, line): + if self.defTemplate.isValid(): + try: + date = self.defTemplate.getDate(line) + return date + except ValueError: + return None + else: + # TODO Should be called from outside. Add locking + self.sortTemplate() + for template in self.templates: + try: + date = template.getDate(line) + template.incHits() + return date + except ValueError: + pass + return None + + def getUnixTime(self, line): + date = self.getTime(line) + if date == None: + return None + else: + return time.mktime(date) + + def sortTemplate(self): + self.templates.sort(cmp = lambda x, y: cmp(x.getHits(), y.getHits()), + reverse=True) + \ No newline at end of file diff --git a/server/datetemplate.py b/server/datetemplate.py new file mode 100644 index 00000000..5944adca --- /dev/null +++ b/server/datetemplate.py @@ -0,0 +1,74 @@ +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Author: Cyril Jaquier +# +# $Revision: 321 $ + +__author__ = "Cyril Jaquier" +__version__ = "$Revision: 321 $" +__date__ = "$Date: 2006-09-04 21:19:58 +0200 (Mon, 04 Sep 2006) $" +__copyright__ = "Copyright (c) 2004 Cyril Jaquier" +__license__ = "GPL" + +import re, time + +class DateTemplate: + + def __init__(self): + self.regex = "" + self.pattern = "" + self.hits = 0 + + def setRegex(self, regex): + self.regex = regex + + def getRegex(self): + return self.regex + + def setPattern(self, pattern): + self.pattern = pattern + + def getPattern(self): + return self.pattern + + def isValid(self): + return self.regex != "" and self.pattern != "" + + def incHits(self): + self.hits = self.hits + 1 + + def getHits(self): + return self.hits + + def matchDate(self, line): + dateMatch = re.search(self.regex, line) + return dateMatch + + def getDate(self, line): + date = None + dateMatch = self.matchDate(line) + if dateMatch: + date = list(time.strptime(dateMatch.group(), self.pattern)) + if date[0] < 2000: + # There is probably no year field in the logs + date[0] = time.gmtime()[0] + # Bug fix for #1241756 + # If the date is greater than the current time, we suppose + # that the log is not from this year but from the year before + if time.mktime(date) > time.time(): + date[0] -= 1 + return date diff --git a/testcases/datedetectortestcase.py b/testcases/datedetectortestcase.py new file mode 100644 index 00000000..64d703d8 --- /dev/null +++ b/testcases/datedetectortestcase.py @@ -0,0 +1,52 @@ +# This file is part of Fail2Ban. +# +# Fail2Ban is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Fail2Ban is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Fail2Ban; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Author: Cyril Jaquier +# +# $Revision: 253 $ + +__author__ = "Cyril Jaquier" +__version__ = "$Revision: 253 $" +__date__ = "$Date: 2006-07-17 00:21:58 +0200 (Mon, 17 Jul 2006) $" +__copyright__ = "Copyright (c) 2004 Cyril Jaquier" +__license__ = "GPL" + +import unittest, time +from server.datedetector import DateDetector +from server.datetemplate import DateTemplate + +class DateDetectorTest(unittest.TestCase): + + def setUp(self): + """Call before every test case.""" + self.datedetector = DateDetector() + self.datedetector.addDefaultTemplate() + + def tearDown(self): + """Call after every test case.""" + + def testGetTime(self): + log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure" + date = [2006, 1, 23, 21, 59, 59, 1, 23, -1] + dateUnix = 1138049999.0 + + self.assertEqual(self.datedetector.getTime(log), date) + self.assertEqual(self.datedetector.getTime(log), date) + self.assertEqual(self.datedetector.getTime(log), date) + self.assertEqual(self.datedetector.getUnixTime(log), dateUnix) + self.assertEqual(self.datedetector.getUnixTime(log), dateUnix) + self.assertEqual(self.datedetector.getUnixTime(log), dateUnix) + \ No newline at end of file