mirror of https://github.com/fail2ban/fail2ban
NF: Filters now allow adding of [Init] section similar to actions
parent
9a14cf8b7b
commit
01499ad0de
|
@ -28,66 +28,42 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|||
__license__ = "GPL"
|
||||
|
||||
import logging
|
||||
from configreader import ConfigReader
|
||||
from configreader import ConfigReader, OptionConfigReader
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger(__name__)
|
||||
|
||||
class ActionReader(ConfigReader):
|
||||
class ActionReader(OptionConfigReader):
|
||||
|
||||
def __init__(self, action, name, **kwargs):
|
||||
ConfigReader.__init__(self, **kwargs)
|
||||
self.__file = action[0]
|
||||
self.__cInfo = action[1]
|
||||
self.__name = name
|
||||
|
||||
def setFile(self, fileName):
|
||||
self.__file = fileName
|
||||
|
||||
def getFile(self):
|
||||
return self.__file
|
||||
|
||||
def setName(self, name):
|
||||
self.__name = name
|
||||
|
||||
def getName(self):
|
||||
return self.__name
|
||||
|
||||
def read(self):
|
||||
return ConfigReader.read(self, "action.d/" + self.__file)
|
||||
|
||||
def getOptions(self, pOpts):
|
||||
opts = [["string", "actionstart", ""],
|
||||
_configOpts = [
|
||||
["string", "actionstart", ""],
|
||||
["string", "actionstop", ""],
|
||||
["string", "actioncheck", ""],
|
||||
["string", "actionban", ""],
|
||||
["string", "actionunban", ""]]
|
||||
self.__opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
|
||||
["string", "actionunban", ""],
|
||||
]
|
||||
|
||||
if self.has_section("Init"):
|
||||
for opt in self.options("Init"):
|
||||
if not self.__cInfo.has_key(opt):
|
||||
self.__cInfo[opt] = self.get("Init", opt)
|
||||
def read(self):
|
||||
return ConfigReader.read(self, "action.d/" + self._file)
|
||||
|
||||
def convert(self):
|
||||
head = ["set", self.__name]
|
||||
head = ["set", self._name]
|
||||
stream = list()
|
||||
stream.append(head + ["addaction", self.__file])
|
||||
for opt in self.__opts:
|
||||
stream.append(head + ["addaction", self._file])
|
||||
for opt in self._opts:
|
||||
if opt == "actionstart":
|
||||
stream.append(head + ["actionstart", self.__file, self.__opts[opt]])
|
||||
stream.append(head + ["actionstart", self._file, self._opts[opt]])
|
||||
elif opt == "actionstop":
|
||||
stream.append(head + ["actionstop", self.__file, self.__opts[opt]])
|
||||
stream.append(head + ["actionstop", self._file, self._opts[opt]])
|
||||
elif opt == "actioncheck":
|
||||
stream.append(head + ["actioncheck", self.__file, self.__opts[opt]])
|
||||
stream.append(head + ["actioncheck", self._file, self._opts[opt]])
|
||||
elif opt == "actionban":
|
||||
stream.append(head + ["actionban", self.__file, self.__opts[opt]])
|
||||
stream.append(head + ["actionban", self._file, self._opts[opt]])
|
||||
elif opt == "actionunban":
|
||||
stream.append(head + ["actionunban", self.__file, self.__opts[opt]])
|
||||
stream.append(head + ["actionunban", self._file, self._opts[opt]])
|
||||
# cInfo
|
||||
if self.__cInfo:
|
||||
for p in self.__cInfo:
|
||||
stream.append(head + ["setcinfo", self.__file, p, self.__cInfo[p]])
|
||||
if self._initOpts:
|
||||
for p in self._initOpts:
|
||||
stream.append(head + ["setcinfo", self._file, p, self._initOpts[p]])
|
||||
|
||||
return stream
|
||||
|
||||
|
|
|
@ -130,3 +130,40 @@ class ConfigReader(SafeConfigParserWithIncludes):
|
|||
"'. Using default one: '" + `option[2]` + "'")
|
||||
values[option[1]] = option[2]
|
||||
return values
|
||||
|
||||
class OptionConfigReader(ConfigReader):
|
||||
|
||||
_configOpts = []
|
||||
|
||||
def __init__(self, file_, jailName, initOpts, **kwargs):
|
||||
ConfigReader.__init__(self, **kwargs)
|
||||
self._file = file_
|
||||
self._name = jailName
|
||||
self._initOpts = initOpts
|
||||
|
||||
def setFile(self, fileName):
|
||||
self._file = fileName
|
||||
|
||||
def getFile(self):
|
||||
return self.__file
|
||||
|
||||
def setName(self, name):
|
||||
self._name = name
|
||||
|
||||
def getName(self):
|
||||
return self._name
|
||||
|
||||
def read(self):
|
||||
return ConfigReader.read(self, self._file)
|
||||
|
||||
def getOptions(self, pOpts):
|
||||
self._opts = ConfigReader.getOptions(
|
||||
self, "Definition", self._configOpts, pOpts)
|
||||
|
||||
if self.has_section("Init"):
|
||||
for opt in self.options("Init"):
|
||||
if not self._initOpts.has_key(opt):
|
||||
self._initOpts[opt] = self.get("Init", opt)
|
||||
|
||||
def convert(self):
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -28,50 +28,33 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|||
__license__ = "GPL"
|
||||
|
||||
import logging
|
||||
from configreader import ConfigReader
|
||||
from configreader import ConfigReader, OptionConfigReader
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger(__name__)
|
||||
|
||||
class FilterReader(ConfigReader):
|
||||
class FilterReader(OptionConfigReader):
|
||||
|
||||
def __init__(self, fileName, name, **kwargs):
|
||||
ConfigReader.__init__(self, **kwargs)
|
||||
self.__file = fileName
|
||||
self.__name = name
|
||||
|
||||
def setFile(self, fileName):
|
||||
self.__file = fileName
|
||||
|
||||
def getFile(self):
|
||||
return self.__file
|
||||
|
||||
def setName(self, name):
|
||||
self.__name = name
|
||||
|
||||
def getName(self):
|
||||
return self.__name
|
||||
_configOpts = [
|
||||
["string", "ignoreregex", ""],
|
||||
["string", "failregex", ""],
|
||||
]
|
||||
|
||||
def read(self):
|
||||
return ConfigReader.read(self, "filter.d/" + self.__file)
|
||||
|
||||
def getOptions(self, pOpts):
|
||||
opts = [["string", "ignoreregex", ""],
|
||||
["string", "failregex", ""]]
|
||||
self.__opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
|
||||
return ConfigReader.read(self, "filter.d/" + self._file)
|
||||
|
||||
def convert(self):
|
||||
stream = list()
|
||||
for opt in self.__opts:
|
||||
for opt in self._opts:
|
||||
if opt == "failregex":
|
||||
for regex in self.__opts[opt].split('\n'):
|
||||
for regex in self._opts[opt].split('\n'):
|
||||
# Do not send a command if the rule is empty.
|
||||
if regex != '':
|
||||
stream.append(["set", self.__name, "addfailregex", regex])
|
||||
stream.append(["set", self._name, "addfailregex", regex])
|
||||
elif opt == "ignoreregex":
|
||||
for regex in self.__opts[opt].split('\n'):
|
||||
for regex in self._opts[opt].split('\n'):
|
||||
# Do not send a command if the rule is empty.
|
||||
if regex != '':
|
||||
stream.append(["set", self.__name, "addignoreregex", regex])
|
||||
stream.append(["set", self._name, "addignoreregex", regex])
|
||||
return stream
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ logSys = logging.getLogger(__name__)
|
|||
|
||||
class JailReader(ConfigReader):
|
||||
|
||||
actionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$")
|
||||
optionCRE = re.compile("^((?:\w|-|_|\.)+)(?:\[(.*)\])?$")
|
||||
|
||||
def __init__(self, name, force_enable=False, **kwargs):
|
||||
ConfigReader.__init__(self, **kwargs)
|
||||
|
@ -78,8 +78,10 @@ class JailReader(ConfigReader):
|
|||
|
||||
if self.isEnabled():
|
||||
# Read filter
|
||||
self.__filter = FilterReader(self.__opts["filter"], self.__name,
|
||||
basedir=self.getBaseDir())
|
||||
filterName, filterOpt = JailReader.splitOption(
|
||||
self.__opts["filter"])
|
||||
self.__filter = FilterReader(
|
||||
filterName, self.__name, filterOpt, basedir=self.getBaseDir())
|
||||
ret = self.__filter.read()
|
||||
if ret:
|
||||
self.__filter.getOptions(self.__opts)
|
||||
|
@ -92,8 +94,9 @@ class JailReader(ConfigReader):
|
|||
try:
|
||||
if not act: # skip empty actions
|
||||
continue
|
||||
splitAct = JailReader.splitAction(act)
|
||||
action = ActionReader(splitAct, self.__name, basedir=self.getBaseDir())
|
||||
actName, actOpt = JailReader.splitOption(act)
|
||||
action = ActionReader(
|
||||
actName, self.__name, actOpt, basedir=self.getBaseDir())
|
||||
ret = action.read()
|
||||
if ret:
|
||||
action.getOptions(self.__opts)
|
||||
|
@ -151,23 +154,23 @@ class JailReader(ConfigReader):
|
|||
return stream
|
||||
|
||||
#@staticmethod
|
||||
def splitAction(action):
|
||||
m = JailReader.actionCRE.match(action)
|
||||
def splitOption(option):
|
||||
m = JailReader.optionCRE.match(option)
|
||||
d = dict()
|
||||
mgroups = m.groups()
|
||||
if len(mgroups) == 2:
|
||||
action_name, action_opts = mgroups
|
||||
option_name, option_opts = mgroups
|
||||
elif len(mgroups) == 1:
|
||||
action_name, action_opts = mgroups[0], None
|
||||
option_name, option_opts = mgroups[0], None
|
||||
else:
|
||||
raise ValueError("While reading action %s we should have got up to "
|
||||
"2 groups. Got: %r" % (action, mgroups))
|
||||
if not action_opts is None:
|
||||
raise ValueError("While reading option %s we should have got up to "
|
||||
"2 groups. Got: %r" % (option, mgroups))
|
||||
if not option_opts is None:
|
||||
# Huge bad hack :( This method really sucks. TODO Reimplement it.
|
||||
actions = ""
|
||||
options = ""
|
||||
escapeChar = None
|
||||
allowComma = False
|
||||
for c in action_opts:
|
||||
for c in option_opts:
|
||||
if c in ('"', "'") and not allowComma:
|
||||
# Start
|
||||
escapeChar = c
|
||||
|
@ -178,20 +181,20 @@ class JailReader(ConfigReader):
|
|||
allowComma = False
|
||||
else:
|
||||
if c == ',' and allowComma:
|
||||
actions += "<COMMA>"
|
||||
options += "<COMMA>"
|
||||
else:
|
||||
actions += c
|
||||
options += c
|
||||
|
||||
# Split using ,
|
||||
actionsSplit = actions.split(',')
|
||||
optionsSplit = options.split(',')
|
||||
# Replace the tag <COMMA> with ,
|
||||
actionsSplit = [n.replace("<COMMA>", ',') for n in actionsSplit]
|
||||
optionsSplit = [n.replace("<COMMA>", ',') for n in optionsSplit]
|
||||
|
||||
for param in actionsSplit:
|
||||
for param in optionsSplit:
|
||||
p = param.split('=')
|
||||
try:
|
||||
d[p[0].strip()] = p[1].strip()
|
||||
except IndexError:
|
||||
logSys.error("Invalid argument %s in '%s'" % (p, action_opts))
|
||||
return [action_name, d]
|
||||
splitAction = staticmethod(splitAction)
|
||||
logSys.error("Invalid argument %s in '%s'" % (p, option_opts))
|
||||
return [option_name, d]
|
||||
splitOption = staticmethod(splitOption)
|
||||
|
|
|
@ -112,10 +112,10 @@ class JailReaderTest(unittest.TestCase):
|
|||
self.assertFalse(jail.isEnabled())
|
||||
self.assertEqual(jail.getName(), 'ssh-iptables')
|
||||
|
||||
def testSplitAction(self):
|
||||
def testSplitOption(self):
|
||||
action = "mail-whois[name=SSH]"
|
||||
expected = ['mail-whois', {'name': 'SSH'}]
|
||||
result = JailReader.splitAction(action)
|
||||
result = JailReader.splitOption(action)
|
||||
self.assertEquals(expected, result)
|
||||
|
||||
class FilterReaderTest(unittest.TestCase):
|
||||
|
@ -140,7 +140,7 @@ class FilterReaderTest(unittest.TestCase):
|
|||
"+$<SKIPLINES>^.+ module for .* from <HOST>\\s*$"],
|
||||
['set', 'testcase01', 'addignoreregex',
|
||||
"^.+ john from host 192.168.1.1\\s*$"]]
|
||||
filterReader = FilterReader("testcase01", "testcase01")
|
||||
filterReader = FilterReader("testcase01", "testcase01", {})
|
||||
filterReader.setBaseDir(TEST_FILES_DIR)
|
||||
filterReader.read()
|
||||
#filterReader.getOptions(["failregex", "ignoreregex"])
|
||||
|
|
Loading…
Reference in New Issue