Merge remote-tracking branch 'remotes/upstream/master', fix test cases (see bellow)

Conflicts resolved:
	ChangeLog
	fail2ban/server/filter.py
	fail2ban/server/jail.py
	fail2ban/tests/actionstestcase.py
Test cases fixed:
	testBanActionsAInfo - fail ticket with current time (otherwise ticket will be ignored - ban time too old)
	testFail2BanExceptHook - use local sys.__excepthook__ to check was really executed and prevent write error in stderr.
pull/716/head
sebres 2014-06-24 14:02:24 +02:00
commit 00b7205a3c
58 changed files with 301 additions and 323 deletions

View File

@ -10,6 +10,11 @@ Fail2Ban (version 0.9.0.dev) 2014/xx/xx
ver. 0.9.1 (2014/xx/xx) - better, faster, stronger ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
---------- ----------
- Refactoring (IMPORTANT -- Please review your setup and configuration):
* iptables-common.conf replaced iptables-blocktype.conf
(iptables-blocktype.local should still be read) and now also
provides defaults for the chain, port, protocol and name tags
- Fixes: - Fixes:
* systemd backend error on bad utf-8 in python3 * systemd backend error on bad utf-8 in python3
* badips.py action error when logging HTTP error raised with badips request * badips.py action error when logging HTTP error raised with badips request
@ -27,18 +32,23 @@ ver. 0.9.1 (2014/xx/xx) - better, faster, stronger
* Database now returns persistent bans on restart (bantime < 0) * Database now returns persistent bans on restart (bantime < 0)
* Recursive action tags now fully processed. Fixes issue with bsd-ipfw * Recursive action tags now fully processed. Fixes issue with bsd-ipfw
action action
* Correct times for non-timezone date times formats during DST.
* Fixed TypeError with "ipfailures" and "ipjailfailures" action tags. * Fixed TypeError with "ipfailures" and "ipjailfailures" action tags.
Thanks Serg G. Brester (sebres) Thanks Serg G. Brester (sebres)
* Correct times for non-timezone date times formats during DST
Thanks Serg G. Brester (sebres)
* Pass a copy of, not original, aInfo into actions to avoid side-effects
- New features: - New features:
- Added monit filter thanks Jason H Martin. - Added monit filter thanks Jason H Martin.
- Enhancements - Enhancements
* Fail2ban-regex - add print-all-matched option. Closes gh-652 * Fail2ban-regex - add print-all-matched option. Closes gh-652
* Suppress fail2ban-client warnings for non-critical config options * Suppress fail2ban-client warnings for non-critical config options
* Match non "Bye Bye" disconnect messages for sshd locked account regex * Match non "Bye Bye" disconnect messages for sshd locked account regex
* Add <chain> tag to iptables-ipsets
* Realign fail2ban log output with white space to improve readability. Does
not affect SYSLOG output
* Log unhandled exceptions
ver. 0.9.0 (2014/03/14) - beta ver. 0.9.0 (2014/03/14) - beta
---------- ----------

View File

@ -258,7 +258,7 @@ config/action.d/dummy.conf
config/action.d/firewallcmd-new.conf config/action.d/firewallcmd-new.conf
config/action.d/firewallcmd-ipset.conf config/action.d/firewallcmd-ipset.conf
config/action.d/iptables-ipset-proto6-allports.conf config/action.d/iptables-ipset-proto6-allports.conf
config/action.d/iptables-blocktype.conf config/action.d/iptables-common.conf
config/action.d/iptables-ipset-proto4.conf config/action.d/iptables-ipset-proto4.conf
config/action.d/iptables-ipset-proto6.conf config/action.d/iptables-ipset-proto6.conf
config/action.d/iptables-xt_recent-echo.conf config/action.d/iptables-xt_recent-echo.conf

1
THANKS
View File

@ -87,6 +87,7 @@ Robert Edeker
Rolf Fokkens Rolf Fokkens
Roman Gelfand Roman Gelfand
Russell Odom Russell Odom
SATO Kentaro
Sebastian Arcus Sebastian Arcus
Serg G. Brester (sebres) Serg G. Brester (sebres)
Sireyessire Sireyessire

View File

@ -30,9 +30,10 @@ from fail2ban.protocol import printFormatted
from fail2ban.client.csocket import CSocket from fail2ban.client.csocket import CSocket
from fail2ban.client.configurator import Configurator from fail2ban.client.configurator import Configurator
from fail2ban.client.beautifier import Beautifier from fail2ban.client.beautifier import Beautifier
from fail2ban.helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.client") logSys = getLogger("fail2ban")
## ##
# #

View File

