BF: usedns=no was not working at all

it was not adding any detected address, IP or not to the list of failed attempts
This commit also adds appropriate unittest
pull/43/merge
Yaroslav Halchenko 2012-06-15 23:43:11 -04:00
parent 971406f722
commit 3989d24967
3 changed files with 70 additions and 38 deletions

View File

@ -54,7 +54,7 @@ class Filter(JailThread):
# Initialize the filter object with default values. # Initialize the filter object with default values.
# @param jail the jail object # @param jail the jail object
def __init__(self, jail): def __init__(self, jail, useDns='warn'):
JailThread.__init__(self) JailThread.__init__(self)
## The jail which contains this filter. ## The jail which contains this filter.
self.jail = jail self.jail = jail
@ -65,7 +65,7 @@ class Filter(JailThread):
## The regular expression list with expressions to ignore. ## The regular expression list with expressions to ignore.
self.__ignoreRegex = list() self.__ignoreRegex = list()
## Use DNS setting ## Use DNS setting
self.__useDns = "warn" self.setUseDns(useDns)
## The amount of time to look back. ## The amount of time to look back.
self.__findTime = 6000 self.__findTime = 6000
## The ignore IP list. ## The ignore IP list.
@ -149,6 +149,13 @@ class Filter(JailThread):
# @param value the usedns mode # @param value the usedns mode
def setUseDns(self, value): def setUseDns(self, value):
if isinstance(value, bool):
value = {True: 'yes', False: 'no'}[value]
value = value.lower() # must be a string by now
if not (value in ('yes', 'no', 'warn')):
logSys.error("Incorrect value %r specified for usedns. "
"Using safe 'no'" % (value,))
value = 'no'
logSys.debug("Setting usedns = %s for %s" % (value, self)) logSys.debug("Setting usedns = %s for %s" % (value, self))
self.__useDns = value self.__useDns = value
@ -373,8 +380,8 @@ class Filter(JailThread):
class FileFilter(Filter): class FileFilter(Filter):
def __init__(self, jail): def __init__(self, jail, **kwargs):
Filter.__init__(self, jail) Filter.__init__(self, jail, **kwargs)
## The log file path. ## The log file path.
self.__logPath = [] self.__logPath = []
@ -589,25 +596,24 @@ class DNSUtils:
def textToIp(text, useDns): def textToIp(text, useDns):
""" Return the IP of DNS found in a given text. """ Return the IP of DNS found in a given text.
""" """
if useDns == "no": ipList = list()
return None # Search for plain IP
else: plainIP = DNSUtils.searchIP(text)
ipList = list() if not plainIP is None:
# Search for plain IP plainIPStr = plainIP.group(0)
plainIP = DNSUtils.searchIP(text) if DNSUtils.isValidIP(plainIPStr):
if not plainIP is None: ipList.append(plainIPStr)
plainIPStr = plainIP.group(0)
if DNSUtils.isValidIP(plainIPStr): # If we are allowed to resolve -- give it a try if nothing was found
ipList.append(plainIPStr) if useDns in ("yes", "warn") and not ipList:
if not ipList: # Try to get IP from possible DNS
# Try to get IP from possible DNS ip = DNSUtils.dnsToIp(text)
ip = DNSUtils.dnsToIp(text) ipList.extend(ip)
for e in ip: if ip and useDns == "warn":
ipList.append(e) logSys.warning("Determined IP using DNS Reverse Lookup: %s = %s",
if useDns == "warn": text, ipList)
logSys.warning("Determined IP using DNS Reverse Lookup: %s = %s",
text, ipList) return ipList
return ipList
textToIp = staticmethod(textToIp) textToIp = staticmethod(textToIp)
#@staticmethod #@staticmethod

View File

@ -0,0 +1,2 @@
Aug 14 11:54:59 i60p295 sshd[12365]: Failed publickey for roehl from example.com port 51332 ssh2
Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:192.0.43.10 port 51332 ssh2

View File

