Upgraded to fresh upstream 0.7.8

debian-upstream sdist/0.7.8
Yaroslav Halchenko 2007-10-16 17:01:22 -04:00
commit d77f67bb89
24 changed files with 558 additions and 172 deletions

View File

@ -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 File

@ -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

8
README
View File

@ -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:
--------

14
TODO
View File

@ -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 File

@ -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 @@ class Beautifier:
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 File

@ -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 File

@ -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 File

@ -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 File

@ -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 =

23
config/filter.d/exim.conf Normal file
View File

@ -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 File

@ -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 File

@ -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 File

@ -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 File

@ -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]

8
files/gentoo-confd Normal file
View File

@ -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 File

@ -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 File

@ -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 @@ class Action:
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 @@ class Action:
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 @@ class Action:
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 @@ class Action:
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 @@ class Action:
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 @@ class Action:
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 @@ class Action:
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 File

@ -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 @@ class Actions(JailThread):
## 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 File

@ -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 @@ class BanManager:
# @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 @@ class BanManager:
# @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 File

@ -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 @@ class DateDetector:
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 @@ class DateDetector:
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 @@ class DateDetector:
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 @@ class DateDetector:
# 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 File

@ -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 @@ class FailManager:
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 @@ class FailManager:
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 @@ class FailManager:
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 @@ class FailManager:
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 @@ class FailManager:
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 @@ class FailManager:
class FailManagerEmpty(Exception):
pass

View File

@ -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 @@ class MyTime:
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 File

@ -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 @@ class SSocket(Thread):
#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 @@ class SSocket(Thread):
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 @@ class SocketWorker(Thread):
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 File

@ -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