Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Upgraded to fresh upstream 0.7.8

  • Loading branch information...
commit d77f67bb890ca240e74e0fb25ab56f7cca070823 2 parents 018484d + bf72fe7
@yarikoptic yarikoptic authored
View
10 CHANGELOG
@@ -4,9 +4,17 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
-Fail2Ban (version 0.7.7) 2007/02/08
+Fail2Ban (version 0.7.8) 2007/03/21
=============================================================
+ver. 0.7.8 (2007/03/21) - release candidate
+----------
+- Fixed asctime pattern in datedetector.py
+- Added new filters/actions. Thanks to Yaroslav Halchenko
+- Added Suse init script and modified gentoo-initd. Thanks to
+ Christian Rauch
+- Moved every locking statements in a try..finally block
+
ver. 0.7.7 (2007/02/08) - release candidate
----------
- Added signal handling in fail2ban-client
View
2  PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: fail2ban
-Version: 0.7.7
+Version: 0.7.8
Summary: Ban IPs that make too many password failure
Home-page: http://fail2ban.sourceforge.net
Author: Cyril Jaquier
View
8 README
@@ -4,7 +4,7 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
-Fail2Ban (version 0.7.7) 2007/02/08
+Fail2Ban (version 0.7.8) 2007/03/21
=============================================================
Fail2Ban scans log files like /var/log/pwdfail and bans IP
@@ -28,8 +28,8 @@ Optional:
To install, just do:
-> tar xvfj fail2ban-0.7.7.tar.bz2
-> cd fail2ban-0.7.7
+> tar xvfj fail2ban-0.7.8.tar.bz2
+> cd fail2ban-0.7.8
> python setup.py install
This will install Fail2Ban into /usr/share/fail2ban. The
@@ -73,7 +73,7 @@ Tom Pike, Iain Lea, Andrey G. Grozin, Yaroslav Halchenko,
Jonathan Kamens, Stephen Gildea, Markus Hoffmann, Mark
Edgington, Patrick Börjesson, kojiro, zugeschmiert, Tyler,
Nick Munger, Christoph Haas, Justin Shore, Joël Bertrand,
-René Berber, mEDI, Axel Thimm, Eric Gerbier
+René Berber, mEDI, Axel Thimm, Eric Gerbier, Christian Rauch
License:
--------
View
14 TODO
@@ -4,7 +4,7 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
-ToDo $Revision: 540 $
+ToDo $Revision: 557 $
=============================================================
Legend:
@@ -13,16 +13,24 @@ Legend:
# partially done
* done
+- Removed relative imports
+
+- Discuss where Fail2ban should be installed (/usr/share,
+ /usr/lib/python/site-packages/, etc)
+
+- Cleanup fail2ban-client and fail2ban-server. Move code to
+ server/ and client/
+
- Add timeout to external commands (signal alarm, watchdog
thread, etc)
-- New backend: pynotify
+- New backend: pyinotify
- Uniformize filters and actions name. Use the software name
(openssh, postfix, proftp)
- Added <USER> tag for failregex. Add features using this
- information
+ information. Maybe add more tags
- Look at the memory consumption. Decrease memory usage
View
13 client/beautifier.py
@@ -16,11 +16,11 @@
# Author: Cyril Jaquier
#
-# $Revision: 537 $
+# $Revision: 547 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 537 $"
-__date__ = "$Date: 2007-02-01 21:50:12 +0100 (Thu, 01 Feb 2007) $"
+__version__ = "$Revision: 547 $"
+__date__ = "$Date: 2007-02-12 00:21:56 +0100 (Mon, 12 Feb 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
@@ -68,13 +68,18 @@ def beautify(self, response):
msg = "Added jail " + response
elif inC[0:1] == ['status']:
if len(inC) > 1:
+ # Create IP list
+ ipList = ""
+ for ip in response[1][1][2][1]:
+ ipList += ip + " "
+ # Display information
msg = "Status for the jail: " + inC[1] + "\n"
msg = msg + "|- " + response[0][0] + "\n"
msg = msg + "| |- " + response[0][1][0][0] + ":\t" + `response[0][1][0][1]` + "\n"
msg = msg + "| `- " + response[0][1][1][0] + ":\t" + `response[0][1][1][1]` + "\n"
msg = msg + "`- " + response[1][0] + "\n"
msg = msg + " |- " + response[1][1][0][0] + ":\t" + `response[1][1][0][1]` + "\n"
- msg = msg + " | `- " + response[1][1][2][0] + ":\t" + `response[1][1][2][1]` + "\n"
+ msg = msg + " | `- " + response[1][1][2][0] + ":\t" + ipList + "\n"
msg = msg + " `- " + response[1][1][1][0] + ":\t" + `response[1][1][1][1]`
else:
msg = "Status\n"
View
8 common/version.py
@@ -16,12 +16,12 @@
# Author: Cyril Jaquier
#
-# $Revision: 543 $
+# $Revision: 561 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 543 $"
-__date__ = "$Date: 2007-02-08 22:14:01 +0100 (Thu, 08 Feb 2007) $"
+__version__ = "$Revision: 561 $"
+__date__ = "$Date: 2007-03-21 22:44:07 +0100 (Wed, 21 Mar 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
-version = "0.7.7"
+version = "0.7.8"
View
6 config/action.d/hostsdeny.conf
@@ -2,7 +2,7 @@
#
# Author: Cyril Jaquier
#
-# $Revision: 496 $
+# $Revision: 554 $
#
[Definition]
@@ -11,13 +11,13 @@
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
-actionstart = touch <tmpfile>
+actionstart =
# Option: actionend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
-actionstop = rm -f <tmpfile>
+actionstop =
# Option: actioncheck
# Notes.: command executed once before each actionban command
View
88 config/action.d/mail-buffered.conf
@@ -0,0 +1,88 @@
+# Fail2Ban configuration file
+#
+# Author: Cyril Jaquier
+#
+# $Revision: 510 $
+#
+
+[Definition]
+
+# Option: actionstart
+# Notes.: command executed once at the start of Fail2Ban.
+# Values: CMD
+#
+actionstart = echo -en "Hi,\n
+ The jail <name> has been started successfuly.\n
+ Output will be buffered until <lines> lines are available.\n
+ Regards,\n
+ Fail2Ban"|mail -s "[Fail2Ban] <name>: started" <dest>
+
+# Option: actionend
+# Notes.: command executed once at the end of Fail2Ban
+# Values: CMD
+#
+actionstop = if [ -d <tmpfile> ]; then
+ echo -en "Hi,\n
+ These hosts have been banned by Fail2Ban.\n
+ `cat <tmpfile>`
+ Regards,\n
+ Fail2Ban"|mail -s "[Fail2Ban] <name>: Summary" <dest>
+ rm <tmpfile>
+ fi
+ echo -en "Hi,\n
+ The jail <name> has been stopped.\n
+ Regards,\n
+ Fail2Ban"|mail -s "[Fail2Ban] <name>: stopped" <dest>
+
+# Option: actioncheck
+# Notes.: command executed once before each actionban command
+# Values: CMD
+#
+actioncheck =
+
+# Option: actionban
+# Notes.: command executed when banning an IP. Take care that the
+# command is executed with Fail2Ban user rights.
+# Tags: <ip> IP address
+# <failures> number of failures
+# <time> unix timestamp of the ban time
+# Values: CMD
+#
+actionban = echo `date`": <ip> (<failures> failures)" >> <tmpfile>
+ LINE=$( wc -l <tmpfile> | awk '{ print $1 }' )
+ if [ $LINE -eq <lines> ]; then
+ echo -en "Hi,\n
+ These hosts have been banned by Fail2Ban.\n
+ `cat <tmpfile>`
+ Regards,\n
+ Fail2Ban"|mail -s "[Fail2Ban] <name>: Summary" <dest>
+ rm <tmpfile>
+ fi
+
+# Option: actionunban
+# Notes.: command executed when unbanning an IP. Take care that the
+# command is executed with Fail2Ban user rights.
+# Tags: <ip> IP address
+# <failures> number of failures
+# <time> unix timestamp of the ban time
+# Values: CMD
+#
+actionunban =
+
+[Init]
+
+# Default name of the chain
+#
+name = default
+
+# Default number of lines that are buffered
+#
+lines = 5
+
+# Default temporary file
+#
+tmpfile = /tmp/fail2ban-mail.txt
+
+# Destination/Addressee of the mail
+#
+dest = root
View
26 config/filter.d/apache-badbots.conf
@@ -0,0 +1,26 @@
+# Fail2Ban configuration file
+#
+# List of bad bots fetched from http://www.user-agents.org
+# Generated on Sun Feb 11 01:09:15 EST 2007 by ./badbots.sh
+#
+# Author: Yaroslav Halchenko
+#
+
+[Definition]
+
+badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\.02
+badbots = atSpider/1\.0|autoemailspider|China Local Browse 2\.6|ContentSmartz|DataCha0s/2\.0|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 +http\://letscrawl\.com/|Lincoln State Web Browser|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|MVAClient|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|sogou spider|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|WebVulnCrawl\.blogspot\.com/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00
+
+# Option: failregex
+# Notes.: Regexp to catch known spambots and software alike. Please verify
+# that it is your intent to block IPs which were driven by
+# abovementioned bots.
+# Values: TEXT
+#
+failregex = ^<HOST> -.*"(GET|POST).*HTTP.*"(?:%(badbots)s|%(badbotscustom)s)"$
+
+# Option: ignoreregex
+# Notes.: regex to ignore. If this regex matches, the line is ignored.
+# Values: TEXT
+#
+ignoreregex =
View
23 config/filter.d/exim.conf
@@ -0,0 +1,23 @@
+# Fail2Ban configuration file
+#
+# Author: Cyril Jaquier
+#
+# $Revision: 510 $
+#
+
+[Definition]
+
+# Option: failregex
+# Notes.: regex to match the password failures messages in the logfile. The
+# host must be matched by a group named "host". The tag "<HOST>" can
+# be used for standard IP/hostname matching and is only an alias for
+# (?:::f{4,6}:)?(?P<host>\S+)
+# Values: TEXT
+#
+failregex = \[<HOST>\] .*(?:rejected by local_scan|Unrouteable address)
+
+# Option: ignoreregex
+# Notes.: regex to ignore. If this regex matches, the line is ignored.
+# Values: TEXT
+#
+ignoreregex =
View
29 config/filter.d/pure-ftpd.conf
@@ -0,0 +1,29 @@
+# Fail2Ban configuration file
+#
+# Author: Cyril Jaquier
+# Modified: Yaroslav Halchenko for pure-ftpd
+#
+# $Revision: 3$
+#
+
+[Definition]
+
+# Error message specified in multiple languages
+__errmsg = (?:Authentication failed for user|Erreur d'authentification pour l'utilisateur)
+
+#
+# Option: failregex
+# Notes.: regex to match the password failures messages in the logfile. The
+# host must be matched by a group named "host". The tag "<HOST>" can
+# be used for standard IP/hostname matching and is only an alias for
+# (?:::f{4,6}:)?(?P<host>\S+)
+# Values: TEXT
+#
+failregex = pure-ftpd: (.+?@<HOST>) \[WARNING\] %(__errmsg)s \[.+\]$
+
+# Option: ignoreregex
+# Notes.: regex to ignore. If this regex matches, the line is ignored.
+# Values: TEXT
+#
+ignoreregex =
+
View
23 config/filter.d/sshd-ddos.conf
@@ -0,0 +1,23 @@
+# Fail2Ban configuration file
+#
+# Author: Yaroslav Halchenko
+#
+# $Revision: 510 $
+#
+
+[Definition]
+
+# Option: failregex
+# Notes.: regex to match the password failures messages in the logfile. The
+# host must be matched by a group named "host". The tag "<HOST>" can
+# be used for standard IP/hostname matching and is only an alias for
+# (?:::f{4,6}:)?(?P<host>\S+)
+# Values: TEXT
+#
+failregex = sshd\[\S*\]: Did not receive identification string from <HOST>
+
+# Option: ignoreregex
+# Notes.: regex to ignore. If this regex matches, the line is ignored.
+# Values: TEXT
+#
+ignoreregex =
View
4 config/filter.d/sshd.conf
@@ -2,7 +2,7 @@
#
# Author: Cyril Jaquier
#
-# $Revision: 532 $
+# $Revision: 551 $
#
[Definition]
@@ -15,7 +15,7 @@
# Values: TEXT
#
failregex = Authentication failure for .* from <HOST>
- Failed [-/\w+]+ for .* from <HOST>
+ Failed [-/\w]+ for .* from <HOST>
ROOT LOGIN REFUSED .* FROM <HOST>
[iI](?:llegal|nvalid) user .* from <HOST>
View
27 config/jail.conf
@@ -2,7 +2,7 @@
#
# Author: Cyril Jaquier
#
-# $Revision: 524 $
+# $Revision: 552 $
#
# The DEFAULT allows a global definition of the options. They can be override
@@ -117,6 +117,31 @@ logpath = /var/log/vsftpd.log
maxretry = 5
bantime = 1800
+# Same as above but with banning the IP address.
+
+[vsftpd-iptables]
+
+enabled = false
+filter = vsftpd
+action = iptables[name=VSFTPD, port=ftp, protocol=tcp]
+ mail-whois[name=VSFTPD, dest=yourmail@mail.com]
+logpath = /var/log/vsftpd.log
+maxretry = 5
+bantime = 1800
+
+# Ban hosts which agent identifies spammer robots crawling the web
+# for email addresses. The mail outputs are buffered.
+
+[apache-badbots]
+
+enabled = false
+filter = apache-badbots
+action = iptables-multiport[name=BadBots, port="http,https"]
+ mail-buffered[name=BadBots, lines=5, dest=yourmail@mail.com]
+logpath = /var/www/*/logs/access_log
+bantime = 172800
+maxretry = 1
+
# Use shorewall instead of iptables.
[apache-shorewall]
View
8 files/gentoo-confd
@@ -0,0 +1,8 @@
+# Config file for /etc/init.d/fail2ban
+#
+# For information on options, see "/usr/bin/fail2ban-client -h".
+
+FAIL2BAN_OPTIONS=""
+
+# Force execution of the server even if the socket already exists:
+#FAIL2BAN_OPTIONS="-x"
View
32 files/gentoo-initd
@@ -17,11 +17,11 @@
#
# Author: Sireyessire, Cyril Jaquier
#
-# $Revision: 491 $
+# $Revision: 559 $
opts="start stop restart reload showlog"
-FAIL2BAN="/usr/bin/fail2ban-client"
+FAIL2BAN="/usr/bin/fail2ban-client ${FAIL2BAN_OPTIONS}"
depend() {
need net
@@ -42,29 +42,11 @@ stop() {
}
restart() {
- if ! service_stopped "${SVCNAME}" ; then
- svc_stop || return "$?"
- einfon "Waiting for server to shutdown ."
- cnt=0
- while [ 1 ]; do
- # Ping fail2ban-server
- ${FAIL2BAN} ping &> /dev/null
- if [ ! "$?" == "0" ]; then
- break
- fi
- cnt=`expr $cnt + 1`
- if [ $cnt -gt 60 ] ; then
- # We have waited 1 minute. Failed
- echo
- eend 1 "Failed"
- break
- fi
- sleep 1
- echo -n "."
- done
- echo
- fi
- svc_start
+ if ! service_stopped "${SVCNAME}" ; then
+ svc_stop || return "$?"
+ sleep 1
+ fi
+ svc_start
}
reload() {
View
94 server/action.py
@@ -16,11 +16,11 @@
# Author: Cyril Jaquier
#
-# $Revision: 434 $
+# $Revision: 556 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 434 $"
-__date__ = "$Date: 2006-10-24 21:49:31 +0200 (Tue, 24 Oct 2006) $"
+__version__ = "$Revision: 556 $"
+__date__ = "$Date: 2007-03-07 21:54:32 +0100 (Wed, 07 Mar 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
@@ -54,18 +54,48 @@ def __init__(self, name):
self.__actionStop = ''
logSys.debug("Created Action")
+ ##
+ # Sets the action name.
+ #
+ # @param name the name of the action
+
def setName(self, name):
self.__name = name
+ ##
+ # Returns the action name.
+ #
+ # @return the name of the action
+
def getName(self):
return self.__name
+ ##
+ # Sets a "CInfo".
+ #
+ # CInfo are statically defined properties. They can be definied by
+ # the user and are used to set e-mail addresses, port, host or
+ # anything that should not change during the life of the server.
+ #
+ # @param key the property name
+ # @param value the property value
+
def setCInfo(self, key, value):
self.__cInfo[key] = value
+ ##
+ # Returns a "CInfo".
+ #
+ # @param key the property name
+
def getCInfo(self, key):
return self.__cInfo[key]
+ ##
+ # Removes a "CInfo".
+ #
+ # @param key the property name
+
def delCInfo(self, key):
del self.__cInfo[key]
@@ -86,6 +116,14 @@ def setActionStart(self, value):
def getActionStart(self):
return self.__actionStart
+ ##
+ # Executes the action "start" command.
+ #
+ # Replaces the tags in the action command with value of "cInfo"
+ # and executes the resulting command.
+ #
+ # @return True if the command succeeded
+
def execActionStart(self):
startCmd = Action.replaceTag(self.__actionStart, self.__cInfo)
return Action.executeCmd(startCmd)
@@ -107,6 +145,11 @@ def setActionBan(self, value):
def getActionBan(self):
return self.__actionBan
+ ##
+ # Executes the action "ban" command.
+ #
+ # @return True if the command succeeded
+
def execActionBan(self, aInfo):
return self.__processCmd(self.__actionBan, aInfo)
@@ -127,6 +170,11 @@ def setActionUnban(self, value):
def getActionUnban(self):
return self.__actionUnban
+ ##
+ # Executes the action "unban" command.
+ #
+ # @return True if the command succeeded
+
def execActionUnban(self, aInfo):
return self.__processCmd(self.__actionUnban, aInfo)
@@ -164,10 +212,25 @@ def setActionStop(self, value):
def getActionStop(self):
return self.__actionStop
+ ##
+ # Executes the action "stop" command.
+ #
+ # Replaces the tags in the action command with value of "cInfo"
+ # and executes the resulting command.
+ #
+ # @return True if the command succeeded
+
def execActionStop(self):
stopCmd = Action.replaceTag(self.__actionStop, self.__cInfo)
return Action.executeCmd(stopCmd)
+ ##
+ # Replaces tags in query with property values in aInfo.
+ #
+ # @param query the query string with tags
+ # @param aInfo the properties
+ # @return a string
+
@staticmethod
def replaceTag(query, aInfo):
""" Replace tags in query
@@ -179,6 +242,19 @@ def replaceTag(query, aInfo):
string = string.replace("<br>", '\n')
return string
+ ##
+ # Executes a command with preliminary checks and substitutions.
+ #
+ # Before executing any commands, executes the "check" command first
+ # in order to check if prerequirements are met. If this check fails,
+ # it tries to restore a sane environnement before executing the real
+ # command.
+ # Replaces "aInfo" and "cInfo" in the query too.
+ #
+ # @param cmd The command to execute
+ # @param aInfo Dynamic properties
+ # @return True if the command succeeded
+
def __processCmd(self, cmd, aInfo = None):
""" Executes an OS command.
"""
@@ -209,6 +285,18 @@ def __processCmd(self, cmd, aInfo = None):
return Action.executeCmd(realCmd)
+ ##
+ # Executes a command.
+ #
+ # We need a shell here because commands are mainly shell script. They
+ # contain pipe, redirection, etc.
+ #
+ # @todo Force the use of bash!?
+ # @todo Kill the command after a given timeout
+ #
+ # @param realCmd the command to execute
+ # @return True if the command succeeded
+
@staticmethod
def executeCmd(realCmd):
logSys.debug(realCmd)
View
29 server/actions.py
@@ -16,11 +16,11 @@
# Author: Cyril Jaquier
#
-# $Revision: 535 $
+# $Revision: 556 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 535 $"
-__date__ = "$Date: 2007-01-29 22:46:59 +0100 (Mon, 29 Jan 2007) $"
+__version__ = "$Revision: 556 $"
+__date__ = "$Date: 2007-03-07 21:54:32 +0100 (Wed, 07 Mar 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
@@ -56,22 +56,45 @@ def __init__(self, jail):
## The ban manager.
self.__banManager = BanManager()
+ ##
+ # Adds an action.
+ #
+ # @param name The action name
+
def addAction(self, name):
action = Action(name)
self.__actions.append(action)
+ ##
+ # Removes an action.
+ #
+ # @param name The action name
+
def delAction(self, name):
for action in self.__actions:
if action.getName() == name:
self.__actions.remove(action)
break
+ ##
+ # Returns an action.
+ #
+ # Raises a KeyError exception if the action does not exist.
+ #
+ # @param name the action name
+ # @return the action
+
def getAction(self, name):
for action in self.__actions:
if action.getName() == name:
return action
raise KeyError
+ ##
+ # Returns the last defined action.
+ #
+ # @return The last defined action.
+
def getLastAction(self):
action = self.__actions.pop()
self.__actions.append(action)
View
22 server/banmanager.py
@@ -16,11 +16,11 @@
# Author: Cyril Jaquier
#
-# $Revision: 536 $
+# $Revision: 553 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 536 $"
-__date__ = "$Date: 2007-01-31 23:31:42 +0100 (Wed, 31 Jan 2007) $"
+__version__ = "$Revision: 553 $"
+__date__ = "$Date: 2007-02-26 00:53:22 +0100 (Mon, 26 Feb 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
@@ -62,9 +62,11 @@ def __init__(self):
# @param value the time
def setBanTime(self, value):
- self.__lock.acquire()
- self.__banTime = int(value)
- self.__lock.release()
+ try:
+ self.__lock.acquire()
+ self.__banTime = int(value)
+ finally:
+ self.__lock.release()
##
# Get the ban time.
@@ -85,9 +87,11 @@ def getBanTime(self):
# @param value total number
def setBanTotal(self, value):
- self.__lock.acquire()
- self.__banTotal = value
- self.__lock.release()
+ try:
+ self.__lock.acquire()
+ self.__banTotal = value
+ finally:
+ self.__lock.release()
##
# Get the total number of banned address.
View
143 server/datedetector.py
@@ -16,11 +16,11 @@
# Author: Cyril Jaquier
#
-# $Revision: 504 $
+# $Revision: 553 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 504 $"
-__date__ = "$Date: 2006-12-23 17:37:17 +0100 (Sat, 23 Dec 2006) $"
+__version__ = "$Revision: 553 $"
+__date__ = "$Date: 2007-02-26 00:53:22 +0100 (Mon, 26 Feb 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
@@ -42,44 +42,48 @@ def __init__(self):
self.__defTemplate = DateStrptime()
def addDefaultTemplate(self):
- # standard
- template = DateStrptime()
- template.setName("Month Day Hour:Minute:Second")
- template.setRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
- template.setPattern("%b %d %H:%M:%S")
- self.__templates.append(template)
- # asctime
- template = DateStrptime()
- template.setName("Weekday Month Day Hour:Minute:Second Year")
- template.setRegex("\S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}")
- template.setPattern("%a %b %d %H:%M:%S %Y")
- self.__templates.append(template)
- # simple date
- template = DateStrptime()
- template.setName("Year/Month/Day Hour:Minute:Second")
- template.setRegex("\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}")
- template.setPattern("%Y/%m/%d %H:%M:%S")
- self.__templates.append(template)
- # Apache format [31/Oct/2006:09:22:55 -0000]
- template = DateStrptime()
- template.setName("Day/Month/Year:Hour:Minute:Second")
- template.setRegex("\d{2}/\S{3}/\d{4}:\d{2}:\d{2}:\d{2}")
- template.setPattern("%d/%b/%Y:%H:%M:%S")
- self.__templates.append(template)
- # Exim 2006-12-21 06:43:20
- template = DateStrptime()
- template.setName("Year-Month-Day Hour:Minute:Second")
- template.setRegex("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")
- template.setPattern("%Y-%m-%d %H:%M:%S")
- self.__templates.append(template)
- # TAI64N
- template = DateTai64n()
- template.setName("TAI64N")
- self.__templates.append(template)
- # Epoch
- template = DateEpoch()
- template.setName("Epoch")
- self.__templates.append(template)
+ try:
+ self.__lock.acquire()
+ # standard
+ template = DateStrptime()
+ template.setName("Month Day Hour:Minute:Second")
+ template.setRegex("^\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
+ template.setPattern("%b %d %H:%M:%S")
+ self.__templates.append(template)
+ # asctime
+ template = DateStrptime()
+ template.setName("Weekday Month Day Hour:Minute:Second Year")
+ template.setRegex("\S{3} \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2} \d{4}")
+ template.setPattern("%a %b %d %H:%M:%S %Y")
+ self.__templates.append(template)
+ # simple date
+ template = DateStrptime()
+ template.setName("Year/Month/Day Hour:Minute:Second")
+ template.setRegex("\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}")
+ template.setPattern("%Y/%m/%d %H:%M:%S")
+ self.__templates.append(template)
+ # Apache format [31/Oct/2006:09:22:55 -0000]
+ template = DateStrptime()
+ template.setName("Day/Month/Year:Hour:Minute:Second")
+ template.setRegex("\d{2}/\S{3}/\d{4}:\d{2}:\d{2}:\d{2}")
+ template.setPattern("%d/%b/%Y:%H:%M:%S")
+ self.__templates.append(template)
+ # Exim 2006-12-21 06:43:20
+ template = DateStrptime()
+ template.setName("Year-Month-Day Hour:Minute:Second")
+ template.setRegex("\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}")
+ template.setPattern("%Y-%m-%d %H:%M:%S")
+ self.__templates.append(template)
+ # TAI64N
+ template = DateTai64n()
+ template.setName("TAI64N")
+ self.__templates.append(template)
+ # Epoch
+ template = DateEpoch()
+ template.setName("Epoch")
+ self.__templates.append(template)
+ finally:
+ self.__lock.release()
def getTemplates(self):
return self.__templates
@@ -100,14 +104,15 @@ def matchTime(self, line):
if self.__defTemplate.isValid():
return self.__defTemplate.matchDate(line)
else:
- self.__lock.acquire()
- for template in self.__templates:
- match = template.matchDate(line)
- if not match == None:
- self.__lock.release()
- return match
- self.__lock.release()
- return None
+ try:
+ self.__lock.acquire()
+ for template in self.__templates:
+ match = template.matchDate(line)
+ if not match == None:
+ return match
+ return None
+ finally:
+ self.__lock.release()
def getTime(self, line):
if self.__defTemplate.isValid():
@@ -117,19 +122,20 @@ def getTime(self, line):
except ValueError:
return None
else:
- self.__lock.acquire()
- for template in self.__templates:
- try:
- date = template.getDate(line)
- if date == None:
- continue
- template.incHits()
- self.__lock.release()
- return date
- except ValueError:
- pass
- self.__lock.release()
- return None
+ try:
+ self.__lock.acquire()
+ for template in self.__templates:
+ try:
+ date = template.getDate(line)
+ if date == None:
+ continue
+ template.incHits()
+ return date
+ except ValueError:
+ pass
+ return None
+ finally:
+ self.__lock.release()
def getUnixTime(self, line):
date = self.getTime(line)
@@ -143,8 +149,11 @@ def getUnixTime(self, line):
# in this object and thus should be called from time to time.
def sortTemplate(self):
- self.__lock.acquire()
- logSys.debug("Sorting the template list")
- self.__templates.sort(cmp = lambda x, y: cmp(x.getHits(), y.getHits()),
- reverse=True)
- self.__lock.release()
+ try:
+ self.__lock.acquire()
+ logSys.debug("Sorting the template list")
+ self.__templates.sort(cmp = lambda x, y:
+ cmp(x.getHits(), y.getHits()),
+ reverse = True)
+ finally:
+ self.__lock.release()
View
75 server/failmanager.py
@@ -16,11 +16,11 @@
# Author: Cyril Jaquier
#
-# $Revision: 537 $
+# $Revision: 553 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 537 $"
-__date__ = "$Date: 2007-02-01 21:50:12 +0100 (Thu, 01 Feb 2007) $"
+__version__ = "$Revision: 553 $"
+__date__ = "$Date: 2007-02-26 00:53:22 +0100 (Mon, 26 Feb 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
@@ -42,9 +42,11 @@ def __init__(self):
self.__failTotal = 0
def setFailTotal(self, value):
- self.__lock.acquire()
- self.__failTotal = value
- self.__lock.release()
+ try:
+ self.__lock.acquire()
+ self.__failTotal = value
+ finally:
+ self.__lock.release()
def getFailTotal(self):
try:
@@ -54,9 +56,11 @@ def getFailTotal(self):
self.__lock.release()
def setMaxRetry(self, value):
- self.__lock.acquire()
- self.__maxRetry = value
- self.__lock.release()
+ try:
+ self.__lock.acquire()
+ self.__maxRetry = value
+ finally:
+ self.__lock.release()
def getMaxRetry(self):
try:
@@ -66,9 +70,11 @@ def getMaxRetry(self):
self.__lock.release()
def setMaxTime(self, value):
- self.__lock.acquire()
- self.__maxTime = value
- self.__lock.release()
+ try:
+ self.__lock.acquire()
+ self.__maxTime = value
+ finally:
+ self.__lock.release()
def getMaxTime(self):
try:
@@ -78,20 +84,22 @@ def getMaxTime(self):
self.__lock.release()
def addFailure(self, ticket):
- self.__lock.acquire()
- ip = ticket.getIP()
- unixTime = ticket.getTime()
- if self.__failList.has_key(ip):
- fData = self.__failList[ip]
- fData.inc()
- fData.setLastTime(unixTime)
- else:
- fData = FailData()
- fData.inc()
- fData.setLastTime(unixTime)
- self.__failList[ip] = fData
- self.__failTotal += 1
- self.__lock.release()
+ try:
+ self.__lock.acquire()
+ ip = ticket.getIP()
+ unixTime = ticket.getTime()
+ if self.__failList.has_key(ip):
+ fData = self.__failList[ip]
+ fData.inc()
+ fData.setLastTime(unixTime)
+ else:
+ fData = FailData()
+ fData.inc()
+ fData.setLastTime(unixTime)
+ self.__failList[ip] = fData
+ self.__failTotal += 1
+ finally:
+ self.__lock.release()
def size(self):
try:
@@ -101,12 +109,14 @@ def size(self):
self.__lock.release()
def cleanup(self, time):
- self.__lock.acquire()
- tmp = self.__failList.copy()
- for item in tmp:
- if tmp[item].getLastTime() < time - self.__maxTime:
- self.__delFailure(item)
- self.__lock.release()
+ try:
+ self.__lock.acquire()
+ tmp = self.__failList.copy()
+ for item in tmp:
+ if tmp[item].getLastTime() < time - self.__maxTime:
+ self.__delFailure(item)
+ finally:
+ self.__lock.release()
def __delFailure(self, ip):
if self.__failList.has_key(ip):
@@ -129,4 +139,3 @@ def toBan(self):
class FailManagerEmpty(Exception):
pass
-
View
32 server/mytime.py
@@ -16,24 +16,45 @@
# Author: Cyril Jaquier
#
-# $Revision: 504 $
+# $Revision: 556 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 504 $"
-__date__ = "$Date: 2006-12-23 17:37:17 +0100 (Sat, 23 Dec 2006) $"
+__version__ = "$Revision: 556 $"
+__date__ = "$Date: 2007-03-07 21:54:32 +0100 (Wed, 07 Mar 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import time
+##
+# MyTime class.
+#
+# This class is a wrapper around time.time() and time.gmtime(). When
+# performing unit test, it is very useful to get a fixed value from these
+# functions.
+# Thus, time.time() and time.gmtime() should never be called directly.
+# This wrapper should be called instead. The API are equivalent.
+
class MyTime:
myTime = None
+ ##
+ # Sets the current time.
+ #
+ # Use None in order to always get the real current time.
+ #
+ # @param t the time to set or None
+
@staticmethod
def setTime(t):
MyTime.myTime = t
+ ##
+ # Equivalent to time.time()
+ #
+ # @return time.time() if setTime was called with None
+
@staticmethod
def time():
if MyTime.myTime == None:
@@ -41,6 +62,11 @@ def time():
else:
return MyTime.myTime
+ ##
+ # Equivalent to time.gmtime()
+ #
+ # @return time.gmtime() if setTime was called with None
+
@staticmethod
def gmtime():
if MyTime.myTime == None:
View
13 server/ssocket.py
@@ -16,11 +16,11 @@
# Author: Cyril Jaquier
#
-# $Revision: 443 $
+# $Revision: 555 $
__author__ = "Cyril Jaquier"
-__version__ = "$Revision: 443 $"
-__date__ = "$Date: 2006-11-01 00:36:59 +0100 (Wed, 01 Nov 2006) $"
+__version__ = "$Revision: 555 $"
+__date__ = "$Date: 2007-03-07 21:53:37 +0100 (Wed, 07 Mar 2007) $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
@@ -68,7 +68,7 @@ def initialize(self, sock = "/tmp/fail2ban.sock", force = False):
#self.__ssock.bind(("localhost", 2222))
self.__ssock.bind(sock)
# Become a server socket
- self.__ssock.listen(5)
+ self.__ssock.listen(1)
def run(self):
self.__isRunning = True
@@ -80,6 +80,9 @@ def run(self):
except socket.timeout:
# Do nothing here
pass
+ except socket.error:
+ # Do nothing here
+ pass
self.__ssock.close()
# Remove socket
if os.path.exists(self.__socket):
@@ -122,7 +125,7 @@ def __send(sock, msg):
def __receive(sock):
msg = ''
while msg.rfind(SSocket.END_STRING) == -1:
- chunk = sock.recv(6)
+ chunk = sock.recv(128)
if chunk == '':
raise RuntimeError, "socket connection broken"
msg = msg + chunk
View
1  testcases/files/testcase02.log
@@ -11,4 +11,3 @@ Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:141.
Aug 14 11:59:01 i60p295 sshd[12365]: Accepted keyboard-interactive/pam for roehl from ::ffff:141.3.81.106 port 51332 ssh2
Aug 14 11:59:01 i60p295 sshd[12365]: Accepted keyboard-interactive/pam for roehl from ::ffff:141.3.81.106 port 51332 ssh2
Aug 14 11:59:01 i60p295 sshd[12365]: Accepted keyboard-interactive/pam for roehl from ::ffff:141.3.81.106 port 51332 ssh2
-Aug 14 11:59:59 i60p295 sshd[11437]: Failed password for illegal user from from toto.com from ::ffff:66.38.192.238 port 51381 ssh2
Please sign in to comment.
Something went wrong with that request. Please try again.