mirror of https://github.com/fail2ban/fail2ban
better handling of default date templates (bounds, replacement using own expressions `...{DATE}...`, etc.)
parent
ce6ca0029a
commit
2e533a3a3a
|
@ -109,9 +109,6 @@ class DateDetectorCache(object):
|
|||
"""Cache Fail2Ban's default template.
|
||||
|
||||
"""
|
||||
if isinstance(template, str):
|
||||
# exact given template with word begin-end boundary:
|
||||
template = _getPatternTemplate(template)
|
||||
# if not already line-begin anchored, additional template, that prefers datetime
|
||||
# at start of a line (safety+performance feature):
|
||||
name = template.name
|
||||
|
@ -126,60 +123,74 @@ class DateDetectorCache(object):
|
|||
# add template:
|
||||
self.__tmpcache[1].append(template)
|
||||
|
||||
def _addDefaultTemplate(self):
|
||||
"""Add resp. cache Fail2Ban's default set of date templates.
|
||||
"""
|
||||
self.__tmpcache = [], []
|
||||
DEFAULT_TEMPLATES = [
|
||||
# ISO 8601, simple date, optional subsecond and timezone:
|
||||
# 2005-01-23T21:59:59.981746, 2005-01-23 21:59:59, 2005-01-23 8:59:59
|
||||
# simple date: 2005/01/23 21:59:59
|
||||
# custom for syslog-ng 2006.12.21 06:43:20
|
||||
self._cacheTemplate("%ExY(?P<_sep>[-/.])%m(?P=_sep)%d(?:T| ?)%H:%M:%S(?:[.,]%f)?(?:\s*%z)?")
|
||||
"%ExY(?P<_sep>[-/.])%m(?P=_sep)%d(?:T| ?)%H:%M:%S(?:[.,]%f)?(?:\s*%z)?",
|
||||
# asctime with optional day, subsecond and/or year:
|
||||
# Sun Jan 23 21:59:59.011 2005
|
||||
self._cacheTemplate("(?:%a )?%b %d %k:%M:%S(?:\.%f)?(?: %ExY)?")
|
||||
"(?:%a )?%b %d %k:%M:%S(?:\.%f)?(?: %ExY)?",
|
||||
# asctime with optional day, subsecond and/or year coming after day
|
||||
# http://bugs.debian.org/798923
|
||||
# Sun Jan 23 2005 21:59:59.011
|
||||
self._cacheTemplate("(?:%a )?%b %d %ExY %k:%M:%S(?:\.%f)?")
|
||||
"(?:%a )?%b %d %ExY %k:%M:%S(?:\.%f)?",
|
||||
# simple date too (from x11vnc): 23/01/2005 21:59:59
|
||||
# and with optional year given by 2 digits: 23/01/05 21:59:59
|
||||
# (See http://bugs.debian.org/537610)
|
||||
# 17-07-2008 17:23:25
|
||||
self._cacheTemplate("%d(?P<_sep>[-/])%m(?P=_sep)(?:%ExY|%Exy) %k:%M:%S")
|
||||
"%d(?P<_sep>[-/])%m(?P=_sep)(?:%ExY|%Exy) %k:%M:%S",
|
||||
# Apache format optional time zone:
|
||||
# [31/Oct/2006:09:22:55 -0000]
|
||||
# 26-Jul-2007 15:20:52
|
||||
# named 26-Jul-2007 15:20:52.252
|
||||
# roundcube 26-Jul-2007 15:20:52 +0200
|
||||
self._cacheTemplate("%d(?P<_sep>[-/])%b(?P=_sep)%ExY[ :]?%H:%M:%S(?:\.%f)?(?: %z)?")
|
||||
"%d(?P<_sep>[-/])%b(?P=_sep)%ExY[ :]?%H:%M:%S(?:\.%f)?(?: %z)?",
|
||||
# CPanel 05/20/2008:01:57:39
|
||||
self._cacheTemplate("%m/%d/%ExY:%H:%M:%S")
|
||||
"%m/%d/%ExY:%H:%M:%S",
|
||||
# 01-27-2012 16:22:44.252
|
||||
# subseconds explicit to avoid possible %m<->%d confusion
|
||||
# with previous ("%d-%m-%ExY %k:%M:%S" by "%d(?P<_sep>[-/])%m(?P=_sep)(?:%ExY|%Exy) %k:%M:%S")
|
||||
self._cacheTemplate("%m-%d-%ExY %k:%M:%S(?:\.%f)?")
|
||||
"%m-%d-%ExY %k:%M:%S(?:\.%f)?",
|
||||
# Epoch
|
||||
self._cacheTemplate('EPOCH')
|
||||
"EPOCH",
|
||||
# Only time information in the log
|
||||
self._cacheTemplate("{^LN-BEG}%H:%M:%S")
|
||||
"{^LN-BEG}%H:%M:%S",
|
||||
# <09/16/08@05:03:30>
|
||||
self._cacheTemplate("^<%m/%d/%Exy@%H:%M:%S>")
|
||||
"^<%m/%d/%Exy@%H:%M:%S>",
|
||||
# MySQL: 130322 11:46:11
|
||||
self._cacheTemplate("%Exy%Exm%Exd ?%H:%M:%S")
|
||||
"%Exy%Exm%Exd ?%H:%M:%S",
|
||||
# Apache Tomcat
|
||||
self._cacheTemplate("%b %d, %ExY %I:%M:%S %p")
|
||||
"%b %d, %ExY %I:%M:%S %p",
|
||||
# ASSP: Apr-27-13 02:33:06
|
||||
self._cacheTemplate("^%b-%d-%Exy %k:%M:%S")
|
||||
"^%b-%d-%Exy %k:%M:%S",
|
||||
# 20050123T215959, 20050123 215959, 20050123 85959
|
||||
self._cacheTemplate("%ExY%Exm%Exd(?:T| ?)%ExH%ExM%ExS(?:[.,]%f)?(?:\s*%z)?")
|
||||
"%ExY%Exm%Exd(?:T| ?)%ExH%ExM%ExS(?:[.,]%f)?(?:\s*%z)?",
|
||||
# prefixed with optional named time zone (monit):
|
||||
# PDT Apr 16 21:05:29
|
||||
self._cacheTemplate("(?:%Z )?(?:%a )?%b %d %k:%M:%S(?:\.%f)?(?: %ExY)?")
|
||||
"(?:%Z )?(?:%a )?%b %d %k:%M:%S(?:\.%f)?(?: %ExY)?",
|
||||
# +00:00 Jan 23 21:59:59.011 2005
|
||||
self._cacheTemplate("(?:%z )?(?:%a )?%b %d %k:%M:%S(?:\.%f)?(?: %ExY)?")
|
||||
"(?:%z )?(?:%a )?%b %d %k:%M:%S(?:\.%f)?(?: %ExY)?",
|
||||
# TAI64N
|
||||
self._cacheTemplate("TAI64N")
|
||||
"TAI64N",
|
||||
]
|
||||
|
||||
@property
|
||||
def defaultTemplates(self):
|
||||
if isinstance(DateDetectorCache.DEFAULT_TEMPLATES[0], str):
|
||||
for i, dt in enumerate(DateDetectorCache.DEFAULT_TEMPLATES):
|
||||
dt = _getPatternTemplate(dt)
|
||||
DateDetectorCache.DEFAULT_TEMPLATES[i] = dt
|
||||
return DateDetectorCache.DEFAULT_TEMPLATES
|
||||
|
||||
def _addDefaultTemplate(self):
|
||||
"""Add resp. cache Fail2Ban's default set of date templates.
|
||||
"""
|
||||
self.__tmpcache = [], []
|
||||
# cache default templates:
|
||||
for dt in self.defaultTemplates:
|
||||
self._cacheTemplate(dt)
|
||||
#
|
||||
self.__templates = self.__tmpcache[0] + self.__tmpcache[1]
|
||||
del self.__tmpcache
|
||||
|
@ -269,8 +280,7 @@ class DateDetector(object):
|
|||
self.addDefaultTemplate(flt)
|
||||
return
|
||||
elif "{DATE}" in key:
|
||||
self.addDefaultTemplate(
|
||||
lambda template: not template.flags & DateTemplate.LINE_BEGIN, pattern)
|
||||
self.addDefaultTemplate(preMatch=pattern, allDefaults=False)
|
||||
return
|
||||
else:
|
||||
template = _getPatternTemplate(pattern, key)
|
||||
|
@ -283,18 +293,20 @@ class DateDetector(object):
|
|||
logSys.debug(" date pattern regex for %r: %s",
|
||||
getattr(template, 'pattern', ''), template.regex)
|
||||
|
||||
def addDefaultTemplate(self, filterTemplate=None, preMatch=None):
|
||||
def addDefaultTemplate(self, filterTemplate=None, preMatch=None, allDefaults=True):
|
||||
"""Add Fail2Ban's default set of date templates.
|
||||
"""
|
||||
ignoreDup = len(self.__templates) > 0
|
||||
for template in DateDetector._defCache.templates:
|
||||
for template in (
|
||||
DateDetector._defCache.templates if allDefaults else DateDetector._defCache.defaultTemplates
|
||||
):
|
||||
# filter if specified:
|
||||
if filterTemplate is not None and not filterTemplate(template): continue
|
||||
# if exact pattern available - create copy of template, contains replaced {DATE} with default regex:
|
||||
if preMatch is not None:
|
||||
# get cached or create a copy with modified name/pattern, using preMatch replacement for {DATE}:
|
||||
template = _getAnchoredTemplate(template,
|
||||
wrap=lambda s: RE_DATE_PREMATCH.sub(lambda m: s, preMatch))
|
||||
wrap=lambda s: RE_DATE_PREMATCH.sub(lambda m: DateTemplate.unboundPattern(s), preMatch))
|
||||
# append date detector template (ignore duplicate if some was added before default):
|
||||
self._appendTemplate(template, ignoreDup=ignoreDup)
|
||||
|
||||
|
|
|
@ -37,8 +37,10 @@ RE_GROUPED = re.compile(r'(?<!(?:\(\?))(?<!\\)\((?!\?)')
|
|||
RE_GROUP = ( re.compile(r'^((?:\(\?\w+\))?\^?(?:\(\?\w+\))?)(.*?)(\$?)$'), r"\1(\2)\3" )
|
||||
|
||||
RE_EXLINE_BOUND_BEG = re.compile(r'^\{\^LN-BEG\}')
|
||||
RE_EXSANC_BOUND_BEG = re.compile(r'^\(\?:\^\|\\b\|\\W\)')
|
||||
RE_EXEANC_BOUND_BEG = re.compile(r'\(\?=\\b\|\\W\|\$\)$')
|
||||
RE_NO_WRD_BOUND_BEG = re.compile(r'^\(*(?:\(\?\w+\))?(?:\^|\(*\*\*|\(\?:\^)')
|
||||
RE_NO_WRD_BOUND_END = re.compile(r'(?<!\\)(?:\$\)?|\*\*\)*)$')
|
||||
RE_NO_WRD_BOUND_END = re.compile(r'(?<!\\)(?:\$\)?|\\b|\\s|\*\*\)*)$')
|
||||
RE_DEL_WRD_BOUNDS = ( re.compile(r'^\(*(?:\(\?\w+\))?\(*\*\*|(?<!\\)\*\*\)*$'),
|
||||
lambda m: m.group().replace('**', '') )
|
||||
|
||||
|
@ -131,7 +133,7 @@ class DateTemplate(object):
|
|||
# remove possible special pattern "**" in front and end of regex:
|
||||
regex = RE_DEL_WRD_BOUNDS[0].sub(RE_DEL_WRD_BOUNDS[1], regex)
|
||||
self._regex = regex
|
||||
logSys.debug(' constructed regex %s', regex)
|
||||
logSys.log(7, ' constructed regex %s', regex)
|
||||
self._cRegex = None
|
||||
|
||||
regex = property(getRegex, setRegex, doc=
|
||||
|
@ -182,6 +184,14 @@ class DateTemplate(object):
|
|||
"""
|
||||
raise NotImplementedError("getDate() is abstract")
|
||||
|
||||
@staticmethod
|
||||
def unboundPattern(pattern):
|
||||
return RE_EXEANC_BOUND_BEG.sub('',
|
||||
RE_EXSANC_BOUND_BEG.sub('',
|
||||
RE_EXLINE_BOUND_BEG.sub('', pattern)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class DateEpoch(DateTemplate):
|
||||
"""A date template which searches for Unix timestamps.
|
||||
|
|
Loading…
Reference in New Issue