Files
fail2ban/server/datedetector.py
Yaroslav Halchenko 2b6366656f BF: make sorting of date templates stable
Before, it would first do stable sort followed with explicit reverse.
Now reverse is given as an argument to sort, and it results in actually
preserving the order in case of e.g. no sorting needed
2012-12-11 11:18:52 -05:00

202 lines
6.7 KiB
Python

# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
# vi: set ft=python sts=4 ts=4 sw=4 noet :
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# Author: Cyril Jaquier
#
# $Revision$
__author__ = "Cyril Jaquier"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import time, logging
from datetemplate import DateStrptime, DateTai64n, DateEpoch, DateISO8601
from threading import Lock
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter.datedetector")
class DateDetector:
def __init__(self):
self.__lock = Lock()
self.__templates = list()
def addDefaultTemplate(self):
self.__lock.acquire()
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.__templates.append(template)
# asctime
template = DateStrptime()
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.__templates.append(template)
# asctime without year
template = DateStrptime()
template.setName("WEEKDAY MONTH Day Hour:Minute:Second")
template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
template.setPattern("%a %b %d %H:%M:%S")
self.__templates.append(template)
# simple date
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.__templates.append(template)
# simple date too (from x11vnc)
template = DateStrptime()
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.__templates.append(template)
# previous one but with year given by 2 digits
# (See http://bugs.debian.org/537610)
template = DateStrptime()
template.setName("Day/Month/Year 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.__templates.append(template)
# Apache format [31/Oct/2006:09:22:55 -0000]
template = DateStrptime()
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.__templates.append(template)
# CPanel 05/20/2008:01:57:39
template = DateStrptime()
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.__templates.append(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.__templates.append(template)
# custom for syslog-ng 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.__templates.append(template)
# named 26-Jul-2007 15:20:52.252
template = DateStrptime()
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.__templates.append(template)
# 17-07-2008 17:23:25
template = DateStrptime()
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.__templates.append(template)
# 01-27-2012 16:22:44.252
template = DateStrptime()
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.__templates.append(template)
# TAI64N
template = DateTai64n()
template.setName("TAI64N")
self.__templates.append(template)
# Epoch
template = DateEpoch()
template.setName("Epoch")
self.__templates.append(template)
# ISO 8601
template = DateISO8601()
template.setName("ISO 8601")
self.__templates.append(template)
# Only time information in the log
template = DateStrptime()
template.setName("Hour:Minute:Second")
template.setRegex("^\d{2}:\d{2}:\d{2}")
template.setPattern("%H:%M:%S")
self.__templates.append(template)
# <09/16/08@05:03:30>
template = DateStrptime()
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.__templates.append(template)
finally:
self.__lock.release()
def getTemplates(self):
return self.__templates
def matchTime(self, line):
self.__lock.acquire()
try:
for template in self.__templates:
match = template.matchDate(line)
if not match == None:
return match
return None
finally:
self.__lock.release()
def getTime(self, line):
self.__lock.acquire()
try:
for template in self.__templates:
try:
date = template.getDate(line)
if date == None:
continue
return date
except ValueError:
pass
return None
finally:
self.__lock.release()
def getUnixTime(self, line):
date = self.getTime(line)
if date == None:
return None
else:
return time.mktime(date)
##
# Sort the template lists using the hits score. This method is not called
# in this object and thus should be called from time to time.
def sortTemplate(self):
self.__lock.acquire()
try:
logSys.debug("Sorting the template list")
self.__templates.sort(lambda x, y: cmp(x.getHits(), y.getHits()), reverse=True)
t = self.__templates[0]
logSys.debug("Winning template: %s with %d hits" % (t.getName(), t.getHits()))
finally:
self.__lock.release()