diff --git a/.gitignore b/.gitignore index dd4b1af..082f70a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1 @@ -fail2ban-FAIL2BAN-0_8.tar.bz2 -fail2ban-0.8.4.tar.bz2 -/fail2ban_0.8.7.1.orig.tar.gz -/fail2ban_0.8.8.orig.tar.gz -/fail2ban-0.8.10.tar.gz -/fail2ban-0.8.11.tar.gz -/fail2ban-0.9-d529151.tar.xz -/fail2ban-0.9-1f1a561.tar.xz -/fail2ban-0.9.tar.gz -/fail2ban-0.9.1.tar.gz -/fail2ban-0.9.2.tar.gz -/fail2ban-0.9.3.tar.gz -/fail2ban-0.9.4.tar.gz -/fail2ban-0.9.5.tar.gz -/fail2ban-0.9.6.tar.gz -/fail2ban-0.9.7.tar.gz -/fail2ban-0.10.0.tar.gz -/fail2ban-0.10.1.tar.gz -/fail2ban-0.10.2.tar.gz -/fail2ban-0.10.3.1.tar.gz -/fail2ban-0.10.4.tar.gz -/fail2ban-0.10.5.tar.gz -/fail2ban-0.11.1.tar.gz +/fail2ban-*/ diff --git a/04ff4c060cdc233af9a6deeb85a6523da0416f31.patch b/04ff4c060cdc233af9a6deeb85a6523da0416f31.patch new file mode 100644 index 0000000..cb6d5c2 --- /dev/null +++ b/04ff4c060cdc233af9a6deeb85a6523da0416f31.patch @@ -0,0 +1,60 @@ +From 04ff4c060cdc233af9a6deeb85a6523da0416f31 Mon Sep 17 00:00:00 2001 +From: Nic Boet +Date: Fri, 13 Jun 2025 16:44:57 -0500 +Subject: [PATCH] Dovecot 2.4 filter support + +Dovecot 2.4 release is a major upgrade +Logger event structure has changed, all messages are now +prefixed with: + + "Login aborted: " "auth failed" + +Maintain 2.3 support as many folks have yet to migrate, +community edition is still receiving cretial security patches + +Dovecot 2.4.1 +Python 3.12.10 + +Signed-off-by: Nic Boet +--- + config/filter.d/dovecot.conf | 2 ++ + fail2ban/tests/files/logs/dovecot | 6 ++++++ + 2 files changed, 8 insertions(+) + +diff --git a/config/filter.d/dovecot.conf b/config/filter.d/dovecot.conf +index dc3ebbcd42..f49eebe726 100644 +--- a/config/filter.d/dovecot.conf ++++ b/config/filter.d/dovecot.conf +@@ -17,6 +17,7 @@ prefregex = ^%(__prefix_line)s(?:%(_auth_worker)s(?:\([^\)]+\))?: )?(?:%(__pam_a + + failregex = ^authentication failure; logname=\S* uid=\S* euid=\S* tty=dovecot ruser=\S* rhost=(?:\s+user=\S*)?\s*$ + ^(?:Aborted login|Disconnected|Remote closed connection|Client has quit the connection)%(_bypass_reject_reason)s \((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\):(?: user=<[^>]*>,)?(?: method=\S+,)? rip=(?:[^>]*(?:, session=<\S+>)?)\s*$ ++ ^(?:Login aborted):\s*%(_bypass_reject_reason)s.*?\((?:auth failed, \d+ attempts(?: in \d+ secs)?|tried to use (?:disabled|disallowed) \S+ auth|proxy dest auth failed)\)(?:\s*\([^)]+\))?:\s*(?:user=<[^>]*>,?\s*)?(?:,?\s*method=\S+,\s*)?rip=(?:[^>]*(?:, session=<\S+>)?)\s*$ + ^pam\(\S+,(?:,\S*)?\): pam_authenticate\(\) failed: (?:User not known to the underlying authentication module: \d+ Time\(s\)|Authentication failure \([Pp]assword mismatch\?\)|Permission denied)\s*$ + ^[a-z\-]{3,15}\(\S*,(?:,\S*)?\): (?:[Uu]nknown user|[Ii]nvalid credentials|[Pp]assword mismatch) + > +@@ -43,6 +44,7 @@ datepattern = {^LN-BEG}TAI64N + # DEV Notes: + # * the first regex is essentially a copy of pam-generic.conf + # * Probably doesn't do dovecot sql/ldap backends properly (resolved in edit 21/03/2016) ++# * Dovecot version 2.4 changed event log structure, line prior needed to maintain 2.3 support + # + # Author: Martin Waschbuesch + # Daniel Black (rewrote with begin and end anchors) +diff --git a/fail2ban/tests/files/logs/dovecot b/fail2ban/tests/files/logs/dovecot +index 0e33296129..4f5a0b7867 100644 +--- a/fail2ban/tests/files/logs/dovecot ++++ b/fail2ban/tests/files/logs/dovecot +@@ -22,6 +22,12 @@ Jun 14 00:48:21 platypus dovecot: imap-login: Disconnected (auth failed, 1 attem + # failJSON: { "time": "2005-06-23T00:52:43", "match": true , "host": "193.95.245.163" } + Jun 23 00:52:43 vhost1-ua dovecot: pop3-login: Disconnected: Inactivity (auth failed, 1 attempts): user=, method=PLAIN, rip=193.95.245.163, lip=176.214.13.210 + ++# Dovecot version 2.4 ++# failJSON: { "time": "2005-06-12T19:07:29", "match": true , "host": "192.0.2.241" } ++Jun 12 19:07:29 hostname dovecot[241]: imap-login: Login aborted: Connection closed (auth failed, 3 attempts in 16 secs) (auth_failed): user=, method=PLAIN, rip=192.0.2.241, lip=203.0.113.104, TLS, session=<9ZHq02g3J8S60fan> ++# failJSON: { "time": "2005-06-13T16:35:56", "match": true , "host": "192.0.2.241" } ++Jun 13 16:35:56 mx dovecot[241]: managesieve-login: Login aborted: Logged out (auth failed, 1 attempts in 10 secs) (auth_failed): user=, method=PLAIN, rip=192.0.2.241, lip=203.0.113.104, TLS, session= ++ + # failJSON: { "time": "2005-07-02T13:49:31", "match": true , "host": "192.51.100.13" } + Jul 02 13:49:31 hostname dovecot[442]: pop3-login: Aborted login (auth failed, 1 attempts in 17 secs): user=, method=PLAIN, rip=192.51.100.13, lip=203.0.113.17, session= + diff --git a/2605.patch b/2605.patch deleted file mode 100644 index 05e5646..0000000 --- a/2605.patch +++ /dev/null @@ -1,152 +0,0 @@ -From 3965d690b137152b2a0a6a46989178b5566cfd8e Mon Sep 17 00:00:00 2001 -From: Angelo Compagnucci -Date: Thu, 16 Jan 2020 12:05:13 +0100 -Subject: [PATCH 1/2] Revert "setup.py: adding option to install without tests" - -Test should actually removed from the stup data in finalize_options -instead of being added back. - -This reverts commit 9b918bba2f672780fb4469294d80ba7deb6b8cab. - -Signed-off-by: Angelo Compagnucci ---- - setup.py | 41 ++++++++++++++++------------------------- - 1 file changed, 16 insertions(+), 25 deletions(-) - -diff --git a/setup.py b/setup.py -index e476c5dd6..8da292683 100755 ---- a/setup.py -+++ b/setup.py -@@ -119,11 +119,9 @@ def update_scripts(self, dry_run=False): - class install_command_f2b(install): - user_options = install.user_options + [ - ('disable-2to3', None, 'Specify to deactivate 2to3, e.g. if the install runs from fail2ban test-cases.'), -- ('without-tests', None, 'without tests files installation'), - ] - def initialize_options(self): - self.disable_2to3 = None -- self.without_tests = None - install.initialize_options(self) - def finalize_options(self): - global _2to3 -@@ -134,28 +132,6 @@ def finalize_options(self): - cmdclass = self.distribution.cmdclass - cmdclass['build_py'] = build_py_2to3 - cmdclass['build_scripts'] = build_scripts_2to3 -- if not self.without_tests: -- self.distribution.scripts += [ -- 'bin/fail2ban-testcases', -- ] -- -- self.distribution.packages += [ -- 'fail2ban.tests', -- 'fail2ban.tests.action_d', -- ] -- -- self.distribution.package_data = { -- 'fail2ban.tests': -- [ join(w[0], f).replace("fail2ban/tests/", "", 1) -- for w in os.walk('fail2ban/tests/files') -- for f in w[2]] + -- [ join(w[0], f).replace("fail2ban/tests/", "", 1) -- for w in os.walk('fail2ban/tests/config') -- for f in w[2]] + -- [ join(w[0], f).replace("fail2ban/tests/", "", 1) -- for w in os.walk('fail2ban/tests/action_d') -- for f in w[2]] -- } - install.finalize_options(self) - def run(self): - install.run(self) -@@ -232,20 +208,35 @@ def run(self): - license = "GPL", - platforms = "Posix", - cmdclass = { -- 'build_py': build_py, 'build_scripts': build_scripts, -+ 'build_py': build_py, 'build_scripts': build_scripts, - 'install_scripts': install_scripts_f2b, 'install': install_command_f2b - }, - scripts = [ - 'bin/fail2ban-client', - 'bin/fail2ban-server', - 'bin/fail2ban-regex', -+ 'bin/fail2ban-testcases', - # 'bin/fail2ban-python', -- link (binary), will be installed via install_scripts_f2b wrapper - ], - packages = [ - 'fail2ban', - 'fail2ban.client', - 'fail2ban.server', -+ 'fail2ban.tests', -+ 'fail2ban.tests.action_d', - ], -+ package_data = { -+ 'fail2ban.tests': -+ [ join(w[0], f).replace("fail2ban/tests/", "", 1) -+ for w in os.walk('fail2ban/tests/files') -+ for f in w[2]] + -+ [ join(w[0], f).replace("fail2ban/tests/", "", 1) -+ for w in os.walk('fail2ban/tests/config') -+ for f in w[2]] + -+ [ join(w[0], f).replace("fail2ban/tests/", "", 1) -+ for w in os.walk('fail2ban/tests/action_d') -+ for f in w[2]] -+ }, - data_files = [ - ('/etc/fail2ban', - glob("config/*.conf") - -From 5fa1f69264d3c23793f64c03c96737d54555e919 Mon Sep 17 00:00:00 2001 -From: Angelo Compagnucci -Date: Thu, 16 Jan 2020 12:28:42 +0100 -Subject: [PATCH 2/2] setup.py: adding option to install without tests - -Tests files are not always needed especially when installing on low -resource systems like an embedded one. -This patch adds the --without-tests option to skip installing the -tests files. - -Signed-off-by: Angelo Compagnucci ---- - setup.py | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/setup.py b/setup.py -index 8da292683..ce1eedf68 100755 ---- a/setup.py -+++ b/setup.py -@@ -119,9 +119,11 @@ def update_scripts(self, dry_run=False): - class install_command_f2b(install): - user_options = install.user_options + [ - ('disable-2to3', None, 'Specify to deactivate 2to3, e.g. if the install runs from fail2ban test-cases.'), -+ ('without-tests', None, 'without tests files installation'), - ] - def initialize_options(self): - self.disable_2to3 = None -+ self.without_tests = None - install.initialize_options(self) - def finalize_options(self): - global _2to3 -@@ -132,6 +134,13 @@ def finalize_options(self): - cmdclass = self.distribution.cmdclass - cmdclass['build_py'] = build_py_2to3 - cmdclass['build_scripts'] = build_scripts_2to3 -+ if self.without_tests: -+ self.distribution.scripts.remove('bin/fail2ban-testcases') -+ -+ self.distribution.packages.remove('fail2ban.tests') -+ self.distribution.packages.remove('fail2ban.tests.action_d') -+ -+ del self.distribution.package_data['fail2ban.tests'] - install.finalize_options(self) - def run(self): - install.run(self) -@@ -208,7 +217,7 @@ def run(self): - license = "GPL", - platforms = "Posix", - cmdclass = { -- 'build_py': build_py, 'build_scripts': build_scripts, -+ 'build_py': build_py, 'build_scripts': build_scripts, - 'install_scripts': install_scripts_f2b, 'install': install_command_f2b - }, - scripts = [ diff --git a/2651.patch b/2651.patch deleted file mode 100644 index 520d5d2..0000000 --- a/2651.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 781a25512b107828aff71998c19f2fa4dbf471c1 Mon Sep 17 00:00:00 2001 -From: "Sergey G. Brester" -Date: Fri, 6 Mar 2020 19:04:39 +0100 -Subject: [PATCH 1/4] travis CI: add 3.9-dev as target - ---- - .travis.yml | 1 + - 1 file changed, 1 insertion(+) - ---- a/fail2ban/server/jailthread.py -+++ b/fail2ban/server/jailthread.py -@@ -120,3 +120,6 @@ class JailThread(Thread): - ## python 2.x replace binding of private __bootstrap method: - if sys.version_info < (3,): # pragma: 3.x no cover - JailThread._Thread__bootstrap = JailThread._JailThread__bootstrap -+## python 3.9, restore isAlive method: -+elif not hasattr(JailThread, 'isAlive'): # pragma: 2.x no cover -+ JailThread.isAlive = JailThread.is_alive ---- a/fail2ban/tests/sockettestcase.py -+++ b/fail2ban/tests/sockettestcase.py -@@ -87,7 +87,7 @@ class Socket(LogCaptureTestCase): - def _stopServerThread(self): - serverThread = self.serverThread - # wait for end of thread : -- Utils.wait_for(lambda: not serverThread.isAlive() -+ Utils.wait_for(lambda: not serverThread.is_alive() - or serverThread.join(Utils.DEFAULT_SLEEP_TIME), unittest.F2B.maxWaitTime(10)) - self.serverThread = None - -@@ -98,7 +98,7 @@ class Socket(LogCaptureTestCase): - self.server.close() - # wait for end of thread : - self._stopServerThread() -- self.assertFalse(serverThread.isAlive()) -+ self.assertFalse(serverThread.is_alive()) - # clean : - self.server.stop() - self.assertFalse(self.server.isActive()) -@@ -139,7 +139,7 @@ class Socket(LogCaptureTestCase): - self.server.stop() - # wait for end of thread : - self._stopServerThread() -- self.assertFalse(serverThread.isAlive()) -+ self.assertFalse(serverThread.is_alive()) - self.assertFalse(self.server.isActive()) - self.assertFalse(os.path.exists(self.sock_name)) - -@@ -180,7 +180,7 @@ class Socket(LogCaptureTestCase): - self.server.stop() - # wait for end of thread : - self._stopServerThread() -- self.assertFalse(serverThread.isAlive()) -+ self.assertFalse(serverThread.is_alive()) - - def testLoopErrors(self): - # replace poll handler to produce error in loop-cycle: -@@ -216,7 +216,7 @@ class Socket(LogCaptureTestCase): - self.server.stop() - # wait for end of thread : - self._stopServerThread() -- self.assertFalse(serverThread.isAlive()) -+ self.assertFalse(serverThread.is_alive()) - self.assertFalse(self.server.isActive()) - self.assertFalse(os.path.exists(self.sock_name)) - diff --git a/309c8dddd7adc2de140ed5a72088cd4f2dcc9b91.patch b/309c8dddd7adc2de140ed5a72088cd4f2dcc9b91.patch deleted file mode 100644 index 2039459..0000000 --- a/309c8dddd7adc2de140ed5a72088cd4f2dcc9b91.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 309c8dddd7adc2de140ed5a72088cd4f2dcc9b91 Mon Sep 17 00:00:00 2001 -From: sebres -Date: Wed, 24 Jun 2020 19:20:36 +0200 -Subject: [PATCH] action.d/nftables.conf (type=multiport only): fixed port - range selector (replacing `:` with `-`) - ---- - config/action.d/nftables.conf | 2 +- - fail2ban/tests/servertestcase.py | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/config/action.d/nftables.conf b/config/action.d/nftables.conf -index c1fb8550f..77cf36615 100644 ---- a/config/action.d/nftables.conf -+++ b/config/action.d/nftables.conf -@@ -34,7 +34,7 @@ type = multiport - - rule_match-custom = - rule_match-allports = meta l4proto \{ \} --rule_match-multiport = $proto dport \{ \} -+rule_match-multiport = $proto dport \{ $(echo '' | sed s/:/-/g) \} - match = > - - # Option: rule_stat -diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py -index b771ab50b..f1b667b12 100644 ---- a/fail2ban/tests/servertestcase.py -+++ b/fail2ban/tests/servertestcase.py -@@ -1296,11 +1296,11 @@ def testCheckStockCommandActions(self): - ), - 'ip4-start': ( - r"`nft add set inet f2b-table addr-set-j-w-nft-mp \{ type ipv4_addr\; \}`", -- r"`nft add rule inet f2b-table f2b-chain $proto dport \{ http,https \} ip saddr @addr-set-j-w-nft-mp reject`", -+ r"`nft add rule inet f2b-table f2b-chain $proto dport \{ $(echo 'http,https' | sed s/:/-/g) \} ip saddr @addr-set-j-w-nft-mp reject`", - ), - 'ip6-start': ( - r"`nft add set inet f2b-table addr6-set-j-w-nft-mp \{ type ipv6_addr\; \}`", -- r"`nft add rule inet f2b-table f2b-chain $proto dport \{ http,https \} ip6 saddr @addr6-set-j-w-nft-mp reject`", -+ r"`nft add rule inet f2b-table f2b-chain $proto dport \{ $(echo 'http,https' | sed s/:/-/g) \} ip6 saddr @addr6-set-j-w-nft-mp reject`", - ), - 'flush': ( - "`{ nft flush set inet f2b-table addr-set-j-w-nft-mp 2> /dev/null; } || ", diff --git a/343ec1cdd296530f331637c725bd2bb0549e01e6.patch b/343ec1cdd296530f331637c725bd2bb0549e01e6.patch deleted file mode 100644 index fb597ad..0000000 --- a/343ec1cdd296530f331637c725bd2bb0549e01e6.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 343ec1cdd296530f331637c725bd2bb0549e01e6 Mon Sep 17 00:00:00 2001 -From: sebres -Date: Wed, 18 Mar 2020 20:37:25 +0100 -Subject: [PATCH] test-causes: avoid host-depending issue (mistakenly ignoring - IP 127.0.0.2 as own address) - replace loop-back addr with test sub-net addr - (and disable ignoreself) - ---- - fail2ban/tests/observertestcase.py | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/fail2ban/tests/observertestcase.py b/fail2ban/tests/observertestcase.py -index 8e9444548..e379ccd18 100644 ---- a/fail2ban/tests/observertestcase.py -+++ b/fail2ban/tests/observertestcase.py -@@ -36,7 +36,6 @@ - from ..server.observer import Observers, ObserverThread - from ..server.utils import Utils - from .utils import LogCaptureTestCase --from ..server.filter import Filter - from .dummyjail import DummyJail - - from .databasetestcase import getFail2BanDb, Fail2BanDb -@@ -224,7 +223,7 @@ def testBanTimeIncr(self): - jail.actions.setBanTime(10) - jail.setBanTimeExtra('increment', 'true') - jail.setBanTimeExtra('multipliers', '1 2 4 8 16 32 64 128 256 512 1024 2048') -- ip = "127.0.0.2" -+ ip = "192.0.2.1" - # used as start and fromtime (like now but time independence, cause test case can run slow): - stime = int(MyTime.time()) - ticket = FailTicket(ip, stime, []) -@@ -385,10 +384,12 @@ def testBanTimeIncr(self): - - # two separate jails : - jail1 = DummyJail(backend='polling') -+ jail1.filter.ignoreSelf = False - jail1.setBanTimeExtra('increment', 'true') - jail1.database = self.db - self.db.addJail(jail1) - jail2 = DummyJail(name='DummyJail-2', backend='polling') -+ jail2.filter.ignoreSelf = False - jail2.database = self.db - self.db.addJail(jail2) - ticket1 = FailTicket(ip, stime, []) -@@ -477,7 +478,7 @@ def testObserver(self): - self.assertEqual(tickets, []) - - # add failure: -- ip = "127.0.0.2" -+ ip = "192.0.2.1" - ticket = FailTicket(ip, stime-120, []) - failManager = FailManager() - failManager.setMaxRetry(3) diff --git a/3728.patch b/3728.patch new file mode 100644 index 0000000..b25c4a9 --- /dev/null +++ b/3728.patch @@ -0,0 +1,160 @@ +From a763fbbdfd6486e372965b4009eb3fe5db346718 Mon Sep 17 00:00:00 2001 +From: Branch Vincent +Date: Sat, 27 Apr 2024 10:24:01 -0700 +Subject: [PATCH 1/3] replace distutils for python 3.12 + +--- + doc/conf.py | 5 +---- + fail2ban/server/filterpyinotify.py | 3 +-- + fail2ban/server/filtersystemd.py | 3 +-- + 3 files changed, 3 insertions(+), 8 deletions(-) + +diff --git a/doc/conf.py b/doc/conf.py +index 20845a5a0e..48d27f7062 100644 +--- a/doc/conf.py ++++ b/doc/conf.py +@@ -47,12 +47,9 @@ + # + + from fail2ban.version import version as fail2ban_version +-from distutils.version import LooseVersion +- +-fail2ban_loose_version = LooseVersion(fail2ban_version) + + # The short X.Y version. +-version = ".".join(str(_) for _ in fail2ban_loose_version.version[:2]) ++version = ".".join(str(_) for _ in fail2ban_version.split(".")[:2]) + # The full version, including alpha/beta/rc tags. + release = fail2ban_version + +diff --git a/fail2ban/server/filterpyinotify.py b/fail2ban/server/filterpyinotify.py +index 81bc7de393..c6972ced3f 100644 +--- a/fail2ban/server/filterpyinotify.py ++++ b/fail2ban/server/filterpyinotify.py +@@ -24,7 +24,6 @@ + __license__ = "GPL" + + import logging +-from distutils.version import LooseVersion + import os + from os.path import dirname, sep as pathsep + +@@ -38,7 +37,7 @@ + + + if not hasattr(pyinotify, '__version__') \ +- or LooseVersion(pyinotify.__version__) < '0.8.3': # pragma: no cover ++ or pyinotify.__version__.split(".") < '0.8.3'.split("."): # pragma: no cover + raise ImportError("Fail2Ban requires pyinotify >= 0.8.3") + + # Verify that pyinotify is functional on this system +diff --git a/fail2ban/server/filtersystemd.py b/fail2ban/server/filtersystemd.py +index 5aea9fdadc..2d4f862b97 100644 +--- a/fail2ban/server/filtersystemd.py ++++ b/fail2ban/server/filtersystemd.py +@@ -24,10 +24,9 @@ + + import os + import time +-from distutils.version import LooseVersion + + from systemd import journal +-if LooseVersion(getattr(journal, '__version__', "0")) < '204': ++if getattr(journal, "__version__", "0").split(".") < "204".split("."): + raise ImportError("Fail2Ban requires systemd >= 204") + + from .failmanager import FailManagerEmpty + +From ed20a9a5b9039319dd8913dfecf640e6eafee28b Mon Sep 17 00:00:00 2001 +From: sebres +Date: Tue, 7 May 2024 12:51:14 +0200 +Subject: [PATCH 2/3] there is no systemd < 204 and pyinotify < 0.8.3 for + supported python3 versions anymore + +--- + fail2ban/server/filterpyinotify.py | 4 ---- + fail2ban/server/filtersystemd.py | 2 -- + 2 files changed, 6 deletions(-) + +diff --git a/fail2ban/server/filterpyinotify.py b/fail2ban/server/filterpyinotify.py +index c6972ced3f..f2f31e6fb5 100644 +--- a/fail2ban/server/filterpyinotify.py ++++ b/fail2ban/server/filterpyinotify.py +@@ -36,10 +36,6 @@ + from ..helpers import getLogger + + +-if not hasattr(pyinotify, '__version__') \ +- or pyinotify.__version__.split(".") < '0.8.3'.split("."): # pragma: no cover +- raise ImportError("Fail2Ban requires pyinotify >= 0.8.3") +- + # Verify that pyinotify is functional on this system + # Even though imports -- might be dysfunctional, e.g. as on kfreebsd + try: +diff --git a/fail2ban/server/filtersystemd.py b/fail2ban/server/filtersystemd.py +index 2d4f862b97..abd66e1f76 100644 +--- a/fail2ban/server/filtersystemd.py ++++ b/fail2ban/server/filtersystemd.py +@@ -26,8 +26,6 @@ + import time + + from systemd import journal +-if getattr(journal, "__version__", "0").split(".") < "204".split("."): +- raise ImportError("Fail2Ban requires systemd >= 204") + + from .failmanager import FailManagerEmpty + from .filter import JournalFilter, Filter + +From 0185e1c7d5e6534ab212462dd2aeab6f89e2fb50 Mon Sep 17 00:00:00 2001 +From: sebres +Date: Tue, 7 May 2024 13:06:50 +0200 +Subject: [PATCH 3/3] setup.py: no distutils anymore + +--- + setup.py | 25 ++++++------------------- + 1 file changed, 6 insertions(+), 19 deletions(-) + +diff --git a/setup.py b/setup.py +index 9f7bd8fb59..ee9ea4df82 100755 +--- a/setup.py ++++ b/setup.py +@@ -24,23 +24,10 @@ + + import platform + +-try: +- import setuptools +- from setuptools import setup +- from setuptools.command.install import install +- from setuptools.command.install_scripts import install_scripts +- from setuptools.command.build_py import build_py +- build_scripts = None +-except ImportError: +- setuptools = None +- from distutils.core import setup +- +-# older versions +-if setuptools is None: +- from distutils.command.build_py import build_py +- from distutils.command.build_scripts import build_scripts +- from distutils.command.install import install +- from distutils.command.install_scripts import install_scripts ++import setuptools ++from setuptools import setup ++from setuptools.command.install import install ++from setuptools.command.install_scripts import install_scripts + + import os + from os.path import isfile, join, isdir, realpath +@@ -207,9 +194,9 @@ def run(self): + url = "http://www.fail2ban.org", + license = "GPL", + platforms = "Posix", +- cmdclass = dict({'build_py': build_py, 'build_scripts': build_scripts} if build_scripts else {}, **{ ++ cmdclass = { + 'install_scripts': install_scripts_f2b, 'install': install_command_f2b +- }), ++ }, + scripts = [ + 'bin/fail2ban-client', + 'bin/fail2ban-server', diff --git a/3782.patch b/3782.patch new file mode 100644 index 0000000..764db01 --- /dev/null +++ b/3782.patch @@ -0,0 +1,94 @@ +From 2fed408c05ac5206b490368d94599869bd6a056d Mon Sep 17 00:00:00 2001 +From: Fabian Dellwing +Date: Tue, 2 Jul 2024 07:54:15 +0200 +Subject: [PATCH 1/5] Adjust sshd filter for OpenSSH 9.8 new daemon name + +--- + config/filter.d/sshd.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config/filter.d/sshd.conf b/config/filter.d/sshd.conf +index 1c8a02deb5..a1fd749aed 100644 +--- a/config/filter.d/sshd.conf ++++ b/config/filter.d/sshd.conf +@@ -16,7 +16,7 @@ before = common.conf + + [DEFAULT] + +-_daemon = sshd ++_daemon = (?:sshd(?:-session)?) + + # optional prefix (logged from several ssh versions) like "error: ", "error: PAM: " or "fatal: " + __pref = (?:(?:error|fatal): (?:PAM: )?)? + +From 7b335f47ea112e2a36e59287582e613aef2fa0a3 Mon Sep 17 00:00:00 2001 +From: "Sergey G. Brester" +Date: Wed, 3 Jul 2024 19:09:28 +0200 +Subject: [PATCH 2/5] sshd: add test coverage for new format, gh-3782 + +--- + fail2ban/tests/files/logs/sshd | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fail2ban/tests/files/logs/sshd b/fail2ban/tests/files/logs/sshd +index ed54ded4d4..7d3948ed80 100644 +--- a/fail2ban/tests/files/logs/sshd ++++ b/fail2ban/tests/files/logs/sshd +@@ -20,6 +20,9 @@ Feb 25 14:34:10 belka sshd[31603]: Failed password for invalid user ROOT from aa + # failJSON: { "time": "2005-02-25T14:34:11", "match": true , "host": "aaaa:bbbb:cccc:1234::1:1" } + Feb 25 14:34:11 belka sshd[31603]: Failed password for invalid user ROOT from aaaa:bbbb:cccc:1234::1:1 + ++# failJSON: { "time": "2005-07-03T14:59:17", "match": true , "host": "192.0.2.1", "desc": "new log with session in daemon prefix, gh-3782" } ++Jul 3 14:59:17 host sshd-session[1571]: Failed password for root from 192.0.2.1 port 56502 ssh2 ++ + #3 + # failJSON: { "time": "2005-01-05T01:31:41", "match": true , "host": "1.2.3.4" } + Jan 5 01:31:41 www sshd[1643]: ROOT LOGIN REFUSED FROM 1.2.3.4 + +From 8360776ce1b119d519a842069c73bec7f5e24fad Mon Sep 17 00:00:00 2001 +From: "Sergey G. Brester" +Date: Wed, 3 Jul 2024 19:33:39 +0200 +Subject: [PATCH 3/5] zzz-sshd-obsolete-multiline.conf: adjusted to new + sshd-session log format + +--- + fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf b/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf +index ad8adeb69f..14256ba68c 100644 +--- a/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf ++++ b/fail2ban/tests/config/filter.d/zzz-sshd-obsolete-multiline.conf +@@ -9,7 +9,7 @@ before = ../../../../config/filter.d/common.conf + + [DEFAULT] + +-_daemon = sshd ++_daemon = sshd(?:-session)? + + # optional prefix (logged from several ssh versions) like "error: ", "error: PAM: " or "fatal: " + __pref = (?:(?:error|fatal): (?:PAM: )?)? + +From 50ff131a0fd8f54fdeb14b48353f842ee8ae8c1a Mon Sep 17 00:00:00 2001 +From: "Sergey G. Brester" +Date: Wed, 3 Jul 2024 19:35:28 +0200 +Subject: [PATCH 4/5] filter.d/sshd.conf: ungroup (unneeded for _daemon) + +--- + config/filter.d/sshd.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config/filter.d/sshd.conf b/config/filter.d/sshd.conf +index a1fd749aed..3a84b1ba52 100644 +--- a/config/filter.d/sshd.conf ++++ b/config/filter.d/sshd.conf +@@ -16,7 +16,7 @@ before = common.conf + + [DEFAULT] + +-_daemon = (?:sshd(?:-session)?) ++_daemon = sshd(?:-session)? + + # optional prefix (logged from several ssh versions) like "error: ", "error: PAM: " or "fatal: " + __pref = (?:(?:error|fatal): (?:PAM: )?)? + diff --git a/54c0effceb998b73545073ac59c479d9d9bf19a4.patch b/54c0effceb998b73545073ac59c479d9d9bf19a4.patch new file mode 100644 index 0000000..e606591 --- /dev/null +++ b/54c0effceb998b73545073ac59c479d9d9bf19a4.patch @@ -0,0 +1,23 @@ +From 54c0effceb998b73545073ac59c479d9d9bf19a4 Mon Sep 17 00:00:00 2001 +From: sebres +Date: Sun, 11 Aug 2024 12:10:12 +0200 +Subject: [PATCH] filter.d/sshd.conf: amend to #3747/#3812 (new ssh version + would log with `_COMM=sshd-session`) + +--- + config/filter.d/sshd.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/config/filter.d/sshd.conf b/config/filter.d/sshd.conf +index 206b913a78..595e957f0b 100644 +--- a/config/filter.d/sshd.conf ++++ b/config/filter.d/sshd.conf +@@ -126,7 +126,7 @@ ignoreregex = + + maxlines = 1 + +-journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd ++journalmatch = _SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session + + # DEV Notes: + # diff --git a/8694c547285c4030d4bf7661981673038e6e9829.patch b/8694c547285c4030d4bf7661981673038e6e9829.patch deleted file mode 100644 index 71ead1e..0000000 --- a/8694c547285c4030d4bf7661981673038e6e9829.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 8694c547285c4030d4bf7661981673038e6e9829 Mon Sep 17 00:00:00 2001 -From: sebres -Date: Tue, 14 Jan 2020 11:51:27 +0100 -Subject: [PATCH] increase test stack size to 128K (on some platforms min size - is greater then 32K), closes gh-2597 - ---- - fail2ban/tests/fail2banclienttestcase.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/fail2ban/tests/fail2banclienttestcase.py b/fail2ban/tests/fail2banclienttestcase.py -index 29adb1220..5caa4dd90 100644 ---- a/fail2ban/tests/fail2banclienttestcase.py -+++ b/fail2ban/tests/fail2banclienttestcase.py -@@ -469,14 +469,14 @@ def _testStartForeground(self, tmp, startparams, phase): - - @with_foreground_server_thread(startextra={'f2b_local':( - "[Thread]", -- "stacksize = 32" -+ "stacksize = 128" - "", - )}) - def testStartForeground(self, tmp, startparams): - # check thread options were set: - self.pruneLog() - self.execCmd(SUCCESS, startparams, "get", "thread") -- self.assertLogged("{'stacksize': 32}") -+ self.assertLogged("{'stacksize': 128}") - # several commands to server: - self.execCmd(SUCCESS, startparams, "ping") - self.execCmd(FAILED, startparams, "~~unknown~cmd~failed~~") diff --git a/8dc6f30cdd855c41b80ebdde3fe2bc91cc94e594.patch b/8dc6f30cdd855c41b80ebdde3fe2bc91cc94e594.patch deleted file mode 100644 index abc806c..0000000 --- a/8dc6f30cdd855c41b80ebdde3fe2bc91cc94e594.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 8dc6f30cdd855c41b80ebdde3fe2bc91cc94e594 Mon Sep 17 00:00:00 2001 -From: sebres -Date: Wed, 15 Jan 2020 19:22:53 +0100 -Subject: [PATCH] closes #2596: fixed supplying of backend-related `logtype` to - the jail filter - don't merge it (provide as init parameter if not set in - definition section), init parameters don't affect config-cache (better - implementation as in #2387 and it covered now with new test) - ---- - MANIFEST | 2 ++ - fail2ban/client/configreader.py | 8 +++-- - fail2ban/client/fail2banregex.py | 7 ++--- - fail2ban/client/filterreader.py | 8 +++++ - fail2ban/client/jailreader.py | 7 ++--- - fail2ban/tests/clientreadertestcase.py | 17 +++++++++- - .../tests/config/filter.d/checklogtype.conf | 31 +++++++++++++++++++ - .../config/filter.d/checklogtype_test.conf | 12 +++++++ - fail2ban/tests/config/jail.conf | 25 +++++++++++++++ - 9 files changed, 104 insertions(+), 13 deletions(-) - create mode 100644 fail2ban/tests/config/filter.d/checklogtype.conf - create mode 100644 fail2ban/tests/config/filter.d/checklogtype_test.conf - ---- a/MANIFEST -+++ b/MANIFEST -@@ -227,6 +227,8 @@ fail2ban/tests/clientreadertestcase.py - fail2ban/tests/config/action.d/action.conf - fail2ban/tests/config/action.d/brokenaction.conf - fail2ban/tests/config/fail2ban.conf -+fail2ban/tests/config/filter.d/checklogtype.conf -+fail2ban/tests/config/filter.d/checklogtype_test.conf - fail2ban/tests/config/filter.d/simple.conf - fail2ban/tests/config/filter.d/test.conf - fail2ban/tests/config/filter.d/test.local ---- a/fail2ban/client/configreader.py -+++ b/fail2ban/client/configreader.py -@@ -120,6 +120,10 @@ class ConfigReader(): - except AttributeError: - return False - -+ def has_option(self, sec, opt, withDefault=True): -+ return self._cfg.has_option(sec, opt) if withDefault \ -+ else opt in self._cfg._sections.get(sec, {}) -+ - def merge_defaults(self, d): - self._cfg.get_defaults().update(d) - -@@ -261,8 +265,8 @@ class ConfigReaderUnshared(SafeConfigPar - logSys.warning("'%s' not defined in '%s'. Using default one: %r" - % (optname, sec, optvalue)) - values[optname] = optvalue -- elif logSys.getEffectiveLevel() <= logLevel: -- logSys.log(logLevel, "Non essential option '%s' not defined in '%s'.", optname, sec) -+ # elif logSys.getEffectiveLevel() <= logLevel: -+ # logSys.log(logLevel, "Non essential option '%s' not defined in '%s'.", optname, sec) - except ValueError: - logSys.warning("Wrong value for '" + optname + "' in '" + sec + - "'. Using default one: '" + repr(optvalue) + "'") ---- a/fail2ban/client/fail2banregex.py -+++ b/fail2ban/client/fail2banregex.py -@@ -372,11 +372,8 @@ class Fail2banRegex(object): - if not ret: - output( "ERROR: failed to load filter %s" % value ) - return False -- # overwrite default logtype (considering that the filter could specify this too in Definition/Init sections): -- if not fltOpt.get('logtype'): -- reader.merge_defaults({ -- 'logtype': ['file','journal'][int(self._backend.startswith("systemd"))] -- }) -+ # set backend-related options (logtype): -+ reader.applyAutoOptions(self._backend) - # get, interpolate and convert options: - reader.getOptions(None) - # show real options if expected: ---- a/fail2ban/client/filterreader.py -+++ b/fail2ban/client/filterreader.py -@@ -53,6 +53,14 @@ class FilterReader(DefinitionInitConfigR - def getFile(self): - return self.__file - -+ def applyAutoOptions(self, backend): -+ # set init option to backend-related logtype, considering -+ # that the filter settings may be overwritten in its local: -+ if (not self._initOpts.get('logtype') and -+ not self.has_option('Definition', 'logtype', False) -+ ): -+ self._initOpts['logtype'] = ['file','journal'][int(backend.startswith("systemd"))] -+ - def convert(self): - stream = list() - opts = self.getCombined() ---- a/fail2ban/client/jailreader.py -+++ b/fail2ban/client/jailreader.py -@@ -149,11 +149,8 @@ class JailReader(ConfigReader): - ret = self.__filter.read() - if not ret: - raise JailDefError("Unable to read the filter %r" % filterName) -- if not filterOpt.get('logtype'): -- # overwrite default logtype backend-related (considering that the filter settings may be overwritten): -- self.__filter.merge_defaults({ -- 'logtype': ['file','journal'][int(self.__opts.get('backend', '').startswith("systemd"))] -- }) -+ # set backend-related options (logtype): -+ self.__filter.applyAutoOptions(self.__opts.get('backend', '')) - # merge options from filter as 'known/...' (all options unfiltered): - self.__filter.getOptions(self.__opts, all=True) - ConfigReader.merge_section(self, self.__name, self.__filter.getCombined(), 'known/') ---- a/fail2ban/tests/clientreadertestcase.py -+++ b/fail2ban/tests/clientreadertestcase.py -@@ -328,7 +328,22 @@ class JailReaderTest(LogCaptureTestCase) - self.assertFalse(len(o) > 2 and o[2].endswith('regex')) - i += 1 - if i > usednsidx: break -- -+ -+ def testLogTypeOfBackendInJail(self): -+ unittest.F2B.SkipIfCfgMissing(stock=True); # expected include of common.conf -+ # test twice to check cache works peoperly: -+ for i in (1, 2): -+ # backend-related, overwritten in definition, specified in init parameters: -+ for prefline in ('JRNL', 'FILE', 'TEST', 'INIT'): -+ jail = JailReader('checklogtype_'+prefline.lower(), basedir=IMPERFECT_CONFIG, -+ share_config=IMPERFECT_CONFIG_SHARE_CFG, force_enable=True) -+ self.assertTrue(jail.read()) -+ self.assertTrue(jail.getOptions()) -+ stream = jail.convert() -+ # 'JRNL' for systemd, 'FILE' for file backend, 'TEST' for custom logtype (overwrite it): -+ self.assertEqual([['set', jail.getName(), 'addfailregex', '^%s failure from $' % prefline]], -+ [o for o in stream if len(o) > 2 and o[2] == 'addfailregex']) -+ - def testSplitOption(self): - # Simple example - option = "mail-whois[name=SSH]" ---- /dev/null -+++ b/fail2ban/tests/config/filter.d/checklogtype.conf -@@ -0,0 +1,31 @@ -+# Fail2Ban configuration file -+# -+ -+[INCLUDES] -+ -+# Read common prefixes (logtype is set in default section) -+before = ../../../../config/filter.d/common.conf -+ -+[Definition] -+ -+_daemon = test -+ -+failregex = ^/__prefix_line> failure from $ -+ignoreregex = -+ -+# following sections define prefix line considering logtype: -+ -+# backend-related (retrieved from backend, overwrite default): -+[lt_file] -+__prefix_line = FILE -+ -+[lt_journal] -+__prefix_line = JRNL -+ -+# specified in definition section of filter (see filter checklogtype_test.conf): -+[lt_test] -+__prefix_line = TEST -+ -+# specified in init parameter of jail (see ../jail.conf, jail checklogtype_init): -+[lt_init] -+__prefix_line = INIT ---- /dev/null -+++ b/fail2ban/tests/config/filter.d/checklogtype_test.conf -@@ -0,0 +1,12 @@ -+# Fail2Ban configuration file -+# -+ -+[INCLUDES] -+ -+# Read common prefixes (logtype is set in default section) -+before = checklogtype.conf -+ -+[Definition] -+ -+# overwrite logtype in definition (no backend anymore): -+logtype = test -\ No newline at end of file ---- a/fail2ban/tests/config/jail.conf -+++ b/fail2ban/tests/config/jail.conf -@@ -74,3 +74,28 @@ journalmatch = _COMM=test - maxlines = 2 - usedns = no - enabled = false -+ -+[checklogtype_jrnl] -+filter = checklogtype -+backend = systemd -+action = action -+enabled = false -+ -+[checklogtype_file] -+filter = checklogtype -+backend = polling -+logpath = README.md -+action = action -+enabled = false -+ -+[checklogtype_test] -+filter = checklogtype_test -+backend = systemd -+action = action -+enabled = false -+ -+[checklogtype_init] -+filter = checklogtype_test[logtype=init] -+backend = systemd -+action = action -+enabled = false diff --git a/ab9d41e5309b417a3c7a84fa8f03cf4f93831f1b.patch b/ab9d41e5309b417a3c7a84fa8f03cf4f93831f1b.patch new file mode 100644 index 0000000..3dc9890 --- /dev/null +++ b/ab9d41e5309b417a3c7a84fa8f03cf4f93831f1b.patch @@ -0,0 +1,148 @@ +From ab9d41e5309b417a3c7a84fa8f03cf4f93831f1b Mon Sep 17 00:00:00 2001 +From: sebres +Date: Fri, 14 Jun 2024 14:31:21 +0200 +Subject: [PATCH] beautifier detect whether it can use unicode chars in stats + table; asciified output of beautifier in test suite; closes gh-3750 + +--- + fail2ban/client/beautifier.py | 51 ++++++++++++++-------- + fail2ban/tests/clientbeautifiertestcase.py | 22 ++++++---- + 2 files changed, 45 insertions(+), 28 deletions(-) + +diff --git a/fail2ban/client/beautifier.py b/fail2ban/client/beautifier.py +index 7ef173a655..21c49b9483 100644 +--- a/fail2ban/client/beautifier.py ++++ b/fail2ban/client/beautifier.py +@@ -21,8 +21,10 @@ + __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko" + __license__ = "GPL" + ++import sys ++ + from ..exceptions import UnknownJailException, DuplicateJailException +-from ..helpers import getLogger, logging ++from ..helpers import getLogger, logging, PREFER_ENC + + # Gets the instance of the logger. + logSys = getLogger(__name__) +@@ -36,6 +38,11 @@ + + class Beautifier: + ++ stdoutEnc = PREFER_ENC ++ if sys.stdout and sys.stdout.encoding is not None: ++ stdoutEnc = sys.stdout.encoding ++ encUtf = 1 if stdoutEnc.lower() == 'utf-8' else 0 ++ + def __init__(self, cmd = None): + self.__inputCmd = cmd + +@@ -104,7 +111,11 @@ def jail_stat(response, pref=""): + jail_stat(j, " " if i == len(jstat) else " | ") + msg = "\n".join(msg) + elif inC[0:1] == ['stats'] or inC[0:1] == ['statistics']: +- def _statstable(response): ++ chrTable = [ ++ ['|', '-', '|', 'x', 'x', '-', '|', '-'], ## ascii ++ ["\u2551", "\u2550", "\u255F", "\u256B", "\u256C", "\u2569", "\u2502", "\u2500"] ## utf-8 ++ ]; ++ def _statstable(response, ct): + tophead = ["Jail", "Backend", "Filter", "Actions"] + headers = ["", "", "cur", "tot", "cur", "tot"] + minlens = [8, 8, 3, 3, 3, 3] +@@ -120,29 +131,31 @@ def _statstable(response): + f = "%%%ds" if ralign[i] else "%%-%ds" + rfmt.append(f % lens[i]) + hfmt.append(f % lens[i]) +- rfmt = [rfmt[0], rfmt[1], "%s \u2502 %s" % (rfmt[2], rfmt[3]), "%s \u2502 %s" % (rfmt[4], rfmt[5])] +- hfmt = [hfmt[0], hfmt[1], "%s \u2502 %s" % (hfmt[2], hfmt[3]), "%s \u2502 %s" % (hfmt[4], hfmt[5])] ++ rfmt = [rfmt[0], rfmt[1], "%s %s %s" % (rfmt[2], ct[6], rfmt[3]), "%s %s %s" % (rfmt[4], ct[6], rfmt[5])] ++ hfmt = [hfmt[0], hfmt[1], "%s %s %s" % (hfmt[2], ct[6], hfmt[3]), "%s %s %s" % (hfmt[4], ct[6], hfmt[5])] + tlens = [lens[0], lens[1], 3 + lens[2] + lens[3], 3 + lens[4] + lens[5]] + tfmt = [hfmt[0], hfmt[1], "%%-%ds" % (tlens[2],), "%%-%ds" % (tlens[3],)] + tsep = tfmt[0:2] +- rfmt = " \u2551 ".join(rfmt) +- hfmt = " \u2551 ".join(hfmt) +- tfmt = " \u2551 ".join(tfmt) +- tsep = " \u2551 ".join(tsep) +- separator = ((tsep % tuple(tophead[0:2])) + " \u255F\u2500" + +- ("\u2500\u256B\u2500".join(['\u2500' * n for n in tlens[2:]])) + '\u2500') ++ rfmt = (" "+ct[0]+" ").join(rfmt) ++ hfmt = (" "+ct[0]+" ").join(hfmt) ++ tfmt = (" "+ct[0]+" ").join(tfmt) ++ tsep = (" "+ct[0]+" ").join(tsep) ++ separator = ((tsep % tuple(tophead[0:2])) + " "+ct[2]+ct[7] + ++ ((ct[7]+ct[3]+ct[7]).join([ct[7] * n for n in tlens[2:]])) + ct[7]) + ret = [] +- ret.append(tfmt % tuple(["", ""]+tophead[2:])) +- ret.append(separator) +- ret.append(hfmt % tuple(headers)) +- separator = "\u2550\u256C\u2550".join(['\u2550' * n for n in tlens]) + '\u2550' +- ret.append(separator) ++ ret.append(" "+tfmt % tuple(["", ""]+tophead[2:])) ++ ret.append(" "+separator) ++ ret.append(" "+hfmt % tuple(headers)) ++ separator = (ct[1]+ct[4]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1] ++ ret.append(ct[1]+separator) + for row in rows: +- ret.append(rfmt % tuple(row)) +- separator = "\u2550\u2569\u2550".join(['\u2550' * n for n in tlens]) + '\u2550' +- ret.append(separator) ++ ret.append(" "+rfmt % tuple(row)) ++ separator = (ct[1]+ct[5]+ct[1]).join([ct[1] * n for n in tlens]) + ct[1] ++ ret.append(ct[1]+separator) + return ret +- msg = "\n".join(_statstable(response)) ++ if not response: ++ return "No jails found." ++ msg = "\n".join(_statstable(response, chrTable[self.encUtf])) + elif len(inC) < 2: + pass # to few cmd args for below + elif inC[1] == "syslogsocket": +diff --git a/fail2ban/tests/clientbeautifiertestcase.py b/fail2ban/tests/clientbeautifiertestcase.py +index defedbe1bf..5fcb240479 100644 +--- a/fail2ban/tests/clientbeautifiertestcase.py ++++ b/fail2ban/tests/clientbeautifiertestcase.py +@@ -34,6 +34,7 @@ def setUp(self): + """ Call before every test case """ + super(BeautifierTest, self).setUp() + self.b = Beautifier() ++ self.b.encUtf = 0; ## we prefer ascii in test suite (see #3750) + + def tearDown(self): + """ Call after every test case """ +@@ -170,22 +171,25 @@ def testStatus(self): + + def testStatusStats(self): + self.b.setInputCmd(["stats"]) ++ ## no jails: ++ self.assertEqual(self.b.beautify({}), "No jails found.") ++ ## 3 jails: + response = { + "ssh": ["systemd", (3, 6), (12, 24)], + "exim4": ["pyinotify", (6, 12), (20, 20)], + "jail-with-long-name": ["polling", (0, 0), (0, 0)] + } + output = ("" +- + " ? ? Filter ? Actions \n" +- + "Jail ? Backend ????????????????????????\n" +- + " ? ? cur ? tot ? cur ? tot\n" +- + "????????????????????????????????????????????????????????\n" +- + "ssh ? systemd ? 3 ? 6 ? 12 ? 24\n" +- + "exim4 ? pyinotify ? 6 ? 12 ? 20 ? 20\n" +- + "jail-with-long-name ? polling ? 0 ? 0 ? 0 ? 0\n" +- + "????????????????????????????????????????????????????????" ++ + " | | Filter | Actions \n" ++ + " Jail | Backend |-----------x-----------\n" ++ + " | | cur | tot | cur | tot\n" ++ + "---------------------x-----------x-----------x-----------\n" ++ + " ssh | systemd | 3 | 6 | 12 | 24\n" ++ + " exim4 | pyinotify | 6 | 12 | 20 | 20\n" ++ + " jail-with-long-name | polling | 0 | 0 | 0 | 0\n" ++ + "---------------------------------------------------------" + ) +- response = self.b.beautify(response).encode('ascii', 'replace').decode('ascii') ++ response = self.b.beautify(response) + self.assertEqual(response, output) + + diff --git a/b158f83aa3795f387c8475ceb48df197a94a37e8.patch b/b158f83aa3795f387c8475ceb48df197a94a37e8.patch deleted file mode 100644 index f4a2416..0000000 --- a/b158f83aa3795f387c8475ceb48df197a94a37e8.patch +++ /dev/null @@ -1,22 +0,0 @@ -From b158f83aa3795f387c8475ceb48df197a94a37e8 Mon Sep 17 00:00:00 2001 -From: sebres -Date: Mon, 13 Jan 2020 12:37:19 +0100 -Subject: [PATCH] testIPAddr_CompareDNS: add missing network constraint - (gh-2596) - ---- - fail2ban/tests/filtertestcase.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/fail2ban/tests/filtertestcase.py b/fail2ban/tests/filtertestcase.py -index d6ad82358..6ca8162bd 100644 ---- a/fail2ban/tests/filtertestcase.py -+++ b/fail2ban/tests/filtertestcase.py -@@ -2064,6 +2064,7 @@ def testIPAddr_CIDR_Repr(self): - ) - - def testIPAddr_CompareDNS(self): -+ unittest.F2B.SkipIfNoNetwork() - ips = IPAddr('example.com') - self.assertTrue(IPAddr("93.184.216.34").isInNet(ips)) - self.assertTrue(IPAddr("2606:2800:220:1:248:1893:25c8:1946").isInNet(ips)) diff --git a/ec37b1942c4da76f7a0f71efe81bea6835466648.patch b/ec37b1942c4da76f7a0f71efe81bea6835466648.patch deleted file mode 100644 index 3878213..0000000 --- a/ec37b1942c4da76f7a0f71efe81bea6835466648.patch +++ /dev/null @@ -1,25 +0,0 @@ -From ec37b1942c4da76f7a0f71efe81bea6835466648 Mon Sep 17 00:00:00 2001 -From: sebres -Date: Tue, 14 Jan 2020 11:39:13 +0100 -Subject: [PATCH] action.d/nginx-block-map.conf: fixed backslash substitution - (different echo behavior in some shells, gh-2596) - ---- - config/action.d/nginx-block-map.conf | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/config/action.d/nginx-block-map.conf b/config/action.d/nginx-block-map.conf -index 0b6aa0ad7..ee702907e 100644 ---- a/config/action.d/nginx-block-map.conf -+++ b/config/action.d/nginx-block-map.conf -@@ -103,6 +103,8 @@ actionstop = %(actionflush)s - - actioncheck = - --actionban = echo "\\\\ 1;" >> '%(blck_lst_file)s'; %(blck_lst_reload)s -+_echo_blck_row = printf '\%%s 1;\n' "" - --actionunban = id=$(echo "" | sed -e 's/[]\/$*.^|[]/\\&/g'); sed -i "/^\\\\$id 1;$/d" %(blck_lst_file)s; %(blck_lst_reload)s -+actionban = %(_echo_blck_row)s >> '%(blck_lst_file)s'; %(blck_lst_reload)s -+ -+actionunban = id=$(%(_echo_blck_row)s | sed -e 's/[]\/$*.^|[]/\\&/g'); sed -i "/^$id$/d" %(blck_lst_file)s; %(blck_lst_reload)s diff --git a/fail2ban-1.1.0.tar.gz.asc b/fail2ban-1.1.0.tar.gz.asc new file mode 100644 index 0000000..f764f97 --- /dev/null +++ b/fail2ban-1.1.0.tar.gz.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- + +iQEzBAABCgAdFiEEhzhVnib2cd+eLG2eaDvxvr0KiCwFAmYqzEoACgkQaDvxvr0K +iCwMfQf9GcxsuVs/LiHeDYmmvFOxCmS2zO4K5pzDuX1JmtSzKCj9HbPSxUWbIZIc +yJv+x8t6QNBPBMnxI70TP+RcxKpCO4Fc2WRcrYS5B6gDTKy9Ty0fHorHlA4QQthu +ywoqxf1eddQKcwlk+lw/wI1QPwZ1xA93BkasJht/bTnhAvXJBeN1Tgf+jZ23bHHf +9FIGV8zt8fvaAIG8lB22AD/+PhSYEkp1TRuRx9VEuBbkH00u1i054I0cHTrsu3Fr +jTIljf5TgpmFyXHBCA6JT6nnGn0jsaNDT/lBNxUmw5BmMxGWUTv4SlKbcjKjgXRH +MTZipOHHYPx/7IyKJJvB1p1gvmOxyg== +=qvry +-----END PGP SIGNATURE----- diff --git a/fail2ban-nftables.patch b/fail2ban-nftables.patch new file mode 100644 index 0000000..1124e85 --- /dev/null +++ b/fail2ban-nftables.patch @@ -0,0 +1,62 @@ +Index: fail2ban-1.0.2/config/action.d/firewallcmd-rich-rules.conf +=================================================================== +--- fail2ban-1.0.2.orig/config/action.d/firewallcmd-rich-rules.conf ++++ fail2ban-1.0.2/config/action.d/firewallcmd-rich-rules.conf +@@ -37,8 +37,8 @@ actioncheck = + + fwcmd_rich_rule = rule family='' source address='' port port='$p' protocol='' %(rich-suffix)s + +-actionban = ports=""; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="%(fwcmd_rich_rule)s"; done ++actionban = ports=""; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --add-rich-rule="%(fwcmd_rich_rule)s"; done + +-actionunban = ports=""; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="%(fwcmd_rich_rule)s"; done ++actionunban = ports=""; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --remove-rich-rule="%(fwcmd_rich_rule)s"; done + +-rich-suffix = +\ No newline at end of file ++rich-suffix = +Index: fail2ban-1.0.2/fail2ban/tests/servertestcase.py +=================================================================== +--- fail2ban-1.0.2.orig/fail2ban/tests/servertestcase.py ++++ fail2ban-1.0.2/fail2ban/tests/servertestcase.py +@@ -2051,32 +2051,32 @@ class ServerConfigReaderTests(LogCapture + ('j-fwcmd-rr', 'firewallcmd-rich-rules[port="22:24", protocol="tcp"]', { + 'ip4': ("family='ipv4'", "icmp-port-unreachable",), 'ip6': ("family='ipv6'", 'icmp6-port-unreachable',), + 'ip4-ban': ( +- """`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' reject type='icmp-port-unreachable'"; done`""", ++ """`ports="22:24"; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' reject type='icmp-port-unreachable'"; done`""", + ), + 'ip4-unban': ( +- """`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' reject type='icmp-port-unreachable'"; done`""", ++ """`ports="22:24"; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' reject type='icmp-port-unreachable'"; done`""", + ), + 'ip6-ban': ( +- """ `ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' reject type='icmp6-port-unreachable'"; done`""", ++ """ `ports="22:24"; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --add-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' reject type='icmp6-port-unreachable'"; done`""", + ), + 'ip6-unban': ( +- """`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' reject type='icmp6-port-unreachable'"; done`""", ++ """`ports="22:24"; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --remove-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' reject type='icmp6-port-unreachable'"; done`""", + ), + }), + # firewallcmd-rich-logging -- + ('j-fwcmd-rl', 'firewallcmd-rich-logging[port="22:24", protocol="tcp"]', { + 'ip4': ("family='ipv4'", "icmp-port-unreachable",), 'ip6': ("family='ipv6'", 'icmp6-port-unreachable',), + 'ip4-ban': ( +- """`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp-port-unreachable'"; done`""", ++ """`ports="22:24"; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp-port-unreachable'"; done`""", + ), + 'ip4-unban': ( +- """`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp-port-unreachable'"; done`""", ++ """`ports="22:24"; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.0.2.1' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp-port-unreachable'"; done`""", + ), + 'ip6-ban': ( +- """ `ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --add-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp6-port-unreachable'"; done`""", ++ """ `ports="22:24"; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --add-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp6-port-unreachable'"; done`""", + ), + 'ip6-unban': ( +- """`ports="22:24"; for p in $(echo $ports | tr ", " " "); do firewall-cmd --remove-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp6-port-unreachable'"; done`""", ++ """`ports="22:24"; for p in $(echo $ports | tr ":, " "- "); do firewall-cmd --remove-rich-rule="rule family='ipv6' source address='2001:db8::' port port='$p' protocol='tcp' log prefix='f2b-j-fwcmd-rl' level='info' limit value='1/m' reject type='icmp6-port-unreachable'"; done`""", + ), + }), + ) diff --git a/fail2ban.fc b/fail2ban.fc index 4da938f..f481c4a 100644 --- a/fail2ban.fc +++ b/fail2ban.fc @@ -1,4 +1,4 @@ -/etc/rc\.d/init\.d/fail2ban -- gen_context(system_u:object_r:fail2ban_initrc_exec_t,s0) +#/etc/rc\.d/init\.d/fail2ban -- gen_context(system_u:object_r:fail2ban_initrc_exec_t,s0) /usr/bin/fail2ban -- gen_context(system_u:object_r:fail2ban_exec_t,s0) /usr/bin/fail2ban-client -- gen_context(system_u:object_r:fail2ban_client_exec_t,s0) @@ -6,4 +6,5 @@ /var/lib/fail2ban(/.*)? gen_context(system_u:object_r:fail2ban_var_lib_t,s0) /var/log/fail2ban\.log.* -- gen_context(system_u:object_r:fail2ban_log_t,s0) -/var/run/fail2ban.* gen_context(system_u:object_r:fail2ban_var_run_t,s0) + +/run/fail2ban(/.*)? gen_context(system_u:object_r:fail2ban_var_run_t,s0) diff --git a/fail2ban.if b/fail2ban.if index 94e1936..82c627f 100644 --- a/fail2ban.if +++ b/fail2ban.if @@ -243,7 +243,7 @@ interface(`fail2ban_read_pid_files',` ######################################## ## -## dontaudit read and write an leaked file descriptors +## dontaudit read and write leaked file descriptors ## ## ## @@ -264,7 +264,7 @@ interface(`fail2ban_dontaudit_leaks',` ######################################## ## ## All of the rules required to administrate -## an fail2ban environment +## a fail2ban environment ## ## ## diff --git a/.rpmlint b/fail2ban.rpmlintrc similarity index 100% rename from .rpmlint rename to fail2ban.rpmlintrc diff --git a/fail2ban.spec b/fail2ban.spec index b72b39b..6ca56b5 100644 --- a/fail2ban.spec +++ b/fail2ban.spec @@ -1,60 +1,91 @@ +%if 0%{?rhel} >= 9 +%bcond_with shorewall +%else +%bcond_without shorewall +%endif + +# RHEL < 10 and Fedora < 40 use file context entries in /var/run +%if %{defined rhel} && 0%{?rhel} < 10 +%define legacy_var_run 1 +%endif + Name: fail2ban -Version: 0.11.1 -Release: 10%{?dist} +Version: 1.1.0 +Release: 15%{?dist} Summary: Daemon to ban hosts that cause multiple authentication errors -License: GPLv2+ -URL: http://fail2ban.sourceforge.net/ +License: GPL-2.0-or-later +URL: https://www.fail2ban.org Source0: https://github.com/%{name}/%{name}/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz +Source1: https://github.com/%{name}/%{name}/releases/download/%{version}/%{name}-%{version}.tar.gz.asc +# Releases are signed by Serg G. Brester (sebres) . The +# fingerprint can be found in a signature file: +# gpg --list-packets fail2ban-1.0.2.tar.gz.asc | grep 'issuer fpr' +# +# The following commands can be used to fetch the signing key via fingerprint +# and extract it: +# fpr=8738559E26F671DF9E2C6D9E683BF1BEBD0A882C +# gpg --receive-keys $fpr +# gpg -a --export-options export-minimal --export $fpr >gpgkey-$fpr.asc +Source2: gpgkey-8738559E26F671DF9E2C6D9E683BF1BEBD0A882C.asc # SELinux policy -Source1: fail2ban.fc -Source2: fail2ban.if -Source3: fail2ban.te -Source4: Makefile +Source3: fail2ban.fc +Source4: fail2ban.if +Source5: fail2ban.te +Source6: Makefile + # Give up being PartOf iptables and ipset for now # https://bugzilla.redhat.com/show_bug.cgi?id=1379141 # https://bugzilla.redhat.com/show_bug.cgi?id=1573185 Patch0: fail2ban-partof.patch -# Fix nginx-block-map -Patch1: https://github.com/fail2ban/fail2ban/commit/ec37b1942c4da76f7a0f71efe81bea6835466648.patch -# testIPAddr_CompareDNS: add missing network constraint -Patch2: https://github.com/fail2ban/fail2ban/commit/b158f83aa3795f387c8475ceb48df197a94a37e8.patch -# Fix test thread stack size on aarch64 -Patch3: https://github.com/fail2ban/fail2ban/commit/8694c547285c4030d4bf7661981673038e6e9829.patch -# Fix handling of journal in tests -Patch4: https://github.com/fail2ban/fail2ban/commit/8dc6f30cdd855c41b80ebdde3fe2bc91cc94e594.patch -# Fix test install -Patch5: https://patch-diff.githubusercontent.com/raw/fail2ban/fail2ban/pull/2605.patch -# Patch for Python 3.9 -# https://bugzilla.redhat.com/show_bug.cgi?id=1808347 -Patch6: https://patch-diff.githubusercontent.com/raw/fail2ban/fail2ban/pull/2651.patch -Patch7: https://github.com/fail2ban/fail2ban/commit/343ec1cdd296530f331637c725bd2bb0549e01e6.patch -# In Fedora 32 and EL 8 nftables is the default firewall and does not accept ":" for port ranges. +# default port in jail.conf is not compatible with firewalld-cmd syntax # https://bugzilla.redhat.com/show_bug.cgi?id=1850164 -Patch8: https://github.com/fail2ban/fail2ban/commit/309c8dddd7adc2de140ed5a72088cd4f2dcc9b91.patch +Patch1: fail2ban-nftables.patch +# Work around encoding issues during tests +Patch2: https://github.com/fail2ban/fail2ban/commit/ab9d41e5309b417a3c7a84fa8f03cf4f93831f1b.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2315252 +Patch3: https://patch-diff.githubusercontent.com/raw/fail2ban/fail2ban/pull/3782.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2295265 +Patch4: https://patch-diff.githubusercontent.com/raw/fail2ban/fail2ban/pull/3728.patch +# Upstream fix to also catch sshd-session logs +# https://bugzilla.redhat.com/show_bug.cgi?id=2332945 +Patch5: https://github.com/fail2ban/fail2ban/commit/54c0effceb998b73545073ac59c479d9d9bf19a4.patch +# Needed for Dovecot change to loging format in 2.4, fixed in f2b version 1.1.1. +# https://bugzilla.redhat.com/show_bug.cgi?id=2426440 +Patch6: https://github.com/fail2ban/fail2ban/commit/04ff4c060cdc233af9a6deeb85a6523da0416f31.patch + BuildArch: noarch -%if 0%{?rhel} && 0%{?rhel} < 8 -BuildRequires: python-devel -# For testcases -BuildRequires: python-inotify -%else BuildRequires: python3-devel -BuildRequires: /usr/bin/2to3 +BuildRequires: python3-setuptools # For testcases BuildRequires: python3-inotify +# using a python3_version-based conditional does not work here, so +# this is a proxy for "Python version greater than 3.12". asyncore +# and asynchat were dropped from cpython core in 3.12, these modules +# make them available again. See: +# https://github.com/fail2ban/fail2ban/issues/3487 +# https://bugzilla.redhat.com/show_bug.cgi?id=2219991 +%if 0%{?fedora} || 0%{?rhel} >= 10 +BuildRequires: python3-pyasyncore +BuildRequires: python3-pyasynchat %endif BuildRequires: sqlite BuildRequires: systemd BuildRequires: selinux-policy-devel +BuildRequires: make +%if 0%{?fedora} || 0%{?rhel} >= 11 +BuildRequires: bash-completion-devel +%else +BuildRequires: bash-completion +%endif +BuildRequires: gnupg2 # Default components Requires: %{name}-firewalld = %{version}-%{release} Requires: %{name}-sendmail = %{version}-%{release} Requires: %{name}-server = %{version}-%{release} -# Currently this breaks jails that don't log to the journal -#Requires: %{name}-systemd = %{version}-%{release} %description @@ -85,19 +116,16 @@ SELinux policies for Fail2Ban. %package server Summary: Core server component for Fail2Ban -%if 0%{?rhel} && 0%{?rhel} < 8 -Requires: systemd-python -%else Requires: python3-systemd -%endif +Requires: nftables Requires(post): systemd Requires(preun): systemd Requires(postun): systemd -Requires: ipset -Requires: iptables - -%if 0%{?fedora} Requires: (%{name}-selinux if selinux-policy-%{selinuxtype}) +# see note above in BuildRequires section +%if 0%{?fedora} || 0%{?rhel} >= 10 +Requires: python3-pyasyncore +Requires: python3-pyasynchat %endif %description server @@ -113,17 +141,11 @@ Requires: %{name}-hostsdeny = %{version}-%{release} Requires: %{name}-mail = %{version}-%{release} Requires: %{name}-sendmail = %{version}-%{release} Requires: %{name}-server = %{version}-%{release} +%if %{with shorewall} Requires: %{name}-shorewall = %{version}-%{release} -# Currently this breaks jails that don't log to the journal -#Requires: %{name}-systemd = %{version}-%{release} -Requires: perl-interpreter -%if 0%{?rhel} && 0%{?rhel} < 8 -Requires: python-inotify -# No python3 support for gamin so epel only -Requires: gamin-python -%else -Requires: python3-inotify %endif +Requires: perl-interpreter +Requires: python3-inotify Requires: /usr/bin/whois %description all @@ -162,7 +184,7 @@ This package contains Fail2Ban's testscases and scripts. %package mail Summary: Mail actions for Fail2Ban Requires: %{name}-server = %{version}-%{release} -Requires: mailx +Requires: /usr/bin/mail %description mail This package installs Fail2Ban's mail actions. These are an alternative @@ -179,6 +201,7 @@ This package installs Fail2Ban's sendmail actions. This is the default mail actions for Fail2Ban. +%if %{with shorewall} %package shorewall Summary: Shorewall support for Fail2Ban Requires: %{name}-server = %{version}-%{release} @@ -197,6 +220,7 @@ Conflicts: %{name}-shorewall %description shorewall-lite This package enables support for manipulating shorewall rules. +%endif %package systemd @@ -209,39 +233,44 @@ by default. %prep +%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' %autosetup -p1 # Use Fedora paths sed -i -e 's/^before = paths-.*/before = paths-fedora.conf/' config/jail.conf -%if 0%{?fedora} || 0%{?rhel} >= 8 -2to3 --write --nobackups . -find -type f -exec sed -i -e '1s,^#!/usr/bin/python *,#!/usr/bin/python%{python3_version},' {} + -%endif # SELinux sources -cp -p %SOURCE1 %SOURCE2 %SOURCE3 . +cp -p %SOURCE3 %SOURCE4 %SOURCE5 . + +%if %{defined legacy_var_run} +sed -i 's|^/run/|/var/run/|' %{name}.fc +%endif + +# 2to3 has been removed from setuptools and we already use the binary in +# %%prep. +sed -i "/use_2to3/d" setup.py + + +%generate_buildrequires +%pyproject_buildrequires %build -%if 0%{?rhel} && 0%{?rhel} < 8 -%py2_build -%else -%py3_build -%endif -make -f %SOURCE4 +%pyproject_wheel +make -f %SOURCE6 + %install -%if 0%{?rhel} && 0%{?rhel} < 8 -%py2_install -# Make symbolic link relative -ln -fs python2 %{buildroot}%{_bindir}/fail2ban-python -%else -%py3_install +%pyproject_install ln -fs python3 %{buildroot}%{_bindir}/fail2ban-python -%endif +mv %{buildroot}%{python3_sitelib}/etc %{buildroot} +mv %{buildroot}%{python3_sitelib}/%{_datadir} %{buildroot}%{_datadir} +rmdir %{buildroot}%{python3_sitelib}%{_prefix} mkdir -p %{buildroot}%{_unitdir} -cp -p build/fail2ban.service %{buildroot}%{_unitdir}/ +# Note that the tests rewrite build/fail2ban.service, but it uses build/ paths before the rewrite +# so we will do our own modification +sed -e 's,@BINDIR@,%{_bindir},' files/fail2ban.service.in > %{buildroot}%{_unitdir}/fail2ban.service mkdir -p %{buildroot}%{_mandir}/man{1,5} install -p -m 644 man/*.1 %{buildroot}%{_mandir}/man1 install -p -m 644 man/*.5 %{buildroot}%{_mandir}/man5 @@ -252,6 +281,7 @@ install -m 0600 /dev/null %{buildroot}/run/fail2ban/fail2ban.pid install -d -m 0755 %{buildroot}%{_localstatedir}/lib/fail2ban/ mkdir -p %{buildroot}%{_tmpfilesdir} install -p -m 0644 files/fail2ban-tmpfiles.conf %{buildroot}%{_tmpfilesdir}/fail2ban.conf +mkdir -p %{buildroot}%{_sysconfdir}/%{name}/jail.d # Remove non-Linux actions rm %{buildroot}%{_sysconfdir}/%{name}/action.d/*ipfw.conf @@ -267,8 +297,8 @@ cat > %{buildroot}%{_sysconfdir}/%{name}/jail.d/00-firewalld.conf <] -banaction_allports = firewallcmd-rich-rules[actiontype=] +banaction = firewallcmd-rich-rules +banaction_allports = firewallcmd-rich-rules EOF # systemd journal configuration @@ -289,13 +319,14 @@ rm -r %{buildroot}%{_docdir}/%{name} install -d %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype} install -m 0644 %{modulename}.pp.bz2 %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype} +#BASH completion +COMPLETIONDIR=%{buildroot}$(pkg-config --variable=completionsdir bash-completion) +%__mkdir_p $COMPLETIONDIR +%__install -p -m 644 files/bash-completion $COMPLETIONDIR/fail2ban + %check -%if 0%{?rhel} && 0%{?rhel} < 8 -%python2 bin/fail2ban-testcases --verbosity=2 --no-network -%else %python3 bin/fail2ban-testcases --verbosity=2 --no-network -%endif %pre selinux @@ -312,7 +343,6 @@ fi %posttrans selinux %selinux_relabel_post -s %{selinuxtype} - %post server %systemd_post fail2ban.service @@ -336,21 +366,17 @@ fi %{_bindir}/fail2ban-python %{_bindir}/fail2ban-regex %{_bindir}/fail2ban-server -%if 0%{?rhel} && 0%{?rhel} < 8 -%{python2_sitelib}/* -%exclude %{python2_sitelib}/fail2ban/tests -%else %{python3_sitelib}/* %exclude %{python3_sitelib}/fail2ban/tests -%endif %{_unitdir}/fail2ban.service +%{_datadir}/bash-completion/ %{_mandir}/man1/fail2ban.1* %{_mandir}/man1/fail2ban-client.1* %{_mandir}/man1/fail2ban-python.1* %{_mandir}/man1/fail2ban-regex.1* %{_mandir}/man1/fail2ban-server.1* %{_mandir}/man5/*.5* -%config(noreplace) %{_sysconfdir}/fail2ban +%config(noreplace) %{_sysconfdir}/fail2ban/ %exclude %{_sysconfdir}/fail2ban/action.d/complain.conf %exclude %{_sysconfdir}/fail2ban/action.d/hostsdeny.conf %exclude %{_sysconfdir}/fail2ban/action.d/mail.conf @@ -377,11 +403,7 @@ fi %files tests %{_bindir}/fail2ban-testcases %{_mandir}/man1/fail2ban-testcases.1* -%if 0%{?rhel} && 0%{?rhel} < 8 -%{python2_sitelib}/fail2ban/tests -%else %{python3_sitelib}/fail2ban/tests -%endif %files mail %config(noreplace) %{_sysconfdir}/fail2ban/action.d/complain.conf @@ -393,17 +415,167 @@ fi %files sendmail %config(noreplace) %{_sysconfdir}/fail2ban/action.d/sendmail-*.conf +%if %{with shorewall} %files shorewall %config(noreplace) %{_sysconfdir}/fail2ban/action.d/shorewall.conf %files shorewall-lite %config(noreplace) %{_sysconfdir}/fail2ban/action.d/shorewall.conf +%endif %files systemd %config(noreplace) %{_sysconfdir}/fail2ban/jail.d/00-systemd.conf %changelog +* Wed Dec 31 2025 Richard Shaw - 1.1.0-15 +- Add patch for Dovecot 2.4 jail. Fixes BZ#2426440. + +* Sat Oct 11 2025 Orion Poplawski - 1.1.0-14 +- Cleanup old conditionals + +* Fri Oct 10 2025 Orion Poplawski - 1.1.0-13 +- Fix paths in fail2ban.service (rhbz#2399981) + +* Fri Sep 19 2025 Python Maint - 1.1.0-12 +- Rebuilt for Python 3.14.0rc3 bytecode + +* Thu Aug 21 2025 Richard Shaw - 1.1.0-11 +- Move from setup.py to wheels per + https://fedoraproject.org/wiki/Changes/DeprecateSetuppyMacros. + +* Fri Aug 15 2025 Python Maint - 1.1.0-10 +- Rebuilt for Python 3.14.0rc2 bytecode + +* Wed Jul 23 2025 Fedora Release Engineering - 1.1.0-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + +* Tue Jun 03 2025 Python Maint - 1.1.0-8 +- Rebuilt for Python 3.14 + +* Thu Jan 16 2025 Fedora Release Engineering - 1.1.0-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + +* Thu Dec 19 2024 Orion Poplawski - 1.1.0-6 +- Add upstream fix for sshd filter (rhbz#2332945) + +* Wed Oct 16 2024 Richard Shaw - 1.1.0-5 +- Add upstream patch for python distutils removal. + +* Sat Sep 28 2024 Richard Shaw - 1.1.0-4 +- Add patch to deal with changes to OpenSSL log output. + +* Wed Jul 17 2024 Fedora Release Engineering - 1.1.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + +* Fri Jul 12 2024 Nils Philippsen - 1.1.0-2 +- Use SPDX license identifier +- Use https upstream URL + +* Wed Jun 12 2024 Richard Shaw - 1.1.0-1 +- Update to 1.1.0 for Python 3.13 support. + +* Fri Jun 07 2024 Python Maint - 1.0.2-16 +- Rebuilt for Python 3.13 + +* Sat May 11 2024 Todd Zullinger - 1.0.2-15 +- Handle /var/run->/run transition in older Fedora and EPEL (RHBZ#2279054) + +* Sun May 05 2024 Richard Shaw - 1.0.2-14 +- Increment SELinux module version. +- Tweak selinux regex for /run/fail2ban. + +* Thu Apr 25 2024 Richard Shaw - 1.0.2-13 +- Add nftables patch and fix selinux /var/run->/run issue, fixes RHBZ#1850164 + and RHBZ#2272476. + +* Thu Feb 22 2024 Orion Poplawski - 1.0.2-12 +- Allow watch on more logfiles + +* Wed Jan 24 2024 Fedora Release Engineering - 1.0.2-11 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Jan 19 2024 Fedora Release Engineering - 1.0.2-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Wed Sep 27 2023 Adam Williamson - 1.0.2-9 +- Require pyasynchat and pyasyncore with Python 3.12+ +- Disable smtp tests on F39+ due to removal of smtpd from Python 3.12 +- Disable db repair test on F39+ as it's broken with sqlite 3.42.0+ + +* Wed Jul 19 2023 Fedora Release Engineering - 1.0.2-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Mon Jun 26 2023 Todd Zullinger - 1.0.2-7 +- exclude shorewall subpackage on epel9 (rhbz#2217649) + +* Wed Jun 14 2023 Python Maint - 1.0.2-6 +- Rebuilt for Python 3.12 + +* Tue Apr 04 2023 Orion Poplawski - 1.0.2-5 +- Drop downstream python3.11 patch, upstream went with a different fix + +* Sun Apr 02 2023 Todd Zullinger - 1.0.2-4 +- verify upstream source signature + +* Thu Mar 30 2023 Orion Poplawski - 1.0.2-3 +- Add upstream patch to remove warning about allowipv6 (bz#2160781) + +* Thu Jan 19 2023 Fedora Release Engineering - 1.0.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Sat Dec 17 2022 Richard Shaw - 1.0.2-1 +- Update to 1.0.2. + +* Wed Nov 02 2022 Richard Shaw - 1.0.1-2 +- Add patch for dovecot eating 100% CPU. + +* Sun Oct 02 2022 Richard Shaw - 1.0.1-1 +- Update to 1.0.1. + +* Thu Jul 21 2022 Fedora Release Engineering - 0.11.2-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Wed Jun 15 2022 Python Maint - 0.11.2-13 +- Rebuilt for Python 3.11 + +* Wed May 18 2022 Orion Poplawski - 0.11.2-12 +- Fix SELinux policy to allow watch on var_log_t (bz#2083923) + +* Fri Jan 28 2022 Orion Poplawski - 0.11.2-11 +- Require /usr/bin/mail instead of mailx + +* Thu Jan 20 2022 Fedora Release Engineering - 0.11.2-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Sun Sep 26 2021 Mikel Olasagasti Uranga - 0.11.2-9 +- Fix CVE-2021-32749 RHBZ#1983223 + +* Wed Jul 21 2021 Fedora Release Engineering - 0.11.2-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Mon Jun 07 2021 Python Maint - 0.11.2-7 +- Rebuilt for Python 3.10 + +* Sun Jun 06 2021 Richard Shaw - 0.11.2-6 +- Update selinux policy for Fedora 34+ + +* Fri Jun 04 2021 Python Maint - 0.11.2-5 +- Rebuilt for Python 3.10 + +* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 0.11.2-4 +- Rebuilt for updated systemd-rpm-macros + See https://pagure.io/fesco/issue/2583. + +* Tue Jan 26 2021 Fedora Release Engineering - 0.11.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Jan 06 2021 Richard Shaw - 0.11.2-2 +- Add patch to deal with a new century in tests (2021). + +* Tue Nov 24 2020 Richard Shaw - 0.11.2-1 +- Update to 0.11.2. + * Fri Aug 28 2020 Richard Shaw - 0.11.1-10.2 - Create shorewall-lite subpackage package which conflicts with shorewall subpackage. Fixes RHBZ#1872759. diff --git a/fail2ban.te b/fail2ban.te index 302f4bc..5bc2394 100644 --- a/fail2ban.te +++ b/fail2ban.te @@ -1,4 +1,4 @@ -policy_module(fail2ban, 1.5.0) +policy_module(fail2ban, 1.5.1) ######################################## # @@ -88,7 +88,6 @@ files_read_etc_runtime_files(fail2ban_t) files_list_var(fail2ban_t) files_dontaudit_list_tmp(fail2ban_t) -fs_list_inotifyfs(fail2ban_t) fs_getattr_all_fs(fail2ban_t) auth_use_nsswitch(fail2ban_t) @@ -100,6 +99,13 @@ logging_read_syslog_pid(fail2ban_t) logging_dontaudit_search_audit_logs(fail2ban_t) logging_mmap_generic_logs(fail2ban_t) logging_mmap_journal(fail2ban_t) +# Not in EL9 yet +#logging_watch_audit_log_files(fail2ban_t) +logging_watch_all_log_files(fail2ban_t) +logging_watch_all_log_dirs(fail2ban_t) +logging_watch_audit_log_files(fail2ban_t) +logging_watch_audit_log_dirs(fail2ban_t) +logging_watch_journal_dir(fail2ban_t) mta_send_mail(fail2ban_t) diff --git a/gpgkey-8738559E26F671DF9E2C6D9E683BF1BEBD0A882C.asc b/gpgkey-8738559E26F671DF9E2C6D9E683BF1BEBD0A882C.asc new file mode 100644 index 0000000..14da565 --- /dev/null +++ b/gpgkey-8738559E26F671DF9E2C6D9E683BF1BEBD0A882C.asc @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFeHbzIBCACWgr54J4t2fpI7EIrMTqso5kqPRTSY7eO2T0965JW6Zl4C0HZT +Wz+9c5aGlKeotf4Fv7zOhpUwULFSGAq3tVbxAxW9++LAXPGad6uE4aPsXoQ6+0RV +lJozNclURRal46vz3uuGLiSJ5+VQ1WD1sFLuw2/bMzE4GFR0z4w4UOc3ufAQ3obC +i5szSy5JWtCsmvCdNlhXTxa66aUddN8/8IHJSB6QZabGEcG4WfsfhUiH38KUuqrO +hYvT9ROY74pwSsHuWEzVRE00eJB4uxngsKHAGMYhkNxdKCG7Blu2IbJRcBE8QAs3 +BGqJR8FBify86COZYUZ7CuAyLyo1U6BZd7ohABEBAAG0KVNlcmcgRy4gQnJlc3Rl +ciAoc2VicmVzKSA8aW5mb0BzZWJyZXMuZGU+iQE4BBMBAgAiBQJXh28yAhsDBgsJ +CAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBoO/G+vQqILMThB/0YUr7Y+urJChgm +NG9exjjmTayoNb+XiMR5T2+A919NrKulEaH2mb51B7XBmFuCj8x5O1wA3xYo7B6h +RVuNyb2eI3+bRD33QsKcs6NsgK/I1xLD15NrEftPckWqYypR6//u9Tmz5o9n9+/n +2dH7SU7UPW468/bRUhFp+SQ70B0XLdyDgGLEN9TNsAvnEi30Vtjbia4Lp/NXYRkq +GEzvpgZ7Dt9YhT+qdSs6AwyN0ZhnvX+zqXi+Q18xlbnuq2ZZkwK8Es/HdEDu2HNJ +3nn3l15pyMe/OxYhg646NcqGR6j1rEZ7jXyN2i5sEdspXfwv0lGtLr7ANElWqOvX +XYBAspRvuQENBFeHbzIBCACyCMv4CQ+blzj53ZLPyBMnj38oQ7bbpAtDThfB8hEZ +uk6Kmo799Zo2rLG2iqvy8SEuN/bLQKyzFTiB4UYWvRxne792N0nWLU24/bd7j/Gh +Q4EHUhs38WRSYtu93XCKzvyzn5s3504luOBF6czNrLeDfWXGVGosBsBoASY7de7a +kiXb7a28dNDSG0JaR+QwONjmde9hAzqOX0iOYHvJeu68UKaUp4IrJ+nTMHFhwUbf +awCmz+NPPrm360j4BuvYSWhS06tM7c6+gfvXHOTtJ5TEGbrm+I8d2q7nhxg3nku6 +7qnddkW2OS8EQVlw7XFox929mTLzw0MEmjqmSRTx2Qk3ABEBAAGJAR8EGAECAAkF +AleHbzICGwwACgkQaDvxvr0KiCwdxQf7BM7jo6v7uU7324ZkLQmtZndcXnXZMbSw +2pDzR2h01Vx7dHppzNOkyv8DvUWttwaMaTU57cdzThTkQPk8Lx8sCvi40RmWS2vs +IArgTS1HNStprPUg4sk99JOZg2y4LBqkLUxZveDsH+rXdFA/fp8048/M4ss6qj4O +ySe4crABbbv5yRADBJZt4LQdFoNGEpSaOtcxJmwJ7hrV+wQhVMm9m+/JpgzNT4rb +muPgveqzmSiTGJ6Yy2bEKyY0dCyPuWbWWPt4mCcT+9emZC1O8EjST0i9f9EUUU6c +6UCy7zi5EQ9CVv1Dlz1qefm/5/iFAAFQ5DtYC3cwDq8CqgqzoHMtNg== +=vqSW +-----END PGP PUBLIC KEY BLOCK----- diff --git a/sources b/sources index 585083b..934b139 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (fail2ban-0.11.1.tar.gz) = 019b088aa6375f98742ed101ef6f65adabca3324444d71d5b8597a8d1d22fa76b9f503660f0498643fe24a3b8e4368de916072a1ab77b8e2ea3eda41c3e0c8c6 +SHA512 (fail2ban-1.1.0.tar.gz) = 9bff7b9c41e58a953901800468e5c4153c9db6af01c7eb18111ad8620b40d03a0771020472fb759b2809d250e2bb45471e6c7e8283e72ea48290ecf7bf921821