mirror of https://github.com/fail2ban/fail2ban
fix sporadic time related errors after fail2ban restart resp. reload jail:
- ValueError: need more than N values to unpack - empty banip from restoreCurrentBans, etc.pull/1460/head
parent
0636b3247d
commit
8c54675750
|
@ -80,7 +80,10 @@ class RequestHandler(asynchat.async_chat):
|
||||||
# Deserialize
|
# Deserialize
|
||||||
message = loads(message)
|
message = loads(message)
|
||||||
# Gives the message to the transmitter.
|
# Gives the message to the transmitter.
|
||||||
message = self.__transmitter.proceed(message)
|
if self.__transmitter:
|
||||||
|
message = self.__transmitter.proceed(message)
|
||||||
|
else:
|
||||||
|
message = ['SHUTDOWN']
|
||||||
# Serializes the response.
|
# Serializes the response.
|
||||||
message = dumps(message, HIGHEST_PROTOCOL)
|
message = dumps(message, HIGHEST_PROTOCOL)
|
||||||
# Sends the response to the client.
|
# Sends the response to the client.
|
||||||
|
@ -228,6 +231,13 @@ class AsyncServer(asyncore.dispatcher):
|
||||||
##
|
##
|
||||||
# Stops the communication server.
|
# Stops the communication server.
|
||||||
|
|
||||||
|
def stop_communication(self):
|
||||||
|
logSys.debug("Stop communication")
|
||||||
|
self.__transmitter = None
|
||||||
|
|
||||||
|
##
|
||||||
|
# Stops the server.
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
|
@ -643,7 +643,6 @@ class Fail2BanDb(object):
|
||||||
cur = self._db.cursor()
|
cur = self._db.cursor()
|
||||||
return cur.execute(query, queryArgs)
|
return cur.execute(query, queryArgs)
|
||||||
|
|
||||||
@commitandrollback
|
|
||||||
def _getCurrentBans(self, cur, jail = None, ip = None, forbantime=None, fromtime=None):
|
def _getCurrentBans(self, cur, jail = None, ip = None, forbantime=None, fromtime=None):
|
||||||
if fromtime is None:
|
if fromtime is None:
|
||||||
fromtime = MyTime.time()
|
fromtime = MyTime.time()
|
||||||
|
@ -666,20 +665,29 @@ class Fail2BanDb(object):
|
||||||
cur = self._db.cursor()
|
cur = self._db.cursor()
|
||||||
return cur.execute(query, queryArgs)
|
return cur.execute(query, queryArgs)
|
||||||
|
|
||||||
def getCurrentBans(self, jail = None, ip = None, forbantime=None, fromtime=None):
|
@commitandrollback
|
||||||
|
def getCurrentBans(self, cur, jail = None, ip = None, forbantime=None, fromtime=None):
|
||||||
tickets = []
|
tickets = []
|
||||||
ticket = None
|
ticket = None
|
||||||
|
|
||||||
results = list(self._getCurrentBans(jail=jail, ip=ip, forbantime=forbantime, fromtime=fromtime))
|
for ticket in self._getCurrentBans(cur, jail=jail, ip=ip,
|
||||||
|
forbantime=forbantime, fromtime=fromtime
|
||||||
if results:
|
):
|
||||||
for banip, timeofban, bantime, bancount, data in results:
|
# can produce unpack error (database may return sporadical wrong-empty row):
|
||||||
# logSys.debug('restore ticket %r, %r, %r', banip, timeofban, data)
|
try:
|
||||||
ticket = FailTicket(banip, timeofban, data=data)
|
banip, timeofban, bantime, bancount, data = ticket
|
||||||
# logSys.debug('restored ticket: %r', ticket)
|
# additionally check for empty values:
|
||||||
ticket.setBanTime(bantime)
|
if banip is None or banip == "": # pragma: no cover
|
||||||
ticket.setBanCount(bancount)
|
raise ValueError('unexpected value %r' % (banip,))
|
||||||
tickets.append(ticket)
|
except ValueError as e: # pragma: no cover
|
||||||
|
logSys.debug("get current bans: ignore row %r - %s", ticket, e)
|
||||||
|
continue
|
||||||
|
# logSys.debug('restore ticket %r, %r, %r', banip, timeofban, data)
|
||||||
|
ticket = FailTicket(banip, timeofban, data=data)
|
||||||
|
# logSys.debug('restored ticket: %r', ticket)
|
||||||
|
ticket.setBanTime(bantime)
|
||||||
|
ticket.setBanCount(bancount)
|
||||||
|
tickets.append(ticket)
|
||||||
|
|
||||||
return tickets if ip is None else ticket
|
return tickets if ip is None else ticket
|
||||||
|
|
||||||
|
|
|
@ -274,8 +274,9 @@ class Jail(object):
|
||||||
if not self.getBanTimeExtra('increment'):
|
if not self.getBanTimeExtra('increment'):
|
||||||
forbantime = self.actions.getBanTime()
|
forbantime = self.actions.getBanTime()
|
||||||
for ticket in self.database.getCurrentBans(jail=self, forbantime=forbantime):
|
for ticket in self.database.getCurrentBans(jail=self, forbantime=forbantime):
|
||||||
#logSys.debug('restored ticket: %s', ticket)
|
try:
|
||||||
if not self.filter.inIgnoreIPList(ticket.getIP(), log_ignore=True):
|
#logSys.debug('restored ticket: %s', ticket)
|
||||||
|
if self.filter.inIgnoreIPList(ticket.getIP(), log_ignore=True): continue
|
||||||
# mark ticked was restored from database - does not put it again into db:
|
# mark ticked was restored from database - does not put it again into db:
|
||||||
ticket.restored = True
|
ticket.restored = True
|
||||||
# correct start time / ban time (by the same end of ban):
|
# correct start time / ban time (by the same end of ban):
|
||||||
|
@ -287,8 +288,12 @@ class Jail(object):
|
||||||
if btm != -1 and btm <= 0:
|
if btm != -1 and btm <= 0:
|
||||||
continue
|
continue
|
||||||
self.putFailTicket(ticket)
|
self.putFailTicket(ticket)
|
||||||
|
except Exception as e: # pragma: no cover
|
||||||
|
logSys.error('Restore ticket failed: %s', e,
|
||||||
|
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||||
except Exception as e: # pragma: no cover
|
except Exception as e: # pragma: no cover
|
||||||
logSys.error('%s', e, exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
logSys.error('Restore bans failed: %s', e,
|
||||||
|
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Start the jail, by starting filter and actions threads.
|
"""Start the jail, by starting filter and actions threads.
|
||||||
|
|
|
@ -159,17 +159,16 @@ class Server:
|
||||||
self.__asyncServer.start(sock, force)
|
self.__asyncServer.start(sock, force)
|
||||||
except AsyncServerException as e:
|
except AsyncServerException as e:
|
||||||
logSys.error("Could not start server: %s", e)
|
logSys.error("Could not start server: %s", e)
|
||||||
|
|
||||||
# Removes the PID file.
|
# Removes the PID file.
|
||||||
try:
|
try:
|
||||||
logSys.debug("Remove PID file %s", pidfile)
|
logSys.debug("Remove PID file %s", pidfile)
|
||||||
os.remove(pidfile)
|
os.remove(pidfile)
|
||||||
except (OSError, IOError) as e: # pragma: no cover
|
except (OSError, IOError) as e: # pragma: no cover
|
||||||
logSys.error("Unable to remove PID file: %s", e)
|
logSys.error("Unable to remove PID file: %s", e)
|
||||||
# Stop observer and exit
|
|
||||||
if Observers.Main is not None:
|
# Stop (if not yet already executed):
|
||||||
Observers.Main.stop()
|
self.quit()
|
||||||
Observers.Main = None
|
|
||||||
logSys.info("Exiting Fail2ban")
|
|
||||||
|
|
||||||
def quit(self):
|
def quit(self):
|
||||||
# Give observer a small chance to complete its work before exit
|
# Give observer a small chance to complete its work before exit
|
||||||
|
@ -183,8 +182,7 @@ class Server:
|
||||||
# are exiting)
|
# are exiting)
|
||||||
# See https://github.com/fail2ban/fail2ban/issues/7
|
# See https://github.com/fail2ban/fail2ban/issues/7
|
||||||
if self.__asyncServer is not None:
|
if self.__asyncServer is not None:
|
||||||
self.__asyncServer.stop()
|
self.__asyncServer.stop_communication()
|
||||||
self.__asyncServer = None
|
|
||||||
|
|
||||||
# Now stop all the jails
|
# Now stop all the jails
|
||||||
self.stopAllJail()
|
self.stopAllJail()
|
||||||
|
@ -205,6 +203,16 @@ class Server:
|
||||||
for s, sh in self.__prev_signals.iteritems():
|
for s, sh in self.__prev_signals.iteritems():
|
||||||
signal.signal(s, sh)
|
signal.signal(s, sh)
|
||||||
|
|
||||||
|
# Stop observer and exit
|
||||||
|
if Observers.Main is not None:
|
||||||
|
Observers.Main.stop()
|
||||||
|
Observers.Main = None
|
||||||
|
# Stop async
|
||||||
|
if self.__asyncServer is not None:
|
||||||
|
self.__asyncServer.stop()
|
||||||
|
self.__asyncServer = None
|
||||||
|
logSys.info("Exiting Fail2ban")
|
||||||
|
|
||||||
# Prevent to call quit twice:
|
# Prevent to call quit twice:
|
||||||
self.quit = lambda: False
|
self.quit = lambda: False
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue