mirror of https://github.com/fail2ban/fail2ban
- Added new prefix remover.
- Added ISO 8601 date/time format. git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@694 a942ae1a-1317-0410-a47c-b1dcaea8d6050.x
parent
419005fd1f
commit
f9a9d249ef
29
COPYING
29
COPYING
|
@ -1,3 +1,7 @@
|
||||||
|
The following copyright applies to all files present in the Fail2ban package,
|
||||||
|
except if a different copyright is explicitly defined in this file.
|
||||||
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 2, June 1991
|
Version 2, June 1991
|
||||||
|
|
||||||
|
@ -337,3 +341,28 @@ proprietary programs. If your program is a subroutine library, you may
|
||||||
consider it more useful to permit linking proprietary applications with the
|
consider it more useful to permit linking proprietary applications with the
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License.
|
Public License instead of this License.
|
||||||
|
|
||||||
|
---------------------------------
|
||||||
|
The file server/iso8601.py is licensed under the following terms.
|
||||||
|
|
||||||
|
|
||||||
|
Copyright (c) 2007 Michael Twomey
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
|
@ -9,6 +9,8 @@ Fail2Ban (version 0.9.0) 2008/??/??
|
||||||
|
|
||||||
ver. 0.9.0 (2008/??/??) - alpha
|
ver. 0.9.0 (2008/??/??) - alpha
|
||||||
----------
|
----------
|
||||||
|
- Added new prefix remover.
|
||||||
|
- Added ISO 8601 date/time format.
|
||||||
|
|
||||||
ver. 0.8.3 (2008/??/??) - stable
|
ver. 0.8.3 (2008/??/??) - stable
|
||||||
----------
|
----------
|
||||||
|
|
2
MANIFEST
2
MANIFEST
|
@ -22,6 +22,7 @@ server/filter.py
|
||||||
server/filtergamin.py
|
server/filtergamin.py
|
||||||
server/filterpoll.py
|
server/filterpoll.py
|
||||||
server/server.py
|
server/server.py
|
||||||
|
server/iso8601.py
|
||||||
server/actions.py
|
server/actions.py
|
||||||
server/faildata.py
|
server/faildata.py
|
||||||
server/failmanager.py
|
server/failmanager.py
|
||||||
|
@ -44,7 +45,6 @@ testcases/failmanagertestcase.py
|
||||||
testcases/clientreadertestcase.py
|
testcases/clientreadertestcase.py
|
||||||
testcases/filtertestcase.py
|
testcases/filtertestcase.py
|
||||||
testcases/__init__.py
|
testcases/__init__.py
|
||||||
testcases/datedetectortestcase.py
|
|
||||||
testcases/actiontestcase.py
|
testcases/actiontestcase.py
|
||||||
testcases/servertestcase.py
|
testcases/servertestcase.py
|
||||||
testcases/files/testcase01.log
|
testcases/files/testcase01.log
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
# Copyright (c) 2007 Michael Twomey
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
# copy of this software and associated documentation files (the
|
||||||
|
# "Software"), to deal in the Software without restriction, including
|
||||||
|
# without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
# permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
# the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included
|
||||||
|
# in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
"""ISO 8601 date time string parsing
|
||||||
|
|
||||||
|
Basic usage:
|
||||||
|
>>> import iso8601
|
||||||
|
>>> iso8601.parse_date("2007-01-25T12:00:00Z")
|
||||||
|
datetime.datetime(2007, 1, 25, 12, 0, tzinfo=<iso8601.iso8601.Utc ...>)
|
||||||
|
>>>
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from datetime import datetime, timedelta, tzinfo
|
||||||
|
import re
|
||||||
|
|
||||||
|
__all__ = ["parse_date", "ParseError"]
|
||||||
|
|
||||||
|
# Adapted from http://delete.me.uk/2005/03/iso8601.html
|
||||||
|
ISO8601_REGEX = re.compile(r"(?P<year>[0-9]{4})(-(?P<month>[0-9]{1,2})(-(?P<day>[0-9]{1,2})"
|
||||||
|
r"((?P<separator>.)(?P<hour>[0-9]{2}):(?P<minute>[0-9]{2})(:(?P<second>[0-9]{2})(\.(?P<fraction>[0-9]+))?)?"
|
||||||
|
r"(?P<timezone>Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"
|
||||||
|
)
|
||||||
|
TIMEZONE_REGEX = re.compile("(?P<prefix>[+-])(?P<hours>[0-9]{2}).(?P<minutes>[0-9]{2})")
|
||||||
|
|
||||||
|
class ParseError(Exception):
|
||||||
|
"""Raised when there is a problem parsing a date string"""
|
||||||
|
|
||||||
|
# Yoinked from python docs
|
||||||
|
ZERO = timedelta(0)
|
||||||
|
class Utc(tzinfo):
|
||||||
|
"""UTC
|
||||||
|
|
||||||
|
"""
|
||||||
|
def utcoffset(self, dt):
|
||||||
|
return ZERO
|
||||||
|
|
||||||
|
def tzname(self, dt):
|
||||||
|
return "UTC"
|
||||||
|
|
||||||
|
def dst(self, dt):
|
||||||
|
return ZERO
|
||||||
|
UTC = Utc()
|
||||||
|
|
||||||
|
class FixedOffset(tzinfo):
|
||||||
|
"""Fixed offset in hours and minutes from UTC
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, offset_hours, offset_minutes, name):
|
||||||
|
self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes)
|
||||||
|
self.__name = name
|
||||||
|
|
||||||
|
def utcoffset(self, dt):
|
||||||
|
return self.__offset
|
||||||
|
|
||||||
|
def tzname(self, dt):
|
||||||
|
return self.__name
|
||||||
|
|
||||||
|
def dst(self, dt):
|
||||||
|
return ZERO
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<FixedOffset %r>" % self.__name
|
||||||
|
|
||||||
|
def parse_timezone(tzstring, default_timezone=UTC):
|
||||||
|
"""Parses ISO 8601 time zone specs into tzinfo offsets
|
||||||
|
|
||||||
|
"""
|
||||||
|
if tzstring == "Z":
|
||||||
|
return default_timezone
|
||||||
|
# This isn't strictly correct, but it's common to encounter dates without
|
||||||
|
# timezones so I'll assume the default (which defaults to UTC).
|
||||||
|
# Addresses issue 4.
|
||||||
|
if tzstring is None:
|
||||||
|
return default_timezone
|
||||||
|
m = TIMEZONE_REGEX.match(tzstring)
|
||||||
|
prefix, hours, minutes = m.groups()
|
||||||
|
hours, minutes = int(hours), int(minutes)
|
||||||
|
if prefix == "-":
|
||||||
|
hours = -hours
|
||||||
|
minutes = -minutes
|
||||||
|
return FixedOffset(hours, minutes, tzstring)
|
||||||
|
|
||||||
|
def parse_date(datestring, default_timezone=UTC):
|
||||||
|
"""Parses ISO 8601 dates into datetime objects
|
||||||
|
|
||||||
|
The timezone is parsed from the date string. However it is quite common to
|
||||||
|
have dates without a timezone (not strictly correct). In this case the
|
||||||
|
default timezone specified in default_timezone is used. This is UTC by
|
||||||
|
default.
|
||||||
|
"""
|
||||||
|
if not isinstance(datestring, basestring):
|
||||||
|
raise ParseError("Expecting a string %r" % datestring)
|
||||||
|
m = ISO8601_REGEX.match(datestring)
|
||||||
|
if not m:
|
||||||
|
raise ParseError("Unable to parse date string %r" % datestring)
|
||||||
|
groups = m.groupdict()
|
||||||
|
tz = parse_timezone(groups["timezone"], default_timezone=default_timezone)
|
||||||
|
if groups["fraction"] is None:
|
||||||
|
groups["fraction"] = 0
|
||||||
|
else:
|
||||||
|
groups["fraction"] = int(float("0.%s" % groups["fraction"]) * 1e6)
|
||||||
|
return datetime(int(groups["year"]), int(groups["month"]), int(groups["day"]),
|
||||||
|
int(groups["hour"]), int(groups["minute"]), int(groups["second"]),
|
||||||
|
int(groups["fraction"]), tz)
|
|
@ -25,11 +25,17 @@ __date__ = "$Date: 2008-01-16 23:55:04 +0100 (Wed, 16 Jan 2008) $"
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
import time
|
import time, logging
|
||||||
|
|
||||||
from template import Template, Templates
|
from template import Template, Templates
|
||||||
from mytime import MyTime
|
from mytime import MyTime
|
||||||
|
|
||||||
|
# Import ISO 8601 support.
|
||||||
|
import iso8601
|
||||||
|
|
||||||
|
# Gets the instance of the logger.
|
||||||
|
logSys = logging.getLogger("fail2ban.timetemplate")
|
||||||
|
|
||||||
class TimeTemplate(Template):
|
class TimeTemplate(Template):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -42,6 +48,20 @@ class TimeTemplate(Template):
|
||||||
raise Exception("getTime() is abstract")
|
raise Exception("getTime() is abstract")
|
||||||
|
|
||||||
|
|
||||||
|
class TimeISO8601(TimeTemplate):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
TimeTemplate.__init__(self)
|
||||||
|
date_re = "[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}" \
|
||||||
|
".[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?" \
|
||||||
|
"(Z|(([-+])([0-9]{2}):([0-9]{2})))?"
|
||||||
|
self.setRegex(date_re)
|
||||||
|
|
||||||
|
def getTime(self, line):
|
||||||
|
# Parses the date.
|
||||||
|
return list(iso8601.parse_date(line).utctimetuple())
|
||||||
|
|
||||||
|
|
||||||
class TimeEpoch(TimeTemplate):
|
class TimeEpoch(TimeTemplate):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -193,3 +213,7 @@ class TimeTemplates(Templates):
|
||||||
template = TimeEpoch()
|
template = TimeEpoch()
|
||||||
template.setDescription("Epoch")
|
template.setDescription("Epoch")
|
||||||
self.templates.append(template)
|
self.templates.append(template)
|
||||||
|
# ISO 8601
|
||||||
|
template = TimeISO8601()
|
||||||
|
template.setDescription("ISO 8601")
|
||||||
|
self.templates.append(template)
|
||||||
|
|
Loading…
Reference in New Issue