RF: Change Jails and Actions to Mapping types

pull/549/head
Steven Hiscocks 2014-01-04 16:57:08 +00:00
parent a070284a18
commit 6e63f0ea5a
12 changed files with 332 additions and 373 deletions

View File

@ -103,7 +103,7 @@ class SMTPAction(ActionBase):
self.message_values = CallingMap(
jailname = self._jail.getName(), # Doesn't change
hostname = socket.gethostname,
bantime = self._jail.getAction().getBanTime,
bantime = self._jail.actions.getBanTime,
)
def _sendMessage(self, subject, text):

View File

@ -29,7 +29,7 @@ __license__ = "GPL"
class DuplicateJailException(Exception):
pass
class UnknownJailException(Exception):
class UnknownJailException(KeyError):
pass

View File

@ -102,7 +102,6 @@ protocol = [
["get <JAIL> usedns", "gets the usedns setting for <JAIL>"],
["get <JAIL> maxretry", "gets the number of failures allowed for <JAIL>"],
["get <JAIL> maxlines", "gets the number of lines to buffer for <JAIL>"],
["get <JAIL> addaction", "gets the last action which has been added for <JAIL>"],
["get <JAIL> actions", "gets a list of actions for <JAIL>"],
["", "COMMAND ACTION INFORMATION",""],
["get <JAIL> action <ACT> actionstart", "gets the start command for the action <ACT> for <JAIL>"],

View File

@ -79,12 +79,11 @@ class ActionBase(object):
place to create a python based action for fail2ban. This class can
be inherited from to ease implementation, but is not required as
long as the following required methods/properties are implemented:
- __init__(jail, actionname)
- __init__(jail, name)
- start()
- stop()
- ban(aInfo)
- unban(aInfo)
- actionname
"""
__metaclass__ = ABCMeta
@ -101,23 +100,17 @@ class ActionBase(object):
return False
return True
def __init__(self, jail, actionname):
def __init__(self, jail, name):
"""Should initialise the action class with `jail` being the Jail
object the action belongs to, `actionname` being the name assigned
object the action belongs to, `name` being the name assigned
to the action, and `kwargs` being all other args that have been
specified with jail.conf or on the fail2ban-client.
"""
self._jail = jail
self._actionname = actionname
self._name = name
self._logSys = logging.getLogger(
'%s.%s' % (__name__, self.__class__.__name__))
@property
def actionname(self):
"""The name of the action, which should not change in the
lifetime of the action."""
return self._actionname
def start(self):
"""Executed when the jail/action starts."""
pass
@ -144,8 +137,8 @@ class CommandAction(ActionBase):
Fail2Ban uses.
"""
def __init__(self, jail, actionname):
super(CommandAction, self).__init__(jail, actionname)
def __init__(self, jail, name):
super(CommandAction, self).__init__(jail, name)
self.timeout = 60
## Command executed in order to initialize the system.
self.actionstart = ''
@ -172,7 +165,7 @@ class CommandAction(ActionBase):
def timeout(self, timeout):
self._timeout = int(timeout)
self._logSys.debug("Set action %s timeout = %i" %
(self.actionname, self.timeout))
(self._name, self.timeout))
@property
def _properties(self):

View File

