mirror of https://github.com/fail2ban/fail2ban
Merge branch 'ainfo-copy' of https://github.com/kwirk/fail2ban
* 'ainfo-copy' of https://github.com/kwirk/fail2ban: TST: actions modifying aInfo test more robust TST: Test for actions modifying (un)ban aInfo BF: aInfo could be modified by actions, causing unexpected behaviourpull/747/head
commit
0adb10f653
|
@ -45,7 +45,7 @@ messages['ban'] = {}
|
|||
messages['ban']['head'] = \
|
||||
"""Hi,
|
||||
|
||||
The IP %(ip)s has just been banned for %(bantime)s seconds
|
||||
The IP %(ip)s has just been banned for %(bantime)i seconds
|
||||
by Fail2Ban after %(failures)i attempts against %(jailname)s.
|
||||
"""
|
||||
messages['ban']['tail'] = \
|
||||
|
|
|
@ -69,6 +69,9 @@ class CallingMap(MutableMapping):
|
|||
def __init__(self, *args, **kwargs):
|
||||
self.data = dict(*args, **kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%r)" % (self.__class__.__name__, self.data)
|
||||
|
||||
def __getitem__(self, key):
|
||||
value = self.data[key]
|
||||
if callable(value):
|
||||
|
@ -88,6 +91,9 @@ class CallingMap(MutableMapping):
|
|||
def __len__(self):
|
||||
return len(self.data)
|
||||
|
||||
def copy(self):
|
||||
return self.__class__(self.data.copy())
|
||||
|
||||
class ActionBase(object):
|
||||
"""An abstract base class for actions in Fail2Ban.
|
||||
|
||||
|
|
|
@ -274,11 +274,12 @@ class Actions(JailThread, Mapping):
|
|||
logSys.notice("[%s] Ban %s" % (self._jail.name, aInfo["ip"]))
|
||||
for name, action in self._actions.iteritems():
|
||||
try:
|
||||
action.ban(aInfo)
|
||||
action.ban(aInfo.copy())
|
||||
except Exception as e:
|
||||
logSys.error(
|
||||
"Failed to execute ban jail '%s' action '%s': %s",
|
||||
self._jail.name, name, e,
|
||||
"Failed to execute ban jail '%s' action '%s' "
|
||||
"info '%r': %s",
|
||||
self._jail.name, name, aInfo, e,
|
||||
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||
return True
|
||||
else:
|
||||
|
@ -322,11 +323,12 @@ class Actions(JailThread, Mapping):
|
|||
logSys.notice("[%s] Unban %s" % (self._jail.name, aInfo["ip"]))
|
||||
for name, action in self._actions.iteritems():
|
||||
try:
|
||||
action.unban(aInfo)
|
||||
action.unban(aInfo.copy())
|
||||
except Exception as e:
|
||||
logSys.error(
|
||||
"Failed to execute unban jail '%s' action '%s': %s",
|
||||
self._jail.name, name, e,
|
||||
"Failed to execute unban jail '%s' action '%s' "
|
||||
"info '%r': %s",
|
||||
self._jail.name, name, aInfo, e,
|
||||
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
|
||||
|
||||
@property
|
||||
|
|
|
@ -29,6 +29,7 @@ import os
|
|||
import tempfile
|
||||
|
||||
from ..server.actions import Actions
|
||||
from ..server.ticket import FailTicket
|
||||
from .dummyjail import DummyJail
|
||||
from .utils import LogCaptureTestCase
|
||||
|
||||
|
@ -140,3 +141,28 @@ class ExecuteActions(LogCaptureTestCase):
|
|||
self.__actions.stop()
|
||||
self.__actions.join()
|
||||
self.assertTrue(self._is_logged("Failed to stop"))
|
||||
|
||||
def testBanActionsAInfo(self):
|
||||
# Action which deletes IP address from aInfo
|
||||
self.__actions.add(
|
||||
"action1",
|
||||
os.path.join(TEST_FILES_DIR, "action.d/action_modifyainfo.py"),
|
||||
{})
|
||||
self.__actions.add(
|
||||
"action2",
|
||||
os.path.join(TEST_FILES_DIR, "action.d/action_modifyainfo.py"),
|
||||
{})
|
||||
self.__jail.putFailTicket(FailTicket("1.2.3.4", 0))
|
||||
self.__actions._Actions__checkBan()
|
||||
# Will fail if modification of aInfo from first action propagates
|
||||
# to second action, as both delete same key
|
||||
self.assertFalse(self._is_logged("Failed to execute ban"))
|
||||
self.assertTrue(self._is_logged("action1 ban deleted aInfo IP"))
|
||||
self.assertTrue(self._is_logged("action2 ban deleted aInfo IP"))
|
||||
|
||||
self.__actions._Actions__flushBan()
|
||||
# Will fail if modification of aInfo from first action propagates
|
||||
# to second action, as both delete same key
|
||||
self.assertFalse(self._is_logged("Failed to execute unban"))
|
||||
self.assertTrue(self._is_logged("action1 unban deleted aInfo IP"))
|
||||
self.assertTrue(self._is_logged("action2 unban deleted aInfo IP"))
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
from fail2ban.server.action import ActionBase
|
||||
|
||||
class TestAction(ActionBase):
|
||||
|
||||
def ban(self, aInfo):
|
||||
del aInfo['ip']
|
||||
self._logSys.info("%s ban deleted aInfo IP", self._name)
|
||||
|
||||
def unban(self, aInfo):
|
||||
del aInfo['ip']
|
||||
self._logSys.info("%s unban deleted aInfo IP", self._name)
|
||||
|
||||
Action = TestAction
|
Loading…
Reference in New Issue