diff --git a/server/banmanager.py b/server/banmanager.py index fc18f55d..1e123f7c 100644 --- a/server/banmanager.py +++ b/server/banmanager.py @@ -61,7 +61,9 @@ class BanManager: # @param value the time def setBanTime(self, value): + self.lock.acquire() self.banTime = int(value) + self.lock.release() ## # Get the ban time. @@ -70,7 +72,11 @@ class BanManager: # @return the time def getBanTime(self): - return self.banTime + try: + self.lock.acquire() + return self.banTime + finally: + self.lock.release() ## # Set the total number of banned address. @@ -78,7 +84,9 @@ class BanManager: # @param value total number def setBanTotal(self, value): + self.lock.acquire() self.banTotal = value + self.lock.release() ## # Get the total number of banned address. @@ -86,7 +94,11 @@ class BanManager: # @return the total number def getBanTotal(self): - return self.banTotal + try: + self.lock.acquire() + return self.banTotal + finally: + self.lock.release() ## # Create a ban ticket. @@ -98,12 +110,16 @@ class BanManager: @staticmethod def createBanTicket(ticket): - ip = ticket.getIP() - #lastTime = ticket.getTime() - lastTime = time.time() - banTicket = BanTicket(ip, lastTime) - banTicket.setAttempt(ticket.getAttempt()) - return banTicket + try: + self.lock.acquire() + ip = ticket.getIP() + #lastTime = ticket.getTime() + lastTime = time.time() + banTicket = BanTicket(ip, lastTime) + banTicket.setAttempt(ticket.getAttempt()) + return banTicket + finally: + self.lock.release() ## # Add a ban ticket. @@ -113,14 +129,15 @@ class BanManager: # @return True if the IP address is not in the ban list def addBanTicket(self, ticket): - self.lock.acquire() - if not self.inBanList(ticket): - self.banList.append(ticket) - self.banTotal += 1 + try: + self.lock.acquire() + if not self.inBanList(ticket): + self.banList.append(ticket) + self.banTotal += 1 + return True + return False + finally: self.lock.release() - return True - self.lock.release() - return False ## # Delete a ban ticket. @@ -128,7 +145,7 @@ class BanManager: # Remove a BanTicket from the ban list. # @param ticket the ticket - def delBanTicket(self, ticket): + def __delBanTicket(self, ticket): self.banList.remove(ticket) ## @@ -137,7 +154,11 @@ class BanManager: # @return the size def size(self): - return len(self.banList) + try: + self.lock.acquire() + return len(self.banList) + finally: + self.lock.release() ## # Check if a ticket is in the list. @@ -148,10 +169,14 @@ class BanManager: # @return True if a ticket already exists def inBanList(self, ticket): - for i in self.banList: - if ticket.getIP() == i.getIP(): - return True - return False + try: + self.lock.acquire() + for i in self.banList: + if ticket.getIP() == i.getIP(): + return True + return False + finally: + self.lock.release() ## # Get the list of IP address to unban. @@ -162,14 +187,16 @@ class BanManager: # @todo Check the delete operation def unBanList(self, time): - uBList = list() - self.lock.acquire() - for ticket in self.banList: - if ticket.getTime() < time - self.banTime: - uBList.append(ticket) - self.delBanTicket(ticket) - self.lock.release() - return uBList + try: + self.lock.acquire() + uBList = list() + for ticket in self.banList: + if ticket.getTime() < time - self.banTime: + uBList.append(ticket) + self.__delBanTicket(ticket) + return uBList + finally: + self.lock.release() ## # Flush the ban list. @@ -178,9 +205,10 @@ class BanManager: # @return the complete ban list def flushBanList(self): - self.lock.acquire() - uBList = self.banList - self.banList = list() - self.lock.release() - return uBList - \ No newline at end of file + try: + self.lock.acquire() + uBList = self.banList + self.banList = list() + return uBList + finally: + self.lock.release() diff --git a/server/failmanager.py b/server/failmanager.py index 18ea5a86..46dbe258 100644 --- a/server/failmanager.py +++ b/server/failmanager.py @@ -42,22 +42,40 @@ class FailManager: self.failTotal = 0 def setFailTotal(self, value): + self.lock.acquire() self.failTotal = value + self.lock.release() def getFailTotal(self): - return self.failTotal + try: + self.lock.acquire() + return self.failTotal + finally: + self.lock.release() def setMaxRetry(self, value): + self.lock.acquire() self.maxRetry = value + self.lock.release() def getMaxRetry(self): - return self.maxRetry + try: + self.lock.acquire() + return self.maxRetry + finally: + self.lock.release() def setMaxTime(self, value): + self.lock.acquire() self.maxTime = value + self.lock.release() def getMaxTime(self): - return self.maxTime + try: + self.lock.acquire() + return self.maxTime + finally: + self.lock.release() def addFailure(self, ticket): self.lock.acquire() @@ -76,33 +94,38 @@ class FailManager: self.lock.release() def size(self): - return len(self.failList) + try: + self.lock.acquire() + return len(self.failList) + finally: + self.lock.release() def cleanup(self, time): self.lock.acquire() tmp = self.failList.copy() for item in tmp: if tmp[item].getLastTime() < time - self.maxTime: - self.delFailure(item) + self.__delFailure(item) self.lock.release() - def delFailure(self, ip): + def __delFailure(self, ip): if self.failList.has_key(ip): del self.failList[ip] def toBan(self): - self.lock.acquire() - for ip in self.failList: - data = self.failList[ip] - if data.getRetry() >= self.maxRetry: - self.delFailure(ip) - self.lock.release() - # Create a FailTicket from BanData - failTicket = FailTicket(ip, data.getLastTime()) - failTicket.setAttempt(data.getRetry()) - return failTicket - self.lock.release() - raise FailManagerEmpty + try: + self.lock.acquire() + for ip in self.failList: + data = self.failList[ip] + if data.getRetry() >= self.maxRetry: + self.delFailure(ip) + # Create a FailTicket from BanData + failTicket = FailTicket(ip, data.getLastTime()) + failTicket.setAttempt(data.getRetry()) + return failTicket + raise FailManagerEmpty + finally: + self.lock.release() class FailManagerEmpty(Exception): pass diff --git a/server/jail.py b/server/jail.py index d5f11671..b48dea20 100644 --- a/server/jail.py +++ b/server/jail.py @@ -27,6 +27,7 @@ __license__ = "GPL" import Queue, logging from actions import Actions +from threading import Lock # Gets the instance of the logger. logSys = logging.getLogger("fail2ban.jail") @@ -34,6 +35,7 @@ logSys = logging.getLogger("fail2ban.jail") class Jail: def __init__(self, name): + self.lock = Lock() self.name = name self.queue = Queue.Queue() try: @@ -48,58 +50,99 @@ class Jail: self.action = Actions(self) def setName(self, name): + self.lock.acquire() self.name = name + self.lock.release() def getName(self): - return self.name + try: + self.lock.acquire() + return self.name + finally: + self.lock.release() def setFilter(self, filter): + self.lock.acquire() self.filter = filter + self.lock.release() def getFilter(self): - return self.filter + try: + self.lock.acquire() + return self.filter + finally: + self.lock.release() def setAction(self, action): + self.lock.acquire() self.action = action + self.lock.release() def getAction(self): - return self.action + try: + self.lock.acquire() + return self.action + finally: + self.lock.release() def putFailTicket(self, ticket): + self.lock.acquire() self.queue.put(ticket) + self.lock.release() def getFailTicket(self): try: - return self.queue.get(False) - except Queue.Empty: - return False + try: + self.lock.acquire() + return self.queue.get(False) + except Queue.Empty: + return False + finally: + self.lock.release() def start(self): + self.lock.acquire() self.filter.start() self.action.start() + self.lock.release() def stop(self): + self.lock.acquire() self.filter.stop() self.action.stop() + self.lock.release() self.filter.join() self.action.join() def isActive(self): - isActive0 = self.filter.isActive() - isActive1 = self.action.isActive() - return isActive0 or isActive1 + try: + self.lock.acquire() + isActive0 = self.filter.isActive() + isActive1 = self.action.isActive() + return isActive0 or isActive1 + finally: + self.lock.release() def setIdle(self, value): + self.lock.acquire() self.filter.setIdle(value) self.action.setIdle(value) + self.lock.release() def getIdle(self): - return self.filter.getIdle() or self.action.getIdle() + try: + self.lock.acquire() + return self.filter.getIdle() or self.action.getIdle() + finally: + self.lock.release() def getStatus(self): - fStatus = self.filter.status() - aStatus = self.action.status() - ret = [("filter", fStatus), - ("action", aStatus)] - return ret - \ No newline at end of file + try: + self.lock.acquire() + fStatus = self.filter.status() + aStatus = self.action.status() + ret = [("filter", fStatus), + ("action", aStatus)] + return ret + finally: + self.lock.release() diff --git a/server/transmitter.py b/server/transmitter.py index c01c0e7f..07132875 100644 --- a/server/transmitter.py +++ b/server/transmitter.py @@ -26,6 +26,7 @@ __license__ = "GPL" from ssocket import SSocket from ssocket import SSocketErrorException +from threading import Lock import re, pickle, logging # Gets the instance of the logger. @@ -34,6 +35,7 @@ logSys = logging.getLogger("fail2ban.comm") class Transmitter: def __init__(self, server): + self.lock = Lock() self.server = server self.socket = SSocket(self) @@ -44,11 +46,14 @@ class Transmitter: def start(self, force): try: + self.lock.acquire() self.socket.initialize(force) self.socket.start() + self.lock.release() self.socket.join() except SSocketErrorException: logSys.error("Could not start server") + self.lock.release() ## # Stop the transmitter. @@ -58,18 +63,22 @@ class Transmitter: def stop(self): self.socket.stop() - #self.socket.join() + self.socket.join() def proceed(self, action): # Deserialize object - logSys.debug("Action: " + `action`) try: - ret = self.actionHandler(action) - ack = 0, ret - except Exception, e: - logSys.warn("Invalid command: " + `action`) - ack = 1, e - return ack + self.lock.acquire() + logSys.debug("Action: " + `action`) + try: + ret = self.actionHandler(action) + ack = 0, ret + except Exception, e: + logSys.warn("Invalid command: " + `action`) + ack = 1, e + return ack + finally: + self.lock.release() ## # Handle an action. @@ -129,6 +138,14 @@ class Transmitter: self.server.setIdleJail(name, False) return self.server.getIdleJail(name) # Filter + elif action[1] == "addignoreip": + value = action[2] + self.server.addIgnoreIP(name, value) + return self.server.getIgnoreIP(name) + elif action[1] == "delignoreip": + value = action[2] + self.server.delIgnoreIP(name, value) + return self.server.getIgnoreIP(name) elif action[1] == "addlogpath": value = action[2:] for path in value: @@ -217,8 +234,13 @@ class Transmitter: # Logging if name == "loglevel": return self.server.getLogLevel() + elif name == "logtarget": + return self.server.getLogTarget() + # Filter elif action[1] == "logpath": return self.server.getLogPath(name) + elif action[1] == "ignoreip": + return self.server.getIgnoreIP(name) elif action[1] == "timeregex": return self.server.getTimeRegex(name) elif action[1] == "timepattern": @@ -231,7 +253,7 @@ class Transmitter: return self.server.getFindTime(name) elif action[1] == "maxretry": return self.server.getMaxRetry(name) - # Filter + # Action elif action[1] == "bantime": return self.server.getBanTime(name) elif action[1] == "addaction":