- Fixed fail2ban-regex. It support "includes" in configuration files.

- Modified "includes" to be more generic. We will probably support URL in the future.
- Small refactoring.

git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/branches/FAIL2BAN-0_8@656 a942ae1a-1317-0410-a47c-b1dcaea8d605
_tent/ipv6_via_aInfo
Cyril Jaquier 17 years ago
parent 6779814d91
commit 174ce7027a

@ -15,6 +15,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Author: Yaroslav Halchenko
# Modified: Cyril Jaquier
# $Revision$
__author__ = 'Yaroslav Halhenko'
@ -23,8 +24,11 @@ __date__ = '$Date: $'
__copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko'
__license__ = 'GPL'
import logging, os
from ConfigParser import SafeConfigParser
from ConfigParser import NoOptionError, NoSectionError
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client.config")
class SafeConfigParserWithIncludes(SafeConfigParser):
"""
@ -38,10 +42,10 @@ class SafeConfigParserWithIncludes(SafeConfigParser):
Example:
[INCLUDES]
files_before = 1.conf
before = 1.conf
3.conf
files_after = 1.conf
after = 1.conf
It is a simple implementation, so just basic care is taken about
recursion. Includes preserve right order, ie new files are
@ -55,35 +59,42 @@ files_after = 1.conf
"""
SECTION_NAME = "INCLUDES"
#@staticmethod
def getIncludedFiles(filename, sectionName='INCLUDES',
defaults={}, seen=[]):
def getIncludes(resource, seen = []):
"""
Given 1 config filename returns list of included files
Given 1 config resource returns list of included files
(recursively) with the original one as well
Simple loops are taken care about
"""
filenames = []
#print "Opening file " + filename
d = defaults.copy() # so that we do not poison our defaults
parser = SafeConfigParser(defaults = d)
parser.read(filename)
newFiles = [ ('files_before', []), ('files_after', []) ]
if sectionName in parser.sections():
# Use a short class name ;)
SCPWI = SafeConfigParserWithIncludes
parser = SafeConfigParser()
parser.read(resource)
resourceDir = os.path.dirname(resource)
newFiles = [ ('before', []), ('after', []) ]
if SCPWI.SECTION_NAME in parser.sections():
for option_name, option_list in newFiles:
if option_name in parser.options(sectionName):
newFileNames = parser.get(sectionName, option_name)
for newFileName in newFileNames.split('\n'):
if newFileName in seen: continue
option_list += SafeConfigParserWithIncludes.\
getIncludedFiles(newFileName,
defaults=defaults,
seen=seen + [filename])
if option_name in parser.options(SCPWI.SECTION_NAME):
newResources = parser.get(SCPWI.SECTION_NAME, option_name)
for newResource in newResources.split('\n'):
if os.path.isabs(newResource):
r = newResource
else:
r = "%s/%s" % (resourceDir, newResource)
if r in seen:
continue
s = seen + [resource]
option_list += SCPWI.getIncludes(r, s)
# combine lists
filenames = newFiles[0][1] + [filename] + newFiles[1][1]
#print "Includes list for " + filename + " is " + `filenames`
return filenames
getIncludedFiles = staticmethod(getIncludedFiles)
return newFiles[0][1] + [resource] + newFiles[1][1]
#print "Includes list for " + resource + " is " + `resources`
getIncludes = staticmethod(getIncludes)
def read(self, filenames):
@ -91,8 +102,7 @@ files_after = 1.conf
if not isinstance(filenames, list):
filenames = [ filenames ]
for filename in filenames:
fileNamesFull += SafeConfigParserWithIncludes.\
getIncludedFiles(filename, defaults=self._defaults)
#print "Opening config files " + `fileNamesFull`
fileNamesFull += SafeConfigParserWithIncludes.getIncludes(filename)
logSys.debug("Reading files: %s" % fileNamesFull)
return SafeConfigParser.read(self, fileNamesFull)

@ -36,9 +36,7 @@ class ConfigReader(SafeConfigParserWithIncludes):
BASE_DIRECTORY = "/etc/fail2ban/"
def __init__(self):
SafeConfigParserWithIncludes.__init__(self,
{'configpath' : \
ConfigReader.BASE_DIRECTORY} )
SafeConfigParserWithIncludes.__init__(self)
self.__opts = None
#@staticmethod

@ -9,7 +9,7 @@
[INCLUDES]
# Load customizations if any available
files_after = %(configpath)s/filter.d/common.local
after = common.local
[DEFAULT]

@ -9,7 +9,7 @@
# Read common prefixes. If any customizations available -- read them from
# common.local
files_before = %(configpath)s/filter.d/common.conf
before = common.conf
[Definition]

@ -222,7 +222,7 @@ class Fail2banRegex:
try:
self.__filter.addFailRegex(regex.getFailRegex())
try:
ret = self.__filter.findFailure(line)
ret = self.__filter.processLine(line)
if not len(ret) == 0:
if found == True:
ret[0].append(True)

@ -235,9 +235,6 @@ class Filter(JailThread):
def processLine(self, line):
if not self._isActive():
# The jail has been stopped
return
try:
# Decode line to UTF-8
l = line.decode('utf-8')
@ -246,25 +243,27 @@ class Filter(JailThread):
timeMatch = self.dateDetector.matchTime(l)
if not timeMatch:
# There is no valid time in this line
return
return []
# Lets split into time part and log part of the line
timeLine = timeMatch.group()
# Lets leave the beginning in as well, so if there is no
# anchore at the beginning of the time regexp, we don't
# at least allow injection. Should be harmless otherwise
logLine = l[:timeMatch.start()] + l[timeMatch.end():]
for element in self.findFailure(timeLine, logLine):
return self.findFailure(timeLine, logLine)
def processLineAndAdd(self, line):
for element in self.processLine(line):
ip = element[0]
unixTime = element[1]
if unixTime < MyTime.time() - self.__findTime:
if unixTime < MyTime.time() - self.getFindTime():
break
if self.inIgnoreIPList(ip):
logSys.debug("Ignore "+ip)
logSys.debug("Ignore %s" % ip)
continue
logSys.debug("Found "+ip)
logSys.debug("Found %s" % ip)
self.failManager.addFailure(FailTicket(ip, unixTime))
##
# Returns true if the line should be ignored.
#
@ -409,32 +408,7 @@ class FileFilter(Filter):
if not self._isActive():
# The jail has been stopped
break
try:
# Decode line to UTF-8
line = line.decode('utf-8')
except UnicodeDecodeError:
pass
timeMatch = self.dateDetector.matchTime(line)
if not timeMatch:
# There is no valid time in this line
line = container.readline()
continue
# Lets split into time part and log part of the line
timeLine = timeMatch.group()
# Lets leave the beginning in as well, so if there is no
# anchore at the beginning of the time regexp, we don't
# at least allow injection. Should be harmless otherwise
logLine = line[:timeMatch.start()] + line[timeMatch.end():]
for element in self.findFailure(timeLine, logLine):
ip = element[0]
unixTime = element[1]
if unixTime < MyTime.time() - self.getFindTime():
break
if self.inIgnoreIPList(ip):
logSys.debug("Ignore "+ip)
continue
logSys.debug("Found "+ip)
self.failManager.addFailure(FailTicket(ip, unixTime))
self.processLineAndAdd(line)
# Read a new line.
line = container.readline()
container.close()

Loading…
Cancel
Save