diff --git a/CHANGELOG b/CHANGELOG index 430b803d..60d4f7cc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -4,12 +4,16 @@ |_| \__,_|_|_/___|_.__/\__,_|_||_| ============================================================= -Fail2Ban (version 0.6.?) 2006/??/?? +Fail2Ban (version 0.6.2) 2006/??/?? ============================================================= -ver. 0.6.? (2006/??/??) - ??? +ver. 0.6.2 (2006/??/??) - ??? ---------- - Fixed UTF-8 log file parsing +- Propagated patches introduced by Debian maintainer + (Yaroslav Halchenko): + * Made locale configurable + * Fixed warning if ignoreip is empty ver. 0.6.1 (2006/03/16) - stable ---------- @@ -26,7 +30,7 @@ ver. 0.6.1 (2006/03/16) - stable - Added parsing of timestamp in TAI64N format (#1275325). Thanks to Mark Edgington - Added patch #1382936 (Default formatted syslog logging). - Thanks to Patrick Börjesson + Thanks to Patrick B�rjesson - Removed 192.168.0.0/16 from ignoreip. Attacks could also come from the local network. - Robust startup: if iptables module does not get fully diff --git a/config/fail2ban.conf.hostsdeny b/config/fail2ban.conf.hostsdeny index 05c9d582..68a75409 100644 --- a/config/fail2ban.conf.hostsdeny +++ b/config/fail2ban.conf.hostsdeny @@ -11,6 +11,15 @@ # background = false +# Option: locale +# Notes.: global (cannot be redefined per section) locale to use for +# timestamp pattern matching by changing LC_TIME for +# fail2ban process. Empty entry sets locale to default one +# (usually specified by LC_ALL environment variable). +# Values: LOCALE Default: +# +locale = + # Option: logtargets # Notes.: log targets. Space separated list of logging targets. # Values: STDERR SYSLOG file Default: /var/log/fail2ban.log diff --git a/config/fail2ban.conf.iptables b/config/fail2ban.conf.iptables index 6aafc0ad..9d492e95 100644 --- a/config/fail2ban.conf.iptables +++ b/config/fail2ban.conf.iptables @@ -11,6 +11,15 @@ # background = false +# Option: locale +# Notes.: global (cannot be redefined per section) locale to use for +# timestamp pattern matching by changing LC_TIME for +# fail2ban process. Empty entry sets locale to default one +# (usually specified by LC_ALL environment variable). +# Values: LOCALE Default: +# +locale = + # Option: logtargets # Notes.: log targets. Space separated list of logging targets. # Values: STDERR SYSLOG file Default: /var/log/fail2ban.log diff --git a/config/fail2ban.conf.shorewall b/config/fail2ban.conf.shorewall index 2cb0fc46..ed99c8ec 100644 --- a/config/fail2ban.conf.shorewall +++ b/config/fail2ban.conf.shorewall @@ -11,6 +11,15 @@ # background = false +# Option: locale +# Notes.: global (cannot be redefined per section) locale to use for +# timestamp pattern matching by changing LC_TIME for +# fail2ban process. Empty entry sets locale to default one +# (usually specified by LC_ALL environment variable). +# Values: LOCALE Default: +# +locale = + # Option: logtargets # Notes.: log targets. Space separated list of logging targets. # Values: STDERR SYSLOG file Default: /var/log/fail2ban.log diff --git a/fail2ban b/fail2ban index 5eace8bd..64986126 100755 --- a/fail2ban +++ b/fail2ban @@ -26,14 +26,7 @@ __date__ = "$Date$" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import sys, traceback, logging, locale - -# Set the locale with the user's default setting -try: - locale.setlocale(locale.LC_ALL, '') -except Exception: - print "Unable to set locale to " + `locale.getdefaultlocale()` - sys.exit(-1) +import sys, traceback, logging # Inserts our own modules path first in the list # fix for bug #343821 diff --git a/fail2ban.py b/fail2ban.py index 1ab2ab90..44dfe32e 100755 --- a/fail2ban.py +++ b/fail2ban.py @@ -25,7 +25,8 @@ __date__ = "$Date$" __copyright__ = "Copyright (c) 2004 Cyril Jaquier" __license__ = "GPL" -import time, sys, getopt, os, string, signal, logging, logging.handlers, copy +import time, sys, getopt, os, string, signal, logging, logging.handlers, \ + copy, locale from ConfigParser import * from version import version @@ -192,7 +193,7 @@ def main(): # Reads the command line options. try: cmdOpts = 'hvVbdkc:t:i:r:p:' - cmdLongOpts = ['help','version'] + cmdLongOpts = ['help', 'version'] optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts) except getopt.GetoptError: dispUsage() @@ -212,19 +213,20 @@ def main(): confReader.openConf() # Options - optionValues = (["bool", "background", False], - ["str", "logtargets", "/var/log/fail2ban.log"], - ["str", "syslog-target", "/dev/log"], - ["int", "syslog-facility", 1], - ["str", "pidlock", "/var/run/fail2ban.pid"], - ["int", "maxfailures", 5], - ["int", "bantime", 600], - ["int", "findtime", 600], - ["str", "ignoreip", ""], - ["int", "polltime", 1], - ["str", "cmdstart", ""], - ["str", "cmdend", ""], - ["int", "reinittime", 100], + optionValues = (["bool", "background", False], + ["str", "logtargets", "/var/log/fail2ban.log"], + ["str", "syslog-target", "/dev/log"], + ["int", "syslog-facility", 1], + ["str", "pidlock", "/var/run/fail2ban.pid"], + ["str", "locale", ""], + ["int", "maxfailures", 5], + ["int", "bantime", 600], + ["int", "findtime", 600], + ["str", "ignoreip", ""], + ["int", "polltime", 1], + ["str", "cmdstart", ""], + ["str", "cmdend", ""], + ["int", "reinittime", 100], ["int", "maxreinits", 100]) # Gets global configuration options @@ -236,6 +238,14 @@ def main(): # PID lock pidLock.setPath(conf["pidlock"]) + # Set the LC_TIME with the user's default setting + try: + logSys.info("Setting LC_TIME locale option to '%s'"%conf["locale"]) + locale.setlocale(locale.LC_TIME, conf["locale"]) + except Exception: + logSys.error("Unable to set locale to '%s'"%conf["locale"]) + sys.exit(-1) + # Now we can kill properly a running instance if needed if conf["kill"]: pid = pidLock.exists() @@ -270,7 +280,7 @@ def main(): # a socket (file, so it starts with /) # or hostname # or hostname:port - syslogtargets = re.findall("(/[\w/]*)|([^/ ][^: ]*)(:(\d+)){,1}", + syslogtargets = re.findall("(/[\w/]*)|([^/ ][^: ]*)(:(\d+)){,1}", conf["syslog-target"]) # we are waiting for a single match syslogtargets = syslogtargets[0] @@ -284,7 +294,7 @@ def main(): if len(syslogtargets) == 0: # everything default hdlr = logging.handlers.SysLogHandler() else: - if not ( syslogtargets[0] == "" ): # got socket + if not (syslogtargets[0] == ""): # got socket syslogtarget = syslogtargets[0] else: # got hostname and maybe a port if syslogtargets[3] == "": # no port specified @@ -326,7 +336,9 @@ def main(): "ONLY DISPLAYED IN THE LOG MESSAGES") # Ignores IP list - ignoreIPList = conf["ignoreip"].split(' ') + # and filter out empty entries. Otherwise + # WARNING: is not a valid IP address + ignoreIPList = filter(None, conf["ignoreip"].split(' ')) # Checks for root user. This is necessary because log files # are owned by root and firewall needs root access. @@ -352,15 +364,15 @@ def main(): logSys.debug("MaxFailure is " + `conf["maxfailures"]`) # Options - optionValues = (["bool", "enabled", False], - ["str", "host", "localhost"], - ["int", "port", "25"], - ["str", "from", "root"], - ["str", "to", "root"], - ["str", "user", ''], - ["str", "password", ''], - ["bool", "localtime", False], - ["str", "subject", "[Fail2Ban] Banned "], + optionValues = (["bool", "enabled", False], + ["str", "host", "localhost"], + ["int", "port", "25"], + ["str", "from", "root"], + ["str", "to", "root"], + ["str", "user", ''], + ["str", "password", ''], + ["bool", "localtime", False], + ["str", "subject", "[Fail2Ban] Banned "], ["str", "message", "Fail2Ban notification"]) # Gets global configuration options @@ -378,18 +390,18 @@ def main(): logSys.debug("to: " + mailConf["to"] + " from: " + mailConf["from"]) # Options - optionValues = (["bool", "enabled", False], - ["str", "logfile", "/dev/null"], - ["int", "maxfailures", conf["maxfailures"]], - ["int", "bantime", conf["bantime"]], - ["int", "findtime", conf["findtime"]], - ["str", "timeregex", ""], - ["str", "timepattern", ""], - ["str", "failregex", ""], - ["str", "fwstart", ""], - ["str", "fwend", ""], - ["str", "fwban", ""], - ["str", "fwunban", ""], + optionValues = (["bool", "enabled", False], + ["str", "logfile", "/dev/null"], + ["int", "maxfailures", conf["maxfailures"]], + ["int", "bantime", conf["bantime"]], + ["int", "findtime", conf["findtime"]], + ["str", "timeregex", ""], + ["str", "timepattern", ""], + ["str", "failregex", ""], + ["str", "fwstart", ""], + ["str", "fwend", ""], + ["str", "fwban", ""], + ["str", "fwunban", ""], ["str", "fwcheck", ""]) logSys.info("Fail2Ban v" + version + " is running") @@ -399,10 +411,10 @@ def main(): l = confReader.getLogOptions(t, optionValues) if l["enabled"]: # Creates a logreader object - lObj = LogReader(l["logfile"], l["timeregex"], l["timepattern"], + lObj = LogReader(l["logfile"], l["timeregex"], l["timepattern"], l["failregex"], l["maxfailures"], l["findtime"]) # Creates a firewall object - fObj = Firewall(l["fwstart"], l["fwend"], l["fwban"], l["fwunban"], + fObj = Firewall(l["fwstart"], l["fwend"], l["fwban"], l["fwunban"], l["fwcheck"], l["bantime"]) # "Name" the firewall fObj.setSection(t) @@ -474,7 +486,7 @@ def main(): e = element[1].getFailures() for key in e.iterkeys(): if element[3].has_key(key): - element[3][key] = (element[3][key][0] + e[key][0], + element[3][key] = (element[3][key][0] + e[key][0], e[key][1]) else: element[3][key] = (e[key][0], e[key][1]) @@ -491,9 +503,9 @@ def main(): if failTime < unixTime - findTime: del element[3][attempt] elif fails[attempt][0] >= element[1].getMaxRetry(): - aInfo = {"section": element[0], - "ip": attempt, - "failures": element[3][attempt][0], + aInfo = {"section": element[0], + "ip": attempt, + "failures": element[3][attempt][0], "failtime": failTime} logSys.info(element[0] + ": " + aInfo["ip"] + " has " + `aInfo["failures"]` + @@ -501,7 +513,7 @@ def main(): element[2].addBanIP(aInfo, conf["debug"]) # Send a mail notification if 'mail' in locals(): - mail.sendmail(mailConf["subject"], + mail.sendmail(mailConf["subject"], mailConf["message"], aInfo) del element[3][attempt] except ExternalError, e: