mirror of https://github.com/fail2ban/fail2ban
fail2ban-regex: loading parsing settings from jail now (by simple name it'd prefer jail to the filter now), fallback:
- fail2ban-regex ... sshd + fail2ban-regex ... filter.d/sshd closes gh-2655pull/3641/head
parent
7de1057f94
commit
781321d609
|
@ -51,7 +51,7 @@ except ImportError:
|
|||
FilterSystemd = None
|
||||
|
||||
from ..version import version, normVersion
|
||||
from .filterreader import FilterReader
|
||||
from .jailreader import FilterReader, JailReader, NoJailError
|
||||
from ..server.filter import Filter, FileContainer, MyTime
|
||||
from ..server.failregex import Regex, RegexException
|
||||
|
||||
|
@ -312,12 +312,18 @@ class Fail2banRegex(object):
|
|||
def _dumpRealOptions(self, reader, fltOpt):
|
||||
realopts = {}
|
||||
combopts = reader.getCombined()
|
||||
if isinstance(reader, FilterReader):
|
||||
_get_opt = lambda k: reader.get('Definition', k)
|
||||
elif reader.filter: # JailReader for jail with filter:
|
||||
_get_opt = lambda k: reader.filter.get('Definition', k)
|
||||
else: # JailReader for jail without filter:
|
||||
_get_opt = lambda k: None
|
||||
# output all options that are specified in filter-argument as well as some special (mostly interested):
|
||||
for k in ['logtype', 'datepattern'] + list(fltOpt.keys()):
|
||||
# combined options win, but they contain only a sub-set in filter expected keys,
|
||||
# so get the rest from definition section:
|
||||
try:
|
||||
realopts[k] = combopts[k] if k in combopts else reader.get('Definition', k)
|
||||
realopts[k] = combopts[k] if k in combopts else _get_opt(k)
|
||||
except NoOptionError: # pragma: no cover
|
||||
pass
|
||||
self.output("Real filter options : %r" % realopts)
|
||||
|
@ -330,16 +336,26 @@ class Fail2banRegex(object):
|
|||
fltName = value
|
||||
fltFile = None
|
||||
fltOpt = {}
|
||||
jail = None
|
||||
if regextype == 'fail':
|
||||
if re.search(r'(?ms)^/{0,3}[\w/_\-.]+(?:\[.*\])?$', value):
|
||||
try:
|
||||
fltName, fltOpt = extractOptions(value)
|
||||
if re.search(r'(?ms)^[\w/_\-]+$', fltName): # name of jail?
|
||||
try:
|
||||
jail = JailReader(fltName, force_enable=True,
|
||||
share_config=self.share_config)
|
||||
jail.read()
|
||||
except NoJailError:
|
||||
jail = None
|
||||
if "." in fltName[~5:]:
|
||||
tryNames = (fltName,)
|
||||
else:
|
||||
tryNames = (fltName, fltName + '.conf', fltName + '.local')
|
||||
for fltFile in tryNames:
|
||||
if not "/" in fltFile:
|
||||
if os.path.dirname(fltFile) == 'filter.d':
|
||||
fltFile = os.path.join(basedir, fltFile)
|
||||
elif not "/" in fltFile:
|
||||
if os.path.basename(basedir) == 'filter.d':
|
||||
fltFile = os.path.join(basedir, fltFile)
|
||||
else:
|
||||
|
@ -354,8 +370,25 @@ class Fail2banRegex(object):
|
|||
output(" while parsing: %s" % (value,))
|
||||
if self._verbose: raise(e)
|
||||
return False
|
||||
|
||||
readercommands = None
|
||||
# if it is jail:
|
||||
if jail:
|
||||
self.output( "Use %11s jail : %s" % ('', fltName) )
|
||||
if fltOpt:
|
||||
self.output( "Use jail/flt options : %r" % fltOpt )
|
||||
if not fltOpt: fltOpt = {}
|
||||
fltOpt['backend'] = self._backend
|
||||
ret = jail.getOptions(addOpts=fltOpt)
|
||||
if not ret:
|
||||
output('ERROR: Failed to get jail for %r' % (value,))
|
||||
return False
|
||||
# show real options if expected:
|
||||
if self._verbose > 1 or logSys.getEffectiveLevel()<=logging.DEBUG:
|
||||
self._dumpRealOptions(jail, fltOpt)
|
||||
readercommands = jail.convert(allow_no_files=True)
|
||||
# if it is filter file:
|
||||
if fltFile is not None:
|
||||
elif fltFile is not None:
|
||||
if (basedir == self._opts.config
|
||||
or os.path.basename(basedir) == 'filter.d'
|
||||
or ("." not in fltName[~5:] and "/" not in fltName)
|
||||
|
@ -364,10 +397,10 @@ class Fail2banRegex(object):
|
|||
if os.path.basename(basedir) == 'filter.d':
|
||||
basedir = os.path.dirname(basedir)
|
||||
fltName = os.path.splitext(os.path.basename(fltName))[0]
|
||||
self.output( "Use %11s filter file : %s, basedir: %s" % (regex, fltName, basedir) )
|
||||
self.output( "Use %11s file : %s, basedir: %s" % ('filter', fltName, basedir) )
|
||||
else:
|
||||
## foreign file - readexplicit this file and includes if possible:
|
||||
self.output( "Use %11s file : %s" % (regex, fltName) )
|
||||
self.output( "Use %11s file : %s" % ('filter', fltName) )
|
||||
basedir = None
|
||||
if not os.path.isabs(fltName): # avoid join with "filter.d" inside FilterReader
|
||||
fltName = os.path.abspath(fltName)
|
||||
|
@ -398,6 +431,7 @@ class Fail2banRegex(object):
|
|||
# to stream:
|
||||
readercommands = reader.convert()
|
||||
|
||||
if readercommands:
|
||||
regex_values = {}
|
||||
for opt in readercommands:
|
||||
if opt[0] == 'multi-set':
|
||||
|
|
|
@ -29,16 +29,19 @@ import json
|
|||
import os.path
|
||||
import re
|
||||
|
||||
from .configreader import ConfigReaderUnshared, ConfigReader
|
||||
from .configreader import ConfigReaderUnshared, ConfigReader, NoSectionError
|
||||
from .filterreader import FilterReader
|
||||
from .actionreader import ActionReader
|
||||
from ..version import version
|
||||
from ..helpers import getLogger, extractOptions, splitWithOptions, splitwords
|
||||
from ..helpers import _merge_dicts, getLogger, extractOptions, splitWithOptions, splitwords
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = getLogger(__name__)
|
||||
|
||||
|
||||
class NoJailError(ValueError):
|
||||
pass
|
||||
|
||||
class JailReader(ConfigReader):
|
||||
|
||||
def __init__(self, name, force_enable=False, **kwargs):
|
||||
|
@ -64,7 +67,7 @@ class JailReader(ConfigReader):
|
|||
# Before returning -- verify that requested section
|
||||
# exists at all
|
||||
if not (self.__name in self.sections()):
|
||||
raise ValueError("Jail %r was not found among available"
|
||||
raise NoJailError("Jail %r was not found among available"
|
||||
% self.__name)
|
||||
return out
|
||||
|
||||
|
@ -117,9 +120,9 @@ class JailReader(ConfigReader):
|
|||
}
|
||||
_configOpts.update(FilterReader._configOpts)
|
||||
|
||||
_ignoreOpts = set(['action', 'filter', 'enabled'] + list(FilterReader._configOpts.keys()))
|
||||
_ignoreOpts = set(['action', 'filter', 'enabled', 'backend'] + list(FilterReader._configOpts.keys()))
|
||||
|
||||
def getOptions(self):
|
||||
def getOptions(self, addOpts=None):
|
||||
|
||||
basedir = self.getBaseDir()
|
||||
|
||||
|
@ -136,6 +139,8 @@ class JailReader(ConfigReader):
|
|||
shouldExist=True)
|
||||
if not self.__opts: # pragma: no cover
|
||||
raise JailDefError("Init jail options failed")
|
||||
if addOpts:
|
||||
self.__opts = _merge_dicts(self.__opts, addOpts)
|
||||
|
||||
if not self.isEnabled():
|
||||
return True
|
||||
|
@ -147,6 +152,8 @@ class JailReader(ConfigReader):
|
|||
filterName, filterOpt = extractOptions(flt)
|
||||
except ValueError as e:
|
||||
raise JailDefError("Invalid filter definition %r: %s" % (flt, e))
|
||||
if addOpts:
|
||||
filterOpt = _merge_dicts(filterOpt, addOpts)
|
||||
self.__filter = FilterReader(
|
||||
filterName, self.__name, filterOpt,
|
||||
share_config=self.share_config, basedir=basedir)
|
||||
|
@ -219,6 +226,15 @@ class JailReader(ConfigReader):
|
|||
return False
|
||||
return True
|
||||
|
||||
@property
|
||||
def filter(self):
|
||||
return self.__filter
|
||||
|
||||
def getCombined(self):
|
||||
if not self.__filter:
|
||||
return self.__opts
|
||||
return _merge_dicts(self.__opts, self.__filter.getCombined())
|
||||
|
||||
def convert(self, allow_no_files=False):
|
||||
"""Convert read before __opts to the commands stream
|
||||
|
||||
|
@ -240,9 +256,10 @@ class JailReader(ConfigReader):
|
|||
stream.extend(self.__filter.convert())
|
||||
# and using options from jail:
|
||||
FilterReader._fillStream(stream, self.__opts, self.__name)
|
||||
backend = self.__opts.get('backend', 'auto')
|
||||
for opt, value in self.__opts.items():
|
||||
if opt == "logpath":
|
||||
if self.__opts.get('backend', '').startswith("systemd"): continue
|
||||
if backend.startswith("systemd"): continue
|
||||
found_files = 0
|
||||
for path in value.split("\n"):
|
||||
path = path.rsplit(" ", 1)
|
||||
|
@ -260,8 +277,6 @@ class JailReader(ConfigReader):
|
|||
if not allow_no_files:
|
||||
raise ValueError(msg)
|
||||
logSys.warning(msg)
|
||||
elif opt == "backend":
|
||||
backend = value
|
||||
elif opt == "ignoreip":
|
||||
stream.append(["set", self.__name, "addignoreip"] + splitwords(value))
|
||||
elif opt not in JailReader._ignoreOpts:
|
||||
|
|
Loading…
Reference in New Issue