introduced new flag "banned" as property, used to recognize the ticket was really banned;

get/set restored flag functions rewritten to property "restored" similar to "banned";
several code optimizations and tests extensions;
pull/1557/head
sebres 8 years ago
parent 2108216d33
commit f6197200a9

@ -359,9 +359,10 @@ class Actions(JailThread, Mapping):
aInfo["ipjailmatches"] = lambda: "\n".join(mi4ip().getMatches())
aInfo["ipfailures"] = lambda: mi4ip(True).getAttempt()
aInfo["ipjailfailures"] = lambda: mi4ip().getAttempt()
if self.__banManager.addBanTicket(bTicket):
reason = {}
if self.__banManager.addBanTicket(bTicket, reason=reason):
cnt += 1
logSys.notice("[%s] %sBan %s", self._jail.name, ('' if not bTicket.getRestored() else 'Restore '), ip)
logSys.notice("[%s] %sBan %s", self._jail.name, ('' if not bTicket.restored else 'Restore '), ip)
for name, action in self._actions.iteritems():
try:
action.ban(aInfo.copy())
@ -371,8 +372,22 @@ class Actions(JailThread, Mapping):
"info '%r': %s",
self._jail.name, name, aInfo, e,
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
# after all actions are processed set banned flag:
bTicket.banned = True
else:
logSys.notice("[%s] %s already banned", self._jail.name, ip)
bTicket = reason['ticket']
# if already banned (otherwise still process some action)
if bTicket.banned:
# compare time of failure occurrence with time ticket was really banned:
diftm = ticket.getTime() - bTicket.getTime()
# log already banned with following level:
# DEBUG - before 3 seconds - certain interval for it, because of possible latency by recognizing in backends, etc.
# NOTICE - before 60 seconds - may still occurre if action are slow, or very high load in backend,
# WARNING - after 60 seconds - very long time, something may be wrong
ll = logging.DEBUG if diftm < 3 \
else logging.NOTICE if diftm < 60 \
else logging.WARNING
logSys.log(ll, "[%s] %s already banned", self._jail.name, ip)
if cnt:
logSys.debug("Banned %s / %s, %s ticket(s) in %r", cnt,
self.__banManager.getBanTotal(), self.__banManager.size(), self._jail.name)

@ -256,29 +256,30 @@ class BanManager:
# @param ticket the ticket
# @return True if the IP address is not in the ban list
def addBanTicket(self, ticket):
def addBanTicket(self, ticket, reason={}):
eob = ticket.getEndOfBanTime(self.__banTime)
with self.__lock:
# check already banned
fid = ticket.getID()
oldticket = self.__banList.get(fid)
if oldticket:
# if already permanent
btold, told = oldticket.getBanTime(self.__banTime), oldticket.getTime()
if btold == -1:
return False
# if given time is less than already banned time
btnew, tnew = ticket.getBanTime(self.__banTime), ticket.getTime()
if btnew != -1 and tnew + btnew <= told + btold:
return False
# we have longest ban - set new (increment) ban time
oldticket.setTime(tnew)
oldticket.setBanTime(btnew)
reason['ticket'] = oldticket
# if new time for end of ban is larger than already banned end-time:
if eob > oldticket.getEndOfBanTime(self.__banTime):
# we have longest ban - set new (increment) ban time
reason['prolong'] = 1
btm = ticket.getBanTime(self.__banTime)
# if not permanent:
if btm != -1:
diftm = ticket.getTime() - oldticket.getTime()
if diftm > 0:
btm += diftm
oldticket.setBanTime(btm)
return False
# not yet banned - add new
# not yet banned - add new one:
self.__banList[fid] = ticket
self.__banTotal += 1
# correct next unban time:
eob = ticket.getEndOfBanTime(self.__banTime)
if self.__nextUnbanTime > eob:
self.__nextUnbanTime = eob
return True

