From fc315be4ea88c3619f984542b21c95820f53d87b Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 16 Feb 2017 13:32:56 +0100 Subject: [PATCH] try to parse and interpolate all options in section "Definition" (section "Init" no more needed) --- fail2ban/client/configreader.py | 22 ++++++++++++++++++---- fail2ban/server/action.py | 6 +++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/fail2ban/client/configreader.py b/fail2ban/client/configreader.py index 7840cd12..b44a8c57 100644 --- a/fail2ban/client/configreader.py +++ b/fail2ban/client/configreader.py @@ -221,10 +221,14 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes): # Or it is a dict: # {name: [type, default], ...} - def getOptions(self, sec, options, pOptions=None, shouldExist=False): + def getOptions(self, sec, options, pOptions=None, + allOpts=None, shouldExist=False + ): values = dict() if pOptions is None: pOptions = {} + + # Get only specified options: for optname in options: if isinstance(options, (list,tuple)): if len(optname) > 2: @@ -261,6 +265,15 @@ class ConfigReaderUnshared(SafeConfigParserWithIncludes): logSys.warning("Wrong value for '" + optname + "' in '" + sec + "'. Using default one: '" + repr(optvalue) + "'") values[optname] = optvalue + + # Fill all option of the section (used for replacement): + if allOpts is not None and self.has_section(sec): + for optname in self.options(sec): + v = values.get(optname) + if v is None: + v = self.get(sec, optname, vars=pOptions) + allOpts[optname] = v + return values @@ -310,9 +323,9 @@ class DefinitionInitConfigReader(ConfigReader): if not pOpts: pOpts = dict() pOpts = _merge_dicts(pOpts, self._initOpts) + self._allOpts = dict() self._opts = ConfigReader.getOptions( - self, "Definition", self._configOpts, pOpts) - + self, "Definition", self._configOpts, pOpts, allOpts=self._allOpts) if self.has_section("Init"): for opt in self.options("Init"): v = self.get("Init", opt) @@ -338,7 +351,8 @@ class DefinitionInitConfigReader(ConfigReader): n, cond = cond.groups() ignore.add(n) # substiture options already specified direct: - opts = CommandAction.substituteRecursiveTags(combinedopts, ignore=ignore) + opts = CommandAction.substituteRecursiveTags(combinedopts, + ignore=ignore, addtags=self._allOpts) if not opts: raise ValueError('recursive tag definitions unable to be resolved') return opts diff --git a/fail2ban/server/action.py b/fail2ban/server/action.py index 46a19cd1..69cd84a3 100644 --- a/fail2ban/server/action.py +++ b/fail2ban/server/action.py @@ -365,7 +365,9 @@ class CommandAction(ActionBase): return self._executeOperation('', 'reloading') @classmethod - def substituteRecursiveTags(cls, inptags, conditional='', ignore=()): + def substituteRecursiveTags(cls, inptags, conditional='', + ignore=(), addtags={} + ): """Sort out tag definitions within other tags. Since v.0.9.2 supports embedded interpolation (see test cases for examples). @@ -420,6 +422,8 @@ class CommandAction(ActionBase): repl = tags.get(found_tag + '?' + conditional) if repl is None: repl = tags.get(found_tag) + if repl is None: + repl = addtags.get(found_tag) if repl is None: # Escaped or missing tags - just continue on searching after end of match # Missing tags are ok - cInfo can contain aInfo elements like and valid shell