Merge pull request #299 from kwirk/datepatterns-dateregex

Custom date templates and date detector changes
pull/348/head
Steven Hiscocks 2013-07-26 03:53:40 -07:00
commit 27feb57e80
21 changed files with 169 additions and 112 deletions

View File

@ -88,6 +88,8 @@ IGNOREREGEX:
version="%prog " + version) version="%prog " + version)
p.add_options([ p.add_options([
Option("-d", "--datepattern",
help="set custom pattern used to match date/times"),
Option("-e", "--encoding", Option("-e", "--encoding",
help="File encoding. Default: system locale"), help="File encoding. Default: system locale"),
Option("-L", "--maxlines", type=int, default=0, Option("-L", "--maxlines", type=int, default=0,
@ -179,6 +181,9 @@ class Fail2banRegex(object):
self._maxlines_set = False # so we allow to override maxlines in cmdline self._maxlines_set = False # so we allow to override maxlines in cmdline
self._journalmatch = None self._journalmatch = None
if opts.datepattern:
self.setDatePattern(opts.datepattern)
if opts.encoding: if opts.encoding:
self.encoding = opts.encoding self.encoding = opts.encoding
else: else:
@ -194,6 +199,8 @@ class Fail2banRegex(object):
if opts.journalmatch is not None: if opts.journalmatch is not None:
self.setJournalMatch(opts.journalmatch.split()) self.setJournalMatch(opts.journalmatch.split())
def setDatePattern(self, pattern):
self._filter.setDatePattern(pattern)
def setMaxLines(self, v): def setMaxLines(self, v):
if not self._maxlines_set: if not self._maxlines_set:

View File

@ -18,4 +18,4 @@ after = apache-common.local
# 2.2: [Sat Jun 01 11:23:08 2013] [error] [client 1.2.3.4] # 2.2: [Sat Jun 01 11:23:08 2013] [error] [client 1.2.3.4]
# 2.4: [Thu Jun 27 11:55:44.569531 2013] [core:info] [pid 4101:tid 2992634688] [client 1.2.3.4:46652] # 2.4: [Thu Jun 27 11:55:44.569531 2013] [core:info] [pid 4101:tid 2992634688] [client 1.2.3.4:46652]
# Reference: https://github.com/fail2ban/fail2ban/issues/268 # Reference: https://github.com/fail2ban/fail2ban/issues/268
_apache_error_client = \[[^]]+\] \[(error|core:\S+)\]( \[pid \d+:\S+ \d+\])? \[client <HOST>(:\d{1,5})?\]( \S+:)? _apache_error_client = \[[^]]*\] \[(error|core:\S+)\]( \[pid \d+:\S+ \d+\])? \[client <HOST>(:\d{1,5})?\]( \S+:)?

View File

@ -23,3 +23,8 @@
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging
# Custom debug level
logging.HEAVYDEBUG = 5

View File

@ -23,8 +23,3 @@
__author__ = "Cyril Jaquier" __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging
# Custom debug level
logging.HEAVYDEBUG = 5

View File

@ -119,6 +119,12 @@ class Beautifier:
else: else:
msg = "Current match filter:\n" msg = "Current match filter:\n"
msg += ' + '.join(" ".join(res) for res in response) msg += ' + '.join(" ".join(res) for res in response)
elif inC[2] == "datepattern":
msg = "Current date pattern set to: "
if response is None:
msg = msg + "Default Detectors"
else:
msg = msg + "%s (%s)" % response
elif inC[2] in ("ignoreip", "addignoreip", "delignoreip"): elif inC[2] in ("ignoreip", "addignoreip", "delignoreip"):
if len(response) == 0: if len(response) == 0:
msg = "No IP address/network is ignored" msg = "No IP address/network is ignored"

View File

@ -56,6 +56,8 @@ class FilterReader(DefinitionInitConfigReader):
if self._initOpts: if self._initOpts:
if 'maxlines' in self._initOpts: if 'maxlines' in self._initOpts:
stream.append(["set", self._jailName, "maxlines", self._initOpts["maxlines"]]) stream.append(["set", self._jailName, "maxlines", self._initOpts["maxlines"]])
if 'datepattern' in self._initOpts:
stream.append(["set", self._jailName, "datepattern", self._initOpts["datepattern"]])
# Do not send a command if the match is empty. # Do not send a command if the match is empty.
if self._initOpts.get("journalmatch", '') != '': if self._initOpts.get("journalmatch", '') != '':
for match in self._initOpts["journalmatch"].split("\n"): for match in self._initOpts["journalmatch"].split("\n"):

View File

@ -63,6 +63,7 @@ protocol = [
["set <JAIL> delignoreregex <INDEX>", "removes the regular expression at <INDEX> for ignoreregex"], ["set <JAIL> delignoreregex <INDEX>", "removes the regular expression at <INDEX> for ignoreregex"],
["set <JAIL> findtime <TIME>", "sets the number of seconds <TIME> for which the filter will look back for <JAIL>"], ["set <JAIL> findtime <TIME>", "sets the number of seconds <TIME> for which the filter will look back for <JAIL>"],
["set <JAIL> bantime <TIME>", "sets the number of seconds <TIME> a host will be banned for <JAIL>"], ["set <JAIL> bantime <TIME>", "sets the number of seconds <TIME> a host will be banned for <JAIL>"],
["set <JAIL> datepattern <PATTERN>", "sets the <PATTERN> used to match date/times for <JAIL>"],
["set <JAIL> usedns <VALUE>", "sets the usedns mode for <JAIL>"], ["set <JAIL> usedns <VALUE>", "sets the usedns mode for <JAIL>"],
["set <JAIL> banip <IP>", "manually Ban <IP> for <JAIL>"], ["set <JAIL> banip <IP>", "manually Ban <IP> for <JAIL>"],
["set <JAIL> unbanip <IP>", "manually Unban <IP> in <JAIL>"], ["set <JAIL> unbanip <IP>", "manually Unban <IP> in <JAIL>"],
@ -87,6 +88,7 @@ protocol = [
["get <JAIL> ignoreregex", "gets the list of regular expressions which matches patterns to ignore for <JAIL>"], ["get <JAIL> ignoreregex", "gets the list of regular expressions which matches patterns to ignore for <JAIL>"],
["get <JAIL> findtime", "gets the time for which the filter will look back for failures for <JAIL>"], ["get <JAIL> findtime", "gets the time for which the filter will look back for failures for <JAIL>"],
["get <JAIL> bantime", "gets the time a host is banned for <JAIL>"], ["get <JAIL> bantime", "gets the time a host is banned for <JAIL>"],
["get <JAIL> datepattern", "gets the patern used to match date/times for <JAIL>"],
["get <JAIL> usedns", "gets the usedns setting for <JAIL>"], ["get <JAIL> usedns", "gets the usedns setting for <JAIL>"],
["get <JAIL> maxretry", "gets the number of failures allowed for <JAIL>"], ["get <JAIL> maxretry", "gets the number of failures allowed for <JAIL>"],
["get <JAIL> maxlines", "gets the number of lines to buffer for <JAIL>"], ["get <JAIL> maxlines", "gets the number of lines to buffer for <JAIL>"],

View File

@ -23,7 +23,7 @@ __license__ = "GPL"
import time, logging import time, logging
from datetemplate import DateStrptime, DateTai64n, DateEpoch, DateISO8601 from datetemplate import DatePatternRegex, DateTai64n, DateEpoch, DateISO8601
from threading import Lock from threading import Lock
# Gets the instance of the logger. # Gets the instance of the logger.
@ -43,130 +43,63 @@ class DateDetector:
self.__known_names.add(name) self.__known_names.add(name)
self.__templates.append(template) self.__templates.append(template)
def appendTemplate(self, template, **kwargs):
if isinstance(template, str):
template = DatePatternRegex(template, **kwargs)
else:
assert not kwargs
DateDetector._appendTemplate(self, template)
def addDefaultTemplate(self): def addDefaultTemplate(self):
self.__lock.acquire() self.__lock.acquire()
try: try:
# standard
template = DateStrptime()
template.setName("MONTH Day Hour:Minute:Second")
template.setRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
template.setPattern("%b %d %H:%M:%S")
self._appendTemplate(template)
# asctime # asctime
template = DateStrptime() self.appendTemplate("%a %b %d %H:%M:%S %Y")
template.setName("WEEKDAY MONTH Day Hour:Minute:Second Year")
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4}")
template.setPattern("%a %b %d %H:%M:%S %Y")
self._appendTemplate(template)
# asctime without year # asctime without year
template = DateStrptime() self.appendTemplate("%a %b %d %H:%M:%S")
template.setName("WEEKDAY MONTH Day Hour:Minute:Second") # standard
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}") self.appendTemplate("%b %d %H:%M:%S")
template.setPattern("%a %b %d %H:%M:%S")
self._appendTemplate(template)
# simple date # simple date
template = DateStrptime() self.appendTemplate("%Y/%m/%d %H:%M:%S")
template.setName("Year/Month/Day Hour:Minute:Second")
template.setRegex("\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}")
template.setPattern("%Y/%m/%d %H:%M:%S")
self._appendTemplate(template)
# simple date too (from x11vnc) # simple date too (from x11vnc)
template = DateStrptime() self.appendTemplate("%d/%m/%Y %H:%M:%S")
template.setName("Day/Month/Year Hour:Minute:Second")
template.setRegex("\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}")
template.setPattern("%d/%m/%Y %H:%M:%S")
self._appendTemplate(template)
# previous one but with year given by 2 digits # previous one but with year given by 2 digits
# (See http://bugs.debian.org/537610) # (See http://bugs.debian.org/537610)
template = DateStrptime() self.appendTemplate("%d/%m/%y %H:%M:%S")
template.setName("Day/Month/Year2 Hour:Minute:Second")
template.setRegex("\d{2}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}")
template.setPattern("%d/%m/%y %H:%M:%S")
self._appendTemplate(template)
# Apache format [31/Oct/2006:09:22:55 -0000] # Apache format [31/Oct/2006:09:22:55 -0000]
template = DateStrptime() self.appendTemplate("%d/%b/%Y:%H:%M:%S")
template.setName("Day/MONTH/Year:Hour:Minute:Second")
template.setRegex("\d{2}/\S{3}/\d{4}:\d{2}:\d{2}:\d{2}")
template.setPattern("%d/%b/%Y:%H:%M:%S")
self._appendTemplate(template)
# CPanel 05/20/2008:01:57:39 # CPanel 05/20/2008:01:57:39
template = DateStrptime() self.appendTemplate("%m/%d/%Y:%H:%M:%S")
template.setName("Month/Day/Year:Hour:Minute:Second")
template.setRegex("\d{2}/\d{2}/\d{4}:\d{2}:\d{2}:\d{2}")
template.setPattern("%m/%d/%Y:%H:%M:%S")
self._appendTemplate(template)
# Exim 2006-12-21 06:43:20
template = DateStrptime()
template.setName("Year-Month-Day Hour:Minute:Second")
template.setRegex("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")
template.setPattern("%Y-%m-%d %H:%M:%S")
self._appendTemplate(template)
# custom for syslog-ng 2006.12.21 06:43:20 # custom for syslog-ng 2006.12.21 06:43:20
template = DateStrptime() self.appendTemplate("%Y.%m.%d %H:%M:%S")
template.setName("Year.Month.Day Hour:Minute:Second")
template.setRegex("\d{4}.\d{2}.\d{2} \d{2}:\d{2}:\d{2}")
template.setPattern("%Y.%m.%d %H:%M:%S")
self._appendTemplate(template)
# named 26-Jul-2007 15:20:52.252 # named 26-Jul-2007 15:20:52.252
template = DateStrptime() self.appendTemplate("%d-%b-%Y %H:%M:%S")
template.setName("Day-MONTH-Year Hour:Minute:Second[.Millisecond]")
template.setRegex("\d{2}-\S{3}-\d{4} \d{2}:\d{2}:\d{2}")
template.setPattern("%d-%b-%Y %H:%M:%S")
self._appendTemplate(template)
# 17-07-2008 17:23:25 # 17-07-2008 17:23:25
template = DateStrptime() self.appendTemplate("%d-%m-%Y %H:%M:%S")
template.setName("Day-Month-Year Hour:Minute:Second")
template.setRegex("\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}")
template.setPattern("%d-%m-%Y %H:%M:%S")
self._appendTemplate(template)
# 01-27-2012 16:22:44.252 # 01-27-2012 16:22:44.252
template = DateStrptime() self.appendTemplate("%m-%d-%Y %H:%M:%S")
template.setName("Month-Day-Year Hour:Minute:Second[.Millisecond]")
template.setRegex("\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}")
template.setPattern("%m-%d-%Y %H:%M:%S")
self._appendTemplate(template)
# TAI64N # TAI64N
template = DateTai64n() template = DateTai64n()
template.setName("TAI64N") template.setName("TAI64N")
self._appendTemplate(template) self.appendTemplate(template)
# Epoch # Epoch
template = DateEpoch() template = DateEpoch()
template.setName("Epoch") template.setName("Epoch")
self._appendTemplate(template) self.appendTemplate(template)
# ISO 8601 # ISO 8601
template = DateISO8601() template = DateISO8601()
template.setName("ISO 8601") template.setName("ISO 8601")
self._appendTemplate(template) self.appendTemplate(template)
# Only time information in the log # Only time information in the log
template = DateStrptime() self.appendTemplate("%H:%M:%S", anchor=True)
template.setName("Hour:Minute:Second")
template.setRegex("^\d{2}:\d{2}:\d{2}")
template.setPattern("%H:%M:%S")
self._appendTemplate(template)
# <09/16/08@05:03:30> # <09/16/08@05:03:30>
template = DateStrptime() self.appendTemplate("<%m/%d/%y@%H:%M:%S>", anchor=True)
template.setName("<Month/Day/Year@Hour:Minute:Second>")
template.setRegex("^<\d{2}/\d{2}/\d{2}@\d{2}:\d{2}:\d{2}>")
template.setPattern("<%m/%d/%y@%H:%M:%S>")
self._appendTemplate(template)
# MySQL: 130322 11:46:11 # MySQL: 130322 11:46:11
template = DateStrptime() self.appendTemplate("%y%m%d %H:%M:%S", anchor=True)
template.setName("MonthDayYear Hour:Minute:Second")
template.setRegex("^\d{2}\d{2}\d{2} +\d{1,2}:\d{2}:\d{2}")
template.setPattern("%y%m%d %H:%M:%S")
self._appendTemplate(template)
# Apache Tomcat # Apache Tomcat
template = DateStrptime() self.appendTemplate("%b %d, %Y %I:%M:%S %p")
template.setName("MONTH Day, Year 12hour:Minute:Second AM/PM")
template.setRegex("\S{3}\s{1,2}\d{1,2}, \d{4} \d{1,2}:\d{2}:\d{2} [AP]M")
template.setPattern("%b %d, %Y %I:%M:%S %p")
self._appendTemplate(template)
# ASSP: Apr-27-13 02:33:06 # ASSP: Apr-27-13 02:33:06
template = DateStrptime() self.appendTemplate("%b-%d-%y %H:%M:%S", anchor=True)
template.setName("Month-Day-Year Hour:Minute:Second")
template.setRegex("^[a-zA-Z]{3}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")
template.setPattern("%b-%d-%y %H:%M:%S")
self._appendTemplate(template)
finally: finally:
self.__lock.release() self.__lock.release()

View File

@ -52,7 +52,7 @@ class DateTemplate:
if (wordBegin and not re.search(r'^\^', regex)): if (wordBegin and not re.search(r'^\^', regex)):
regex = r'\b' + regex regex = r'\b' + regex
self.__regex = regex self.__regex = regex
self.__cRegex = re.compile(regex) self.__cRegex = re.compile(regex, re.UNICODE)
def getRegex(self): def getRegex(self):
return self.__regex return self.__regex
@ -178,6 +178,51 @@ class DateStrptime(DateTemplate):
date[2] = MyTime.gmtime()[2] date[2] = MyTime.gmtime()[2]
return date return date
class DatePatternRegex(DateStrptime):
_reEscape = r"([\\.^$*+?\(\){}\[\]|])"
_patternRE = r"%(%|[aAbBdHIjmMpSUwWyY])"
_patternName = {
'a': "DAY", 'A': "DAYNAME", 'b': "MON", 'B': "MONTH", 'd': "Day",
'H': "24hour", 'I': "12hour", 'j': "Yearday", 'm': "Month",
'M': "Minute", 'p': "AMPM", 'S': "Second", 'U': "Yearweek",
'w': "Weekday", 'W': "Yearweek", 'y': 'Year2', 'Y': "Year", '%': "%"}
_patternRegex = {
'a': r"\w{3}", 'A': r"\w+", 'b': r"\w{3}", 'B': r"\w+",
'd': r"(?:3[0-1]|[1-2]\d|[ 0]?\d)", 'H': r"(?:2[0-3]|1\d|[ 0]?\d)",
'I': r"(?:1[0-2]|[ 0]?\d)",
'j': r"(?:36[0-6]3[0-5]\d|[1-2]\d\d|[ 0]?\d\d|[ 0]{0,2}\d)",
'm': r"(?:1[0-2]|[ 0]?[1-9])", 'M': r"[0-5]\d", 'p': r"[AP]M",
'S': r"(?:6[01]|[0-5]\d)", 'U': r"(?:5[0-3]|[1-4]\d|[ 0]?\d)",
'w': r"[0-6]", 'W': r"(?:5[0-3]|[ 0]?\d)", 'y': r"\d{2}",
'Y': r"\d{4}", '%': "%"}
def __init__(self, pattern=None, **kwargs):
DateStrptime.__init__(self)
if pattern:
self.setPattern(pattern, **kwargs)
def setPattern(self, pattern, anchor=False, **kwargs):
self.__pattern = pattern.strip()
name = re.sub(self._patternRE, r'%(\1)s', pattern) % self._patternName
DateStrptime.setName(self, name)
# Custom escape as don't want to escape "%"
pattern = re.sub(self._reEscape, r'\\\1', pattern)
regex = re.sub(
self._patternRE, r'%(\1)s', pattern) % self._patternRegex
if anchor:
regex = r"^" + regex
DateStrptime.setRegex(self, regex, **kwargs)
def getPattern(self):
return self.__pattern
def setRegex(self, line):
raise NotImplementedError("Regex derived from pattern")
def setName(self, line):
raise NotImplementedError("Name derived from pattern")
class DateTai64n(DateTemplate): class DateTai64n(DateTemplate):
@ -214,6 +259,6 @@ class DateISO8601(DateTemplate):
if dateMatch: if dateMatch:
# Parses the date. # Parses the date.
value = dateMatch.group() value = dateMatch.group()
date = list(iso8601.parse_date(value).timetuple()) date = list(iso8601.parse_date(value, None).timetuple())
return date return date

View File

@ -28,6 +28,7 @@ from failmanager import FailManager
from ticket import FailTicket from ticket import FailTicket
from jailthread import JailThread from jailthread import JailThread
from datedetector import DateDetector from datedetector import DateDetector
from datetemplate import DatePatternRegex
from mytime import MyTime from mytime import MyTime
from failregex import FailRegex, Regex, RegexException from failregex import FailRegex, Regex, RegexException
@ -191,6 +192,40 @@ class Filter(JailThread):
def getFindTime(self): def getFindTime(self):
return self.__findTime return self.__findTime
##
# Set the date detector pattern, removing Defaults
#
# @param pattern the date template pattern
def setDatePattern(self, pattern):
dateDetector = DateDetector()
template = DatePatternRegex()
if pattern[0] == "^": # Special extra to enable anchor
template.setPattern(pattern[1:], anchor=True)
else:
template.setPattern(pattern, anchor=False)
dateDetector.appendTemplate(template)
self.dateDetector = dateDetector
logSys.info("Date pattern set to `%r`: `%s`" %
(pattern, template.getName()))
logSys.debug("Date pattern regex for %r: %s" %
(pattern, template.getRegex()))
##
# Get the date detector pattern, or Default Detectors if not changed
#
# @return pattern of the date template pattern
def getDatePattern(self):
templates = self.dateDetector.getTemplates()
if len(templates) > 1:
return None # Default Detectors in use
elif len(templates) == 1:
pattern = templates[0].getPattern()
if templates[0].getRegex()[0] == "^":
pattern = "^" + pattern
return pattern, templates[0].getName()
## ##
# Set the maximum retry value. # Set the maximum retry value.
# #
@ -394,7 +429,9 @@ class Filter(JailThread):
logSys.log(7, "Matched %s", failRegex) logSys.log(7, "Matched %s", failRegex)
if date is None: if date is None:
logSys.debug("Found a match for %r but no valid date/time " logSys.debug("Found a match for %r but no valid date/time "
"found for %r. Please file a detailed issue on" "found for %r. Please try setting a custom "
"date pattern. If format is complex, please "
"file a detailed issue on"
" https://github.com/fail2ban/fail2ban/issues " " https://github.com/fail2ban/fail2ban/issues "
"in order to get support for this format." "in order to get support for this format."
% (logLine, timeLine)) % (logLine, timeLine))

View File

@ -222,6 +222,12 @@ class Server:
def getFindTime(self, name): def getFindTime(self, name):
return self.__jails.getFilter(name).getFindTime() return self.__jails.getFilter(name).getFindTime()
def setDatePattern(self, name, pattern):
self.__jails.getFilter(name).setDatePattern(pattern)
def getDatePattern(self, name):
return self.__jails.getFilter(name).getDatePattern()
def addFailRegex(self, name, value): def addFailRegex(self, name, value):
self.__jails.getFilter(name).addFailRegex(value) self.__jails.getFilter(name).addFailRegex(value)

View File

@ -176,6 +176,10 @@ class Transmitter:
value = command[2] value = command[2]
self.__server.setFindTime(name, int(value)) self.__server.setFindTime(name, int(value))
return self.__server.getFindTime(name) return self.__server.getFindTime(name)
elif command[1] == "datepattern":
value = command[2]
self.__server.setDatePattern(name, value)
return self.__server.getDatePattern(name)
elif command[1] == "maxretry": elif command[1] == "maxretry":
value = command[2] value = command[2]
self.__server.setMaxRetry(name, int(value)) self.__server.setMaxRetry(name, int(value))
@ -270,6 +274,8 @@ class Transmitter:
return self.__server.getUseDns(name) return self.__server.getUseDns(name)
elif command[1] == "findtime": elif command[1] == "findtime":
return self.__server.getFindTime(name) return self.__server.getFindTime(name)
elif command[1] == "datepattern":
return self.__server.getDatePattern(name)
elif command[1] == "maxretry": elif command[1] == "maxretry":
return self.__server.getMaxRetry(name) return self.__server.getMaxRetry(name)
elif command[1] == "maxlines": elif command[1] == "maxlines":

View File

@ -201,6 +201,7 @@ class FilterReaderTest(unittest.TestCase):
"_COMM=sshd", "+", "_SYSTEMD_UNIT=sshd.service", "_UID=0"], "_COMM=sshd", "+", "_SYSTEMD_UNIT=sshd.service", "_UID=0"],
['set', 'testcase01', 'addjournalmatch', ['set', 'testcase01', 'addjournalmatch',
"FIELD= with spaces ", "+", "AFIELD= with + char and spaces"], "FIELD= with spaces ", "+", "AFIELD= with + char and spaces"],
['set', 'testcase01', 'datepattern', "%Y %m %d %H:%M:%S"],
['set', 'testcase01', 'maxlines', "1"], # Last for overide test ['set', 'testcase01', 'maxlines', "1"], # Last for overide test
] ]
filterReader = FilterReader("testcase01", "testcase01", {}) filterReader = FilterReader("testcase01", "testcase01", {})

