mirror of https://github.com/fail2ban/fail2ban
- Initial commit of the new prefix remover.
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@688 a942ae1a-1317-0410-a47c-b1dcaea8d6050.x
parent
543741f6e8
commit
1b3828421e
6
MANIFEST
6
MANIFEST
|
@ -25,16 +25,18 @@ server/server.py
|
|||
server/actions.py
|
||||
server/faildata.py
|
||||
server/failmanager.py
|
||||
server/datedetector.py
|
||||
server/jailthread.py
|
||||
server/transmitter.py
|
||||
server/template.py
|
||||
server/hosttemplate.py
|
||||
server/action.py
|
||||
server/ticket.py
|
||||
server/jail.py
|
||||
server/jails.py
|
||||
server/__init__.py
|
||||
server/banmanager.py
|
||||
server/datetemplate.py
|
||||
server/timetemplate.py
|
||||
server/prefixtemplate.py
|
||||
server/mytime.py
|
||||
server/failregex.py
|
||||
testcases/banmanagertestcase.py
|
||||
|
|
|
@ -222,7 +222,12 @@ class Fail2banRegex:
|
|||
try:
|
||||
self.__filter.addFailRegex(regex.getFailRegex())
|
||||
try:
|
||||
ret = self.__filter.processLine(line)
|
||||
try:
|
||||
# Decode line to UTF-8
|
||||
l = line.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
l = line
|
||||
ret = self.__filter.findFailure(l)
|
||||
if not len(ret) == 0:
|
||||
if found == True:
|
||||
ret[0].append(True)
|
||||
|
@ -320,12 +325,6 @@ class Fail2banRegex:
|
|||
|
||||
print
|
||||
|
||||
print "Date template hits:"
|
||||
for template in self.__filter.dateDetector.getTemplates():
|
||||
print `template.getHits()` + " hit(s): " + template.getName()
|
||||
|
||||
print
|
||||
|
||||
print "Success, the total number of match is " + str(total)
|
||||
print
|
||||
print "However, look at the above section 'Running tests' which could contain important"
|
||||
|
@ -333,7 +332,7 @@ class Fail2banRegex:
|
|||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
def main():
|
||||
fail2banRegex = Fail2banRegex()
|
||||
# Reads the command line options.
|
||||
try:
|
||||
|
@ -388,3 +387,9 @@ if __name__ == "__main__":
|
|||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(-1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
print "Interrupted by the user"
|
||||
|
|
|
@ -34,7 +34,6 @@ from testcases import clientreadertestcase
|
|||
from testcases import failmanagertestcase
|
||||
from testcases import filtertestcase
|
||||
from testcases import servertestcase
|
||||
from testcases import datedetectortestcase
|
||||
from testcases import actiontestcase
|
||||
from server.mytime import MyTime
|
||||
|
||||
|
@ -67,8 +66,6 @@ tests.addTest(unittest.makeSuite(failmanagertestcase.AddFailure))
|
|||
tests.addTest(unittest.makeSuite(banmanagertestcase.AddFailure))
|
||||
# ClientReader
|
||||
tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest))
|
||||
# DateDetector
|
||||
tests.addTest(unittest.makeSuite(datedetectortestcase.DateDetectorTest))
|
||||
|
||||
# Tests runner
|
||||
testRunner = unittest.TextTestRunner()
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
# 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$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import time, logging
|
||||
|
||||
from datetemplate import DateStrptime
|
||||
from datetemplate import DateTai64n
|
||||
from datetemplate import DateEpoch
|
||||
from threading import Lock
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.filter.datedetector")
|
||||
|
||||
class DateDetector:
|
||||
|
||||
def __init__(self):
|
||||
self.__lock = Lock()
|
||||
self.__templates = list()
|
||||
|
||||
def addDefaultTemplate(self):
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
# standard
|
||||
template = DateStrptime()
|
||||
template.setName("Month Day Hour:Minute:Second")
|
||||
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)
|
||||
# asctime
|
||||
template = DateStrptime()
|
||||
template.setName("Weekday Month Day Hour:Minute:Second Year")
|
||||
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4}")
|
||||
template.setPattern("%a %b %d %H:%M:%S %Y")
|
||||
self.__templates.append(template)
|
||||
# asctime without year
|
||||
template = DateStrptime()
|
||||
template.setName("Weekday Month Day Hour:Minute:Second")
|
||||
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%a %b %d %H:%M:%S")
|
||||
self.__templates.append(template)
|
||||
# simple date
|
||||
template = DateStrptime()
|
||||
template.setName("Year/Month/Day Hour:Minute:Second")
|
||||
template.setRegex("\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%Y/%m/%d %H:%M:%S")
|
||||
self.__templates.append(template)
|
||||
# simple date too (from x11vnc)
|
||||
template = DateStrptime()
|
||||
template.setName("Day/Month/Year Hour:Minute:Second")
|
||||
template.setRegex("\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%d/%m/%Y %H:%M:%S")
|
||||
self.__templates.append(template)
|
||||
# Apache format [31/Oct/2006:09:22:55 -0000]
|
||||
template = DateStrptime()
|
||||
template.setName("Day/Month/Year:Hour:Minute:Second")
|
||||
template.setRegex("\d{2}/\S{3}/\d{4}:\d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%d/%b/%Y:%H:%M:%S")
|
||||
self.__templates.append(template)
|
||||
# Exim 2006-12-21 06:43:20
|
||||
template = DateStrptime()
|
||||
template.setName("Year-Month-Day Hour:Minute:Second")
|
||||
template.setRegex("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%Y-%m-%d %H:%M:%S")
|
||||
self.__templates.append(template)
|
||||
# named 26-Jul-2007 15:20:52.252
|
||||
template = DateStrptime()
|
||||
template.setName("Day-Month-Year Hour:Minute:Second[.Millisecond]")
|
||||
template.setRegex("\d{2}-\S{3}-\d{4} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%d-%b-%Y %H:%M:%S")
|
||||
self.__templates.append(template)
|
||||
# TAI64N
|
||||
template = DateTai64n()
|
||||
template.setName("TAI64N")
|
||||
self.__templates.append(template)
|
||||
# Epoch
|
||||
template = DateEpoch()
|
||||
template.setName("Epoch")
|
||||
self.__templates.append(template)
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def getTemplates(self):
|
||||
return self.__templates
|
||||
|
||||
def matchTime(self, line):
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
for template in self.__templates:
|
||||
match = template.matchDate(line)
|
||||
if not match == None:
|
||||
return match
|
||||
return None
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def getTime(self, line):
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
for template in self.__templates:
|
||||
try:
|
||||
date = template.getDate(line)
|
||||
if date == None:
|
||||
continue
|
||||
return date
|
||||
except ValueError:
|
||||
pass
|
||||
return None
|
||||
finally:
|
||||
self.__lock.release()
|
||||
|
||||
def getUnixTime(self, line):
|
||||
date = self.getTime(line)
|
||||
if date == None:
|
||||
return None
|
||||
else:
|
||||
return time.mktime(date)
|
||||
|
||||
##
|
||||
# Sort the template lists using the hits score. This method is not called
|
||||
# in this object and thus should be called from time to time.
|
||||
|
||||
def sortTemplate(self):
|
||||
self.__lock.acquire()
|
||||
try:
|
||||
logSys.debug("Sorting the template list")
|
||||
self.__templates.sort(lambda x, y: cmp(x.getHits(), y.getHits()))
|
||||
self.__templates.reverse()
|
||||
finally:
|
||||
self.__lock.release()
|
|
@ -1,166 +0,0 @@
|
|||
# -*- coding: utf8 -*-
|
||||
# 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$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import re, time
|
||||
|
||||
from mytime import MyTime
|
||||
|
||||
class DateTemplate:
|
||||
|
||||
def __init__(self):
|
||||
self.__name = ""
|
||||
self.__regex = ""
|
||||
self.__cRegex = None
|
||||
self.__hits = 0
|
||||
|
||||
def setName(self, name):
|
||||
self.__name = name
|
||||
|
||||
def getName(self):
|
||||
return self.__name
|
||||
|
||||
def setRegex(self, regex):
|
||||
self.__regex = regex.strip()
|
||||
self.__cRegex = re.compile(regex)
|
||||
|
||||
def getRegex(self):
|
||||
return self.__regex
|
||||
|
||||
def getHits(self):
|
||||
return self.__hits
|
||||
|
||||
def matchDate(self, line):
|
||||
dateMatch = self.__cRegex.search(line)
|
||||
if not dateMatch == None:
|
||||
self.__hits += 1
|
||||
return dateMatch
|
||||
|
||||
def getDate(self, line):
|
||||
raise Exception("matchDate() is abstract")
|
||||
|
||||
|
||||
class DateEpoch(DateTemplate):
|
||||
|
||||
def __init__(self):
|
||||
DateTemplate.__init__(self)
|
||||
# We already know the format for TAI64N
|
||||
self.setRegex("^\d{10}(\.\d{6})?")
|
||||
|
||||
def getDate(self, line):
|
||||
date = None
|
||||
dateMatch = self.matchDate(line)
|
||||
if dateMatch:
|
||||
# extract part of format which represents seconds since epoch
|
||||
date = list(time.localtime(float(dateMatch.group())))
|
||||
return date
|
||||
|
||||
|
||||
##
|
||||
# Use strptime() to parse a date. Our current locale is the 'C'
|
||||
# one because we do not set the locale explicitly. This is POSIX
|
||||
# standard.
|
||||
|
||||
class DateStrptime(DateTemplate):
|
||||
|
||||
TABLE = dict()
|
||||
TABLE["Jan"] = []
|
||||
TABLE["Feb"] = [u"Fév"]
|
||||
TABLE["Mar"] = [u"Mär"]
|
||||
TABLE["Apr"] = ["Avr"]
|
||||
TABLE["May"] = ["Mai"]
|
||||
TABLE["Jun"] = []
|
||||
TABLE["Jul"] = []
|
||||
TABLE["Aug"] = ["Aou"]
|
||||
TABLE["Sep"] = []
|
||||
TABLE["Oct"] = ["Okt"]
|
||||
TABLE["Nov"] = []
|
||||
TABLE["Dec"] = [u"Déc", "Dez"]
|
||||
|
||||
def __init__(self):
|
||||
DateTemplate.__init__(self)
|
||||
self.__pattern = ""
|
||||
|
||||
def setPattern(self, pattern):
|
||||
self.__pattern = pattern.strip()
|
||||
|
||||
def getPattern(self):
|
||||
return self.__pattern
|
||||
|
||||
#@staticmethod
|
||||
def convertLocale(date):
|
||||
for t in DateStrptime.TABLE:
|
||||
for m in DateStrptime.TABLE[t]:
|
||||
if date.find(m) >= 0:
|
||||
return date.replace(m, t)
|
||||
return date
|
||||
convertLocale = staticmethod(convertLocale)
|
||||
|
||||
def getDate(self, line):
|
||||
date = None
|
||||
dateMatch = self.matchDate(line)
|
||||
if dateMatch:
|
||||
try:
|
||||
# Try first with 'C' locale
|
||||
date = list(time.strptime(dateMatch.group(), self.getPattern()))
|
||||
except ValueError:
|
||||
# Try to convert date string to 'C' locale
|
||||
conv = self.convertLocale(dateMatch.group())
|
||||
try:
|
||||
date = list(time.strptime(conv, self.getPattern()))
|
||||
except ValueError:
|
||||
# Try to add the current year to the pattern. Should fix
|
||||
# the "Feb 29" issue.
|
||||
conv += " %s" % MyTime.gmtime()[0]
|
||||
pattern = "%s %%Y" % self.getPattern()
|
||||
date = list(time.strptime(conv, pattern))
|
||||
if date[0] < 2000:
|
||||
# There is probably no year field in the logs
|
||||
date[0] = MyTime.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) > MyTime.time():
|
||||
date[0] -= 1
|
||||
return date
|
||||
|
||||
|
||||
class DateTai64n(DateTemplate):
|
||||
|
||||
def __init__(self):
|
||||
DateTemplate.__init__(self)
|
||||
# We already know the format for TAI64N
|
||||
self.setRegex("@[0-9a-f]{24}")
|
||||
|
||||
def getDate(self, line):
|
||||
date = None
|
||||
dateMatch = self.matchDate(line)
|
||||
if dateMatch:
|
||||
# extract part of format which represents seconds since epoch
|
||||
value = dateMatch.group()
|
||||
seconds_since_epoch = value[2:17]
|
||||
date = list(time.gmtime(int(seconds_since_epoch, 16)))
|
||||
return date
|
|
@ -24,66 +24,119 @@ __date__ = "$Date$"
|
|||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import re, sre_constants
|
||||
import re, sre_constants, logging
|
||||
|
||||
##
|
||||
# Regular expression class.
|
||||
#
|
||||
# This class represents a regular expression with its compiled version.
|
||||
from template import Template
|
||||
from timetemplate import TimeTemplates
|
||||
from prefixtemplate import PrefixTemplates
|
||||
from hosttemplate import HostTemplates
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.filter.failregex")
|
||||
|
||||
class Regex:
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# Creates a new object. This method can throw RegexException in order to
|
||||
# avoid construction of invalid object.
|
||||
# @param value the regular expression
|
||||
|
||||
def __init__(self, regex):
|
||||
self._matchCache = None
|
||||
# Perform shortcuts expansions.
|
||||
# Replace "<HOST>" with default regular expression for host.
|
||||
regex = regex.replace("<HOST>", "(?:::f{4,6}:)?(?P<host>\S+)")
|
||||
if regex.lstrip() == '':
|
||||
raise RegexException("Cannot add empty regex")
|
||||
self.__originalRegex = regex
|
||||
self.__convertedRegex = None
|
||||
self.__compiledRegex = None
|
||||
self.__templates = dict()
|
||||
self.__hostRegex = None
|
||||
self.__dateRegex = None
|
||||
self.__prefixRegex = None
|
||||
|
||||
def process(self):
|
||||
regex = self.__originalRegex
|
||||
for item in self.__templates.values():
|
||||
regex = regex.replace(item.getTag(), item.getRegex(), 1)
|
||||
try:
|
||||
self._regexObj = re.compile(regex)
|
||||
self._regex = regex
|
||||
self.__compiledRegex = re.compile(regex)
|
||||
self.__convertedRegex = regex
|
||||
except sre_constants.error:
|
||||
raise RegexException("Unable to compile regular expression '%s'" %
|
||||
regex)
|
||||
|
||||
def register(self, template):
|
||||
self.__templates[template.getName()] = template
|
||||
|
||||
##
|
||||
# Gets the regular expression.
|
||||
#
|
||||
# The effective regular expression used is returned.
|
||||
# @return the regular expression
|
||||
def getTemplate(self, tag):
|
||||
return self.__templates[tag]
|
||||
|
||||
def match(self, line):
|
||||
return self.__compiledRegex.match(line)
|
||||
|
||||
def getRegex(self):
|
||||
return self._regex
|
||||
def getOriginalRegex(self):
|
||||
return self.__originalRegex
|
||||
|
||||
##
|
||||
# Searches the regular expression.
|
||||
#
|
||||
# Sets an internal cache (match object) in order to avoid searching for
|
||||
# the pattern again. This method must be called before calling any other
|
||||
# method of this object.
|
||||
# @param value the line
|
||||
def getConvertedRegex(self):
|
||||
return self.__convertedRegex
|
||||
|
||||
|
||||
class FailRegex:
|
||||
|
||||
def search(self, value):
|
||||
self._matchCache = self._regexObj.search(value)
|
||||
HOST_TEMPLATES = HostTemplates()
|
||||
PREFIX_TEMPLATES = PrefixTemplates()
|
||||
TIME_TEMPLATES = TimeTemplates()
|
||||
|
||||
##
|
||||
# Checks if the previous call to search() matched.
|
||||
#
|
||||
# @return True if a match was found, False otherwise
|
||||
def __init__(self, regex):
|
||||
self.__regex = Regex(regex)
|
||||
self.__match = None
|
||||
self.__found = False
|
||||
|
||||
def __autoDetection(self, line):
|
||||
for host in self.HOST_TEMPLATES.getTemplates():
|
||||
self.__regex.register(host)
|
||||
for date in self.TIME_TEMPLATES.getTemplates():
|
||||
self.__regex.register(date)
|
||||
for prefix in self.PREFIX_TEMPLATES.getTemplates():
|
||||
self.__regex.register(prefix)
|
||||
self.__regex.process()
|
||||
match = self.__regex.match(line)
|
||||
if match:
|
||||
self.__found = True
|
||||
#logSys.debug("Auto-detection succeeded")
|
||||
#logSys.debug("failregex is %s" %
|
||||
# self.__regex.getConvertedRegex())
|
||||
return match
|
||||
return None
|
||||
|
||||
def search(self, line):
|
||||
if self.__found:
|
||||
self.__match = self.__regex.match(line)
|
||||
else:
|
||||
self.__match = self.__autoDetection(line)
|
||||
|
||||
def hasMatched(self):
|
||||
if self._matchCache:
|
||||
if self.__match:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def getOriginalRegex(self):
|
||||
return self.__regex.getOriginalRegex()
|
||||
|
||||
def getHost(self):
|
||||
template = self.__regex.getTemplate(Template.TEMPLATE_HOST)
|
||||
host = self.__match.group(template.getName())
|
||||
if host == None:
|
||||
# Gets a few information.
|
||||
s = self.__match.string
|
||||
r = self.__match.re
|
||||
raise RegexException("No 'host' found in '%s' using '%s'" % (s, r))
|
||||
return host
|
||||
|
||||
def getTime(self):
|
||||
template = self.__regex.getTemplate(Template.TEMPLATE_TIME)
|
||||
time = self.__match.group(template.getName())
|
||||
if time == None:
|
||||
# Gets a few information.
|
||||
s = self.__match.string
|
||||
r = self.__match.re
|
||||
raise RegexException("No 'time' found in '%s' using '%s'" % (s, r))
|
||||
try:
|
||||
return template.getTime(time)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
##
|
||||
|
@ -91,40 +144,3 @@ class Regex:
|
|||
|
||||
class RegexException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
##
|
||||
# Regular expression class.
|
||||
#
|
||||
# This class represents a regular expression with its compiled version.
|
||||
|
||||
class FailRegex(Regex):
|
||||
|
||||
##
|
||||
# Constructor.
|
||||
#
|
||||
# Creates a new object. This method can throw RegexException in order to
|
||||
# avoid construction of invalid object.
|
||||
# @param value the regular expression
|
||||
|
||||
def __init__(self, regex):
|
||||
# Initializes the parent.
|
||||
Regex.__init__(self, regex)
|
||||
# Check for group "host"
|
||||
if "host" not in self._regexObj.groupindex:
|
||||
raise RegexException("No 'host' group in '%s'" % self._regex)
|
||||
|
||||
##
|
||||
# Returns the matched host.
|
||||
#
|
||||
# This corresponds to the pattern matched by the named group "host".
|
||||
# @return the matched host
|
||||
|
||||
def getHost(self):
|
||||
host = self._matchCache.group("host")
|
||||
if host == None:
|
||||
# Gets a few information.
|
||||
s = self._matchCache.string
|
||||
r = self._matchCache.re
|
||||
raise RegexException("No 'host' found in '%s' using '%s'" % (s, r))
|
||||
return host
|
||||
|
|
|
@ -27,11 +27,10 @@ __license__ = "GPL"
|
|||
from failmanager import FailManager
|
||||
from ticket import FailTicket
|
||||
from jailthread import JailThread
|
||||
from datedetector import DateDetector
|
||||
from mytime import MyTime
|
||||
from failregex import FailRegex, Regex, RegexException
|
||||
|
||||
import logging, re
|
||||
import logging, re, time
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger("fail2ban.filter")
|
||||
|
@ -65,9 +64,6 @@ class Filter(JailThread):
|
|||
self.__findTime = 6000
|
||||
## The ignore IP list.
|
||||
self.__ignoreIpList = []
|
||||
|
||||
self.dateDetector = DateDetector()
|
||||
self.dateDetector.addDefaultTemplate()
|
||||
logSys.info("Created Filter")
|
||||
|
||||
|
||||
|
@ -101,7 +97,7 @@ class Filter(JailThread):
|
|||
def getFailRegex(self):
|
||||
failRegex = list()
|
||||
for regex in self.__failRegex:
|
||||
failRegex.append(regex.getRegex())
|
||||
failRegex.append(regex.getOriginalRegex())
|
||||
return failRegex
|
||||
|
||||
##
|
||||
|
@ -232,28 +228,14 @@ class Filter(JailThread):
|
|||
if a == b:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def processLine(self, line):
|
||||
def processLineAndAdd(self, line):
|
||||
try:
|
||||
# Decode line to UTF-8
|
||||
l = line.decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
l = line
|
||||
timeMatch = self.dateDetector.matchTime(l)
|
||||
if not timeMatch:
|
||||
# There is no valid time in this line
|
||||
return []
|
||||
# Lets split into time part and log part of the line
|
||||
timeLine = timeMatch.group()
|
||||
# Lets leave the beginning in as well, so if there is no
|
||||
# anchore at the beginning of the time regexp, we don't
|
||||
# at least allow injection. Should be harmless otherwise
|
||||
logLine = l[:timeMatch.start()] + l[timeMatch.end():]
|
||||
return self.findFailure(timeLine, logLine)
|
||||
|
||||
def processLineAndAdd(self, line):
|
||||
for element in self.processLine(line):
|
||||
for element in self.findFailure(l):
|
||||
ip = element[0]
|
||||
unixTime = element[1]
|
||||
if unixTime < MyTime.time() - self.getFindTime():
|
||||
|
@ -273,8 +255,8 @@ class Filter(JailThread):
|
|||
|
||||
def ignoreLine(self, line):
|
||||
for ignoreRegex in self.__ignoreRegex:
|
||||
ignoreRegex.search(line)
|
||||
if ignoreRegex.hasMatched():
|
||||
ignoreRegex.process()
|
||||
if ignoreRegex.match(line):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -285,35 +267,33 @@ class Filter(JailThread):
|
|||
# to find the logging time.
|
||||
# @return a dict with IP and timestamp.
|
||||
|
||||
def findFailure(self, timeLine, logLine):
|
||||
def findFailure(self, line):
|
||||
failList = list()
|
||||
# Checks if we must ignore this line.
|
||||
if self.ignoreLine(logLine):
|
||||
if self.ignoreLine(line):
|
||||
# The ignoreregex matched. Return.
|
||||
return failList
|
||||
# Iterates over all the regular expressions.
|
||||
for failRegex in self.__failRegex:
|
||||
failRegex.search(logLine)
|
||||
failRegex.search(line)
|
||||
if failRegex.hasMatched():
|
||||
# The failregex matched.
|
||||
date = self.dateDetector.getUnixTime(timeLine)
|
||||
if date == None:
|
||||
logSys.debug("Found a match for '" + logLine +"' but no "
|
||||
+ "valid date/time found for '"
|
||||
+ timeLine + "'. Please contact the "
|
||||
+ "author in order to get support for this "
|
||||
+ "format")
|
||||
else:
|
||||
try:
|
||||
host = failRegex.getHost()
|
||||
ipMatch = DNSUtils.textToIp(host)
|
||||
if ipMatch:
|
||||
for ip in ipMatch:
|
||||
failList.append([ip, date])
|
||||
# We matched a regex, it is enough to stop.
|
||||
break
|
||||
except RegexException, e:
|
||||
logSys.error(e)
|
||||
try:
|
||||
host = failRegex.getHost()
|
||||
date = failRegex.getTime()
|
||||
if not date:
|
||||
logSys.warning("Unable to get a valid date: %s" % line)
|
||||
break
|
||||
# Use Unix timestamp.
|
||||
dateUnix = time.mktime(date)
|
||||
ipMatch = DNSUtils.textToIp(host)
|
||||
if ipMatch:
|
||||
for ip in ipMatch:
|
||||
failList.append([ip, dateUnix])
|
||||
# We matched a regex, it is enough to stop.
|
||||
break
|
||||
except RegexException, e:
|
||||
logSys.error(e)
|
||||
return failList
|
||||
|
||||
|
||||
|
@ -325,7 +305,7 @@ class Filter(JailThread):
|
|||
# @return a list with tuple
|
||||
|
||||
def status(self):
|
||||
ret = [("Currently failed", self.failManager.size()),
|
||||
ret = [("Currently failed", self.failManager.size()),
|
||||
("Total failed", self.failManager.getFailTotal())]
|
||||
return ret
|
||||
|
||||
|
@ -342,7 +322,7 @@ class FileFilter(Filter):
|
|||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path, tail = False):
|
||||
def addLogPath(self, path, tail = True):
|
||||
container = FileContainer(path, tail)
|
||||
self.__logPath.append(container)
|
||||
|
||||
|
|
|
@ -113,7 +113,6 @@ class FilterGamin(FileFilter):
|
|||
self.jail.putFailTicket(ticket)
|
||||
except FailManagerEmpty:
|
||||
self.failManager.cleanup(MyTime.time())
|
||||
self.dateDetector.sortTemplate()
|
||||
self.__modified = False
|
||||
time.sleep(self.getSleepTime())
|
||||
else:
|
||||
|
|
|
@ -108,7 +108,6 @@ class FilterPoll(FileFilter):
|
|||
self.jail.putFailTicket(ticket)
|
||||
except FailManagerEmpty:
|
||||
self.failManager.cleanup(MyTime.time())
|
||||
self.dateDetector.sortTemplate()
|
||||
self.__modified = False
|
||||
time.sleep(self.getSleepTime())
|
||||
else:
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# -*- coding: utf8 -*-
|
||||
# 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: 645 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 645 $"
|
||||
__date__ = "$Date: 2008-01-16 23:55:04 +0100 (Wed, 16 Jan 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from template import Template, Templates
|
||||
|
||||
class HostTemplate(Template):
|
||||
|
||||
def __init__(self):
|
||||
Template.__init__(self, Template.TEMPLATE_HOST, "<HOST>")
|
||||
|
||||
|
||||
class HostTemplates(Templates):
|
||||
|
||||
def __init__(self):
|
||||
Templates.__init__(self)
|
||||
# ::ffff:141.3.81.106
|
||||
template = HostTemplate()
|
||||
template.setRegex("(?:::f{4,6}:)?(?P<%s>\S+)" % template.getName())
|
||||
self.templates.append(template)
|
|
@ -0,0 +1,51 @@
|
|||
# -*- coding: utf8 -*-
|
||||
# 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: 645 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 645 $"
|
||||
__date__ = "$Date: 2008-01-16 23:55:04 +0100 (Wed, 16 Jan 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from template import Template, Templates
|
||||
|
||||
class PrefixTemplate(Template):
|
||||
|
||||
def __init__(self):
|
||||
Template.__init__(self, Template.TEMPLATE_PREFIX, "<PREFIX>")
|
||||
|
||||
|
||||
class PrefixTemplates(Templates):
|
||||
|
||||
def __init__(self):
|
||||
Templates.__init__(self)
|
||||
# i60p295 sshd[12365]:
|
||||
template = PrefixTemplate()
|
||||
template.setRegex("\S+ \S+\[\d+\]:")
|
||||
self.templates.append(template)
|
||||
# [sshd] error: PAM:
|
||||
template = PrefixTemplate()
|
||||
template.setRegex("\[\S+\] \S+: \S+:")
|
||||
self.templates.append(template)
|
||||
# HOSTNAME courieresmtpd
|
||||
template = PrefixTemplate()
|
||||
template.setRegex("\S+ \S+:")
|
||||
self.templates.append(template)
|
|
@ -159,7 +159,8 @@ class Server:
|
|||
return self.__jails.getFilter(name).getIgnoreIP()
|
||||
|
||||
def addLogPath(self, name, fileName):
|
||||
self.__jails.getFilter(name).addLogPath(fileName)
|
||||
# Enable tail mode.
|
||||
self.__jails.getFilter(name).addLogPath(fileName, True)
|
||||
|
||||
def delLogPath(self, name, fileName):
|
||||
self.__jails.getFilter(name).delLogPath(fileName)
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
# 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: 642 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 642 $"
|
||||
__date__ = "$Date: 2008-01-05 23:33:44 +0100 (Sat, 05 Jan 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
|
||||
class Template:
|
||||
|
||||
TEMPLATE_HOST = "host"
|
||||
TEMPLATE_TIME = "time"
|
||||
TEMPLATE_PREFIX = "prefix"
|
||||
|
||||
def __init__(self, name, tag):
|
||||
self.__name = name
|
||||
self.__tag = tag
|
||||
self.__regex = ""
|
||||
self.__description = ""
|
||||
|
||||
def getName(self):
|
||||
return self.__name
|
||||
|
||||
def getTag(self):
|
||||
return self.__tag
|
||||
|
||||
def setDescription(self, description):
|
||||
self.__description = description
|
||||
|
||||
def getDescription(self):
|
||||
return self.__description
|
||||
|
||||
def setRegex(self, regex):
|
||||
self.__regex = regex
|
||||
|
||||
def getRegex(self):
|
||||
return self.__regex
|
||||
|
||||
|
||||
class Templates:
|
||||
|
||||
def __init__(self):
|
||||
self.templates = list()
|
||||
|
||||
def getTemplates(self):
|
||||
return self.templates
|
|
@ -0,0 +1,195 @@
|
|||
# -*- coding: utf8 -*-
|
||||
# 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: 645 $
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision: 645 $"
|
||||
__date__ = "$Date: 2008-01-16 23:55:04 +0100 (Wed, 16 Jan 2008) $"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import time
|
||||
|
||||
from template import Template, Templates
|
||||
from mytime import MyTime
|
||||
|
||||
class TimeTemplate(Template):
|
||||
|
||||
def __init__(self):
|
||||
Template.__init__(self, Template.TEMPLATE_TIME, "<TIME>")
|
||||
|
||||
def setRegex(self, regex):
|
||||
Template.setRegex(self, "(?P<%s>%s)" % (self.getName(), regex))
|
||||
|
||||
def getTime(self, line):
|
||||
raise Exception("getTime() is abstract")
|
||||
|
||||
|
||||
class TimeEpoch(TimeTemplate):
|
||||
|
||||
def __init__(self):
|
||||
TimeTemplate.__init__(self)
|
||||
# We already know the format for TAI64N
|
||||
self.setRegex("\d{10}(\.\d{6})?")
|
||||
|
||||
def getTime(self, line):
|
||||
# extract part of format which represents seconds since epoch
|
||||
return list(time.localtime(float(line)))
|
||||
|
||||
|
||||
##
|
||||
# Use strptime() to parse a date. Our current locale is the 'C'
|
||||
# one because we do not set the locale explicitly. This is POSIX
|
||||
# standard.
|
||||
|
||||
class TimeStrptime(TimeTemplate):
|
||||
|
||||
TABLE = dict()
|
||||
TABLE["Jan"] = []
|
||||
TABLE["Feb"] = [u"Fév"]
|
||||
TABLE["Mar"] = [u"Mär"]
|
||||
TABLE["Apr"] = ["Avr"]
|
||||
TABLE["May"] = ["Mai"]
|
||||
TABLE["Jun"] = []
|
||||
TABLE["Jul"] = []
|
||||
TABLE["Aug"] = ["Aou"]
|
||||
TABLE["Sep"] = []
|
||||
TABLE["Oct"] = ["Okt"]
|
||||
TABLE["Nov"] = []
|
||||
TABLE["Dec"] = [u"Déc", "Dez"]
|
||||
|
||||
def __init__(self):
|
||||
TimeTemplate.__init__(self)
|
||||
self.__pattern = ""
|
||||
|
||||
def setPattern(self, pattern):
|
||||
self.__pattern = pattern.strip()
|
||||
|
||||
def getPattern(self):
|
||||
return self.__pattern
|
||||
|
||||
#@staticmethod
|
||||
def convertLocale(date):
|
||||
for t in TimeStrptime.TABLE:
|
||||
for m in TimeStrptime.TABLE[t]:
|
||||
if date.find(m) >= 0:
|
||||
return date.replace(m, t)
|
||||
return date
|
||||
convertLocale = staticmethod(convertLocale)
|
||||
|
||||
def getTime(self, line):
|
||||
try:
|
||||
# Try first with 'C' locale
|
||||
date = list(time.strptime(line, self.getPattern()))
|
||||
except ValueError:
|
||||
# Try to convert date string to 'C' locale
|
||||
conv = self.convertLocale(line)
|
||||
try:
|
||||
date = list(time.strptime(conv, self.getPattern()))
|
||||
except ValueError:
|
||||
# Try to add the current year to the pattern. Should fix
|
||||
# the "Feb 29" issue.
|
||||
conv += " %s" % MyTime.gmtime()[0]
|
||||
pattern = "%s %%Y" % self.getPattern()
|
||||
date = list(time.strptime(conv, pattern))
|
||||
if date[0] < 2000:
|
||||
# There is probably no year field in the logs
|
||||
date[0] = MyTime.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) > MyTime.time():
|
||||
date[0] -= 1
|
||||
return date
|
||||
|
||||
|
||||
class TimeTai64n(TimeTemplate):
|
||||
|
||||
def __init__(self):
|
||||
TimeTemplate.__init__(self)
|
||||
# We already know the format for TAI64N
|
||||
self.setRegex("@[0-9a-f]{24}")
|
||||
|
||||
def getTime(self, line):
|
||||
# extract part of format which represents seconds since epoch
|
||||
seconds_since_epoch = line[2:17]
|
||||
return list(time.gmtime(int(seconds_since_epoch, 16)))
|
||||
|
||||
|
||||
class TimeTemplates(Templates):
|
||||
|
||||
def __init__(self):
|
||||
Templates.__init__(self)
|
||||
# standard
|
||||
template = TimeStrptime()
|
||||
template.setDescription("Month Day Hour:Minute:Second")
|
||||
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)
|
||||
# asctime
|
||||
template = TimeStrptime()
|
||||
template.setDescription("Weekday Month Day Hour:Minute:Second Year")
|
||||
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4}")
|
||||
template.setPattern("%a %b %d %H:%M:%S %Y")
|
||||
self.templates.append(template)
|
||||
# asctime without year
|
||||
template = TimeStrptime()
|
||||
template.setDescription("Weekday Month Day Hour:Minute:Second")
|
||||
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%a %b %d %H:%M:%S")
|
||||
self.templates.append(template)
|
||||
# simple date
|
||||
template = TimeStrptime()
|
||||
template.setDescription("Year/Month/Day Hour:Minute:Second")
|
||||
template.setRegex("\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%Y/%m/%d %H:%M:%S")
|
||||
self.templates.append(template)
|
||||
# simple date too (from x11vnc)
|
||||
template = TimeStrptime()
|
||||
template.setDescription("Day/Month/Year Hour:Minute:Second")
|
||||
template.setRegex("\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%d/%m/%Y %H:%M:%S")
|
||||
self.templates.append(template)
|
||||
# Apache format [31/Oct/2006:09:22:55 -0000]
|
||||
template = TimeStrptime()
|
||||
template.setDescription("Day/Month/Year:Hour:Minute:Second")
|
||||
template.setRegex("\d{2}/\S{3}/\d{4}:\d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%d/%b/%Y:%H:%M:%S")
|
||||
self.templates.append(template)
|
||||
# Exim 2006-12-21 06:43:20
|
||||
template = TimeStrptime()
|
||||
template.setDescription("Year-Month-Day Hour:Minute:Second")
|
||||
template.setRegex("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%Y-%m-%d %H:%M:%S")
|
||||
self.templates.append(template)
|
||||
# named 26-Jul-2007 15:20:52.252
|
||||
template = TimeStrptime()
|
||||
template.setDescription("Day-Month-Year Hour:Minute:Second[.Millisecond]")
|
||||
template.setRegex("\d{2}-\S{3}-\d{4} \d{2}:\d{2}:\d{2}")
|
||||
template.setPattern("%d-%b-%Y %H:%M:%S")
|
||||
self.templates.append(template)
|
||||
# TAI64N
|
||||
template = TimeTai64n()
|
||||
template.setDescription("TAI64N")
|
||||
self.templates.append(template)
|
||||
# Epoch
|
||||
template = TimeEpoch()
|
||||
template.setDescription("Epoch")
|
||||
self.templates.append(template)
|
|
@ -1,67 +0,0 @@
|
|||
# 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$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import unittest
|
||||
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 testGetEpochTime(self):
|
||||
log = "1138049999 [sshd] error: PAM: Authentication failure"
|
||||
date = [2006, 1, 23, 21, 59, 59, 0, 23, 0]
|
||||
dateUnix = 1138049999.0
|
||||
|
||||
self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
|
||||
def testGetTime(self):
|
||||
log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure"
|
||||
date = [2005, 1, 23, 21, 59, 59, 1, 23, -1]
|
||||
dateUnix = 1106513999.0
|
||||
|
||||
self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
|
||||
# def testDefaultTempate(self):
|
||||
# self.__datedetector.setDefaultRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||
# self.__datedetector.setDefaultPattern("%b %d %H:%M:%S")
|
||||
#
|
||||
# log = "Jan 23 21:59:59 [sshd] error: PAM: Authentication failure"
|
||||
# date = [2005, 1, 23, 21, 59, 59, 1, 23, -1]
|
||||
# dateUnix = 1106513999.0
|
||||
#
|
||||
# self.assertEqual(self.__datedetector.getTime(log), date)
|
||||
# self.assertEqual(self.__datedetector.getUnixTime(log), dateUnix)
|
||||
|
|
@ -98,8 +98,8 @@ class GetFailures(unittest.TestCase):
|
|||
def testGetFailures01(self):
|
||||
output = ('193.168.0.128', 3, 1124013599.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_01)
|
||||
self.__filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) (?:::f{4,6}:)?(?P<host>\S*)")
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_01, False)
|
||||
self.__filter.addFailRegex("<TIME> <PREFIX> (?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) <HOST>")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_01)
|
||||
|
||||
|
@ -115,8 +115,8 @@ class GetFailures(unittest.TestCase):
|
|||
def testGetFailures02(self):
|
||||
output = ('141.3.81.106', 4, 1124013539.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02)
|
||||
self.__filter.addFailRegex("Failed .* (?:::f{4,6}:)(?P<host>\S*)")
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02, False)
|
||||
self.__filter.addFailRegex("<TIME> <PREFIX> Failed .* (?:::f{4,6}:)(?P<host>\S*)")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_02)
|
||||
|
||||
|
@ -132,8 +132,8 @@ class GetFailures(unittest.TestCase):
|
|||
def testGetFailures03(self):
|
||||
output = ('203.162.223.135', 6, 1124013544.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_03)
|
||||
self.__filter.addFailRegex("error,relay=(?:::f{4,6}:)?(?P<host>\S*),.*550 User unknown")
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_03, False)
|
||||
self.__filter.addFailRegex("<TIME> <PREFIX> error,relay=(?:::f{4,6}:)?(?P<host>\S*),.*550 User unknown")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_03)
|
||||
|
||||
|
@ -150,8 +150,8 @@ class GetFailures(unittest.TestCase):
|
|||
output = [('212.41.96.186', 4, 1124013600.0),
|
||||
('212.41.96.185', 4, 1124013598.0)]
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_04)
|
||||
self.__filter.addFailRegex("Invalid user .* (?P<host>\S*)")
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_04, False)
|
||||
self.__filter.addFailRegex("<TIME> <PREFIX> Invalid user .* (?P<host>\S*)")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_04)
|
||||
|
||||
|
@ -169,9 +169,9 @@ class GetFailures(unittest.TestCase):
|
|||
def testGetFailuresMultiRegex(self):
|
||||
output = ('141.3.81.106', 8, 1124013541.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02)
|
||||
self.__filter.addFailRegex("Failed .* from <HOST>")
|
||||
self.__filter.addFailRegex("Accepted .* from <HOST>")
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02, False)
|
||||
self.__filter.addFailRegex("<TIME> <PREFIX> Failed .* from <HOST>")
|
||||
self.__filter.addFailRegex("<TIME> <PREFIX> Accepted .* from <HOST>")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_02)
|
||||
|
||||
|
@ -187,10 +187,10 @@ class GetFailures(unittest.TestCase):
|
|||
def testGetFailuresIgnoreRegex(self):
|
||||
output = ('141.3.81.106', 8, 1124013541.0)
|
||||
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02)
|
||||
self.__filter.addFailRegex("Failed .* from <HOST>")
|
||||
self.__filter.addFailRegex("Accepted .* from <HOST>")
|
||||
self.__filter.addIgnoreRegex("for roehl")
|
||||
self.__filter.addLogPath(GetFailures.FILENAME_02, False)
|
||||
self.__filter.addFailRegex("<TIME> <PREFIX> Failed .* from <HOST>")
|
||||
self.__filter.addFailRegex("<TIME> <PREFIX> Accepted .* from <HOST>")
|
||||
self.__filter.addIgnoreRegex(".* for roehl")
|
||||
|
||||
self.__filter.getFailures(GetFailures.FILENAME_02)
|
||||
|
||||
|
|
Loading…
Reference in New Issue