diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index fda5d40c..98086cf4 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -42,9 +42,14 @@ logSys = getLogger(__name__) class JailReader(ConfigReader): + # regex, to extract list of options: optionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$") + # regex, to iterate over single option in option list, syntax: + # `action = act[p1="...", p2='...', p3=...]`, where the p3=... not contains `,` or ']' + # since v0.10 separator extended with `]\s*[` for support of multiple option groups, syntax + # `action = act[p1=...][p2=...]` optionExtractRE = re.compile( - r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,]*))(?:,|$)') + r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,\]]*))(?:,|\]\s*\[|$)') def __init__(self, name, force_enable=False, **kwargs): ConfigReader.__init__(self, **kwargs) diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py index 5e66e25e..521fda2e 100644 --- a/fail2ban/tests/clientreadertestcase.py +++ b/fail2ban/tests/clientreadertestcase.py @@ -255,6 +255,13 @@ class JailReaderTest(LogCaptureTestCase): result = JailReader.extractOptions(option) self.assertEqual(expected, result) + # And multiple groups (`][` instead of `,`) + result = JailReader.extractOptions(option.replace(',', '][')) + expected2 = (expected[0], + dict((k, v.replace(',', '][')) for k, v in expected[1].iteritems()) + ) + self.assertEqual(expected2, result) + def testVersionAgent(self): jail = JailReader('blocklisttest', force_enable=True, basedir=CONFIG_DIR) # emulate jail.read(), because such jail not exists: