actions: extend tags replacement in non ticket-based commands (actionstart, actionstop, etc);

fixes regression by interpolation of tag `<bantime>` introduced in 0.11 with dynamic bantime (due to `bantime.increment`, see #2869)
pull/2181/merge
sebres 2020-11-11 11:08:23 +01:00
parent 66ff90408f
commit ca4da9d1d3
3 changed files with 21 additions and 7 deletions

View File

@ -455,7 +455,18 @@ class CommandAction(ActionBase):
ret = True
# avoid double execution of same command for both families:
if cmd and cmd not in self._operationExecuted(tag, lambda f: f != famoper):
ret = self.executeCmd(cmd, self.timeout)
realCmd = cmd
if self._jail:
# simulate action info with "empty" ticket:
aInfo = getattr(self._jail.actions, 'actionInfo', None)
if not aInfo:
aInfo = self._jail.actions._getActionInfo(None)
setattr(self._jail.actions, 'actionInfo', aInfo)
aInfo['time'] = MyTime.time()
aInfo['family'] = famoper
# replace dynamical tags, important - don't cache, no recursion and auto-escape here
realCmd = self.replaceDynamicTags(cmd, aInfo)
ret = self.executeCmd(realCmd, self.timeout)
res &= ret
if afterExec: afterExec(famoper, ret)
self._operationExecuted(tag, famoper, cmd if ret else None)

View File

@ -457,7 +457,9 @@ class Actions(JailThread, Mapping):
return mi[idx] if mi[idx] is not None else self.__ticket
def __getActionInfo(self, ticket):
def _getActionInfo(self, ticket):
if not ticket:
ticket = BanTicket("", MyTime.time())
aInfo = Actions.ActionInfo(ticket, self._jail)
return aInfo
@ -491,7 +493,7 @@ class Actions(JailThread, Mapping):
bTicket = BanTicket.wrap(ticket)
btime = ticket.getBanTime(self.__banManager.getBanTime())
ip = bTicket.getIP()
aInfo = self.__getActionInfo(bTicket)
aInfo = self._getActionInfo(bTicket)
reason = {}
if self.__banManager.addBanTicket(bTicket, reason=reason):
cnt += 1
@ -568,7 +570,7 @@ class Actions(JailThread, Mapping):
"""
actions = actions or self._actions
ip = ticket.getIP()
aInfo = self.__getActionInfo(ticket)
aInfo = self._getActionInfo(ticket)
if log:
logSys.notice("[%s] Reban %s%s", self._jail.name, aInfo["ip"], (', action %r' % actions.keys()[0] if len(actions) == 1 else ''))
for name, action in actions.iteritems():
@ -602,7 +604,7 @@ class Actions(JailThread, Mapping):
if not action._prolongable:
continue
if aInfo is None:
aInfo = self.__getActionInfo(ticket)
aInfo = self._getActionInfo(ticket)
if not aInfo.immutable: aInfo.reset()
action.prolong(aInfo)
except Exception as e:
@ -696,7 +698,7 @@ class Actions(JailThread, Mapping):
else:
unbactions = actions
ip = ticket.getIP()
aInfo = self.__getActionInfo(ticket)
aInfo = self._getActionInfo(ticket)
if log:
logSys.notice("[%s] Unban %s", self._jail.name, aInfo["ip"])
for name, action in unbactions.iteritems():

View File

@ -1448,9 +1448,10 @@ class ServerConfigReaderTests(LogCaptureTestCase):
),
}),
# dummy --
('j-dummy', 'dummy[name=%(__name__)s, init="==", target="/tmp/fail2ban.dummy"]', {
('j-dummy', '''dummy[name=%(__name__)s, init="=='<family>/<ip>'==bt:<bantime>==bc:<bancount>==", target="/tmp/fail2ban.dummy"]''', {
'ip4': ('family: inet4',), 'ip6': ('family: inet6',),
'start': (
'''`printf %b "=='/'==bt:600==bc:0==\\n"''', ## empty family (independent in this action, same for both), no ip on start, initial bantime and bancount
'`echo "[j-dummy] dummy /tmp/fail2ban.dummy -- started"`',
),
'flush': (