mirror of
https://github.com/nmap/nmap.git
synced 2025-12-17 21:19:01 +00:00
Enforce PEP 8 style on Ndiff
Issues fixed: 1 E111 indentation is not a multiple of four 1 E201 whitespace after '[' 14 E251 no spaces around keyword / parameter equals 7 E301 expected 1 blank line, found 0 55 E302 expected 2 blank lines, found 1 69 E501 line too long (80 characters) 3 W291 trailing whitespace 4 W601 .has_key() is deprecated, use 'in'
This commit is contained in:
273
ndiff/ndiff.py
273
ndiff/ndiff.py
@@ -7,8 +7,8 @@
|
|||||||
#
|
#
|
||||||
# Copyright 2008 Insecure.Com LLC
|
# Copyright 2008 Insecure.Com LLC
|
||||||
# Ndiff is distributed under the same license as Nmap. See the file COPYING or
|
# Ndiff is distributed under the same license as Nmap. See the file COPYING or
|
||||||
# http://nmap.org/data/COPYING. See http://nmap.org/book/man-legal.html for more
|
# http://nmap.org/data/COPYING. See http://nmap.org/book/man-legal.html for
|
||||||
# details.
|
# more details.
|
||||||
#
|
#
|
||||||
# David Fifield
|
# David Fifield
|
||||||
# based on a design by Michael Pattrick
|
# based on a design by Michael Pattrick
|
||||||
@@ -26,9 +26,10 @@ verbose = False
|
|||||||
|
|
||||||
NDIFF_XML_VERSION = u"1"
|
NDIFF_XML_VERSION = u"1"
|
||||||
|
|
||||||
|
|
||||||
class Scan(object):
|
class Scan(object):
|
||||||
"""A single Nmap scan, corresponding to a single invocation of Nmap. It is a
|
"""A single Nmap scan, corresponding to a single invocation of Nmap. It is
|
||||||
container for a list of hosts. It also has utility methods to load itself
|
a container for a list of hosts. It also has utility methods to load itself
|
||||||
from an Nmap XML file."""
|
from an Nmap XML file."""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.scanner = None
|
self.scanner = None
|
||||||
@@ -41,7 +42,7 @@ class Scan(object):
|
|||||||
self.post_script_results = []
|
self.post_script_results = []
|
||||||
|
|
||||||
def sort_hosts(self):
|
def sort_hosts(self):
|
||||||
self.hosts.sort(key = lambda h: h.get_id())
|
self.hosts.sort(key=lambda h: h.get_id())
|
||||||
|
|
||||||
def load(self, f):
|
def load(self, f):
|
||||||
"""Load a scan from the Nmap XML in the file-like object f."""
|
"""Load a scan from the Nmap XML in the file-like object f."""
|
||||||
@@ -66,7 +67,8 @@ class Scan(object):
|
|||||||
attrs[u"args"] = self.args
|
attrs[u"args"] = self.args
|
||||||
if self.start_date is not None:
|
if self.start_date is not None:
|
||||||
attrs[u"start"] = "%d" % time.mktime(self.start_date.timetuple())
|
attrs[u"start"] = "%d" % time.mktime(self.start_date.timetuple())
|
||||||
attrs[u"startstr"] = self.start_date.strftime("%a %b %d %H:%M:%S %Y")
|
attrs[u"startstr"] = self.start_date.strftime(
|
||||||
|
"%a %b %d %H:%M:%S %Y")
|
||||||
if self.version is not None:
|
if self.version is not None:
|
||||||
attrs[u"version"] = self.version
|
attrs[u"version"] = self.version
|
||||||
writer.startElement(u"nmaprun", attrs)
|
writer.startElement(u"nmaprun", attrs)
|
||||||
@@ -82,13 +84,17 @@ class Scan(object):
|
|||||||
if self.args is not None:
|
if self.args is not None:
|
||||||
elem.setAttribute(u"args", self.args)
|
elem.setAttribute(u"args", self.args)
|
||||||
if self.start_date is not None:
|
if self.start_date is not None:
|
||||||
elem.setAttribute(u"start", "%d" % time.mktime(self.start_date.timetuple()))
|
elem.setAttribute(
|
||||||
elem.setAttribute(u"startstr", self.start_date.strftime("%a %b %d %H:%M:%S %Y"))
|
u"start", "%d" % time.mktime(self.start_date.timetuple()))
|
||||||
|
elem.setAttribute(
|
||||||
|
u"startstr",
|
||||||
|
self.start_date.strftime("%a %b %d %H:%M:%S %Y"))
|
||||||
if self.version is not None:
|
if self.version is not None:
|
||||||
elem.setAttribute(u"version", self.version)
|
elem.setAttribute(u"version", self.version)
|
||||||
frag.appendChild(elem)
|
frag.appendChild(elem)
|
||||||
return frag
|
return frag
|
||||||
|
|
||||||
|
|
||||||
class Host(object):
|
class Host(object):
|
||||||
"""A single host, with a state, addresses, host names, a dict mapping port
|
"""A single host, with a state, addresses, host names, a dict mapping port
|
||||||
specs to Ports, and a list of OS matches. Host states are strings, or None
|
specs to Ports, and a list of OS matches. Host states are strings, or None
|
||||||
@@ -103,8 +109,8 @@ class Host(object):
|
|||||||
self.script_results = []
|
self.script_results = []
|
||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
"""Return an id that is used to determine if hosts are "the same" across
|
"""Return an id that is used to determine if hosts are "the same"
|
||||||
scans."""
|
across scans."""
|
||||||
if len(self.addresses) > 0:
|
if len(self.addresses) > 0:
|
||||||
return str(sorted(self.addresses)[0])
|
return str(sorted(self.addresses)[0])
|
||||||
if len(self.hostnames) > 0:
|
if len(self.hostnames) > 0:
|
||||||
@@ -142,8 +148,9 @@ class Host(object):
|
|||||||
def extraports_string(self):
|
def extraports_string(self):
|
||||||
list = [(count, state) for (state, count) in self.extraports.items()]
|
list = [(count, state) for (state, count) in self.extraports.items()]
|
||||||
# Reverse-sort by count.
|
# Reverse-sort by count.
|
||||||
list.sort(reverse = True)
|
list.sort(reverse=True)
|
||||||
return u", ".join([u"%d %s ports" % (count, state) for (count, state) in list])
|
return u", ".join(
|
||||||
|
[u"%d %s ports" % (count, state) for (count, state) in list])
|
||||||
|
|
||||||
def state_to_dom_fragment(self, document):
|
def state_to_dom_fragment(self, document):
|
||||||
frag = document.createDocumentFragment()
|
frag = document.createDocumentFragment()
|
||||||
@@ -189,7 +196,8 @@ class Host(object):
|
|||||||
if len(self.hostnames) > 0:
|
if len(self.hostnames) > 0:
|
||||||
hostnames_elem = document.createElement(u"hostnames")
|
hostnames_elem = document.createElement(u"hostnames")
|
||||||
for hostname in self.hostnames:
|
for hostname in self.hostnames:
|
||||||
hostnames_elem.appendChild(self.hostname_to_dom_fragment(document, hostname))
|
hostnames_elem.appendChild(
|
||||||
|
self.hostname_to_dom_fragment(document, hostname))
|
||||||
elem.appendChild(hostnames_elem)
|
elem.appendChild(hostnames_elem)
|
||||||
|
|
||||||
ports_elem = document.createElement(u"ports")
|
ports_elem = document.createElement(u"ports")
|
||||||
@@ -215,6 +223,7 @@ class Host(object):
|
|||||||
frag.appendChild(elem)
|
frag.appendChild(elem)
|
||||||
return frag
|
return frag
|
||||||
|
|
||||||
|
|
||||||
class Address(object):
|
class Address(object):
|
||||||
def __init__(self, s):
|
def __init__(self, s):
|
||||||
self.s = s
|
self.s = s
|
||||||
@@ -259,27 +268,34 @@ class Address(object):
|
|||||||
# The sort_key method in the Address subclasses determines the order in which
|
# The sort_key method in the Address subclasses determines the order in which
|
||||||
# addresses are displayed. We do IPv4, then IPv6, then MAC.
|
# addresses are displayed. We do IPv4, then IPv6, then MAC.
|
||||||
|
|
||||||
|
|
||||||
class IPv4Address(Address):
|
class IPv4Address(Address):
|
||||||
type = property(lambda self: u"ipv4")
|
type = property(lambda self: u"ipv4")
|
||||||
|
|
||||||
def sort_key(self):
|
def sort_key(self):
|
||||||
return (0, self.s)
|
return (0, self.s)
|
||||||
|
|
||||||
|
|
||||||
class IPv6Address(Address):
|
class IPv6Address(Address):
|
||||||
type = property(lambda self: u"ipv6")
|
type = property(lambda self: u"ipv6")
|
||||||
|
|
||||||
def sort_key(self):
|
def sort_key(self):
|
||||||
return (1, self.s)
|
return (1, self.s)
|
||||||
|
|
||||||
|
|
||||||
class MACAddress(Address):
|
class MACAddress(Address):
|
||||||
type = property(lambda self: u"mac")
|
type = property(lambda self: u"mac")
|
||||||
|
|
||||||
def sort_key(self):
|
def sort_key(self):
|
||||||
return (2, self.s)
|
return (2, self.s)
|
||||||
|
|
||||||
|
|
||||||
class Port(object):
|
class Port(object):
|
||||||
"""A single port, consisting of a port specification, a state, and a service
|
"""A single port, consisting of a port specification, a state, and a
|
||||||
version. A specification, or "spec," is the 2-tuple (number, protocol). So
|
service version. A specification, or "spec," is the 2-tuple (number,
|
||||||
(10, "tcp") corresponds to the port 10/tcp. Port states are strings, or None
|
protocol). So (10, "tcp") corresponds to the port 10/tcp. Port states are
|
||||||
for "unknown"."""
|
strings, or None for "unknown"."""
|
||||||
def __init__(self, spec, state = None):
|
def __init__(self, spec, state=None):
|
||||||
self.spec = spec
|
self.spec = spec
|
||||||
self.state = state
|
self.state = state
|
||||||
self.service = Service()
|
self.service = Service()
|
||||||
@@ -316,6 +332,7 @@ class Port(object):
|
|||||||
frag.appendChild(elem)
|
frag.appendChild(elem)
|
||||||
return frag
|
return frag
|
||||||
|
|
||||||
|
|
||||||
class Service(object):
|
class Service(object):
|
||||||
"""A service version as determined by -sV scan. Also contains the looked-up
|
"""A service version as determined by -sV scan. Also contains the looked-up
|
||||||
port name if -sV wasn't used."""
|
port name if -sV wasn't used."""
|
||||||
@@ -331,6 +348,7 @@ class Service(object):
|
|||||||
# self.devicetype = None
|
# self.devicetype = None
|
||||||
|
|
||||||
__hash__ = None
|
__hash__ = None
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.name == other.name \
|
return self.name == other.name \
|
||||||
and self.product == other.product \
|
and self.product == other.product \
|
||||||
@@ -379,12 +397,14 @@ class Service(object):
|
|||||||
frag.appendChild(elem)
|
frag.appendChild(elem)
|
||||||
return frag
|
return frag
|
||||||
|
|
||||||
|
|
||||||
class ScriptResult(object):
|
class ScriptResult(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.id = None
|
self.id = None
|
||||||
self.output = None
|
self.output = None
|
||||||
|
|
||||||
__hash__ = None
|
__hash__ = None
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.id == other.id and self.output == other.output
|
return self.id == other.id and self.output == other.output
|
||||||
|
|
||||||
@@ -413,23 +433,26 @@ class ScriptResult(object):
|
|||||||
frag.appendChild(elem)
|
frag.appendChild(elem)
|
||||||
return frag
|
return frag
|
||||||
|
|
||||||
|
|
||||||
def format_banner(scan):
|
def format_banner(scan):
|
||||||
"""Format a startup banner more or less like Nmap does."""
|
"""Format a startup banner more or less like Nmap does."""
|
||||||
scanner = u"Nmap"
|
scanner = u"Nmap"
|
||||||
if scan.scanner is not None and scan.scanner != u"nmap":
|
if scan.scanner is not None and scan.scanner != u"nmap":
|
||||||
scanner = scan.scanner
|
scanner = scan.scanner
|
||||||
parts = [ scanner ]
|
parts = [scanner]
|
||||||
if scan.version is not None:
|
if scan.version is not None:
|
||||||
parts.append(scan.version)
|
parts.append(scan.version)
|
||||||
parts.append(u"scan")
|
parts.append(u"scan")
|
||||||
if scan.start_date is not None:
|
if scan.start_date is not None:
|
||||||
parts.append(u"initiated %s" % scan.start_date.strftime("%a %b %d %H:%M:%S %Y"))
|
parts.append(u"initiated %s" % scan.start_date.strftime(
|
||||||
|
"%a %b %d %H:%M:%S %Y"))
|
||||||
if scan.args is not None:
|
if scan.args is not None:
|
||||||
parts.append(u"as: %s" % scan.args)
|
parts.append(u"as: %s" % scan.args)
|
||||||
return u" ".join(parts)
|
return u" ".join(parts)
|
||||||
|
|
||||||
|
|
||||||
def print_script_result_diffs_text(title, script_results_a, script_results_b,
|
def print_script_result_diffs_text(title, script_results_a, script_results_b,
|
||||||
script_result_diffs, f = sys.stdout):
|
script_result_diffs, f=sys.stdout):
|
||||||
table = Table(u"*")
|
table = Table(u"*")
|
||||||
for sr_diff in script_result_diffs:
|
for sr_diff in script_result_diffs:
|
||||||
sr_diff.append_to_port_table(table)
|
sr_diff.append_to_port_table(table)
|
||||||
@@ -443,6 +466,7 @@ def print_script_result_diffs_text(title, script_results_a, script_results_b,
|
|||||||
print >> f, u" %s:" % title
|
print >> f, u" %s:" % title
|
||||||
print >> f, table
|
print >> f, table
|
||||||
|
|
||||||
|
|
||||||
def script_result_diffs_to_dom_fragment(elem, script_results_a,
|
def script_result_diffs_to_dom_fragment(elem, script_results_a,
|
||||||
script_results_b, script_result_diffs, document):
|
script_results_b, script_result_diffs, document):
|
||||||
if len(script_results_a) == 0 and len(script_results_b) == 0:
|
if len(script_results_a) == 0 and len(script_results_b) == 0:
|
||||||
@@ -464,12 +488,13 @@ def script_result_diffs_to_dom_fragment(elem, script_results_a,
|
|||||||
elem.appendChild(sr_diff.to_dom_fragment(document))
|
elem.appendChild(sr_diff.to_dom_fragment(document))
|
||||||
return elem
|
return elem
|
||||||
|
|
||||||
|
|
||||||
def host_pairs(a, b):
|
def host_pairs(a, b):
|
||||||
"""Take hosts lists a and b, which must be sorted by id, and return pairs.
|
"""Take hosts lists a and b, which must be sorted by id, and return pairs.
|
||||||
When the heads of both lists have the same ids, they are returned together.
|
When the heads of both lists have the same ids, they are returned together.
|
||||||
Otherwise the one with the smaller id is returned, with an empty host as its
|
Otherwise the one with the smaller id is returned, with an empty host as
|
||||||
counterpart, and the one with the higher id will remain in its list for a
|
its counterpart, and the one with the higher id will remain in its list for
|
||||||
later iteration."""
|
a later iteration."""
|
||||||
i = 0
|
i = 0
|
||||||
j = 0
|
j = 0
|
||||||
while i < len(a) and j < len(b):
|
while i < len(a) and j < len(b):
|
||||||
@@ -490,11 +515,13 @@ def host_pairs(a, b):
|
|||||||
yield Host(), b[j]
|
yield Host(), b[j]
|
||||||
j += 1
|
j += 1
|
||||||
|
|
||||||
|
|
||||||
class ScanDiff(object):
|
class ScanDiff(object):
|
||||||
"""An abtract class for different diff output types. Subclasses must define
|
"""An abtract class for different diff output types. Subclasses must define
|
||||||
various output methods."""
|
various output methods."""
|
||||||
def __init__(self, scan_a, scan_b, f = sys.stdout):
|
def __init__(self, scan_a, scan_b, f=sys.stdout):
|
||||||
"""Create a ScanDiff from the "before" scan_a and the "after" scan_b."""
|
"""Create a ScanDiff from the "before" scan_a and the "after"
|
||||||
|
scan_b."""
|
||||||
self.scan_a = scan_a
|
self.scan_a = scan_a
|
||||||
self.scan_b = scan_b
|
self.scan_b = scan_b
|
||||||
self.f = f
|
self.f = f
|
||||||
@@ -505,7 +532,8 @@ class ScanDiff(object):
|
|||||||
|
|
||||||
self.output_beginning()
|
self.output_beginning()
|
||||||
|
|
||||||
pre_script_result_diffs = ScriptResultDiff.diff_lists(self.scan_a.pre_script_results, self.scan_b.pre_script_results)
|
pre_script_result_diffs = ScriptResultDiff.diff_lists(
|
||||||
|
self.scan_a.pre_script_results, self.scan_b.pre_script_results)
|
||||||
self.output_pre_scripts(pre_script_result_diffs)
|
self.output_pre_scripts(pre_script_result_diffs)
|
||||||
|
|
||||||
cost = 0
|
cost = 0
|
||||||
@@ -518,15 +546,18 @@ class ScanDiff(object):
|
|||||||
host = host_a or host_b
|
host = host_a or host_b
|
||||||
self.output_host_diff(h_diff)
|
self.output_host_diff(h_diff)
|
||||||
|
|
||||||
post_script_result_diffs = ScriptResultDiff.diff_lists(self.scan_a.post_script_results, self.scan_b.post_script_results)
|
post_script_result_diffs = ScriptResultDiff.diff_lists(
|
||||||
|
self.scan_a.post_script_results,
|
||||||
|
self.scan_b.post_script_results)
|
||||||
self.output_post_scripts(post_script_result_diffs)
|
self.output_post_scripts(post_script_result_diffs)
|
||||||
|
|
||||||
self.output_ending()
|
self.output_ending()
|
||||||
|
|
||||||
return cost
|
return cost
|
||||||
|
|
||||||
|
|
||||||
class ScanDiffText(ScanDiff):
|
class ScanDiffText(ScanDiff):
|
||||||
def __init__(self, scan_a, scan_b, f = sys.stdout):
|
def __init__(self, scan_a, scan_b, f=sys.stdout):
|
||||||
ScanDiff.__init__(self, scan_a, scan_b, f)
|
ScanDiff.__init__(self, scan_a, scan_b, f)
|
||||||
|
|
||||||
def output_beginning(self):
|
def output_beginning(self):
|
||||||
@@ -555,8 +586,9 @@ class ScanDiffText(ScanDiff):
|
|||||||
def output_ending(self):
|
def output_ending(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ScanDiffXML(ScanDiff):
|
class ScanDiffXML(ScanDiff):
|
||||||
def __init__(self, scan_a, scan_b, f = sys.stdout):
|
def __init__(self, scan_a, scan_b, f=sys.stdout):
|
||||||
ScanDiff.__init__(self, scan_a, scan_b, f)
|
ScanDiff.__init__(self, scan_a, scan_b, f)
|
||||||
|
|
||||||
impl = xml.dom.minidom.getDOMImplementation()
|
impl = xml.dom.minidom.getDOMImplementation()
|
||||||
@@ -566,7 +598,8 @@ class ScanDiffXML(ScanDiff):
|
|||||||
|
|
||||||
def nmaprun_differs(self):
|
def nmaprun_differs(self):
|
||||||
for attr in ("scanner", "version", "args", "start_date", "end_date"):
|
for attr in ("scanner", "version", "args", "start_date", "end_date"):
|
||||||
if getattr(self.scan_a, attr, None) != getattr(self.scan_b, attr, None):
|
if getattr(self.scan_a, attr, None) !=\
|
||||||
|
getattr(self.scan_b, attr, None):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -576,10 +609,13 @@ class ScanDiffXML(ScanDiff):
|
|||||||
self.writer.startElement(u"scandiff", {})
|
self.writer.startElement(u"scandiff", {})
|
||||||
|
|
||||||
if self.nmaprun_differs():
|
if self.nmaprun_differs():
|
||||||
self.writer.frag_a(self.scan_a.nmaprun_to_dom_fragment(self.document))
|
self.writer.frag_a(
|
||||||
self.writer.frag_b(self.scan_b.nmaprun_to_dom_fragment(self.document))
|
self.scan_a.nmaprun_to_dom_fragment(self.document))
|
||||||
|
self.writer.frag_b(
|
||||||
|
self.scan_b.nmaprun_to_dom_fragment(self.document))
|
||||||
elif verbose:
|
elif verbose:
|
||||||
self.writer.frag(self.scan_a.nmaprun_to_dom_fragment(self.document))
|
self.writer.frag(
|
||||||
|
self.scan_a.nmaprun_to_dom_fragment(self.document))
|
||||||
|
|
||||||
def output_pre_scripts(self, pre_script_result_diffs):
|
def output_pre_scripts(self, pre_script_result_diffs):
|
||||||
if len(pre_script_result_diffs) > 0 or verbose:
|
if len(pre_script_result_diffs) > 0 or verbose:
|
||||||
@@ -611,9 +647,10 @@ class ScanDiffXML(ScanDiff):
|
|||||||
self.writer.endElement(u"nmapdiff")
|
self.writer.endElement(u"nmapdiff")
|
||||||
self.writer.endDocument()
|
self.writer.endDocument()
|
||||||
|
|
||||||
|
|
||||||
class HostDiff(object):
|
class HostDiff(object):
|
||||||
"""A diff of two Hosts. It contains the two hosts, variables describing what
|
"""A diff of two Hosts. It contains the two hosts, variables describing
|
||||||
changed, and a list of PortDiffs and OS differences."""
|
what changed, and a list of PortDiffs and OS differences."""
|
||||||
def __init__(self, host_a, host_b):
|
def __init__(self, host_a, host_b):
|
||||||
self.host_a = host_a
|
self.host_a = host_a
|
||||||
self.host_b = host_b
|
self.host_b = host_b
|
||||||
@@ -639,12 +676,14 @@ class HostDiff(object):
|
|||||||
self.id_changed = True
|
self.id_changed = True
|
||||||
self.cost += 1
|
self.cost += 1
|
||||||
|
|
||||||
all_specs = list(set(self.host_a.ports.keys()).union(set(self.host_b.ports.keys())))
|
all_specs = list(
|
||||||
|
set(self.host_a.ports.keys()).union(
|
||||||
|
set(self.host_b.ports.keys())))
|
||||||
all_specs.sort()
|
all_specs.sort()
|
||||||
for spec in all_specs:
|
for spec in all_specs:
|
||||||
# Currently we only compare ports with the same spec. This ignores
|
# Currently we only compare ports with the same spec. This ignores
|
||||||
# the possibility that a service is moved lock, stock, and barrel to
|
# the possibility that a service is moved lock, stock, and barrel
|
||||||
# another port.
|
# to another port.
|
||||||
port_a = self.host_a.ports.get(spec)
|
port_a = self.host_a.ports.get(spec)
|
||||||
port_b = self.host_b.ports.get(spec)
|
port_b = self.host_b.ports.get(spec)
|
||||||
diff = PortDiff(port_a or Port(spec), port_b or Port(spec))
|
diff = PortDiff(port_a or Port(spec), port_b or Port(spec))
|
||||||
@@ -654,20 +693,24 @@ class HostDiff(object):
|
|||||||
self.port_diffs[port] = diff
|
self.port_diffs[port] = diff
|
||||||
self.cost += diff.cost
|
self.cost += diff.cost
|
||||||
|
|
||||||
os_diffs = difflib.SequenceMatcher(None, self.host_a.os, self.host_b.os)
|
os_diffs = difflib.SequenceMatcher(
|
||||||
|
None, self.host_a.os, self.host_b.os)
|
||||||
self.os_diffs = os_diffs.get_opcodes()
|
self.os_diffs = os_diffs.get_opcodes()
|
||||||
os_cost = len([x for x in self.os_diffs if x[0] != "equal"])
|
os_cost = len([x for x in self.os_diffs if x[0] != "equal"])
|
||||||
if os_cost > 0:
|
if os_cost > 0:
|
||||||
self.os_changed = True
|
self.os_changed = True
|
||||||
self.cost += os_cost
|
self.cost += os_cost
|
||||||
|
|
||||||
extraports_a = tuple((count, state) for (state, count) in self.host_a.extraports.items())
|
extraports_a = tuple((count, state)
|
||||||
extraports_b = tuple((count, state) for (state, count) in self.host_b.extraports.items())
|
for (state, count) in self.host_a.extraports.items())
|
||||||
|
extraports_b = tuple((count, state)
|
||||||
|
for (state, count) in self.host_b.extraports.items())
|
||||||
if extraports_a != extraports_b:
|
if extraports_a != extraports_b:
|
||||||
self.extraports_changed = True
|
self.extraports_changed = True
|
||||||
self.cost += 1
|
self.cost += 1
|
||||||
|
|
||||||
self.script_result_diffs = ScriptResultDiff.diff_lists(self.host_a.script_results, self.host_b.script_results)
|
self.script_result_diffs = ScriptResultDiff.diff_lists(
|
||||||
|
self.host_a.script_results, self.host_b.script_results)
|
||||||
self.cost += len(self.script_result_diffs)
|
self.cost += len(self.script_result_diffs)
|
||||||
|
|
||||||
def include_diff(self, diff):
|
def include_diff(self, diff):
|
||||||
@@ -680,7 +723,7 @@ class HostDiff(object):
|
|||||||
return True
|
return True
|
||||||
return diff.cost > 0
|
return diff.cost > 0
|
||||||
|
|
||||||
def print_text(self, f = sys.stdout):
|
def print_text(self, f=sys.stdout):
|
||||||
host_a = self.host_a
|
host_a = self.host_a
|
||||||
host_b = self.host_b
|
host_b = self.host_b
|
||||||
|
|
||||||
@@ -738,7 +781,8 @@ class HostDiff(object):
|
|||||||
print >> f, u"-OS details:"
|
print >> f, u"-OS details:"
|
||||||
elif len(host_b.os) > 0:
|
elif len(host_b.os) > 0:
|
||||||
print >> f, u"+OS details:"
|
print >> f, u"+OS details:"
|
||||||
# os_diffs is a list of 5-tuples returned by difflib.SequenceMatcher.
|
# os_diffs is a list of 5-tuples returned by
|
||||||
|
# difflib.SequenceMatcher.
|
||||||
for op, i1, i2, j1, j2 in self.os_diffs:
|
for op, i1, i2, j1, j2 in self.os_diffs:
|
||||||
if op == "replace" or op == "delete":
|
if op == "replace" or op == "delete":
|
||||||
for i in range(i1, i2):
|
for i in range(i1, i2):
|
||||||
@@ -809,15 +853,18 @@ class HostDiff(object):
|
|||||||
hostnameset_a = set(host_a.hostnames)
|
hostnameset_a = set(host_a.hostnames)
|
||||||
hostnameset_b = set(host_b.hostnames)
|
hostnameset_b = set(host_b.hostnames)
|
||||||
for hostname in sorted(hostnameset_a.intersection(hostnameset_b)):
|
for hostname in sorted(hostnameset_a.intersection(hostnameset_b)):
|
||||||
hostnames_elem.appendChild(host_a.hostname_to_dom_fragment(document, hostname))
|
hostnames_elem.appendChild(
|
||||||
|
host_a.hostname_to_dom_fragment(document, hostname))
|
||||||
a_elem = document.createElement(u"a")
|
a_elem = document.createElement(u"a")
|
||||||
for hostname in sorted(hostnameset_a - hostnameset_b):
|
for hostname in sorted(hostnameset_a - hostnameset_b):
|
||||||
a_elem.appendChild(host_a.hostname_to_dom_fragment(document, hostname))
|
a_elem.appendChild(
|
||||||
|
host_a.hostname_to_dom_fragment(document, hostname))
|
||||||
if a_elem.hasChildNodes():
|
if a_elem.hasChildNodes():
|
||||||
hostnames_elem.appendChild(a_elem)
|
hostnames_elem.appendChild(a_elem)
|
||||||
b_elem = document.createElement(u"b")
|
b_elem = document.createElement(u"b")
|
||||||
for hostname in sorted(hostnameset_b - hostnameset_a):
|
for hostname in sorted(hostnameset_b - hostnameset_a):
|
||||||
b_elem.appendChild(host_b.hostname_to_dom_fragment(document, hostname))
|
b_elem.appendChild(
|
||||||
|
host_b.hostname_to_dom_fragment(document, hostname))
|
||||||
if b_elem.hasChildNodes():
|
if b_elem.hasChildNodes():
|
||||||
hostnames_elem.appendChild(b_elem)
|
hostnames_elem.appendChild(b_elem)
|
||||||
if hostnames_elem.hasChildNodes():
|
if hostnames_elem.hasChildNodes():
|
||||||
@@ -848,21 +895,25 @@ class HostDiff(object):
|
|||||||
# OS changes.
|
# OS changes.
|
||||||
if self.os_changed or verbose:
|
if self.os_changed or verbose:
|
||||||
os_elem = document.createElement(u"os")
|
os_elem = document.createElement(u"os")
|
||||||
# os_diffs is a list of 5-tuples returned by difflib.SequenceMatcher.
|
# os_diffs is a list of 5-tuples returned by
|
||||||
|
# difflib.SequenceMatcher.
|
||||||
for op, i1, i2, j1, j2 in self.os_diffs:
|
for op, i1, i2, j1, j2 in self.os_diffs:
|
||||||
if op == "replace" or op == "delete":
|
if op == "replace" or op == "delete":
|
||||||
a_elem = document.createElement(u"a")
|
a_elem = document.createElement(u"a")
|
||||||
for i in range(i1, i2):
|
for i in range(i1, i2):
|
||||||
a_elem.appendChild(host_a.os_to_dom_fragment(document, host_a.os[i]))
|
a_elem.appendChild(host_a.os_to_dom_fragment(
|
||||||
|
document, host_a.os[i]))
|
||||||
os_elem.appendChild(a_elem)
|
os_elem.appendChild(a_elem)
|
||||||
if op == "replace" or op == "insert":
|
if op == "replace" or op == "insert":
|
||||||
b_elem = document.createElement(u"b")
|
b_elem = document.createElement(u"b")
|
||||||
for i in range(j1, j2):
|
for i in range(j1, j2):
|
||||||
b_elem.appendChild(host_b.os_to_dom_fragment(document, host_b.os[i]))
|
b_elem.appendChild(host_b.os_to_dom_fragment(
|
||||||
|
document, host_b.os[i]))
|
||||||
os_elem.appendChild(b_elem)
|
os_elem.appendChild(b_elem)
|
||||||
if op == "equal":
|
if op == "equal":
|
||||||
for i in range(i1, i2):
|
for i in range(i1, i2):
|
||||||
os_elem.appendChild(host_a.os_to_dom_fragment(document, host_a.os[i]))
|
os_elem.appendChild(host_a.os_to_dom_fragment(
|
||||||
|
document, host_a.os[i]))
|
||||||
if os_elem.hasChildNodes():
|
if os_elem.hasChildNodes():
|
||||||
host_elem.appendChild(os_elem)
|
host_elem.appendChild(os_elem)
|
||||||
|
|
||||||
@@ -878,6 +929,7 @@ class HostDiff(object):
|
|||||||
|
|
||||||
return frag
|
return frag
|
||||||
|
|
||||||
|
|
||||||
class PortDiff(object):
|
class PortDiff(object):
|
||||||
"""A diff of two Ports. It contains the two ports and the cost of changing
|
"""A diff of two Ports. It contains the two ports and the cost of changing
|
||||||
one into the other. If the cost is 0 then the two ports are the same."""
|
one into the other. If the cost is 0 then the two ports are the same."""
|
||||||
@@ -899,7 +951,8 @@ class PortDiff(object):
|
|||||||
if self.port_a.service != self.port_b.service:
|
if self.port_a.service != self.port_b.service:
|
||||||
self.cost += 1
|
self.cost += 1
|
||||||
|
|
||||||
self.script_result_diffs = ScriptResultDiff.diff_lists(self.port_a.script_results, self.port_b.script_results)
|
self.script_result_diffs = ScriptResultDiff.diff_lists(
|
||||||
|
self.port_a.script_results, self.port_b.script_results)
|
||||||
self.cost += len(self.script_result_diffs)
|
self.cost += len(self.script_result_diffs)
|
||||||
|
|
||||||
# PortDiffs are inserted into a Table and then printed, not printed out
|
# PortDiffs are inserted into a Table and then printed, not printed out
|
||||||
@@ -933,7 +986,8 @@ class PortDiff(object):
|
|||||||
frag = document.createDocumentFragment()
|
frag = document.createDocumentFragment()
|
||||||
portdiff_elem = document.createElement(u"portdiff")
|
portdiff_elem = document.createElement(u"portdiff")
|
||||||
frag.appendChild(portdiff_elem)
|
frag.appendChild(portdiff_elem)
|
||||||
if self.port_a.spec == self.port_b.spec and self.port_a.state == self.port_b.state:
|
if (self.port_a.spec == self.port_b.spec and
|
||||||
|
self.port_a.state == self.port_b.state):
|
||||||
port_elem = document.createElement(u"port")
|
port_elem = document.createElement(u"port")
|
||||||
port_elem.setAttribute(u"portid", unicode(self.port_a.spec[0]))
|
port_elem.setAttribute(u"portid", unicode(self.port_a.spec[0]))
|
||||||
port_elem.setAttribute(u"protocol", self.port_a.spec[1])
|
port_elem.setAttribute(u"protocol", self.port_a.spec[1])
|
||||||
@@ -942,13 +996,16 @@ class PortDiff(object):
|
|||||||
state_elem.setAttribute(u"state", self.port_a.state)
|
state_elem.setAttribute(u"state", self.port_a.state)
|
||||||
port_elem.appendChild(state_elem)
|
port_elem.appendChild(state_elem)
|
||||||
if self.port_a.service == self.port_b.service:
|
if self.port_a.service == self.port_b.service:
|
||||||
port_elem.appendChild(self.port_a.service.to_dom_fragment(document))
|
port_elem.appendChild(
|
||||||
|
self.port_a.service.to_dom_fragment(document))
|
||||||
else:
|
else:
|
||||||
a_elem = document.createElement(u"a")
|
a_elem = document.createElement(u"a")
|
||||||
a_elem.appendChild(self.port_a.service.to_dom_fragment(document))
|
a_elem.appendChild(
|
||||||
|
self.port_a.service.to_dom_fragment(document))
|
||||||
port_elem.appendChild(a_elem)
|
port_elem.appendChild(a_elem)
|
||||||
b_elem = document.createElement(u"b")
|
b_elem = document.createElement(u"b")
|
||||||
b_elem.appendChild(self.port_b.service.to_dom_fragment(document))
|
b_elem.appendChild(
|
||||||
|
self.port_b.service.to_dom_fragment(document))
|
||||||
port_elem.appendChild(b_elem)
|
port_elem.appendChild(b_elem)
|
||||||
for sr_diff in self.script_result_diffs:
|
for sr_diff in self.script_result_diffs:
|
||||||
port_elem.appendChild(sr_diff.to_dom_fragment(document))
|
port_elem.appendChild(sr_diff.to_dom_fragment(document))
|
||||||
@@ -963,6 +1020,7 @@ class PortDiff(object):
|
|||||||
|
|
||||||
return frag
|
return frag
|
||||||
|
|
||||||
|
|
||||||
class ScriptResultDiff(object):
|
class ScriptResultDiff(object):
|
||||||
def __init__(self, sr_a, sr_b):
|
def __init__(self, sr_a, sr_b):
|
||||||
"""One of sr_a and sr_b may be None."""
|
"""One of sr_a and sr_b may be None."""
|
||||||
@@ -997,8 +1055,8 @@ class ScriptResultDiff(object):
|
|||||||
return diffs
|
return diffs
|
||||||
diff_lists = staticmethod(diff_lists)
|
diff_lists = staticmethod(diff_lists)
|
||||||
|
|
||||||
# Script result diffs are appended to a port table rather than being printed
|
# Script result diffs are appended to a port table rather than being
|
||||||
# directly, so append_to_port_table exists instead of print_text.
|
# printed directly, so append_to_port_table exists instead of print_text.
|
||||||
def append_to_port_table(self, table):
|
def append_to_port_table(self, table):
|
||||||
a_lines = []
|
a_lines = []
|
||||||
b_lines = []
|
b_lines = []
|
||||||
@@ -1021,7 +1079,9 @@ class ScriptResultDiff(object):
|
|||||||
|
|
||||||
def to_dom_fragment(self, document):
|
def to_dom_fragment(self, document):
|
||||||
frag = document.createDocumentFragment()
|
frag = document.createDocumentFragment()
|
||||||
if self.sr_a is not None and self.sr_b is not None and self.sr_a == self.sr_b:
|
if (self.sr_a is not None and
|
||||||
|
self.sr_b is not None and
|
||||||
|
self.sr_a == self.sr_b):
|
||||||
frag.appendChild(self.sr_a.to_dom_fragment(document))
|
frag.appendChild(self.sr_a.to_dom_fragment(document))
|
||||||
else:
|
else:
|
||||||
if self.sr_a is not None:
|
if self.sr_a is not None:
|
||||||
@@ -1034,12 +1094,13 @@ class ScriptResultDiff(object):
|
|||||||
frag.appendChild(b_elem)
|
frag.appendChild(b_elem)
|
||||||
return frag
|
return frag
|
||||||
|
|
||||||
|
|
||||||
class Table(object):
|
class Table(object):
|
||||||
"""A table of character data, like NmapOutputTable."""
|
"""A table of character data, like NmapOutputTable."""
|
||||||
def __init__(self, template):
|
def __init__(self, template):
|
||||||
"""template is a string consisting of "*" and other characters. Each "*"
|
"""template is a string consisting of "*" and other characters. Each
|
||||||
is a left-justified space-padded field. All other characters are copied
|
"*" is a left-justified space-padded field. All other characters are
|
||||||
to the output."""
|
copied to the output."""
|
||||||
self.widths = []
|
self.widths = []
|
||||||
self.rows = []
|
self.rows = []
|
||||||
self.prefix = u""
|
self.prefix = u""
|
||||||
@@ -1101,10 +1162,12 @@ class Table(object):
|
|||||||
lines.append(u"".join(parts).rstrip())
|
lines.append(u"".join(parts).rstrip())
|
||||||
return u"\n".join(lines)
|
return u"\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
def warn(str):
|
def warn(str):
|
||||||
"""Print a warning to stderr."""
|
"""Print a warning to stderr."""
|
||||||
print >> sys.stderr, str
|
print >> sys.stderr, str
|
||||||
|
|
||||||
|
|
||||||
class NmapContentHandler(xml.sax.handler.ContentHandler):
|
class NmapContentHandler(xml.sax.handler.ContentHandler):
|
||||||
"""The xml.sax ContentHandler for the XML parser. It contains a Scan object
|
"""The xml.sax ContentHandler for the XML parser. It contains a Scan object
|
||||||
that is filled in and can be read back again once the parse method is
|
that is filled in and can be read back again once the parse method is
|
||||||
@@ -1139,8 +1202,8 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def parent_element(self):
|
def parent_element(self):
|
||||||
"""Return the name of the element containing the current one, or None if
|
"""Return the name of the element containing the current one, or None
|
||||||
this is the root element."""
|
if this is the root element."""
|
||||||
if len(self.element_stack) == 0:
|
if len(self.element_stack) == 0:
|
||||||
return None
|
return None
|
||||||
return self.element_stack[-1]
|
return self.element_stack[-1]
|
||||||
@@ -1164,9 +1227,10 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
|
|
||||||
def _start_nmaprun(self, name, attrs):
|
def _start_nmaprun(self, name, attrs):
|
||||||
assert self.parent_element() == None
|
assert self.parent_element() == None
|
||||||
if attrs.has_key(u"start"):
|
if "start" in attrs:
|
||||||
start_timestamp = int(attrs.get(u"start"))
|
start_timestamp = int(attrs.get(u"start"))
|
||||||
self.scan.start_date = datetime.datetime.fromtimestamp(start_timestamp)
|
self.scan.start_date = datetime.datetime.fromtimestamp(
|
||||||
|
start_timestamp)
|
||||||
self.scan.scanner = attrs.get(u"scanner")
|
self.scan.scanner = attrs.get(u"scanner")
|
||||||
self.scan.args = attrs.get(u"args")
|
self.scan.args = attrs.get(u"args")
|
||||||
self.scan.version = attrs.get(u"version")
|
self.scan.version = attrs.get(u"version")
|
||||||
@@ -1181,7 +1245,9 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
assert self.current_host is not None
|
assert self.current_host is not None
|
||||||
state = attrs.get(u"state")
|
state = attrs.get(u"state")
|
||||||
if state is None:
|
if state is None:
|
||||||
warn(u"%s element of host %s is missing the \"state\" attribute; assuming \"unknown\"." % (name, self.current_host.format_name()))
|
warn(u'%s element of host %s is missing the "state" attribute; '
|
||||||
|
'assuming \unknown\.' % (
|
||||||
|
name, self.current_host.format_name()))
|
||||||
return
|
return
|
||||||
self.current_host.state = state
|
self.current_host.state = state
|
||||||
|
|
||||||
@@ -1190,7 +1256,9 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
assert self.current_host is not None
|
assert self.current_host is not None
|
||||||
addr = attrs.get(u"addr")
|
addr = attrs.get(u"addr")
|
||||||
if addr is None:
|
if addr is None:
|
||||||
warn(u"%s element of host %s is missing the \"addr\" attribute; skipping." % (name, self.current_host.format_name()))
|
warn(u'%s element of host %s is missing the "addr" '
|
||||||
|
'attribute; skipping.' % (
|
||||||
|
name, self.current_host.format_name()))
|
||||||
return
|
return
|
||||||
addrtype = attrs.get(u"addrtype", u"ipv4")
|
addrtype = attrs.get(u"addrtype", u"ipv4")
|
||||||
self.current_host.add_address(Address.new(addrtype, addr))
|
self.current_host.add_address(Address.new(addrtype, addr))
|
||||||
@@ -1200,7 +1268,9 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
assert self.current_host is not None
|
assert self.current_host is not None
|
||||||
hostname = attrs.get(u"name")
|
hostname = attrs.get(u"name")
|
||||||
if hostname is None:
|
if hostname is None:
|
||||||
warn(u"%s element of host %s is missing the \"name\" attribute; skipping." % (name, self.current_host.format_name()))
|
warn(u'%s element of host %s is missing the "name" '
|
||||||
|
'attribute; skipping.' % (
|
||||||
|
name, self.current_host.format_name()))
|
||||||
return
|
return
|
||||||
self.current_host.add_hostname(hostname)
|
self.current_host.add_hostname(hostname)
|
||||||
|
|
||||||
@@ -1209,20 +1279,27 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
assert self.current_host is not None
|
assert self.current_host is not None
|
||||||
state = attrs.get(u"state")
|
state = attrs.get(u"state")
|
||||||
if state is None:
|
if state is None:
|
||||||
warn(u"%s element of host %s is missing the \"state\" attribute; assuming \"unknown\"." % (name, self.current_host.format_name()))
|
warn(u'%s element of host %s is missing the "state" '
|
||||||
|
'attribute; assuming "unknown".' % (
|
||||||
|
name, self.current_host.format_name()))
|
||||||
state = None
|
state = None
|
||||||
if state in self.current_host.extraports:
|
if state in self.current_host.extraports:
|
||||||
warn(u"Duplicate extraports state \"%s\" in host %s." % (state, self.current_host.format_name()))
|
warn(u'Duplicate extraports state "%s" in host %s.' % (
|
||||||
|
state, self.current_host.format_name()))
|
||||||
|
|
||||||
count = attrs.get(u"count")
|
count = attrs.get(u"count")
|
||||||
if count is None:
|
if count is None:
|
||||||
warn(u"%s element of host %s is missing the \"count\" attribute; assuming 0." % (name, self.current_host.format_name()))
|
warn(u'%s element of host %s is missing the "count" '
|
||||||
|
'attribute; assuming 0.' % (
|
||||||
|
name, self.current_host.format_name()))
|
||||||
count = 0
|
count = 0
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
count = int(count)
|
count = int(count)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
warn(u"Can't convert extraports count \"%s\" to an integer in host %s; assuming 0." % (attrs[u"count"], self.current_host.format_name()))
|
warn(u"Can't convert extraports count \"%s\" "
|
||||||
|
"to an integer in host %s; assuming 0." % (
|
||||||
|
attrs[u"count"], self.current_host.format_name()))
|
||||||
count = 0
|
count = 0
|
||||||
self.current_host.extraports[state] = count
|
self.current_host.extraports[state] = count
|
||||||
|
|
||||||
@@ -1231,16 +1308,22 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
assert self.current_host is not None
|
assert self.current_host is not None
|
||||||
portid_str = attrs.get(u"portid")
|
portid_str = attrs.get(u"portid")
|
||||||
if portid_str is None:
|
if portid_str is None:
|
||||||
warn(u"%s element of host %s missing the \"portid\" attribute; skipping." % (name, self.current_host.format_name()))
|
warn(u'%s element of host %s missing the "portid" '
|
||||||
|
'attribute; skipping.' % (
|
||||||
|
name, self.current_host.format_name()))
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
portid = int(portid_str)
|
portid = int(portid_str)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
warn(u"Can't convert portid \"%s\" to an integer in host %s; skipping port." % (portid_str, self.current_host.format_name()))
|
warn(u"Can't convert portid \"%s\" to an integer "
|
||||||
|
"in host %s; skipping port." % (
|
||||||
|
portid_str, self.current_host.format_name()))
|
||||||
return
|
return
|
||||||
protocol = attrs.get(u"protocol")
|
protocol = attrs.get(u"protocol")
|
||||||
if protocol is None:
|
if protocol is None:
|
||||||
warn(u"%s element of host %s missing the \"protocol\" attribute; skipping." % (name, self.current_host.format_name()))
|
warn(u'%s element of host %s missing the "protocol" '
|
||||||
|
'attribute; skipping.' % (
|
||||||
|
name, self.current_host.format_name()))
|
||||||
return
|
return
|
||||||
self.current_port = Port((portid, protocol))
|
self.current_port = Port((portid, protocol))
|
||||||
|
|
||||||
@@ -1249,8 +1332,10 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
assert self.current_host is not None
|
assert self.current_host is not None
|
||||||
if self.current_port is None:
|
if self.current_port is None:
|
||||||
return
|
return
|
||||||
if not attrs.has_key(u"state"):
|
if "state" not in attrs:
|
||||||
warn(u"%s element of port %s is missing the \"state\" attribute; assuming \"unknown\"." % (name, self.current_port.spec_string()))
|
warn(u'%s element of port %s is missing the "state" '
|
||||||
|
'attribute; assuming "unknown".' % (
|
||||||
|
name, self.current_port.spec_string()))
|
||||||
return
|
return
|
||||||
self.current_port.state = attrs[u"state"]
|
self.current_port.state = attrs[u"state"]
|
||||||
self.current_host.add_port(self.current_port)
|
self.current_host.add_port(self.current_port)
|
||||||
@@ -1270,12 +1355,13 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
result = ScriptResult()
|
result = ScriptResult()
|
||||||
result.id = attrs.get(u"id")
|
result.id = attrs.get(u"id")
|
||||||
if result.id is None:
|
if result.id is None:
|
||||||
warn(u"%s element missing the \"id\" attribute; skipping." % name)
|
warn(u'%s element missing the "id" attribute; skipping.' % name)
|
||||||
return
|
return
|
||||||
|
|
||||||
result.output = attrs.get(u"output")
|
result.output = attrs.get(u"output")
|
||||||
if result.output is None:
|
if result.output is None:
|
||||||
warn(u"%s element missing the \"output\" attribute; skipping." % name)
|
warn(u'%s element missing the "output" attribute; skipping.'
|
||||||
|
% name)
|
||||||
return
|
return
|
||||||
if self.parent_element() == u"prescript":
|
if self.parent_element() == u"prescript":
|
||||||
self.scan.pre_script_results.append(result)
|
self.scan.pre_script_results.append(result)
|
||||||
@@ -1286,20 +1372,23 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
elif self.parent_element() == u"port":
|
elif self.parent_element() == u"port":
|
||||||
self.current_port.script_results.append(result)
|
self.current_port.script_results.append(result)
|
||||||
else:
|
else:
|
||||||
warn(u"%s element not inside prescript, postscript, hostscript, or port element; ignoring." % name)
|
warn(u"%s element not inside prescript, postscript, hostscript, "
|
||||||
|
"or port element; ignoring." % name)
|
||||||
return
|
return
|
||||||
|
|
||||||
def _start_osmatch(self, name, attrs):
|
def _start_osmatch(self, name, attrs):
|
||||||
assert self.parent_element() == u"os"
|
assert self.parent_element() == u"os"
|
||||||
assert self.current_host is not None
|
assert self.current_host is not None
|
||||||
if not attrs.has_key(u"name"):
|
if "name" not in attrs:
|
||||||
warn(u"%s element of host %s is missing the \"name\" attribute; skipping." % (name, self.current_host.format_name()))
|
warn(u'%s element of host %s is missing the "name" '
|
||||||
|
'attribute; skipping.' % (
|
||||||
|
name, self.current_host.format_name()))
|
||||||
return
|
return
|
||||||
self.current_host.os.append(attrs[u"name"])
|
self.current_host.os.append(attrs[u"name"])
|
||||||
|
|
||||||
def _start_finished(self, name, attrs):
|
def _start_finished(self, name, attrs):
|
||||||
assert self.parent_element() == u"runstats"
|
assert self.parent_element() == u"runstats"
|
||||||
if attrs.has_key(u"time"):
|
if "time" in attrs:
|
||||||
end_timestamp = int(attrs.get(u"time"))
|
end_timestamp = int(attrs.get(u"time"))
|
||||||
self.scan.end_date = datetime.datetime.fromtimestamp(end_timestamp)
|
self.scan.end_date = datetime.datetime.fromtimestamp(end_timestamp)
|
||||||
|
|
||||||
@@ -1311,6 +1400,7 @@ class NmapContentHandler(xml.sax.handler.ContentHandler):
|
|||||||
self.current_port.script_results.sort()
|
self.current_port.script_results.sort()
|
||||||
self.current_port = None
|
self.current_port = None
|
||||||
|
|
||||||
|
|
||||||
class XMLWriter (xml.sax.saxutils.XMLGenerator):
|
class XMLWriter (xml.sax.saxutils.XMLGenerator):
|
||||||
def __init__(self, f):
|
def __init__(self, f):
|
||||||
xml.sax.saxutils.XMLGenerator.__init__(self, f, "utf-8")
|
xml.sax.saxutils.XMLGenerator.__init__(self, f, "utf-8")
|
||||||
@@ -1318,20 +1408,21 @@ class XMLWriter (xml.sax.saxutils.XMLGenerator):
|
|||||||
|
|
||||||
def frag(self, frag):
|
def frag(self, frag):
|
||||||
for node in frag.childNodes:
|
for node in frag.childNodes:
|
||||||
node.writexml(self.f, newl = u"\n")
|
node.writexml(self.f, newl=u"\n")
|
||||||
|
|
||||||
def frag_a(self, frag):
|
def frag_a(self, frag):
|
||||||
self.startElement(u"a", {})
|
self.startElement(u"a", {})
|
||||||
for node in frag.childNodes:
|
for node in frag.childNodes:
|
||||||
node.writexml(self.f, newl = u"\n")
|
node.writexml(self.f, newl=u"\n")
|
||||||
self.endElement(u"a")
|
self.endElement(u"a")
|
||||||
|
|
||||||
def frag_b(self, frag):
|
def frag_b(self, frag):
|
||||||
self.startElement(u"b", {})
|
self.startElement(u"b", {})
|
||||||
for node in frag.childNodes:
|
for node in frag.childNodes:
|
||||||
node.writexml(self.f, newl = u"\n")
|
node.writexml(self.f, newl=u"\n")
|
||||||
self.endElement(u"b")
|
self.endElement(u"b")
|
||||||
|
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
print u"""\
|
print u"""\
|
||||||
Usage: %s [option] FILE1 FILE2
|
Usage: %s [option] FILE1 FILE2
|
||||||
@@ -1349,17 +1440,20 @@ EXIT_EQUAL = 0
|
|||||||
EXIT_DIFFERENT = 1
|
EXIT_DIFFERENT = 1
|
||||||
EXIT_ERROR = 2
|
EXIT_ERROR = 2
|
||||||
|
|
||||||
|
|
||||||
def usage_error(msg):
|
def usage_error(msg):
|
||||||
print >> sys.stderr, u"%s: %s" % (sys.argv[0], msg)
|
print >> sys.stderr, u"%s: %s" % (sys.argv[0], msg)
|
||||||
print >> sys.stderr, u"Try '%s -h' for help." % sys.argv[0]
|
print >> sys.stderr, u"Try '%s -h' for help." % sys.argv[0]
|
||||||
sys.exit(EXIT_ERROR)
|
sys.exit(EXIT_ERROR)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
global verbose
|
global verbose
|
||||||
output_format = None
|
output_format = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, input_filenames = getopt.gnu_getopt(sys.argv[1:], "hv", ["help", "text", "verbose", "xml"])
|
opts, input_filenames = getopt.gnu_getopt(
|
||||||
|
sys.argv[1:], "hv", ["help", "text", "verbose", "xml"])
|
||||||
except getopt.GetoptError, e:
|
except getopt.GetoptError, e:
|
||||||
usage_error(e.msg)
|
usage_error(e.msg)
|
||||||
for o, a in opts:
|
for o, a in opts:
|
||||||
@@ -1406,6 +1500,7 @@ def main():
|
|||||||
else:
|
else:
|
||||||
return EXIT_DIFFERENT
|
return EXIT_DIFFERENT
|
||||||
|
|
||||||
|
|
||||||
# Catch uncaught exceptions so they can produce an exit code of 2 (EXIT_ERROR),
|
# Catch uncaught exceptions so they can produce an exit code of 2 (EXIT_ERROR),
|
||||||
# not 1 like they would by default.
|
# not 1 like they would by default.
|
||||||
def excepthook(type, value, tb):
|
def excepthook(type, value, tb):
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ for x in dir(ndiff):
|
|||||||
sys.dont_write_bytecode = dont_write_bytecode
|
sys.dont_write_bytecode = dont_write_bytecode
|
||||||
del dont_write_bytecode
|
del dont_write_bytecode
|
||||||
|
|
||||||
|
|
||||||
class scan_test(unittest.TestCase):
|
class scan_test(unittest.TestCase):
|
||||||
"""Test the Scan class."""
|
"""Test the Scan class."""
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
@@ -54,7 +55,8 @@ class scan_test(unittest.TestCase):
|
|||||||
scan.load_from_file("test-scans/complex.xml")
|
scan.load_from_file("test-scans/complex.xml")
|
||||||
host = scan.hosts[0]
|
host = scan.hosts[0]
|
||||||
self.assertEqual(len(host.ports), 6)
|
self.assertEqual(len(host.ports), 6)
|
||||||
self.assertEqual(set(host.extraports.items()), set([("filtered", 95), ("open|filtered", 99)]))
|
self.assertEqual(set(host.extraports.items()),
|
||||||
|
set([("filtered", 95), ("open|filtered", 99)]))
|
||||||
|
|
||||||
def test_nmaprun(self):
|
def test_nmaprun(self):
|
||||||
"""Test that nmaprun information is recorded."""
|
"""Test that nmaprun information is recorded."""
|
||||||
@@ -94,18 +96,20 @@ class scan_test(unittest.TestCase):
|
|||||||
self.assertTrue(len(host.ports[(22, u"tcp")].script_results) > 0)
|
self.assertTrue(len(host.ports[(22, u"tcp")].script_results) > 0)
|
||||||
|
|
||||||
# This test is commented out because Nmap XML doesn't store any information
|
# This test is commented out because Nmap XML doesn't store any information
|
||||||
# about down hosts, not even the fact that they are down. Recovering the list of
|
# about down hosts, not even the fact that they are down. Recovering the list
|
||||||
# scanned hosts to infer which ones are down would involve parsing the targets
|
# of scanned hosts to infer which ones are down would involve parsing the
|
||||||
# out of the /nmaprun/@args attribute (which is non-trivial) and possibly
|
# targets out of the /nmaprun/@args attribute (which is non-trivial) and
|
||||||
# looking up their addresses.
|
# possibly looking up their addresses.
|
||||||
# def test_down_state(self):
|
# def test_down_state(self):
|
||||||
# """Test that hosts that are not marked "up" are in the "down" state."""
|
# """Test that hosts that are not marked "up" are in the "down"
|
||||||
|
# state."""
|
||||||
# scan = Scan()
|
# scan = Scan()
|
||||||
# scan.load_from_file("test-scans/down.xml")
|
# scan.load_from_file("test-scans/down.xml")
|
||||||
# self.assertTrue(len(scan.hosts) == 1)
|
# self.assertTrue(len(scan.hosts) == 1)
|
||||||
# host = scan.hosts[0]
|
# host = scan.hosts[0]
|
||||||
# self.assertTrue(host.state == "down")
|
# self.assertTrue(host.state == "down")
|
||||||
|
|
||||||
|
|
||||||
class host_test(unittest.TestCase):
|
class host_test(unittest.TestCase):
|
||||||
"""Test the Host class."""
|
"""Test the Host class."""
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
@@ -191,6 +195,7 @@ class host_test(unittest.TestCase):
|
|||||||
self.assertEqual(h.extraports.values()[0], 95)
|
self.assertEqual(h.extraports.values()[0], 95)
|
||||||
self.assertEqual(h.state, "up")
|
self.assertEqual(h.state, "up")
|
||||||
|
|
||||||
|
|
||||||
class address_test(unittest.TestCase):
|
class address_test(unittest.TestCase):
|
||||||
"""Test the Address class."""
|
"""Test the Address class."""
|
||||||
def test_ipv4_new(self):
|
def test_ipv4_new(self):
|
||||||
@@ -225,6 +230,7 @@ class address_test(unittest.TestCase):
|
|||||||
self.assertEqual(e, e)
|
self.assertEqual(e, e)
|
||||||
self.assertNotEqual(a, e)
|
self.assertNotEqual(a, e)
|
||||||
|
|
||||||
|
|
||||||
class port_test(unittest.TestCase):
|
class port_test(unittest.TestCase):
|
||||||
"""Test the Port class."""
|
"""Test the Port class."""
|
||||||
def test_spec_string(self):
|
def test_spec_string(self):
|
||||||
@@ -237,6 +243,7 @@ class port_test(unittest.TestCase):
|
|||||||
p = Port((10, "tcp"))
|
p = Port((10, "tcp"))
|
||||||
self.assertEqual(p.state_string(), u"unknown")
|
self.assertEqual(p.state_string(), u"unknown")
|
||||||
|
|
||||||
|
|
||||||
class service_test(unittest.TestCase):
|
class service_test(unittest.TestCase):
|
||||||
"""Test the Service class."""
|
"""Test the Service class."""
|
||||||
def test_compare(self):
|
def test_compare(self):
|
||||||
@@ -278,13 +285,16 @@ class service_test(unittest.TestCase):
|
|||||||
serv.product = u"FooBar"
|
serv.product = u"FooBar"
|
||||||
serv.version = u"1.2.3"
|
serv.version = u"1.2.3"
|
||||||
# Must match Nmap output.
|
# Must match Nmap output.
|
||||||
self.assertEqual(serv.version_string(), u"%s %s" % (serv.product, serv.version))
|
self.assertEqual(serv.version_string(),
|
||||||
|
u"%s %s" % (serv.product, serv.version))
|
||||||
serv.extrainfo = u"misconfigured"
|
serv.extrainfo = u"misconfigured"
|
||||||
self.assertEqual(serv.version_string(), u"%s %s (%s)" % (serv.product, serv.version, serv.extrainfo))
|
self.assertEqual(serv.version_string(),
|
||||||
|
u"%s %s (%s)" % (serv.product, serv.version, serv.extrainfo))
|
||||||
|
|
||||||
|
|
||||||
class ScanDiffSub(ScanDiff):
|
class ScanDiffSub(ScanDiff):
|
||||||
"""A subclass of ScanDiff that counts diffs for testing."""
|
"""A subclass of ScanDiff that counts diffs for testing."""
|
||||||
def __init__(self, scan_a, scan_b, f = sys.stdout):
|
def __init__(self, scan_a, scan_b, f=sys.stdout):
|
||||||
ScanDiff.__init__(self, scan_a, scan_b, f)
|
ScanDiff.__init__(self, scan_a, scan_b, f)
|
||||||
self.pre_script_result_diffs = []
|
self.pre_script_result_diffs = []
|
||||||
self.post_script_result_diffs = []
|
self.post_script_result_diffs = []
|
||||||
@@ -305,6 +315,7 @@ class ScanDiffSub(ScanDiff):
|
|||||||
def output_ending(self):
|
def output_ending(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class scan_diff_test(unittest.TestCase):
|
class scan_diff_test(unittest.TestCase):
|
||||||
"""Test the ScanDiff class."""
|
"""Test the ScanDiff class."""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -374,6 +385,7 @@ class scan_diff_test(unittest.TestCase):
|
|||||||
diff = ScanDiffSub(a, b)
|
diff = ScanDiffSub(a, b)
|
||||||
self.assertEqual(diff.host_diffs, [])
|
self.assertEqual(diff.host_diffs, [])
|
||||||
|
|
||||||
|
|
||||||
class host_diff_test(unittest.TestCase):
|
class host_diff_test(unittest.TestCase):
|
||||||
"""Test the HostDiff class."""
|
"""Test the HostDiff class."""
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
@@ -531,8 +543,8 @@ class host_diff_test(unittest.TestCase):
|
|||||||
|
|
||||||
def test_diff_is_effective(self):
|
def test_diff_is_effective(self):
|
||||||
"""Test that a host diff is effective.
|
"""Test that a host diff is effective.
|
||||||
This means that if the recommended changes are applied to the first host
|
This means that if the recommended changes are applied to the first
|
||||||
the hosts become the same."""
|
host the hosts become the same."""
|
||||||
a = Host()
|
a = Host()
|
||||||
b = Host()
|
b = Host()
|
||||||
|
|
||||||
@@ -569,6 +581,7 @@ class host_diff_test(unittest.TestCase):
|
|||||||
self.assertFalse(diff.extraports_changed)
|
self.assertFalse(diff.extraports_changed)
|
||||||
self.assertEqual(diff.cost, 0)
|
self.assertEqual(diff.cost, 0)
|
||||||
|
|
||||||
|
|
||||||
class port_diff_test(unittest.TestCase):
|
class port_diff_test(unittest.TestCase):
|
||||||
"""Test the PortDiff class."""
|
"""Test the PortDiff class."""
|
||||||
def test_equal(self):
|
def test_equal(self):
|
||||||
@@ -604,6 +617,7 @@ class port_diff_test(unittest.TestCase):
|
|||||||
self.assertEqual(PortDiff(a, diff.port_a).cost, 0)
|
self.assertEqual(PortDiff(a, diff.port_a).cost, 0)
|
||||||
self.assertEqual(PortDiff(b, diff.port_b).cost, 0)
|
self.assertEqual(PortDiff(b, diff.port_b).cost, 0)
|
||||||
|
|
||||||
|
|
||||||
class table_test(unittest.TestCase):
|
class table_test(unittest.TestCase):
|
||||||
"""Test the table class."""
|
"""Test the table class."""
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
@@ -676,6 +690,7 @@ class table_test(unittest.TestCase):
|
|||||||
t.append(("b"))
|
t.append(("b"))
|
||||||
self.assertFalse(str(t).endswith("\n"))
|
self.assertFalse(str(t).endswith("\n"))
|
||||||
|
|
||||||
|
|
||||||
class scan_diff_xml_test(unittest.TestCase):
|
class scan_diff_xml_test(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
a = Scan()
|
a = Scan()
|
||||||
@@ -692,7 +707,9 @@ class scan_diff_xml_test(unittest.TestCase):
|
|||||||
try:
|
try:
|
||||||
document = xml.dom.minidom.parseString(self.xml)
|
document = xml.dom.minidom.parseString(self.xml)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.fail(u"Parsing XML diff output caused the exception: %s" % str(e))
|
self.fail(u"Parsing XML diff output caused the exception: %s"
|
||||||
|
% str(e))
|
||||||
|
|
||||||
|
|
||||||
def scan_apply_diff(scan, diff):
|
def scan_apply_diff(scan, diff):
|
||||||
"""Apply a scan diff to the given scan."""
|
"""Apply a scan diff to the given scan."""
|
||||||
@@ -702,6 +719,7 @@ def scan_apply_diff(scan, diff):
|
|||||||
scan.hosts.append(host)
|
scan.hosts.append(host)
|
||||||
host_apply_diff(host, h_diff)
|
host_apply_diff(host, h_diff)
|
||||||
|
|
||||||
|
|
||||||
def host_apply_diff(host, diff):
|
def host_apply_diff(host, diff):
|
||||||
"""Apply a host diff to the given host."""
|
"""Apply a host diff to the given host."""
|
||||||
if diff.state_changed:
|
if diff.state_changed:
|
||||||
@@ -739,10 +757,12 @@ def host_apply_diff(host, diff):
|
|||||||
host.script_results[host.script_results.index(sr_a)] = sr_b
|
host.script_results[host.script_results.index(sr_a)] = sr_b
|
||||||
host.script_results.sort()
|
host.script_results.sort()
|
||||||
|
|
||||||
|
|
||||||
def call_quiet(args, **kwargs):
|
def call_quiet(args, **kwargs):
|
||||||
"""Run a command with subprocess.call and hide its output."""
|
"""Run a command with subprocess.call and hide its output."""
|
||||||
return subprocess.call(args, stdout = subprocess.PIPE,
|
return subprocess.call(args, stdout=subprocess.PIPE,
|
||||||
stderr = subprocess.STDOUT, env = {'PYTHONPATH': "."}, **kwargs)
|
stderr=subprocess.STDOUT, env={'PYTHONPATH': "."}, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class exit_code_test(unittest.TestCase):
|
class exit_code_test(unittest.TestCase):
|
||||||
NDIFF = "./scripts/ndiff"
|
NDIFF = "./scripts/ndiff"
|
||||||
|
|||||||
@@ -6,29 +6,34 @@ import distutils.core
|
|||||||
import distutils.cmd
|
import distutils.cmd
|
||||||
import distutils.errors
|
import distutils.errors
|
||||||
|
|
||||||
|
|
||||||
class null_command(distutils.cmd.Command):
|
class null_command(distutils.cmd.Command):
|
||||||
"""This is a dummy distutils command that does nothing. We use it to replace
|
"""This is a dummy distutils command that does nothing. We use it to
|
||||||
the install_egg_info and avoid installing a .egg-info file, because there's
|
replace the install_egg_info and avoid installing a .egg-info file, because
|
||||||
no option to disable that."""
|
there's no option to disable that."""
|
||||||
def initialize_options(self):
|
def initialize_options(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def finalize_options(self):
|
def finalize_options(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class checked_install(distutils.command.install.install):
|
class checked_install(distutils.command.install.install):
|
||||||
"""This is a wrapper around the install command that checks for an error
|
"""This is a wrapper around the install command that checks for an error
|
||||||
caused by not having the python-dev package installed. By default, distutils
|
caused by not having the python-dev package installed. By default,
|
||||||
gives a misleading error message: "invalid Python installation." """
|
distutils gives a misleading error message: "invalid Python installation."
|
||||||
|
"""
|
||||||
def finalize_options(self):
|
def finalize_options(self):
|
||||||
try:
|
try:
|
||||||
distutils.command.install.install.finalize_options(self)
|
distutils.command.install.install.finalize_options(self)
|
||||||
except distutils.errors.DistutilsPlatformError, e:
|
except distutils.errors.DistutilsPlatformError, e:
|
||||||
raise distutils.errors.DistutilsPlatformError(str(e) + "\n"
|
raise distutils.errors.DistutilsPlatformError(str(e) + """
|
||||||
+ "Installing your distribution's python-dev package may solve this problem.")
|
Installing your distribution's python-dev package may solve this problem.""")
|
||||||
|
|
||||||
distutils.core.setup(name = u"ndiff", scripts = [u"scripts/ndiff"],
|
distutils.core.setup(name=u"ndiff", scripts=[u"scripts/ndiff"],
|
||||||
py_modules = [u"ndiff"],
|
py_modules=[u"ndiff"],
|
||||||
data_files = [(u"share/man/man1", [u"docs/ndiff.1"])],
|
data_files=[(u"share/man/man1", [u"docs/ndiff.1"])],
|
||||||
cmdclass = {"install_egg_info": null_command, "install": checked_install})
|
cmdclass={"install_egg_info": null_command, "install": checked_install})
|
||||||
|
|||||||
@@ -18,20 +18,24 @@ VERBOSE = True
|
|||||||
|
|
||||||
r = random.Random()
|
r = random.Random()
|
||||||
|
|
||||||
|
|
||||||
def hash(s):
|
def hash(s):
|
||||||
digest = hashlib.sha512(s).hexdigest()
|
digest = hashlib.sha512(s).hexdigest()
|
||||||
return int(digest, 16)
|
return int(digest, 16)
|
||||||
|
|
||||||
|
|
||||||
def anonymize_mac_address(addr):
|
def anonymize_mac_address(addr):
|
||||||
r.seed(hash(addr))
|
r.seed(hash(addr))
|
||||||
nums = (0, 0, 0) + tuple(r.randrange(256) for i in range(3))
|
nums = (0, 0, 0) + tuple(r.randrange(256) for i in range(3))
|
||||||
return u":".join(u"%02X" % x for x in nums)
|
return u":".join(u"%02X" % x for x in nums)
|
||||||
|
|
||||||
|
|
||||||
def anonymize_ipv4_address(addr):
|
def anonymize_ipv4_address(addr):
|
||||||
r.seed(hash(addr))
|
r.seed(hash(addr))
|
||||||
nums = (10,) + tuple(r.randrange(256) for i in range(3))
|
nums = (10,) + tuple(r.randrange(256) for i in range(3))
|
||||||
return u".".join(unicode(x) for x in nums)
|
return u".".join(unicode(x) for x in nums)
|
||||||
|
|
||||||
|
|
||||||
def anonymize_ipv6_address(addr):
|
def anonymize_ipv6_address(addr):
|
||||||
r.seed(hash(addr))
|
r.seed(hash(addr))
|
||||||
# RFC 4193.
|
# RFC 4193.
|
||||||
@@ -43,6 +47,7 @@ def anonymize_ipv6_address(addr):
|
|||||||
hostname_map = {}
|
hostname_map = {}
|
||||||
address_map = {}
|
address_map = {}
|
||||||
|
|
||||||
|
|
||||||
def anonymize_hostname(name):
|
def anonymize_hostname(name):
|
||||||
if name in hostname_map:
|
if name in hostname_map:
|
||||||
return hostname_map[name]
|
return hostname_map[name]
|
||||||
@@ -60,6 +65,7 @@ mac_re = re.compile(r'\b([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}\b')
|
|||||||
ipv4_re = re.compile(r'\b([0-9]{1,3}\.){3}[0-9]{1,3}\b')
|
ipv4_re = re.compile(r'\b([0-9]{1,3}\.){3}[0-9]{1,3}\b')
|
||||||
ipv6_re = re.compile(r'\b([0-9a-fA-F]{1,4}::?){3,}[0-9a-fA-F]{1,4}\b')
|
ipv6_re = re.compile(r'\b([0-9a-fA-F]{1,4}::?){3,}[0-9a-fA-F]{1,4}\b')
|
||||||
|
|
||||||
|
|
||||||
def anonymize_address(addr):
|
def anonymize_address(addr):
|
||||||
if addr in address_map:
|
if addr in address_map:
|
||||||
return address_map[addr]
|
return address_map[addr]
|
||||||
@@ -75,21 +81,25 @@ def anonymize_address(addr):
|
|||||||
print >> sys.stderr, "Replace %s with %s" % (addr, address_map[addr])
|
print >> sys.stderr, "Replace %s with %s" % (addr, address_map[addr])
|
||||||
return address_map[addr]
|
return address_map[addr]
|
||||||
|
|
||||||
|
|
||||||
def repl_addr(match):
|
def repl_addr(match):
|
||||||
addr = match.group(0)
|
addr = match.group(0)
|
||||||
anon_addr = anonymize_address(addr)
|
anon_addr = anonymize_address(addr)
|
||||||
return anon_addr
|
return anon_addr
|
||||||
|
|
||||||
|
|
||||||
def repl_hostname_name(match):
|
def repl_hostname_name(match):
|
||||||
name = match.group(1)
|
name = match.group(1)
|
||||||
anon_name = anonymize_hostname(name)
|
anon_name = anonymize_hostname(name)
|
||||||
return r'<hostname name="%s"' % anon_name
|
return r'<hostname name="%s"' % anon_name
|
||||||
|
|
||||||
|
|
||||||
def repl_hostname(match):
|
def repl_hostname(match):
|
||||||
name = match.group(1)
|
name = match.group(1)
|
||||||
anon_name = anonymize_hostname(name)
|
anon_name = anonymize_hostname(name)
|
||||||
return r'hostname="%s"' % anon_name
|
return r'hostname="%s"' % anon_name
|
||||||
|
|
||||||
|
|
||||||
def anonymize_file(f):
|
def anonymize_file(f):
|
||||||
for line in f:
|
for line in f:
|
||||||
repls = []
|
repls = []
|
||||||
@@ -101,6 +111,7 @@ def anonymize_file(f):
|
|||||||
line = re.sub(r' *\bservicefp="([^"]*)"', r'', line)
|
line = re.sub(r' *\bservicefp="([^"]*)"', r'', line)
|
||||||
yield line
|
yield line
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
filename = sys.argv[1]
|
filename = sys.argv[1]
|
||||||
f = open(filename, "r")
|
f = open(filename, "r")
|
||||||
|
|||||||
Reference in New Issue
Block a user