BF: Remove manually unbanned IPs from persistent database

Stops them being restored when Fail2Ban is restarted. Particularly this
is an issue with bantime < 0

Fixes gh-768
pull/769/head
Steven Hiscocks 2014-07-19 15:17:32 +01:00
parent e301d6c840
commit 01d02ca5e6
4 changed files with 26 additions and 1 deletions

View File

@ -39,6 +39,8 @@ ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
* Per-distribution paths to the exim's main log * Per-distribution paths to the exim's main log
* Ignored IPs are no longer banned when being restored from persistent * Ignored IPs are no longer banned when being restored from persistent
database database
* Manually unbanned IPs are now removed from persistent database, such they
wont be banned again when Fail2Ban is restarted
- New features: - New features:
- Added monit filter thanks Jason H Martin. - Added monit filter thanks Jason H Martin.

View File

@ -197,6 +197,8 @@ class Actions(JailThread, Mapping):
if ticket is not None: if ticket is not None:
# Unban the IP. # Unban the IP.
self.__unBan(ticket) self.__unBan(ticket)
if self._jail.database is not None:
self._jail.database.delBan(self._jail, ticket)
else: else:
raise ValueError("IP %s is not banned" % ip) raise ValueError("IP %s is not banned" % ip)

View File

@ -368,10 +368,25 @@ class Fail2BanDb(object):
#TODO: Implement data parts once arbitrary match keys completed #TODO: Implement data parts once arbitrary match keys completed
cur.execute( cur.execute(
"INSERT INTO bans(jail, ip, timeofban, data) VALUES(?, ?, ?, ?)", "INSERT INTO bans(jail, ip, timeofban, data) VALUES(?, ?, ?, ?)",
(jail.name, ticket.getIP(), round(ticket.getTime()), (jail.name, ticket.getIP(), int(round(ticket.getTime())),
{"matches": ticket.getMatches(), {"matches": ticket.getMatches(),
"failures": ticket.getAttempt()})) "failures": ticket.getAttempt()}))
@commitandrollback
def delBan(self, cur, jail, ticket):
"""Delete a ban from the database.
Parameters
----------
jail : Jail
Jail in which the ban has occurred.
ticket : BanTicket
Ticket of the ban to be removed.
"""
cur.execute(
"DELETE FROM bans WHERE jail = ? AND ip = ? AND timeofban = ?",
(jail.name, ticket.getIP(), int(round(ticket.getTime()))))
@commitandrollback @commitandrollback
def _getBans(self, cur, jail=None, bantime=None, ip=None): def _getBans(self, cur, jail=None, bantime=None, ip=None):
query = "SELECT ip, timeofban, data FROM bans WHERE 1" query = "SELECT ip, timeofban, data FROM bans WHERE 1"

View File

@ -173,6 +173,12 @@ class DatabaseTest(unittest.TestCase):
self.assertTrue( self.assertTrue(
isinstance(self.db.getBans(jail=self.jail)[0], FailTicket)) isinstance(self.db.getBans(jail=self.jail)[0], FailTicket))
def testDelBan(self):
self.testAddBan()
ticket = self.db.getBans(jail=self.jail)[0]
self.db.delBan(self.jail, ticket)
self.assertEqual(len(self.db.getBans(jail=self.jail)), 0)
def testGetBansWithTime(self): def testGetBansWithTime(self):
if Fail2BanDb is None: # pragma: no cover if Fail2BanDb is None: # pragma: no cover
return return