@ -28,7 +28,7 @@ import Queue
from .actions import Actions
from ..client.jailreader import JailReader
from ..helpers import getLogger
from ..helpers import getLogger, MyTime
# Gets the instance of the logger.
logSys = getLogger(__name__)
@ -194,7 +194,7 @@ class Jail(object):
Used by filter to add a failure for banning.
"""
self.__queue.put(ticket)
if not ticket.getRestored() and self.database is not None:
if not ticket.restored and self.database is not None:
self.database.addBan(self, ticket)
def getFailTicket(self):
@ -203,7 +203,8 @@ class Jail(object):
Used by actions to get a failure for banning.
"""
try:
return self.__queue.get(False)
ticket = self.__queue.get(False)
return ticket
except Queue.Empty:
return False
@ -217,7 +218,17 @@ class Jail(object):
#logSys.debug('restored ticket: %s', ticket)
if not self.filter.inIgnoreIPList(ticket.getIP(), log_ignore=True):
# mark ticked was restored from database - does not put it again into db:
ticket.setRestored(True)
ticket.restored = True
# correct start time / ban time (by the same end of ban):
btm = ticket.getBanTime(forbantime)
diftm = MyTime.time() - ticket.getTime()
if btm != -1 and diftm > 0:
btm -= diftm
# ignore obsolete tickets:
if btm != -1 and btm <= 0:
continue
ticket.setTime(MyTime.time())
ticket.setBanTime(btm)
self.putFailTicket(ticket)
except Exception as e: # pragma: no cover
logSys.error('%s', e, exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)

@ -34,9 +34,10 @@ from .mytime import MyTime
logSys = getLogger(__name__)
class Ticket:
class Ticket(object):
RESTORED = 0x01
BANNED = 0x08
def __init__(self, ip=None, time=None, matches=None, data={}, ticket=None):
"""Ticket constructor
@ -135,14 +136,25 @@ class Ticket:
def getMatches(self):
return self._data.get('matches', [])
def setRestored(self, value):
@property
def restored(self):
return self._flags & Ticket.RESTORED
@restored.setter
def restored(self, value):
if value:
self._flags = Ticket.RESTORED
self._flags |= Ticket.RESTORED
else:
self._flags &= ~(Ticket.RESTORED)
def getRestored(self):
return self._flags & Ticket.RESTORED
@property
def banned(self):
return self._flags & Ticket.BANNED
@banned.setter
def banned(self, value):
if value:
self._flags |= Ticket.BANNED
else:
self._flags &= ~(Ticket.BANNED)
def setData(self, *args, **argv):
# if overwrite - set data and filter None values:

@ -53,11 +53,15 @@ class AddFailure(unittest.TestCase):
self.assertEqual(self.__banManager.size(), 1)
def testAddDuplicateWithTime(self):
defBanTime = self.__banManager.getBanTime()
prevEndOfBanTime = 0
# add again a duplicate :
# 1) with newer start time and the same ban time
# 0) with same start time and the same (default) ban time
# 1) with newer start time and the same (default) ban time
# 2) with same start time and longer ban time
# 3) with permanent ban time (-1)
for tnew, btnew in (
(1167605999.0, None),
(1167605999.0 + 100, None),
(1167605999.0, 24*60*60),
(1167605999.0, -1),
@ -71,9 +75,14 @@ class AddFailure(unittest.TestCase):
self.assertEqual(self.__banManager.size(), 1)
# pop ticket and check it was prolonged :
banticket = self.__banManager.getTicketByID(ticket2.getID())
self.assertEqual(banticket.getTime(), ticket2.getTime())
self.assertEqual(banticket.getTime(), ticket2.getTime())
self.assertEqual(banticket.getBanTime(), ticket2.getBanTime(self.__banManager.getBanTime()))
self.assertEqual(banticket.getEndOfBanTime(defBanTime), ticket2.getEndOfBanTime(defBanTime))
self.assertTrue(banticket.getEndOfBanTime(defBanTime) > prevEndOfBanTime)
prevEndOfBanTime = ticket1.getEndOfBanTime(defBanTime)
# but the start time should not be changed (+ 100 is ignored):
self.assertEqual(banticket.getTime(), 1167605999.0)
# if prolong to permanent, it should also have permanent ban time:
if btnew == -1:
self.assertEqual(banticket.getBanTime(defBanTime), -1)
def testInListOK(self):
self.assertTrue(self.__banManager.addBanTicket(self.__ticket))

@ -108,6 +108,24 @@ class TicketTests(unittest.TestCase):
self.assertEqual(ft2.getLastTime(), ft.getLastTime())
self.assertEqual(ft2.getBanTime(), ft.getBanTime())
def testTicketFlags(self):
flags = ('restored', 'banned')
ticket = Ticket('test', 0)
trueflags = []
for v in (True, False, True):
for f in flags:
setattr(ticket, f, v)
if v:
trueflags.append(f)
else:
trueflags.remove(f)
for f2 in flags:
self.assertEqual(bool(getattr(ticket, f2)), f2 in trueflags)
## inherite props from another tockets:
ticket = FailTicket(ticket=ticket)
for f2 in flags:
self.assertTrue(bool(getattr(ticket, f2)))
def testTicketData(self):
t = BanTicket('193.168.0.128', None, ['first', 'second'])
# expand data (no overwrites, matches are available) :

Loading…
Cancel
Save