diff --git a/server/jail.py b/server/jail.py
index 31d2a419..00d0b96c 100644
--- a/server/jail.py
+++ b/server/jail.py
@@ -27,7 +27,6 @@ __license__ = "GPL"
import Queue, logging
from actions import Actions
-from threading import Lock
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.jail")
@@ -35,7 +34,6 @@ logSys = logging.getLogger("fail2ban.jail")
class Jail:
def __init__(self, name, backend = "auto"):
- self.__lock = Lock()
self.__name = name
self.__queue = Queue.Queue()
self.__filter = None
@@ -61,89 +59,51 @@ class Jail:
self.__filter = FilterGamin(self)
def setName(self, name):
- self.__lock.acquire()
self.__name = name
- self.__lock.release()
def getName(self):
- try:
- self.__lock.acquire()
- return self.__name
- finally:
- self.__lock.release()
+ return self.__name
def getFilter(self):
- try:
- self.__lock.acquire()
- return self.__filter
- finally:
- self.__lock.release()
+ return self.__filter
def getAction(self):
- try:
- self.__lock.acquire()
- return self.__action
- finally:
- self.__lock.release()
+ return self.__action
def putFailTicket(self, ticket):
- self.__lock.acquire()
self.__queue.put(ticket)
- self.__lock.release()
def getFailTicket(self):
try:
- self.__lock.acquire()
- try:
- return self.__queue.get(False)
- except Queue.Empty:
- return False
- finally:
- self.__lock.release()
+ return self.__queue.get(False)
+ except Queue.Empty:
+ return False
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):
- try:
- self.__lock.acquire()
- isActive0 = self.__filter.isActive()
- isActive1 = self.__action.isActive()
- return isActive0 or isActive1
- finally:
- self.__lock.release()
+ isActive0 = self.__filter.isActive()
+ isActive1 = self.__action.isActive()
+ return isActive0 or isActive1
def setIdle(self, value):
- self.__lock.acquire()
self.__filter.setIdle(value)
self.__action.setIdle(value)
- self.__lock.release()
def getIdle(self):
- try:
- self.__lock.acquire()
- return self.__filter.getIdle() or self.__action.getIdle()
- finally:
- self.__lock.release()
+ return self.__filter.getIdle() or self.__action.getIdle()
def getStatus(self):
- try:
- self.__lock.acquire()
- fStatus = self.__filter.status()
- aStatus = self.__action.status()
- ret = [("filter", fStatus),
- ("action", aStatus)]
- return ret
- finally:
- self.__lock.release()
+ fStatus = self.__filter.status()
+ aStatus = self.__action.status()
+ ret = [("filter", fStatus),
+ ("action", aStatus)]
+ return ret
diff --git a/server/jails.py b/server/jails.py
index 8ae2ab67..6a327e1c 100644
--- a/server/jails.py
+++ b/server/jails.py
@@ -28,29 +28,63 @@ __license__ = "GPL"
from jail import Jail
from threading import Lock
+##
+# Handles the jails.
+#
+# This class handles the jails. Creation, deletion or access to a jail must be
+# done through this class. This class is thread-safe which is not the case of
+# the jail itself, including filter and actions.
+
class Jails:
+ ##
+ # Constructor.
+
def __init__(self):
self.__lock = Lock()
self.__jails = dict()
+ ##
+ # Adds a jail.
+ #
+ # Adds a new jail which should use the given backend. Raises a
+ # DuplicateJailException
if the jail is already defined.
+ # @param name The name of the jail
+ # @param backend The backend to use
+
def add(self, name, backend):
- self.__lock.acquire()
- if self.__jails.has_key(name):
- self.__lock.release()
- raise DuplicateJailException(name)
- else:
- self.__jails[name] = Jail(name, backend)
+ try:
+ self.__lock.acquire()
+ if self.__jails.has_key(name):
+ raise DuplicateJailException(name)
+ else:
+ self.__jails[name] = Jail(name, backend)
+ finally:
self.__lock.release()
+ ##
+ # Removes a jail.
+ #
+ # Removes the jail name
. Raise an UnknownJailException
+ # if the jail does not exist.
+ # @param name The name of the jail
+
def remove(self, name):
- self.__lock.acquire()
- if self.__jails.has_key(name):
- del self.__jails[name]
+ try:
+ self.__lock.acquire()
+ if self.__jails.has_key(name):
+ del self.__jails[name]
+ else:
+ raise UnknownJailException(name)
+ finally:
self.__lock.release()
- else:
- self.__lock.release()
- raise UnknownJailException(name)
+
+ ##
+ # Returns a jail.
+ #
+ # Returns the jail name
. Raise an UnknownJailException
+ # if the jail does not exist.
+ # @param name The name of the jail
def get(self, name):
try:
@@ -63,6 +97,13 @@ class Jails:
finally:
self.__lock.release()
+ ##
+ # Returns an action class instance.
+ #
+ # Returns the action object of the jail name
. Raise an
+ # UnknownJailException
if the jail does not exist.
+ # @param name The name of the jail
+
def getAction(self, name):
try:
self.__lock.acquire()
@@ -74,6 +115,13 @@ class Jails:
finally:
self.__lock.release()
+ ##
+ # Returns a filter class instance.
+ #
+ # Returns the filter object of the jail name
. Raise an
+ # UnknownJailException
if the jail does not exist.
+ # @param name The name of the jail
+
def getFilter(self, name):
try:
self.__lock.acquire()
@@ -85,6 +133,11 @@ class Jails:
finally:
self.__lock.release()
+ ##
+ # Returns the jails.
+ #
+ # Returns a copy of the jails list.
+
def getAll(self):
try:
self.__lock.acquire()
@@ -92,6 +145,11 @@ class Jails:
finally:
self.__lock.release()
+ ##
+ # Returns the size of the jails.
+ #
+ # Returns the number of jails.
+
def size(self):
try:
self.__lock.acquire()
diff --git a/server/server.py b/server/server.py
index af995f54..88099335 100644
--- a/server/server.py
+++ b/server/server.py
@@ -24,6 +24,7 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
+from threading import Lock, RLock
from jails import Jails
from transmitter import Transmitter
from ssocket import SSocket
@@ -36,6 +37,8 @@ logSys = logging.getLogger("fail2ban.server")
class Server:
def __init__(self, daemon = False):
+ self.__loggingLock = Lock()
+ self.__lock = RLock()
self.__jails = Jails()
self.__daemon = daemon
self.__transm = Transmitter(self)
@@ -91,17 +94,29 @@ class Server:
self.__jails.remove(name)
def startJail(self, name):
- if not self.isActive(name):
- self.__jails.get(name).start()
+ try:
+ self.__lock.acquire()
+ if not self.isActive(name):
+ self.__jails.get(name).start()
+ finally:
+ self.__lock.release()
def stopJail(self, name):
- if self.isActive(name):
- self.__jails.get(name).stop()
- self.delJail(name)
+ try:
+ self.__lock.acquire()
+ if self.isActive(name):
+ self.__jails.get(name).stop()
+ self.delJail(name)
+ finally:
+ self.__lock.release()
def stopAllJail(self):
- for jail in self.__jails.getAll():
- self.stopJail(jail)
+ try:
+ self.__lock.acquire()
+ for jail in self.__jails.getAll():
+ self.stopJail(jail)
+ finally:
+ self.__lock.release()
def isActive(self, name):
return self.__jails.get(name).isActive()
@@ -225,15 +240,19 @@ class Server:
# Status
def status(self):
- jailList = ''
- for jail in self.__jails.getAll():
- jailList += jail + ', '
- length = len(jailList)
- if not length == 0:
- jailList = jailList[:length-2]
- ret = [("Number of jail", self.__jails.size()),
- ("Jail list", jailList)]
- return ret
+ try:
+ self.__lock.acquire()
+ jailList = ''
+ for jail in self.__jails.getAll():
+ jailList += jail + ', '
+ length = len(jailList)
+ if not length == 0:
+ jailList = jailList[:length-2]
+ ret = [("Number of jail", self.__jails.size()),
+ ("Jail list", jailList)]
+ return ret
+ finally:
+ self.__lock.release()
def statusJail(self, name):
return self.__jails.get(name).getStatus()
@@ -252,17 +271,21 @@ class Server:
# @param value the level
def setLogLevel(self, value):
- self.__logLevel = value
- logLevel = logging.DEBUG
- if value == 0:
- logLevel = logging.FATAL
- elif value == 1:
- logLevel = logging.ERROR
- elif value == 2:
- logLevel = logging.WARNING
- elif value == 3:
- logLevel = logging.INFO
- logging.getLogger("fail2ban").setLevel(logLevel)
+ try:
+ self.__loggingLock.acquire()
+ self.__logLevel = value
+ logLevel = logging.DEBUG
+ if value == 0:
+ logLevel = logging.FATAL
+ elif value == 1:
+ logLevel = logging.ERROR
+ elif value == 2:
+ logLevel = logging.WARNING
+ elif value == 3:
+ logLevel = logging.INFO
+ logging.getLogger("fail2ban").setLevel(logLevel)
+ finally:
+ self.__loggingLock.release()
##
# Get the logging level.
@@ -271,35 +294,47 @@ class Server:
# @return the log level
def getLogLevel(self):
- return self.__logLevel
+ try:
+ self.__loggingLock.acquire()
+ return self.__logLevel
+ finally:
+ self.__loggingLock.release()
def setLogTarget(self, target):
- # Remove previous handler
- logging.getLogger("fail2ban").handlers = []
- self.__logTarget = target
- if target == "SYSLOG":
- hdlr = logging.handlers.SysLogHandler()
- elif target == "STDOUT":
- hdlr = logging.StreamHandler(sys.stdout)
- elif target == "STDERR":
- hdlr = logging.StreamHandler(sys.stderr)
- else:
- # Target should be a file
- try:
- open(target, "a")
- hdlr = logging.FileHandler(target)
- except IOError:
- logSys.error("Unable to log to " + target)
- return False
- # set a format which is simpler for console use
- formatter = logging.Formatter("%(asctime)s %(name)-16s: %(levelname)-6s %(message)s")
- # tell the handler to use this format
- hdlr.setFormatter(formatter)
- logging.getLogger("fail2ban").addHandler(hdlr)
- return True
+ try:
+ self.__loggingLock.acquire()
+ # Remove previous handler
+ logging.getLogger("fail2ban").handlers = []
+ if target == "SYSLOG":
+ hdlr = logging.handlers.SysLogHandler()
+ elif target == "STDOUT":
+ hdlr = logging.StreamHandler(sys.stdout)
+ elif target == "STDERR":
+ hdlr = logging.StreamHandler(sys.stderr)
+ else:
+ # Target should be a file
+ try:
+ open(target, "a")
+ hdlr = logging.FileHandler(target)
+ except IOError:
+ logSys.error("Unable to log to " + target)
+ return False
+ self.__logTarget = target
+ # set a format which is simpler for console use
+ formatter = logging.Formatter("%(asctime)s %(name)-16s: %(levelname)-6s %(message)s")
+ # tell the handler to use this format
+ hdlr.setFormatter(formatter)
+ logging.getLogger("fail2ban").addHandler(hdlr)
+ return True
+ finally:
+ self.__loggingLock.release()
def getLogTarget(self):
- return self.__logTarget
+ try:
+ self.__loggingLock.acquire()
+ return self.__logTarget
+ finally:
+ self.__loggingLock.release()
def __createDaemon(self):
""" Detach a process from the controlling terminal and run it in the
diff --git a/server/transmitter.py b/server/transmitter.py
index 64ad3919..f6051597 100644
--- a/server/transmitter.py
+++ b/server/transmitter.py
@@ -24,7 +24,6 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
-from threading import Lock
import logging, time
# Gets the instance of the logger.
@@ -32,229 +31,235 @@ logSys = logging.getLogger("fail2ban.comm")
class Transmitter:
+ ##
+ # Constructor.
+ #
+ # @param The server reference
+
def __init__(self, server):
- self.__lock = Lock()
self.__server = server
- def proceed(self, action):
+ ##
+ # Proceeds a command.
+ #
+ # Proceeds an incoming command.
+ # @param command The incoming command
+
+ def proceed(self, command):
# Deserialize object
+ logSys.debug("Command: " + `command`)
try:
- 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()
+ ret = self.__commandHandler(command)
+ ack = 0, ret
+ except Exception, e:
+ logSys.warn("Invalid command: " + `command`)
+ ack = 1, e
+ return ack
##
- # Handle an action.
+ # Handle an command.
#
#
- def __actionHandler(self, action):
- if action[0] == "ping":
+ def __commandHandler(self, command):
+ if command[0] == "ping":
return "pong"
- elif action[0] == "add":
- name = action[1]
+ elif command[0] == "add":
+ name = command[1]
if name == "all":
raise Exception("Reserved name")
try:
- backend = action[2]
+ backend = command[2]
except IndexError:
backend = "auto"
self.__server.addJail(name, backend)
return name
- elif action[0] == "start":
- name = action[1]
+ elif command[0] == "start":
+ name = command[1]
self.__server.startJail(name)
return None
- elif action[0] == "stop":
- if len(action) == 1:
+ elif command[0] == "stop":
+ if len(command) == 1:
self.__server.quit()
- elif action[1] == "all":
+ elif command[1] == "all":
self.__server.stopAllJail()
else:
- name = action[1]
+ name = command[1]
self.__server.stopJail(name)
return None
- elif action[0] == "sleep":
- value = action[1]
+ elif command[0] == "sleep":
+ value = command[1]
time.sleep(int(value))
return None
- elif action[0] == "set":
- return self.__actionSet(action[1:])
- elif action[0] == "get":
- return self.__actionGet(action[1:])
- elif action[0] == "status":
- return self.status(action[1:])
+ elif command[0] == "set":
+ return self.__commandSet(command[1:])
+ elif command[0] == "get":
+ return self.__commandGet(command[1:])
+ elif command[0] == "status":
+ return self.status(command[1:])
raise Exception("Invalid command")
- def __actionSet(self, action):
- name = action[0]
+ def __commandSet(self, command):
+ name = command[0]
# Logging
if name == "loglevel":
- value = int(action[1])
+ value = int(command[1])
self.__server.setLogLevel(value)
return self.__server.getLogLevel()
elif name == "logtarget":
- value = action[1]
+ value = command[1]
self.__server.setLogTarget(value)
return self.__server.getLogTarget()
# Jail
- elif action[1] == "idle":
- if action[2] == "on":
+ elif command[1] == "idle":
+ if command[2] == "on":
self.__server.setIdleJail(name, True)
- elif action[2] == "off":
+ elif command[2] == "off":
self.__server.setIdleJail(name, False)
return self.__server.getIdleJail(name)
# Filter
- elif action[1] == "addignoreip":
- value = action[2]
+ elif command[1] == "addignoreip":
+ value = command[2]
self.__server.addIgnoreIP(name, value)
return self.__server.getIgnoreIP(name)
- elif action[1] == "delignoreip":
- value = action[2]
+ elif command[1] == "delignoreip":
+ value = command[2]
self.__server.delIgnoreIP(name, value)
return self.__server.getIgnoreIP(name)
- elif action[1] == "addlogpath":
- value = action[2:]
+ elif command[1] == "addlogpath":
+ value = command[2:]
for path in value:
self.__server.addLogPath(name, path)
return self.__server.getLogPath(name)
- elif action[1] == "dellogpath":
- value = action[2]
+ elif command[1] == "dellogpath":
+ value = command[2]
self.__server.delLogPath(name, value)
return self.__server.getLogPath(name)
- elif action[1] == "timeregex":
- value = action[2]
+ elif command[1] == "timeregex":
+ value = command[2]
self.__server.setTimeRegex(name, value)
return self.__server.getTimeRegex(name)
- elif action[1] == "timepattern":
- value = action[2]
+ elif command[1] == "timepattern":
+ value = command[2]
self.__server.setTimePattern(name, value)
return self.__server.getTimePattern(name)
- elif action[1] == "failregex":
- value = action[2]
+ elif command[1] == "failregex":
+ value = command[2]
self.__server.setFailRegex(name, value)
return self.__server.getFailRegex(name)
- elif action[1] == "maxtime":
- value = action[2]
+ elif command[1] == "maxtime":
+ value = command[2]
self.__server.setMaxTime(name, int(value))
return self.__server.getMaxTime(name)
- elif action[1] == "findtime":
- value = action[2]
+ elif command[1] == "findtime":
+ value = command[2]
self.__server.setFindTime(name, int(value))
return self.__server.getFindTime(name)
- elif action[1] == "maxretry":
- value = action[2]
+ elif command[1] == "maxretry":
+ value = command[2]
self.__server.setMaxRetry(name, int(value))
return self.__server.getMaxRetry(name)
- # Action
- elif action[1] == "bantime":
- value = action[2]
+ # command
+ elif command[1] == "bantime":
+ value = command[2]
self.__server.setBanTime(name, int(value))
return self.__server.getBanTime(name)
- elif action[1] == "addaction":
- value = action[2]
+ elif command[1] == "addaction":
+ value = command[2]
self.__server.addAction(name, value)
- return self.__server.getLastAction(name).getName()
- elif action[1] == "delaction":
+ return self.__server.getLastcommand(name).getName()
+ elif command[1] == "delaction":
self.__server.delAction(name, value)
return None
- elif action[1] == "setcinfo":
- act = action[2]
- key = action[3]
- value = action[4]
+ elif command[1] == "setcinfo":
+ act = command[2]
+ key = command[3]
+ value = command[4]
self.__server.setCInfo(name, act, key, value)
return self.__server.getCInfo(name, act, key)
- elif action[1] == "delcinfo":
- act = action[2]
- key = action[3]
+ elif command[1] == "delcinfo":
+ act = command[2]
+ key = command[3]
self.__server.delCInfo(name, act, key)
return None
- elif action[1] == "actionstart":
- act = action[2]
- value = action[3]
+ elif command[1] == "actionstart":
+ act = command[2]
+ value = command[3]
self.__server.setActionStart(name, act, value)
return self.__server.getActionStart(name, act)
- elif action[1] == "actionstop":
- act = action[2]
- value = action[3]
+ elif command[1] == "actionstop":
+ act = command[2]
+ value = command[3]
self.__server.setActionStop(name, act, value)
return self.__server.getActionStop(name, act)
- elif action[1] == "actioncheck":
- act = action[2]
- value = action[3]
+ elif command[1] == "actioncheck":
+ act = command[2]
+ value = command[3]
self.__server.setActionCheck(name, act, value)
return self.__server.getActionCheck(name, act)
- elif action[1] == "actionban":
- act = action[2]
- value = action[3]
+ elif command[1] == "actionban":
+ act = command[2]
+ value = command[3]
self.__server.setActionBan(name, act, value)
return self.__server.getActionBan(name, act)
- elif action[1] == "actionunban":
- act = action[2]
- value = action[3]
+ elif command[1] == "actionunban":
+ act = command[2]
+ value = command[3]
self.__server.setActionUnban(name, act, value)
return self.__server.getActionUnban(name, act)
raise Exception("Invalid command (no set action or not yet implemented)")
- def __actionGet(self, action):
- name = action[0]
+ def __commandGet(self, command):
+ name = command[0]
# Logging
if name == "loglevel":
return self.__server.getLogLevel()
elif name == "logtarget":
return self.__server.getLogTarget()
# Filter
- elif action[1] == "logpath":
+ elif command[1] == "logpath":
return self.__server.getLogPath(name)
- elif action[1] == "ignoreip":
+ elif command[1] == "ignoreip":
return self.__server.getIgnoreIP(name)
- elif action[1] == "timeregex":
+ elif command[1] == "timeregex":
return self.__server.getTimeRegex(name)
- elif action[1] == "timepattern":
+ elif command[1] == "timepattern":
return self.__server.getTimePattern(name)
- elif action[1] == "failregex":
+ elif command[1] == "failregex":
return self.__server.getFailRegex(name)
- elif action[1] == "maxtime":
+ elif command[1] == "maxtime":
return self.__server.getMaxTime(name)
- elif action[1] == "findtime":
+ elif command[1] == "findtime":
return self.__server.getFindTime(name)
- elif action[1] == "maxretry":
+ elif command[1] == "maxretry":
return self.__server.getMaxRetry(name)
# Action
- elif action[1] == "bantime":
+ elif command[1] == "bantime":
return self.__server.getBanTime(name)
- elif action[1] == "addaction":
+ elif command[1] == "addaction":
return self.__server.getLastAction(name).getName()
- elif action[1] == "actionstart":
- act = action[2]
+ elif command[1] == "actionstart":
+ act = command[2]
return self.__server.getActionStart(name, act)
- elif action[1] == "actionstop":
- act = action[2]
+ elif command[1] == "actionstop":
+ act = command[2]
return self.__server.getActionStop(name, act)
- elif action[1] == "actioncheck":
- act = action[2]
+ elif command[1] == "actioncheck":
+ act = command[2]
return self.__server.getActionCheck(name, act)
- elif action[1] == "actionban":
- act = action[2]
+ elif command[1] == "actionban":
+ act = command[2]
return self.__server.getActionBan(name, act)
- elif action[1] == "actionunban":
- act = action[2]
+ elif command[1] == "actionunban":
+ act = command[2]
return self.__server.getActionUnban(name, act)
raise Exception("Invalid command (no get action or not yet implemented)")
- def status(self, action):
- if len(action) == 0:
+ def status(self, command):
+ if len(command) == 0:
return self.__server.status()
else:
- name = action[0]
+ name = command[0]
return self.__server.statusJail(name)
raise Exception("Invalid command (no status)")
\ No newline at end of file