From aec709f4c19d4c873345e184c71c5181d15b126c Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Tue, 22 Jan 2013 20:54:14 +0000 Subject: [PATCH 01/37] Initial changes and test for multi-line filtering --- client/jailreader.py | 3 +++ common/protocol.py | 2 ++ man/fail2ban-client.1 | 9 ++++++++ server/failregex.py | 2 +- server/filter.py | 30 +++++++++++++++++++++++++- server/server.py | 6 ++++++ server/transmitter.py | 6 ++++++ testcases/files/testcase-multiline.log | 12 +++++++++++ testcases/filtertestcase.py | 15 +++++++++++++ 9 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 testcases/files/testcase-multiline.log diff --git a/client/jailreader.py b/client/jailreader.py index f66dc010..ca9cc5a8 100644 --- a/client/jailreader.py +++ b/client/jailreader.py @@ -63,6 +63,7 @@ class JailReader(ConfigReader): ["string", "logpath", "/var/log/messages"], ["string", "backend", "auto"], ["int", "maxretry", 3], + ["int", "maxlines", 1], ["int", "findtime", 600], ["int", "bantime", 600], ["string", "usedns", "warn"], @@ -114,6 +115,8 @@ class JailReader(ConfigReader): backend = self.__opts[opt] elif opt == "maxretry": stream.append(["set", self.__name, "maxretry", self.__opts[opt]]) + elif opt == "maxlines": + stream.append(["set", self.__name, "maxlines", self.__opts[opt]]) elif opt == "ignoreip": for ip in self.__opts[opt].split(): # Do not send a command if the rule is empty. diff --git a/common/protocol.py b/common/protocol.py index 2f8ffa6c..de7c84a8 100644 --- a/common/protocol.py +++ b/common/protocol.py @@ -66,6 +66,7 @@ protocol = [ ["set banip ", "manually Ban for "], ["set unbanip ", "manually Unban in "], ["set maxretry ", "sets the number of failures before banning the host for "], +["set maxlines ", "sets the number of to buffer for regex search for "], ["set addaction ", "adds a new action named for "], ["set delaction ", "removes the action from "], ["set setcinfo ", "sets for of the action for "], @@ -84,6 +85,7 @@ protocol = [ ["get bantime", "gets the time a host is banned for "], ["get usedns", "gets the usedns setting for "], ["get maxretry", "gets the number of failures allowed for "], +["get maxlines", "gets the number of lines to buffer for "], ["get addaction", "gets the last action which has been added for "], ["get actionstart ", "gets the start command for the action for "], ["get actionstop ", "gets the stop command for the action for "], diff --git a/man/fail2ban-client.1 b/man/fail2ban-client.1 index 1bbddf09..d60c9481 100644 --- a/man/fail2ban-client.1 +++ b/man/fail2ban-client.1 @@ -145,6 +145,11 @@ sets the number of failures before banning the host for .TP +\fBset maxlines \fR +sets the number of to +buffer for regex search for + +.TP \fBset addaction \fR adds a new action named for @@ -222,6 +227,10 @@ gets the time a host is banned for gets the number of failures allowed for .TP +\fBget maxlines\fR +gets the number lines to +buffer for +.TP \fBget addaction\fR gets the last action which has been added for diff --git a/server/failregex.py b/server/failregex.py index 8ce9597a..c595b4de 100644 --- a/server/failregex.py +++ b/server/failregex.py @@ -51,7 +51,7 @@ class Regex: if regex.lstrip() == '': raise RegexException("Cannot add empty regex") try: - self._regexObj = re.compile(regex) + self._regexObj = re.compile(regex, re.MULTILINE) self._regex = regex except sre_constants.error: raise RegexException("Unable to compile regular expression '%s'" % diff --git a/server/filter.py b/server/filter.py index b37e37e6..3ab21b17 100644 --- a/server/filter.py +++ b/server/filter.py @@ -36,6 +36,7 @@ from mytime import MyTime from failregex import FailRegex, Regex, RegexException import logging, re, os, fcntl, time +from collections import deque # Gets the instance of the logger. logSys = logging.getLogger("fail2ban.filter") @@ -71,6 +72,10 @@ class Filter(JailThread): self.__findTime = 6000 ## The ignore IP list. self.__ignoreIpList = [] + ## Size of line buffer + self.__line_buffer_size = 1 + ## Line buffer + self.__line_buffer = deque() self.dateDetector = DateDetector() self.dateDetector.addDefaultTemplate() @@ -204,6 +209,25 @@ class Filter(JailThread): def getMaxRetry(self): return self.failManager.getMaxRetry() + ## + # Set the maximum line buffer size. + # + # @param value the line buffer size + + def setMaxLines(self, value): + if value < 1: + value = 1 + self.__line_buffer_size = value + logSys.info("Set maxLines = %s" % value) + + ## + # Get the maximum line buffer size. + # + # @return the line buffer size + + def getMaxLines(self): + return self.__line_buffer_size + ## # Main loop. # @@ -305,7 +329,10 @@ class Filter(JailThread): else: timeLine = l logLine = l - return self.findFailure(timeLine, logLine) + self.__line_buffer.append(logLine) + while len(self.__line_buffer) > self.__line_buffer_size: + self.__line_buffer.popleft() + return self.findFailure(timeLine, "".join(self.__line_buffer)) def processLineAndAdd(self, line): """Processes the line for failures and populates failManager @@ -365,6 +392,7 @@ class Filter(JailThread): "in order to get support for this format." % (logLine, timeLine)) else: + self.__line_buffer.clear() try: host = failRegex.getHost() ipMatch = DNSUtils.textToIp(host, self.__useDns) diff --git a/server/server.py b/server/server.py index d9532be2..32d72770 100644 --- a/server/server.py +++ b/server/server.py @@ -216,6 +216,12 @@ class Server: def getMaxRetry(self, name): return self.__jails.getFilter(name).getMaxRetry() + def setMaxLines(self, name, value): + self.__jails.getFilter(name).setMaxLines(value) + + def getMaxLines(self, name): + return self.__jails.getFilter(name).getMaxLines() + # Action def addAction(self, name, value): self.__jails.getAction(name).addAction(value) diff --git a/server/transmitter.py b/server/transmitter.py index 23b609a1..23fb3eba 100644 --- a/server/transmitter.py +++ b/server/transmitter.py @@ -167,6 +167,10 @@ class Transmitter: value = command[2] self.__server.setMaxRetry(name, int(value)) return self.__server.getMaxRetry(name) + elif command[1] == "maxlines": + value = command[2] + self.__server.setMaxLines(name, int(value)) + return self.__server.getMaxLines(name) # command elif command[1] == "bantime": value = command[2] @@ -245,6 +249,8 @@ class Transmitter: return self.__server.getFindTime(name) elif command[1] == "maxretry": return self.__server.getMaxRetry(name) + elif command[1] == "maxlines": + return self.__server.getMaxLines(name) # Action elif command[1] == "bantime": return self.__server.getBanTime(name) diff --git a/testcases/files/testcase-multiline.log b/testcases/files/testcase-multiline.log new file mode 100644 index 00000000..b91f2756 --- /dev/null +++ b/testcases/files/testcase-multiline.log @@ -0,0 +1,12 @@ +Aug 14 11:59:58 [sshd] Invalid user toto... +Aug 14 11:59:58 [sshd] from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user toto... +Aug 14 11:59:58 [sshd] from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user fuck... +Aug 14 11:59:58 [sshd] from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user toto... +Aug 14 11:59:58 [sshd] from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user fuck... +Aug 14 11:59:58 [sshd] from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user fuck... +Aug 14 11:59:58 [sshd] from 212.41.96.185 diff --git a/testcases/filtertestcase.py b/testcases/filtertestcase.py index c10fa78d..31d89239 100644 --- a/testcases/filtertestcase.py +++ b/testcases/filtertestcase.py @@ -499,6 +499,7 @@ class GetFailures(unittest.TestCase): FILENAME_03 = "testcases/files/testcase03.log" FILENAME_04 = "testcases/files/testcase04.log" FILENAME_USEDNS = "testcases/files/testcase-usedns.log" + FILENAME_MULTILINE = "testcases/files/testcase-multiline.log" # so that they could be reused by other tests FAILURES_01 = ('193.168.0.128', 3, 1124013599.0, @@ -604,6 +605,20 @@ class GetFailures(unittest.TestCase): self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) + def testGetFailuresMultiLine(self): + output = ("212.41.96.185", 3, 1124013598.0) + self.filter.addLogPath(GetFailures.FILENAME_MULTILINE) + self.filter.addFailRegex("Invalid user .+\n.+ from $") + self.filter.addIgnoreRegex("user fuck") + + self.filter.setMaxLines(2) + + self.filter.getFailures(GetFailures.FILENAME_MULTILINE) + + _assert_correct_last_attempt(self, self.filter, output) + + self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) + class DNSUtilsTests(unittest.TestCase): def testUseDns(self): From 5c7e3841e095b7d0581091c8425c92ad626f8e89 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 23 Jan 2013 18:26:49 +0000 Subject: [PATCH 02/37] Simplify and change some filter line buffer Include change variable names to `fail2ban` style --- server/filter.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/server/filter.py b/server/filter.py index 3ab21b17..a66a3c06 100644 --- a/server/filter.py +++ b/server/filter.py @@ -36,7 +36,6 @@ from mytime import MyTime from failregex import FailRegex, Regex, RegexException import logging, re, os, fcntl, time -from collections import deque # Gets the instance of the logger. logSys = logging.getLogger("fail2ban.filter") @@ -73,9 +72,9 @@ class Filter(JailThread): ## The ignore IP list. self.__ignoreIpList = [] ## Size of line buffer - self.__line_buffer_size = 1 + self.__lineBufferSize = 1 ## Line buffer - self.__line_buffer = deque() + self.__lineBuffer = [] self.dateDetector = DateDetector() self.dateDetector.addDefaultTemplate() @@ -215,10 +214,8 @@ class Filter(JailThread): # @param value the line buffer size def setMaxLines(self, value): - if value < 1: - value = 1 - self.__line_buffer_size = value - logSys.info("Set maxLines = %s" % value) + self.__lineBufferSize = max(1, value) + logSys.info("Set maxLines = %i" % self.__lineBufferSize) ## # Get the maximum line buffer size. @@ -226,7 +223,7 @@ class Filter(JailThread): # @return the line buffer size def getMaxLines(self): - return self.__line_buffer_size + return self.__lineBufferSize ## # Main loop. @@ -329,10 +326,9 @@ class Filter(JailThread): else: timeLine = l logLine = l - self.__line_buffer.append(logLine) - while len(self.__line_buffer) > self.__line_buffer_size: - self.__line_buffer.popleft() - return self.findFailure(timeLine, "".join(self.__line_buffer)) + self.__lineBuffer = ((self.__lineBuffer + + [logLine])[-self.__lineBufferSize:]) + return self.findFailure(timeLine, "".join(self.__lineBuffer)) def processLineAndAdd(self, line): """Processes the line for failures and populates failManager @@ -392,7 +388,7 @@ class Filter(JailThread): "in order to get support for this format." % (logLine, timeLine)) else: - self.__line_buffer.clear() + self.__lineBuffer = [] try: host = failRegex.getHost() ipMatch = DNSUtils.textToIp(host, self.__useDns) From 055aeeb227e129fdf56bacb3e1ee006264cd2350 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 23 Jan 2013 18:42:25 +0000 Subject: [PATCH 03/37] Filter for multi-line now stores last time match This is useful for log files which dont contain a date/time on every line --- server/filter.py | 5 ++++- testcases/files/testcase-multiline.log | 20 ++++++++++---------- testcases/filtertestcase.py | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/server/filter.py b/server/filter.py index a66a3c06..4d99ae33 100644 --- a/server/filter.py +++ b/server/filter.py @@ -75,6 +75,8 @@ class Filter(JailThread): self.__lineBufferSize = 1 ## Line buffer self.__lineBuffer = [] + ## Store last time stamp, applicable for multi-line + self.__lastTimeLine = "" self.dateDetector = DateDetector() self.dateDetector.addDefaultTemplate() @@ -319,12 +321,13 @@ class Filter(JailThread): if timeMatch: # Lets split into time part and log part of the line timeLine = timeMatch.group() + self.__lastTimeLine = timeLine # Lets leave the beginning in as well, so if there is no # anchore at the beginning of the time regexp, we don't # at least allow injection. Should be harmless otherwise logLine = l[:timeMatch.start()] + l[timeMatch.end():] else: - timeLine = l + timeLine = self.__lastTimeLine or l logLine = l self.__lineBuffer = ((self.__lineBuffer + [logLine])[-self.__lineBufferSize:]) diff --git a/testcases/files/testcase-multiline.log b/testcases/files/testcase-multiline.log index b91f2756..12132920 100644 --- a/testcases/files/testcase-multiline.log +++ b/testcases/files/testcase-multiline.log @@ -1,12 +1,12 @@ -Aug 14 11:59:58 [sshd] Invalid user toto... +Aug 14 11:59:58 [sshd] Invalid user toto + from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user toto + from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user duck + from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user toto + from 212.41.96.185 +Aug 14 11:59:58 [sshd] Invalid user duck... Aug 14 11:59:58 [sshd] from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user toto... -Aug 14 11:59:58 [sshd] from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user fuck... -Aug 14 11:59:58 [sshd] from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user toto... -Aug 14 11:59:58 [sshd] from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user fuck... -Aug 14 11:59:58 [sshd] from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user fuck... +Aug 14 11:59:58 [sshd] Invalid user duck... Aug 14 11:59:58 [sshd] from 212.41.96.185 diff --git a/testcases/filtertestcase.py b/testcases/filtertestcase.py index 31d89239..4083d231 100644 --- a/testcases/filtertestcase.py +++ b/testcases/filtertestcase.py @@ -608,8 +608,8 @@ class GetFailures(unittest.TestCase): def testGetFailuresMultiLine(self): output = ("212.41.96.185", 3, 1124013598.0) self.filter.addLogPath(GetFailures.FILENAME_MULTILINE) - self.filter.addFailRegex("Invalid user .+\n.+ from $") - self.filter.addIgnoreRegex("user fuck") + self.filter.addFailRegex("Invalid user .+\n.* from $") + self.filter.addIgnoreRegex("user duck") self.filter.setMaxLines(2) From 00ab42549228cca2034dd0f47ff5ece34b885c5e Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 23 Jan 2013 19:10:27 +0000 Subject: [PATCH 04/37] Changed multi-line test to provided example --- testcases/files/testcase-multiline.log | 36 +++++++++++++++++--------- testcases/filtertestcase.py | 9 +++---- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/testcases/files/testcase-multiline.log b/testcases/files/testcase-multiline.log index 12132920..70bd99ad 100644 --- a/testcases/files/testcase-multiline.log +++ b/testcases/files/testcase-multiline.log @@ -1,12 +1,24 @@ -Aug 14 11:59:58 [sshd] Invalid user toto - from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user toto - from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user duck - from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user toto - from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user duck... -Aug 14 11:59:58 [sshd] from 212.41.96.185 -Aug 14 11:59:58 [sshd] Invalid user duck... -Aug 14 11:59:58 [sshd] from 212.41.96.185 +Aug 14 11:58:58 yyyy rsyncd[23864]: connect from example.com (192.0.43.10) +Aug 14 11:59:58 yyyy rsyncd[23864]: rsync on xxx/ from example.com (192.0.43.10) +Aug 14 11:59:58 yyyy rsyncd[23864]: building file list +Aug 14 11:59:58 yyyy rsyncd[28101]: connect from irrelevant (192.0.43.11) +Aug 14 11:59:58 yyyy rsyncd[28101]: rsync on xxx/ from irrelevant (192.0.43.11) +Aug 14 11:59:58 yyyy rsyncd[28101]: building file list +Aug 14 11:59:58 yyyy rsyncd[28101]: sent 294382 bytes received 781 bytes total size 29221543998 +Aug 14 11:59:58 yyyy rsyncd[18067]: sent 2833586339 bytes received 65115 bytes total size 29221543998 +Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], SMART Usage Attribute: 194 Temperature_Celsius changed from 116 to 115 +Aug 14 11:59:58 yyyy rsyncd[1762]: connect from irrelevant (192.0.43.11) +Aug 14 11:59:58 yyyy rsyncd[1762]: rsync on xxx/ from irrelevant (192.0.43.11) +Aug 14 11:59:58 yyyy rsyncd[1762]: building file list +Aug 14 11:59:58 yyyy rsyncd[1762]: sent 294382 bytes received 781 bytes total size 29221543998 +Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sda [SAT], starting scheduled Short Self-Test. +Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], SMART Usage Attribute: 194 Temperature_Celsius changed from 115 to 116 +Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], starting scheduled Short Self-Test. +Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sda [SAT], previous self-test completed without error +Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], previous self-test completed without error +Aug 14 11:59:58 yyyy rsyncd[7788]: connect from irrelevant (192.0.43.11) +Aug 14 11:59:58 yyyy rsyncd[7788]: rsync on xxx/ from irrelevant (192.0.43.11) +Aug 14 11:59:58 yyyy rsyncd[7788]: building file list +Aug 14 11:59:58 yyyy rsyncd[7788]: sent 294382 bytes received 781 bytes total size 29221543998 +Aug 14 11:59:58 yyyy rsyncd[21919]: sent 2836906453 bytes received 6768 bytes total size 29221543998 +Aug 14 11:59:58 yyyy rsyncd[23864]: rsync error: timeout in data send/receive (code 30) at io.c(137) [sender=3.0.9] diff --git a/testcases/filtertestcase.py b/testcases/filtertestcase.py index 4083d231..7cd4c5ec 100644 --- a/testcases/filtertestcase.py +++ b/testcases/filtertestcase.py @@ -606,12 +606,11 @@ class GetFailures(unittest.TestCase): self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) def testGetFailuresMultiLine(self): - output = ("212.41.96.185", 3, 1124013598.0) + output = ("192.0.43.10", 1, 1124013598.0) self.filter.addLogPath(GetFailures.FILENAME_MULTILINE) - self.filter.addFailRegex("Invalid user .+\n.* from $") - self.filter.addIgnoreRegex("user duck") - - self.filter.setMaxLines(2) + self.filter.addFailRegex("rsyncd\[(?P\d+)\]: connect from .+ \(\)\n(?:.*\n)*?.+ rsyncd\[(?P=pid)\]: rsync error") + self.filter.setMaxLines(100) + self.filter.setMaxRetry(1) self.filter.getFailures(GetFailures.FILENAME_MULTILINE) From 5952819a580c9e9824a19cd7a123b8b696edfe9a Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 23 Jan 2013 19:32:55 +0000 Subject: [PATCH 05/37] Sanitise testcase log 04 --- testcases/files/testcase04.log | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/testcases/files/testcase04.log b/testcases/files/testcase04.log index c0304d06..987abec6 100644 --- a/testcases/files/testcase04.log +++ b/testcases/files/testcase04.log @@ -1,15 +1,15 @@ Sep 21 22:03:07 [sshd] Invalid user toto from 212.41.96.185 -1124012400 [sshd] Invalid user fuck from 212.41.96.185 +1124012400 [sshd] Invalid user duck from 212.41.96.185 Sep 21 21:03:38 [sshd] Invalid user toto from 212.41.96.185 -1124012500 [sshd] Invalid user fuck from 212.41.96.185 +1124012500 [sshd] Invalid user duck from 212.41.96.185 Sep 21 21:03:46 [sshd] Invalid user toto from 212.41.96.185 -Aug 14 11:58:48 [sshd] Invalid user fuck from 212.41.96.185 +Aug 14 11:58:48 [sshd] Invalid user duck from 212.41.96.185 Aug 14 11:59:58 [sshd] Invalid user toto from 212.41.96.185 -Sep 21 21:04:03 [sshd] Invalid user fuck from 212.41.96.185 +Sep 21 21:04:03 [sshd] Invalid user duck from 212.41.96.185 - Last output repeated twice - 2005/08/14 11:57:00 [sshd] Invalid user toto from 212.41.96.186 -2005/08/14 11:58:00 [sshd] Invalid user fuck from 212.41.96.186 +2005/08/14 11:58:00 [sshd] Invalid user duck from 212.41.96.186 2005/08/14 11:59:00 [sshd] Invalid user toto from 212.41.96.186 -2005/08/14 12:00:00 [sshd] Invalid user fuck from 212.41.96.186 +2005/08/14 12:00:00 [sshd] Invalid user duck from 212.41.96.186 - Last output repeated twice - Sep 21 21:09:01 [sshd] Invalid user toto from 212.41.96.185 From 9b4806bfd31e286e8b3271e7765c53f1c3c6445c Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Thu, 24 Jan 2013 18:16:17 +0000 Subject: [PATCH 06/37] Added regex applicable for multi-line This allows lines captured by regex to remain in the line buffer in Filter --- server/failregex.py | 23 +++++++++++++++++++++++ server/filter.py | 2 +- testcases/files/testcase-multiline.log | 6 +++++- testcases/filtertestcase.py | 8 +++++--- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/server/failregex.py b/server/failregex.py index c595b4de..84b237c7 100644 --- a/server/failregex.py +++ b/server/failregex.py @@ -48,6 +48,11 @@ class Regex: # Perform shortcuts expansions. # Replace "" with default regular expression for host. regex = regex.replace("", "(?:::f{4,6}:)?(?P[\w\-.^_]+)") + # Replace "" with regular expression for multiple lines. + regexSplit = regex.split("") + regex = regexSplit[0] + for n, regexLine in enumerate(regexSplit[1:]): + regex += "\n(?P(?:(.*\n)*?))" % n + regexLine if regex.lstrip() == '': raise RegexException("Cannot add empty regex") try: @@ -131,3 +136,21 @@ class FailRegex(Regex): r = self._matchCache.re raise RegexException("No 'host' found in '%s' using '%s'" % (s, r)) return host + + ## + # Returns unmatched lines. + # + # This returns unmatched lines inlcuding captured by the tag. + # @return list of unmatched lines + + def getUnmatchedLines(self): + unmatchedLines = self._matchCache.string[:self._matchCache.start()] + n = 0 + while True: + try: + unmatchedLines += self._matchCache.group("skiplines%i" % n) + n += 1 + except IndexError: + break + unmatchedLines += self._matchCache.string[self._matchCache.end():] + return unmatchedLines.splitlines(True) diff --git a/server/filter.py b/server/filter.py index 4d99ae33..0b0e0535 100644 --- a/server/filter.py +++ b/server/filter.py @@ -391,7 +391,7 @@ class Filter(JailThread): "in order to get support for this format." % (logLine, timeLine)) else: - self.__lineBuffer = [] + self.__lineBuffer = failRegex.getUnmatchedLines() try: host = failRegex.getHost() ipMatch = DNSUtils.textToIp(host, self.__useDns) diff --git a/testcases/files/testcase-multiline.log b/testcases/files/testcase-multiline.log index 70bd99ad..c0151d34 100644 --- a/testcases/files/testcase-multiline.log +++ b/testcases/files/testcase-multiline.log @@ -19,6 +19,10 @@ Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], previous self-test co Aug 14 11:59:58 yyyy rsyncd[7788]: connect from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[7788]: rsync on xxx/ from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[7788]: building file list -Aug 14 11:59:58 yyyy rsyncd[7788]: sent 294382 bytes received 781 bytes total size 29221543998 Aug 14 11:59:58 yyyy rsyncd[21919]: sent 2836906453 bytes received 6768 bytes total size 29221543998 Aug 14 11:59:58 yyyy rsyncd[23864]: rsync error: timeout in data send/receive (code 30) at io.c(137) [sender=3.0.9] +Aug 14 11:59:58 yyyy rsyncd[5534]: connect from irrelevant (192.0.43.11) +Aug 14 11:59:58 yyyy rsyncd[5534]: rsync on xxx/ from irrelevant (192.0.43.11) +Aug 14 11:59:58 yyyy rsyncd[5534]: building file list +Aug 14 11:59:58 yyyy rsyncd[7788]: rsync error: timeout in data send/receive (code 30) at io.c(137) [sender=3.0.9] +Aug 14 11:59:58 yyyy rsyncd[5534]: sent 294382 bytes received 781 bytes total size 29221543998 diff --git a/testcases/filtertestcase.py b/testcases/filtertestcase.py index 7cd4c5ec..262074e6 100644 --- a/testcases/filtertestcase.py +++ b/testcases/filtertestcase.py @@ -606,15 +606,17 @@ class GetFailures(unittest.TestCase): self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) def testGetFailuresMultiLine(self): - output = ("192.0.43.10", 1, 1124013598.0) + output = [("192.0.43.10", 1, 1124013598.0), + ("192.0.43.11", 1, 1124013598.0)] self.filter.addLogPath(GetFailures.FILENAME_MULTILINE) - self.filter.addFailRegex("rsyncd\[(?P\d+)\]: connect from .+ \(\)\n(?:.*\n)*?.+ rsyncd\[(?P=pid)\]: rsync error") + self.filter.addFailRegex("^.*rsyncd\[(?P\d+)\]: connect from .+ \(\)$^.+ rsyncd\[(?P=pid)\]: rsync error: .*$") self.filter.setMaxLines(100) self.filter.setMaxRetry(1) self.filter.getFailures(GetFailures.FILENAME_MULTILINE) - _assert_correct_last_attempt(self, self.filter, output) + _assert_correct_last_attempt(self, self.filter, output.pop()) + _assert_correct_last_attempt(self, self.filter, output.pop()) self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) From 28f68a693f8f042497cd6a18de49bd9c4ff85a54 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Thu, 24 Jan 2013 21:12:45 +0000 Subject: [PATCH 07/37] Minor typo in server/failregex.py --- server/failregex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/failregex.py b/server/failregex.py index 84b237c7..b7084ce2 100644 --- a/server/failregex.py +++ b/server/failregex.py @@ -140,7 +140,7 @@ class FailRegex(Regex): ## # Returns unmatched lines. # - # This returns unmatched lines inlcuding captured by the tag. + # This returns unmatched lines including captured by the tag. # @return list of unmatched lines def getUnmatchedLines(self): From ea466d59f478c18e4a3695032499b3c390d93222 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Fri, 25 Jan 2013 18:11:40 +0000 Subject: [PATCH 08/37] ignoreregex now functions correctly with multiline Ignore regexs are now only compared to lines that match the failregex. Supporting test also added for multiline regex and overlapping multiline regex matches. --- server/failregex.py | 66 +++++++++++++++++++------- server/filter.py | 9 ++-- testcases/files/testcase-multiline.log | 7 ++- testcases/filtertestcase.py | 16 ++++++- 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/server/failregex.py b/server/failregex.py index b7084ce2..d98ffa27 100644 --- a/server/failregex.py +++ b/server/failregex.py @@ -93,6 +93,54 @@ class Regex: else: return False + ## + # Returns skipped lines. + # + # This returns skipped lines captured by the tag. + # @return list of skipped lines + + def getSkippedLines(self): + if not self._matchCache: + return [] + skippedLines = "" + n = 0 + while True: + try: + skippedLines += self._matchCache.group("skiplines%i" % n) + n += 1 + except IndexError: + break + return skippedLines.splitlines(True) + + ## + # Returns unmatched lines. + # + # This returns unmatched lines including captured by the tag. + # @return list of unmatched lines + + def getUnmatchedLines(self): + if not self._matchCache: + return [] + unmatchedLines = ( + self._matchCache.string[:self._matchCache.start()].splitlines(True) + + self.getSkippedLines() + + self._matchCache.string[self._matchCache.end():].splitlines(True)) + return unmatchedLines + + ## + # Returns matched lines. + # + # This returns matched lines by excluding those captured + # by the tag. + # @return list of matched lines + + def getMatchedLines(self): + if not self._matchCache: + return [] + matchedLines = self._matchCache.string[ + self._matchCache.start():self._matchCache.end()].splitlines(True) + return [line for line in matchedLines + if line not in self.getSkippedLines()] ## # Exception dedicated to the class Regex. @@ -136,21 +184,3 @@ class FailRegex(Regex): r = self._matchCache.re raise RegexException("No 'host' found in '%s' using '%s'" % (s, r)) return host - - ## - # Returns unmatched lines. - # - # This returns unmatched lines including captured by the tag. - # @return list of unmatched lines - - def getUnmatchedLines(self): - unmatchedLines = self._matchCache.string[:self._matchCache.start()] - n = 0 - while True: - try: - unmatchedLines += self._matchCache.group("skiplines%i" % n) - n += 1 - except IndexError: - break - unmatchedLines += self._matchCache.string[self._matchCache.end():] - return unmatchedLines.splitlines(True) diff --git a/server/filter.py b/server/filter.py index 0b0e0535..5f2f0f2b 100644 --- a/server/filter.py +++ b/server/filter.py @@ -374,14 +374,15 @@ class Filter(JailThread): def findFailure(self, timeLine, logLine): failList = list() - # Checks if we must ignore this line. - if self.ignoreLine(logLine): - # The ignoreregex matched. Return. - return failList # Iterates over all the regular expressions. for failRegex in self.__failRegex: failRegex.search(logLine) if failRegex.hasMatched(): + # Checks if we must ignore this match. + if self.ignoreLine("".join(failRegex.getMatchedLines())): + # The ignoreregex matched. Remove ignored match. + self.__lineBuffer = failRegex.getUnmatchedLines() + continue # The failregex matched. date = self.dateDetector.getUnixTime(timeLine) if date == None: diff --git a/testcases/files/testcase-multiline.log b/testcases/files/testcase-multiline.log index c0151d34..69dac361 100644 --- a/testcases/files/testcase-multiline.log +++ b/testcases/files/testcase-multiline.log @@ -1,3 +1,4 @@ +Aug 14 11:58:58 yyyy rsyncd[9874]: connect from example.com (192.0.43.10) Aug 14 11:58:58 yyyy rsyncd[23864]: connect from example.com (192.0.43.10) Aug 14 11:59:58 yyyy rsyncd[23864]: rsync on xxx/ from example.com (192.0.43.10) Aug 14 11:59:58 yyyy rsyncd[23864]: building file list @@ -9,6 +10,7 @@ Aug 14 11:59:58 yyyy rsyncd[18067]: sent 2833586339 bytes received 65115 bytes Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], SMART Usage Attribute: 194 Temperature_Celsius changed from 116 to 115 Aug 14 11:59:58 yyyy rsyncd[1762]: connect from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[1762]: rsync on xxx/ from irrelevant (192.0.43.11) + Aug 14 11:59:58 yyyy rsyncd[1762]: building file list Aug 14 11:59:58 yyyy rsyncd[1762]: sent 294382 bytes received 781 bytes total size 29221543998 Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sda [SAT], starting scheduled Short Self-Test. @@ -16,6 +18,8 @@ Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], SMART Usage Attribute Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], starting scheduled Short Self-Test. Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sda [SAT], previous self-test completed without error Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], previous self-test completed without error + + Aug 14 11:59:58 yyyy rsyncd[7788]: connect from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[7788]: rsync on xxx/ from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[7788]: building file list @@ -24,5 +28,6 @@ Aug 14 11:59:58 yyyy rsyncd[23864]: rsync error: timeout in data send/receive (c Aug 14 11:59:58 yyyy rsyncd[5534]: connect from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[5534]: rsync on xxx/ from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[5534]: building file list -Aug 14 11:59:58 yyyy rsyncd[7788]: rsync error: timeout in data send/receive (code 30) at io.c(137) [sender=3.0.9] +Aug 14 11:59:58 yyyy rsyncd[7788]: rsync error: Received SIGINT Aug 14 11:59:58 yyyy rsyncd[5534]: sent 294382 bytes received 781 bytes total size 29221543998 +Aug 14 11:59:59 yyyy rsyncd[9874]: rsync error: timeout in data send/receive (code 30) at io.c(137) [sender=3.0.9] diff --git a/testcases/filtertestcase.py b/testcases/filtertestcase.py index 262074e6..4e60c242 100644 --- a/testcases/filtertestcase.py +++ b/testcases/filtertestcase.py @@ -606,7 +606,7 @@ class GetFailures(unittest.TestCase): self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) def testGetFailuresMultiLine(self): - output = [("192.0.43.10", 1, 1124013598.0), + output = [("192.0.43.10", 2, 1124013599.0), ("192.0.43.11", 1, 1124013598.0)] self.filter.addLogPath(GetFailures.FILENAME_MULTILINE) self.filter.addFailRegex("^.*rsyncd\[(?P\d+)\]: connect from .+ \(\)$^.+ rsyncd\[(?P=pid)\]: rsync error: .*$") @@ -620,6 +620,20 @@ class GetFailures(unittest.TestCase): self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) + def testGetFailuresMultiLineIgnoreRegex(self): + output = [("192.0.43.10", 2, 1124013599.0)] + self.filter.addLogPath(GetFailures.FILENAME_MULTILINE) + self.filter.addFailRegex("^.*rsyncd\[(?P\d+)\]: connect from .+ \(\)$^.+ rsyncd\[(?P=pid)\]: rsync error: .*$") + self.filter.addIgnoreRegex("rsync error: Received SIGINT") + self.filter.setMaxLines(100) + self.filter.setMaxRetry(1) + + self.filter.getFailures(GetFailures.FILENAME_MULTILINE) + + _assert_correct_last_attempt(self, self.filter, output.pop()) + + self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) + class DNSUtilsTests(unittest.TestCase): def testUseDns(self): From 7234c2a3aa07faa8dea755b973e835b13e8a37d6 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Fri, 25 Jan 2013 18:16:55 +0000 Subject: [PATCH 09/37] Added multiregex test for multi-line filter --- testcases/files/testcase-multiline.log | 2 ++ testcases/filtertestcase.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/testcases/files/testcase-multiline.log b/testcases/files/testcase-multiline.log index 69dac361..a8d977ab 100644 --- a/testcases/files/testcase-multiline.log +++ b/testcases/files/testcase-multiline.log @@ -13,6 +13,7 @@ Aug 14 11:59:58 yyyy rsyncd[1762]: rsync on xxx/ from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[1762]: building file list Aug 14 11:59:58 yyyy rsyncd[1762]: sent 294382 bytes received 781 bytes total size 29221543998 +Aug 14 11:59:58 yyyy sendmail[30222]: r0NNNlC0030222: from=, size=6420, class=0, nrcpts=1, msgid=<0.0.9881290652.3772024cf8879cycvau18081.0@example.com>, bodytype=8BITMIME, proto=ESMTP, daemon=MTA, relay=[192.0.43.15] (may be forged) Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sda [SAT], starting scheduled Short Self-Test. Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], SMART Usage Attribute: 194 Temperature_Celsius changed from 115 to 116 Aug 14 11:59:58 yyyy smartd[2635]: Device: /dev/sdb [SAT], starting scheduled Short Self-Test. @@ -25,6 +26,7 @@ Aug 14 11:59:58 yyyy rsyncd[7788]: rsync on xxx/ from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[7788]: building file list Aug 14 11:59:58 yyyy rsyncd[21919]: sent 2836906453 bytes received 6768 bytes total size 29221543998 Aug 14 11:59:58 yyyy rsyncd[23864]: rsync error: timeout in data send/receive (code 30) at io.c(137) [sender=3.0.9] +Aug 14 11:59:58 yyyy spamd[19119]: spamd: result: Y 11 - AWL,BAYES_50,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HTML_MESSAGE,RCVD_IN_BRBL_LASTEXT,RCVD_IN_PSBL,RCVD_IN_RP_RNBL,RDNS_NONE,URIBL_BLACK,URIBL_DBL_SPAM scantime=1.2,size=6910,user=sa-milt,uid=499,required_score=5.0,rhost=localhost,raddr=127.0.0.1,rport=57429,mid=<0.0.9881290652.3772024cf8879cycvau18081.0@example.com>,bayes=0.536244,autolearn=no Aug 14 11:59:58 yyyy rsyncd[5534]: connect from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[5534]: rsync on xxx/ from irrelevant (192.0.43.11) Aug 14 11:59:58 yyyy rsyncd[5534]: building file list diff --git a/testcases/filtertestcase.py b/testcases/filtertestcase.py index 4e60c242..f61abacb 100644 --- a/testcases/filtertestcase.py +++ b/testcases/filtertestcase.py @@ -634,6 +634,24 @@ class GetFailures(unittest.TestCase): self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) + def testGetFailuresMultiLineMultiRegex(self): + output = [("192.0.43.10", 2, 1124013599.0), + ("192.0.43.11", 1, 1124013598.0), + ("192.0.43.15", 1, 1124013598.0)] + self.filter.addLogPath(GetFailures.FILENAME_MULTILINE) + self.filter.addFailRegex("^.*rsyncd\[(?P\d+)\]: connect from .+ \(\)$^.+ rsyncd\[(?P=pid)\]: rsync error: .*$") + self.filter.addFailRegex("^.* sendmail\[.*, msgid=<(?P[^>]+).*relay=\[\].*$^.+ spamd: result: Y \d+ .*,mid=<(?P=msgid)>(,bayes=[.\d]+)?(,autolearn=\S+)?\s*$") + self.filter.setMaxLines(100) + self.filter.setMaxRetry(1) + + self.filter.getFailures(GetFailures.FILENAME_MULTILINE) + + _assert_correct_last_attempt(self, self.filter, output.pop()) + _assert_correct_last_attempt(self, self.filter, output.pop()) + _assert_correct_last_attempt(self, self.filter, output.pop()) + + self.assertRaises(FailManagerEmpty, self.filter.failManager.toBan) + class DNSUtilsTests(unittest.TestCase): def testUseDns(self): From d05f42075811f4299954f1d74ee913b42fed465e Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Fri, 25 Jan 2013 18:28:48 +0000 Subject: [PATCH 10/37] Added FilterReader test --- fail2ban-testcases | 1 + testcases/clientreadertestcase.py | 37 +++++++++++++++ testcases/files/filter.d/testcase-common.conf | 47 +++++++++++++++++++ testcases/files/filter.d/testcase01.conf | 34 ++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 testcases/files/filter.d/testcase-common.conf create mode 100644 testcases/files/filter.d/testcase01.conf diff --git a/fail2ban-testcases b/fail2ban-testcases index aaf78525..3ea3f413 100755 --- a/fail2ban-testcases +++ b/fail2ban-testcases @@ -115,6 +115,7 @@ tests.addTest(unittest.makeSuite(failmanagertestcase.AddFailure)) tests.addTest(unittest.makeSuite(banmanagertestcase.AddFailure)) # ClientReader tests.addTest(unittest.makeSuite(clientreadertestcase.JailReaderTest)) +tests.addTest(unittest.makeSuite(clientreadertestcase.FilterReaderTest)) # Filter tests.addTest(unittest.makeSuite(filtertestcase.IgnoreIP)) diff --git a/testcases/clientreadertestcase.py b/testcases/clientreadertestcase.py index 83121345..058ed5dd 100644 --- a/testcases/clientreadertestcase.py +++ b/testcases/clientreadertestcase.py @@ -29,6 +29,8 @@ __license__ = "GPL" import unittest from client.jailreader import JailReader +from client.configreader import ConfigReader +from client.filterreader import FilterReader class JailReaderTest(unittest.TestCase): @@ -44,3 +46,38 @@ class JailReaderTest(unittest.TestCase): result = JailReader.splitAction(action) self.assertEquals(expected, result) +class FilterReaderTest(unittest.TestCase): + + def setUp(self): + """Call before every test case.""" + ConfigReader.setBaseDir("testcases/files/") + + def tearDown(self): + """Call after every test case.""" + + def testConvert(self): + output = [['set', 'testcase01', 'addfailregex', + "^\\s*(?:\\S+ )?(?:kernel: \\[\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )" + "?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|" + "[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:)?\\s*(?:" + "error: PAM: )?Authentication failure for .* from \\s*$"], + ['set', 'testcase01', 'addfailregex', + "^\\s*(?:\\S+ )?(?:kernel: \\[\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )" + "?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|" + "[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:)?\\s*(?:" + "error: PAM: )?User not known to the underlying authentication mo" + "dule for .* from \\s*$"], + ['set', 'testcase01', 'addfailregex', + "^\\s*(?:\\S+ )?(?:kernel: \\[\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )" + "?(?:(?:\\[\\d+\\])?:\\s+[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?|" + "[\\[\\(]?sshd(?:\\(\\S+\\))?[\\]\\)]?:?(?:\\[\\d+\\])?:)?\\s*(?:" + "error: PAM: )?User not known to the\\nunderlying authentication." + "+$^.+ module for .* from \\s*$"], + ['set', 'testcase01', 'addignoreregex', + "^.+ john from host 192.168.1.1\\s*$"]] + filterReader = FilterReader("testcase01", "testcase01") + filterReader.read() + #filterReader.getOptions(["failregex", "ignoreregex"]) + filterReader.getOptions(None) + + self.assertEquals(filterReader.convert(), output) diff --git a/testcases/files/filter.d/testcase-common.conf b/testcases/files/filter.d/testcase-common.conf new file mode 100644 index 00000000..18bf41c5 --- /dev/null +++ b/testcases/files/filter.d/testcase-common.conf @@ -0,0 +1,47 @@ +# Generic configuration items (to be used as interpolations) in other +# filters or actions configurations +# +# Author: Yaroslav Halchenko +# +# $Revision$ +# + +[INCLUDES] + +# Load customizations if any available +after = common.local + + +[DEFAULT] + +# Daemon definition is to be specialized (if needed) in .conf file +_daemon = \S* + +# +# Shortcuts for easier comprehension of the failregex +# +# PID. +# EXAMPLES: [123] +__pid_re = (?:\[\d+\]) + +# Daemon name (with optional source_file:line or whatever) +# EXAMPLES: pam_rhosts_auth, [sshd], pop(pam_unix) +__daemon_re = [\[\(]?%(_daemon)s(?:\(\S+\))?[\]\)]?:? + +# Combinations of daemon name and PID +# EXAMPLES: sshd[31607], pop(pam_unix)[4920] +__daemon_combs_re = (?:%(__pid_re)s?:\s+%(__daemon_re)s|%(__daemon_re)s%(__pid_re)s?:) + +# Some messages have a kernel prefix with a timestamp +# EXAMPLES: kernel: [769570.846956] +__kernel_prefix = kernel: \[\d+\.\d+\] + +__hostname = \S+ + +# +# Common line prefixes (beginnings) which could be used in filters +# +# [hostname] [vserver tag] daemon_id spaces +# this can be optional (for instance if we match named native log files) +__prefix_line = \s*(?:%(__hostname)s )?(?:%(__kernel_prefix)s )?(?:@vserver_\S+ )?%(__daemon_combs_re)s?\s* + diff --git a/testcases/files/filter.d/testcase01.conf b/testcases/files/filter.d/testcase01.conf new file mode 100644 index 00000000..4a3a95e9 --- /dev/null +++ b/testcases/files/filter.d/testcase01.conf @@ -0,0 +1,34 @@ +# Fail2Ban configuration file +# +# Author: Cyril Jaquier +# +# $Revision$ +# + +[INCLUDES] + +# Read common prefixes. If any customizations available -- read them from +# common.local +before = testcase-common.conf + + +[Definition] + +_daemon = sshd + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. The +# host must be matched by a group named "host". The tag "" can +# be used for standard IP/hostname matching and is only an alias for +# (?:::f{4,6}:)?(?P[\w\-.^_]+) +# Values: TEXT +# +failregex = ^%(__prefix_line)s(?:error: PAM: )?Authentication failure for .* from \s*$ + ^%(__prefix_line)s(?:error: PAM: )?User not known to the underlying authentication module for .* from \s*$ + ^%(__prefix_line)s(?:error: PAM: )?User not known to the\nunderlying authentication.+$^.+ module for .* from \s*$ + +# Option: ignoreregex +# Notes.: regex to ignore. If this regex matches, the line is ignored. +# Values: TEXT +# +ignoreregex = ^.+ john from host 192.168.1.1\s*$ From 99914ac0f3d7af67f88b4ffb1c4413bb4c72871d Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sun, 27 Jan 2013 09:17:48 +0000 Subject: [PATCH 11/37] Regex get(Un)MatchedLines now returns whole lines only Fix issue where for regexs not anchored at start/end of line, that getMatchedLines and getUnmatchedLines returned partial lines --- server/failregex.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/server/failregex.py b/server/failregex.py index d98ffa27..608d5652 100644 --- a/server/failregex.py +++ b/server/failregex.py @@ -81,6 +81,19 @@ class Regex: def search(self, value): self._matchCache = self._regexObj.search(value) + if self.hasMatched(): + # Find start of the first line where the match was found + try: + self._matchLineStart = self._matchCache.string.rindex( + "\n", 0, self._matchCache.start() +1 ) + 1 + except ValueError: + self._matchLineStart = 0 + # Find end of the last line where the match was found + try: + self._matchLineEnd = self._matchCache.string.index( + "\n", self._matchCache.end() - 1) + 1 + except ValueError: + self._matchLineEnd = len(self._matchCache.string) ## # Checks if the previous call to search() matched. @@ -119,12 +132,12 @@ class Regex: # @return list of unmatched lines def getUnmatchedLines(self): - if not self._matchCache: + if not self.hasMatched(): return [] unmatchedLines = ( - self._matchCache.string[:self._matchCache.start()].splitlines(True) + self._matchCache.string[:self._matchLineStart].splitlines(True) + self.getSkippedLines() - + self._matchCache.string[self._matchCache.end():].splitlines(True)) + + self._matchCache.string[self._matchLineEnd:].splitlines(True)) return unmatchedLines ## @@ -135,10 +148,10 @@ class Regex: # @return list of matched lines def getMatchedLines(self): - if not self._matchCache: + if not self.hasMatched(): return [] matchedLines = self._matchCache.string[ - self._matchCache.start():self._matchCache.end()].splitlines(True) + self._matchLineStart:self._matchLineEnd].splitlines(True) return [line for line in matchedLines if line not in self.getSkippedLines()] From b48c17b8c49aed67f0979b462d7c5e0dead211ef Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sun, 27 Jan 2013 10:41:58 +0000 Subject: [PATCH 12/37] Added 'maxlines' option to fail2ban-regex This allows multi-line regex to be tested --- fail2ban-regex | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fail2ban-regex b/fail2ban-regex index 3900c909..4e5698ab 100755 --- a/fail2ban-regex +++ b/fail2ban-regex @@ -105,6 +105,7 @@ class Fail2banRegex: print " -h, --help display this help message" print " -V, --version print the version" print " -v, --verbose verbose output" + print " -l INT, --maxlines=INT set maxlines for multi-line regex default: 1" print print "Log:" print " string a string representing a log line" @@ -133,6 +134,14 @@ class Fail2banRegex: sys.exit(0) elif opt[0] in ["-v", "--verbose"]: self.__verbose = True + elif opt[0] in ["-l", "--maxlines"]: + try: + self.__filter.setMaxLines(int(opt[1])) + except ValueError: + print "Invlaid value for maxlines: %s" % ( + opt[1]) + fail2banRegex.dispUsage() + sys.exit(-1) #@staticmethod def logIsFile(value): @@ -310,8 +319,8 @@ if __name__ == "__main__": fail2banRegex = Fail2banRegex() # Reads the command line options. try: - cmdOpts = 'hVcv' - cmdLongOpts = ['help', 'version', 'verbose'] + cmdOpts = 'hVcvl:' + cmdLongOpts = ['help', 'version', 'verbose', 'maxlines='] optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts) except getopt.GetoptError: fail2banRegex.dispUsage() From 02218294bc0d012e22cec7d4c33c810df187a2be Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Mon, 28 Jan 2013 18:41:12 +0000 Subject: [PATCH 13/37] Removed "common.local" include for FilterReader test --- testcases/files/filter.d/testcase-common.conf | 6 ------ 1 file changed, 6 deletions(-) diff --git a/testcases/files/filter.d/testcase-common.conf b/testcases/files/filter.d/testcase-common.conf index 18bf41c5..af7df1f7 100644 --- a/testcases/files/filter.d/testcase-common.conf +++ b/testcases/files/filter.d/testcase-common.conf @@ -6,12 +6,6 @@ # $Revision$ # -[INCLUDES] - -# Load customizations if any available -after = common.local - - [DEFAULT] # Daemon definition is to be specialized (if needed) in .conf file From efea62e03f9da6e277d9a60a5af9e3df87f692ec Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Mon, 28 Jan 2013 20:47:32 +0000 Subject: [PATCH 14/37] Revert changes to man/fail2ban-client.1 --- man/fail2ban-client.1 | 9 --------- 1 file changed, 9 deletions(-) diff --git a/man/fail2ban-client.1 b/man/fail2ban-client.1 index d60c9481..1bbddf09 100644 --- a/man/fail2ban-client.1 +++ b/man/fail2ban-client.1 @@ -145,11 +145,6 @@ sets the number of failures before banning the host for .TP -\fBset maxlines \fR -sets the number of to -buffer for regex search for - -.TP \fBset addaction \fR adds a new action named for @@ -227,10 +222,6 @@ gets the time a host is banned for gets the number of failures allowed for .TP -\fBget maxlines\fR -gets the number lines to -buffer for -.TP \fBget addaction\fR gets the last action which has been added for From 9dc662af2794f11ab3d1dc1e68c14b87038f486e Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 11 Feb 2013 16:00:05 -0500 Subject: [PATCH 15/37] Introducing 0.9.x series with 0.9.0a0 0.9.0a0 is chosen so that StrictVersion works within python 2.x --- ChangeLog | 12 +++++++++++- README | 2 +- common/version.py | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index eabd6e81..59533c64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,9 +4,19 @@ |_| \__,_|_|_/___|_.__/\__,_|_||_| ================================================================================ -Fail2Ban (version 0.8.8) 2012/12/06 +Fail2Ban (version 0.9.0a) 20??/??/?? ================================================================================ + +ver. 0.9.0 (20??/??/??) - alpha +---------- + +Will carry all fixes in 0.8.x series and new features and enhancements + +- Fixes: +- New features: +- Enhancements: + ver. 0.8.8 (2012/12/06) - stable ---------- - Fixes: diff --git a/README b/README index db97aa8b..0a3d5117 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ |_| \__,_|_|_/___|_.__/\__,_|_||_| ================================================================================ -Fail2Ban (version 0.8.8) 2012/07/31 +Fail2Ban (version 0.9.0a0) 20??/??/?? ================================================================================ Fail2Ban scans log files like /var/log/pwdfail and bans IP that makes too many diff --git a/common/version.py b/common/version.py index 2a1c0d0b..a4499b21 100644 --- a/common/version.py +++ b/common/version.py @@ -22,7 +22,7 @@ # $Revision$ __author__ = "Cyril Jaquier, Yaroslav Halchenko" -__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2012 Yaroslav Halchenko" +__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko" __license__ = "GPL" -version = "0.8.8" +version = "0.9.0a0" From 4d4c2d7e0209bd1d7c93ac936df2f19441f228d9 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 11 Feb 2013 16:04:44 -0500 Subject: [PATCH 16/37] Brief changelog entry for multiline failregex. With this Close gh-54 --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 59533c64..e5979331 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,8 @@ Will carry all fixes in 0.8.x series and new features and enhancements - Fixes: - New features: + Steven Hiscocks + * Multiline failregex. Close gh-54 - Enhancements: ver. 0.8.8 (2012/12/06) - stable From 29d0df58be4eba2cf7e241eb57a4d311dcff682a Mon Sep 17 00:00:00 2001 From: Artur Penttinen Date: Sun, 24 Mar 2013 16:52:58 +0200 Subject: [PATCH 17/37] Added support for MySQL logfiles --- config/filter.d/mysqld.conf | 32 ++++++++++++++++++++++++++++++++ config/jail.conf | 13 +++++++++++++ server/datedetector.py | 6 ++++++ 3 files changed, 51 insertions(+) create mode 100644 config/filter.d/mysqld.conf diff --git a/config/filter.d/mysqld.conf b/config/filter.d/mysqld.conf new file mode 100644 index 00000000..bc9164ce --- /dev/null +++ b/config/filter.d/mysqld.conf @@ -0,0 +1,32 @@ +# Fail2Ban configuration file +# +# Author: Artur Penttinen +# +# $Revision$ +# + +[INCLUDES] + +# Read common prefixes. If any customizations available -- read them from +# common.local +before = common.conf + + +[Definition] + +#_daemon = mysqld + +# Option: failregex +# Notes.: regex to match the password failures messages in the logfile. The +# host must be matched by a group named "host". The tag "" can +# be used for standard IP/hostname matching and is only an alias for +# (?:::f{4,6}:)?(?P[\w\-.^_]+) +# Values: TEXT +# 130322 11:26:54 [Warning] Access denied for user 'root'@'127.0.0.1' (using password: YES) +failregex = Access denied for user '\w+'@'' + +# Option: ignoreregex +# Notes.: regex to ignore. If this regex matches, the line is ignored. +# Values: TEXT +# +ignoreregex = diff --git a/config/jail.conf b/config/jail.conf index 8bb1a6b6..d56de5d0 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -331,6 +331,19 @@ action = iptables-multiport[name=asterisk-udp, port="5060,5061", protocol=udp] logpath = /var/log/asterisk/messages maxretry = 10 +# For log wrong MySQL access add to /etc/my.cnf: +# log-error=/var/log/mysqld.log +# log-warning = 2 +[mysqld-iptables] + +enabled = false +filter = mysqld +action = iptables[name=mysql, port=3306, protocol=tcp] + sendmail-whois[name=MySQL, dest=root, sender=fail2ban@example.com] +logpath = /var/log/mysqld.log +maxretry = 5 + + # Jail for more extended banning of persistent abusers # !!! WARNING !!! # Make sure that your loglevel specified in fail2ban.conf/.local diff --git a/server/datedetector.py b/server/datedetector.py index c013d551..a54e072d 100644 --- a/server/datedetector.py +++ b/server/datedetector.py @@ -155,6 +155,12 @@ class DateDetector: template.setRegex("^<\d{2}/\d{2}/\d{2}@\d{2}:\d{2}:\d{2}>") template.setPattern("<%m/%d/%y@%H:%M:%S>") self._appendTemplate(template) + # MySQL: 130322 11:46:11 + template = DateStrptime() + template.setName("MonthDayYear Hour:Minute:Second") + template.setRegex("^\d{2}\d{2}\d{2} +\d{1,2}:\d{2}:\d{2}") + template.setPattern("%y%m%d %H:%M:%S") + self._appendTemplate(template) finally: self.__lock.release() From edc0eb2a9c4518ca8e458564fd4429c2d4c4a115 Mon Sep 17 00:00:00 2001 From: Artur Penttinen Date: Mon, 25 Mar 2013 16:00:07 +0200 Subject: [PATCH 18/37] Added testcase for MySQL date format to testcases/datedetectortestcase.py and example of MySQL log file. --- testcases/datedetectortestcase.py | 1 + testcases/files/logs/mysqld.log | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 testcases/files/logs/mysqld.log diff --git a/testcases/datedetectortestcase.py b/testcases/datedetectortestcase.py index 34ce22ce..5784387d 100644 --- a/testcases/datedetectortestcase.py +++ b/testcases/datedetectortestcase.py @@ -68,6 +68,7 @@ class DateDetectorTest(unittest.TestCase): "2005.01.23 21:59:59", "23/01/2005 21:59:59", "01-23-2005 21:59:59.252", # reported on f2b, causes Feb29 fix to break + "050123 21:59:59", # MySQL ): log = sdate + "[sshd] error: PAM: Authentication failure" # exclude diff --git a/testcases/files/logs/mysqld.log b/testcases/files/logs/mysqld.log new file mode 100644 index 00000000..8dfd6338 --- /dev/null +++ b/testcases/files/logs/mysqld.log @@ -0,0 +1,17 @@ +130323 21:14:28 [Warning] Access denied for user 'root'@'192.168.1.34' (using password: NO) +130324 0:04:00 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: NO) +130324 0:04:02 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) +130324 0:04:05 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) +130324 0:04:07 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) +130324 0:04:09 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) +130324 0:04:11 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) +130324 0:04:13 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) +130324 0:04:16 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) +130324 0:04:18 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) +130324 8:24:09 [Warning] Access denied for user 'root'@'220.95.238.171' (using password: NO) +130324 17:56:13 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: NO) +130324 17:56:14 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: YES) +130324 17:56:15 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: YES) +130324 19:01:39 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: NO) +130324 19:01:40 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: YES) +130324 19:01:41 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: YES) From d7d5228964baf589270f7f1ecdb83bcda0d6dac1 Mon Sep 17 00:00:00 2001 From: Erwan Ben Souiden Date: Tue, 26 Mar 2013 15:55:26 +0100 Subject: [PATCH 19/37] Replace the check_fail2ban script by a new one which respects the Nagios specs (like status, output, perfdata, help...). Also add a README which includes the content of f2ban.txt (which is now removed) --- files/nagios/README | 104 ++++++++++ files/nagios/check_fail2ban | 404 ++++++++++++++++++++++++++++-------- files/nagios/f2ban.txt | 18 -- 3 files changed, 426 insertions(+), 100 deletions(-) create mode 100644 files/nagios/README delete mode 100644 files/nagios/f2ban.txt diff --git a/files/nagios/README b/files/nagios/README new file mode 100644 index 00000000..99ffc4e0 --- /dev/null +++ b/files/nagios/README @@ -0,0 +1,104 @@ +Description +----------- +This plugin checks if the fail2ban server is running and how many IPs are currently banned. +You can use this plugin to monitor all the jails or just a specific jail. + + +How to use +---------- +Just have to run the following command: + $ ./check_fail2ban_activity --help + +If you need to use this script with NRPE you just have to do the +following steps: + +1 allow your user to run the script with the sudo rights. Just add + something like that in your /etc/sudoers (use visudo) : + nagios ALL=(ALL) NOPASSWD: //check_fail2ban_activity + +2 then just add this kind of line in your NRPE config file : + command[check_fail2ban]=/usr/bin/sudo //check_fail2ban_activity + +3 don't forget to restart your NRPE daemon + +/!\ be careful to let no one able to update the check_fail2ban_activity ;) +------------------------------------------------------------------------------ + + +Notes (from f2ban.txt) +----- +It seems that Fail2ban is currently not working, please login and check + +HELP: + +1.) stop the Service +/etc/init.d/fail2ban stop + +2.) delete the socket if available +rm /tmp/fail2ban.sock + +3.) start the Service +/etc/init.d/fail2ban start + +4.) check if fail2ban is working +fail2ban-client ping +Answer should be "pong" + +5.) if the answer is not "pong" run away or CRY FOR HELP ;-) + + +Help +---- + +Usage: //check_fail2ban_activity [-p] [-D "CHECK FAIL2BAN ACTIVITY"] [-v] [-c 2] [-w 1] [-s //socket] [-P /usr/bin/fail2ban-client] + +Options: + -h, --help + Print detailed help screen + -V, --version + Print version information + -D, --display=STRING + To modify the output display + default is "CHECK FAIL2BAN ACTIVITY" + -P, --path-fail2ban_client=STRING + Specify the path to the tw_cli binary + default value is /usr/bin/fail2ban-client + -c, --critical=INT + Specify a critical threshold + default is 2 + -w, --warning=INT + Specify a warning threshold + default is 1 + -s, --socket=STRING + Specify a socket path + default is unset + -p, --perfdata + If you want to activate the perfdata output + -v, --verbose + Show details for command-line debugging (Nagios may truncate the output) + + +Example +------- + +# for a specific jail +$ ./check_fail2ban_activity --verbose -p -j ssh -w 1 -c 5 -P /usr/bin/fail2ban-client +DEBUG : fail2ban_client_path: /usr/bin/fail2ban-client +DEBUG : /usr/bin/fail2ban-client exists and is executable +DEBUG : final fail2ban command: /usr/bin/fail2ban-client +DEBUG : warning threshold : 1, critical threshold : 5 +DEBUG : it seems the connection with the fail2ban server is ok +CHECK FAIL2BAN ACTIVITY - OK - 0 current banned IP(s) for the specific jail ssh | currentBannedIP=0 + +# for all the current jails +$ ./check_fail2ban_activity --verbose -p -w 1 -c 5 -P /usr/bin/fail2ban-client +DEBUG : fail2ban_client_path: /usr/bin/fail2ban-client +DEBUG : /usr/bin/fail2ban-client exists and is executable +DEBUG : final fail2ban command: /usr/bin/fail2ban-client +DEBUG : warning threshold : 1, critical threshold : 5 +DEBUG : it seems the connection with the fail2ban server is ok +DEBUG : jails list: apache, ssh-ddos, ssh +DEBUG : the jail apache has currently 0 banned IPs +DEBUG : the jail ssh-ddos has currently 0 banned IPs +DEBUG : the jail ssh has currently 0 banned IPs +CHECK FAIL2BAN ACTIVITY - OK - 3 detected jails with 0 current banned IP(s) | currentBannedIP=0 diff --git a/files/nagios/check_fail2ban b/files/nagios/check_fail2ban index 2b38e8a9..01ff2dae 100755 --- a/files/nagios/check_fail2ban +++ b/files/nagios/check_fail2ban @@ -1,105 +1,345 @@ -#!/bin/bash +#!/usr/bin/perl + +# ------------------------------------------------------- +# -=- -=- +# ------------------------------------------------------- # -# Usage: ./check_fail2ban -############################################################################################### -# Description: -# This plugin will check the status of Fail2ban. +# Description : This plugin checks if the fail2ban server is running +# and how many IPs are currently banned. +# # -# Created: 2008-10-25 (Sebastian Mueller) +# inspired by the work of Sebastian Mueller - http://www.elchtest.eu +# # -# Changes: 2008-10-26 fixed some issues (Sebastian Mueller) -# Changes: 2009-01-25 add the second check, when server is not replying and the -# process is hang-up (Sebastian Mueller) +# Version : 0.1 +# ------------------------------------------------------- +# In : +# - see the How to use section # -# please visit my website http://www.elchtest.eu or my personal WIKI http://wiki.elchtest.eu +# Out : +# - only print on the standard output # -################################################################################################ -# if you have any questions, send a mail to linux@krabbe-offline.de +# Features : +# - perfdata output +# - works with only a specific jail # -# this script is for my personal use. read the script before running/using it!!! +# Fix Me/Todo : +# - too many things ;) but let me know what do you think about it # +# #################################################################### + +# #################################################################### +# GPL v3 +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# #################################################################### + +# #################################################################### +# How to use : +# ------------ # -# YOU HAVE BEEN WARNED. THIS MAY DESTROY YOUR MACHINE. I ACCEPT NO RESPONSIBILITY. -############################################################################################### +# Just have to run the following command: +# $ ./check_fail2ban_activity --help +# +# If you need to use this script with NRPE you just have to do the +# following steps: +# +# 1 allow your user to run the script with the sudo rights. Just add +# something like that in your /etc/sudoers (use visudo) : +# nagios ALL=(ALL) NOPASSWD: //check_fail2ban_activity +# +# 2 then just add this kind of line in your NRPE config file : +# command[check_fail2ban]=/usr/bin/sudo //check_fail2ban_activity +# +# 3 don't forget to restart your NRPE daemon +# +# +# /!\ be careful to let no one able to update the check_fail2ban_activity ;) +# ------------------------------------------------------------------------------ +# +# #################################################################### + +# #################################################################### +# Changelog : +# ----------- +# +# -------------------------------------------------------------------- +# Date:12/03/2013 Version:0.1 Author:Erwan Ben Souiden +# >> creation +# #################################################################### + +# #################################################################### +# Don't touch anything under this line! +# You shall not pass - Gandalf is watching you +# #################################################################### + +use strict; +use warnings; +use Getopt::Long qw(:config no_ignore_case); + +# Generic variables +# ----------------- +my $version = '0.1'; +my $author = 'Erwan Labynocle Ben Souiden'; +my $a_mail = 'erwan@aleikoum.net'; +my $script_name = 'check_fail2ban_activity'; +my $verbose_value = 0; +my $version_value = 0; +my $more_value = 0; +my $help_value = 0; +my $perfdata_value = 0; +my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); + +# Plugin default variables +# ------------------------ +my $display = 'CHECK FAIL2BAN ACTIVITY'; +my ($critical,$warning) = (2,1); +my $fail2ban_client_path = '/usr/bin/fail2ban-client'; +my $fail2ban_socket = ''; +my $jail_specific = ''; + +GetOptions ( + 'P=s' => \ $fail2ban_client_path, + 'path-fail2ban_client=s' => \ $fail2ban_client_path, + 'j=s' => \ $jail_specific, + 'jail=s' => \ $jail_specific, + 'w=i' => \ $warning, + 'warning=i' => \ $warning, + 'socket=s' => \ $fail2ban_socket, + 'S=s' => \ $fail2ban_socket, + 'c=i' => \ $critical, + 'critical=i' => \ $critical, + 'V' => \ $version_value, + 'version' => \ $version_value, + 'h' => \ $help_value, + 'H' => \ $help_value, + 'help' => \ $help_value, + 'display=s' => \ $display, + 'D=s' => \ $display, + 'perfdata' => \ $perfdata_value, + 'p' => \ $perfdata_value, + 'v' => \ $verbose_value, + 'verbose' => \ $verbose_value +); + +print_usage() if ($help_value); +print_version() if ($version_value); -SECOND_CHECK=0 -STATE_OK=0 -STATE_CRITICAL=2 - -###################################################################### -# Read the Status from fail2ban-client -###################################################################### -check_processes_fail2ban() -{ - - F2B=`sudo -u root fail2ban-client ping | awk -F " " '{print $3}'` - exit_fail2ban=0 - - if [[ $F2B = "pong" ]]; then - exit_fail2ban=$STATE_OK - else - exit_fail2ban=$STATE_CRITICAL - fi +# Syntax check of your specified options +# -------------------------------------- +print "DEBUG : fail2ban_client_path: $fail2ban_client_path\n" if ($verbose_value); +if (($fail2ban_client_path eq "")) { + print $display.'- one or more following arguments are missing: fail2ban_client_path'."\n"; + exit $ERRORS{"UNKNOWN"}; } -###################################################################### -# first check in the Background, PID will be killed when no response -# after 10 seconds, might be possible, otherwise the script will be -# present in your memory all the time -###################################################################### -check_processes_fail2ban & -pid=$! +if(! -x $fail2ban_client_path) { + print $display.' - '.$fail2ban_client_path.' is not executable by you'."\n"; + exit $ERRORS{"UNKNOWN"}; +} +print "DEBUG : $fail2ban_client_path exists and is executable\n" if ($verbose_value); -typeset -i i=0 -while ps $pid >/dev/null -do - sleep 1 - i=$i+1 -if [ $i -ge 10 ] - then - kill $pid - SECOND_CHECK=1 - exit_fail2ban=$STATE_CRITICAL - break -fi -done +my $fail2ban_cmd = $fail2ban_client_path; +$fail2ban_cmd .= " -s $fail2ban_socket" if ($fail2ban_socket); -###################################################################### -# when the Server response (does not mean the FAIL2BAN is working) -# in the first step, then it will run again and test the Service -# and provide the real status -###################################################################### +print "DEBUG : final fail2ban command: $fail2ban_cmd\n" if ($verbose_value); + +print "DEBUG : warning threshold : $warning, critical threshold : $critical\n" if ($verbose_value); +if (($critical < 0) or ($warning < 0) or ($critical < $warning)) { + print $display.' - the thresholds must be integers and the critical threshold higher or equal than the warning threshold'."\n"; + exit $ERRORS{"UNKNOWN"}; +} + +# Core script +# ----------- +my ($how_many_jail,$how_many_banned,$return_print,$plugstate) = (0,0,"","OK"); -if [ $SECOND_CHECK -eq 0 ]; then - check_processes_fail2ban - elif [ $SECOND_CHECK -eq 1 ]; then - exit_fail2ban=$STATE_CRITICAL -fi +### Test the connection to the fail2ban server +my @command_output = `$fail2ban_cmd ping`; +my $return_code = $?; +if ($return_code) { + print $display.'CRITICAL - non-zero exit code during testing fail2ban-client ping, check if the server is running and if you have the good permissions'; + exit $ERRORS{"CRITICAL"}; +} +else { + print "DEBUG : it seems the connection with the fail2ban server is ok\n" if ($verbose_value); +} +### Only if you specify one jail +if ($jail_specific) { + my $current_ban_number = currently_ban("$fail2ban_cmd","$jail_specific"); + if ($current_ban_number == -1) { + print $display.' - CRITICAL - impossible to retrieve info about the jail '.$jail_specific; + exit $ERRORS{"CRITICAL"}; + } + else { + $how_many_banned = int($current_ban_number); + $return_print = $how_many_banned.' current banned IP(s) for the specific jail '.$jail_specific; + } +} +### To analyze all the jail +else { + # Retrieve the jails list + my @jail_list = obtain_jail_list("$fail2ban_cmd"); + if ($jail_list[0] eq "-1") { + print $display.' - CRITICAL - impossible to retrieve the jail list'."\n"; + exit $ERRORS{"CRITICAL"}; + } -###################################################################### -# Main Menu -###################################################################### + foreach (@jail_list) { + $how_many_jail ++; + + my $jail_name = $_; + $jail_name =~ tr/ //ds; + + my $current_ban_number = currently_ban("$fail2ban_cmd","$jail_name"); + if ($current_ban_number == -1) { + print "DEBUG : problem to parse the current banned IPs for jail $jail_name\n" if ($verbose_value); + } + else { + print "DEBUG : the jail $jail_name has currently $current_ban_number banned IPs\n" if ($verbose_value); + $how_many_banned += int($current_ban_number); + } + } + $return_print = $how_many_jail.' detected jails with '.$how_many_banned.' current banned IP(s)'; +} + +### Final +$plugstate = "CRITICAL" if ($how_many_banned >= $critical); +$plugstate = "WARNING" if (($how_many_banned >= $warning) && ($how_many_banned < $critical)); + +$return_print = $display." - ".$plugstate." - ".$return_print; +$return_print .= " | currentBannedIP=$how_many_banned" if ($perfdata_value); + +print $return_print; +exit $ERRORS{"$plugstate"}; -final_exit=$exit_fail2ban -if [ $final_exit -eq 0 ]; then - echo "SYSTEM OK - Fail2ban is working normally" - exitstatus=$STATE_OK -elif [ $final_exit -ne "0" ]; then - echo "SYSTEM WARNING - Fail2Ban is not working" -###################################################################### -# If don't have a Nagios Server for monitoring, remove the comment and -# add your Mail Address. You can check it with a Cron Job once an hour. -# put a txt file on your server and describe how to fix the issue, this -# could be attached to the mail. -###################################################################### -# mutt -s "FAIL2BAN NOT WORKING" your@example.com < /home/f2ban.txt +# #################################################################### +# function 1 : display the help +# ----------------------------- +sub print_usage { + print </$script_name [-p] [-D "$display"] [-v] [-c 2] [-w 1] [-s //socket] [-P /usr/bin/fail2ban-client] + +Options: + -h, --help + Print detailed help screen + -V, --version + Print version information + -D, --display=STRING + To modify the output display + default is "CHECK FAIL2BAN ACTIVITY" + -P, --path-fail2ban_client=STRING + Specify the path to the tw_cli binary + default value is /usr/bin/fail2ban-client + -c, --critical=INT + Specify a critical threshold + default is 2 + -w, --warning=INT + Specify a warning threshold + default is 1 + -s, --socket=STRING + Specify a socket path + default is unset + -p, --perfdata + If you want to activate the perfdata output + -v, --verbose + Show details for command-line debugging (Nagios may truncate the output) + +Send email to $a_mail if you have questions +regarding use of this software. To submit patches or suggest improvements, +send email to $a_mail +This plugin has been created by $author + +Hope you will enjoy it ;) + +Remember : + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + +EOT + exit $ERRORS{"UNKNOWN"}; +} + +# function 2 : display version information +# ---------------------------------------- +sub print_version { + print < Date: Tue, 26 Mar 2013 16:08:05 +0100 Subject: [PATCH 20/37] fix the script name to check_fail2ban everywhere --- files/nagios/README | 14 +++++++------- files/nagios/check_fail2ban | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/files/nagios/README b/files/nagios/README index 99ffc4e0..28e84495 100644 --- a/files/nagios/README +++ b/files/nagios/README @@ -7,21 +7,21 @@ You can use this plugin to monitor all the jails or just a specific jail. How to use ---------- Just have to run the following command: - $ ./check_fail2ban_activity --help + $ ./check_fail2ban --help If you need to use this script with NRPE you just have to do the following steps: 1 allow your user to run the script with the sudo rights. Just add something like that in your /etc/sudoers (use visudo) : - nagios ALL=(ALL) NOPASSWD: //check_fail2ban_activity + nagios ALL=(ALL) NOPASSWD: //check_fail2ban 2 then just add this kind of line in your NRPE config file : - command[check_fail2ban]=/usr/bin/sudo //check_fail2ban_activity + command[check_fail2ban]=/usr/bin/sudo //check_fail2ban 3 don't forget to restart your NRPE daemon -/!\ be careful to let no one able to update the check_fail2ban_activity ;) +/!\ be careful to let no one able to update the check_fail2ban ;) ------------------------------------------------------------------------------ @@ -50,7 +50,7 @@ Answer should be "pong" Help ---- -Usage: //check_fail2ban_activity [-p] [-D "CHECK FAIL2BAN ACTIVITY"] [-v] [-c 2] [-w 1] [-s //socket] [-P /usr/bin/fail2ban-client] +Usage: //check_fail2ban [-p] [-D "CHECK FAIL2BAN ACTIVITY"] [-v] [-c 2] [-w 1] [-s //socket] [-P /usr/bin/fail2ban-client] Options: -h, --help @@ -82,7 +82,7 @@ Example ------- # for a specific jail -$ ./check_fail2ban_activity --verbose -p -j ssh -w 1 -c 5 -P /usr/bin/fail2ban-client +$ ./check_fail2ban --verbose -p -j ssh -w 1 -c 5 -P /usr/bin/fail2ban-client DEBUG : fail2ban_client_path: /usr/bin/fail2ban-client DEBUG : /usr/bin/fail2ban-client exists and is executable DEBUG : final fail2ban command: /usr/bin/fail2ban-client @@ -91,7 +91,7 @@ DEBUG : it seems the connection with the fail2ban server is ok CHECK FAIL2BAN ACTIVITY - OK - 0 current banned IP(s) for the specific jail ssh | currentBannedIP=0 # for all the current jails -$ ./check_fail2ban_activity --verbose -p -w 1 -c 5 -P /usr/bin/fail2ban-client +$ ./check_fail2ban --verbose -p -w 1 -c 5 -P /usr/bin/fail2ban-client DEBUG : fail2ban_client_path: /usr/bin/fail2ban-client DEBUG : /usr/bin/fail2ban-client exists and is executable DEBUG : final fail2ban command: /usr/bin/fail2ban-client diff --git a/files/nagios/check_fail2ban b/files/nagios/check_fail2ban index 01ff2dae..148c92d5 100755 --- a/files/nagios/check_fail2ban +++ b/files/nagios/check_fail2ban @@ -1,7 +1,7 @@ #!/usr/bin/perl # ------------------------------------------------------- -# -=- -=- +# -=- -=- # ------------------------------------------------------- # # Description : This plugin checks if the fail2ban server is running @@ -49,22 +49,22 @@ # ------------ # # Just have to run the following command: -# $ ./check_fail2ban_activity --help +# $ ./check_fail2ban --help # # If you need to use this script with NRPE you just have to do the # following steps: # # 1 allow your user to run the script with the sudo rights. Just add # something like that in your /etc/sudoers (use visudo) : -# nagios ALL=(ALL) NOPASSWD: //check_fail2ban_activity +# nagios ALL=(ALL) NOPASSWD: //check_fail2ban # # 2 then just add this kind of line in your NRPE config file : -# command[check_fail2ban]=/usr/bin/sudo //check_fail2ban_activity +# command[check_fail2ban]=/usr/bin/sudo //check_fail2ban # # 3 don't forget to restart your NRPE daemon # # -# /!\ be careful to let no one able to update the check_fail2ban_activity ;) +# /!\ be careful to let no one able to update the check_fail2ban ;) # ------------------------------------------------------------------------------ # # #################################################################### @@ -92,7 +92,7 @@ use Getopt::Long qw(:config no_ignore_case); my $version = '0.1'; my $author = 'Erwan Labynocle Ben Souiden'; my $a_mail = 'erwan@aleikoum.net'; -my $script_name = 'check_fail2ban_activity'; +my $script_name = 'check_fail2ban'; my $verbose_value = 0; my $version_value = 0; my $more_value = 0; From b0a08b9790726312d1a4fa7ce7b4cf5d1592651b Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sat, 30 Mar 2013 18:17:01 +0000 Subject: [PATCH 21/37] TST: Add gamin support for Travis CI --- .travis.yml | 3 +++ .travis_coveragerc | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 773c5f0b..75b7ce4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,11 @@ python: - "2.5" - "2.6" - "2.7" +before_install: + - sudo apt-get update -qq install: - pip install pyinotify + - sudo apt-get install -qq python-gamin - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then pip install -q coveralls; fi script: - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then coverage run --rcfile=.travis_coveragerc fail2ban-testcases; else python ./fail2ban-testcases; fi diff --git a/.travis_coveragerc b/.travis_coveragerc index 4d4b7ebd..ac4a15d5 100644 --- a/.travis_coveragerc +++ b/.travis_coveragerc @@ -4,4 +4,3 @@ branch = True omit = /usr/* /home/travis/virtualenv/* - server/filtergamin.py From e43fcc80dbfb1c9b70ccbb200b691894b22328ca Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sat, 30 Mar 2013 18:30:23 -0400 Subject: [PATCH 22/37] BF: setBaseDir is not static method now -- so set it for the filterReader in question --- testcases/clientreadertestcase.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/testcases/clientreadertestcase.py b/testcases/clientreadertestcase.py index 21dd4745..8eccb2b9 100644 --- a/testcases/clientreadertestcase.py +++ b/testcases/clientreadertestcase.py @@ -113,13 +113,6 @@ class JailReaderTest(unittest.TestCase): class FilterReaderTest(unittest.TestCase): - def setUp(self): - """Call before every test case.""" - ConfigReader.setBaseDir("testcases/files/") - - def tearDown(self): - """Call after every test case.""" - def testConvert(self): output = [['set', 'testcase01', 'addfailregex', "^\\s*(?:\\S+ )?(?:kernel: \\[\\d+\\.\\d+\\] )?(?:@vserver_\\S+ )" @@ -141,6 +134,7 @@ class FilterReaderTest(unittest.TestCase): ['set', 'testcase01', 'addignoreregex', "^.+ john from host 192.168.1.1\\s*$"]] filterReader = FilterReader("testcase01", "testcase01") + filterReader.setBaseDir("testcases/files/") filterReader.read() #filterReader.getOptions(["failregex", "ignoreregex"]) filterReader.getOptions(None) From dba88e842f3583ce7f213d06892db7f68d890209 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sun, 31 Mar 2013 18:18:21 +0100 Subject: [PATCH 23/37] ENH+BF+TST+DOC: Make fail2ban a python module --- DEVELOP | 4 +- MANIFEST | 76 +++++++++---------- fail2ban-client | 18 ++--- fail2ban-regex | 17 ++--- fail2ban-server | 11 +-- fail2ban-testcases | 10 +-- {client => fail2ban}/__init__.py | 0 {common => fail2ban/client}/__init__.py | 0 {client => fail2ban/client}/actionreader.py | 0 {client => fail2ban/client}/beautifier.py | 2 +- .../client}/configparserinc.py | 0 {client => fail2ban/client}/configreader.py | 0 {client => fail2ban/client}/configurator.py | 0 {client => fail2ban/client}/csocket.py | 0 {client => fail2ban/client}/fail2banreader.py | 0 {client => fail2ban/client}/filterreader.py | 0 {client => fail2ban/client}/jailreader.py | 0 {client => fail2ban/client}/jailsreader.py | 0 {common => fail2ban}/exceptions.py | 0 {common => fail2ban}/helpers.py | 0 {common => fail2ban}/protocol.py | 0 {server => fail2ban/server}/__init__.py | 0 {server => fail2ban/server}/action.py | 0 {server => fail2ban/server}/actions.py | 0 {server => fail2ban/server}/asyncserver.py | 3 +- {server => fail2ban/server}/banmanager.py | 0 {server => fail2ban/server}/datedetector.py | 0 {server => fail2ban/server}/datetemplate.py | 0 {server => fail2ban/server}/faildata.py | 0 {server => fail2ban/server}/failmanager.py | 0 {server => fail2ban/server}/failregex.py | 0 {server => fail2ban/server}/filter.py | 0 {server => fail2ban/server}/filtergamin.py | 0 {server => fail2ban/server}/filterpoll.py | 0 .../server}/filterpyinotify.py | 0 {server => fail2ban/server}/iso8601.py | 0 {server => fail2ban/server}/jail.py | 0 {server => fail2ban/server}/jails.py | 2 +- {server => fail2ban/server}/jailthread.py | 0 {server => fail2ban/server}/mytime.py | 0 {server => fail2ban/server}/server.py | 2 +- {server => fail2ban/server}/ticket.py | 0 {server => fail2ban/server}/transmitter.py | 0 {common => fail2ban}/version.py | 0 setup.cfg | 3 - setup.py | 15 ++-- testcases/actiontestcase.py | 3 +- testcases/banmanagertestcase.py | 5 +- testcases/clientreadertestcase.py | 9 ++- testcases/datedetectortestcase.py | 5 +- testcases/failmanagertestcase.py | 5 +- testcases/filtertestcase.py | 10 +-- testcases/servertestcase.py | 5 +- testcases/sockettestcase.py | 5 +- 54 files changed, 97 insertions(+), 113 deletions(-) rename {client => fail2ban}/__init__.py (100%) rename {common => fail2ban/client}/__init__.py (100%) rename {client => fail2ban/client}/actionreader.py (100%) rename {client => fail2ban/client}/beautifier.py (98%) rename {client => fail2ban/client}/configparserinc.py (100%) rename {client => fail2ban/client}/configreader.py (100%) rename {client => fail2ban/client}/configurator.py (100%) rename {client => fail2ban/client}/csocket.py (100%) rename {client => fail2ban/client}/fail2banreader.py (100%) rename {client => fail2ban/client}/filterreader.py (100%) rename {client => fail2ban/client}/jailreader.py (100%) rename {client => fail2ban/client}/jailsreader.py (100%) rename {common => fail2ban}/exceptions.py (100%) rename {common => fail2ban}/helpers.py (100%) rename {common => fail2ban}/protocol.py (100%) rename {server => fail2ban/server}/__init__.py (100%) rename {server => fail2ban/server}/action.py (100%) rename {server => fail2ban/server}/actions.py (100%) rename {server => fail2ban/server}/asyncserver.py (99%) rename {server => fail2ban/server}/banmanager.py (100%) rename {server => fail2ban/server}/datedetector.py (100%) rename {server => fail2ban/server}/datetemplate.py (100%) rename {server => fail2ban/server}/faildata.py (100%) rename {server => fail2ban/server}/failmanager.py (100%) rename {server => fail2ban/server}/failregex.py (100%) rename {server => fail2ban/server}/filter.py (100%) rename {server => fail2ban/server}/filtergamin.py (100%) rename {server => fail2ban/server}/filterpoll.py (100%) rename {server => fail2ban/server}/filterpyinotify.py (100%) rename {server => fail2ban/server}/iso8601.py (100%) rename {server => fail2ban/server}/jail.py (100%) rename {server => fail2ban/server}/jails.py (98%) rename {server => fail2ban/server}/jailthread.py (100%) rename {server => fail2ban/server}/mytime.py (100%) rename {server => fail2ban/server}/server.py (99%) rename {server => fail2ban/server}/ticket.py (100%) rename {server => fail2ban/server}/transmitter.py (100%) rename {common => fail2ban}/version.py (100%) diff --git a/DEVELOP b/DEVELOP index 623aee12..158fb2b2 100644 --- a/DEVELOP +++ b/DEVELOP @@ -249,7 +249,7 @@ Takes care about executing start/check/ban/unban/stop commands Releasing ========= -# Ensure the version is correct in ./common/version.py +# Ensure the version is correct in ./fail2ban/version.py # Add/finalize the corresponding entry in the ChangeLog @@ -271,7 +271,7 @@ Releasing # Run the following and update the wiki with output: - python -c 'import common.protocol; common.protocol.printWiki()' + python -c 'import fail2ban.protocol; fail2ban.protocol.printWiki()' # Email users and development list of release diff --git a/MANIFEST b/MANIFEST index 28063b83..fc56356a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,39 +9,39 @@ fail2ban-client fail2ban-server fail2ban-testcases fail2ban-regex -client/configreader.py -client/configparserinc.py -client/jailreader.py -client/fail2banreader.py -client/jailsreader.py -client/beautifier.py -client/filterreader.py -client/actionreader.py -client/__init__.py -client/configurator.py -client/csocket.py -server/asyncserver.py -server/filter.py -server/filterpyinotify.py -server/filtergamin.py -server/filterpoll.py -server/iso8601.py -server/server.py -server/actions.py -server/faildata.py -server/failmanager.py -server/datedetector.py -server/jailthread.py -server/transmitter.py -server/action.py -server/ticket.py -server/jail.py -server/jails.py -server/__init__.py -server/banmanager.py -server/datetemplate.py -server/mytime.py -server/failregex.py +fail2ban/client/configreader.py +fail2ban/client/configparserinc.py +fail2ban/client/jailreader.py +fail2ban/client/fail2banreader.py +fail2ban/client/jailsreader.py +fail2ban/client/beautifier.py +fail2ban/client/filterreader.py +fail2ban/client/actionreader.py +fail2ban/client/__init__.py +fail2ban/client/configurator.py +fail2ban/client/csocket.py +fail2ban/server/asyncserver.py +fail2ban/server/filter.py +fail2ban/server/filterpyinotify.py +fail2ban/server/filtergamin.py +fail2ban/server/filterpoll.py +fail2ban/server/iso8601.py +fail2ban/server/server.py +fail2ban/server/actions.py +fail2ban/server/faildata.py +fail2ban/server/failmanager.py +fail2ban/server/datedetector.py +fail2ban/server/jailthread.py +fail2ban/server/transmitter.py +fail2ban/server/action.py +fail2ban/server/ticket.py +fail2ban/server/jail.py +fail2ban/server/jails.py +fail2ban/server/__init__.py +fail2ban/server/banmanager.py +fail2ban/server/datetemplate.py +fail2ban/server/mytime.py +fail2ban/server/failregex.py testcases/files/testcase-usedns.log testcases/banmanagertestcase.py testcases/failmanagertestcase.py @@ -58,11 +58,11 @@ testcases/files/testcase03.log testcases/files/testcase04.log setup.py setup.cfg -common/__init__.py -common/exceptions.py -common/helpers.py -common/version.py -common/protocol.py +fail2ban/__init__.py +fail2ban/exceptions.py +fail2ban/helpers.py +fail2ban/version.py +fail2ban/protocol.py config/jail.conf config/filter.d/common.conf config/filter.d/apache-auth.conf diff --git a/fail2ban-client b/fail2ban-client index d8147f02..8068d60f 100755 --- a/fail2ban-client +++ b/fail2ban-client @@ -25,19 +25,11 @@ __license__ = "GPL" import sys, string, os, pickle, re, logging, signal import getopt, time, shlex, socket -# Inserts our own modules path first in the list -# fix for bug #343821 -try: - from common.version import version -except ImportError, e: - sys.path.insert(1, "/usr/share/fail2ban") - from common.version import version - -# Now we can import the rest of modules -from common.protocol import printFormatted -from client.csocket import CSocket -from client.configurator import Configurator -from client.beautifier import Beautifier +from fail2ban.version import version +from fail2ban.protocol import printFormatted +from fail2ban.client.csocket import CSocket +from fail2ban.client.configurator import Configurator +from fail2ban.client.beautifier import Beautifier # Gets the instance of the logger. logSys = logging.getLogger("fail2ban.client") diff --git a/fail2ban-regex b/fail2ban-regex index a0a90b05..6bff21de 100755 --- a/fail2ban-regex +++ b/fail2ban-regex @@ -23,19 +23,12 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012 Yaroslav Halchenko" __license__ = "GPL" import getopt, sys, time, logging, os - -# Inserts our own modules path first in the list -# fix for bug #343821 -try: - from common.version import version -except ImportError, e: - sys.path.insert(1, "/usr/share/fail2ban") - from common.version import version - -from client.configparserinc import SafeConfigParserWithIncludes from ConfigParser import NoOptionError, NoSectionError, MissingSectionHeaderError -from server.filter import Filter -from server.failregex import RegexException + +from fail2ban.version import version +from fail2ban.client.configparserinc import SafeConfigParserWithIncludes +from fail2ban.server.filter import Filter +from fail2ban.server.failregex import RegexException # Gets the instance of the logger. logSys = logging.getLogger("fail2ban.regex") diff --git a/fail2ban-server b/fail2ban-server index 404a1ced..3a1686d3 100755 --- a/fail2ban-server +++ b/fail2ban-server @@ -24,15 +24,8 @@ __license__ = "GPL" import getopt, sys, logging, os -# Inserts our own modules path first in the list -# fix for bug #343821 -try: - from common.version import version -except ImportError, e: - sys.path.insert(1, "/usr/share/fail2ban") - from common.version import version - -from server.server import Server +from fail2ban.version import version +from fail2ban.server.server import Server # Gets the instance of the logger. logSys = logging.getLogger("fail2ban") diff --git a/fail2ban-testcases b/fail2ban-testcases index e00cc908..c10856ec 100755 --- a/fail2ban-testcases +++ b/fail2ban-testcases @@ -27,7 +27,7 @@ __license__ = "GPL" import unittest, logging, sys, time, os -from common.version import version +from fail2ban.version import version from testcases import banmanagertestcase from testcases import clientreadertestcase from testcases import failmanagertestcase @@ -38,7 +38,7 @@ from testcases import actiontestcase from testcases import sockettestcase from testcases.utils import FormatterWithTraceBack -from server.mytime import MyTime +from fail2ban.server.mytime import MyTime from optparse import OptionParser, Option @@ -168,20 +168,20 @@ tests.addTest(unittest.makeSuite(datedetectortestcase.DateDetectorTest)) # Extensive use-tests of different available filters backends # -from server.filterpoll import FilterPoll +from fail2ban.server.filterpoll import FilterPoll filters = [FilterPoll] # always available # Additional filters available only if external modules are available # yoh: Since I do not know better way for parametric tests # with good old unittest try: - from server.filtergamin import FilterGamin + from fail2ban.server.filtergamin import FilterGamin filters.append(FilterGamin) except Exception, e: # pragma: no cover print "I: Skipping gamin backend testing. Got exception '%s'" % e try: - from server.filterpyinotify import FilterPyinotify + from fail2ban.server.filterpyinotify import FilterPyinotify filters.append(FilterPyinotify) except Exception, e: # pragma: no cover print "I: Skipping pyinotify backend testing. Got exception '%s'" % e diff --git a/client/__init__.py b/fail2ban/__init__.py similarity index 100% rename from client/__init__.py rename to fail2ban/__init__.py diff --git a/common/__init__.py b/fail2ban/client/__init__.py similarity index 100% rename from common/__init__.py rename to fail2ban/client/__init__.py diff --git a/client/actionreader.py b/fail2ban/client/actionreader.py similarity index 100% rename from client/actionreader.py rename to fail2ban/client/actionreader.py diff --git a/client/beautifier.py b/fail2ban/client/beautifier.py similarity index 98% rename from client/beautifier.py rename to fail2ban/client/beautifier.py index 7e48016c..1403bb08 100644 --- a/client/beautifier.py +++ b/fail2ban/client/beautifier.py @@ -23,7 +23,7 @@ __license__ = "GPL" import logging -from common.exceptions import UnknownJailException, DuplicateJailException +from fail2ban.exceptions import UnknownJailException, DuplicateJailException # Gets the instance of the logger. logSys = logging.getLogger("fail2ban.client.config") diff --git a/client/configparserinc.py b/fail2ban/client/configparserinc.py similarity index 100% rename from client/configparserinc.py rename to fail2ban/client/configparserinc.py diff --git a/client/configreader.py b/fail2ban/client/configreader.py similarity index 100% rename from client/configreader.py rename to fail2ban/client/configreader.py diff --git a/client/configurator.py b/fail2ban/client/configurator.py similarity index 100% rename from client/configurator.py rename to fail2ban/client/configurator.py diff --git a/client/csocket.py b/fail2ban/client/csocket.py similarity index 100% rename from client/csocket.py rename to fail2ban/client/csocket.py diff --git a/client/fail2banreader.py b/fail2ban/client/fail2banreader.py similarity index 100% rename from client/fail2banreader.py rename to fail2ban/client/fail2banreader.py diff --git a/client/filterreader.py b/fail2ban/client/filterreader.py similarity index 100% rename from client/filterreader.py rename to fail2ban/client/filterreader.py diff --git a/client/jailreader.py b/fail2ban/client/jailreader.py similarity index 100% rename from client/jailreader.py rename to fail2ban/client/jailreader.py diff --git a/client/jailsreader.py b/fail2ban/client/jailsreader.py similarity index 100% rename from client/jailsreader.py rename to fail2ban/client/jailsreader.py diff --git a/common/exceptions.py b/fail2ban/exceptions.py similarity index 100% rename from common/exceptions.py rename to fail2ban/exceptions.py diff --git a/common/helpers.py b/fail2ban/helpers.py similarity index 100% rename from common/helpers.py rename to fail2ban/helpers.py diff --git a/common/protocol.py b/fail2ban/protocol.py similarity index 100% rename from common/protocol.py rename to fail2ban/protocol.py diff --git a/server/__init__.py b/fail2ban/server/__init__.py similarity index 100% rename from server/__init__.py rename to fail2ban/server/__init__.py diff --git a/server/action.py b/fail2ban/server/action.py similarity index 100% rename from server/action.py rename to fail2ban/server/action.py diff --git a/server/actions.py b/fail2ban/server/actions.py similarity index 100% rename from server/actions.py rename to fail2ban/server/actions.py diff --git a/server/asyncserver.py b/fail2ban/server/asyncserver.py similarity index 99% rename from server/asyncserver.py rename to fail2ban/server/asyncserver.py index 66b2b53f..d5fb791c 100644 --- a/server/asyncserver.py +++ b/fail2ban/server/asyncserver.py @@ -28,9 +28,10 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" from pickle import dumps, loads, HIGHEST_PROTOCOL -from common import helpers import asyncore, asynchat, socket, os, logging, sys, traceback +from fail2ban import helpers + # Gets the instance of the logger. logSys = logging.getLogger("fail2ban.server") diff --git a/server/banmanager.py b/fail2ban/server/banmanager.py similarity index 100% rename from server/banmanager.py rename to fail2ban/server/banmanager.py diff --git a/server/datedetector.py b/fail2ban/server/datedetector.py similarity index 100% rename from server/datedetector.py rename to fail2ban/server/datedetector.py diff --git a/server/datetemplate.py b/fail2ban/server/datetemplate.py similarity index 100% rename from server/datetemplate.py rename to fail2ban/server/datetemplate.py diff --git a/server/faildata.py b/fail2ban/server/faildata.py similarity index 100% rename from server/faildata.py rename to fail2ban/server/faildata.py diff --git a/server/failmanager.py b/fail2ban/server/failmanager.py similarity index 100% rename from server/failmanager.py rename to fail2ban/server/failmanager.py diff --git a/server/failregex.py b/fail2ban/server/failregex.py similarity index 100% rename from server/failregex.py rename to fail2ban/server/failregex.py diff --git a/server/filter.py b/fail2ban/server/filter.py similarity index 100% rename from server/filter.py rename to fail2ban/server/filter.py diff --git a/server/filtergamin.py b/fail2ban/server/filtergamin.py similarity index 100% rename from server/filtergamin.py rename to fail2ban/server/filtergamin.py diff --git a/server/filterpoll.py b/fail2ban/server/filterpoll.py similarity index 100% rename from server/filterpoll.py rename to fail2ban/server/filterpoll.py diff --git a/server/filterpyinotify.py b/fail2ban/server/filterpyinotify.py similarity index 100% rename from server/filterpyinotify.py rename to fail2ban/server/filterpyinotify.py diff --git a/server/iso8601.py b/fail2ban/server/iso8601.py similarity index 100% rename from server/iso8601.py rename to fail2ban/server/iso8601.py diff --git a/server/jail.py b/fail2ban/server/jail.py similarity index 100% rename from server/jail.py rename to fail2ban/server/jail.py diff --git a/server/jails.py b/fail2ban/server/jails.py similarity index 98% rename from server/jails.py rename to fail2ban/server/jails.py index 4bf5f971..7ea1dde0 100644 --- a/server/jails.py +++ b/fail2ban/server/jails.py @@ -21,7 +21,7 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko" __license__ = "GPL" -from common.exceptions import DuplicateJailException, UnknownJailException +from fail2ban.exceptions import DuplicateJailException, UnknownJailException from jail import Jail from threading import Lock diff --git a/server/jailthread.py b/fail2ban/server/jailthread.py similarity index 100% rename from server/jailthread.py rename to fail2ban/server/jailthread.py diff --git a/server/mytime.py b/fail2ban/server/mytime.py similarity index 100% rename from server/mytime.py rename to fail2ban/server/mytime.py diff --git a/server/server.py b/fail2ban/server/server.py similarity index 99% rename from server/server.py rename to fail2ban/server/server.py index a0824f1d..e8696b36 100644 --- a/server/server.py +++ b/fail2ban/server/server.py @@ -32,7 +32,7 @@ from jails import Jails from transmitter import Transmitter from asyncserver import AsyncServer from asyncserver import AsyncServerException -from common import version +from fail2ban import version import logging, logging.handlers, sys, os, signal # Gets the instance of the logger. diff --git a/server/ticket.py b/fail2ban/server/ticket.py similarity index 100% rename from server/ticket.py rename to fail2ban/server/ticket.py diff --git a/server/transmitter.py b/fail2ban/server/transmitter.py similarity index 100% rename from server/transmitter.py rename to fail2ban/server/transmitter.py diff --git a/common/version.py b/fail2ban/version.py similarity index 100% rename from common/version.py rename to fail2ban/version.py diff --git a/setup.cfg b/setup.cfg index 74c22b25..bb016599 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,3 @@ -[install] -install-purelib=/usr/share/fail2ban - [sdist] formats=bztar diff --git a/setup.py b/setup.py index 784999a2..004f2f84 100755 --- a/setup.py +++ b/setup.py @@ -23,11 +23,12 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" from distutils.core import setup -from common.version import version from os.path import isfile, join, isdir -from sys import argv +import sys from glob import glob +from fail2ban.version import version + longdesc = ''' Fail2Ban scans log files like /var/log/pwdfail or /var/log/apache/error_log and bans IP that makes @@ -38,7 +39,7 @@ commands.''' setup( name = "fail2ban", version = version, - description = "Ban IPs that make too many password failure", + description = "Ban IPs that make too many password failures", long_description = longdesc, author = "Cyril Jaquier", author_email = "cyril.jaquier@fail2ban.org", @@ -51,9 +52,9 @@ setup( 'fail2ban-regex' ], packages = [ - 'common', - 'client', - 'server' + 'fail2ban', + 'fail2ban.client', + 'fail2ban.server' ], data_files = [ ('/etc/fail2ban', @@ -117,7 +118,7 @@ if isdir("/usr/lib/fail2ban"): print # Update config file -if argv[1] == "install": +if sys.argv[1] == "install": print print "Please do not forget to update your configuration files." print "They are in /etc/fail2ban/." diff --git a/testcases/actiontestcase.py b/testcases/actiontestcase.py index b8292c27..e0ea3a9b 100644 --- a/testcases/actiontestcase.py +++ b/testcases/actiontestcase.py @@ -29,9 +29,10 @@ __license__ = "GPL" import unittest, time import logging, sys -from server.action import Action from StringIO import StringIO +from fail2ban.server.action import Action + class ExecuteAction(unittest.TestCase): def setUp(self): diff --git a/testcases/banmanagertestcase.py b/testcases/banmanagertestcase.py index 6d0ce55a..8d0f1929 100644 --- a/testcases/banmanagertestcase.py +++ b/testcases/banmanagertestcase.py @@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" import unittest -from server.banmanager import BanManager -from server.ticket import BanTicket + +from fail2ban.server.banmanager import BanManager +from fail2ban.server.ticket import BanTicket class AddFailure(unittest.TestCase): diff --git a/testcases/clientreadertestcase.py b/testcases/clientreadertestcase.py index fad16f04..f54df659 100644 --- a/testcases/clientreadertestcase.py +++ b/testcases/clientreadertestcase.py @@ -22,10 +22,11 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko" __license__ = "GPL" import os, shutil, tempfile, unittest -from client.configreader import ConfigReader -from client.jailreader import JailReader -from client.jailsreader import JailsReader -from client.configurator import Configurator + +from fail2ban.client.configreader import ConfigReader +from fail2ban.client.jailreader import JailReader +from fail2ban.client.jailsreader import JailsReader +from fail2ban.client.configurator import Configurator class ConfigReaderTest(unittest.TestCase): diff --git a/testcases/datedetectortestcase.py b/testcases/datedetectortestcase.py index 64af1fab..e9cabca0 100644 --- a/testcases/datedetectortestcase.py +++ b/testcases/datedetectortestcase.py @@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" import unittest -from server.datedetector import DateDetector -from server.datetemplate import DateTemplate + +from fail2ban.server.datedetector import DateDetector +from fail2ban.server.datetemplate import DateTemplate class DateDetectorTest(unittest.TestCase): diff --git a/testcases/failmanagertestcase.py b/testcases/failmanagertestcase.py index ffee4ff1..7a714122 100644 --- a/testcases/failmanagertestcase.py +++ b/testcases/failmanagertestcase.py @@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" import unittest, socket, time, pickle -from server.failmanager import FailManager, FailManagerEmpty -from server.ticket import FailTicket + +from fail2ban.server.failmanager import FailManager, FailManagerEmpty +from fail2ban.server.ticket import FailTicket class AddFailure(unittest.TestCase): diff --git a/testcases/filtertestcase.py b/testcases/filtertestcase.py index 927cb2fe..75b72c05 100644 --- a/testcases/filtertestcase.py +++ b/testcases/filtertestcase.py @@ -29,11 +29,11 @@ import sys import time import tempfile -from server.jail import Jail -from server.filterpoll import FilterPoll -from server.filter import FileFilter, DNSUtils -from server.failmanager import FailManager -from server.failmanager import FailManagerEmpty +from fail2ban.server.jail import Jail +from fail2ban.server.filterpoll import FilterPoll +from fail2ban.server.filter import FileFilter, DNSUtils +from fail2ban.server.failmanager import FailManager +from fail2ban.server.failmanager import FailManagerEmpty # # Useful helpers diff --git a/testcases/servertestcase.py b/testcases/servertestcase.py index ffb057a9..0cdf0422 100644 --- a/testcases/servertestcase.py +++ b/testcases/servertestcase.py @@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" import unittest, socket, time, tempfile, os -from server.server import Server -from common.exceptions import UnknownJailException + +from fail2ban.server.server import Server +from fail2ban.exceptions import UnknownJailException class StartStop(unittest.TestCase): diff --git a/testcases/sockettestcase.py b/testcases/sockettestcase.py index 4cd5a687..bbca8dde 100644 --- a/testcases/sockettestcase.py +++ b/testcases/sockettestcase.py @@ -28,8 +28,9 @@ __copyright__ = "Copyright (c) 2013 Steven Hiscocks" __license__ = "GPL" import unittest, time, tempfile, os, threading -from server.asyncserver import AsyncServer, AsyncServerException -from client.csocket import CSocket + +from fail2ban.server.asyncserver import AsyncServer, AsyncServerException +from fail2ban.client.csocket import CSocket class Socket(unittest.TestCase): From e53bfafd6afaa07b7049163a3363ab7cead789e9 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sun, 31 Mar 2013 19:36:52 +0100 Subject: [PATCH 24/37] TST: Update Travis CI coverage config for python module structure --- .travis_coveragerc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis_coveragerc b/.travis_coveragerc index 4d4b7ebd..3f6404ff 100644 --- a/.travis_coveragerc +++ b/.travis_coveragerc @@ -4,4 +4,4 @@ branch = True omit = /usr/* /home/travis/virtualenv/* - server/filtergamin.py + fail2ban/server/filtergamin.py From e3bd2042ebcdf891eef7d04632b22ce82e1eeffd Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Mon, 1 Apr 2013 11:22:40 +0100 Subject: [PATCH 25/37] TST+ENH: Move testcases to part of fail2ban module This allows fail2ban-testcases to be run on an installed fail2ban instance. TODO: Fix tests requiring config files --- MANIFEST | 29 ++++++++++--------- fail2ban-testcases | 18 ++++++------ {testcases => fail2ban/tests}/__init__.py | 0 .../tests}/actiontestcase.py | 0 .../tests}/banmanagertestcase.py | 0 .../tests}/clientreadertestcase.py | 0 .../tests}/datedetectortestcase.py | 0 .../tests}/failmanagertestcase.py | 0 .../tests}/files/logs/apache-overflows | 0 .../tests}/files/logs/asterisk | 0 .../tests}/files/logs/dovecot | 0 {testcases => fail2ban/tests}/files/logs/exim | 0 .../tests}/files/logs/lighttpd | 0 .../tests}/files/logs/named-refused | 0 .../tests}/files/logs/pam-generic | 0 .../tests}/files/logs/postfix | 0 .../tests}/files/logs/proftpd | 0 .../tests}/files/logs/pure-ftpd | 0 .../tests}/files/logs/roundcube-auth | 0 {testcases => fail2ban/tests}/files/logs/sasl | 0 .../tests}/files/logs/sogo-auth | 0 {testcases => fail2ban/tests}/files/logs/sshd | 0 .../tests}/files/logs/sshd-ddos | 0 .../tests}/files/logs/vsftpd | 0 .../tests}/files/logs/webmin-auth | 0 .../tests}/files/logs/wu-ftpd | 0 .../tests}/files/testcase-usedns.log | 0 .../tests}/files/testcase01.log | 0 .../tests}/files/testcase02.log | 0 .../tests}/files/testcase03.log | 0 .../tests}/files/testcase04.log | 0 .../tests}/filtertestcase.py | 14 +++++---- .../tests}/servertestcase.py | 10 ++++--- .../tests}/sockettestcase.py | 0 {testcases => fail2ban/tests}/utils.py | 0 setup.py | 9 ++++-- 36 files changed, 45 insertions(+), 35 deletions(-) rename {testcases => fail2ban/tests}/__init__.py (100%) rename {testcases => fail2ban/tests}/actiontestcase.py (100%) rename {testcases => fail2ban/tests}/banmanagertestcase.py (100%) rename {testcases => fail2ban/tests}/clientreadertestcase.py (100%) rename {testcases => fail2ban/tests}/datedetectortestcase.py (100%) rename {testcases => fail2ban/tests}/failmanagertestcase.py (100%) rename {testcases => fail2ban/tests}/files/logs/apache-overflows (100%) rename {testcases => fail2ban/tests}/files/logs/asterisk (100%) rename {testcases => fail2ban/tests}/files/logs/dovecot (100%) rename {testcases => fail2ban/tests}/files/logs/exim (100%) rename {testcases => fail2ban/tests}/files/logs/lighttpd (100%) rename {testcases => fail2ban/tests}/files/logs/named-refused (100%) rename {testcases => fail2ban/tests}/files/logs/pam-generic (100%) rename {testcases => fail2ban/tests}/files/logs/postfix (100%) rename {testcases => fail2ban/tests}/files/logs/proftpd (100%) rename {testcases => fail2ban/tests}/files/logs/pure-ftpd (100%) rename {testcases => fail2ban/tests}/files/logs/roundcube-auth (100%) rename {testcases => fail2ban/tests}/files/logs/sasl (100%) rename {testcases => fail2ban/tests}/files/logs/sogo-auth (100%) rename {testcases => fail2ban/tests}/files/logs/sshd (100%) rename {testcases => fail2ban/tests}/files/logs/sshd-ddos (100%) rename {testcases => fail2ban/tests}/files/logs/vsftpd (100%) rename {testcases => fail2ban/tests}/files/logs/webmin-auth (100%) rename {testcases => fail2ban/tests}/files/logs/wu-ftpd (100%) rename {testcases => fail2ban/tests}/files/testcase-usedns.log (100%) rename {testcases => fail2ban/tests}/files/testcase01.log (100%) rename {testcases => fail2ban/tests}/files/testcase02.log (100%) rename {testcases => fail2ban/tests}/files/testcase03.log (100%) rename {testcases => fail2ban/tests}/files/testcase04.log (100%) rename {testcases => fail2ban/tests}/filtertestcase.py (98%) rename {testcases => fail2ban/tests}/servertestcase.py (98%) rename {testcases => fail2ban/tests}/sockettestcase.py (100%) rename {testcases => fail2ban/tests}/utils.py (100%) diff --git a/MANIFEST b/MANIFEST index fc56356a..93698e95 100644 --- a/MANIFEST +++ b/MANIFEST @@ -42,20 +42,21 @@ fail2ban/server/banmanager.py fail2ban/server/datetemplate.py fail2ban/server/mytime.py fail2ban/server/failregex.py -testcases/files/testcase-usedns.log -testcases/banmanagertestcase.py -testcases/failmanagertestcase.py -testcases/clientreadertestcase.py -testcases/filtertestcase.py -testcases/__init__.py -testcases/datedetectortestcase.py -testcases/actiontestcase.py -testcases/servertestcase.py -testcases/sockettestcase.py -testcases/files/testcase01.log -testcases/files/testcase02.log -testcases/files/testcase03.log -testcases/files/testcase04.log +fail2ban/tests/banmanagertestcase.py +fail2ban/tests/failmanagertestcase.py +fail2ban/tests/clientreadertestcase.py +fail2ban/tests/filtertestcase.py +fail2ban/tests/__init__.py +fail2ban/tests/datedetectortestcase.py +fail2ban/tests/actiontestcase.py +fail2ban/tests/servertestcase.py +fail2ban/tests/sockettestcase.py +fail2ban/tests/utils.py +fail2ban/tests/files/testcase01.log +fail2ban/tests/files/testcase02.log +fail2ban/tests/files/testcase03.log +fail2ban/tests/files/testcase04.log +fail2ban/tests/files/testcase-usedns.log setup.py setup.cfg fail2ban/__init__.py diff --git a/fail2ban-testcases b/fail2ban-testcases index c10856ec..45ba03ad 100755 --- a/fail2ban-testcases +++ b/fail2ban-testcases @@ -28,16 +28,16 @@ __license__ = "GPL" import unittest, logging, sys, time, os from fail2ban.version import version -from testcases import banmanagertestcase -from testcases import clientreadertestcase -from testcases import failmanagertestcase -from testcases import filtertestcase -from testcases import servertestcase -from testcases import datedetectortestcase -from testcases import actiontestcase -from testcases import sockettestcase +from fail2ban.tests import banmanagertestcase +from fail2ban.tests import clientreadertestcase +from fail2ban.tests import failmanagertestcase +from fail2ban.tests import filtertestcase +from fail2ban.tests import servertestcase +from fail2ban.tests import datedetectortestcase +from fail2ban.tests import actiontestcase +from fail2ban.tests import sockettestcase -from testcases.utils import FormatterWithTraceBack +from fail2ban.tests.utils import FormatterWithTraceBack from fail2ban.server.mytime import MyTime from optparse import OptionParser, Option diff --git a/testcases/__init__.py b/fail2ban/tests/__init__.py similarity index 100% rename from testcases/__init__.py rename to fail2ban/tests/__init__.py diff --git a/testcases/actiontestcase.py b/fail2ban/tests/actiontestcase.py similarity index 100% rename from testcases/actiontestcase.py rename to fail2ban/tests/actiontestcase.py diff --git a/testcases/banmanagertestcase.py b/fail2ban/tests/banmanagertestcase.py similarity index 100% rename from testcases/banmanagertestcase.py rename to fail2ban/tests/banmanagertestcase.py diff --git a/testcases/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py similarity index 100% rename from testcases/clientreadertestcase.py rename to fail2ban/tests/clientreadertestcase.py diff --git a/testcases/datedetectortestcase.py b/fail2ban/tests/datedetectortestcase.py similarity index 100% rename from testcases/datedetectortestcase.py rename to fail2ban/tests/datedetectortestcase.py diff --git a/testcases/failmanagertestcase.py b/fail2ban/tests/failmanagertestcase.py similarity index 100% rename from testcases/failmanagertestcase.py rename to fail2ban/tests/failmanagertestcase.py diff --git a/testcases/files/logs/apache-overflows b/fail2ban/tests/files/logs/apache-overflows similarity index 100% rename from testcases/files/logs/apache-overflows rename to fail2ban/tests/files/logs/apache-overflows diff --git a/testcases/files/logs/asterisk b/fail2ban/tests/files/logs/asterisk similarity index 100% rename from testcases/files/logs/asterisk rename to fail2ban/tests/files/logs/asterisk diff --git a/testcases/files/logs/dovecot b/fail2ban/tests/files/logs/dovecot similarity index 100% rename from testcases/files/logs/dovecot rename to fail2ban/tests/files/logs/dovecot diff --git a/testcases/files/logs/exim b/fail2ban/tests/files/logs/exim similarity index 100% rename from testcases/files/logs/exim rename to fail2ban/tests/files/logs/exim diff --git a/testcases/files/logs/lighttpd b/fail2ban/tests/files/logs/lighttpd similarity index 100% rename from testcases/files/logs/lighttpd rename to fail2ban/tests/files/logs/lighttpd diff --git a/testcases/files/logs/named-refused b/fail2ban/tests/files/logs/named-refused similarity index 100% rename from testcases/files/logs/named-refused rename to fail2ban/tests/files/logs/named-refused diff --git a/testcases/files/logs/pam-generic b/fail2ban/tests/files/logs/pam-generic similarity index 100% rename from testcases/files/logs/pam-generic rename to fail2ban/tests/files/logs/pam-generic diff --git a/testcases/files/logs/postfix b/fail2ban/tests/files/logs/postfix similarity index 100% rename from testcases/files/logs/postfix rename to fail2ban/tests/files/logs/postfix diff --git a/testcases/files/logs/proftpd b/fail2ban/tests/files/logs/proftpd similarity index 100% rename from testcases/files/logs/proftpd rename to fail2ban/tests/files/logs/proftpd diff --git a/testcases/files/logs/pure-ftpd b/fail2ban/tests/files/logs/pure-ftpd similarity index 100% rename from testcases/files/logs/pure-ftpd rename to fail2ban/tests/files/logs/pure-ftpd diff --git a/testcases/files/logs/roundcube-auth b/fail2ban/tests/files/logs/roundcube-auth similarity index 100% rename from testcases/files/logs/roundcube-auth rename to fail2ban/tests/files/logs/roundcube-auth diff --git a/testcases/files/logs/sasl b/fail2ban/tests/files/logs/sasl similarity index 100% rename from testcases/files/logs/sasl rename to fail2ban/tests/files/logs/sasl diff --git a/testcases/files/logs/sogo-auth b/fail2ban/tests/files/logs/sogo-auth similarity index 100% rename from testcases/files/logs/sogo-auth rename to fail2ban/tests/files/logs/sogo-auth diff --git a/testcases/files/logs/sshd b/fail2ban/tests/files/logs/sshd similarity index 100% rename from testcases/files/logs/sshd rename to fail2ban/tests/files/logs/sshd diff --git a/testcases/files/logs/sshd-ddos b/fail2ban/tests/files/logs/sshd-ddos similarity index 100% rename from testcases/files/logs/sshd-ddos rename to fail2ban/tests/files/logs/sshd-ddos diff --git a/testcases/files/logs/vsftpd b/fail2ban/tests/files/logs/vsftpd similarity index 100% rename from testcases/files/logs/vsftpd rename to fail2ban/tests/files/logs/vsftpd diff --git a/testcases/files/logs/webmin-auth b/fail2ban/tests/files/logs/webmin-auth similarity index 100% rename from testcases/files/logs/webmin-auth rename to fail2ban/tests/files/logs/webmin-auth diff --git a/testcases/files/logs/wu-ftpd b/fail2ban/tests/files/logs/wu-ftpd similarity index 100% rename from testcases/files/logs/wu-ftpd rename to fail2ban/tests/files/logs/wu-ftpd diff --git a/testcases/files/testcase-usedns.log b/fail2ban/tests/files/testcase-usedns.log similarity index 100% rename from testcases/files/testcase-usedns.log rename to fail2ban/tests/files/testcase-usedns.log diff --git a/testcases/files/testcase01.log b/fail2ban/tests/files/testcase01.log similarity index 100% rename from testcases/files/testcase01.log rename to fail2ban/tests/files/testcase01.log diff --git a/testcases/files/testcase02.log b/fail2ban/tests/files/testcase02.log similarity index 100% rename from testcases/files/testcase02.log rename to fail2ban/tests/files/testcase02.log diff --git a/testcases/files/testcase03.log b/fail2ban/tests/files/testcase03.log similarity index 100% rename from testcases/files/testcase03.log rename to fail2ban/tests/files/testcase03.log diff --git a/testcases/files/testcase04.log b/fail2ban/tests/files/testcase04.log similarity index 100% rename from testcases/files/testcase04.log rename to fail2ban/tests/files/testcase04.log diff --git a/testcases/filtertestcase.py b/fail2ban/tests/filtertestcase.py similarity index 98% rename from testcases/filtertestcase.py rename to fail2ban/tests/filtertestcase.py index 75b72c05..27a1510d 100644 --- a/testcases/filtertestcase.py +++ b/fail2ban/tests/filtertestcase.py @@ -35,6 +35,8 @@ from fail2ban.server.filter import FileFilter, DNSUtils from fail2ban.server.failmanager import FailManager from fail2ban.server.failmanager import FailManagerEmpty +TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") + # # Useful helpers # @@ -182,7 +184,7 @@ class IgnoreIP(unittest.TestCase): class LogFile(unittest.TestCase): - FILENAME = "testcases/files/testcase01.log" + FILENAME = os.path.join(TEST_FILES_DIR, "testcase01.log") def setUp(self): """Call before every test case.""" @@ -522,11 +524,11 @@ def get_monitor_failures_testcase(Filter_): class GetFailures(unittest.TestCase): - FILENAME_01 = "testcases/files/testcase01.log" - FILENAME_02 = "testcases/files/testcase02.log" - FILENAME_03 = "testcases/files/testcase03.log" - FILENAME_04 = "testcases/files/testcase04.log" - FILENAME_USEDNS = "testcases/files/testcase-usedns.log" + FILENAME_01 = os.path.join(TEST_FILES_DIR, "testcase01.log") + FILENAME_02 = os.path.join(TEST_FILES_DIR, "testcase02.log") + FILENAME_03 = os.path.join(TEST_FILES_DIR, "testcase03.log") + FILENAME_04 = os.path.join(TEST_FILES_DIR, "testcase04.log") + FILENAME_USEDNS = os.path.join(TEST_FILES_DIR, "testcase-usedns.log") # so that they could be reused by other tests FAILURES_01 = ('193.168.0.128', 3, 1124013599.0, diff --git a/testcases/servertestcase.py b/fail2ban/tests/servertestcase.py similarity index 98% rename from testcases/servertestcase.py rename to fail2ban/tests/servertestcase.py index 0cdf0422..4a3435b4 100644 --- a/testcases/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -32,6 +32,8 @@ import unittest, socket, time, tempfile, os from fail2ban.server.server import Server from fail2ban.exceptions import UnknownJailException +TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") + class StartStop(unittest.TestCase): def setUp(self): @@ -273,14 +275,14 @@ class Transmitter(TransmitterBase): self.jailAddDelTest( "logpath", [ - "testcases/files/testcase01.log", - "testcases/files/testcase02.log", - "testcases/files/testcase03.log", + os.path.join(TEST_FILES_DIR, "testcase01.log"), + os.path.join(TEST_FILES_DIR, "testcase02.log"), + os.path.join(TEST_FILES_DIR, "testcase03.log"), ], self.jailName ) # Try duplicates - value = "testcases/files/testcase04.log" + value = os.path.join(TEST_FILES_DIR, "testcase04.log") self.assertEqual( self.transm.proceed(["set", self.jailName, "addlogpath", value]), (0, [value])) diff --git a/testcases/sockettestcase.py b/fail2ban/tests/sockettestcase.py similarity index 100% rename from testcases/sockettestcase.py rename to fail2ban/tests/sockettestcase.py diff --git a/testcases/utils.py b/fail2ban/tests/utils.py similarity index 100% rename from testcases/utils.py rename to fail2ban/tests/utils.py diff --git a/setup.py b/setup.py index 004f2f84..87159635 100755 --- a/setup.py +++ b/setup.py @@ -49,13 +49,18 @@ setup( scripts = [ 'fail2ban-client', 'fail2ban-server', - 'fail2ban-regex' + 'fail2ban-regex', + 'fail2ban-testcases', ], packages = [ 'fail2ban', 'fail2ban.client', - 'fail2ban.server' + 'fail2ban.server', + 'fail2ban.tests', ], + package_data = { + 'fail2ban.tests': ['files/*.log'], + }, data_files = [ ('/etc/fail2ban', glob("config/*.conf") From a153653a2709dc032d814c9bacdbde50b1d0a171 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Mon, 1 Apr 2013 19:06:13 +0100 Subject: [PATCH 26/37] ENH+TST: Move fail2ban-* scripts to bin/ --- .travis.yml | 2 +- DEVELOP | 8 ++++---- MANIFEST | 8 ++++---- fail2ban-client => bin/fail2ban-client | 0 fail2ban-regex => bin/fail2ban-regex | 0 fail2ban-server => bin/fail2ban-server | 0 fail2ban-testcases => bin/fail2ban-testcases | 5 +++++ fail2ban-testcases-all | 2 +- setup.py | 8 ++++---- 9 files changed, 19 insertions(+), 14 deletions(-) rename fail2ban-client => bin/fail2ban-client (100%) rename fail2ban-regex => bin/fail2ban-regex (100%) rename fail2ban-server => bin/fail2ban-server (100%) rename fail2ban-testcases => bin/fail2ban-testcases (97%) diff --git a/.travis.yml b/.travis.yml index 773c5f0b..93082658 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,6 @@ install: - pip install pyinotify - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then pip install -q coveralls; fi script: - - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then coverage run --rcfile=.travis_coveragerc fail2ban-testcases; else python ./fail2ban-testcases; fi + - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then coverage run --rcfile=.travis_coveragerc bin/fail2ban-testcases; else python bin/fail2ban-testcases; fi after_script: - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then coveralls; fi diff --git a/DEVELOP b/DEVELOP index 158fb2b2..0fe80596 100644 --- a/DEVELOP +++ b/DEVELOP @@ -24,9 +24,9 @@ Request feature. You can find more details on the Fail2Ban wiki Testing ======= -Existing tests can be run by executing `fail2ban-testcases`. This has options -like --log-level that will probably be useful. `fail2ban-testcases --help` for -full options. +Existing tests can be run by executing `bin/fail2ban-testcases`. This has +options like --log-level that will probably be useful. +`bin/fail2ban-testcases --help` forfull options. Test cases should cover all usual cases, all exception cases and all inside / outside boundary conditions. @@ -39,7 +39,7 @@ Install the package python-coverage to visualise your test coverage. Run the following (note: on Debian-based systems, the script is called `python-coverage`): -coverage run fail2ban-testcases +coverage run bin/fail2ban-testcases coverage html Then look at htmlcov/index.html and see how much coverage your test cases diff --git a/MANIFEST b/MANIFEST index 93698e95..12ba3435 100644 --- a/MANIFEST +++ b/MANIFEST @@ -5,10 +5,10 @@ THANKS COPYING DEVELOP doc/run-rootless.txt -fail2ban-client -fail2ban-server -fail2ban-testcases -fail2ban-regex +bin/fail2ban-client +bin/fail2ban-server +bin/fail2ban-testcases +bin/fail2ban-regex fail2ban/client/configreader.py fail2ban/client/configparserinc.py fail2ban/client/jailreader.py diff --git a/fail2ban-client b/bin/fail2ban-client similarity index 100% rename from fail2ban-client rename to bin/fail2ban-client diff --git a/fail2ban-regex b/bin/fail2ban-regex similarity index 100% rename from fail2ban-regex rename to bin/fail2ban-regex diff --git a/fail2ban-server b/bin/fail2ban-server similarity index 100% rename from fail2ban-server rename to bin/fail2ban-server diff --git a/fail2ban-testcases b/bin/fail2ban-testcases similarity index 97% rename from fail2ban-testcases rename to bin/fail2ban-testcases index 45ba03ad..5faaa75e 100755 --- a/fail2ban-testcases +++ b/bin/fail2ban-testcases @@ -27,6 +27,11 @@ __license__ = "GPL" import unittest, logging, sys, time, os +# Check if local fail2ban module exists, and use if it exists by +# modifying the path. This is such that tests can be used in dev +# environment. +if os.path.exists("fail2ban/__init__.py"): + sys.path.insert(0, ".") from fail2ban.version import version from fail2ban.tests import banmanagertestcase from fail2ban.tests import clientreadertestcase diff --git a/fail2ban-testcases-all b/fail2ban-testcases-all index fd33dce4..6b399337 100755 --- a/fail2ban-testcases-all +++ b/fail2ban-testcases-all @@ -9,7 +9,7 @@ for python in /usr/{,local/}bin/python2.[0-9]{,.*}{,-dbg} do [ -e "$python" ] || continue echo "Testing using $python" - $python ./fail2ban-testcases "$@" || failed+=" $python" + $python bin/fail2ban-testcases "$@" || failed+=" $python" done if [ ! -z "$failed" ]; then diff --git a/setup.py b/setup.py index 87159635..43658b47 100755 --- a/setup.py +++ b/setup.py @@ -47,10 +47,10 @@ setup( license = "GPL", platforms = "Posix", scripts = [ - 'fail2ban-client', - 'fail2ban-server', - 'fail2ban-regex', - 'fail2ban-testcases', + 'bin/fail2ban-client', + 'bin/fail2ban-server', + 'bin/fail2ban-regex', + 'bin/fail2ban-testcases', ], packages = [ 'fail2ban', From 0ce046ec477447d34c3721b953dc498835da681c Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Mon, 1 Apr 2013 19:06:58 +0100 Subject: [PATCH 27/37] TST: clientreader test now use /etc/fail2ban/ if no local config/ --- fail2ban/tests/clientreadertestcase.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index f54df659..8bc462d4 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -28,6 +28,11 @@ from fail2ban.client.jailreader import JailReader from fail2ban.client.jailsreader import JailsReader from fail2ban.client.configurator import Configurator +if os.path.exists('config/fail2ban.conf'): + CONFIG_DIR='config' +else: + CONFIG_DIR='/etc/fail2ban' + class ConfigReaderTest(unittest.TestCase): def setUp(self): @@ -99,7 +104,7 @@ option = %s class JailReaderTest(unittest.TestCase): def testStockSSHJail(self): - jail = JailReader('ssh-iptables', basedir='config') # we are running tests from root project dir atm + jail = JailReader('ssh-iptables', basedir=CONFIG_DIR) # we are running tests from root project dir atm self.assertTrue(jail.read()) self.assertTrue(jail.getOptions()) self.assertFalse(jail.isEnabled()) @@ -119,7 +124,7 @@ class JailsReaderTest(unittest.TestCase): self.assertRaises(ValueError, reader.read) def testReadStockJailConf(self): - jails = JailsReader(basedir='config') # we are running tests from root project dir atm + jails = JailsReader(basedir=CONFIG_DIR) # we are running tests from root project dir atm self.assertTrue(jails.read()) # opens fine self.assertTrue(jails.getOptions()) # reads fine comm_commands = jails.convert() @@ -130,7 +135,7 @@ class JailsReaderTest(unittest.TestCase): def testReadStockJailConfForceEnabled(self): # more of a smoke test to make sure that no obvious surprises # on users' systems when enabling shipped jails - jails = JailsReader(basedir='config', force_enable=True) # we are running tests from root project dir atm + jails = JailsReader(basedir=CONFIG_DIR, force_enable=True) # we are running tests from root project dir atm self.assertTrue(jails.read()) # opens fine self.assertTrue(jails.getOptions()) # reads fine comm_commands = jails.convert() @@ -152,8 +157,8 @@ class JailsReaderTest(unittest.TestCase): def testConfigurator(self): configurator = Configurator() - configurator.setBaseDir('config') - self.assertEqual(configurator.getBaseDir(), 'config') + configurator.setBaseDir(CONFIG_DIR) + self.assertEqual(configurator.getBaseDir(), CONFIG_DIR) configurator.readEarly() opts = configurator.getEarlyOptions() @@ -166,4 +171,4 @@ class JailsReaderTest(unittest.TestCase): # otherwise just a code smoke test) configurator._Configurator__jails.setBaseDir('/tmp') self.assertEqual(configurator._Configurator__jails.getBaseDir(), '/tmp') - self.assertEqual(configurator.getBaseDir(), 'config') + self.assertEqual(configurator.getBaseDir(), CONFIG_DIR) From 44736035bda2f34d5a91cb9e1f1f3475902bd1e3 Mon Sep 17 00:00:00 2001 From: Erwan Ben Souiden Date: Tue, 2 Apr 2013 09:49:44 +0200 Subject: [PATCH 28/37] change the license to GPLv2 + adapat text --- files/nagios/check_fail2ban | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/files/nagios/check_fail2ban b/files/nagios/check_fail2ban index 148c92d5..77a63393 100755 --- a/files/nagios/check_fail2ban +++ b/files/nagios/check_fail2ban @@ -29,19 +29,20 @@ # #################################################################### # #################################################################### -# GPL v3 -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - +# GPL v2 +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # #################################################################### # #################################################################### @@ -274,10 +275,10 @@ This plugin has been created by $author Hope you will enjoy it ;) Remember : - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -285,8 +286,8 @@ Remember : GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . - + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. EOT exit $ERRORS{"UNKNOWN"}; From c4bdc48edbbf7641ec0385e0796e31c74c86820b Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sat, 6 Apr 2013 10:15:43 +0100 Subject: [PATCH 29/37] TST: Fix up tests from multiline elements broken in previous merge --- fail2ban/tests/clientreadertestcase.py | 3 ++- .../tests}/files/filter.d/testcase-common.conf | 0 {testcases => fail2ban/tests}/files/filter.d/testcase01.conf | 0 {testcases => fail2ban/tests}/files/testcase-multiline.log | 0 4 files changed, 2 insertions(+), 1 deletion(-) rename {testcases => fail2ban/tests}/files/filter.d/testcase-common.conf (100%) rename {testcases => fail2ban/tests}/files/filter.d/testcase01.conf (100%) rename {testcases => fail2ban/tests}/files/testcase-multiline.log (100%) diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 340c9c15..99d9a50e 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -29,6 +29,7 @@ from fail2ban.client.filterreader import FilterReader from fail2ban.client.jailsreader import JailsReader from fail2ban.client.configurator import Configurator +TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files") if os.path.exists('config/fail2ban.conf'): CONFIG_DIR='config' else: @@ -140,7 +141,7 @@ class FilterReaderTest(unittest.TestCase): ['set', 'testcase01', 'addignoreregex', "^.+ john from host 192.168.1.1\\s*$"]] filterReader = FilterReader("testcase01", "testcase01") - filterReader.setBaseDir("testcases/files/") + filterReader.setBaseDir(TEST_FILES_DIR) filterReader.read() #filterReader.getOptions(["failregex", "ignoreregex"]) filterReader.getOptions(None) diff --git a/testcases/files/filter.d/testcase-common.conf b/fail2ban/tests/files/filter.d/testcase-common.conf similarity index 100% rename from testcases/files/filter.d/testcase-common.conf rename to fail2ban/tests/files/filter.d/testcase-common.conf diff --git a/testcases/files/filter.d/testcase01.conf b/fail2ban/tests/files/filter.d/testcase01.conf similarity index 100% rename from testcases/files/filter.d/testcase01.conf rename to fail2ban/tests/files/filter.d/testcase01.conf diff --git a/testcases/files/testcase-multiline.log b/fail2ban/tests/files/testcase-multiline.log similarity index 100% rename from testcases/files/testcase-multiline.log rename to fail2ban/tests/files/testcase-multiline.log From 3a16ceed0aa937c9ceeedff77be0b8b33e2d3d34 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sat, 6 Apr 2013 10:20:53 +0100 Subject: [PATCH 30/37] BF: Added test filter.d files to setup.py package data --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 43658b47..4fea8c29 100755 --- a/setup.py +++ b/setup.py @@ -59,7 +59,8 @@ setup( 'fail2ban.tests', ], package_data = { - 'fail2ban.tests': ['files/*.log'], + 'fail2ban.tests': + ['files/*.log', 'files/filter.d/*.conf'], }, data_files = [ ('/etc/fail2ban', From 47c54ba293448c73fd3c9928d41472d1264128fa Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Sat, 6 Apr 2013 11:08:07 +0100 Subject: [PATCH 31/37] TST: Add gamin testing for and only coveralls coverage for python2.7 --- .travis.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 75b7ce4d..8da3e0bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,10 @@ before_install: - sudo apt-get update -qq install: - pip install pyinotify - - sudo apt-get install -qq python-gamin - - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then pip install -q coveralls; fi + - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then sudo apt-get install -qq python-gamin; fi + - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install -q coveralls; fi script: - - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then coverage run --rcfile=.travis_coveragerc fail2ban-testcases; else python ./fail2ban-testcases; fi + - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then export PYTHONPATH="$PYTHONPATH:/usr/share/pyshared:/usr/lib/pyshared/python2.7"; fi + - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coverage run --rcfile=.travis_coveragerc fail2ban-testcases; else python ./fail2ban-testcases; fi after_script: - - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then coveralls; fi + - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coveralls; fi From ffaa9697eeab80f40df7d2fd449cb619d55e0a84 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Tue, 9 Apr 2013 17:59:45 -0400 Subject: [PATCH 32/37] Adjusting previous PR (MySQL logs) according to my comments --- config/filter.d/mysqld.conf | 9 ++++----- testcases/files/logs/mysqld.log | 11 ----------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/config/filter.d/mysqld.conf b/config/filter.d/mysqld.conf index bc9164ce..197c8232 100644 --- a/config/filter.d/mysqld.conf +++ b/config/filter.d/mysqld.conf @@ -1,8 +1,7 @@ -# Fail2Ban configuration file +# Fail2Ban configuration file for unsuccesfull MySQL authentication attempts # -# Author: Artur Penttinen -# -# $Revision$ +# Authors: Artur Penttinen +# Yaroslav O. Halchenko # [INCLUDES] @@ -23,7 +22,7 @@ before = common.conf # (?:::f{4,6}:)?(?P[\w\-.^_]+) # Values: TEXT # 130322 11:26:54 [Warning] Access denied for user 'root'@'127.0.0.1' (using password: YES) -failregex = Access denied for user '\w+'@'' +failregex = Access denied for user '\w+'@'' (to database '[^']*'|\(using password: (YES|NO)\))*\s*$ # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. diff --git a/testcases/files/logs/mysqld.log b/testcases/files/logs/mysqld.log index 8dfd6338..b3a73078 100644 --- a/testcases/files/logs/mysqld.log +++ b/testcases/files/logs/mysqld.log @@ -1,17 +1,6 @@ -130323 21:14:28 [Warning] Access denied for user 'root'@'192.168.1.34' (using password: NO) 130324 0:04:00 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: NO) -130324 0:04:02 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) -130324 0:04:05 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) -130324 0:04:07 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) -130324 0:04:09 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) -130324 0:04:11 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) -130324 0:04:13 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) -130324 0:04:16 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) -130324 0:04:18 [Warning] Access denied for user 'root'@'192.168.1.35' (using password: YES) 130324 8:24:09 [Warning] Access denied for user 'root'@'220.95.238.171' (using password: NO) 130324 17:56:13 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: NO) 130324 17:56:14 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: YES) -130324 17:56:15 [Warning] Access denied for user 'root'@'61.160.223.112' (using password: YES) 130324 19:01:39 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: NO) 130324 19:01:40 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: YES) -130324 19:01:41 [Warning] Access denied for user 'root'@'61.147.108.35' (using password: YES) From 99a5d78e3766cd8cf247a047611cfb293426af82 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Tue, 9 Apr 2013 18:03:34 -0400 Subject: [PATCH 33/37] ENH: for consistency (and future expansion ;)) -- rename to mysqld-auth --- config/filter.d/{mysqld.conf => mysqld-auth.conf} | 0 config/jail.conf | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename config/filter.d/{mysqld.conf => mysqld-auth.conf} (100%) diff --git a/config/filter.d/mysqld.conf b/config/filter.d/mysqld-auth.conf similarity index 100% rename from config/filter.d/mysqld.conf rename to config/filter.d/mysqld-auth.conf diff --git a/config/jail.conf b/config/jail.conf index 4c1528f1..4399d0bd 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -345,13 +345,13 @@ action = iptables-multiport[name=asterisk-udp, port="5060,5061", protocol=udp] logpath = /var/log/asterisk/messages maxretry = 10 -# For log wrong MySQL access add to /etc/my.cnf: +# To log wrong MySQL access attempts add to /etc/my.cnf: # log-error=/var/log/mysqld.log # log-warning = 2 [mysqld-iptables] enabled = false -filter = mysqld +filter = mysqld-auth action = iptables[name=mysql, port=3306, protocol=tcp] sendmail-whois[name=MySQL, dest=root, sender=fail2ban@example.com] logpath = /var/log/mysqld.log From 7a385fd442d540fe614ba886fda5395cf81019c0 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Tue, 9 Apr 2013 19:46:24 -0400 Subject: [PATCH 34/37] BF: Move mysqld.log into a new location under fail2ban module --- {testcases => fail2ban/tests}/files/logs/mysqld.log | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {testcases => fail2ban/tests}/files/logs/mysqld.log (100%) diff --git a/testcases/files/logs/mysqld.log b/fail2ban/tests/files/logs/mysqld.log similarity index 100% rename from testcases/files/logs/mysqld.log rename to fail2ban/tests/files/logs/mysqld.log From fe1c3fbdd9d0cc98fddec87f36dfb202f1807907 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Tue, 9 Apr 2013 20:24:54 -0400 Subject: [PATCH 35/37] BF: fixing incorrect merge conflict -- run coverage only for 2.7 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a92df23a..f685ee38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,6 @@ install: - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install -q coveralls; fi script: - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then export PYTHONPATH="$PYTHONPATH:/usr/share/pyshared:/usr/lib/pyshared/python2.7"; fi - - if [[ $TRAVIS_PYTHON_VERSION == 2.[6-7] ]]; then coverage run --rcfile=.travis_coveragerc bin/fail2ban-testcases; else python bin/fail2ban-testcases; fi + - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coverage run --rcfile=.travis_coveragerc bin/fail2ban-testcases; else python bin/fail2ban-testcases; fi after_script: - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coveralls; fi From a3d82e2ab9174d088f883120a61b967fe0543bf7 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Wed, 10 Apr 2013 21:33:55 +0100 Subject: [PATCH 36/37] ENH: fail2ban logging uses __name__ for logger names --- bin/fail2ban-testcases | 2 +- fail2ban/client/actionreader.py | 2 +- fail2ban/client/beautifier.py | 2 +- fail2ban/client/configparserinc.py | 2 +- fail2ban/client/configreader.py | 2 +- fail2ban/client/configurator.py | 2 +- fail2ban/client/fail2banreader.py | 2 +- fail2ban/client/filterreader.py | 2 +- fail2ban/client/jailreader.py | 2 +- fail2ban/client/jailsreader.py | 2 +- fail2ban/server/action.py | 2 +- fail2ban/server/actions.py | 2 +- fail2ban/server/asyncserver.py | 2 +- fail2ban/server/banmanager.py | 2 +- fail2ban/server/datedetector.py | 2 +- fail2ban/server/datetemplate.py | 2 +- fail2ban/server/faildata.py | 2 +- fail2ban/server/failmanager.py | 2 +- fail2ban/server/filter.py | 2 +- fail2ban/server/filtergamin.py | 2 +- fail2ban/server/filterpoll.py | 2 +- fail2ban/server/filterpyinotify.py | 2 +- fail2ban/server/jail.py | 2 +- fail2ban/server/jailthread.py | 2 +- fail2ban/server/server.py | 11 ++++++----- fail2ban/server/ticket.py | 2 +- fail2ban/server/transmitter.py | 2 +- 27 files changed, 32 insertions(+), 31 deletions(-) diff --git a/bin/fail2ban-testcases b/bin/fail2ban-testcases index 68a31786..d276be1d 100755 --- a/bin/fail2ban-testcases +++ b/bin/fail2ban-testcases @@ -109,7 +109,7 @@ else: # Custom log format for the verbose tests runs if verbosity > 1: # pragma: no cover - stdout.setFormatter(Formatter(' %(asctime)-15s %(thread)s' + fmt)) + stdout.setFormatter(Formatter(' %(asctime)-15s %(thread)s %(name)s' + fmt)) else: # pragma: no cover # just prefix with the space stdout.setFormatter(Formatter(fmt)) diff --git a/fail2ban/client/actionreader.py b/fail2ban/client/actionreader.py index 9ad1ef28..787a41c7 100644 --- a/fail2ban/client/actionreader.py +++ b/fail2ban/client/actionreader.py @@ -31,7 +31,7 @@ import logging from configreader import ConfigReader # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) class ActionReader(ConfigReader): diff --git a/fail2ban/client/beautifier.py b/fail2ban/client/beautifier.py index 1403bb08..fe58ccf3 100644 --- a/fail2ban/client/beautifier.py +++ b/fail2ban/client/beautifier.py @@ -26,7 +26,7 @@ import logging from fail2ban.exceptions import UnknownJailException, DuplicateJailException # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) ## # Beautify the output of the client. diff --git a/fail2ban/client/configparserinc.py b/fail2ban/client/configparserinc.py index 7ac8b4a5..0ffa0728 100644 --- a/fail2ban/client/configparserinc.py +++ b/fail2ban/client/configparserinc.py @@ -31,7 +31,7 @@ import logging, os from ConfigParser import SafeConfigParser # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) class SafeConfigParserWithIncludes(SafeConfigParser): """ diff --git a/fail2ban/client/configreader.py b/fail2ban/client/configreader.py index 243c843c..6f1e7740 100644 --- a/fail2ban/client/configreader.py +++ b/fail2ban/client/configreader.py @@ -32,7 +32,7 @@ from configparserinc import SafeConfigParserWithIncludes from ConfigParser import NoOptionError, NoSectionError # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) class ConfigReader(SafeConfigParserWithIncludes): diff --git a/fail2ban/client/configurator.py b/fail2ban/client/configurator.py index 2097fd54..23ee88c6 100644 --- a/fail2ban/client/configurator.py +++ b/fail2ban/client/configurator.py @@ -33,7 +33,7 @@ from fail2banreader import Fail2banReader from jailsreader import JailsReader # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) class Configurator: diff --git a/fail2ban/client/fail2banreader.py b/fail2ban/client/fail2banreader.py index c8f42976..e388f9ae 100644 --- a/fail2ban/client/fail2banreader.py +++ b/fail2ban/client/fail2banreader.py @@ -31,7 +31,7 @@ import logging from configreader import ConfigReader # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) class Fail2banReader(ConfigReader): diff --git a/fail2ban/client/filterreader.py b/fail2ban/client/filterreader.py index 7dba3579..8b00446e 100644 --- a/fail2ban/client/filterreader.py +++ b/fail2ban/client/filterreader.py @@ -31,7 +31,7 @@ import logging from configreader import ConfigReader # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) class FilterReader(ConfigReader): diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index 55e512f3..e4175f4f 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -34,7 +34,7 @@ from filterreader import FilterReader from actionreader import ActionReader # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) class JailReader(ConfigReader): diff --git a/fail2ban/client/jailsreader.py b/fail2ban/client/jailsreader.py index 91e178d6..345a225f 100644 --- a/fail2ban/client/jailsreader.py +++ b/fail2ban/client/jailsreader.py @@ -32,7 +32,7 @@ from configreader import ConfigReader from jailreader import JailReader # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.client.config") +logSys = logging.getLogger(__name__) class JailsReader(ConfigReader): diff --git a/fail2ban/server/action.py b/fail2ban/server/action.py index 5fde3ae1..d2a8cfde 100644 --- a/fail2ban/server/action.py +++ b/fail2ban/server/action.py @@ -32,7 +32,7 @@ import threading #from subprocess import call # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.actions.action") +logSys = logging.getLogger(__name__) # Create a lock for running system commands _cmd_lock = threading.Lock() diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index ddcc83d6..c0373239 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -34,7 +34,7 @@ from mytime import MyTime import time, logging # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.actions") +logSys = logging.getLogger(__name__) ## # Execute commands. diff --git a/fail2ban/server/asyncserver.py b/fail2ban/server/asyncserver.py index d5fb791c..5f729e11 100644 --- a/fail2ban/server/asyncserver.py +++ b/fail2ban/server/asyncserver.py @@ -33,7 +33,7 @@ import asyncore, asynchat, socket, os, logging, sys, traceback from fail2ban import helpers # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.server") +logSys = logging.getLogger(__name__) ## # Request handler class. diff --git a/fail2ban/server/banmanager.py b/fail2ban/server/banmanager.py index 1143f791..9c81f252 100644 --- a/fail2ban/server/banmanager.py +++ b/fail2ban/server/banmanager.py @@ -33,7 +33,7 @@ from mytime import MyTime import logging # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.action") +logSys = logging.getLogger(__name__) ## # Banning Manager. diff --git a/fail2ban/server/datedetector.py b/fail2ban/server/datedetector.py index c013d551..2f57294a 100644 --- a/fail2ban/server/datedetector.py +++ b/fail2ban/server/datedetector.py @@ -33,7 +33,7 @@ from datetemplate import DateStrptime, DateTai64n, DateEpoch, DateISO8601 from threading import Lock # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.filter.datedetector") +logSys = logging.getLogger(__name__) class DateDetector: diff --git a/fail2ban/server/datetemplate.py b/fail2ban/server/datetemplate.py index 51b8bb1e..c75a02f2 100644 --- a/fail2ban/server/datetemplate.py +++ b/fail2ban/server/datetemplate.py @@ -33,7 +33,7 @@ from mytime import MyTime import iso8601 import logging -logSys = logging.getLogger("fail2ban.datetemplate") +logSys = logging.getLogger(__name__) class DateTemplate: diff --git a/fail2ban/server/faildata.py b/fail2ban/server/faildata.py index 1f0bda04..efda51e1 100644 --- a/fail2ban/server/faildata.py +++ b/fail2ban/server/faildata.py @@ -30,7 +30,7 @@ __license__ = "GPL" import logging # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban") +logSys = logging.getLogger(__name__) class FailData: diff --git a/fail2ban/server/failmanager.py b/fail2ban/server/failmanager.py index 02f16ce3..60e71c7b 100644 --- a/fail2ban/server/failmanager.py +++ b/fail2ban/server/failmanager.py @@ -33,7 +33,7 @@ from threading import Lock import logging # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.filter") +logSys = logging.getLogger(__name__) class FailManager: diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index 4fa22bd4..fe990578 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -38,7 +38,7 @@ from failregex import FailRegex, Regex, RegexException import logging, re, os, fcntl, time # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.filter") +logSys = logging.getLogger(__name__) ## # Log reader class. diff --git a/fail2ban/server/filtergamin.py b/fail2ban/server/filtergamin.py index cff5aa54..e324b677 100644 --- a/fail2ban/server/filtergamin.py +++ b/fail2ban/server/filtergamin.py @@ -30,7 +30,7 @@ from mytime import MyTime import time, logging, gamin # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.filter") +logSys = logging.getLogger(__name__) ## # Log reader class. diff --git a/fail2ban/server/filterpoll.py b/fail2ban/server/filterpoll.py index f0e23ac1..3217e958 100644 --- a/fail2ban/server/filterpoll.py +++ b/fail2ban/server/filterpoll.py @@ -33,7 +33,7 @@ from mytime import MyTime import time, logging, os # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.filter") +logSys = logging.getLogger(__name__) ## # Log reader class. diff --git a/fail2ban/server/filterpyinotify.py b/fail2ban/server/filterpyinotify.py index e86498b0..786c6dfa 100644 --- a/fail2ban/server/filterpyinotify.py +++ b/fail2ban/server/filterpyinotify.py @@ -38,7 +38,7 @@ if not hasattr(pyinotify, '__version__') \ from os.path import dirname, sep as pathsep # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.filter") +logSys = logging.getLogger(__name__) ## # Log reader class. diff --git a/fail2ban/server/jail.py b/fail2ban/server/jail.py index dee64e7f..fa2a8fa5 100644 --- a/fail2ban/server/jail.py +++ b/fail2ban/server/jail.py @@ -28,7 +28,7 @@ import Queue, logging from actions import Actions # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.jail") +logSys = logging.getLogger(__name__) class Jail: diff --git a/fail2ban/server/jailthread.py b/fail2ban/server/jailthread.py index 343ea7e2..98fd4066 100644 --- a/fail2ban/server/jailthread.py +++ b/fail2ban/server/jailthread.py @@ -31,7 +31,7 @@ from threading import Thread import logging # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.server") +logSys = logging.getLogger(__name__) class JailThread(Thread): diff --git a/fail2ban/server/server.py b/fail2ban/server/server.py index 8038a0c1..a5d2d5d2 100644 --- a/fail2ban/server/server.py +++ b/fail2ban/server/server.py @@ -36,7 +36,7 @@ from fail2ban import version import logging, logging.handlers, sys, os, signal # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.server") +logSys = logging.getLogger(__name__) class Server: @@ -329,7 +329,7 @@ class Server: logLevel = logging.WARNING elif value == 3: logLevel = logging.INFO - logging.getLogger("fail2ban").setLevel(logLevel) + logging.getLogger(__name__).parent.parent.setLevel(logLevel) finally: self.__loggingLock.release() @@ -378,9 +378,10 @@ class Server: return False # Removes previous handlers -- in reverse order since removeHandler # alter the list in-place and that can confuses the iterable - for handler in logging.getLogger("fail2ban").handlers[::-1]: + logger = logging.getLogger(__name__).parent.parent + for handler in logger.handlers[::-1]: # Remove the handler. - logging.getLogger("fail2ban").removeHandler(handler) + logger.removeHandler(handler) # And try to close -- it might be closed already try: handler.flush() @@ -392,7 +393,7 @@ class Server: # with older Pythons -- seems to be safe to ignore there # tell the handler to use this format hdlr.setFormatter(formatter) - logging.getLogger("fail2ban").addHandler(hdlr) + logger.addHandler(hdlr) # Does not display this message at startup. if not self.__logTarget == None: logSys.info("Changed logging target to %s for Fail2ban v%s" % diff --git a/fail2ban/server/ticket.py b/fail2ban/server/ticket.py index c03761c1..95643d15 100644 --- a/fail2ban/server/ticket.py +++ b/fail2ban/server/ticket.py @@ -30,7 +30,7 @@ __license__ = "GPL" import logging # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban") +logSys = logging.getLogger(__name__) class Ticket: diff --git a/fail2ban/server/transmitter.py b/fail2ban/server/transmitter.py index 010be268..d209441d 100644 --- a/fail2ban/server/transmitter.py +++ b/fail2ban/server/transmitter.py @@ -30,7 +30,7 @@ __license__ = "GPL" import logging, time # Gets the instance of the logger. -logSys = logging.getLogger("fail2ban.comm") +logSys = logging.getLogger(__name__) class Transmitter: From 0ea9904440e1a6d27fd20806c68658c4c4976204 Mon Sep 17 00:00:00 2001 From: Steven Hiscocks Date: Thu, 11 Apr 2013 18:19:44 +0100 Subject: [PATCH 37/37] TST: revert change of log format for testcases in commit a3d82e2 --- bin/fail2ban-testcases | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/fail2ban-testcases b/bin/fail2ban-testcases index d276be1d..68a31786 100755 --- a/bin/fail2ban-testcases +++ b/bin/fail2ban-testcases @@ -109,7 +109,7 @@ else: # Custom log format for the verbose tests runs if verbosity > 1: # pragma: no cover - stdout.setFormatter(Formatter(' %(asctime)-15s %(thread)s %(name)s' + fmt)) + stdout.setFormatter(Formatter(' %(asctime)-15s %(thread)s' + fmt)) else: # pragma: no cover # just prefix with the space stdout.setFormatter(Formatter(fmt))