@ -27,6 +27,7 @@ __license__ = "GPL"
import time, logging
import os
import imp
from collections import Mapping
from .banmanager import BanManager
from .jailthread import JailThread
@ -36,40 +37,61 @@ from .mytime import MyTime
# Gets the instance of the logger.
logSys = logging.getLogger(__name__)
##
# Execute commands.
#
# This class reads the failures from the Jail queue and decide if an
# action has to be taken. A BanManager take care of the banned IP
# addresses.
class Actions(JailThread, Mapping):
"""Handles jail actions.
This class handles the actions of the jail. Creation, deletion or to
actions must be done through this class. This class is based on the
Mapping type, and the `add` method must be used to add new actions.
This class also starts and stops the actions, and fetches bans from
the jail executing these bans via the actions.
"""
class Actions(JailThread):
##
# Constructor.
#
# Initialize the filter object with default values.
# @param jail the jail object
def __init__(self, jail):
"""Initialise an empty Actions instance.
Parameters
----------
jail: Jail
The jail of which the actions belongs to.
"""
JailThread.__init__(self)
## The jail which contains this action.
self.jail = jail
self.__actions = list()
self._jail = jail
self._actions = dict()
## The ban manager.
self.__banManager = BanManager()
##
# Adds an action.
#
# @param name The action name
def addAction(self, name, pythonModule=None, initOpts=None):
def add(self, name, pythonModule=None, initOpts=None):
"""Adds a new action.
Add a new action if not already present, defaulting to standard
`CommandAction`, or specified Python module.
Parameters
----------
name : str
The name of the action.
pythonModule : str
Path to Python file which must contain `Action` class.
initOpts : dict
Options for Python Action, used as keyword arguments for
initialisation.
Raises
------
ValueError
If action name already exists.
RuntimeError
If external Python module does not have `Action` class
or does not implement necessary methods as per `ActionBase`
abstract class.
"""
# Check is action name already exists
if name in [action.actionname for action in self.__actions]:
if name in self._actions:
raise ValueError("Action %s already exists" % name)
if pythonModule is None:
action = CommandAction(self.jail, name)
action = CommandAction(self._jail, name)
else:
pythonModuleName = os.path.basename(pythonModule.strip(".py"))
customActionModule = imp.load_source(
@ -79,53 +101,35 @@ class Actions(JailThread):
"%s module does not have 'Action' class" % pythonModule)
elif not issubclass(customActionModule.Action, ActionBase):
raise RuntimeError(
"%s module %s does not implment required methods" % (
"%s module %s does not implement required methods" % (
pythonModule, customActionModule.Action.__name__))
action = customActionModule.Action(self.jail, name, **initOpts)
self.__actions.append(action)
##
# Removes an action.
#
# @param name The action name
def delAction(self, name):
for action in self.__actions:
if action.actionname == name:
self.__actions.remove(action)
return
raise KeyError("Invalid Action name: %s" % name)
##
# Returns an action.
#
# Raises a KeyError exception if the action does not exist.
#
# @param name the action name
# @return the action
def getAction(self, name):
for action in self.__actions:
if action.actionname == name:
return action
raise KeyError("Invalid Action name")
##
# Returns the last defined action.
#
# @return The last defined action.
def getLastAction(self):
return self.__actions[-1]
##
# Returns the list of actions
#
# @return list of actions
def getActions(self):
return self.__actions
action = customActionModule.Action(self._jail, name, **initOpts)
self._actions[name] = action
def __getitem__(self, name):
try:
return self._actions[name]
except KeyError:
raise KeyError("Invalid Action name: %s" % name)
def __delitem__(self, name):
try:
del self._actions[name]
except KeyError:
raise KeyError("Invalid Action name: %s" % name)
def __iter__(self):
return iter(self._actions)
def __len__(self):
return len(self._actions)
def __eq__(self, other): # Required for Threading
return False
def __hash__(self): # Required for Threading
return id(self)
##
# Set the ban time.
#
@ -142,38 +146,52 @@ class Actions(JailThread):
def getBanTime(self):
return self.__banManager.getBanTime()
##
# Remove a banned IP now, rather than waiting for it to expire, even if set to never expire.
#
# @return the IP string or 'None' if not unbanned.
def removeBannedIP(self, ip):
"""Removes banned IP calling actions' unban method
Remove a banned IP now, rather than waiting for it to expire,
even if set to never expire.
Parameters
----------
ip : str
The IP address to unban
Raises
------
ValueError
If `ip` is not banned
"""
# Find the ticket with the IP.
ticket = self.__banManager.getTicketByIP(ip)
if ticket is not None:
# Unban the IP.
self.__unBan(ticket)
return ip
raise ValueError("IP %s is not banned" % ip)
else:
raise ValueError("IP %s is not banned" % ip)
##
# Main loop.
#
# This function is the main loop of the thread. It checks the Jail
# queue and executes commands when an IP address is banned.
# @return True when the thread exits nicely
def run(self):
"""Main loop for Threading.
This function is the main loop of the thread. It checks the jail
queue and executes commands when an IP address is banned.
Returns
-------
bool
True when the thread exits nicely.
"""
self.setActive(True)
for action in self.__actions:
for name, action in self._actions.iteritems():
try:
action.start()
except Exception as e:
logSys.error("Failed to start jail '%s' action '%s': %s",
self.jail.getName(), action.actionname, e)
self._jail.getName(), name, e)
while self._isActive():
if not self.getIdle():
#logSys.debug(self.jail.getName() + ": action")
#logSys.debug(self._jail.getName() + ": action")
ret = self.__checkBan()
if not ret:
self.__checkUnBan()
@ -181,24 +199,27 @@ class Actions(JailThread):
else:
time.sleep(self.getSleepTime())
self.__flushBan()
for action in self.__actions:
for name, action in self._actions.iteritems():
try:
action.stop()
except Exception as e:
logSys.error("Failed to stop jail '%s' action '%s': %s",
self.jail.getName(), action.actionname, e)
logSys.debug(self.jail.getName() + ": action terminated")
self._jail.getName(), name, e)
logSys.debug(self._jail.getName() + ": action terminated")
return True
##
# Check for IP address to ban.
#
# Look in the Jail queue for FailTicket. If a ticket is available,
# it executes the "ban" command and add a ticket to the BanManager.
# @return True if an IP address get banned
def __checkBan(self):
ticket = self.jail.getFailTicket()
"""Check for IP address to ban.
Look in the jail queue for FailTicket. If a ticket is available,
it executes the "ban" command and adds a ticket to the BanManager.
Returns
-------
bool
True if an IP address get banned.
"""
ticket = self._jail.getFailTicket()
if ticket != False:
aInfo = CallingMap()
bTicket = BanManager.createBanTicket(ticket)
@ -206,83 +227,88 @@ class Actions(JailThread):
aInfo["failures"] = bTicket.getAttempt()
aInfo["time"] = bTicket.getTime()
aInfo["matches"] = "\n".join(bTicket.getMatches())
if self.jail.getDatabase() is not None:
if self._jail.getDatabase() is not None:
aInfo["ipmatches"] = lambda: "\n".join(
self.jail.getDatabase().getBansMerged(
self._jail.getDatabase().getBansMerged(
ip=bTicket.getIP()).getMatches())
aInfo["ipjailmatches"] = lambda: "\n".join(
self.jail.getDatabase().getBansMerged(
ip=bTicket.getIP(), jail=self.jail).getMatches())
self._jail.getDatabase().getBansMerged(
ip=bTicket.getIP(), jail=self._jail).getMatches())
aInfo["ipfailures"] = lambda: "\n".join(
self.jail.getDatabase().getBansMerged(
self._jail.getDatabase().getBansMerged(
ip=bTicket.getIP()).getAttempt())
aInfo["ipjailfailures"] = lambda: "\n".join(
self.jail.getDatabase().getBansMerged(
ip=bTicket.getIP(), jail=self.jail).getAttempt())
self._jail.getDatabase().getBansMerged(
ip=bTicket.getIP(), jail=self._jail).getAttempt())
if self.__banManager.addBanTicket(bTicket):
logSys.warning("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"]))
for action in self.__actions:
logSys.warning("[%s] Ban %s" % (self._jail.getName(), aInfo["ip"]))
for name, action in self._actions.iteritems():
try:
action.ban(aInfo)
except Exception as e:
logSys.error(
"Failed to execute ban jail '%s' action '%s': %s",
self.jail.getName(), action.actionname, e)
self._jail.getName(), name, e)
return True
else:
logSys.info("[%s] %s already banned" % (self.jail.getName(),
logSys.info("[%s] %s already banned" % (self._jail.getName(),
aInfo["ip"]))
return False
##
# Check for IP address to unban.
#
# Unban IP address which are outdated.
def __checkUnBan(self):
"""Check for IP address to unban.
Unban IP addresses which are outdated.
"""
for ticket in self.__banManager.unBanList(MyTime.time()):
self.__unBan(ticket)
##
# Flush the ban list.
#
# Unban all IP address which are still in the banning list.
def __flushBan(self):
"""Flush the ban list.
Unban all IP address which are still in the banning list.
"""
logSys.debug("Flush ban list")
for ticket in self.__banManager.flushBanList():
self.__unBan(ticket)
##
# Unbans host corresponding to the ticket.
#
# Executes the actions in order to unban the host given in the
# ticket.
def __unBan(self, ticket):
"""Unbans host corresponding to the ticket.
Executes the actions in order to unban the host given in the
ticket.
Parameters
----------
ticket : FailTicket
Ticket of failures of which to unban
"""
aInfo = dict()
aInfo["ip"] = ticket.getIP()
aInfo["failures"] = ticket.getAttempt()
aInfo["time"] = ticket.getTime()
aInfo["matches"] = "".join(ticket.getMatches())
logSys.warning("[%s] Unban %s" % (self.jail.getName(), aInfo["ip"]))
for action in self.__actions:
logSys.warning("[%s] Unban %s" % (self._jail.getName(), aInfo["ip"]))
for name, action in self._actions.iteritems():
try:
action.unban(aInfo)
except Exception as e:
logSys.error(
"Failed to execute unban jail '%s' action '%s': %s",
self.jail.getName(), action.actionname, e)
##
# Get the status of the filter.
#
# Get some informations about the filter state such as the total
# number of failures.
# @return a list with tuple
self._jail.getName(), name, e)
def status(self):
"""Get the status of the filter.
Get some informations about the filter state such as the total
number of failures.
Returns
-------
list
List of tuple pairs, each containing a description and value
for general status information.
"""
ret = [("Currently banned", self.__banManager.size()),
("Total banned", self.__banManager.getBanTotal()),
("IP list", self.__banManager.getBanList())]

View File

@ -71,7 +71,7 @@ class Jail:
"%r was requested" % (b, backend))
else:
logSys.info("Initiated %r backend" % b)
self.__action = Actions(self)
self.__actions = Actions(self)
return # we are done
except ImportError, e:
logSys.debug(
@ -124,11 +124,17 @@ class Jail:
def getDatabase(self):
return self.__db
def getFilter(self):
@property
def filter(self):
"""The filter which the jail is using to monitor log files.
"""
return self.__filter
def getAction(self):
return self.__action
@property
def actions(self):
"""Actions object used to manage actions for jail.
"""
return self.__actions
def putFailTicket(self, ticket):
self.__queue.put(ticket)
@ -143,36 +149,36 @@ class Jail:
def start(self):
self.__filter.start()
self.__action.start()
self.__actions.start()
# Restore any previous valid bans from the database
if self.__db is not None:
for ticket in self.__db.getBans(
jail=self, bantime=self.__action.getBanTime()):
jail=self, bantime=self.__actions.getBanTime()):
self.__queue.put(ticket)
logSys.info("Jail '%s' started" % self.__name)
def stop(self):
self.__filter.stop()
self.__action.stop()
self.__actions.stop()
self.__filter.join()
self.__action.join()
self.__actions.join()
logSys.info("Jail '%s' stopped" % self.__name)
def isAlive(self):
isAlive0 = self.__filter.isAlive()
isAlive1 = self.__action.isAlive()
isAlive1 = self.__actions.isAlive()
return isAlive0 or isAlive1
def setIdle(self, value):
self.__filter.setIdle(value)
self.__action.setIdle(value)
self.__actions.setIdle(value)
def getIdle(self):
return self.__filter.getIdle() or self.__action.getIdle()
return self.__filter.getIdle() or self.__actions.getIdle()
def getStatus(self):
fStatus = self.__filter.status()
aStatus = self.__action.status()
aStatus = self.__actions.status()
ret = [("filter", fStatus),
("action", aStatus)]
return ret

