mirror of https://github.com/fail2ban/fail2ban
Merge branch '0.10' into 0.11
commit
b2036c1d62
|
@ -29,7 +29,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
from ..helpers import getLogger
|
from ..helpers import getLogger
|
||||||
|
|
||||||
if sys.version_info >= (3,2):
|
if sys.version_info >= (3,): # pragma: 2.x no cover
|
||||||
|
|
||||||
# SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
|
# SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
|
||||||
from configparser import ConfigParser as SafeConfigParser, BasicInterpolation, \
|
from configparser import ConfigParser as SafeConfigParser, BasicInterpolation, \
|
||||||
|
@ -61,7 +61,7 @@ if sys.version_info >= (3,2):
|
||||||
return super(BasicInterpolationWithName, self)._interpolate_some(
|
return super(BasicInterpolationWithName, self)._interpolate_some(
|
||||||
parser, option, accum, rest, section, map, *args, **kwargs)
|
parser, option, accum, rest, section, map, *args, **kwargs)
|
||||||
|
|
||||||
else: # pragma: no cover
|
else: # pragma: 3.x no cover
|
||||||
from ConfigParser import SafeConfigParser, \
|
from ConfigParser import SafeConfigParser, \
|
||||||
InterpolationMissingOptionError, NoOptionError, NoSectionError
|
InterpolationMissingOptionError, NoOptionError, NoSectionError
|
||||||
|
|
||||||
|
@ -372,7 +372,8 @@ after = 1.conf
|
||||||
s2 = alls.get(n)
|
s2 = alls.get(n)
|
||||||
if isinstance(s2, dict):
|
if isinstance(s2, dict):
|
||||||
# save previous known values, for possible using in local interpolations later:
|
# save previous known values, for possible using in local interpolations later:
|
||||||
self.merge_section('KNOWN/'+n, s2, '')
|
self.merge_section('KNOWN/'+n,
|
||||||
|
dict(filter(lambda i: i[0] in s, s2.iteritems())), '')
|
||||||
# merge section
|
# merge section
|
||||||
s2.update(s)
|
s2.update(s)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -398,8 +398,8 @@ def splitWithOptions(option):
|
||||||
# tags (<tag>) in tagged options.
|
# tags (<tag>) in tagged options.
|
||||||
#
|
#
|
||||||
|
|
||||||
# max tag replacement count:
|
# max tag replacement count (considering tag X in tag Y repeat):
|
||||||
MAX_TAG_REPLACE_COUNT = 10
|
MAX_TAG_REPLACE_COUNT = 25
|
||||||
|
|
||||||
# compiled RE for tag name (replacement name)
|
# compiled RE for tag name (replacement name)
|
||||||
TAG_CRE = re.compile(r'<([^ <>]+)>')
|
TAG_CRE = re.compile(r'<([^ <>]+)>')
|
||||||
|
@ -433,6 +433,7 @@ def substituteRecursiveTags(inptags, conditional='',
|
||||||
done = set()
|
done = set()
|
||||||
noRecRepl = hasattr(tags, "getRawItem")
|
noRecRepl = hasattr(tags, "getRawItem")
|
||||||
# repeat substitution while embedded-recursive (repFlag is True)
|
# repeat substitution while embedded-recursive (repFlag is True)
|
||||||
|
repCounts = {}
|
||||||
while True:
|
while True:
|
||||||
repFlag = False
|
repFlag = False
|
||||||
# substitute each value:
|
# substitute each value:
|
||||||
|
@ -444,7 +445,7 @@ def substituteRecursiveTags(inptags, conditional='',
|
||||||
value = orgval = uni_string(tags[tag])
|
value = orgval = uni_string(tags[tag])
|
||||||
# search and replace all tags within value, that can be interpolated using other tags:
|
# search and replace all tags within value, that can be interpolated using other tags:
|
||||||
m = tre_search(value)
|
m = tre_search(value)
|
||||||
refCounts = {}
|
rplc = repCounts.get(tag, {})
|
||||||
#logSys.log(5, 'TAG: %s, value: %s' % (tag, value))
|
#logSys.log(5, 'TAG: %s, value: %s' % (tag, value))
|
||||||
while m:
|
while m:
|
||||||
# found replacement tag:
|
# found replacement tag:
|
||||||
|
@ -454,13 +455,13 @@ def substituteRecursiveTags(inptags, conditional='',
|
||||||
m = tre_search(value, m.end())
|
m = tre_search(value, m.end())
|
||||||
continue
|
continue
|
||||||
#logSys.log(5, 'found: %s' % rtag)
|
#logSys.log(5, 'found: %s' % rtag)
|
||||||
if rtag == tag or refCounts.get(rtag, 1) > MAX_TAG_REPLACE_COUNT:
|
if rtag == tag or rplc.get(rtag, 1) > MAX_TAG_REPLACE_COUNT:
|
||||||
# recursive definitions are bad
|
# recursive definitions are bad
|
||||||
#logSys.log(5, 'recursion fail tag: %s value: %s' % (tag, value) )
|
#logSys.log(5, 'recursion fail tag: %s value: %s' % (tag, value) )
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"properties contain self referencing definitions "
|
"properties contain self referencing definitions "
|
||||||
"and cannot be resolved, fail tag: %s, found: %s in %s, value: %s" %
|
"and cannot be resolved, fail tag: %s, found: %s in %s, value: %s" %
|
||||||
(tag, rtag, refCounts, value))
|
(tag, rtag, rplc, value))
|
||||||
repl = None
|
repl = None
|
||||||
if conditional:
|
if conditional:
|
||||||
repl = tags.get(rtag + '?' + conditional)
|
repl = tags.get(rtag + '?' + conditional)
|
||||||
|
@ -480,7 +481,7 @@ def substituteRecursiveTags(inptags, conditional='',
|
||||||
value = value.replace('<%s>' % rtag, repl)
|
value = value.replace('<%s>' % rtag, repl)
|
||||||
#logSys.log(5, 'value now: %s' % value)
|
#logSys.log(5, 'value now: %s' % value)
|
||||||
# increment reference count:
|
# increment reference count:
|
||||||
refCounts[rtag] = refCounts.get(rtag, 0) + 1
|
rplc[rtag] = rplc.get(rtag, 0) + 1
|
||||||
# the next match for replace:
|
# the next match for replace:
|
||||||
m = tre_search(value, m.start())
|
m = tre_search(value, m.start())
|
||||||
#logSys.log(5, 'TAG: %s, newvalue: %s' % (tag, value))
|
#logSys.log(5, 'TAG: %s, newvalue: %s' % (tag, value))
|
||||||
|
@ -488,6 +489,7 @@ def substituteRecursiveTags(inptags, conditional='',
|
||||||
if orgval != value:
|
if orgval != value:
|
||||||
# check still contains any tag - should be repeated (possible embedded-recursive substitution):
|
# check still contains any tag - should be repeated (possible embedded-recursive substitution):
|
||||||
if tre_search(value):
|
if tre_search(value):
|
||||||
|
repCounts[tag] = rplc
|
||||||
repFlag = True
|
repFlag = True
|
||||||
# copy return tags dict to prevent modifying of inptags:
|
# copy return tags dict to prevent modifying of inptags:
|
||||||
if id(tags) == id(inptags):
|
if id(tags) == id(inptags):
|
||||||
|
|
|
@ -252,7 +252,7 @@ class CommandActionTest(LogCaptureTestCase):
|
||||||
delattr(self.__action, 'ac')
|
delattr(self.__action, 'ac')
|
||||||
# produce self-referencing query except:
|
# produce self-referencing query except:
|
||||||
self.assertRaisesRegexp(ValueError, r"possible self referencing definitions in query",
|
self.assertRaisesRegexp(ValueError, r"possible self referencing definitions in query",
|
||||||
lambda: self.__action.replaceTag("<x<x<x<x<x<x<x<x<x<x<x<x<x<x<x<x<x<x<x<x<x>>>>>>>>>>>>>>>>>>>>>",
|
lambda: self.__action.replaceTag("<x"*30+">"*30,
|
||||||
self.__action._properties, conditional="family=inet6")
|
self.__action._properties, conditional="family=inet6")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -562,6 +562,17 @@ class FilterReaderTest(LogCaptureTestCase):
|
||||||
c = filterReader.convert()
|
c = filterReader.convert()
|
||||||
self.assertSortedEqual(c, output)
|
self.assertSortedEqual(c, output)
|
||||||
|
|
||||||
|
def testFilterReaderSubstKnown(self):
|
||||||
|
# testcase02.conf + testcase02.local, test covering that known/option is not overridden
|
||||||
|
# with unmodified (not available) value of option from .local config file, so wouldn't
|
||||||
|
# cause self-recursion if option already has a reference to known/option in .conf file.
|
||||||
|
filterReader = FilterReader('testcase02', "jailname", {},
|
||||||
|
share_config=TEST_FILES_DIR_SHARE_CFG, basedir=TEST_FILES_DIR)
|
||||||
|
filterReader.read()
|
||||||
|
filterReader.getOptions(None)
|
||||||
|
opts = filterReader.getCombined()
|
||||||
|
self.assertTrue('sshd' in opts['failregex'])
|
||||||
|
|
||||||
def testFilterReaderSubstitionSet(self):
|
def testFilterReaderSubstitionSet(self):
|
||||||
output = [['set', 'jailname', 'addfailregex', 'to=sour@example.com fromip=<IP>']]
|
output = [['set', 'jailname', 'addfailregex', 'to=sour@example.com fromip=<IP>']]
|
||||||
filterReader = FilterReader('substition', "jailname", {'honeypot': 'sour@example.com'},
|
filterReader = FilterReader('substition', "jailname", {'honeypot': 'sour@example.com'},
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
[INCLUDES]
|
||||||
|
|
||||||
|
# Read common prefixes. If any customizations available -- read them from
|
||||||
|
# common.local
|
||||||
|
before = testcase-common.conf
|
||||||
|
|
||||||
|
[Definition]
|
||||||
|
|
||||||
|
_daemon = sshd
|
||||||
|
__prefix_line = %(known/__prefix_line)s(?:\w{14,20}: )?
|
||||||
|
|
||||||
|
failregex = %(__prefix_line)s test
|
|
@ -0,0 +1,4 @@
|
||||||
|
[Definition]
|
||||||
|
|
||||||
|
# no options here, coverage for testFilterReaderSubstKnown:
|
||||||
|
# avoid to overwrite known/option with unmodified (not available) value of option from .local config file
|
Loading…
Reference in New Issue