mirror of https://github.com/fail2ban/fail2ban
Merge branch '0.11'
commit
13520a0494
|
@ -11,7 +11,7 @@ before = common.conf
|
|||
|
||||
_daemon = (?:courier)?(?:imapd?|pop3d?)(?:login)?(?:-ssl)?
|
||||
|
||||
failregex = ^%(__prefix_line)sLOGIN FAILED, (?:user|method)=.*, ip=\[<HOST>\]$
|
||||
failregex = ^%(__prefix_line)sLOGIN FAILED, (?:(?!ip=)(?:user=<F-USER>[^,]*</F-USER>|\w+=[^,]*), )*ip=\[<HOST>\]
|
||||
|
||||
ignoreregex =
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ before = common.conf
|
|||
[Definition]
|
||||
|
||||
_auth_worker = (?:dovecot: )?auth(?:-worker)?
|
||||
_auth_worker_info = (?:conn \w+:auth(?:-worker)? \(uid=\w+\): auth(?:-worker)?<\d+>: )?
|
||||
_auth_worker_info = (?:conn \w+:auth(?:-worker)? \([^\)]+\): auth(?:-worker)?<\d+>: )?
|
||||
_daemon = (?:dovecot(?:-auth)?|auth)
|
||||
|
||||
prefregex = ^%(__prefix_line)s(?:%(_auth_worker)s(?:\([^\)]+\))?: )?(?:%(__pam_auth)s(?:\(dovecot:auth\))?: |(?:pop3|imap|managesieve|submission)-login: )?(?:Info: )?%(_auth_worker_info)s<F-CONTENT>.+</F-CONTENT>$
|
||||
|
|
|
@ -547,9 +547,10 @@ class Actions(JailThread, Mapping):
|
|||
if bTicket.banEpoch == self.banEpoch and diftm > 3:
|
||||
# avoid too often checks:
|
||||
if not rebanacts and MyTime.time() > self.__lastConsistencyCheckTM + 3:
|
||||
for action in self._actions.itervalues():
|
||||
action.consistencyCheck()
|
||||
self.__lastConsistencyCheckTM = MyTime.time()
|
||||
for action in self._actions.itervalues():
|
||||
if hasattr(action, 'consistencyCheck'):
|
||||
action.consistencyCheck()
|
||||
# check epoch in order to reban it:
|
||||
if bTicket.banEpoch < self.banEpoch:
|
||||
if not rebanacts: rebanacts = dict(
|
||||
|
|
|
@ -22,7 +22,6 @@ __author__ = "Steven Hiscocks"
|
|||
__copyright__ = "Copyright (c) 2013 Steven Hiscocks"
|
||||
__license__ = "GPL"
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import time
|
||||
from distutils.version import LooseVersion
|
||||
|
@ -254,8 +253,8 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
|
|||
return ((logline[:0], date[0], logline.replace('\n', '\\n')), date[1])
|
||||
|
||||
def seekToTime(self, date):
|
||||
if not isinstance(date, datetime.datetime):
|
||||
date = datetime.datetime.fromtimestamp(date)
|
||||
if isinstance(date, (int, long)):
|
||||
date = float(date)
|
||||
self.__journal.seek_realtime(date)
|
||||
|
||||
def inOperationMode(self):
|
||||
|
@ -281,7 +280,8 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
|
|||
try:
|
||||
self.__journal.seek_tail()
|
||||
logentry = self.__journal.get_previous()
|
||||
self.__journal.get_next()
|
||||
if logentry:
|
||||
self.__journal.get_next()
|
||||
except OSError:
|
||||
logentry = None # Reading failure, so safe to ignore
|
||||
if logentry:
|
||||
|
@ -296,12 +296,6 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
|
|||
self.inOperation = False
|
||||
# Save current time in order to check time to switch "in operation" mode
|
||||
startTime = (1, MyTime.time(), logentry.get('__CURSOR'))
|
||||
# Move back one entry to ensure do not end up in dead space
|
||||
# if start time beyond end of journal
|
||||
try:
|
||||
self.__journal.get_previous()
|
||||
except OSError:
|
||||
pass # Reading failure, so safe to ignore
|
||||
else:
|
||||
# empty journal or no entries for current filter:
|
||||
self.inOperationMode()
|
||||
|
@ -311,6 +305,13 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
|
|||
# for possible future switches of in-operation mode:
|
||||
startTime = (0, startTime)
|
||||
|
||||
# Move back one entry to ensure do not end up in dead space
|
||||
# if start time beyond end of journal
|
||||
try:
|
||||
self.__journal.get_previous()
|
||||
except OSError:
|
||||
pass # Reading failure, so safe to ignore
|
||||
|
||||
line = None
|
||||
while self.active:
|
||||
# wait for records (or for timeout in sleeptime seconds):
|
||||
|
|
|
@ -8,3 +8,5 @@ Nov 13 08:11:53 server imapd-ssl: LOGIN FAILED, user=user@domain.tld, ip=[::ffff
|
|||
Apr 17 19:17:11 SERVER courierpop3login: LOGIN FAILED, user=USER@EXAMPLE.org, ip=[::ffff:1.2.3.4]
|
||||
# failJSON: { "time": "2005-04-17T19:17:12", "match": true , "host": "192.0.2.4" }
|
||||
Apr 17 19:17:12 server imapd-ssl: LOGIN FAILED, method=PLAIN, ip=[::ffff:192.0.2.4]
|
||||
# failJSON: { "time": "2005-04-27T09:00:00", "match": true , "user": "tester", "host": "192.0.2.5" }
|
||||
Apr 27 09:00:00 servername imapd: LOGIN FAILED, user=tester, ip=[::ffff:192.0.2.5], port=[255]
|
||||
|
|
|
@ -60,6 +60,11 @@ Jun 12 11:48:12 auth-worker(80180): Info: conn unix:auth-worker (uid=143): auth-
|
|||
# failJSON: { "time": "2005-06-12T23:06:05", "match": true , "host": "192.0.2.7" }
|
||||
Jun 12 23:06:05 auth-worker(57065): Info: conn unix:auth-worker (uid=143): auth-worker<225622>: sql(user@domain.com,192.0.2.7,<Yx7+W8+Io>): Password mismatch
|
||||
|
||||
# failJSON: { "time": "2005-06-15T11:28:21", "match": true , "host": "192.0.2.7" }
|
||||
Jun 15 11:28:21 hostname dovecot: auth-worker(5787): conn unix:auth-worker (pid=27359,uid=97): auth-worker<55>: pam(webapps,192.0.2.7): unknown user
|
||||
# failJSON: { "time": "2005-06-15T13:57:41", "match": true , "host": "192.0.2.7" }
|
||||
Jun 15 13:57:41 hostname dovecot: auth-worker(3270): conn unix:auth-worker (pid=27359,uid=97): auth-worker<128>: pam(webapps,192.0.2.7): pam_authenticate() failed: Authentication failure (Password mismatch?)
|
||||
|
||||
# failJSON: { "time": "2005-01-29T14:38:51", "match": true , "host": "192.0.2.6", "desc": "PAM Permission denied (gh-1897)" }
|
||||
Jan 29 14:38:51 example.com dovecot[24941]: auth-worker(30165): pam(user@example.com,192.0.2.6,<PNHQq8pZhqIKAQGd>): pam_authenticate() failed: Permission denied
|
||||
|
||||
|
|
|
@ -1368,7 +1368,6 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
|
|||
def setUp(self):
|
||||
"""Call before every test case."""
|
||||
super(MonitorJournalFailures, self).setUp()
|
||||
self._runtimeJournal = None
|
||||
self.test_file = os.path.join(TEST_FILES_DIR, "testcase-journal.log")
|
||||
self.jail = DummyJail()
|
||||
self.filter = None
|
||||
|
@ -1406,7 +1405,7 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
|
|||
If not found, SkipTest exception will be raised.
|
||||
"""
|
||||
# we can cache it:
|
||||
if self._runtimeJournal is None:
|
||||
if not hasattr(MonitorJournalFailures, "_runtimeJournal"):
|
||||
# Depending on the system, it could be found under /run or /var/log (e.g. Debian)
|
||||
# which are pointed by different systemd-path variables. We will
|
||||
# check one at at time until the first hit
|
||||
|
@ -1418,9 +1417,14 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
|
|||
self.assertTrue(tmp)
|
||||
out = str(tmp[1].decode('utf-8')).split('\n')[0]
|
||||
if out: break
|
||||
self._runtimeJournal = out
|
||||
if self._runtimeJournal:
|
||||
return self._runtimeJournal
|
||||
# additional check appropriate default settings (if not root/sudoer and not already set):
|
||||
if os.geteuid() != 0 and os.getenv("F2B_SYSTEMD_DEFAULT_FLAGS", None) is None:
|
||||
# filter default SYSTEM_ONLY(4) is hardly usable for not root/sudoer tester,
|
||||
# so back to default LOCAL_ONLY(1):
|
||||
os.environ["F2B_SYSTEMD_DEFAULT_FLAGS"] = "0"; # or "1", what will be similar to journalflags=0 or ...=1
|
||||
MonitorJournalFailures._runtimeJournal = out
|
||||
if MonitorJournalFailures._runtimeJournal:
|
||||
return MonitorJournalFailures._runtimeJournal
|
||||
raise unittest.SkipTest('systemd journal seems to be not available (e. g. no rights to read)')
|
||||
|
||||
def testJournalFilesArg(self):
|
||||
|
@ -1526,7 +1530,7 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
|
|||
# stop:
|
||||
self.filter.stop()
|
||||
self.filter.join()
|
||||
MyTime.setTime(time.time() + 2)
|
||||
MyTime.setTime(time.time() + 10)
|
||||
# update log manually (should cause a seek to end of log without wait for next second):
|
||||
self.jail.database.updateJournal(self.jail, 'systemd-journal', MyTime.time(), 'TEST')
|
||||
# check seek to last (simulated) position succeeds (without bans of previous copied tickets):
|
||||
|
@ -1534,7 +1538,7 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
|
|||
self._initFilter()
|
||||
self.filter.setMaxRetry(1)
|
||||
self.filter.start()
|
||||
self.waitForTicks(1)
|
||||
self.waitForTicks(2)
|
||||
# check new IP but no old IPs found:
|
||||
_gen_falure("192.0.2.5")
|
||||
self.assertFalse(self.jail.getFailTicket())
|
||||
|
@ -1547,8 +1551,8 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
|
|||
self._initFilter()
|
||||
self.filter.setMaxRetry(1)
|
||||
self.filter.start()
|
||||
self.waitForTicks(1)
|
||||
MyTime.setTime(time.time() + 3)
|
||||
self.waitForTicks(2)
|
||||
MyTime.setTime(time.time() + 20)
|
||||
# check new IP but no old IPs found:
|
||||
_gen_falure("192.0.2.6")
|
||||
self.assertFalse(self.jail.getFailTicket())
|
||||
|
@ -1561,15 +1565,23 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
|
|||
self.filter.setMaxRetry(1)
|
||||
states = []
|
||||
def _state(*args):
|
||||
self.assertNotIn("** in operation", states)
|
||||
self.assertFalse(self.filter.inOperation)
|
||||
states.append("** process line: %r" % (args,))
|
||||
try:
|
||||
self.assertNotIn("** in operation", states)
|
||||
self.assertFalse(self.filter.inOperation)
|
||||
states.append("** process line: %r" % (args,))
|
||||
except Exception as e:
|
||||
states.append("** failed: %r" % (e,))
|
||||
raise
|
||||
self.filter.processLineAndAdd = _state
|
||||
def _inoper():
|
||||
self.assertNotIn("** in operation", states)
|
||||
self.assertEqual(len(states), 11)
|
||||
states.append("** in operation")
|
||||
self.filter.__class__.inOperationMode(self.filter)
|
||||
try:
|
||||
self.assertNotIn("** in operation", states)
|
||||
self.assertEqual(len(states), 11)
|
||||
states.append("** in operation")
|
||||
self.filter.__class__.inOperationMode(self.filter)
|
||||
except Exception as e:
|
||||
states.append("** failed: %r" % (e,))
|
||||
raise
|
||||
self.filter.inOperationMode = _inoper
|
||||
self.filter.start()
|
||||
self.waitForTicks(12)
|
||||
|
|
Loading…
Reference in New Issue