1# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*- 2# vi: set ft=python sts=4 ts=4 sw=4 noet : 3 4# This file is part of Fail2Ban. 5# 6# Fail2Ban is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 2 of the License, or 9# (at your option) any later version. 10# 11# Fail2Ban is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with Fail2Ban; if not, write to the Free Software 18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 20# Author: Cyril Jaquier 21# 22 23__author__ = "Cyril Jaquier" 24__copyright__ = "Copyright (c) 2004 Cyril Jaquier" 25__license__ = "GPL" 26 27import os 28import shlex 29 30from .configreader import DefinitionInitConfigReader 31from ..helpers import getLogger 32 33# Gets the instance of the logger. 34logSys = getLogger(__name__) 35 36 37class FilterReader(DefinitionInitConfigReader): 38 39 _configOpts = { 40 "usedns": ["string", None], 41 "prefregex": ["string", None], 42 "ignoreregex": ["string", None], 43 "failregex": ["string", None], 44 "maxlines": ["int", None], 45 "datepattern": ["string", None], 46 "journalmatch": ["string", None], 47 } 48 49 def setFile(self, fileName): 50 self.__file = fileName 51 DefinitionInitConfigReader.setFile(self, os.path.join("filter.d", fileName)) 52 53 def getFile(self): 54 return self.__file 55 56 def applyAutoOptions(self, backend): 57 # set init option to backend-related logtype, considering 58 # that the filter settings may be overwritten in its local: 59 if (not self._initOpts.get('logtype') and 60 not self.has_option('Definition', 'logtype', False) 61 ): 62 self._initOpts['logtype'] = ['file','journal'][int(backend.startswith("systemd"))] 63 64 def convert(self): 65 stream = list() 66 opts = self.getCombined() 67 if not len(opts): 68 return stream 69 return FilterReader._fillStream(stream, opts, self._jailName) 70 71 @staticmethod 72 def _fillStream(stream, opts, jailName): 73 prio0idx = 0 74 for opt, value in opts.items(): 75 if opt in ("failregex", "ignoreregex"): 76 if value is None: continue 77 multi = [] 78 for regex in value.split('\n'): 79 # Do not send a command if the rule is empty. 80 if regex != '': 81 multi.append(regex) 82 if len(multi) > 1: 83 stream.append(["multi-set", jailName, "add" + opt, multi]) 84 elif len(multi): 85 stream.append(["set", jailName, "add" + opt, multi[0]]) 86 elif opt in ('usedns', 'maxlines', 'prefregex'): 87 # Be sure we set this options first, and usedns is before all regex(s). 88 stream.insert(0 if opt == 'usedns' else prio0idx, 89 ["set", jailName, opt, value]) 90 prio0idx += 1 91 elif opt in ('datepattern'): 92 stream.append(["set", jailName, opt, value]) 93 elif opt == 'journalmatch': 94 # Do not send a command if the match is empty. 95 if value is None: continue 96 for match in value.split("\n"): 97 if match == '': continue 98 stream.append( 99 ["set", jailName, "addjournalmatch"] + shlex.split(match)) 100 return stream 101 102