diff --git a/MANIFEST b/MANIFEST index 25c5d824..e60b2685 100644 --- a/MANIFEST +++ b/MANIFEST @@ -228,6 +228,7 @@ config/action.d/mynetwatchman.conf config/action.d/pf.conf config/action.d/sendmail.conf config/action.d/sendmail-buffered.conf +config/action.d/sendmail-whois-ipmatches.conf config/action.d/sendmail-whois.conf config/action.d/sendmail-whois-lines.conf config/action.d/shorewall.conf diff --git a/config/action.d/sendmail-whois-ipmatches.conf b/config/action.d/sendmail-whois-ipmatches.conf new file mode 100644 index 00000000..3dabf093 --- /dev/null +++ b/config/action.d/sendmail-whois-ipmatches.conf @@ -0,0 +1,77 @@ +# Fail2Ban configuration file +# +# Author: Cyril Jaquier +# +# + +[INCLUDES] + +before = sendmail-common.conf + +[Definition] + +# Option: actionstart +# Notes.: command executed once at the start of Fail2Ban. +# Values: CMD +# +actionstart = printf %%b "Subject: [Fail2Ban] : started on `uname -n` + Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` + From: <> + To: \n + Hi,\n + The jail has been started successfully.\n + Regards,\n + Fail2Ban" | /usr/sbin/sendmail -f + +# Option: actionstop +# Notes.: command executed once at the end of Fail2Ban +# Values: CMD +# +actionstop = printf %%b "Subject: [Fail2Ban] : stopped on `uname -n` + Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` + From: <> + To: \n + Hi,\n + The jail has been stopped.\n + Regards,\n + Fail2Ban" | /usr/sbin/sendmail -f + +# Option: actioncheck +# Notes.: command executed once before each actionban command +# Values: CMD +# +actioncheck = + +# Option: actionban +# Notes.: command executed when banning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionban = printf %%b "Subject: [Fail2Ban] : banned from `uname -n` + Date: `LC_TIME=C date -u +"%%a, %%d %%h %%Y %%T +0000"` + From: <> + To: \n + Hi,\n + The IP has just been banned by Fail2Ban after + attempts against .\n\n + Here are more information about :\n + `/usr/bin/whois `\n\n + Matches for IP:\n + \n\n + Regards,\n + Fail2Ban" | /usr/sbin/sendmail -f + +# Option: actionunban +# Notes.: command executed when unbanning an IP. Take care that the +# command is executed with Fail2Ban user rights. +# Tags: See jail.conf(5) man page +# Values: CMD +# +actionunban = + +[Init] + +# Default name of the chain +# +name = default diff --git a/fail2ban/server/action.py b/fail2ban/server/action.py index 7e16901c..17f33a6f 100644 --- a/fail2ban/server/action.py +++ b/fail2ban/server/action.py @@ -295,7 +295,7 @@ class Action: #@staticmethod def escapeTag(tag): - for c in '\\#&;`|*?~<>^()[]{}$\n\'"': + for c in '\\#&;`|*?~<>^()[]{}$\'"': if c in tag: tag = tag.replace(c, '\\' + c) return tag @@ -314,12 +314,15 @@ class Action: """ string = query for tag, value in aInfo.iteritems(): - value = str(value) # assure string - if tag == 'matches': - # That one needs to be escaped since its content is - # out of our control - value = Action.escapeTag(value) - string = string.replace('<' + tag + '>', value) + if "<%s>" % tag in query: + if callable(value): + value = value() + value = str(value) # assure string + if tag.endswith('matches'): + # That one needs to be escaped since its content is + # out of our control + value = Action.escapeTag(value) + string = string.replace('<' + tag + '>', value) # New line string = string.replace("
", '\n') return string diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index 520886af..96c1b3c1 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -183,7 +183,14 @@ class Actions(JailThread): aInfo["ip"] = bTicket.getIP() aInfo["failures"] = bTicket.getAttempt() aInfo["time"] = bTicket.getTime() - aInfo["matches"] = "".join(bTicket.getMatches()) + aInfo["matches"] = "\n".join(bTicket.getMatches()) + if self.jail.getDatabase() is not None: + aInfo["ipmatches"] = lambda: "\n".join( + self.jail.getDatabase().getBansMerged( + bTicket.getIP()).getMatches()) + aInfo["ipjailmatches"] = lambda: "\n".join( + self.jail.getDatabase().getBansMerged( + bTicket.getIP(), jail=self.jail).getMatches()) if self.__banManager.addBanTicket(bTicket): logSys.warning("[%s] Ban %s" % (self.jail.getName(), aInfo["ip"])) for action in self.__actions: diff --git a/fail2ban/tests/actiontestcase.py b/fail2ban/tests/actiontestcase.py index e25f4cb0..ad22d2a2 100644 --- a/fail2ban/tests/actiontestcase.py +++ b/fail2ban/tests/actiontestcase.py @@ -102,8 +102,28 @@ class ExecuteAction(unittest.TestCase): "Text 890 text 123 ABC") self.assertEqual( self.__action.replaceTag("", - {'matches': "some >char< should \< be[ escap}ed&"}), - r"some \>char\< should \\\< be\[ escap\}ed\&") + {'matches': "some >char< should \< be[ escap}ed&\n"}), + "some \\>char\\< should \\\\\\< be\\[ escap\\}ed\\&\n") + self.assertEqual( + self.__action.replaceTag("", + {'ipmatches': "some >char< should \< be[ escap}ed&\n"}), + "some \\>char\\< should \\\\\\< be\\[ escap\\}ed\\&\n") + self.assertEqual( + self.__action.replaceTag("", + {'ipjailmatches': "some >char< should \< be[ escap}ed&\n"}), + "some \\>char\\< should \\\\\\< be\\[ escap\\}ed\\&\n") + + # Callable + self.assertEqual( + self.__action.replaceTag("09 11", + {'callable': lambda: str(10)}), + "09 10 11") + + # As tag not present, therefore callable should not be called + # Will raise ValueError if it is + self.assertEqual( + self.__action.replaceTag("abc", + {'callable': lambda: int("a")}), "abc") def testExecuteActionBan(self): self.__action.setActionStart("touch /tmp/fail2ban.test")