View File

@ -22,136 +22,83 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko"
__license__ = "GPL"
from threading import Lock
from collections import Mapping
from ..exceptions import DuplicateJailException, UnknownJailException
from .jail import Jail
##
# 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.
class Jails(Mapping):
"""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. This
class is based on Mapping type, and the `add` method must be used to
add additional jails.
"""
def __init__(self):
"""Initialise an empty Jails instance.
"""
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
self._jails = dict()
def add(self, name, backend, db=None):
"""Adds a jail.
Adds a new jail if not already present which should use the
given backend.
Parameters
----------
name : str
The name of the jail.
backend : str
The backend to use.
Raises
------
DuplicateJailException
If jail name is already present.
"""
try:
self.__lock.acquire()
if self.__jails.has_key(name):
if name in self._jails:
raise DuplicateJailException(name)
else:
self.__jails[name] = Jail(name, backend, db)
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):
try:
self.__lock.acquire()
if self.__jails.has_key(name):
del self.__jails[name]
else:
raise UnknownJailException(name)
finally:
self.__lock.release()
##
# 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:
self.__lock.acquire()
if self.__jails.has_key(name):
jail = self.__jails[name]
return jail
else:
raise UnknownJailException(name)
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()
if self.__jails.has_key(name):
action = self.__jails[name].getAction()
return action
else:
raise UnknownJailException(name)
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()
if self.__jails.has_key(name):
action = self.__jails[name].getFilter()
return action
else:
raise UnknownJailException(name)
finally:
self.__lock.release()
##
# Returns the jails.
#
# Returns a copy of the jails list.
def getAll(self):
try:
self.__lock.acquire()
return self.__jails.copy()
finally:
self.__lock.release()
##
# Returns the size of the jails.
#
# Returns the number of jails.
def size(self):
try:
self.__lock.acquire()
return len(self.__jails)
self._jails[name] = Jail(name, backend, db)
finally:
self.__lock.release()
def __getitem__(self, name):
try:
self.__lock.acquire()
return self._jails[name]
except KeyError:
raise UnknownJailException(name)
finally:
self.__lock.release()
def __delitem__(self, name):
try:
self.__lock.acquire()
del self._jails[name]
except KeyError:
raise UnknownJailException(name)
finally:
self.__lock.release()
def __len__(self):
try:
self.__lock.acquire()
return len(self._jails)
finally:
self.__lock.release()
def __iter__(self):
try:
self.__lock.acquire()
return iter(self._jails)
finally:
self.__lock.release()