View File

@ -104,7 +104,7 @@ class DateDetectorTest(unittest.TestCase):
self.assertEqual(old_name, n.getName()) # "Sort must be stable" self.assertEqual(old_name, n.getName()) # "Sort must be stable"
def testAllUniqueTemplateNames(self): def testAllUniqueTemplateNames(self):
self.assertRaises(ValueError, self.__datedetector._appendTemplate, self.assertRaises(ValueError, self.__datedetector.appendTemplate,
self.__datedetector.getTemplates()[0]) self.__datedetector.getTemplates()[0])
def testFullYearMatch_gh130(self): def testFullYearMatch_gh130(self):

View File

@ -37,6 +37,12 @@ ignoreregex = ^.+ john from host 192.168.1.1\s*$
# "maxlines" is number of log lines to buffer for multi-line regex searches # "maxlines" is number of log lines to buffer for multi-line regex searches
maxlines = 1 maxlines = 1
# "datepattern" allows setting of a custom data pattern as alternative
# to the default date detectors. See manpage strptime(3) for date formats.
# NOTE: that ALL '%' must be prefixed with '%' due to string substitution
# e.g. %%Y-%%m-%%d %%H:%%M
datepattern = %%Y %%m %%d %%H:%%M:%%S
# Option: journalmatch # Option: journalmatch
# Notes.: systemd journalctl style match filter for journal based backends # Notes.: systemd journalctl style match filter for journal based backends
# Values: TEXT # Values: TEXT

