1
0
mirror of https://github.com/nmap/nmap.git synced 2026-01-09 07:59:03 +00:00

Remove extraports state inference from Ndiff. This was a feature that,

if there was only one extraports state, would create a Port object for
each scanned port that was not listed explictly. So for example, if a
scan of 100 ports had 5 open ports and an extraports of "filtered",
Ndiff would create 95 port records in the "filtered" state in addition
to the 5 "open". If there was more than one extraports state this was
not possible.

This turned out to be a slow operation, out of all proportion to its
utility. Here are times for a diff of random-1.xml and random-2.xml,
before and after:

real    0m11.912s
user    0m10.970s
sys     0m0.249s

real    0m0.773s
user    0m0.726s
sys     0m0.046s

In most cases extraports are not shown in the output, so this was wasted
effort. I know of only one place where it affected the output, when an
extraports in the A scan because a non-extraports in a different state
in the B scan. Then the previous state would be included in the <a>
port, where now it will just be listed without a state.
This commit is contained in:
david
2009-07-17 19:46:41 +00:00
parent d8925b3c11
commit 3a4a181f2d
2 changed files with 3 additions and 97 deletions

View File

@@ -959,31 +959,6 @@ class Table(object):
lines.append(u"".join(parts).rstrip())
return u"\n".join(lines)
def parse_port_list(port_list):
"""Parse a port list like
"1-1027,1029-1033,1040,1043,1050,1058-1059,1067-1068,1076,1080,1083-1084"
into a list of numbers. Raises ValueError if the port list is somehow
invalid."""
result = set()
if port_list == u"":
return list(result)
chunks = port_list.split(u",")
for chunk in chunks:
if u"-" in chunk:
start, end = chunk.split(u"-")
start = int(start)
end = int(end)
if start >= end:
raise ValueError(u"In range %s, start must be less than end." % chunk)
else:
start = int(chunk)
end = start
for p in range(start, end + 1):
result.add(p)
result = list(result)
result.sort()
return result
def warn(str):
"""Print a warning to stderr."""
print >> sys.stderr, str
@@ -999,7 +974,6 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
# popping on end.
self.element_stack = []
self.scanned_ports = {}
self.current_host = None
self.current_port = None
@@ -1032,25 +1006,6 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
start_timestamp = int(attrs.get(u"start"))
self.scan.start_date = datetime.datetime.fromtimestamp(start_timestamp)
self.scan.version = attrs.get(u"version")
elif name == u"scaninfo":
assert self.parent_element() == u"nmaprun"
try:
protocol = attrs[u"protocol"]
except KeyError:
warn(u"%s element missing the \"protocol\" attribute; skipping." % name)
return
try:
services_str = attrs[u"services"]
except KeyError:
warn(u"%s element missing the \"services\" attribute; skipping." % name)
return
try:
services = parse_port_list(services_str)
except ValueError:
warn(u"Services list \"%s\" cannot be parsed; skipping.")
return
assert protocol not in self.scanned_ports
self.scanned_ports[protocol] = services
elif name == u"host":
assert self.parent_element() == u"nmaprun"
self.current_host = Host()
@@ -1175,21 +1130,7 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
self.scan.end_date = datetime.datetime.fromtimestamp(end_timestamp)
def endElementAux(self, name):
if name == u"nmaprun":
self.scanned_ports = None
elif name == u"host":
if len(self.current_host.extraports) == 1:
# We can infer the state of unlisted ports.
extraports_state = self.current_host.extraports.keys()[0]
known_specs = self.current_host.ports.keys()
for protocol in self.scanned_ports:
for portid in self.scanned_ports[protocol]:
spec = portid, protocol
if spec in known_specs:
continue
assert spec not in self.current_host.ports
self.current_host.add_port(Port(spec, state = extraports_state))
if name == u"host":
self.current_host.script_results.sort()
self.current_host = None
elif name == u"port":

View File

@@ -32,12 +32,10 @@ class scan_test(unittest.TestCase):
self.assertEqual(len(host.ports), 2)
def test_extraports(self):
"""Test that the correct number of known ports is returned when there
are extraports in only one state."""
scan = Scan()
scan.load_from_file("test-scans/single.xml")
host = scan.hosts[0]
self.assertEqual(len(host.ports), 100)
self.assertEqual(len(host.ports), 5)
self.assertEqual(host.extraports.items(), [("filtered", 95)])
def test_extraports_multi(self):
@@ -170,7 +168,7 @@ class host_test(unittest.TestCase):
s = Scan()
s.load_from_file("test-scans/single.xml")
h = s.hosts[0]
self.assertEqual(len(h.ports), 100)
self.assertEqual(len(h.ports), 5)
self.assertEqual(len(h.extraports), 1)
self.assertEqual(h.extraports.keys()[0], u"filtered")
self.assertEqual(h.extraports.values()[0], 95)
@@ -326,39 +324,6 @@ class scan_diff_test(unittest.TestCase):
self.assertEqual(diff.host_diffs, {})
self.assertEqual(set(diff.hosts), set(diff.host_diffs.keys()))
class parse_port_list_test(unittest.TestCase):
"""Test the parse_port_list function."""
def test_empty(self):
ports = parse_port_list(u"")
self.assertEqual(len(ports), 0)
def test_single(self):
ports = parse_port_list(u"1,10,100")
self.assertEqual(len(ports), 3)
self.assertEqual(set(ports), set([1, 10, 100]))
def test_range(self):
ports = parse_port_list(u"10-20")
self.assertEqual(len(ports), 11)
self.assertEqual(set(ports), set(range(10, 21)))
def test_combo(self):
ports = parse_port_list(u"1,10,100-102,150")
self.assertEqual(set(ports), set([1, 10, 100, 101, 102, 150]))
def test_dups(self):
ports = parse_port_list(u"5,1-10")
self.assertEqual(len(ports), 10)
self.assertEqual(set(ports), set(range(1, 11)))
def test_invalid(self):
self.assertRaises(ValueError, parse_port_list, u"a")
self.assertRaises(ValueError, parse_port_list, u",1")
self.assertRaises(ValueError, parse_port_list, u"1,,2")
self.assertRaises(ValueError, parse_port_list, u"1,")
self.assertRaises(ValueError, parse_port_list, u"1-2-3")
self.assertRaises(ValueError, parse_port_list, u"10-1")
class host_diff_test(unittest.TestCase):
"""Test the HostDiff class."""
def test_empty(self):