mirror of https://github.com/fail2ban/fail2ban
fixes default backend handling (as default used value of `known/backend`, which can now be overridden in default section of jail.local);
introduces fallback for `known/option`: interpolate missing `known/option` as `option` from default sectionpull/1750/head
parent
51c54b3253
commit
5ce8d4f741
|
@ -7,7 +7,7 @@ after = paths-overrides.local
|
||||||
|
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
|
|
||||||
default_backend = auto
|
default_backend = %(known/backend)s
|
||||||
|
|
||||||
sshd_log = %(syslog_authpriv)s
|
sshd_log = %(syslog_authpriv)s
|
||||||
sshd_backend = %(default_backend)s
|
sshd_backend = %(default_backend)s
|
||||||
|
|
|
@ -32,8 +32,8 @@ from ..helpers import getLogger
|
||||||
if sys.version_info >= (3,2):
|
if sys.version_info >= (3,2):
|
||||||
|
|
||||||
# SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
|
# SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
|
||||||
from configparser import ConfigParser as SafeConfigParser, NoSectionError, \
|
from configparser import ConfigParser as SafeConfigParser, BasicInterpolation, \
|
||||||
BasicInterpolation
|
InterpolationMissingOptionError, NoSectionError
|
||||||
|
|
||||||
# And interpolation of __name__ was simply removed, thus we need to
|
# And interpolation of __name__ was simply removed, thus we need to
|
||||||
# decorate default interpolator to handle it
|
# decorate default interpolator to handle it
|
||||||
|
@ -52,20 +52,43 @@ if sys.version_info >= (3,2):
|
||||||
But should be fine to reincarnate for our use case
|
But should be fine to reincarnate for our use case
|
||||||
"""
|
"""
|
||||||
def _interpolate_some(self, parser, option, accum, rest, section, map,
|
def _interpolate_some(self, parser, option, accum, rest, section, map,
|
||||||
depth):
|
*args, **kwargs):
|
||||||
if section and not (__name__ in map):
|
if section and not (__name__ in map):
|
||||||
map = map.copy() # just to be safe
|
map = map.copy() # just to be safe
|
||||||
map['__name__'] = section
|
map['__name__'] = section
|
||||||
return super(BasicInterpolationWithName, self)._interpolate_some(
|
try:
|
||||||
parser, option, accum, rest, section, map, depth)
|
return super(BasicInterpolationWithName, self)._interpolate_some(
|
||||||
|
parser, option, accum, rest, section, map, *args, **kwargs)
|
||||||
|
except InterpolationMissingOptionError as e:
|
||||||
|
# fallback: try to wrap missing default options as "known/options":
|
||||||
|
if not parser._map_known_defaults(section, option, rest, map): # pragma: no cover
|
||||||
|
raise e
|
||||||
|
# try again:
|
||||||
|
return super(BasicInterpolationWithName, self)._interpolate_some(
|
||||||
|
parser, option, accum, rest, section, map, *args, **kwargs)
|
||||||
|
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
from ConfigParser import SafeConfigParser, NoSectionError
|
from ConfigParser import SafeConfigParser, \
|
||||||
|
InterpolationMissingOptionError, NoSectionError
|
||||||
|
|
||||||
|
# Interpolate missing known/option as option from default section
|
||||||
|
SafeConfigParser._cp_interpolate_some = SafeConfigParser._interpolate_some
|
||||||
|
def _interpolate_some(self, option, accum, rest, section, map, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
return self._cp_interpolate_some(option, accum, rest, section, map, *args, **kwargs)
|
||||||
|
except InterpolationMissingOptionError as e:
|
||||||
|
# fallback: try to wrap missing default options as "known/options":
|
||||||
|
if self._map_known_defaults(section, option, rest, map): # pragma: no cover
|
||||||
|
raise e
|
||||||
|
# try again:
|
||||||
|
return self._cp_interpolate_some(option, accum, rest, section, map, *args, **kwargs)
|
||||||
|
SafeConfigParser._interpolate_some = _interpolate_some
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
# Gets the instance of the logger.
|
||||||
logSys = getLogger(__name__)
|
logSys = getLogger(__name__)
|
||||||
logLevel = 7
|
logLevel = 7
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['SafeConfigParserWithIncludes']
|
__all__ = ['SafeConfigParserWithIncludes']
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,6 +123,8 @@ after = 1.conf
|
||||||
|
|
||||||
SECTION_NAME = "INCLUDES"
|
SECTION_NAME = "INCLUDES"
|
||||||
|
|
||||||
|
_KNOWN_OPTSUBST_CRE = re.compile(r'%\(known/([^\)]+)\)s')
|
||||||
|
|
||||||
CONDITIONAL_RE = re.compile(r"^(\w+)(\?.+)$")
|
CONDITIONAL_RE = re.compile(r"^(\w+)(\?.+)$")
|
||||||
|
|
||||||
if sys.version_info >= (3,2):
|
if sys.version_info >= (3,2):
|
||||||
|
@ -117,6 +142,25 @@ after = 1.conf
|
||||||
SafeConfigParser.__init__(self, *args, **kwargs)
|
SafeConfigParser.__init__(self, *args, **kwargs)
|
||||||
self._cfg_share = share_config
|
self._cfg_share = share_config
|
||||||
|
|
||||||
|
def _map_known_defaults(self, section, option, rest, map):
|
||||||
|
""" Fallback: try to wrap missing default options as "known/options"
|
||||||
|
"""
|
||||||
|
known = SafeConfigParserWithIncludes._KNOWN_OPTSUBST_CRE.findall(rest)
|
||||||
|
if not known: # pragma: no cover
|
||||||
|
return 0
|
||||||
|
for opt in known:
|
||||||
|
kopt = 'known/'+opt
|
||||||
|
if kopt not in map:
|
||||||
|
try:
|
||||||
|
v = self._defaults[opt]
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
self._defaults[kopt] = v
|
||||||
|
try: # for python 2.6 we should duplicate it in map-vars also:
|
||||||
|
map[kopt] = v
|
||||||
|
except: pass
|
||||||
|
return 1
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def share_config(self):
|
def share_config(self):
|
||||||
return self._cfg_share
|
return self._cfg_share
|
||||||
|
|
Loading…
Reference in New Issue