@ -84,14 +84,11 @@ class GetFailures(unittest.TestCase):
FILENAME_02 = "testcases/files/testcase02.log" FILENAME_02 = "testcases/files/testcase02.log"
FILENAME_03 = "testcases/files/testcase03.log" FILENAME_03 = "testcases/files/testcase03.log"
FILENAME_04 = "testcases/files/testcase04.log" FILENAME_04 = "testcases/files/testcase04.log"
FILENAME_USEDNS = "testcases/files/testcase-usedns.log"
def setUp(self): def setUp(self):
"""Call before every test case.""" """Call before every test case."""
# TODO: RF tests so we could do parametric testing easily. self.__filter = FileFilter(None)
# useDns='warn' and useDns='yes'
# both must be tested appropriately but ATM more
# critical is to assure correct behavior of 'no'
self.__filter = FileFilter(None, useDns='warn')
self.__filter.setActive(True) self.__filter.setActive(True)
# TODO Test this # TODO Test this
#self.__filter.setTimeRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}") #self.__filter.setTimeRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
@ -111,14 +108,14 @@ class GetFailures(unittest.TestCase):
time.localtime(output[2]) time.localtime(output[2])
self.assertEqual(found_time, output_time) self.assertEqual(found_time, output_time)
if len(output) > 3: # match matches if len(output) > 3: # match matches
self.assertEqual(found[3], output[3]) self.assertEqual(repr(found[3]), repr(output[3]))
def _assertCorrectLastAtempt(self, output): def _assertCorrectLastAtempt(self, filter_, output):
"""Additional helper to wrap most common test case """Additional helper to wrap most common test case
Test current filter to contain target ticket Test filter to contain target ticket
""" """
ticket = self.__filter.failManager.toBan() ticket = filter_.failManager.toBan()
attempts = ticket.getAttempt() attempts = ticket.getAttempt()
date = ticket.getTime() date = ticket.getTime()
@ -136,7 +133,7 @@ class GetFailures(unittest.TestCase):
self.__filter.addLogPath(GetFailures.FILENAME_01) self.__filter.addLogPath(GetFailures.FILENAME_01)
self.__filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) <HOST>") self.__filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) <HOST>")
self.__filter.getFailures(GetFailures.FILENAME_01) self.__filter.getFailures(GetFailures.FILENAME_01)
self._assertCorrectLastAtempt(output) self._assertCorrectLastAtempt(self.__filter, output)
def testGetFailures02(self): def testGetFailures02(self):
@ -147,7 +144,7 @@ class GetFailures(unittest.TestCase):
self.__filter.addLogPath(GetFailures.FILENAME_02) self.__filter.addLogPath(GetFailures.FILENAME_02)
self.__filter.addFailRegex("Failed .* from <HOST>") self.__filter.addFailRegex("Failed .* from <HOST>")
self.__filter.getFailures(GetFailures.FILENAME_02) self.__filter.getFailures(GetFailures.FILENAME_02)
self._assertCorrectLastAtempt(output) self._assertCorrectLastAtempt(self.__filter, output)
def testGetFailures03(self): def testGetFailures03(self):
output = ('203.162.223.135', 6, 1124013544.0) output = ('203.162.223.135', 6, 1124013544.0)
@ -155,7 +152,7 @@ class GetFailures(unittest.TestCase):
self.__filter.addLogPath(GetFailures.FILENAME_03) self.__filter.addLogPath(GetFailures.FILENAME_03)
self.__filter.addFailRegex("error,relay=<HOST>,.*550 User unknown") self.__filter.addFailRegex("error,relay=<HOST>,.*550 User unknown")
self.__filter.getFailures(GetFailures.FILENAME_03) self.__filter.getFailures(GetFailures.FILENAME_03)
self._assertCorrectLastAtempt(output) self._assertCorrectLastAtempt(self.__filter, output)
def testGetFailures04(self): def testGetFailures04(self):
output = [('212.41.96.186', 4, 1124013600.0), output = [('212.41.96.186', 4, 1124013600.0),
@ -167,10 +164,37 @@ class GetFailures(unittest.TestCase):
try: try:
for i, out in enumerate(output): for i, out in enumerate(output):
self._assertCorrectLastAtempt(out) self._assertCorrectLastAtempt(self.__filter, out)
except FailManagerEmpty: except FailManagerEmpty:
pass pass
def testGetFailuresUseDNS(self):
# We should still catch failures with usedns = no ;-)
output_yes = ('192.0.43.10', 2, 1124013539.0,
['Aug 14 11:54:59 i60p295 sshd[12365]: Failed publickey for roehl from example.com port 51332 ssh2\n',
'Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:192.0.43.10 port 51332 ssh2\n'])
output_no = ('192.0.43.10', 1, 1124013539.0,
['Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:192.0.43.10 port 51332 ssh2\n'])
# Actually no exception would be raised -- it will be just set to 'no'
#self.assertRaises(ValueError,
# FileFilter, None, useDns='wrong_value_for_useDns')
for useDns, output in (('yes', output_yes),
('no', output_no),
('warn', output_yes)):
filter_ = FileFilter(None, useDns=useDns)
filter_.setActive(True)
filter_.failManager.setMaxRetry(1) # we might have just few failures
filter_.addLogPath(GetFailures.FILENAME_USEDNS)
filter_.addFailRegex("Failed .* from <HOST>")
filter_.getFailures(GetFailures.FILENAME_USEDNS)
self._assertCorrectLastAtempt(filter_, output)
def testGetFailuresMultiRegex(self): def testGetFailuresMultiRegex(self):
output = ('141.3.81.106', 8, 1124013541.0) output = ('141.3.81.106', 8, 1124013541.0)
@ -178,7 +202,7 @@ class GetFailures(unittest.TestCase):
self.__filter.addFailRegex("Failed .* from <HOST>") self.__filter.addFailRegex("Failed .* from <HOST>")
self.__filter.addFailRegex("Accepted .* from <HOST>") self.__filter.addFailRegex("Accepted .* from <HOST>")
self.__filter.getFailures(GetFailures.FILENAME_02) self.__filter.getFailures(GetFailures.FILENAME_02)
self._assertCorrectLastAtempt(output) self._assertCorrectLastAtempt(self.__filter, output)
def testGetFailuresIgnoreRegex(self): def testGetFailuresIgnoreRegex(self):
output = ('141.3.81.106', 8, 1124013541.0) output = ('141.3.81.106', 8, 1124013541.0)
@ -196,7 +220,7 @@ class DNSUtilsTests(unittest.TestCase):
def testUseDns(self): def testUseDns(self):
res = DNSUtils.textToIp('www.example.com', 'no') res = DNSUtils.textToIp('www.example.com', 'no')
self.assertEqual(res, None) self.assertEqual(res, [])
res = DNSUtils.textToIp('www.example.com', 'warn') res = DNSUtils.textToIp('www.example.com', 'warn')
self.assertEqual(res, ['192.0.43.10']) self.assertEqual(res, ['192.0.43.10'])
res = DNSUtils.textToIp('www.example.com', 'yes') res = DNSUtils.textToIp('www.example.com', 'yes')