View File

@ -122,10 +122,10 @@ class Server:
def addJail(self, name, backend):
self.__jails.add(name, backend, self.__db)
if self.__db is not None:
self.__db.addJail(self.__jails.get(name))
self.__db.addJail(self.__jails[name])
def delJail(self, name):
self.__jails.remove(name)
del self.__jails[name]
if self.__db is not None:
self.__db.delJailName(name)
@ -133,7 +133,7 @@ class Server:
try:
self.__lock.acquire()
if not self.isAlive(name):
self.__jails.get(name).start()
self.__jails[name].start()
finally:
self.__lock.release()
@ -142,7 +142,7 @@ class Server:
try:
self.__lock.acquire()
if self.isAlive(name):
self.__jails.get(name).stop()
self.__jails[name].stop()
self.delJail(name)
finally:
self.__lock.release()
@ -151,43 +151,43 @@ class Server:
logSys.info("Stopping all jails")
try:
self.__lock.acquire()
for jail in self.__jails.getAll():
for jail in self.__jails.keys():
self.stopJail(jail)
finally:
self.__lock.release()
def isAlive(self, name):
return self.__jails.get(name).isAlive()
return self.__jails[name].isAlive()
def setIdleJail(self, name, value):
self.__jails.get(name).setIdle(value)
self.__jails[name].setIdle(value)
return True
def getIdleJail(self, name):
return self.__jails.get(name).getIdle()
return self.__jails[name].getIdle()
# Filter
def addIgnoreIP(self, name, ip):
self.__jails.getFilter(name).addIgnoreIP(ip)
self.__jails[name].filter.addIgnoreIP(ip)
def delIgnoreIP(self, name, ip):
self.__jails.getFilter(name).delIgnoreIP(ip)
self.__jails[name].filter.delIgnoreIP(ip)
def getIgnoreIP(self, name):
return self.__jails.getFilter(name).getIgnoreIP()
return self.__jails[name].filter.getIgnoreIP()
def addLogPath(self, name, fileName, tail=False):
filter_ = self.__jails.getFilter(name)
filter_ = self.__jails[name].filter
if isinstance(filter_, FileFilter):
filter_.addLogPath(fileName, tail)
def delLogPath(self, name, fileName):
filter_ = self.__jails.getFilter(name)
filter_ = self.__jails[name].filter
if isinstance(filter_, FileFilter):
filter_.delLogPath(fileName)
def getLogPath(self, name):
filter_ = self.__jails.getFilter(name)
filter_ = self.__jails[name].filter
if isinstance(filter_, FileFilter):
return [m.getFileName()
for m in filter_.getLogPath()]
@ -196,17 +196,17 @@ class Server:
return []
def addJournalMatch(self, name, match): # pragma: systemd no cover
filter_ = self.__jails.getFilter(name)
filter_ = self.__jails[name].filter
if isinstance(filter_, JournalFilter):
filter_.addJournalMatch(match)
def delJournalMatch(self, name, match): # pragma: systemd no cover
filter_ = self.__jails.getFilter(name)
filter_ = self.__jails[name].filter
if isinstance(filter_, JournalFilter):
filter_.delJournalMatch(match)
def getJournalMatch(self, name): # pragma: systemd no cover
filter_ = self.__jails.getFilter(name)
filter_ = self.__jails[name].filter
if isinstance(filter_, JournalFilter):
return filter_.getJournalMatch()
else:
@ -214,112 +214,109 @@ class Server:
return []
def setLogEncoding(self, name, encoding):
filter_ = self.__jails.getFilter(name)
filter_ = self.__jails[name].filter
if isinstance(filter_, FileFilter):
filter_.setLogEncoding(encoding)
def getLogEncoding(self, name):
filter_ = self.__jails.getFilter(name)
filter_ = self.__jails[name].filter
if isinstance(filter_, FileFilter):
return filter_.getLogEncoding()
def setFindTime(self, name, value):
self.__jails.getFilter(name).setFindTime(value)
self.__jails[name].filter.setFindTime(value)
def getFindTime(self, name):
return self.__jails.getFilter(name).getFindTime()
return self.__jails[name].filter.getFindTime()
def setDatePattern(self, name, pattern):
self.__jails.getFilter(name).setDatePattern(pattern)
self.__jails[name].filter.setDatePattern(pattern)
def getDatePattern(self, name):
return self.__jails.getFilter(name).getDatePattern()
return self.__jails[name].filter.getDatePattern()
def setIgnoreCommand(self, name, value):
self.__jails.getFilter(name).setIgnoreCommand(value)
self.__jails[name].filter.setIgnoreCommand(value)
def getIgnoreCommand(self, name):
return self.__jails.getFilter(name).getIgnoreCommand()
return self.__jails[name].filter.getIgnoreCommand()
def addFailRegex(self, name, value):
self.__jails.getFilter(name).addFailRegex(value)
self.__jails[name].filter.addFailRegex(value)
def delFailRegex(self, name, index):
self.__jails.getFilter(name).delFailRegex(index)
self.__jails[name].filter.delFailRegex(index)
def getFailRegex(self, name):
return self.__jails.getFilter(name).getFailRegex()
return self.__jails[name].filter.getFailRegex()
def addIgnoreRegex(self, name, value):
self.__jails.getFilter(name).addIgnoreRegex(value)
self.__jails[name].filter.addIgnoreRegex(value)
def delIgnoreRegex(self, name, index):
self.__jails.getFilter(name).delIgnoreRegex(index)
self.__jails[name].filter.delIgnoreRegex(index)
def getIgnoreRegex(self, name):
return self.__jails.getFilter(name).getIgnoreRegex()
return self.__jails[name].filter.getIgnoreRegex()
def setUseDns(self, name, value):
self.__jails.getFilter(name).setUseDns(value)
self.__jails[name].filter.setUseDns(value)
def getUseDns(self, name):
return self.__jails.getFilter(name).getUseDns()
return self.__jails[name].filter.getUseDns()
def setMaxRetry(self, name, value):
self.__jails.getFilter(name).setMaxRetry(value)
self.__jails[name].filter.setMaxRetry(value)
def getMaxRetry(self, name):
return self.__jails.getFilter(name).getMaxRetry()
return self.__jails[name].filter.getMaxRetry()
def setMaxLines(self, name, value):
self.__jails.getFilter(name).setMaxLines(value)
self.__jails[name].filter.setMaxLines(value)
def getMaxLines(self, name):
return self.__jails.getFilter(name).getMaxLines()
return self.__jails[name].filter.getMaxLines()
# Action
def addAction(self, name, value, *args):
self.__jails.getAction(name).addAction(value, *args)
def getLastAction(self, name):
return self.__jails.getAction(name).getLastAction()
self.__jails[name].actions.add(value, *args)
def getActions(self, name):
return self.__jails.getAction(name).getActions()
return self.__jails[name].actions
def delAction(self, name, value):
self.__jails.getAction(name).delAction(value)
del self.__jails[name].actions[value]
def getAction(self, name, value):
return self.__jails.getAction(name).getAction(value)
return self.__jails[name].actions[value]
def setBanTime(self, name, value):
self.__jails.getAction(name).setBanTime(value)
self.__jails[name].actions.setBanTime(value)
def setBanIP(self, name, value):
return self.__jails.getFilter(name).addBannedIP(value)
return self.__jails[name].filter.addBannedIP(value)
def setUnbanIP(self, name, value):
return self.__jails.getAction(name).removeBannedIP(value)
self.__jails[name].actions.removeBannedIP(value)
def getBanTime(self, name):
return self.__jails.getAction(name).getBanTime()
return self.__jails[name].actions.getBanTime()
# Status
def status(self):
try:
self.__lock.acquire()
jails = list(self.__jails.getAll())
jails = list(self.__jails)
jails.sort()
jailList = ", ".join(jails)
ret = [("Number of jail", self.__jails.size()),
ret = [("Number of jail", len(self.__jails)),
("Jail list", jailList)]
return ret
finally:
self.__lock.release()
def statusJail(self, name):
return self.__jails.get(name).getStatus()
return self.__jails[name].getStatus()
# Logging
@ -447,7 +444,7 @@ class Server:
return "flushed"
def setDatabase(self, filename):
if self.__jails.size() == 0:
if len(self.__jails) == 0:
if filename.lower() == "none":
self.__db = None
else:

View File

@ -227,13 +227,14 @@ class Transmitter:
return self.__server.setBanIP(name,value)
elif command[1] == "unbanip":
value = command[2]
return self.__server.setUnbanIP(name,value)
self.__server.setUnbanIP(name, value)
return value
elif command[1] == "addaction":
args = [command[2]]
if len(command) > 3:
args.extend([command[3], json.loads(command[4])])
self.__server.addAction(name, *args)
return self.__server.getLastAction(name).actionname
return args[0]
elif command[1] == "delaction":
value = command[2]
self.__server.delAction(name, value)
@ -300,10 +301,7 @@ class Transmitter:
elif command[1] == "bantime":
return self.__server.getBanTime(name)
elif command[1] == "actions":
return [action.actionname
for action in self.__server.getActions(name)]
elif command[1] == "addaction":
return self.__server.getLastAction(name).actionname
return self.__server.getActions(name).keys()
elif command[1] == "action":
actionname = command[2]
actionvalue = command[3]

View File

@ -47,8 +47,8 @@ class ExecuteActions(LogCaptureTestCase):
os.remove(self.__tmpfilename)
def defaultActions(self):
self.__actions.addAction('ip')
self.__ip = self.__actions.getAction('ip')
self.__actions.add('ip')
self.__ip = self.__actions['ip']
self.__ip.actionstart = 'echo ip start 64 >> "%s"' % self.__tmpfilename
self.__ip.actionban = 'echo ip ban <ip> >> "%s"' % self.__tmpfilename
self.__ip.actionunban = 'echo ip unban <ip> >> "%s"' % self.__tmpfilename
@ -56,15 +56,15 @@ class ExecuteActions(LogCaptureTestCase):
self.__ip.actionstop = 'echo ip stop >> "%s"' % self.__tmpfilename
def testActionsManipulation(self):
self.__actions.addAction('test')
self.assertTrue(self.__actions.getAction('test'))
self.assertTrue(self.__actions.getLastAction())
self.assertRaises(KeyError,self.__actions.getAction,*['nonexistant action'])
self.__actions.addAction('test1')
self.__actions.delAction('test')
self.__actions.delAction('test1')
self.assertRaises(KeyError, self.__actions.getAction, *['test'])
self.assertRaises(IndexError,self.__actions.getLastAction)
self.__actions.add('test')
self.assertTrue(self.__actions['test'])
self.assertTrue('test' in self.__actions)
self.assertFalse('nonexistant action' in self.__actions)
self.__actions.add('test1')
del self.__actions['test']
del self.__actions['test1']
self.assertFalse('test' in self.__actions)
self.assertEqual(len(self.__actions), 0)
self.__actions.setBanTime(127)
self.assertEqual(self.__actions.getBanTime(),127)
@ -85,7 +85,7 @@ class ExecuteActions(LogCaptureTestCase):
def testAddActionPython(self):
self.__actions.addAction(
self.__actions.add(
"Action", os.path.join(TEST_FILES_DIR, "action.d/action.py"),
{'opt1': 'value'})
@ -100,18 +100,18 @@ class ExecuteActions(LogCaptureTestCase):
self.assertTrue(self._is_logged("TestAction action stop"))
self.assertRaises(IOError,
self.__actions.addAction, "Action3", "/does/not/exist.py", {})
self.__actions.add, "Action3", "/does/not/exist.py", {})
# With optional argument
self.__actions.addAction(
self.__actions.add(
"Action4", os.path.join(TEST_FILES_DIR, "action.d/action.py"),
{'opt1': 'value', 'opt2': 'value2'})
# With too many arguments
self.assertRaises(
TypeError, self.__actions.addAction, "Action5",
TypeError, self.__actions.add, "Action5",
os.path.join(TEST_FILES_DIR, "action.d/action.py"),
{'opt1': 'value', 'opt2': 'value2', 'opt3': 'value3'})
# Missing required argument
self.assertRaises(
TypeError, self.__actions.addAction, "Action5",
TypeError, self.__actions.add, "Action5",
os.path.join(TEST_FILES_DIR, "action.d/action.py"), {})

View File

@ -3,8 +3,8 @@ from fail2ban.server.action import ActionBase
class TestAction(ActionBase):
def __init__(self, jail, actionname, opt1, opt2=None):
super(TestAction, self).__init__(jail, actionname)
def __init__(self, jail, name, opt1, opt2=None):
super(TestAction, self).__init__(jail, name)
self._logSys.debug("%s initialised" % self.__class__.__name__)
self.opt1 = opt1
self.opt2 = opt2

View File

@ -518,9 +518,6 @@ class Transmitter(TransmitterBase):
self.assertEqual(
self.transm.proceed(["set", self.jailName, "addaction", action]),
(0, action))
self.assertEqual(
self.transm.proceed(["get", self.jailName, "addaction"]),
(0, action))
self.assertEqual(
self.transm.proceed(
["get", self.jailName, "actions"])[1][0],
@ -546,10 +543,6 @@ class Transmitter(TransmitterBase):
self.transm.proceed(
["get", self.jailName, "action", action, "InvalidKey"])[0],
1)
self.assertEqual(
self.transm.proceed(
["get", self.jailName, "action", action, "actionname"]),
(0, action))
self.assertEqual(
self.transm.proceed(
["set", self.jailName, "action", action, "timeout", "10"]),
@ -575,7 +568,7 @@ class Transmitter(TransmitterBase):
self.assertEqual(
sorted(self.transm.proceed(["get", self.jailName,
"actionproperties", action])[1]),
['actionname', 'opt1', 'opt2'])
['opt1', 'opt2'])
self.assertEqual(
self.transm.proceed(["get", self.jailName, "action", action,
"opt1"]),