Skip to content

Commit

Permalink
BF: allow newlines in action specifications
Browse files Browse the repository at this point in the history
Based from yarikoptic/_bf/multiline_action_options
  • Loading branch information
kwirk committed Jun 23, 2014
1 parent c7de888 commit abc0756
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
17 changes: 10 additions & 7 deletions fail2ban/client/jailreader.py
Expand Up @@ -37,9 +37,13 @@

class JailReader(ConfigReader):

optionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$")
optionSplitRE = re.compile(
r'^((?:\w|-|_|\.)+(?:\[.*?\])?)$', re.DOTALL | re.MULTILINE)
optionCRE = re.compile(
r'^((?:\w|-|_|\.)+)(?:\[(.*?)\])?$', re.DOTALL | re.MULTILINE)
optionExtractRE = re.compile(
r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,]*))(?:,|$)')
r'([\w\-_\.]+)=(?:"([^"]*)"|\'([^\']*)\'|([^,]*))(?:,|$)',
re.DOTALL | re.MULTILINE)

def __init__(self, name, force_enable=False, **kwargs):
ConfigReader.__init__(self, **kwargs)
Expand Down Expand Up @@ -123,9 +127,9 @@ def getOptions(self):
logSys.warning("No filter set for jail %s" % self.__name)

# Read action
for act in self.__opts["action"].split('\n'):
for act in JailReader.optionSplitRE.split(self.__opts["action"]):
try:
if not act: # skip empty actions
if not act.strip(): # skip empty actions
continue
actName, actOpt = JailReader.extractOptions(act)
if actName.endswith(".py"):
Expand All @@ -149,7 +153,7 @@ def getOptions(self):
else:
raise AttributeError("Unable to read action")
except Exception, e:
logSys.error("Error in action definition " + act)
logSys.error("Error in action definition %r", act)
logSys.debug("Caught exception: %s" % (e,))
return False
if not len(self.__actions):
Expand Down Expand Up @@ -224,8 +228,7 @@ def convert(self, allow_no_files=False):
def extractOptions(option):
match = JailReader.optionCRE.match(option)
if not match:
# TODO proper error handling
return None, None
raise ValueError("Invalid definition: %r" % option)
option_name, optstr = match.groups()
option_opts = dict()
if optstr:
Expand Down
40 changes: 40 additions & 0 deletions fail2ban/tests/clientreadertestcase.py
Expand Up @@ -237,6 +237,12 @@ def testSplitOption(self):
result = JailReader.extractOptions(option)
self.assertEqual(expected, result)

def testSplitOptionMultiline(self):
action = "mail-whois-lines[logpath=/a/b\n/c/d]"
expected = ('mail-whois-lines', {'logpath': '/a/b\n/c/d'})
result = JailReader.extractOptions(action)
self.assertEquals(expected, result)

def testGlob(self):
d = tempfile.mkdtemp(prefix="f2b-temp")
# Generate few files
Expand Down Expand Up @@ -558,3 +564,37 @@ def testMultipleSameAction(self):
self.assertEqual(add_actions[-1][-1], "{}")

shutil.rmtree(basedir)

def testMultipleLineAction(self):
basedir = tempfile.mkdtemp("fail2ban_conf")
os.mkdir(os.path.join(basedir, "filter.d"))
os.mkdir(os.path.join(basedir, "action.d"))
open(os.path.join(basedir, "action.d", "testaction1.conf"), 'w').close()
open(os.path.join(basedir, "action.d", "testaction2.conf"), 'w').close()
open(os.path.join(basedir, "action.d", "testaction3.conf"), 'w').close()
open(os.path.join(basedir, "filter.d", "testfilter1.conf"), 'w').close()
jailfd = open(os.path.join(basedir, "jail.conf"), 'w')
jailfd.write("""
[testjail1]
enabled = true
filter = testfilter1
logpath_ = string1
string2
action = testaction1[logpath=%(logpath_)s]
testaction2
testaction3[logpath=%(logpath_)s]
""")
jailfd.close()
jails = JailsReader(basedir=basedir)
self.assertTrue(jails.read())
self.assertTrue(jails.getOptions())
comm_commands = jails.convert(allow_no_files=True)

self.assertTrue(
['set', 'testjail1', 'action', 'testaction1', 'logpath', 'string1\nstring2'] in comm_commands)
self.assertTrue(
['set', 'testjail1', 'addaction', 'testaction2'] in comm_commands)
self.assertTrue(
['set', 'testjail1', 'action', 'testaction3', 'logpath', 'string1\nstring2'] in comm_commands)

shutil.rmtree(basedir)

0 comments on commit abc0756

Please sign in to comment.