View File

@ -3,5 +3,5 @@
[Sat Jun 01 02:17:42 2013] [error] [client 192.168.33.1] File does not exist: /srv/http/site/[client 192.168.0.1] user root not found [Sat Jun 01 02:17:42 2013] [error] [client 192.168.33.1] File does not exist: /srv/http/site/[client 192.168.0.1] user root not found
# should match # should match
# failJSON: { "time": "2005-06-01T02:17:42", "match": true , "host": "192.168.0.2" } # failJSON: { "time": "2013-06-01T02:17:42", "match": true , "host": "192.168.0.2" }
[Sat Jun 01 02:17:42 2013] [error] [client 192.168.0.2] user root not found [Sat Jun 01 02:17:42 2013] [error] [client 192.168.0.2] user root not found

View File

@ -1,5 +1,5 @@
# Apache 2.2 # Apache 2.2
# failJSON: { "time": "2005-06-01T11:23:08", "match": true , "host": "1.2.3.4" } # failJSON: { "time": "2013-06-01T11:23:08", "match": true , "host": "1.2.3.4" }
[Sat Jun 01 11:23:08 2013] [error] [client 1.2.3.4] File does not exist: /xxx/~ [Sat Jun 01 11:23:08 2013] [error] [client 1.2.3.4] File does not exist: /xxx/~
# Apache 2.4 # Apache 2.4
# failJSON: { "time": "2005-06-27T11:55:44", "match": true , "host": "192.0.2.12" } # failJSON: { "time": "2005-06-27T11:55:44", "match": true , "host": "192.0.2.12" }

