mirror of https://github.com/fail2ban/fail2ban
code review, test case extended;
parent
697da99f8f
commit
4dbc77dbbb
|
@ -559,7 +559,7 @@ class FileFilter(Filter):
|
|||
#
|
||||
# @param path log file path
|
||||
|
||||
def addLogPath(self, path, tail = False):
|
||||
def addLogPath(self, path, tail=False):
|
||||
if self.containsLogPath(path):
|
||||
logSys.error(path + " already exists")
|
||||
else:
|
||||
|
@ -655,7 +655,7 @@ class FileFilter(Filter):
|
|||
# MyTime.time()-self.findTime. When a failure is detected, a FailTicket
|
||||
# is created and is added to the FailManager.
|
||||
|
||||
def getFailures(self, filename, startTime = None):
|
||||
def getFailures(self, filename, startTime=None):
|
||||
container = self.getFileContainer(filename)
|
||||
if container is None:
|
||||
logSys.error("Unable to get failures in " + filename)
|
||||
|
@ -673,14 +673,19 @@ class FileFilter(Filter):
|
|||
logSys.exception(e)
|
||||
return False
|
||||
except OSError, e: # pragma: no cover - Requires implemention error in FileContainer to generate
|
||||
logSys.error("Internal errror in FileContainer open method - please report as a bug to https://github.com/fail2ban/fail2ban/issues")
|
||||
logSys.error("Internal error in FileContainer open method - please report as a bug to https://github.com/fail2ban/fail2ban/issues")
|
||||
logSys.exception(e)
|
||||
return False
|
||||
|
||||
# prevent completely read of big files first time (after start of service), initial seek to start time using half-interval search algorithm:
|
||||
if container.getPos() == 0 and startTime is not None:
|
||||
try:
|
||||
# startTime = MyTime.time() - self.getFindTime()
|
||||
self.seekToTime(container, startTime)
|
||||
except Exception, e: # pragma: no cover
|
||||
logSys.error("Error during seek to start time in \"%s\"", filename)
|
||||
logSys.exception(e)
|
||||
return False
|
||||
|
||||
# yoh: has_content is just a bool, so do not expect it to
|
||||
# change -- loop is exited upon break, and is not entered at
|
||||
|
@ -717,7 +722,7 @@ class FileFilter(Filter):
|
|||
cntr = 0
|
||||
unixTime = None
|
||||
lasti = 0
|
||||
movecntr = 3
|
||||
movecntr = 1
|
||||
while maxp > minp:
|
||||
i = int(minp + (maxp - minp) / 2)
|
||||
pos = container.seek(i)
|
||||
|
@ -726,6 +731,7 @@ class FileFilter(Filter):
|
|||
lncntr = 5;
|
||||
dateTimeMatch = None
|
||||
llen = 0
|
||||
if lastpos == pos:
|
||||
i = pos
|
||||
while True:
|
||||
line = container.readline()
|
||||
|
@ -763,6 +769,7 @@ class FileFilter(Filter):
|
|||
lastpos = container.seek(lastFew, False)
|
||||
else:
|
||||
lastpos = container.seek(lastpos, False)
|
||||
container.setPos(lastpos)
|
||||
if logSys.getEffectiveLevel() <= logging.DEBUG:
|
||||
logSys.debug("Position %s from %s, found time %s (%s) within %s seeks", lastpos, fs, unixTime,
|
||||
(datetime.datetime.fromtimestamp(unixTime).strftime("%Y-%m-%d %H:%M:%S") if unixTime is not None else ''), cntr)
|
||||
|
@ -943,10 +950,6 @@ class DNSUtils:
|
|||
logSys.warning("Unable to find a corresponding IP address for %s: %s"
|
||||
% (dns, e))
|
||||
return list()
|
||||
except socket.error, e:
|
||||
logSys.warning("Socket error raised trying to resolve hostname %s: %s"
|
||||
% (dns, e))
|
||||
return list()
|
||||
|
||||
@staticmethod
|
||||
def searchIP(text):
|
||||
|
@ -967,7 +970,7 @@ class DNSUtils:
|
|||
try:
|
||||
socket.inet_aton(s[0])
|
||||
return True
|
||||
except socket.error:
|
||||
except socket.error: # pragma: no cover
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -27,7 +27,7 @@ import unittest
|
|||
import getpass
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import time, datetime
|
||||
import tempfile
|
||||
import uuid
|
||||
|
||||
|
@ -38,7 +38,7 @@ except ImportError:
|
|||
|
||||
from ..server.jail import Jail
|
||||
from ..server.filterpoll import FilterPoll
|
||||
from ..server.filter import Filter, FileFilter, DNSUtils
|
||||
from ..server.filter import Filter, FileFilter, FileContainer, DNSUtils
|
||||
from ..server.failmanager import FailManagerEmpty
|
||||
from ..server.mytime import MyTime
|
||||
from .utils import setUpMyTime, tearDownMyTime, mtimesleep, LogCaptureTestCase
|
||||
|
@ -314,6 +314,60 @@ class LogFileFilterPoll(unittest.TestCase):
|
|||
self.assertTrue(self.filter.isModified(LogFileFilterPoll.FILENAME))
|
||||
self.assertFalse(self.filter.isModified(LogFileFilterPoll.FILENAME))
|
||||
|
||||
def testSeekToTime(self):
|
||||
fname = tempfile.mktemp(prefix='tmp_fail2ban', suffix='.log')
|
||||
tm = lambda time: datetime.datetime.fromtimestamp(time).strftime("%Y-%m-%d %H:%M:%S")
|
||||
time = 1417512352
|
||||
f = open(fname, 'w')
|
||||
fc = FileContainer(fname, self.filter.getLogEncoding())
|
||||
fc.open()
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
try:
|
||||
f.flush()
|
||||
# empty :
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
self.assertEqual(fc.getPos(), 0)
|
||||
# one entry with exact time:
|
||||
f.write("%s [sshd] error: PAM: failure len 1\n" % tm(time))
|
||||
f.flush()
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
# one entry with smaller time:
|
||||
f.seek(0)
|
||||
f.write("%s [sshd] error: PAM: failure len 1\n" % tm(time - 10))
|
||||
f.flush()
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
self.assertEqual(fc.getPos(), 0)
|
||||
f.write("%s [sshd] error: PAM: failure len 3 2 1\n" % tm(time - 9))
|
||||
f.flush()
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
self.assertEqual(fc.getPos(), 0)
|
||||
# add exact time between:
|
||||
f.write("%s [sshd] error: PAM: failure\n" % tm(time - 1))
|
||||
f.flush()
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
self.assertEqual(fc.getPos(), 110)
|
||||
# stil one exact line:
|
||||
f.write("%s [sshd] error: PAM: Authentication failure\n" % tm(time))
|
||||
f.write("%s [sshd] error: PAM: failure len 1\n" % tm(time))
|
||||
f.flush()
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
self.assertEqual(fc.getPos(), 110)
|
||||
# add something hereafter:
|
||||
f.write("%s [sshd] error: PAM: failure len 3 2 1\n" % tm(time + 2))
|
||||
f.write("%s [sshd] error: PAM: Authentication failure\n" % tm(time + 3))
|
||||
f.flush()
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
self.assertEqual(fc.getPos(), 110)
|
||||
# add something hereafter:
|
||||
f.write("%s [sshd] error: PAM: failure\n" % tm(time + 9))
|
||||
f.write("%s [sshd] error: PAM: failure len 3 2 1\n" % tm(time + 9))
|
||||
f.flush()
|
||||
fc.setPos(0); self.filter.seekToTime(fc, time)
|
||||
self.assertEqual(fc.getPos(), 110)
|
||||
|
||||
finally:
|
||||
fc.close()
|
||||
_killfile(f, fname)
|
||||
|
||||
class LogFileMonitor(LogCaptureTestCase):
|
||||
"""Few more tests for FilterPoll API
|
||||
|
|
Loading…
Reference in New Issue