mirror of https://github.com/fail2ban/fail2ban
- Removed "utils" directory
- Created a "DNSUtils" class in filter.py git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@274 a942ae1a-1317-0410-a47c-b1dcaea8d6050.x
parent
ec8f620f80
commit
535b9a6a36
105
server/filter.py
105
server/filter.py
|
@ -28,7 +28,6 @@ from failmanager import FailManager
|
||||||
from failmanager import FailManagerEmpty
|
from failmanager import FailManagerEmpty
|
||||||
from failticket import FailTicket
|
from failticket import FailTicket
|
||||||
from jailthread import JailThread
|
from jailthread import JailThread
|
||||||
from utils.dns import *
|
|
||||||
import time, logging, os, re, sys, socket
|
import time, logging, os, re, sys, socket
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
# Gets the instance of the logger.
|
||||||
|
@ -257,8 +256,8 @@ class Filter(JailThread):
|
||||||
s.insert(1, '32')
|
s.insert(1, '32')
|
||||||
s[1] = long(s[1])
|
s[1] = long(s[1])
|
||||||
try:
|
try:
|
||||||
a = cidr(s[0], s[1])
|
a = DNSUtils.cidr(s[0], s[1])
|
||||||
b = cidr(ip, s[1])
|
b = DNSUtils.cidr(ip, s[1])
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
if a == b:
|
if a == b:
|
||||||
|
@ -379,7 +378,7 @@ class Filter(JailThread):
|
||||||
if timeMatch:
|
if timeMatch:
|
||||||
date = self.getUnixTime(timeMatch.group())
|
date = self.getUnixTime(timeMatch.group())
|
||||||
try:
|
try:
|
||||||
ipMatch = textToIp(match.group("host"))
|
ipMatch = DNSUtils.textToIp(match.group("host"))
|
||||||
if ipMatch:
|
if ipMatch:
|
||||||
for ip in ipMatch:
|
for ip in ipMatch:
|
||||||
failList.append([ip, date])
|
failList.append([ip, date])
|
||||||
|
@ -457,4 +456,100 @@ class Filter(JailThread):
|
||||||
ret = [("Currently failed", self.failManager.size()),
|
ret = [("Currently failed", self.failManager.size()),
|
||||||
("Total failed", self.failManager.getFailTotal())]
|
("Total failed", self.failManager.getFailTotal())]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# Utils class for DNS and IP handling.
|
||||||
|
#
|
||||||
|
# This class contains only static methods used to handle DNS and IP
|
||||||
|
# addresses.
|
||||||
|
|
||||||
|
import socket, struct
|
||||||
|
|
||||||
|
class DNSUtils:
|
||||||
|
|
||||||
|
dnsRe = re.compile("(?:(?:\w|-)+\.){2,}\w+")
|
||||||
|
ipRe = re.compile("(?:\d{1,3}\.){3}\d{1,3}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def dnsToIp(dns):
|
||||||
|
""" Convert a DNS into an IP address using the Python socket module.
|
||||||
|
Thanks to Kevin Drapel.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return socket.gethostbyname_ex(dns)[2]
|
||||||
|
except socket.gaierror:
|
||||||
|
return list()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def textToDns(text):
|
||||||
|
""" Search for possible DNS in an arbitrary text.
|
||||||
|
Thanks to Tom Pike.
|
||||||
|
"""
|
||||||
|
match = dnsRe.find(text)
|
||||||
|
if match:
|
||||||
|
return match
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def searchIP(text):
|
||||||
|
""" Search if an IP address if directly available and return
|
||||||
|
it.
|
||||||
|
"""
|
||||||
|
match = ipRe.find(text)
|
||||||
|
if match:
|
||||||
|
return match
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def isValidIP(str):
|
||||||
|
""" Return true if str is a valid IP
|
||||||
|
"""
|
||||||
|
s = str.split('/', 1)
|
||||||
|
try:
|
||||||
|
socket.inet_aton(s[0])
|
||||||
|
return True
|
||||||
|
except socket.error:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def textToIp(text):
|
||||||
|
""" Return the IP of DNS found in a given text.
|
||||||
|
"""
|
||||||
|
ipList = list()
|
||||||
|
# Search for plain IP
|
||||||
|
plainIP = DNSUtils.searchIP(text)
|
||||||
|
if not plainIP == None:
|
||||||
|
if isValidIP(element):
|
||||||
|
ipList.append(element)
|
||||||
|
if not ipList:
|
||||||
|
# Try to get IP from possible DNS
|
||||||
|
dnsList = DNSUtils.textToDns(text)
|
||||||
|
if not dnsList == None:
|
||||||
|
dns = DNSUtils.dnsToIp(element)
|
||||||
|
for e in dns:
|
||||||
|
ipList.append(e)
|
||||||
|
return ipList
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cidr(i, n):
|
||||||
|
""" Convert an IP address string with a CIDR mask into a 32-bit
|
||||||
|
integer.
|
||||||
|
"""
|
||||||
|
# 32-bit IPv4 address mask
|
||||||
|
MASK = 0xFFFFFFFFL
|
||||||
|
return ~(MASK >> n) & MASK & DNSUtils.addr2bin(i)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def addr2bin(str):
|
||||||
|
""" Convert a string IPv4 address into an unsigned integer.
|
||||||
|
"""
|
||||||
|
return struct.unpack("!L", socket.inet_aton(str))[0]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def bin2addr(addr):
|
||||||
|
""" Convert a numeric IPv4 address into string n.n.n.n form.
|
||||||
|
"""
|
||||||
|
return socket.inet_ntoa(struct.pack("!L", addr))
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
102
utils/dns.py
102
utils/dns.py
|
@ -1,102 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
import os, re, socket, struct
|
|
||||||
|
|
||||||
def dnsToIp(dns):
|
|
||||||
""" Convert a DNS into an IP address using the Python socket module.
|
|
||||||
Thanks to Kevin Drapel.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return socket.gethostbyname_ex(dns)[2]
|
|
||||||
except socket.gaierror:
|
|
||||||
return list()
|
|
||||||
|
|
||||||
def textToDns(text):
|
|
||||||
""" Search for possible DNS in an arbitrary text.
|
|
||||||
Thanks to Tom Pike.
|
|
||||||
"""
|
|
||||||
match = re.findall("(?:(?:\w|-)+\.){2,}\w+", text)
|
|
||||||
if match:
|
|
||||||
return match
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def searchIP(text):
|
|
||||||
""" Search if an IP address if directly available and return
|
|
||||||
it.
|
|
||||||
"""
|
|
||||||
match = re.findall("(?:\d{1,3}\.){3}\d{1,3}", text)
|
|
||||||
if match:
|
|
||||||
return match
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def isValidIP(str):
|
|
||||||
""" Return true if str is a valid IP
|
|
||||||
"""
|
|
||||||
s = str.split('/', 1)
|
|
||||||
try:
|
|
||||||
socket.inet_aton(s[0])
|
|
||||||
return True
|
|
||||||
except socket.error:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def textToIp(text):
|
|
||||||
""" Return the IP of DNS found in a given text.
|
|
||||||
"""
|
|
||||||
ipList = list()
|
|
||||||
# Search for plain IP
|
|
||||||
plainIP = searchIP(text)
|
|
||||||
for element in plainIP:
|
|
||||||
if isValidIP(element):
|
|
||||||
ipList.append(element)
|
|
||||||
if not ipList:
|
|
||||||
# Try to get IP from possible DNS
|
|
||||||
dnsList = textToDns(text)
|
|
||||||
for element in dnsList:
|
|
||||||
dns = dnsToIp(element)
|
|
||||||
for e in dns:
|
|
||||||
ipList.append(e)
|
|
||||||
return ipList
|
|
||||||
|
|
||||||
def cidr(i, n):
|
|
||||||
""" Convert an IP address string with a CIDR mask into a 32-bit
|
|
||||||
integer.
|
|
||||||
"""
|
|
||||||
# 32-bit IPv4 address mask
|
|
||||||
MASK = 0xFFFFFFFFL
|
|
||||||
return ~(MASK >> n) & MASK & addr2bin(i)
|
|
||||||
|
|
||||||
def addr2bin(str):
|
|
||||||
""" Convert a string IPv4 address into an unsigned integer.
|
|
||||||
"""
|
|
||||||
return struct.unpack("!L", socket.inet_aton(str))[0]
|
|
||||||
|
|
||||||
def bin2addr(addr):
|
|
||||||
""" Convert a numeric IPv4 address into string n.n.n.n form.
|
|
||||||
"""
|
|
||||||
return socket.inet_ntoa(struct.pack("!L", addr))
|
|
|
@ -1,91 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
import logging, smtplib, email.Utils
|
|
||||||
|
|
||||||
from utils.strings import replaceTag
|
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
|
||||||
logSys = logging.getLogger("fail2ban")
|
|
||||||
|
|
||||||
class Mail:
|
|
||||||
""" Mailer class
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, host, port = 25):
|
|
||||||
self.host = host
|
|
||||||
self.port = port
|
|
||||||
self.localTimeFlag = False
|
|
||||||
|
|
||||||
def setFromAddr(self, fromAddr):
|
|
||||||
""" Set from: address
|
|
||||||
"""
|
|
||||||
self.fromAddr = fromAddr
|
|
||||||
|
|
||||||
def setUser(self, user):
|
|
||||||
""" Set smtpuser
|
|
||||||
"""
|
|
||||||
self.user = user
|
|
||||||
|
|
||||||
def setPassword(self, password):
|
|
||||||
""" Set smtppassword
|
|
||||||
"""
|
|
||||||
self.password = password
|
|
||||||
|
|
||||||
def setToAddr(self, toAddr):
|
|
||||||
""" Set to: address
|
|
||||||
"""
|
|
||||||
self.toAddr = toAddr.split()
|
|
||||||
|
|
||||||
def setLocalTimeFlag(self, localTimeFlag):
|
|
||||||
""" Set to: address
|
|
||||||
"""
|
|
||||||
self.localTimeFlag = localTimeFlag
|
|
||||||
|
|
||||||
def sendmail(self, subject, message, aInfo):
|
|
||||||
""" Send an email using smtplib
|
|
||||||
"""
|
|
||||||
subj = replaceTag(subject, aInfo)
|
|
||||||
msg = replaceTag(message, aInfo)
|
|
||||||
|
|
||||||
mail = ("From: %s\r\nTo: %s\r\nDate: %s\r\nSubject: %s\r\n\r\n" %
|
|
||||||
(self.fromAddr, ", ".join(self.toAddr),
|
|
||||||
email.Utils.formatdate(localtime = self.localTimeFlag),
|
|
||||||
subj)) + msg
|
|
||||||
|
|
||||||
try:
|
|
||||||
server = smtplib.SMTP(self.host, self.port)
|
|
||||||
#server.set_debuglevel(1)
|
|
||||||
if not self.user == '':
|
|
||||||
server.login(self.user, self.password)
|
|
||||||
server.sendmail(self.fromAddr, self.toAddr, mail)
|
|
||||||
logSys.debug("Email sent to " + `self.toAddr`)
|
|
||||||
server.quit()
|
|
||||||
except Exception, e:
|
|
||||||
logSys.error("Unable to send mail to " + self.host + ":" +
|
|
||||||
`self.port` + " from " + self.fromAddr + " to " +
|
|
||||||
`self.toAddr` + ": " + `e` + ": " + `e.args`)
|
|
||||||
|
|
109
utils/pidlock.py
109
utils/pidlock.py
|
@ -1,109 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
import os, logging
|
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
|
||||||
logSys = logging.getLogger("fail2ban")
|
|
||||||
|
|
||||||
class PIDLock:
|
|
||||||
""" Manages the PID lock file.
|
|
||||||
|
|
||||||
The following class shows how to implement the singleton pattern[1] in
|
|
||||||
Python. A singleton is a class that makes sure only one instance of it
|
|
||||||
is ever created. Typically such classes are used to manage resources
|
|
||||||
that by their very nature can only exist once.
|
|
||||||
|
|
||||||
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52558
|
|
||||||
"""
|
|
||||||
|
|
||||||
class __impl:
|
|
||||||
""" Implementation of the singleton interface """
|
|
||||||
|
|
||||||
def setPath(self, path):
|
|
||||||
""" Set PID lock file path.
|
|
||||||
"""
|
|
||||||
self.path = path
|
|
||||||
|
|
||||||
def create(self):
|
|
||||||
""" Create PID lock.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
fileHandler = open(self.path, mode='w')
|
|
||||||
pid = os.getpid()
|
|
||||||
fileHandler.write(`pid` + '\n')
|
|
||||||
fileHandler.close()
|
|
||||||
logSys.debug("Created PID lock (" + `pid` + ") in " + self.path)
|
|
||||||
return True
|
|
||||||
except:
|
|
||||||
logSys.error("Unable to create PID lock " + self.path)
|
|
||||||
return False
|
|
||||||
|
|
||||||
def remove(self):
|
|
||||||
""" Remove PID lock.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
os.remove(self.path)
|
|
||||||
logSys.debug("Removed PID lock " + self.path)
|
|
||||||
except OSError:
|
|
||||||
logSys.error("Unable to remove PID lock " + self.path)
|
|
||||||
except AttributeError:
|
|
||||||
# AttributeError if self.path wasn't specified yet
|
|
||||||
logSys.debug("PID lock not removed because not defined yet")
|
|
||||||
|
|
||||||
def exists(self):
|
|
||||||
""" Returns the current PID if Fail2Ban is running or False
|
|
||||||
if no instance found.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
fileHandler = open(self.path)
|
|
||||||
pid = fileHandler.readline()
|
|
||||||
fileHandler.close()
|
|
||||||
return pid
|
|
||||||
except IOError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# storage for the instance reference
|
|
||||||
__instance = None
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
""" Create singleton instance """
|
|
||||||
# Check whether we already have an instance
|
|
||||||
if PIDLock.__instance is None:
|
|
||||||
# Create and remember instance
|
|
||||||
PIDLock.__instance = PIDLock.__impl()
|
|
||||||
|
|
||||||
# Store instance reference as the only member in the handle
|
|
||||||
self.__dict__['_PIDLock__instance'] = PIDLock.__instance
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
""" Delegate access to implementation """
|
|
||||||
return getattr(self.__instance, attr)
|
|
||||||
|
|
||||||
def __setattr__(self, attr, value):
|
|
||||||
""" Delegate access to implementation """
|
|
||||||
return setattr(self.__instance, attr, value)
|
|
||||||
|
|
108
utils/process.py
108
utils/process.py
|
@ -1,108 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
import os, logging, signal
|
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
|
||||||
logSys = logging.getLogger("fail2ban")
|
|
||||||
|
|
||||||
class ExternalError(UserWarning):
|
|
||||||
""" Exception to warn about failed fwcheck or fwban command
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def createDaemon():
|
|
||||||
""" Detach a process from the controlling terminal and run it in the
|
|
||||||
background as a daemon.
|
|
||||||
|
|
||||||
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Fork a child process so the parent can exit. This will return control
|
|
||||||
# to the command line or shell. This is required so that the new process
|
|
||||||
# is guaranteed not to be a process group leader. We have this guarantee
|
|
||||||
# because the process GID of the parent is inherited by the child, but
|
|
||||||
# the child gets a new PID, making it impossible for its PID to equal its
|
|
||||||
# PGID.
|
|
||||||
pid = os.fork()
|
|
||||||
except OSError, e:
|
|
||||||
return((e.errno, e.strerror)) # ERROR (return a tuple)
|
|
||||||
|
|
||||||
if pid == 0: # The first child.
|
|
||||||
|
|
||||||
# Next we call os.setsid() to become the session leader of this new
|
|
||||||
# session. The process also becomes the process group leader of the
|
|
||||||
# new process group. Since a controlling terminal is associated with a
|
|
||||||
# session, and this new session has not yet acquired a controlling
|
|
||||||
# terminal our process now has no controlling terminal. This shouldn't
|
|
||||||
# fail, since we're guaranteed that the child is not a process group
|
|
||||||
# leader.
|
|
||||||
os.setsid()
|
|
||||||
|
|
||||||
# When the first child terminates, all processes in the second child
|
|
||||||
# are sent a SIGHUP, so it's ignored.
|
|
||||||
signal.signal(signal.SIGHUP, signal.SIG_IGN)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Fork a second child to prevent zombies. Since the first child is
|
|
||||||
# a session leader without a controlling terminal, it's possible for
|
|
||||||
# it to acquire one by opening a terminal in the future. This second
|
|
||||||
# fork guarantees that the child is no longer a session leader, thus
|
|
||||||
# preventing the daemon from ever acquiring a controlling terminal.
|
|
||||||
pid = os.fork() # Fork a second child.
|
|
||||||
except OSError, e:
|
|
||||||
return((e.errno, e.strerror)) # ERROR (return a tuple)
|
|
||||||
|
|
||||||
if (pid == 0): # The second child.
|
|
||||||
# Ensure that the daemon doesn't keep any directory in use. Failure
|
|
||||||
# to do this could make a filesystem unmountable.
|
|
||||||
os.chdir("/")
|
|
||||||
else:
|
|
||||||
os._exit(0) # Exit parent (the first child) of the second child.
|
|
||||||
else:
|
|
||||||
os._exit(0) # Exit parent of the first child.
|
|
||||||
|
|
||||||
# Close all open files. Try the system configuration variable, SC_OPEN_MAX,
|
|
||||||
# for the maximum number of open files to close. If it doesn't exist, use
|
|
||||||
# the default value (configurable).
|
|
||||||
try:
|
|
||||||
maxfd = os.sysconf("SC_OPEN_MAX")
|
|
||||||
except (AttributeError, ValueError):
|
|
||||||
maxfd = 256 # default maximum
|
|
||||||
|
|
||||||
for fd in range(0, maxfd):
|
|
||||||
try:
|
|
||||||
os.close(fd)
|
|
||||||
except OSError: # ERROR (ignore)
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Redirect the standard file descriptors to /dev/null.
|
|
||||||
os.open("/dev/null", os.O_RDONLY) # standard input (0)
|
|
||||||
os.open("/dev/null", os.O_RDWR) # standard output (1)
|
|
||||||
os.open("/dev/null", os.O_RDWR) # standard error (2)
|
|
||||||
|
|
||||||
return True
|
|
|
@ -1,40 +0,0 @@
|
||||||
# This file is part of Fail2Ban.
|
|
||||||
#
|
|
||||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Fail2Ban is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with Fail2Ban; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
# Author: Cyril Jaquier
|
|
||||||
#
|
|
||||||
# $Revision$
|
|
||||||
|
|
||||||
__author__ = "Cyril Jaquier"
|
|
||||||
__version__ = "$Revision$"
|
|
||||||
__date__ = "$Date$"
|
|
||||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
||||||
__license__ = "GPL"
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
|
||||||
logSys = logging.getLogger("fail2ban")
|
|
||||||
|
|
||||||
def replaceTag(query, aInfo):
|
|
||||||
""" Replace tags in query
|
|
||||||
"""
|
|
||||||
string = query
|
|
||||||
for tag in aInfo:
|
|
||||||
string = string.replace('<'+tag+'>', `aInfo[tag]`)
|
|
||||||
# New line
|
|
||||||
string = string.replace('<br>', '\n')
|
|
||||||
return string
|
|
Loading…
Reference in New Issue