View File

@ -1,2 +1,2 @@
# failJSON: { "time": "2005-06-09T07:57:47", "match": true , "host": "192.0.43.10" } # failJSON: { "time": "2013-06-09T07:57:47", "match": true , "host": "192.0.43.10" }
[Sun Jun 09 07:57:47 2013] [error] [client 192.0.43.10] script '/usr/lib/cgi-bin/gitweb.cgiwp-login.php' not found or unable to stat [Sun Jun 09 07:57:47 2013] [error] [client 192.0.43.10] script '/usr/lib/cgi-bin/gitweb.cgiwp-login.php' not found or unable to stat

View File

@ -1,4 +1,4 @@
# failJSON: { "time": "2005-03-16T15:39:29", "match": true , "host": "58.179.109.179" } # failJSON: { "time": "2010-03-16T15:39:29", "match": true , "host": "58.179.109.179" }
[Tue Mar 16 15:39:29 2010] [error] [client 58.179.109.179] Invalid URI in request \xf9h\xa9\xf3\x88\x8cXKj \xbf-l*4\x87n\xe4\xfe\xd4\x1d\x06\x8c\xf8m\\rS\xf6n\xeb\x8 [Tue Mar 16 15:39:29 2010] [error] [client 58.179.109.179] Invalid URI in request \xf9h\xa9\xf3\x88\x8cXKj \xbf-l*4\x87n\xe4\xfe\xd4\x1d\x06\x8c\xf8m\\rS\xf6n\xeb\x8
# failJSON: { "time": "2005-03-15T15:44:47", "match": true , "host": "121.222.2.133" } # failJSON: { "time": "2010-03-15T15:44:47", "match": true , "host": "121.222.2.133" }
[Mon Mar 15 15:44:47 2010] [error] [client 121.222.2.133] Invalid URI in request n\xed*\xbe*\xab\xefd\x80\xb5\xae\xf6\x01\x10M?\xf2\xce\x13\x9c\xd7\xa0N\xa7\xdb%0\xde\xe0\xfc\xd2\xa0\xfe\xe9w\xee\xc4`v\x9b[{\x0c:\xcb\x93\xc6\xa0\x93\x9c`l\\\x8d\xc9 [Mon Mar 15 15:44:47 2010] [error] [client 121.222.2.133] Invalid URI in request n\xed*\xbe*\xab\xefd\x80\xb5\xae\xf6\x01\x10M?\xf2\xce\x13\x9c\xd7\xa0N\xa7\xdb%0\xde\xe0\xfc\xd2\xa0\xfe\xe9w\xee\xc4`v\x9b[{\x0c:\xcb\x93\xc6\xa0\x93\x9c`l\\\x8d\xc9

