mirror of https://github.com/fail2ban/fail2ban
Merge branch 'master' into 0.9
* master: DOC: initiated changelog (but not juice left to actually fill it up ;-)) TST: test all valid loglevels in server testcases TST: Add tag replace and escape test for actions ENH: Minor change to action for consistency of execStart/Stop TST: Coverage for coveralls.io should only be run on success TST: no cover additions to server, primarily daemon creation DOC: thanks @kwirk for spotting the typos in exception message FD_CLOEXEC support Typo in default pidfile in fail2ban.conf Conflicts: .travis.yml -- after_success ChangeLog -- added perspective changelog for 0.8.9 fail2ban/server/asyncserver.py -- imports fail2ban/server/server.py -- no pragma (if I got it right ;-) )pull/181/merge
commit
9a14cf8b7b
|
@ -18,5 +18,5 @@ before_script:
|
|||
script:
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then export PYTHONPATH="$PYTHONPATH:/usr/share/pyshared:/usr/lib/pyshared/python2.7"; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coverage run --rcfile=.travis_coveragerc bin/fail2ban-testcases; else python bin/fail2ban-testcases; fi
|
||||
after_script:
|
||||
after_success:
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then coveralls; fi
|
||||
|
|
12
ChangeLog
12
ChangeLog
|
@ -17,6 +17,18 @@ Will carry all fixes in 0.8.x series and new features and enhancements
|
|||
- New features:
|
||||
Steven Hiscocks
|
||||
* Multiline failregex. Close gh-54
|
||||
|
||||
ver. 0.8.9 (2013/04/XXX) - wanna-be-stable
|
||||
----------
|
||||
|
||||
This release incorporates 144 (XXX) non-merge commits from 14
|
||||
contributors (sorted by number of commits): Yaroslav Halchenko, Daniel
|
||||
Black, Steven Hiscocks, ArndRa, hamilton5, pigsyn, Erwan Ben Souiden,
|
||||
Michael Gebetsroither, Orion Poplawski, Artur Penttinen, sebres,
|
||||
Nicolas Collignon, Pascal Borreli, blotus:
|
||||
|
||||
- Fixes:
|
||||
- New features:
|
||||
- Enhancements:
|
||||
|
||||
ver. 0.8.8 (2012/12/06) - stable
|
||||
|
|
4
DEVELOP
4
DEVELOP
|
@ -253,6 +253,10 @@ Releasing
|
|||
|
||||
# Add/finalize the corresponding entry in the ChangeLog
|
||||
|
||||
To generate a list of committers use e.g.
|
||||
|
||||
git shortlog -sn 0.8.8.. | sed -e 's,^[ 0-9\t]*,,g' | tr '\n' '\|' | sed -e 's:|:, :g'
|
||||
|
||||
# Update man pages
|
||||
|
||||
(cd man ; ./generate-man )
|
||||
|
|
|
@ -43,7 +43,7 @@ socket = /var/run/fail2ban/fail2ban.sock
|
|||
# Option: pidfile
|
||||
# Notes.: Set the PID file. This is used to store the process ID of the
|
||||
# fail2ban server.
|
||||
# Values: FILE Default: /var/run/fail2ban/fail2ban.sock
|
||||
# Values: FILE Default: /var/run/fail2ban/fail2ban.pid
|
||||
#
|
||||
pidfile = /var/run/fail2ban/fail2ban.pid
|
||||
|
||||
|
|
|
@ -297,10 +297,8 @@ class Action:
|
|||
if not Action.executeCmd(checkCmd):
|
||||
logSys.error("Invariant check failed. Trying to restore a sane" +
|
||||
" environment")
|
||||
stopCmd = Action.replaceTag(self.__actionStop, self.__cInfo)
|
||||
Action.executeCmd(stopCmd)
|
||||
startCmd = Action.replaceTag(self.__actionStart, self.__cInfo)
|
||||
Action.executeCmd(startCmd)
|
||||
self.execActionStop()
|
||||
self.execActionStart()
|
||||
if not Action.executeCmd(checkCmd):
|
||||
logSys.fatal("Unable to restore environment")
|
||||
return False
|
||||
|
|
|
@ -28,7 +28,7 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|||
__license__ = "GPL"
|
||||
|
||||
from pickle import dumps, loads, HIGHEST_PROTOCOL
|
||||
import asyncore, asynchat, socket, os, logging, sys, traceback
|
||||
import asyncore, asynchat, socket, os, logging, sys, traceback, fcntl
|
||||
|
||||
from fail2ban import helpers
|
||||
|
||||
|
@ -118,6 +118,7 @@ class AsyncServer(asyncore.dispatcher):
|
|||
except TypeError:
|
||||
logSys.warning("Type error")
|
||||
return
|
||||
AsyncServer.__markCloseOnExec(conn)
|
||||
# Creates an instance of the handler class to handle the
|
||||
# request/response on the incoming connection.
|
||||
RequestHandler(conn, self.__transmitter)
|
||||
|
@ -145,6 +146,7 @@ class AsyncServer(asyncore.dispatcher):
|
|||
self.bind(sock)
|
||||
except Exception:
|
||||
raise AsyncServerException("Unable to bind socket %s" % self.__sock)
|
||||
AsyncServer.__markCloseOnExec(self.socket)
|
||||
self.listen(1)
|
||||
# Sets the init flag.
|
||||
self.__init = True
|
||||
|
@ -170,6 +172,18 @@ class AsyncServer(asyncore.dispatcher):
|
|||
os.remove(self.__sock)
|
||||
logSys.debug("Socket shutdown")
|
||||
|
||||
##
|
||||
# Marks socket as close-on-exec to avoid leaking file descriptors when
|
||||
# running actions involving command execution.
|
||||
|
||||
# @param sock: socket file.
|
||||
|
||||
#@staticmethod
|
||||
def __markCloseOnExec(sock):
|
||||
fd = sock.fileno()
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, flags|fcntl.FD_CLOEXEC)
|
||||
__markCloseOnExec = staticmethod(__markCloseOnExec)
|
||||
|
||||
##
|
||||
# AsyncServerException is used to wrap communication exceptions.
|
||||
|
|
|
@ -610,7 +610,8 @@ class FileContainer:
|
|||
self.__handler = open(self.__filename, 'rb')
|
||||
# Set the file descriptor to be FD_CLOEXEC
|
||||
fd = self.__handler.fileno()
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, fd | fcntl.FD_CLOEXEC)
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)
|
||||
firstLine = self.__handler.readline()
|
||||
# Computes the MD5 of the first line.
|
||||
myHash = md5sum(firstLine).digest()
|
||||
|
|
|
@ -27,7 +27,7 @@ from failmanager import FailManagerEmpty
|
|||
from filter import FileFilter
|
||||
from mytime import MyTime
|
||||
|
||||
import time, logging, gamin
|
||||
import time, logging, gamin, fcntl
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = logging.getLogger(__name__)
|
||||
|
@ -52,6 +52,9 @@ class FilterGamin(FileFilter):
|
|||
self.__modified = False
|
||||
# Gamin monitor
|
||||
self.monitor = gamin.WatchMonitor()
|
||||
fd = self.monitor.get_fd()
|
||||
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||
fcntl.fcntl(fd, fcntl.F_SETFD, flags|fcntl.FD_CLOEXEC)
|
||||
logSys.debug("Created FilterGamin")
|
||||
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ class Server:
|
|||
|
||||
# First set the mask to only allow access to owner
|
||||
os.umask(0077)
|
||||
if self.__daemon:
|
||||
if self.__daemon: # pragma: no cover
|
||||
logSys.info("Starting in daemon mode")
|
||||
ret = self.__createDaemon()
|
||||
if ret:
|
||||
|
@ -389,7 +389,7 @@ class Server:
|
|||
try:
|
||||
handler.flush()
|
||||
handler.close()
|
||||
except (ValueError, KeyError):
|
||||
except (ValueError, KeyError): # pragma: no cover
|
||||
if (2,6) <= sys.version_info < (3,) or \
|
||||
(3,2) <= sys.version_info:
|
||||
raise
|
||||
|
@ -415,7 +415,7 @@ class Server:
|
|||
finally:
|
||||
self.__loggingLock.release()
|
||||
|
||||
def __createDaemon(self):
|
||||
def __createDaemon(self): # pragma: no cover
|
||||
""" Detach a process from the controlling terminal and run it in the
|
||||
background as a daemon.
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ class Transmitter:
|
|||
elif command[2] == "off":
|
||||
self.__server.setIdleJail(name, False)
|
||||
else:
|
||||
raise Exception("Invalid idle option, must be 'yes' or 'no'")
|
||||
raise Exception("Invalid idle option, must be 'on' or 'off'")
|
||||
return self.__server.getIdleJail(name)
|
||||
# Filter
|
||||
elif command[1] == "addignoreip":
|
||||
|
|
|
@ -62,6 +62,23 @@ class ExecuteAction(unittest.TestCase):
|
|||
def _is_logged(self, s):
|
||||
return s in self._log.getvalue()
|
||||
|
||||
def testReplaceTag(self):
|
||||
aInfo = {
|
||||
'HOST': "192.0.2.0",
|
||||
'ABC': "123",
|
||||
'xyz': "890",
|
||||
}
|
||||
self.assertEqual(
|
||||
self.__action.replaceTag("Text <HOST> text", aInfo),
|
||||
"Text 192.0.2.0 text")
|
||||
self.assertEqual(
|
||||
self.__action.replaceTag("Text <xyz> text <ABC> ABC", aInfo),
|
||||
"Text 890 text 123 ABC")
|
||||
self.assertEqual(
|
||||
self.__action.replaceTag("<matches>",
|
||||
{'matches': "some >char< should \< be[ escap}ed&"}),
|
||||
r"some \>char\< should \\\< be\[ escap\}ed\&")
|
||||
|
||||
def testExecuteActionBan(self):
|
||||
self.__action.setActionStart("touch /tmp/fail2ban.test")
|
||||
self.__action.setActionStop("rm -f /tmp/fail2ban.test")
|
||||
|
|
|
@ -520,7 +520,9 @@ class TransmitterLogging(TransmitterBase):
|
|||
|
||||
def testLogLevel(self):
|
||||
self.setGetTest("loglevel", "4", 4)
|
||||
self.setGetTest("loglevel", "3", 3)
|
||||
self.setGetTest("loglevel", "2", 2)
|
||||
self.setGetTest("loglevel", "1", 1)
|
||||
self.setGetTest("loglevel", "-1", -1)
|
||||
self.setGetTest("loglevel", "0", 0)
|
||||
self.setGetTestNOK("loglevel", "Bird")
|
||||
|
|
Loading…
Reference in New Issue