- Improved synchronization

git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@452 a942ae1a-1317-0410-a47c-b1dcaea8d605
0.x
Cyril Jaquier 2006-11-06 22:48:46 +00:00
parent 7659452ade
commit cdf5ae19db
4 changed files with 292 additions and 234 deletions

View File

@ -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

View File

@ -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
# <code>DuplicateJailException</code> 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 <code>name</code>. Raise an <code>UnknownJailException</code>
# 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 <code>name</code>. Raise an <code>UnknownJailException</code>
# 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 <code>name</code>. Raise an
# <code>UnknownJailException</code> 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 <code>name</code>. Raise an
# <code>UnknownJailException</code> 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()

View File

@ -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

View File

@ -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)")