@ -45,9 +45,9 @@ from fail2ban.client.filterreader import FilterReader
from fail2ban.server.filter import Filter from fail2ban.server.filter import Filter
from fail2ban.server.failregex import RegexException from fail2ban.server.failregex import RegexException
from fail2ban.helpers import FormatterWithTraceBack from fail2ban.helpers import FormatterWithTraceBack, getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger("fail2ban") logSys = getLogger("fail2ban")
def debuggexURL(sample, regex): def debuggexURL(sample, regex):
q = urllib.urlencode({ 're': regex.replace('<HOST>', '(?&.ipv4)'), q = urllib.urlencode({ 're': regex.replace('<HOST>', '(?&.ipv4)'),

View File

@ -22,13 +22,14 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import getopt, sys, logging, os import getopt, sys, os
from fail2ban.version import version from fail2ban.version import version
from fail2ban.server.server import Server from fail2ban.server.server import Server
from fail2ban.helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger("fail2ban") logSys = getLogger("fail2ban")
## ##
# \mainpage Fail2Ban # \mainpage Fail2Ban

View File

@ -24,8 +24,8 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012- Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012- Yaroslav Halchenko"
__license__ = "GPL" __license__ = "GPL"
import logging
import unittest, logging, sys, time, os import unittest, sys, time, os
# Check if local fail2ban module exists, and use if it exists by # Check if local fail2ban module exists, and use if it exists by
# modifying the path. This is such that tests can be used in dev # modifying the path. This is such that tests can be used in dev
@ -35,7 +35,7 @@ if os.path.exists("fail2ban/__init__.py"):
from fail2ban.version import version from fail2ban.version import version
from fail2ban.tests.utils import gatherTests from fail2ban.tests.utils import gatherTests
from fail2ban.helpers import FormatterWithTraceBack from fail2ban.helpers import FormatterWithTraceBack, getLogger
from fail2ban.server.mytime import MyTime from fail2ban.server.mytime import MyTime
from optparse import OptionParser, Option from optparse import OptionParser, Option
@ -70,7 +70,7 @@ parser = get_opt_parser()
# #
# Logging # Logging
# #
logSys = logging.getLogger("fail2ban") logSys = getLogger("fail2ban")
# Numerical level of verbosity corresponding to a log "level" # Numerical level of verbosity corresponding to a log "level"
verbosity = {'heavydebug': 4, verbosity = {'heavydebug': 4,

View File

@ -14,7 +14,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -31,22 +31,6 @@ actionunban = ipset del fail2ban-<name> <ip> -exist
[Init] [Init]
# Default name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ]
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ]
#
protocol = tcp
# Option: chain # Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be # Notes specifies the iptables chain to which the fail2ban rules should be
# added # added

View File

@ -4,7 +4,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -24,22 +24,6 @@ actionunban = firewall-cmd --direct --remove-rule ipv4 filter f2b-<name> 0 -s <i
[Init] [Init]
# Default name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ]
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ]
#
protocol = tcp
# Option: chain # Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be # Notes specifies the iptables chain to which the fail2ban rules should be
# added # added

View File

@ -8,7 +8,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -53,18 +53,3 @@ actionunban = iptables -D f2b-<name> -s <ip> -j <blocktype>
[Init] [Init]
# Default name of the chain
#
name = default
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
# Values: STRING Default: INPUT
chain = INPUT

View File

@ -1,22 +0,0 @@
# Fail2Ban configuration file
#
# Author: Daniel Black
#
# This is a included configuration file and includes the defination for the blocktype
# used in all iptables based actions by default.
#
# The user can override the default in iptables-blocktype.local
[INCLUDES]
after = iptables-blocktype.local
[Init]
# Option: blocktype
# Note: This is what the action does with rules. This can be any jump target
# as per the iptables man page (section 8). Common values are DROP
# REJECT, REJECT --reject-with icmp-port-unreachable
# Values: STRING
blocktype = REJECT --reject-with icmp-port-unreachable

View File

@ -0,0 +1,45 @@
# Fail2Ban configuration file
#
# Author: Daniel Black
#
# This is a included configuration file and includes the definitions for the iptables
# used in all iptables based actions by default.
#
# The user can override the defaults in iptables-common.local
[INCLUDES]
after = iptables-blocktype.local
iptables-common.local
# iptables-blocktype.local is obsolete
[Init]
# Option: chain
# Notes specifies the iptables chain to which the Fail2Ban rules should be
# added
# Values: STRING Default: INPUT
chain = INPUT
# Default name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: blocktype
# Note: This is what the action does with rules. This can be any jump target
# as per the iptables man page (section 8). Common values are DROP
# REJECT, REJECT --reject-with icmp-port-unreachable
# Values: STRING
blocktype = REJECT --reject-with icmp-port-unreachable

View File

@ -19,7 +19,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -28,13 +28,13 @@ before = iptables-blocktype.conf
# Values: CMD # Values: CMD
# #
actionstart = ipset --create f2b-<name> iphash actionstart = ipset --create f2b-<name> iphash
iptables -I INPUT -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype> iptables -I <chain> -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype>
# Option: actionstop # Option: actionstop
# Notes.: command executed once at the end of Fail2Ban # Notes.: command executed once at the end of Fail2Ban
# Values: CMD # Values: CMD
# #
actionstop = iptables -D INPUT -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype> actionstop = iptables -D <chain> -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype>
ipset --flush f2b-<name> ipset --flush f2b-<name>
ipset --destroy f2b-<name> ipset --destroy f2b-<name>
@ -56,18 +56,3 @@ actionunban = ipset --test f2b-<name> <ip> && ipset --del f2b-<name> <ip>
[Init] [Init]
# Default name of the ipset
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default: ssh
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp

View File

@ -15,8 +15,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -25,13 +24,13 @@ before = iptables-blocktype.conf
# Values: CMD # Values: CMD
# #
actionstart = ipset create f2b-<name> hash:ip timeout <bantime> actionstart = ipset create f2b-<name> hash:ip timeout <bantime>
iptables -I INPUT -m set --match-set f2b-<name> src -j <blocktype> iptables -I <chain> -m set --match-set f2b-<name> src -j <blocktype>
# Option: actionstop # Option: actionstop
# Notes.: command executed once at the end of Fail2Ban # Notes.: command executed once at the end of Fail2Ban
# Values: CMD # Values: CMD
# #
actionstop = iptables -D INPUT -m set --match-set f2b-<name> src -j <blocktype> actionstop = iptables -D <chain> -m set --match-set f2b-<name> src -j <blocktype>
ipset flush f2b-<name> ipset flush f2b-<name>
ipset destroy f2b-<name> ipset destroy f2b-<name>
@ -53,12 +52,8 @@ actionunban = ipset del f2b-<name> <ip> -exist
[Init] [Init]
# Default name of the ipset
#
name = default
# Option: bantime # Option: bantime
# Notes: specifies the bantime in seconds (handled internally rather than by fail2ban) # Notes: specifies the bantime in seconds (handled internally rather than by fail2ban)
# Values: [ NUM ] Default: 600 # Values: [ NUM ] Default: 600
#
bantime = 600 bantime = 600

View File

@ -15,8 +15,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -25,13 +24,13 @@ before = iptables-blocktype.conf
# Values: CMD # Values: CMD
# #
actionstart = ipset create f2b-<name> hash:ip timeout <bantime> actionstart = ipset create f2b-<name> hash:ip timeout <bantime>
iptables -I INPUT -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype> iptables -I <chain> -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype>
# Option: actionstop # Option: actionstop
# Notes.: command executed once at the end of Fail2Ban # Notes.: command executed once at the end of Fail2Ban
# Values: CMD # Values: CMD
# #
actionstop = iptables -D INPUT -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype> actionstop = iptables -D <chain> -p <protocol> -m multiport --dports <port> -m set --match-set f2b-<name> src -j <blocktype>
ipset flush f2b-<name> ipset flush f2b-<name>
ipset destroy f2b-<name> ipset destroy f2b-<name>
@ -53,24 +52,8 @@ actionunban = ipset del f2b-<name> <ip> -exist
[Init] [Init]
# Default name of the ipset
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default: ssh
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: bantime # Option: bantime
# Notes: specifies the bantime in seconds (handled internally rather than by fail2ban) # Notes: specifies the bantime in seconds (handled internally rather than by fail2ban)
# Values: [ NUM ] Default: 600 # Values: [ NUM ] Default: 600
#
bantime = 600 bantime = 600

View File

@ -11,7 +11,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -60,24 +60,3 @@ actionunban = iptables -D f2b-<name> -s <ip> -j f2b-<name>-log
[Init] [Init]
# Default name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
# Values: STRING Default: INPUT
chain = INPUT

View File

@ -6,7 +6,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -50,24 +50,3 @@ actionunban = iptables -D f2b-<name> -s <ip> -j <blocktype>
[Init] [Init]
# Default name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
# Values: STRING Default: INPUT
chain = INPUT

View File

@ -8,8 +8,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -53,24 +52,3 @@ actionunban = iptables -D f2b-<name> -s <ip> -j <blocktype>
[Init] [Init]
# Default name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
# Values: STRING Default: INPUT
chain = INPUT

View File

@ -6,8 +6,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -33,14 +32,14 @@ before = iptables-blocktype.conf
# own rules. The 3600 second timeout is independent and acts as a # own rules. The 3600 second timeout is independent and acts as a
# safeguard in case the fail2ban process dies unexpectedly. The # safeguard in case the fail2ban process dies unexpectedly. The
# shorter of the two timeouts actually matters. # shorter of the two timeouts actually matters.
actionstart = if [ `id -u` -eq 0 ];then iptables -I INPUT -m recent --update --seconds 3600 --name f2b-<name> -j <blocktype>;fi actionstart = if [ `id -u` -eq 0 ];then iptables -I <chain> -m recent --update --seconds 3600 --name f2b-<name> -j <blocktype>;fi
# Option: actionstop # Option: actionstop
# Notes.: command executed once at the end of Fail2Ban # Notes.: command executed once at the end of Fail2Ban
# Values: CMD # Values: CMD
# #
actionstop = echo / > /proc/net/xt_recent/f2b-<name> actionstop = echo / > /proc/net/xt_recent/f2b-<name>
if [ `id -u` -eq 0 ];then iptables -D INPUT -m recent --update --seconds 3600 --name f2b-<name> -j <blocktype>;fi if [ `id -u` -eq 0 ];then iptables -D <chain> -m recent --update --seconds 3600 --name f2b-<name> -j <blocktype>;fi
# Option: actioncheck # Option: actioncheck
# Notes.: command executed once before each actionban command # Notes.: command executed once before each actionban command
@ -66,12 +65,3 @@ actionunban = echo -<ip> > /proc/net/xt_recent/f2b-<name>
[Init] [Init]
# Default name of the chain
#
name = default
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp

View File

@ -6,7 +6,7 @@
[INCLUDES] [INCLUDES]
before = iptables-blocktype.conf before = iptables-common.conf
[Definition] [Definition]
@ -50,24 +50,3 @@ actionunban = iptables -D f2b-<name> -s <ip> -j <blocktype>
[Init] [Init]
# Default name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
# Option: chain
# Notes specifies the iptables chain to which the fail2ban rules should be
# added
# Values: STRING Default: INPUT
chain = INPUT

View File

@ -45,7 +45,7 @@ messages['ban'] = {}
messages['ban']['head'] = \ messages['ban']['head'] = \
"""Hi, """Hi,
The IP %(ip)s has just been banned for %(bantime)s seconds The IP %(ip)s has just been banned for %(bantime)i seconds
by Fail2Ban after %(failures)i attempts against %(jailname)s. by Fail2Ban after %(failures)i attempts against %(jailname)s.
""" """
messages['ban']['tail'] = \ messages['ban']['tail'] = \

View File

@ -21,7 +21,7 @@ before = common.conf
[Definition] [Definition]
_daemon = fail2ban\.server\.actions _daemon = fail2ban\.actions\s*
# The name of the jail that this filter is used for. In jail.conf, name the # The name of the jail that this filter is used for. In jail.conf, name the
# jail using this filter 'recidive', or change this line! # jail using this filter 'recidive', or change this line!

View File

@ -24,12 +24,13 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging, os import os
from .configreader import ConfigReader, DefinitionInitConfigReader from .configreader import ConfigReader, DefinitionInitConfigReader
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class ActionReader(DefinitionInitConfigReader): class ActionReader(DefinitionInitConfigReader):

View File

@ -21,12 +21,11 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2013- Yaroslav Halchenko"
__license__ = "GPL" __license__ = "GPL"
import logging
from ..exceptions import UnknownJailException, DuplicateJailException from ..exceptions import UnknownJailException, DuplicateJailException
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
## ##
# Beautify the output of the client. # Beautify the output of the client.

View File

@ -24,7 +24,8 @@ __author__ = 'Yaroslav Halhenko'
__copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko' __copyright__ = 'Copyright (c) 2007 Yaroslav Halchenko'
__license__ = 'GPL' __license__ = 'GPL'
import logging, os, sys import os, sys
from ..helpers import getLogger
if sys.version_info >= (3,2): # pragma: no cover if sys.version_info >= (3,2): # pragma: no cover
@ -60,7 +61,7 @@ else: # pragma: no cover
from ConfigParser import SafeConfigParser from ConfigParser import SafeConfigParser
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
__all__ = ['SafeConfigParserWithIncludes'] __all__ = ['SafeConfigParserWithIncludes']

View File

@ -24,13 +24,14 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import glob, logging, os import glob, os
from ConfigParser import NoOptionError, NoSectionError from ConfigParser import NoOptionError, NoSectionError
from .configparserinc import SafeConfigParserWithIncludes from .configparserinc import SafeConfigParserWithIncludes
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class ConfigReader(SafeConfigParserWithIncludes): class ConfigReader(SafeConfigParserWithIncludes):

View File

@ -24,13 +24,12 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging
from .fail2banreader import Fail2banReader from .fail2banreader import Fail2banReader
from .jailsreader import JailsReader from .jailsreader import JailsReader
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class Configurator: class Configurator:

View File

@ -24,12 +24,11 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging
from .configreader import ConfigReader from .configreader import ConfigReader
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class Fail2banReader(ConfigReader): class Fail2banReader(ConfigReader):

View File

@ -24,13 +24,14 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging, os, shlex import os, shlex
from .configreader import ConfigReader, DefinitionInitConfigReader from .configreader import ConfigReader, DefinitionInitConfigReader
from ..server.action import CommandAction from ..server.action import CommandAction
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class FilterReader(DefinitionInitConfigReader): class FilterReader(DefinitionInitConfigReader):

View File

@ -24,15 +24,16 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging, re, glob, os.path import re, glob, os.path
import json import json
from .configreader import ConfigReader from .configreader import ConfigReader
from .filterreader import FilterReader from .filterreader import FilterReader
from .actionreader import ActionReader from .actionreader import ActionReader
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class JailReader(ConfigReader): class JailReader(ConfigReader):

View File

@ -24,13 +24,12 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging
from .configreader import ConfigReader from .configreader import ConfigReader
from .jailreader import JailReader from .jailreader import JailReader
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class JailsReader(ConfigReader): class JailsReader(ConfigReader):

View File

@ -107,3 +107,17 @@ class FormatterWithTraceBack(logging.Formatter):
def format(self, record): def format(self, record):
record.tbc = record.tb = self._tb() record.tbc = record.tb = self._tb()
return logging.Formatter.format(self, record) return logging.Formatter.format(self, record)
def getLogger(name):
"""Get logging.Logger instance with Fail2Ban logger name convention
"""
if "." in name:
name = "fail2ban.%s" % name.rpartition(".")[-1]
return logging.getLogger(name)
def excepthook(exctype, value, traceback):
"""Except hook used to log unhandled exceptions to Fail2Ban log
"""
getLogger("fail2ban").critical(
"Unhandled exception in Fail2Ban:", exc_info=True)
return sys.__excepthook__(exctype, value, traceback)

View File

@ -25,10 +25,11 @@ import logging, os, subprocess, time, signal, tempfile
import threading, re import threading, re
from abc import ABCMeta from abc import ABCMeta
from collections import MutableMapping from collections import MutableMapping
#from subprocess import call
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
# Create a lock for running system commands # Create a lock for running system commands
_cmd_lock = threading.Lock() _cmd_lock = threading.Lock()
@ -68,6 +69,9 @@ class CallingMap(MutableMapping):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.data = dict(*args, **kwargs) self.data = dict(*args, **kwargs)
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.data)
def __getitem__(self, key): def __getitem__(self, key):
value = self.data[key] value = self.data[key]
if callable(value): if callable(value):
@ -87,6 +91,9 @@ class CallingMap(MutableMapping):
def __len__(self): def __len__(self):
return len(self.data) return len(self.data)
def copy(self):
return self.__class__(self.data.copy())
class ActionBase(object): class ActionBase(object):
"""An abstract base class for actions in Fail2Ban. """An abstract base class for actions in Fail2Ban.
@ -135,8 +142,7 @@ class ActionBase(object):
def __init__(self, jail, name): def __init__(self, jail, name):
self._jail = jail self._jail = jail
self._name = name self._name = name
self._logSys = logging.getLogger( self._logSys = getLogger("fail2ban.%s" % self.__class__.__name__)
'%s.%s' % (__name__, self.__class__.__name__))
def start(self): def start(self):
"""Executed when the jail/action is started. """Executed when the jail/action is started.

View File

@ -42,9 +42,10 @@ from .observer import Observers
from .jailthread import JailThread from .jailthread import JailThread
from .action import ActionBase, CommandAction, CallingMap from .action import ActionBase, CommandAction, CallingMap
from .mytime import MyTime from .mytime import MyTime
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class Actions(JailThread, Mapping): class Actions(JailThread, Mapping):
"""Handles jail actions. """Handles jail actions.
@ -299,11 +300,12 @@ class Actions(JailThread, Mapping):
# do actions : # do actions :
for name, action in self._actions.iteritems(): for name, action in self._actions.iteritems():
try: try:
action.ban(aInfo) action.ban(aInfo.copy())
except Exception as e: except Exception as e:
logSys.error( logSys.error(
"Failed to execute ban jail '%s' action '%s': %s", "Failed to execute ban jail '%s' action '%s' "
self._jail.name, name, e, "info '%r': %s",
self._jail.name, name, aInfo, e,
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
return True return True
else: else:
@ -347,11 +349,12 @@ class Actions(JailThread, Mapping):
logSys.notice("[%s] Unban %s" % (self._jail.name, aInfo["ip"])) logSys.notice("[%s] Unban %s" % (self._jail.name, aInfo["ip"]))
for name, action in self._actions.iteritems(): for name, action in self._actions.iteritems():
try: try:
action.unban(aInfo) action.unban(aInfo.copy())
except Exception as e: except Exception as e:
logSys.error( logSys.error(
"Failed to execute unban jail '%s' action '%s': %s", "Failed to execute unban jail '%s' action '%s' "
self._jail.name, name, e, "info '%r': %s",
self._jail.name, name, aInfo, e,
exc_info=logSys.getEffectiveLevel()<=logging.DEBUG) exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
@property @property

View File

@ -25,12 +25,12 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
from pickle import dumps, loads, HIGHEST_PROTOCOL from pickle import dumps, loads, HIGHEST_PROTOCOL
import asyncore, asynchat, socket, os, logging, sys, traceback, fcntl import asyncore, asynchat, socket, os, sys, traceback, fcntl
from .. import helpers from ..helpers import getLogger,formatExceptionInfo
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
if sys.version_info >= (3,): if sys.version_info >= (3,):
# b"" causes SyntaxError in python <= 2.5, so below implements equivalent # b"" causes SyntaxError in python <= 2.5, so below implements equivalent
@ -81,7 +81,7 @@ class RequestHandler(asynchat.async_chat):
self.close_when_done() self.close_when_done()
def handle_error(self): def handle_error(self):
e1, e2 = helpers.formatExceptionInfo() e1, e2 = formatExceptionInfo()
logSys.error("Unexpected communication error: %s" % str(e2)) logSys.error("Unexpected communication error: %s" % str(e2))
logSys.error(traceback.format_exc().splitlines()) logSys.error(traceback.format_exc().splitlines())
self.close() self.close()

View File

@ -24,14 +24,14 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging
from threading import Lock from threading import Lock
from .ticket import BanTicket from .ticket import BanTicket
from .mytime import MyTime from .mytime import MyTime
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
## ##
# Banning Manager. # Banning Manager.

View File

@ -21,7 +21,6 @@ __author__ = "Steven Hiscocks"
__copyright__ = "Copyright (c) 2013 Steven Hiscocks" __copyright__ = "Copyright (c) 2013 Steven Hiscocks"
__license__ = "GPL" __license__ = "GPL"
import logging
import sys import sys
import shutil, time import shutil, time
import sqlite3 import sqlite3
@ -32,9 +31,10 @@ from threading import Lock
from .mytime import MyTime from .mytime import MyTime
from .ticket import FailTicket from .ticket import FailTicket
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
if sys.version_info >= (3,): if sys.version_info >= (3,):
sqlite3.register_adapter( sqlite3.register_adapter(

View File

@ -21,13 +21,13 @@ __author__ = "Cyril Jaquier and Fail2Ban Contributors"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging
from threading import Lock from threading import Lock
from .datetemplate import DatePatternRegex, DateTai64n, DateEpoch from .datetemplate import DatePatternRegex, DateTai64n, DateEpoch
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class DateDetector(object): class DateDetector(object):
"""Manages one or more date templates to find a date within a log line. """Manages one or more date templates to find a date within a log line.

View File

@ -25,12 +25,12 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import re import re
import logging
from abc import abstractmethod from abc import abstractmethod
from .strptime import reGroupDictStrptime, timeRE from .strptime import reGroupDictStrptime, timeRE
from ..helpers import getLogger
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class DateTemplate(object): class DateTemplate(object):

View File

@ -24,10 +24,10 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class FailData: class FailData:

View File

@ -29,9 +29,10 @@ import logging
from .faildata import FailData from .faildata import FailData
from .ticket import FailTicket from .ticket import FailTicket
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class FailManager: class FailManager:

View File

@ -21,7 +21,7 @@ __author__ = "Cyril Jaquier and Fail2Ban Contributors"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2011-2013 Yaroslav Halchenko"
__license__ = "GPL" __license__ = "GPL"
import logging, re, os, fcntl, sys, locale, codecs, datetime import re, os, fcntl, sys, locale, codecs, datetime
from .failmanager import FailManagerEmpty, FailManager from .failmanager import FailManagerEmpty, FailManager
from .observer import Observers from .observer import Observers
@ -32,9 +32,10 @@ from .datetemplate import DatePatternRegex, DateEpoch, DateTai64n
from .mytime import MyTime from .mytime import MyTime
from .failregex import FailRegex, Regex, RegexException from .failregex import FailRegex, Regex, RegexException
from .action import CommandAction from .action import CommandAction
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
## ##
# Log reader class. # Log reader class.

View File

@ -23,16 +23,17 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012 Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier, 2012 Yaroslav Halchenko"
__license__ = "GPL" __license__ = "GPL"
import time, logging, fcntl import time, fcntl
import gamin import gamin
from .failmanager import FailManagerEmpty from .failmanager import FailManagerEmpty
from .filter import FileFilter from .filter import FileFilter
from .mytime import MyTime from .mytime import MyTime
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
## ##
# Log reader class. # Log reader class.

View File

@ -24,14 +24,15 @@ __author__ = "Cyril Jaquier, Yaroslav Halchenko"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier; 2012 Yaroslav Halchenko" __copyright__ = "Copyright (c) 2004 Cyril Jaquier; 2012 Yaroslav Halchenko"
__license__ = "GPL" __license__ = "GPL"
import time, logging, os import time, os
from .failmanager import FailManagerEmpty from .failmanager import FailManagerEmpty
from .filter import FileFilter from .filter import FileFilter
from .mytime import MyTime from .mytime import MyTime
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
## ##
# Log reader class. # Log reader class.

View File

@ -32,6 +32,7 @@ import pyinotify
from .failmanager import FailManagerEmpty from .failmanager import FailManagerEmpty
from .filter import FileFilter from .filter import FileFilter
from .mytime import MyTime from .mytime import MyTime
from ..helpers import getLogger
if not hasattr(pyinotify, '__version__') \ if not hasattr(pyinotify, '__version__') \
@ -48,7 +49,7 @@ except Exception, e:
% str(e)) % str(e))
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
## ##
# Log reader class. # Log reader class.

View File

@ -22,7 +22,7 @@ __author__ = "Steven Hiscocks"
__copyright__ = "Copyright (c) 2013 Steven Hiscocks" __copyright__ = "Copyright (c) 2013 Steven Hiscocks"
__license__ = "GPL" __license__ = "GPL"
import logging, datetime, time import datetime, time
from distutils.version import LooseVersion from distutils.version import LooseVersion
from systemd import journal from systemd import journal
@ -32,10 +32,10 @@ if LooseVersion(getattr(journal, '__version__', "0")) < '204':
from .failmanager import FailManagerEmpty from .failmanager import FailManagerEmpty
from .filter import JournalFilter from .filter import JournalFilter
from .mytime import MyTime from .mytime import MyTime
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger("fail2ban.filter") logSys = getLogger(__name__)
## ##
# Journal reader class. # Journal reader class.

View File

@ -26,10 +26,11 @@ __license__ = "GPL"
import Queue, logging, math, random import Queue, logging, math, random
from .actions import Actions from .actions import Actions
from ..helpers import getLogger
from .mytime import MyTime from .mytime import MyTime
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class Jail: class Jail:
"""Fail2Ban jail, which manages a filter and associated actions. """Fail2Ban jail, which manages a filter and associated actions.

View File

@ -24,9 +24,12 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import sys
from threading import Thread from threading import Thread
from abc import abstractproperty, abstractmethod from abc import abstractproperty, abstractmethod
from ..helpers import excepthook
class JailThread(Thread): class JailThread(Thread):
"""Abstract class for threading elements in Fail2Ban. """Abstract class for threading elements in Fail2Ban.
@ -53,6 +56,16 @@ class JailThread(Thread):
## The time the thread sleeps in the loop. ## The time the thread sleeps in the loop.
self.sleeptime = 1 self.sleeptime = 1
# excepthook workaround for threads, derived from:
# http://bugs.python.org/issue1230540#msg91244
run = self.run
def run_with_except_hook(*args, **kwargs):
try:
run(*args, **kwargs)
except:
excepthook(*sys.exc_info())
self.run = run_with_except_hook
@abstractproperty @abstractproperty
def status(self): # pragma: no cover - abstract def status(self): # pragma: no cover - abstract
"""Abstract - Should provide status information. """Abstract - Should provide status information.

View File

@ -25,14 +25,14 @@ __author__ = "Serg G. Brester (sebres)"
__copyright__ = "Copyright (c) 2014 Serg G. Brester" __copyright__ = "Copyright (c) 2014 Serg G. Brester"
__license__ = "GPL" __license__ = "GPL"
import time, logging
import threading import threading
import os, datetime, math, json, random import os, time, datetime, math, json, random
import sys import sys
from ..helpers import getLogger
from .mytime import MyTime from .mytime import MyTime
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class ObserverThread(threading.Thread): class ObserverThread(threading.Thread):
"""Handles observing a database, managing bad ips and ban increment. """Handles observing a database, managing bad ips and ban increment.

View File

@ -33,9 +33,10 @@ from .filter import FileFilter, JournalFilter
from .transmitter import Transmitter from .transmitter import Transmitter
from .asyncserver import AsyncServer, AsyncServerException from .asyncserver import AsyncServer, AsyncServerException
from .. import version from .. import version
from ..helpers import getLogger, excepthook
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
try: try:
from .database import Fail2BanDb from .database import Fail2BanDb
@ -70,6 +71,9 @@ class Server:
signal.signal(signal.SIGTERM, self.__sigTERMhandler) signal.signal(signal.SIGTERM, self.__sigTERMhandler)
signal.signal(signal.SIGINT, self.__sigTERMhandler) signal.signal(signal.SIGINT, self.__sigTERMhandler)
# Ensure unhandled exceptions are logged
sys.excepthook = excepthook
# First set the mask to only allow access to owner # First set the mask to only allow access to owner
os.umask(0077) os.umask(0077)
if self.__daemon: # pragma: no cover if self.__daemon: # pragma: no cover
@ -352,7 +356,7 @@ class Server:
def setLogLevel(self, value): def setLogLevel(self, value):
try: try:
self.__loggingLock.acquire() self.__loggingLock.acquire()
logging.getLogger(__name__).parent.parent.setLevel( getLogger("fail2ban").setLevel(
getattr(logging, value.upper())) getattr(logging, value.upper()))
except AttributeError: except AttributeError:
raise ValueError("Invalid log level") raise ValueError("Invalid log level")
@ -384,7 +388,7 @@ class Server:
try: try:
self.__loggingLock.acquire() self.__loggingLock.acquire()
# set a format which is simpler for console use # set a format which is simpler for console use
formatter = logging.Formatter("%(asctime)s %(name)-16s[%(process)d]: %(levelname)-7s %(message)s") formatter = logging.Formatter("%(asctime)s %(name)-24s[%(process)d]: %(levelname)-7s %(message)s")
if target == "SYSLOG": if target == "SYSLOG":
# Syslog daemons already add date to the message. # Syslog daemons already add date to the message.
formatter = logging.Formatter("%(name)s[%(process)d]: %(levelname)s %(message)s") formatter = logging.Formatter("%(name)s[%(process)d]: %(levelname)s %(message)s")
@ -405,7 +409,7 @@ class Server:
return False return False
# Removes previous handlers -- in reverse order since removeHandler # Removes previous handlers -- in reverse order since removeHandler
# alter the list in-place and that can confuses the iterable # alter the list in-place and that can confuses the iterable
logger = logging.getLogger(__name__).parent.parent logger = getLogger("fail2ban")
for handler in logger.handlers[::-1]: for handler in logger.handlers[::-1]:
# Remove the handler. # Remove the handler.
logger.removeHandler(handler) logger.removeHandler(handler)
@ -442,7 +446,7 @@ class Server:
def flushLogs(self): def flushLogs(self):
if self.__logTarget not in ['STDERR', 'STDOUT', 'SYSLOG']: if self.__logTarget not in ['STDERR', 'STDOUT', 'SYSLOG']:
for handler in logging.getLogger(__name__).parent.parent.handlers: for handler in getLogger("fail2ban").handlers:
try: try:
handler.doRollover() handler.doRollover()
logSys.info("rollover performed on %s" % self.__logTarget) logSys.info("rollover performed on %s" % self.__logTarget)
@ -451,7 +455,7 @@ class Server:
logSys.info("flush performed on %s" % self.__logTarget) logSys.info("flush performed on %s" % self.__logTarget)
return "rolled over" return "rolled over"
else: else:
for handler in logging.getLogger(__name__).parent.parent.handlers: for handler in getLogger("fail2ban").handlers:
handler.flush() handler.flush()
logSys.info("flush performed on %s" % self.__logTarget) logSys.info("flush performed on %s" % self.__logTarget)
return "flushed" return "flushed"

View File

@ -24,14 +24,15 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging from ..helpers import getLogger
from .mytime import MyTime
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class Ticket: class Ticket:
def __init__(self, ip, time, matches=None): def __init__(self, ip, time=None, matches=None):
"""Ticket constructor """Ticket constructor
@param ip the IP address @param ip the IP address
@ -43,7 +44,7 @@ class Ticket:
self.__restored = False; self.__restored = False;
self.__banCount = 0; self.__banCount = 0;
self.__banTime = None; self.__banTime = None;
self.__time = time self.__time = time if time is not None else MyTime.time()
self.__attempt = 0 self.__attempt = 0
self.__file = None self.__file = None
self.__matches = matches or [] self.__matches = matches or []

View File

@ -24,11 +24,13 @@ __author__ = "Cyril Jaquier"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier" __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL" __license__ = "GPL"
import logging, time import time
import json import json
from ..helpers import getLogger
# Gets the instance of the logger. # Gets the instance of the logger.
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
class Transmitter: class Transmitter:

View File

@ -29,6 +29,7 @@ import os
import tempfile import tempfile
from ..server.actions import Actions from ..server.actions import Actions
from ..server.ticket import FailTicket
from .dummyjail import DummyJail from .dummyjail import DummyJail
from .utils import LogCaptureTestCase from .utils import LogCaptureTestCase
@ -141,3 +142,27 @@ class ExecuteActions(LogCaptureTestCase):
self.__actions.join() self.__actions.join()
self.assertTrue(self._is_logged("Failed to stop")) self.assertTrue(self._is_logged("Failed to stop"))
def testBanActionsAInfo(self):
# Action which deletes IP address from aInfo
self.__actions.add(
"action1",
os.path.join(TEST_FILES_DIR, "action.d/action_modifyainfo.py"),
{})
self.__actions.add(
"action2",
os.path.join(TEST_FILES_DIR, "action.d/action_modifyainfo.py"),
{})
self.__jail.putFailTicket(FailTicket("1.2.3.4"))
self.__actions._Actions__checkBan()
# Will fail if modification of aInfo from first action propagates
# to second action, as both delete same key
self.assertFalse(self._is_logged("Failed to execute ban"))
self.assertTrue(self._is_logged("action1 ban deleted aInfo IP"))
self.assertTrue(self._is_logged("action2 ban deleted aInfo IP"))
self.__actions._Actions__flushBan()
# Will fail if modification of aInfo from first action propagates
# to second action, as both delete same key
self.assertFalse(self._is_logged("Failed to execute unban"))
self.assertTrue(self._is_logged("action1 unban deleted aInfo IP"))
self.assertTrue(self._is_logged("action2 unban deleted aInfo IP"))

View File

@ -0,0 +1,14 @@
from fail2ban.server.action import ActionBase
class TestAction(ActionBase):
def ban(self, aInfo):
del aInfo['ip']
self._logSys.info("%s ban deleted aInfo IP", self._name)
def unban(self, aInfo):
del aInfo['ip']
self._logSys.info("%s unban deleted aInfo IP", self._name)
Action = TestAction

View File

@ -1,14 +1,14 @@
# failJSON: { "time": "2006-02-13T15:52:30", "match": true , "host": "1.2.3.4" } # failJSON: { "time": "2006-02-13T15:52:30", "match": true , "host": "1.2.3.4" }
2006-02-13 15:52:30,388 fail2ban.server.actions: NOTICE [sendmail] Ban 1.2.3.4 2006-02-13 15:52:30,388 fail2ban.actions: NOTICE [sendmail] Ban 1.2.3.4
# failJSON: { "time": "2006-02-13T15:52:30", "match": true , "host": "1.2.3.4", "desc": "Extended with [PID]" } # failJSON: { "time": "2006-02-13T15:52:30", "match": true , "host": "1.2.3.4", "desc": "Extended with [PID]" }
2006-02-13 15:52:30,388 fail2ban.server.actions[123]: NOTICE [sendmail] Ban 1.2.3.4 2006-02-13 15:52:30,388 fail2ban.actions[123]: NOTICE [sendmail] Ban 1.2.3.4
# failJSON: { "match": false } # failJSON: { "match": false }
2006-02-13 16:07:31,183 fail2ban.server.actions: NOTICE [sendmail] Unban 1.2.3.4 2006-02-13 16:07:31,183 fail2ban.actions: NOTICE [sendmail] Unban 1.2.3.4
# failJSON: { "match": false } # failJSON: { "match": false }
2006-02-13 15:52:30,388 fail2ban.server.actions: NOTICE [recidive] Ban 1.2.3.4 2006-02-13 15:52:30,388 fail2ban.actions: NOTICE [recidive] Ban 1.2.3.4
# syslog example # syslog example
# failJSON: { "time": "2004-09-16T00:44:55", "match": true , "host": "10.0.0.7" } # failJSON: { "time": "2004-09-16T00:44:55", "match": true , "host": "10.0.0.7" }
Sep 16 00:44:55 spaceman fail2ban.server.actions: NOTICE [jail] Ban 10.0.0.7 Sep 16 00:44:55 spaceman fail2ban.actions: NOTICE [jail] Ban 10.0.0.7
# failJSON: { "time": "2006-02-13T15:52:30", "match": true , "host": "1.2.3.4", "desc": "Extended with [PID] and padding" } # failJSON: { "time": "2006-02-13T15:52:30", "match": true , "host": "1.2.3.4", "desc": "Extended with [PID] and padding" }
2006-02-13 15:52:30,388 fail2ban.server.actions[123]: NOTICE [sendmail] Ban 1.2.3.4 2006-02-13 15:52:30,388 fail2ban.actions [123]: NOTICE [sendmail] Ban 1.2.3.4

View File

@ -32,7 +32,7 @@ import datetime
from glob import glob from glob import glob
from StringIO import StringIO from StringIO import StringIO
from ..helpers import formatExceptionInfo, mbasename, TraceBack, FormatterWithTraceBack from ..helpers import formatExceptionInfo, mbasename, TraceBack, FormatterWithTraceBack, getLogger
from ..server.datetemplate import DatePatternRegex from ..server.datetemplate import DatePatternRegex
@ -159,7 +159,7 @@ class TestsUtilsTest(unittest.TestCase):
# and both types of traceback at once # and both types of traceback at once
fmt = ' %(tb)s | %(tbc)s : %(message)s' fmt = ' %(tb)s | %(tbc)s : %(message)s'
logSys = logging.getLogger("fail2ban_tests") logSys = getLogger("fail2ban_tests")
out = logging.StreamHandler(strout) out = logging.StreamHandler(strout)
out.setFormatter(Formatter(fmt)) out.setFormatter(Formatter(fmt))
logSys.addHandler(out) logSys.addHandler(out)

View File

@ -30,11 +30,13 @@ import tempfile
import os import os
import locale import locale
import sys import sys
import logging
from ..server.failregex import Regex, FailRegex, RegexException from ..server.failregex import Regex, FailRegex, RegexException
from ..server.server import Server from ..server.server import Server
from ..server.jail import Jail from ..server.jail import Jail
from ..server.jailthread import JailThread
from .utils import LogCaptureTestCase
from ..helpers import getLogger
try: try:
from ..server import filtersystemd from ..server import filtersystemd
@ -722,7 +724,7 @@ class TransmitterLogging(TransmitterBase):
os.close(f) os.close(f)
self.server.setLogLevel("WARNING") self.server.setLogLevel("WARNING")
self.assertEqual(self.transm.proceed(["set", "logtarget", fn]), (0, fn)) self.assertEqual(self.transm.proceed(["set", "logtarget", fn]), (0, fn))
l = logging.getLogger('fail2ban.server.server').parent.parent l = getLogger('fail2ban')
l.warning("Before file moved") l.warning("Before file moved")
try: try:
f2, fn2 = tempfile.mkstemp("fail2ban.log") f2, fn2 = tempfile.mkstemp("fail2ban.log")
@ -804,5 +806,33 @@ class RegexTests(unittest.TestCase):
self.assertTrue(fr.hasMatched()) self.assertTrue(fr.hasMatched())
self.assertRaises(RegexException, fr.getHost) self.assertRaises(RegexException, fr.getHost)
class _BadThread(JailThread):
def run(self):
raise RuntimeError('run bad thread exception')
class LoggingTests(LogCaptureTestCase):
def setUp(self):
"""Call before every test case."""
LogCaptureTestCase.setUp(self)
def tearDown(self):
"""Call after every test case."""
LogCaptureTestCase.tearDown(self)
def testGetF2BLogger(self):
testLogSys = getLogger("fail2ban.some.string.with.name")
self.assertEqual(testLogSys.parent.name, "fail2ban")
self.assertEqual(testLogSys.name, "fail2ban.name")
def testFail2BanExceptHook(self):
prev_exchook = sys.__excepthook__
x = []
sys.__excepthook__ = lambda *args: x.append(args)
badThread = _BadThread()
badThread.start()
badThread.join()
self.assertTrue(self._is_logged("Unhandled exception"))
sys.__excepthook__ = prev_exchook
self.assertEqual(len(x), 1)
self.assertEqual(x[0][0], RuntimeError)

View File

@ -30,8 +30,9 @@ import unittest
from StringIO import StringIO from StringIO import StringIO
from ..server.mytime import MyTime from ..server.mytime import MyTime
from ..helpers import getLogger
logSys = logging.getLogger(__name__) logSys = getLogger(__name__)
def mtimesleep(): def mtimesleep():
# no sleep now should be necessary since polling tracks now not only # no sleep now should be necessary since polling tracks now not only
@ -90,6 +91,7 @@ def gatherTests(regexps=None, no_network=False):
tests.addTest(unittest.makeSuite(servertestcase.Transmitter)) tests.addTest(unittest.makeSuite(servertestcase.Transmitter))
tests.addTest(unittest.makeSuite(servertestcase.JailTests)) tests.addTest(unittest.makeSuite(servertestcase.JailTests))
tests.addTest(unittest.makeSuite(servertestcase.RegexTests)) tests.addTest(unittest.makeSuite(servertestcase.RegexTests))
tests.addTest(unittest.makeSuite(servertestcase.LoggingTests))
tests.addTest(unittest.makeSuite(actiontestcase.CommandActionTest)) tests.addTest(unittest.makeSuite(actiontestcase.CommandActionTest))
tests.addTest(unittest.makeSuite(actionstestcase.ExecuteActions)) tests.addTest(unittest.makeSuite(actionstestcase.ExecuteActions))
# FailManager # FailManager
@ -190,7 +192,7 @@ class LogCaptureTestCase(unittest.TestCase):
# For extended testing of what gets output into logging # For extended testing of what gets output into logging
# system, we will redirect it to a string # system, we will redirect it to a string
logSys = logging.getLogger("fail2ban") logSys = getLogger("fail2ban")
# Keep old settings # Keep old settings
self._old_level = logSys.level self._old_level = logSys.level
@ -203,7 +205,7 @@ class LogCaptureTestCase(unittest.TestCase):
def tearDown(self): def tearDown(self):
"""Call after every test case.""" """Call after every test case."""
# print "O: >>%s<<" % self._log.getvalue() # print "O: >>%s<<" % self._log.getvalue()
logSys = logging.getLogger("fail2ban") logSys = getLogger("fail2ban")
logSys.handlers = self._old_handlers logSys.handlers = self._old_handlers
logSys.level = self._old_level logSys.level = self._old_level