View File

@ -5,6 +5,6 @@ Oct 11 01:06:47 ServerJV vsftpd: (pam_unix) authentication failure; logname= uid
Feb 6 12:02:29 server vsftpd(pam_unix)[15522]: authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=64.168.103.1 user=user1 Feb 6 12:02:29 server vsftpd(pam_unix)[15522]: authentication failure; logname= uid=0 euid=0 tty= ruser= rhost=64.168.103.1 user=user1
#2 Internal #2 Internal
# failJSON: { "time": "2005-01-19T12:20:33", "match": true , "host": "64.106.46.98" } # failJSON: { "time": "2007-01-19T12:20:33", "match": true , "host": "64.106.46.98" }
Fri Jan 19 12:20:33 2007 [pid 27202] [anonymous] FAIL LOGIN: Client "64.106.46.98" Fri Jan 19 12:20:33 2007 [pid 27202] [anonymous] FAIL LOGIN: Client "64.106.46.98"

View File

@ -235,6 +235,12 @@ class Transmitter(TransmitterBase):
self.setGetTest("bantime", "-50", -50, jail=self.jailName) self.setGetTest("bantime", "-50", -50, jail=self.jailName)
self.setGetTestNOK("bantime", "Cat", jail=self.jailName) self.setGetTestNOK("bantime", "Cat", jail=self.jailName)
def testDatePattern(self):
self.setGetTest("datepattern", "%%%Y%m%d%H%M%S",
("%%%Y%m%d%H%M%S", "%YearMonthDay24hourMinuteSecond"),
jail=self.jailName)
self.setGetTestNOK("datepattern", "%Cat%a%%%g", jail=self.jailName)
def testJailUseDNS(self): def testJailUseDNS(self):
self.setGetTest("usedns", "yes", jail=self.jailName) self.setGetTest("usedns", "yes", jail=self.jailName)
self.setGetTest("usedns", "warn", jail=self.jailName) self.setGetTest("usedns", "warn", jail=self.jailName)