diff --git a/fail2ban/server/database.py b/fail2ban/server/database.py index 5eb7d8d6..f584d74f 100644 --- a/fail2ban/server/database.py +++ b/fail2ban/server/database.py @@ -712,7 +712,7 @@ class Fail2BanDb(object): cur = self._db.cursor() return cur.execute(query, queryArgs) - def getCurrentBans(self, jail = None, ip = None, forbantime=None, fromtime=None): + def getCurrentBans(self, jail = None, ip = None, forbantime=None, fromtime=None, maxmatches=None): tickets = [] ticket = None @@ -724,6 +724,15 @@ class Fail2BanDb(object): for banip, timeofban, data in results: # logSys.debug('restore ticket %r, %r, %r', banip, timeofban, data) ticket = FailTicket(banip, timeofban, data=data) + # filter matches if expected (current count > as maxmatches specified): + if maxmatches is None: + maxmatches = self.maxMatches + if maxmatches: + matches = ticket.getMatches() + if matches and len(matches) > maxmatches: + ticket.setMatches(matches[-maxmatches:]) + else: + ticket.setMatches(None) # logSys.debug('restored ticket: %r', ticket) if ip is not None: return ticket tickets.append(ticket) diff --git a/fail2ban/server/jail.py b/fail2ban/server/jail.py index eb990c47..1deea49b 100644 --- a/fail2ban/server/jail.py +++ b/fail2ban/server/jail.py @@ -213,7 +213,8 @@ class Jail(object): try: if self.database is not None: forbantime = self.actions.getBanTime() - for ticket in self.database.getCurrentBans(jail=self, forbantime=forbantime): + for ticket in self.database.getCurrentBans(jail=self, + forbantime=forbantime, maxmatches=self.filter.failManager.maxMatches): #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: diff --git a/fail2ban/tests/databasetestcase.py b/fail2ban/tests/databasetestcase.py index f03ec18d..8bb28dfe 100644 --- a/fail2ban/tests/databasetestcase.py +++ b/fail2ban/tests/databasetestcase.py @@ -371,7 +371,15 @@ class DatabaseTest(LogCaptureTestCase): self.assertEqual(ticket.getAttempt(), len(failures)) self.assertEqual(len(ticket.getMatches()), maxMatches) self.assertEqual(ticket.getMatches(), matches2find[-maxMatches:]) - # should retrieve 0 matches by last ban: + # maxmatches of jail < dbmaxmatches (so read 1 match and 0 matches): + ticket = self.db.getCurrentBans(self.jail, "127.0.0.1", fromtime=MyTime.time()-100, + maxmatches=1) + self.assertEqual(len(ticket.getMatches()), 1) + self.assertEqual(ticket.getMatches(), failures[3]['matches']) + ticket = self.db.getCurrentBans(self.jail, "127.0.0.1", fromtime=MyTime.time()-100, + maxmatches=0) + self.assertEqual(len(ticket.getMatches()), 0) + # dbmaxmatches = 0, should retrieve 0 matches by last ban: self.db.maxMatches = 0; self.db.addBan(self.jail, ticket) ticket = self.db.getCurrentBans(self.jail, "127.0.0.1", fromtime=MyTime.time()-100)