From 37acc6b8323230d3f314daeeb9c233e694461de9 Mon Sep 17 00:00:00 2001 From: pacop Date: Mon, 30 Jun 2014 14:29:57 +0200 Subject: [PATCH 1/9] ENH: Add dateTime format for PortSentry Added dateTime format for PortSentry with EPOCH format --- fail2ban/tests/datedetectortestcase.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fail2ban/tests/datedetectortestcase.py b/fail2ban/tests/datedetectortestcase.py index 726e73f8..c82f92ba 100644 --- a/fail2ban/tests/datedetectortestcase.py +++ b/fail2ban/tests/datedetectortestcase.py @@ -86,6 +86,7 @@ class DateDetectorTest(unittest.TestCase): (False, "23-Jan-2005 21:59:59.02"), (False, "23-Jan-2005 21:59:59 +0100"), (False, "23-01-2005 21:59:59"), + (True, "1106513999"), # Portsetry (False, "01-23-2005 21:59:59.252"), # reported on f2b, causes Feb29 fix to break (False, "@4000000041f4104f00000000"), # TAI64N (False, "2005-01-23T20:59:59.252Z"), #ISO 8601 (UTC) From ce4f2d1c88f448b303adda8a19b6e7ae23cd8411 Mon Sep 17 00:00:00 2001 From: pacop Date: Sat, 4 Oct 2014 15:08:12 +0200 Subject: [PATCH 2/9] added filter for PortSentry with jail and samples --- config/filter.d/portsentry.conf | 10 ++++++++++ config/jail.conf | 5 +++++ fail2ban/tests/files/logs/portsentry | 4 ++++ 3 files changed, 19 insertions(+) create mode 100644 config/filter.d/portsentry.conf create mode 100644 fail2ban/tests/files/logs/portsentry diff --git a/config/filter.d/portsentry.conf b/config/filter.d/portsentry.conf new file mode 100644 index 00000000..1ee9531c --- /dev/null +++ b/config/filter.d/portsentry.conf @@ -0,0 +1,10 @@ +# Fail2Ban filter for failure attempts in Counter Strike-1.6 +# +# + +[Definition] + +failregex = \/ Port\: [0-9]+ (TCP|UDP) Blocked$ + +# Author: Pacop + diff --git a/config/jail.conf b/config/jail.conf index c42952d8..2fe3dea2 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -709,3 +709,8 @@ enabled = false logpath = /opt/sun/comms/messaging64/log/mail.log_current maxretry = 6 banaction = iptables-allports + +[portsentry] +enabled = false +logpath = /var/lib/portsentry/portsentry.history +maxretry = 1 diff --git a/fail2ban/tests/files/logs/portsentry b/fail2ban/tests/files/logs/portsentry new file mode 100644 index 00000000..19c917a0 --- /dev/null +++ b/fail2ban/tests/files/logs/portsentry @@ -0,0 +1,4 @@ +# failJSON: { "time": "2014-06-27T17:51:19", "match": true , "host": "192.168.56.1" } +1403884279 - 06/27/2014 17:51:19 Host: 192.168.56.1/192.168.56.1 Port: 1 TCP Blocked +# failJSON: { "time": "2014-06-27T17:51:19", "match": true , "host": "192.168.56.1" } +1403884279 - 06/27/2014 17:51:19 Host: 192.168.56.1/192.168.56.1 Port: 1 UDP Blocked \ No newline at end of file From d4015d6566e15a005ad6fd6cdfb2c477bce5e946 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Thu, 23 Oct 2014 14:51:51 -0400 Subject: [PATCH 3/9] ENH: remove obsolete code for python < 2.6 (we support >= 2.6) --- fail2ban/server/asyncserver.py | 8 ++------ fail2ban/tests/samplestestcase.py | 6 +----- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/fail2ban/server/asyncserver.py b/fail2ban/server/asyncserver.py index 14673a99..6e71da77 100644 --- a/fail2ban/server/asyncserver.py +++ b/fail2ban/server/asyncserver.py @@ -149,12 +149,8 @@ class AsyncServer(asyncore.dispatcher): self.__init = True # TODO Add try..catch # There's a bug report for Python 2.6/3.0 that use_poll=True yields some 2.5 incompatibilities: - if sys.version_info >= (2, 6): # if python 2.6 or greater... - logSys.debug("Detected Python 2.6 or greater. asyncore.loop() not using poll") - asyncore.loop(use_poll = False) # fixes the "Unexpected communication problem" issue on Python 2.6 and 3.0 - else: # pragma: no cover - logSys.debug("NOT Python 2.6/3.* - asyncore.loop() using poll") - asyncore.loop(use_poll = True) + logSys.debug("Detected Python 2.6 or greater. asyncore.loop() not using poll") + asyncore.loop(use_poll=False) # fixes the "Unexpected communication problem" issue on Python 2.6 and 3.0 ## # Stops the communication server. diff --git a/fail2ban/tests/samplestestcase.py b/fail2ban/tests/samplestestcase.py index e0831184..2c18a504 100644 --- a/fail2ban/tests/samplestestcase.py +++ b/fail2ban/tests/samplestestcase.py @@ -24,11 +24,7 @@ __license__ = "GPL" import unittest, sys, os, fileinput, re, time, datetime, inspect -if sys.version_info >= (2, 6): - import json -else: - import simplejson as json - next = lambda x: x.next() +import json from ..server.filter import Filter from ..client.filterreader import FilterReader From caa6006a3179513962f960d57a8fca9e6199951b Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sat, 25 Oct 2014 09:25:18 -0400 Subject: [PATCH 4/9] ENH: do use @staticmethod (we are well beyond support of 2.4 now) --- bin/fail2ban-client | 3 +-- fail2ban/client/csocket.py | 3 +-- fail2ban/client/jailreader.py | 3 +-- fail2ban/server/asyncserver.py | 3 +-- fail2ban/server/banmanager.py | 3 +-- fail2ban/server/filter.py | 21 +++++++-------------- fail2ban/server/mytime.py | 14 +++++--------- 7 files changed, 17 insertions(+), 33 deletions(-) diff --git a/bin/fail2ban-client b/bin/fail2ban-client index 0c6999c1..866a5287 100755 --- a/bin/fail2ban-client +++ b/bin/fail2ban-client @@ -419,12 +419,11 @@ class Fail2banClient: ret = False return ret - #@staticmethod + @staticmethod def dumpConfig(cmd): for c in cmd: print c return True - dumpConfig = staticmethod(dumpConfig) class ServerExecutionException(Exception): diff --git a/fail2ban/client/csocket.py b/fail2ban/client/csocket.py index 1d522f6c..921b0de5 100644 --- a/fail2ban/client/csocket.py +++ b/fail2ban/client/csocket.py @@ -57,7 +57,7 @@ class CSocket: self.__csock.close() return ret - #@staticmethod + @staticmethod def receive(sock): msg = EMPTY_BYTES while msg.rfind(CSocket.END_STRING) == -1: @@ -66,4 +66,3 @@ class CSocket: raise RuntimeError, "socket connection broken" msg = msg + chunk return loads(msg) - receive = staticmethod(receive) diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index ffdc5e26..84cc5e2a 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -220,7 +220,7 @@ class JailReader(ConfigReader): stream.insert(0, ["add", self.__name, backend]) return stream - #@staticmethod + @staticmethod def extractOptions(option): match = JailReader.optionCRE.match(option) if not match: @@ -235,4 +235,3 @@ class JailReader(ConfigReader): val for val in optmatch.group(2,3,4) if val is not None][0] option_opts[opt.strip()] = value.strip() return option_name, option_opts - extractOptions = staticmethod(extractOptions) diff --git a/fail2ban/server/asyncserver.py b/fail2ban/server/asyncserver.py index 6e71da77..a54d41a1 100644 --- a/fail2ban/server/asyncserver.py +++ b/fail2ban/server/asyncserver.py @@ -171,12 +171,11 @@ class AsyncServer(asyncore.dispatcher): # @param sock: socket file. - #@staticmethod + @staticmethod def __markCloseOnExec(sock): fd = sock.fileno() flags = fcntl.fcntl(fd, fcntl.F_GETFD) fcntl.fcntl(fd, fcntl.F_SETFD, flags|fcntl.FD_CLOEXEC) - __markCloseOnExec = staticmethod(__markCloseOnExec) ## # AsyncServerException is used to wrap communication exceptions. diff --git a/fail2ban/server/banmanager.py b/fail2ban/server/banmanager.py index b24fa9e5..c21cad45 100644 --- a/fail2ban/server/banmanager.py +++ b/fail2ban/server/banmanager.py @@ -126,7 +126,7 @@ class BanManager: # @param ticket the FailTicket # @return a BanTicket - #@staticmethod + @staticmethod def createBanTicket(ticket): ip = ticket.getIP() #lastTime = ticket.getTime() @@ -134,7 +134,6 @@ class BanManager: banTicket = BanTicket(ip, lastTime, ticket.getMatches()) banTicket.setAttempt(ticket.getAttempt()) return banTicket - createBanTicket = staticmethod(createBanTicket) ## # Add a ban ticket. diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index d1c9d2ad..c886bf35 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -838,7 +838,7 @@ class DNSUtils: IP_CRE = re.compile("^(?:\d{1,3}\.){3}\d{1,3}$") - #@staticmethod + @staticmethod def dnsToIp(dns): """ Convert a DNS into an IP address using the Python socket module. Thanks to Kevin Drapel. @@ -853,9 +853,8 @@ class DNSUtils: logSys.warning("Socket error raised trying to resolve hostname %s: %s" % (dns, e)) return list() - dnsToIp = staticmethod(dnsToIp) - #@staticmethod + @staticmethod def searchIP(text): """ Search if an IP address if directly available and return it. @@ -865,9 +864,8 @@ class DNSUtils: return match else: return None - searchIP = staticmethod(searchIP) - #@staticmethod + @staticmethod def isValidIP(string): """ Return true if str is a valid IP """ @@ -877,9 +875,8 @@ class DNSUtils: return True except socket.error: return False - isValidIP = staticmethod(isValidIP) - #@staticmethod + @staticmethod def textToIp(text, useDns): """ Return the IP of DNS found in a given text. """ @@ -901,9 +898,8 @@ class DNSUtils: text, ipList) return ipList - textToIp = staticmethod(textToIp) - #@staticmethod + @staticmethod def cidr(i, n): """ Convert an IP address string with a CIDR mask into a 32-bit integer. @@ -911,18 +907,15 @@ class DNSUtils: # 32-bit IPv4 address mask MASK = 0xFFFFFFFFL return ~(MASK >> n) & MASK & DNSUtils.addr2bin(i) - cidr = staticmethod(cidr) - #@staticmethod + @staticmethod def addr2bin(string): """ Convert a string IPv4 address into an unsigned integer. """ return struct.unpack("!L", socket.inet_aton(string))[0] - addr2bin = staticmethod(addr2bin) - #@staticmethod + @staticmethod def bin2addr(addr): """ Convert a numeric IPv4 address into string n.n.n.n form. """ return socket.inet_ntoa(struct.pack("!L", addr)) - bin2addr = staticmethod(bin2addr) diff --git a/fail2ban/server/mytime.py b/fail2ban/server/mytime.py index 96c7f8ab..a27f575b 100644 --- a/fail2ban/server/mytime.py +++ b/fail2ban/server/mytime.py @@ -43,48 +43,44 @@ class MyTime: # # @param t the time to set or None - #@staticmethod + @staticmethod def setTime(t): MyTime.myTime = t - setTime = staticmethod(setTime) ## # Equivalent to time.time() # # @return time.time() if setTime was called with None - #@staticmethod + @staticmethod def time(): if MyTime.myTime is None: return time.time() else: return MyTime.myTime - time = staticmethod(time) ## # Equivalent to time.gmtime() # # @return time.gmtime() if setTime was called with None - #@staticmethod + @staticmethod def gmtime(): if MyTime.myTime is None: return time.gmtime() else: return time.gmtime(MyTime.myTime) - gmtime = staticmethod(gmtime) - #@staticmethod + @staticmethod def now(): if MyTime.myTime is None: return datetime.datetime.now() else: return datetime.datetime.fromtimestamp(MyTime.myTime) - now = staticmethod(now) + @staticmethod def localtime(x=None): if MyTime.myTime is None or x is not None: return time.localtime(x) else: return time.localtime(MyTime.myTime) - localtime = staticmethod(localtime) From e1a5decc00a49bf24702b02de9f5ece81a1b84b9 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sat, 25 Oct 2014 09:34:37 -0400 Subject: [PATCH 5/9] DOC: adjust docs in mytime to place docs into docstrings --- fail2ban/server/mytime.py | 62 +++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/fail2ban/server/mytime.py b/fail2ban/server/mytime.py index a27f575b..f284379e 100644 --- a/fail2ban/server/mytime.py +++ b/fail2ban/server/mytime.py @@ -26,46 +26,48 @@ import time, datetime ## # MyTime class. # -# This class is a wrapper around time.time() and time.gmtime(). When -# performing unit test, it is very useful to get a fixed value from these -# functions. -# Thus, time.time() and time.gmtime() should never be called directly. -# This wrapper should be called instead. The API are equivalent. class MyTime: - + """A wrapper around time module primarily for testing purposes + + This class is a wrapper around time.time() and time.gmtime(). When + performing unit test, it is very useful to get a fixed value from + these functions. Thus, time.time() and time.gmtime() should never + be called directly. This wrapper should be called instead. The API + are equivalent. + """ + myTime = None - - ## - # Sets the current time. - # - # Use None in order to always get the real current time. - # - # @param t the time to set or None - + @staticmethod def setTime(t): + """Set current time. + + Use None in order to always get the real current time. + + @param t the time to set or None + """ + MyTime.myTime = t - - ## - # Equivalent to time.time() - # - # @return time.time() if setTime was called with None - + @staticmethod def time(): + """Decorate time.time() for the purpose of testing mocking + + @return time.time() if setTime was called with None + """ + if MyTime.myTime is None: return time.time() else: return MyTime.myTime - - ## - # Equivalent to time.gmtime() - # - # @return time.gmtime() if setTime was called with None - + @staticmethod def gmtime(): + """Decorate time.gmtime() for the purpose of testing mocking + + @return time.gmtime() if setTime was called with None + """ if MyTime.myTime is None: return time.gmtime() else: @@ -73,6 +75,10 @@ class MyTime: @staticmethod def now(): + """Decorate datetime.now() for the purpose of testing mocking + + @return datetime.now() if setTime was called with None + """ if MyTime.myTime is None: return datetime.datetime.now() else: @@ -80,6 +86,10 @@ class MyTime: @staticmethod def localtime(x=None): + """Decorate time.localtime() for the purpose of testing mocking + + @return time.localtime() if setTime was called with None + """ if MyTime.myTime is None or x is not None: return time.localtime(x) else: From 6293e448895cc342ef83f005a92f304a5d783c3d Mon Sep 17 00:00:00 2001 From: Florian Pelgrim Date: Wed, 13 Aug 2014 17:34:02 +0200 Subject: [PATCH 6/9] Added myself into THANKS --- THANKS | 1 + 1 file changed, 1 insertion(+) diff --git a/THANKS b/THANKS index 0433f7ed..61e99466 100644 --- a/THANKS +++ b/THANKS @@ -26,6 +26,7 @@ Christian Rauch Christophe Carles Christoph Haas Christos Psonis +craneworks Cyril Jaquier Daniel B. Cid Daniel B. From 3dabd5fc833e2546d4715366126ac600a2088614 Mon Sep 17 00:00:00 2001 From: Florian Pelgrim Date: Sat, 25 Oct 2014 10:38:18 -0400 Subject: [PATCH 7/9] DOC: documentation about available vagrantfile setup manually picked up from a commit within https://github.com/fail2ban/fail2ban/pull/786 --- DEVELOP | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/DEVELOP b/DEVELOP index f1426561..1384a6ac 100644 --- a/DEVELOP +++ b/DEVELOP @@ -81,6 +81,18 @@ some quick commands:: status test +Testing with vagrant +-------------------- + +Testing can now be done inside a vagrant VM. Vagrantfile provided in +source code repository established two VMs: + +- VM "secure" which can be used for testing fail2ban code. +- VM "attacker" which hcan be used to perform attack against our "secure" VM. + +Both VMs are sharing the 192.168.200/24 network. If you are using this network +take a look into the Vagrantfile and change the IP. + Coding Standards ================ From 3dac76559853b25ce308488dd1eba6eb5d2ab6b9 Mon Sep 17 00:00:00 2001 From: sebres Date: Sat, 25 Oct 2014 17:20:01 +0200 Subject: [PATCH 8/9] ConfigReader.touch renamed into protected _create_unshared --- fail2ban/client/configreader.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fail2ban/client/configreader.py b/fail2ban/client/configreader.py index d9bfb271..b6c39628 100644 --- a/fail2ban/client/configreader.py +++ b/fail2ban/client/configreader.py @@ -77,7 +77,7 @@ class ConfigReader(): """ # already shared ? if not self._cfg: - self.touch(name) + self._create_unshared(name) # performance feature - read once if using shared config reader: if once and self._cfg.read_cfg_files is not None: return self._cfg.read_cfg_files @@ -90,7 +90,7 @@ class ConfigReader(): self._cfg.read_cfg_files = ret return ret - def touch(self, name=''): + def _create_unshared(self, name=''): """ Allocates and share a config file by it name. Automatically allocates unshared or reuses shared handle by given 'name' and @@ -268,7 +268,7 @@ class DefinitionInitConfigReader(ConfigReader): # needed for fail2ban-regex that doesn't need fancy directories def readexplicit(self): if not self._cfg: - self.touch(self._file) + self._create_unshared(self._file) return SafeConfigParserWithIncludes.read(self._cfg, self._file) def getOptions(self, pOpts): From b60e2bf42f888f7a5421731a12742c0b8c74ccb9 Mon Sep 17 00:00:00 2001 From: pacop Date: Sat, 25 Oct 2014 18:17:57 +0200 Subject: [PATCH 9/9] Add portsentry to changelog --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index ad92a55e..3e9d99b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -81,6 +81,7 @@ ver. 0.9.1 (2014/xx/xx) - better, faster, stronger not affect SYSLOG output * Log unhandled exceptions * cyrus-imap: catch "user not found" attempts + * Add support for Portsentry ver. 0.9.0 (2014/03/14) - beta ----------