From 9da48bf4789f7ef905b93fe132e212a4d72c003e Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sun, 22 Dec 2013 20:38:55 +0100
Subject: [PATCH 001/206] fix issue #6
---
libnmap/process.py | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/libnmap/process.py b/libnmap/process.py
index 3cd163d..1d3b44c 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -85,6 +85,8 @@ def __init__(self, targets="127.0.0.1",
self.__io_queue = Queue()
self.__ioerr_queue = Queue()
self.__process_killed = threading.Event()
+ self.__thread_stdout = None
+ self.__thread_stderr = None
# API usable in callback function
self.__state = self.READY
@@ -97,7 +99,6 @@ def __init__(self, targets="127.0.0.1",
self.__summary = ''
self.__stdout = ''
self.__stderr = ''
- self.initial_threads = 0
def _run_init(self):
"""
@@ -215,13 +216,18 @@ def stream_reader(thread_stdout, io_queue):
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0)
- self.initial_threads = threading.active_count()
- Thread(target=stream_reader, name='stdout-reader',
- args=(self.__nmap_proc.stdout,
- self.__io_queue)).start()
- Thread(target=stream_reader, name='stderr-reader',
- args=(self.__nmap_proc.stderr,
- self.__ioerr_queue)).start()
+ self.__thread_stdout = Thread(target=stream_reader,
+ name='stdout-reader',
+ args=(self.__nmap_proc.stdout,
+ self.__io_queue))
+ self.__thread_stderr = Thread(target=stream_reader,
+ name='stderr-reader',
+ args=(self.__nmap_proc.stderr,
+ self.__ioerr_queue))
+
+ self.__thread_stdout.start()
+ self.__thread_stderr.start()
+
self.__state = self.RUNNING
except OSError:
self.__state = self.FAILED
@@ -229,6 +235,10 @@ def stream_reader(thread_stdout, io_queue):
return self.__wait()
+ def active_fd(self):
+ return (self.__thread_stdout.is_alive() or
+ self.__thread_stderr.is_alive())
+
def __wait(self):
"""
Private method, called by run() which will loop and
@@ -243,8 +253,9 @@ def __wait(self):
"""
thread_stream = ''
while (self.__nmap_proc.poll() is None or
- threading.active_count() != self.initial_threads or
- not self.__io_queue.empty()):
+ self.active_fd() is True or
+ not self.__io_queue.empty() or
+ not self.__ioerr_queue.empty()):
if self.__process_killed.isSet():
break
try:
@@ -276,7 +287,6 @@ def __wait(self):
return self.rc
def run_background(self):
- self.daemon = True
super(NmapProcess, self).start()
def is_running(self):
From 8aec99d18e32c78ab57627e26dd7d6c0b513a1ce Mon Sep 17 00:00:00 2001
From: Ronald
Date: Thu, 26 Dec 2013 18:47:22 +0100
Subject: [PATCH 002/206] fix issue6
---
CHANGES.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGES.txt b/CHANGES.txt
index 943b2c0..f7ce1a1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,5 @@
+v0.4.1, 26/10/2013 -- Bug corrected: issue6
+ Infinite loop while launching several nmap scans in background
v0.4.0, 28/10/2013 -- Bug corrected in missing data from nmap scan output
Added stop() to terminate nmap scan running in background
v0.3.1, 17/06/2013 -- Refactory of objects to isolate each nmap object in a
From 4a2f9cd3e1e0481d8e3cbaba4d1dcfd34e2dd349 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Thu, 26 Dec 2013 19:18:35 +0100
Subject: [PATCH 003/206] fix issue8: set NmapProcess.summary as deprecated
(see changelog)
---
CHANGES.txt | 7 +++++++
libnmap/process.py | 4 ++++
2 files changed, 11 insertions(+)
diff --git a/CHANGES.txt b/CHANGES.txt
index f7ce1a1..4308360 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,10 @@
+v0.4.2, 26/10/2013 -- Bug corrected: issue 8
+ There is no guarantee that "finished" or "runstats" will be
+ received by event parser of process.py.
+ Summary functions are now flagged as deprecated. To use data
+ from scan summary of numbers of hosts up, the user of the
+ lib will have to use NmapParser.parse() and the appropriate
+ accessors.
v0.4.1, 26/10/2013 -- Bug corrected: issue6
Infinite loop while launching several nmap scans in background
v0.4.0, 28/10/2013 -- Bug corrected in missing data from nmap scan output
diff --git a/libnmap/process.py b/libnmap/process.py
index 1d3b44c..1773637 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -6,6 +6,7 @@
import threading
from threading import Thread
from xml.dom import pulldom
+import warnings
try:
from Queue import Queue, Empty, Full
except ImportError:
@@ -423,6 +424,7 @@ def endtime(self):
:return: string. Unix timestamp
"""
+ warnings.warn("data collected from finished events are deprecated. Use NmapParser.parse()", DeprecationWarning)
return self.__endtime
@property
@@ -432,6 +434,7 @@ def elapsed(self):
:return: string
"""
+ warnings.warn("data collected from finished events are deprecated. Use NmapParser.parse()", DeprecationWarning)
return self.__elapsed
@property
@@ -441,6 +444,7 @@ def summary(self):
:return: string
"""
+ warnings.warn("data collected from finished events are deprecated. Use NmapParser.parse()", DeprecationWarning)
return self.__summary
@property
From 22d6beb3799e6b9675d9f9758b12c513924c5c37 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Fri, 27 Dec 2013 04:22:07 +0100
Subject: [PATCH 004/206] fixed pep8 issue
---
libnmap/process.py | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/libnmap/process.py b/libnmap/process.py
index 1773637..cc0aee5 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -424,7 +424,8 @@ def endtime(self):
:return: string. Unix timestamp
"""
- warnings.warn("data collected from finished events are deprecated. Use NmapParser.parse()", DeprecationWarning)
+ warnings.warn("data collected from finished events are deprecated."
+ "Use NmapParser.parse()", DeprecationWarning)
return self.__endtime
@property
@@ -434,7 +435,8 @@ def elapsed(self):
:return: string
"""
- warnings.warn("data collected from finished events are deprecated. Use NmapParser.parse()", DeprecationWarning)
+ warnings.warn("data collected from finished events are deprecated."
+ "Use NmapParser.parse()", DeprecationWarning)
return self.__elapsed
@property
@@ -444,7 +446,8 @@ def summary(self):
:return: string
"""
- warnings.warn("data collected from finished events are deprecated. Use NmapParser.parse()", DeprecationWarning)
+ warnings.warn("data collected from finished events are deprecated."
+ "Use NmapParser.parse()", DeprecationWarning)
return self.__summary
@property
From 1241fcd9e1d15454c64fd345f73544a5801fc0c5 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 24 Feb 2014 20:56:43 +0100
Subject: [PATCH 005/206] issue #10 fix
---
libnmap/objects/host.py | 2 +-
libnmap/parser.py | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index e3a244b..04cf3d5 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -348,7 +348,7 @@ def os_ports_used(self):
"""
rval = []
try:
- rval = self._extras['ports_used']
+ rval = self._extras['os']['ports_used']
except (KeyError, TypeError):
pass
return rval
diff --git a/libnmap/parser.py b/libnmap/parser.py
index 1fad7f9..9248e34 100644
--- a/libnmap/parser.py
+++ b/libnmap/parser.py
@@ -407,7 +407,11 @@ def __parse_os_fingerprint(cls, os_data):
rdict['osmatch'] = os_match_probability
rdict['osclass'] = os_class_probability
rdict['ports_used'] = os_ports_used
- rdict['osfingerprint'] = os_fp['fingerprint']
+ if 'fingerprint' in os_fp:
+ rdict['osfingerprint'] = os_fp['fingerprint']
+ else:
+ rdict['osfingerprint'] = ''
+
return rdict
From 41e1ecf6c391c4cd1c639d6b85414cb0050e6309 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Tue, 25 Feb 2014 00:11:50 +0100
Subject: [PATCH 006/206] fix for issue9: further test with serialization
required
---
examples/json_serialize.py | 4 +--
libnmap/objects/host.py | 60 +++++++++++++++++++++++++++++++++-----
libnmap/parser.py | 7 ++---
3 files changed, 58 insertions(+), 13 deletions(-)
diff --git a/examples/json_serialize.py b/examples/json_serialize.py
index f329bc1..597dabc 100644
--- a/examples/json_serialize.py
+++ b/examples/json_serialize.py
@@ -6,8 +6,8 @@
# create a json object from an NmapReport instance
nmap_report_json = json.dumps(nmap_report_obj, cls=ReportEncoder)
-print nmap_report_json
+#print nmap_report_json
# create a NmapReport instance from a json object
nmap_report_obj = json.loads(nmap_report_json, cls=ReportDecoder)
-print nmap_report_obj
+#print nmap_report_obj
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 04cf3d5..285ce6a 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -51,8 +51,8 @@ def osclass(self, min_accuracy=90):
if int(osclass_entry['accuracy']) >= min_accuracy:
_relevantkeys = ['type', 'vendor', 'osfamily', 'osgen']
_ftstr = "|".join([vkey + ": " + osclass_entry[vkey]
- for vkey in osclass_entry
- if vkey in _relevantkeys])
+ for vkey in osclass_entry
+ if vkey in _relevantkeys])
os_array.append(_ftstr)
except (KeyError, TypeError):
pass
@@ -71,9 +71,9 @@ def __repr__(self):
_fmtstr += "OS CLASS:\r\n"
for _oscline in self.osclass():
_fmtstr += " {0}\r\n".format(_oscline)
- elif len(self.fingerprint):
+ elif len(self.fingerprint()):
_fmtstr += "OS FINGERPRINT:\r\n"
- _fmtstr += " {0}".format(self.fingerprint)
+ _fmtstr += " {0}".format(self.fingerprint())
return _fmtstr
"""
@@ -98,7 +98,6 @@ def __init__(self, starttime='', endtime='', address=None, status=None,
self._endtime = endtime
self._hostnames = hostnames if hostnames is not None else []
self._status = status if status is not None else {}
- self._address = address if address is not None else {}
self._services = services if services is not None else []
self._extras = extras if extras is not None else {}
self._osfingerprinted = False
@@ -106,6 +105,19 @@ def __init__(self, starttime='', endtime='', address=None, status=None,
self.os = self.NmapOSFingerprint(self._extras['os'])
self._osfingerprinted = True
+ self._ipv4_addr = None
+ self._ipv6_addr = None
+ self._mac_addr = None
+ for addr in address:
+ if addr['addrtype'] == "ipv4":
+ self._ipv4_addr = addr['addr']
+ elif addr['addrtype'] == 'ipv6':
+ self._ipv6_addr = addr['addr']
+ elif addr['addrtype'] == 'mac':
+ self._mac_addr = addr['addr']
+
+ self._address = self._ipv4_addr or self._ipv6_addr or ''
+
def __eq__(self, other):
"""
Compare eq NmapHost based on :
@@ -188,7 +200,7 @@ def address(self):
:return: IP address as a string
"""
- return self._address['addr']
+ return self._address
@address.setter
def address(self, addrdict):
@@ -198,7 +210,41 @@ def address(self, addrdict):
:param addrdict: valid dict is {'addr': '1.1.1.1',
'addrtype': 'ipv4'}
"""
- self._address = addrdict
+ if addrdict['addrtype'] == 'ipv4':
+ self._ipv4_addr = addrdict['addr']
+ elif addrdict['addrtype'] == 'ipv6':
+ self._ipv6_addr = addrdict['addr']
+ if addrdict['addrtype'] == 'mac':
+ self._mac_addr = addrdict['addr']
+
+ self._address = self._ipv4_addr or self._ipv6_addr or ''
+
+ @property
+ def ipv4(self):
+ """
+ Accessor for the IPv4 address of the scanned host
+
+ :return: IPv4 address as a string
+ """
+ return self._ipv4_addr or ''
+
+ @property
+ def mac(self):
+ """
+ Accessor for the MAC address of the scanned host
+
+ :return: MAC address as a string
+ """
+ return self._mac_addr or ''
+
+ @property
+ def ipv6(self):
+ """
+ Accessor for the IPv6 address of the scanned host
+
+ :return: IPv6 address as a string
+ """
+ return self._ipv6_addr or ''
@property
def status(self):
diff --git a/libnmap/parser.py b/libnmap/parser.py
index 9248e34..95c56a4 100644
--- a/libnmap/parser.py
+++ b/libnmap/parser.py
@@ -243,7 +243,7 @@ def _parse_xml_host(cls, scanhost_data):
_hostnames = []
_services = []
_status = {}
- _address = {}
+ _addresses = []
_host_extras = {}
extra_tags = ['uptime', 'distance', 'tcpsequence',
'ipidsequence', 'tcptssequence', 'times']
@@ -257,7 +257,7 @@ def _parse_xml_host(cls, scanhost_data):
elif xh.tag == 'status':
_status = cls.__format_attributes(xh)
elif xh.tag == 'address':
- _address = cls.__format_attributes(xh)
+ _addresses.append(cls.__format_attributes(xh))
elif xh.tag == 'os':
_os_extra = cls.__parse_os_fingerprint(xh)
_host_extras.update({'os': _os_extra})
@@ -274,7 +274,7 @@ def _parse_xml_host(cls, scanhost_data):
_etime = _host_header['endtime']
nhost = NmapHost(_stime,
_etime,
- _address,
+ _addresses,
_status,
_hostnames,
_services,
@@ -412,7 +412,6 @@ def __parse_os_fingerprint(cls, os_data):
else:
rdict['osfingerprint'] = ''
-
return rdict
@classmethod
From 3ee74b8cd7c0879b0ca33ba311facc16a2ab9e8b Mon Sep 17 00:00:00 2001
From: Ronald
Date: Tue, 25 Feb 2014 00:39:39 +0100
Subject: [PATCH 007/206] fix for issue9
TODO:
- review OS Fingerprint
- provide some os fingerprint code examples
- provide some nse scripts output code examples
---
examples/json_serialize.py | 4 ++--
libnmap/objects/host.py | 12 +++++++-----
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/examples/json_serialize.py b/examples/json_serialize.py
index 597dabc..f329bc1 100644
--- a/examples/json_serialize.py
+++ b/examples/json_serialize.py
@@ -6,8 +6,8 @@
# create a json object from an NmapReport instance
nmap_report_json = json.dumps(nmap_report_obj, cls=ReportEncoder)
-#print nmap_report_json
+print nmap_report_json
# create a NmapReport instance from a json object
nmap_report_obj = json.loads(nmap_report_json, cls=ReportDecoder)
-#print nmap_report_obj
+print nmap_report_obj
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 285ce6a..5be54f4 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -51,8 +51,8 @@ def osclass(self, min_accuracy=90):
if int(osclass_entry['accuracy']) >= min_accuracy:
_relevantkeys = ['type', 'vendor', 'osfamily', 'osgen']
_ftstr = "|".join([vkey + ": " + osclass_entry[vkey]
- for vkey in osclass_entry
- if vkey in _relevantkeys])
+ for vkey in osclass_entry
+ if vkey in _relevantkeys])
os_array.append(_ftstr)
except (KeyError, TypeError):
pass
@@ -116,7 +116,8 @@ def __init__(self, starttime='', endtime='', address=None, status=None,
elif addr['addrtype'] == 'mac':
self._mac_addr = addr['addr']
- self._address = self._ipv4_addr or self._ipv6_addr or ''
+ self._main_address = self._ipv4_addr or self._ipv6_addr or ''
+ self._address = address #self._ipv4_addr or self._ipv6_addr or ''
def __eq__(self, other):
"""
@@ -200,7 +201,7 @@ def address(self):
:return: IP address as a string
"""
- return self._address
+ return self._main_address
@address.setter
def address(self, addrdict):
@@ -217,7 +218,8 @@ def address(self, addrdict):
if addrdict['addrtype'] == 'mac':
self._mac_addr = addrdict['addr']
- self._address = self._ipv4_addr or self._ipv6_addr or ''
+ self._main_address = self._ipv4_addr or self._ipv6_addr or ''
+ self._address = addrdict
@property
def ipv4(self):
From 00f55eba36a97984fc208a9885f4b880ad119940 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Tue, 25 Feb 2014 00:49:04 +0100
Subject: [PATCH 008/206] fixed pep8 error/typo
---
libnmap/objects/host.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 5be54f4..9d20a41 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -117,7 +117,7 @@ def __init__(self, starttime='', endtime='', address=None, status=None,
self._mac_addr = addr['addr']
self._main_address = self._ipv4_addr or self._ipv6_addr or ''
- self._address = address #self._ipv4_addr or self._ipv6_addr or ''
+ self._address = address
def __eq__(self, other):
"""
From 0b92f980a3c151c581d50fe5877f600927bfcc7e Mon Sep 17 00:00:00 2001
From: Ronald
Date: Tue, 25 Feb 2014 09:46:18 +0100
Subject: [PATCH 009/206] fixed issue in test files
---
libnmap/test/test_report.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libnmap/test/test_report.py b/libnmap/test/test_report.py
index 7e940e7..d2f0f8f 100644
--- a/libnmap/test/test_report.py
+++ b/libnmap/test/test_report.py
@@ -167,7 +167,7 @@ def test_host_not_equal(self):
host1 = np1.hosts.pop()
host2 = np2.hosts.pop()
- host1._address['addr'] = 'xxxxxx'
+ host1.address = {'addr': '1.3.3.7', 'addrtype': 'ipv4'}
self.assertNotEqual(host1, host2)
def test_host_equal(self):
From 5d2c467a000a762ee36fd742fea57b4ac7c25281 Mon Sep 17 00:00:00 2001
From: nnam
Date: Thu, 27 Feb 2014 20:41:23 -0800
Subject: [PATCH 010/206] fixed typo in targets Exception message
---
libnmap/process.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libnmap/process.py b/libnmap/process.py
index cc0aee5..d717cef 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -67,7 +67,7 @@ def __init__(self, targets="127.0.0.1",
self.__nmap_targets = targets
else:
raise Exception("Supplied target list should be either a "
- "string of a list")
+ "string or a list")
self._nmap_options = set(options.split())
if safe_mode and not self._nmap_options.isdisjoint(unsafe_opts):
From 704117390ed808eda322aefb3b249918963502dc Mon Sep 17 00:00:00 2001
From: Ronald
Date: Fri, 14 Mar 2014 20:01:24 +0100
Subject: [PATCH 011/206] fix for issue 14. TODO: additional samples for
testing hostscript tag
---
libnmap/objects/host.py | 15 +++++++++++++++
libnmap/parser.py | 39 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 9d20a41..e4be2af 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -472,6 +472,21 @@ def distance(self):
pass
return rval
+
+ @property
+ def scripts_results(self):
+ """
+ Scripts results specific to the scanned host
+
+ :return: array of
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cpe:/a:openbsd:openssh:5.9p1cpe:/o:linux:linux_kernel
+cpe:/a:apache:http_server:2.2.22
+
+
+
+
+
+
+
+
+
diff --git a/libnmap/test/files/os_scan5.xml b/libnmap/test/files/os_scan5.xml
new file mode 100644
index 0000000..30b787a
--- /dev/null
+++ b/libnmap/test/files/os_scan5.xml
@@ -0,0 +1,864 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libnmap/test/files/os_scan6.xml b/libnmap/test/files/os_scan6.xml
new file mode 100644
index 0000000..d3c4a9a
--- /dev/null
+++ b/libnmap/test/files/os_scan6.xml
@@ -0,0 +1,878 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cpe:/o:linux:linux_kernel:2.6.13
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cpe:/o:microsoft:windows_server_2008::beta3
+
+
+cpe:/o:microsoft:windows_7::-:professional
+
+
+cpe:/o:microsoft:windows
+
+
+cpe:/o:microsoft:windows_vista::-cpe:/o:microsoft:windows_vista::sp1
+cpe:/o:microsoft:windows_server_2008::sp1
+cpe:/o:microsoft:windows_7
+
+
+cpe:/o:microsoft:windows_vista::sp2
+cpe:/o:microsoft:windows_7::sp1
+cpe:/o:microsoft:windows_server_2008
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cpe:/o:apple:mac_os_x:10.8
+
+
+cpe:/o:apple:mac_os_x:10.8
+cpe:/o:apple:iphone_os:5
+cpe:/o:apple:iphone_os:5
+
+
+
+
+
+
+
+
+
+
+
+
+
From a3631cb4ed0087c0e66bd485419ff8e960ed932d Mon Sep 17 00:00:00 2001
From: Ronald B
Date: Fri, 9 May 2014 13:48:52 +0200
Subject: [PATCH 037/206] added OSFPPortUsed and fixed bug in old xml parsing
support
---
libnmap/objects/host.py | 26 +++++++-----------
libnmap/objects/os.py | 60 +++++++++++++++++++++++++++++++++++------
2 files changed, 61 insertions(+), 25 deletions(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 3418765..d321efc 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -2,6 +2,7 @@
from libnmap.diff import NmapDiff
from libnmap.objects.os import NmapOSFingerprint
+
class NmapHost(object):
"""
NmapHost is a class representing a host object of NmapReport
@@ -28,6 +29,7 @@ def __init__(self, starttime='', endtime='', address=None, status=None,
self._services = services if services is not None else []
self._extras = extras if extras is not None else {}
self._osfingerprinted = False
+ self.os = None
if 'os' in self._extras:
self.os = NmapOSFingerprint(self._extras['os'])
self._osfingerprinted = True
@@ -263,16 +265,11 @@ def os_class_probabilities(self):
Returns an array of possible OS class detected during
the OS fingerprinting.
- Example [{'accuracy': '96', 'osfamily': 'embedded',
- 'type': 'WAP', 'vendor': 'Netgear'}, {...}]
-
- :return: dict describing the OS class detected and the accuracy
+ :return: Array of NmapOSClass objects
"""
rval = []
- try:
- rval = self._extras['os']['osclass']
- except (KeyError, TypeError):
- pass
+ if self.os is not None:
+ rval = self.os.osclasses
return rval
def os_match_probabilities(self):
@@ -280,14 +277,11 @@ def os_match_probabilities(self):
Returns an array of possible OS match detected during
the OS fingerprinting
- :return: dict describing the OS version detected and the accuracy
+ :return: array of NmapOSMatches objects
"""
-
rval = []
- try:
- rval = self._extras['os']['osmatch']
- except (KeyError, TypeError):
- pass
+ if self.os is not None:
+ rval = self.os.osmatches
return rval
@property
@@ -307,10 +301,8 @@ def os_fingerprint(self):
:return: string
"""
rval = ''
- try:
+ if self.os is not None:
rval = self.os.fingerprints.join("\n")
- except (KeyError, TypeError):
- pass
return rval
def os_ports_used(self):
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index 751082d..32db210 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -23,6 +23,42 @@ def __repr__(self):
return self._cpestring
+class OSFPPortUsed(object):
+ """
+ Port used class: this enables the user of NmapOSFingerprint class
+ to have a common and clear interface to access portused data which
+ were collected and used during os fingerprint scan
+ """
+ def __init__(self, port_used_dict):
+ try:
+ self._state = port_used_dict['state']
+ self._proto = port_used_dict['proto']
+ self._portid = port_used_dict['portid']
+ except KeyError:
+ raise Exception("Cannot create OSFPPortUsed: missing required key")
+
+ @property
+ def state(self):
+ """
+ Accessor for the portused state (closed, open,...)
+ """
+ return self._state
+
+ @property
+ def proto(self):
+ """
+ Accessor for the portused protocol (tcp, udp,...)
+ """
+ return self._proto
+
+ @property
+ def portid(self):
+ """
+ Accessor for the referenced port number used
+ """
+ return self._portid
+
+
class NmapOSMatch(object):
"""
NmapOSMatch is an internal class used for offering results
@@ -65,17 +101,14 @@ def __init__(self, osmatch_dict):
except KeyError:
pass
- def add_osclass(self, class_dict):
+ def add_osclass(self, osclass_obj):
"""
Add a NmapOSClass object to the OSMatch object. This method is
useful to implement compatibility with older versions of NMAP
by providing a common interface to access os fingerprint data.
"""
- if 'osclass' in class_dict:
- self.__osclasses.append(class_dict)
- else:
- raise Exception("Cannot add: no osclass data in provided dict")
+ self._osclasses.append(osclass_obj)
@property
def osclasses(self):
@@ -243,9 +276,11 @@ def __init__(self, osfp_data):
if 'fingerprint' in _osfp:
self.__fingerprints.append(_osfp['fingerprint'])
if 'ports_used' in osfp_data:
- self.__ports_used = osfp_data['ports_used']
+ for _pused_dict in osfp_data['ports_used']:
+ _pused = OSFPPortUsed(_pused_dict)
+ self.__ports_used.append(_pused)
- def get_osmatch(self, accuracy):
+ def get_osmatch(self, osclass_obj):
"""
This function enables NmapOSFingerprint to determine if an
NmapOSClass object could be attached to an existing NmapOSMatch
@@ -257,7 +292,7 @@ def get_osmatch(self, accuracy):
"""
rval = None
for _osmatch in self.__osmatches:
- if _osmatch.accuracy == accuracy:
+ if _osmatch.accuracy == osclass_obj.accuracy:
rval = _osmatch
break # sorry
return rval
@@ -296,6 +331,15 @@ def fingerprint(self):
def fingerprints(self):
return self.__fingerprints
+ @property
+ def ports_used(self):
+ """
+ Return an array of OSFPPortUsed object with the ports used to
+ perform the os fingerprint. This dict might contain another dict
+ embedded containing the ports_reason values.
+ """
+ return self.__ports_used
+
def osmatch(self, min_accuracy=90):
warnings.warn("NmapOSFingerprint.osmatch is deprecated: "
"use NmapOSFingerprint.osmatches", DeprecationWarning)
From 77b91ede963d189817e2524ab424ffe5e6fd4ca7 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sun, 11 May 2014 21:56:38 +0200
Subject: [PATCH 038/206] fix issue11, 26, 28: Changes in OS fingerprint data
API - NmapHost now holds its OS fingerprint data in
NmapHost.os (NmapOSFingerpring object)
- fingerprint is now a property which means you have to call
it without () NmapHost.os.fingerprint and should be called
directly from NmapHost.os -
NmapHost.os.fingerprints return an array of os
fingerprints (strings) - NmapHost.os.fingerprint return a
concatenated string of all fingerprints
- Fingerprints data are now accessible via
NmapHost.os.osmatches which returns a list of NmapOSMatch
objects - NmapOSMatch objects might contain a list of
NmapOSClass objects matching with it
- NmapOSClass objects might contain a list of CPE object
related to the os class (CPE class will be improved and
API enriched) - TODO: finalize API doc and create all
related unit tests
---
CHANGES.txt | 2 +-
libnmap/objects/host.py | 2 +
libnmap/objects/os.py | 28 ++++++------
libnmap/parser.py | 1 -
libnmap/test/test_fp.py | 92 ++++++++++++++++++++++++++++++++++++++-
libnmap/test/test_osfp.py | 26 +----------
6 files changed, 109 insertions(+), 42 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 99d3cc4..b11b470 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -16,7 +16,7 @@ v0.4.8, 05/05/2014 -- Changes in OS fingerprint data API
- NmapOSClass objects might contain a list of CPE object
related to the os class (CPE class will be improved and
API enriched)
- - TODO: finalize API and create all related unit tests
+ - TODO: finalize API doc and create all related unit tests
v0.4.7, 03/05/2014 -- minor fix for issue25
- fixed exception when optional service tag is not present
in tag
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index d321efc..084241a 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -33,6 +33,8 @@ def __init__(self, starttime='', endtime='', address=None, status=None,
if 'os' in self._extras:
self.os = NmapOSFingerprint(self._extras['os'])
self._osfingerprinted = True
+ else:
+ self.os = NmapOSFingerprint({})
self._ipv4_addr = None
self._ipv6_addr = None
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index 32db210..d634895 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -19,8 +19,8 @@ def cpestring(self):
"""
return self._cpestring
- def __repr__(self):
- return self._cpestring
+# def __repr__(self):
+# return self._cpestring
class OSFPPortUsed(object):
@@ -144,11 +144,11 @@ def accuracy(self):
"""
return int(self._accuracy)
- def __repr__(self):
- rval = "{0}: {1}".format(self.name, self.accuracy)
- for _osclass in self._osclasses:
- rval += "\r\n |__ os class: {0}".format(str(_osclass))
- return rval
+# def __repr__(self):
+# rval = "{0}: {1}".format(self.name, self.accuracy)
+# for _osclass in self._osclasses:
+# rval += "\r\n |__ os class: {0}".format(str(_osclass))
+# return rval
class NmapOSClass(object):
@@ -239,13 +239,13 @@ def type(self):
"""
return self._type
- def __repr__(self):
- rval = "{0}: {1}, {2}".format(self.type, self.vendor, self.osfamily)
- if len(self.osgen):
- rval += "({0})".format(self.osgen)
- for _cpe in self._cpelist:
- rval += "\r\n |__ {0}".format(str(_cpe))
- return rval
+# def __repr__(self):
+# rval = "{0}: {1}, {2}".format(self.type, self.vendor, self.osfamily)
+# if len(self.osgen):
+# rval += "({0})".format(self.osgen)
+# for _cpe in self._cpelist:
+# rval += "\r\n |__ {0}".format(str(_cpe))
+# return rval
class NmapOSFingerprint(object):
diff --git a/libnmap/parser.py b/libnmap/parser.py
index 4b3e17c..a7d9712 100644
--- a/libnmap/parser.py
+++ b/libnmap/parser.py
@@ -513,7 +513,6 @@ def __parse_os_fingerprint(cls, os_data):
elif xos.tag == 'osmatch':
os_match_proba = cls.__parse_osmatch(xos)
os_match_probability.append(os_match_proba)
- print os_match_proba
elif xos.tag == 'portused':
os_portused = cls.__format_attributes(xos)
os_ports_used.append(os_portused)
diff --git a/libnmap/test/test_fp.py b/libnmap/test/test_fp.py
index 18b292d..1167e01 100644
--- a/libnmap/test/test_fp.py
+++ b/libnmap/test/test_fp.py
@@ -14,6 +14,8 @@ def setUp(self):
{ 'file': "%s/%s" % (fdir, 'files/1_hosts_banner.xml'), 'os': 0},
{ 'file': "%s/%s" % (fdir, 'files/1_hosts_down.xml'), 'os': 0}]
self.flist = self.flist_full
+ self.flist_os = {'nv6': {'file': "%s/%s" % (fdir, 'files/full_sudo6.xml'), 'os': 0},
+ 'nv5': { 'file': "%s/%s" % (fdir, 'files/os_scan5.xml'), 'os': 0}}
def test_fp(self):
for file_e in self.flist_full:
@@ -26,7 +28,95 @@ def test_fp(self):
else:
raise Exception
+ def test_osclasses_new(self):
+ oclines = [[[{'type': 'general purpose', 'accuracy': 100, 'vendor': 'Apple', 'osfamily': 'Mac OS X', 'osgen': '10.8.X'},
+ {'type': 'phone', 'accuracy': 100, 'vendor': 'Apple', 'osfamily': 'iOS', 'osgen': '5.X'},
+ {'type': 'media device', 'accuracy': 100, 'vendor': 'Apple', 'osfamily': 'iOS', 'osgen': '5.X'}]],
+ [
+ [{'type': 'general purpose', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': '2008'}],
+ [{'type': 'general purpose', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': '7'}],
+ [{'type': 'phone', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': 'Phone'}],
+ [{'type': 'general purpose', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': 'Vista'},
+ {'type': 'general purpose', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': '2008'},
+ {'type': 'general purpose', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': '7'}],
+ [{'type': 'general purpose', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': 'Vista'},
+ {'type': 'general purpose', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': '7'},
+ {'type': 'general purpose', 'accuracy': 100, 'vendor': 'Microsoft', 'osfamily': 'Windows', 'osgen': '2008'}]]
+ ]
+ rep = NmapParser.parse_fromfile(self.flist_os['nv6']['file'])
+ hlist = []
+ hlist.append(rep.hosts.pop())
+ hlist.append(rep.hosts.pop())
+ i=0
+ j=0
+ k=0
+ for h in hlist:
+ for om in h.os.osmatches:
+ for oc in om.osclasses:
+ tdict = {'type': oc.type, 'accuracy': oc.accuracy, 'vendor': oc.vendor, 'osfamily': oc.osfamily, 'osgen': oc.osgen}
+ self.assertEqual(oclines[i][j][k], tdict)
+ k+=1
+ j+=1
+ k=0
+ j=0
+ i+=1
+
+ def test_osmatches_new(self):
+ rep = NmapParser.parse_fromfile(self.flist_os['nv6']['file'])
+ hlist = []
+ hlist.append(rep.hosts.pop())
+ hlist.append(rep.hosts.pop())
+
+ baseline = [[{'line': 6014, 'accuracy': 100, 'name': 'Apple Mac OS X 10.8 - 10.8.1 (Mountain Lion) (Darwin 12.0.0 - 12.1.0) or iOS 5.0.1'}],
+ [{'line': 52037, 'accuracy': 100, 'name': 'Microsoft Windows Server 2008 Beta 3'},
+ {'line': 52938, 'accuracy': 100, 'name': 'Microsoft Windows 7 Professional'},
+ {'line': 54362, 'accuracy': 100, 'name': 'Microsoft Windows Phone 7.5'},
+ {'line': 54897, 'accuracy': 100, 'name': 'Microsoft Windows Vista SP0 or SP1, Windows Server 2008 SP1, or Windows 7'},
+ {'line': 55210, 'accuracy': 100, 'name': 'Microsoft Windows Vista SP2, Windows 7 SP1, or Windows Server 2008'}]
+ ]
+ i=0
+ j=0
+ for h in hlist:
+ for om in h.os.osmatches:
+ tdict = {'line': om.line, 'accuracy': om.accuracy, 'name': om.name}
+ self.assertEqual(baseline[i][j], tdict)
+ j+=1
+ j=0
+ i+=1
+
+ def test_osmatches_old(self):
+ rep = NmapParser.parse_fromfile(self.flist_os['nv5']['file'])
+ h1 = rep.hosts[4]
+ h1osmatches = [{'line': -1, 'accuracy': 95, 'name': 'general purpose:Linux:Linux'},
+ {'line': -1, 'accuracy': 90, 'name': 'WAP:Gemtek:embedded'},
+ {'line': -1, 'accuracy': 89, 'name': 'general purpose:Nokia:Linux'},
+ {'line': -1, 'accuracy': 88, 'name': 'webcam:AXIS:Linux'}]
+
+ j=0
+ for om in h1.os.osmatches:
+ tdict = {'line': om.line, 'accuracy': om.accuracy, 'name': om.name}
+ self.assertEqual(h1osmatches[j], tdict)
+ j+=1
+
+ def test_fpv6(self):
+ fpval = "OS:SCAN(V=6.40-2%E=4%D=5/9%OT=88%CT=%CU=%PV=Y%DS=0%DC=L%G=N%TM=536BFF2F%P=x\nOS:86_64-apple-darwin10.8.0)SEQ(SP=F9%GCD=1%ISR=103%TI=RD%TS=A)OPS(O1=M3FD8\nOS:NW4NNT11SLL%O2=M3FD8NW4NNT11SLL%O3=M3FD8NW4NNT11%O4=M3FD8NW4NNT11SLL%O5=\nOS:M3FD8NW4NNT11SLL%O6=M3FD8NNT11SLL)WIN(W1=FFFF%W2=FFFF%W3=FFFF%W4=FFFF%W5\nOS:=FFFF%W6=FFFF)ECN(R=Y%DF=Y%TG=40%W=FFFF%O=M3FD8NW4SLL%CC=N%Q=)T1(R=Y%DF=\nOS:Y%TG=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%TG=40%W=0%S=A%A=\nOS:Z%F=R%O=%RD=0%Q=)U1(R=N)IE(R=N)\n"
+ fparray = ['OS:SCAN(V=6.40-2%E=4%D=5/9%OT=88%CT=%CU=%PV=Y%DS=0%DC=L%G=N%TM=536BFF2F%P=x\nOS:86_64-apple-darwin10.8.0)SEQ(SP=F9%GCD=1%ISR=103%TI=RD%TS=A)OPS(O1=M3FD8\nOS:NW4NNT11SLL%O2=M3FD8NW4NNT11SLL%O3=M3FD8NW4NNT11%O4=M3FD8NW4NNT11SLL%O5=\nOS:M3FD8NW4NNT11SLL%O6=M3FD8NNT11SLL)WIN(W1=FFFF%W2=FFFF%W3=FFFF%W4=FFFF%W5\nOS:=FFFF%W6=FFFF)ECN(R=Y%DF=Y%TG=40%W=FFFF%O=M3FD8NW4SLL%CC=N%Q=)T1(R=Y%DF=\nOS:Y%TG=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%TG=40%W=0%S=A%A=\nOS:Z%F=R%O=%RD=0%Q=)U1(R=N)IE(R=N)\n']
+ rep = NmapParser.parse_fromfile(self.flist_os['nv6']['file'])
+ h1 = rep.hosts.pop()
+ self.assertEqual(h1.os.fingerprint, fpval)
+ self.assertEqual(h1.os.fingerprints, fparray)
+
+ def test_fpv5(self):
+ fpval = 'OS:SCAN(V=5.21%D=5/8%OT=22%CT=1%CU=37884%PV=Y%DS=0%DC=L%G=Y%TM=536BFE32%P=x\nOS:86_64-unknown-linux-gnu)SEQ(SP=100%GCD=1%ISR=106%TI=Z%CI=Z%II=I%TS=8)SEQ\nOS:(SP=101%GCD=1%ISR=107%TI=Z%CI=Z%II=I%TS=8)OPS(O1=M400CST11NW3%O2=M400CST\nOS:11NW3%O3=M400CNNT11NW3%O4=M400CST11NW3%O5=M400CST11NW3%O6=M400CST11)WIN(\nOS:W1=8000%W2=8000%W3=8000%W4=8000%W5=8000%W6=8000)ECN(R=Y%DF=Y%T=40%W=8018\nOS:%O=M400CNNSNW3%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(\nOS:R=Y%DF=Y%T=40%W=8000%S=O%A=S+%F=AS%O=M400CST11NW3%RD=0%Q=)T4(R=Y%DF=Y%T=\nOS:40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0\nOS:%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z\nOS:%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G\nOS:%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)\n'
+ fparray = ['OS:SCAN(V=5.21%D=5/8%OT=22%CT=1%CU=37884%PV=Y%DS=0%DC=L%G=Y%TM=536BFE32%P=x\nOS:86_64-unknown-linux-gnu)SEQ(SP=100%GCD=1%ISR=106%TI=Z%CI=Z%II=I%TS=8)SEQ\nOS:(SP=101%GCD=1%ISR=107%TI=Z%CI=Z%II=I%TS=8)OPS(O1=M400CST11NW3%O2=M400CST\nOS:11NW3%O3=M400CNNT11NW3%O4=M400CST11NW3%O5=M400CST11NW3%O6=M400CST11)WIN(\nOS:W1=8000%W2=8000%W3=8000%W4=8000%W5=8000%W6=8000)ECN(R=Y%DF=Y%T=40%W=8018\nOS:%O=M400CNNSNW3%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(\nOS:R=Y%DF=Y%T=40%W=8000%S=O%A=S+%F=AS%O=M400CST11NW3%RD=0%Q=)T4(R=Y%DF=Y%T=\nOS:40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0\nOS:%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z\nOS:%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G\nOS:%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)\n']
+ rep = NmapParser.parse_fromfile(self.flist_os['nv5']['file'])
+ h1 = rep.hosts[4]
+ self.assertEqual(h1.os.fingerprint, fpval)
+ self.assertEqual(h1.os.fingerprints, fparray)
+
+
if __name__ == '__main__':
- test_suite = ['test_fp']
+ test_suite = ['test_fp', 'test_fpv6', 'test_osmatches_new', 'test_osclasses_new',
+ 'test_fpv5', 'test_osmatches_old']
suite = unittest.TestSuite(map(TestNmapFP, test_suite))
test_result = unittest.TextTestRunner(verbosity=2).run(suite)
diff --git a/libnmap/test/test_osfp.py b/libnmap/test/test_osfp.py
index 802ddf9..f916213 100644
--- a/libnmap/test/test_osfp.py
+++ b/libnmap/test/test_osfp.py
@@ -3,34 +3,10 @@
import unittest
from libnmap.parser import NmapParser
-osmatch_v2 = """
-
-
-
-
- cpe:/o:microsoft:windows_7::-
- cpe:/o:microsoft:windows_7::sp1
-
-
-
-"""
-
-osmatch_buggy1 = """
-
-
-
- cpe:/o:microsoft:windows_7::-
- cpe:/o:microsoft:windows_7::sp1
-
-
-
-"""
-
-
class TestNmapService(unittest.TestCase):
# def setUp(self):
def test_osmatch(self):
- myservice = NmapParser.parse(osmatch_v2)
+ myservice = NmapParser.parse_fromfile(osmatch_v2)
myosmatch = myservice.os.osmatch[0]
self.assetEqual(osmatch.accuracy, 100)
sname = "Microsoft Windows 7 SP0 - SP1, Windows Server 2008 SP1, or Windows 8"
From d7b57a95fdca629b72eaf266750c3826c63b15ab Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sun, 11 May 2014 22:04:02 +0200
Subject: [PATCH 039/206] fixed pep on test error and enabled __repr__
---
libnmap/objects/os.py | 28 ++++++++++++++--------------
libnmap/test/test_osfp.py | 23 -----------------------
2 files changed, 14 insertions(+), 37 deletions(-)
delete mode 100644 libnmap/test/test_osfp.py
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index d634895..32db210 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -19,8 +19,8 @@ def cpestring(self):
"""
return self._cpestring
-# def __repr__(self):
-# return self._cpestring
+ def __repr__(self):
+ return self._cpestring
class OSFPPortUsed(object):
@@ -144,11 +144,11 @@ def accuracy(self):
"""
return int(self._accuracy)
-# def __repr__(self):
-# rval = "{0}: {1}".format(self.name, self.accuracy)
-# for _osclass in self._osclasses:
-# rval += "\r\n |__ os class: {0}".format(str(_osclass))
-# return rval
+ def __repr__(self):
+ rval = "{0}: {1}".format(self.name, self.accuracy)
+ for _osclass in self._osclasses:
+ rval += "\r\n |__ os class: {0}".format(str(_osclass))
+ return rval
class NmapOSClass(object):
@@ -239,13 +239,13 @@ def type(self):
"""
return self._type
-# def __repr__(self):
-# rval = "{0}: {1}, {2}".format(self.type, self.vendor, self.osfamily)
-# if len(self.osgen):
-# rval += "({0})".format(self.osgen)
-# for _cpe in self._cpelist:
-# rval += "\r\n |__ {0}".format(str(_cpe))
-# return rval
+ def __repr__(self):
+ rval = "{0}: {1}, {2}".format(self.type, self.vendor, self.osfamily)
+ if len(self.osgen):
+ rval += "({0})".format(self.osgen)
+ for _cpe in self._cpelist:
+ rval += "\r\n |__ {0}".format(str(_cpe))
+ return rval
class NmapOSFingerprint(object):
diff --git a/libnmap/test/test_osfp.py b/libnmap/test/test_osfp.py
deleted file mode 100644
index f916213..0000000
--- a/libnmap/test/test_osfp.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-from libnmap.parser import NmapParser
-
-class TestNmapService(unittest.TestCase):
-# def setUp(self):
- def test_osmatch(self):
- myservice = NmapParser.parse_fromfile(osmatch_v2)
- myosmatch = myservice.os.osmatch[0]
- self.assetEqual(osmatch.accuracy, 100)
- sname = "Microsoft Windows 7 SP0 - SP1, Windows Server 2008 SP1, or Windows 8"
- self.assetEqual(myosmatch.name, sname)
- self.assetEqual(myosmatch.line, 53077)
- osclass_dict = {
- 'type': 'general purpose'
- 'vendor': 'Microsoft',
- 'osfamily': 'Windows',
- 'osgen': '7',
- 'accuracy': '100'
- }
- self.assetEqual(myosmatch.osclasses, [osclass_dict])
- self.assertRaises(NmapParserException, NmapParser.parse, osmatch_buggy1)
From 9ac2885821bdea5dd075847c0605b39df09bd0fe Mon Sep 17 00:00:00 2001
From: Ronald B
Date: Mon, 12 May 2014 16:17:15 +0200
Subject: [PATCH 040/206] fixed serialization issue
---
libnmap/parser.py | 1 +
libnmap/reportjson.py | 7 ++++++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/libnmap/parser.py b/libnmap/parser.py
index a7d9712..4f0eca7 100644
--- a/libnmap/parser.py
+++ b/libnmap/parser.py
@@ -225,6 +225,7 @@ def parse_fromdict(cls, rdict):
slist.append(NmapService(portid=s[cname]['_portid'],
protocol=s[cname]['_protocol'],
state=s[cname]['_state'],
+ owner=s[cname]['_owner'],
service=s[cname]['_service']))
nh = NmapHost(starttime=h['__NmapHost__']['_starttime'],
diff --git a/libnmap/reportjson.py b/libnmap/reportjson.py
index 0dbbe4e..92f5b1e 100644
--- a/libnmap/reportjson.py
+++ b/libnmap/reportjson.py
@@ -1,13 +1,18 @@
#!/usr/bin/env python
import json
from libnmap.objects import NmapHost, NmapService, NmapReport
+from libnmap.objects.os import *
from libnmap.parser import NmapParser
class ReportEncoder(json.JSONEncoder):
def default(self, obj):
otype = {'NmapHost': NmapHost,
- 'NmapOSFingerprint': NmapHost.NmapOSFingerprint,
+ 'NmapOSFingerprint': NmapOSFingerprint,
+ 'NmapOSMatch': NmapOSMatch,
+ 'NmapOSClass': NmapOSClass,
+ 'CPE': CPE,
+ 'OSFPPortUsed': OSFPPortUsed,
'NmapService': NmapService,
'NmapReport': NmapReport}
if isinstance(obj, tuple(otype.values())):
From 95c5ea5d1b4b805164a1979321dba6399a44dd88 Mon Sep 17 00:00:00 2001
From: Ronald B
Date: Mon, 12 May 2014 16:28:30 +0200
Subject: [PATCH 041/206] fixed serialization issue: pep8 issue
---
libnmap/reportjson.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libnmap/reportjson.py b/libnmap/reportjson.py
index 92f5b1e..c559983 100644
--- a/libnmap/reportjson.py
+++ b/libnmap/reportjson.py
@@ -1,7 +1,8 @@
#!/usr/bin/env python
import json
from libnmap.objects import NmapHost, NmapService, NmapReport
-from libnmap.objects.os import *
+from libnmap.objects.os import NmapOSFingerprint, NmapOSMatch, NmapOSClass
+from libnmap.objects.os import CPE, OSFPPortUsed
from libnmap.parser import NmapParser
From a9d6c54c5152bfd58efaead1e2d6f614fb1e4dd4 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 12 May 2014 19:24:46 +0200
Subject: [PATCH 042/206] added missing test file
---
libnmap/test/files/full_sudo6.xml | 1010 +++++++++++++++++++++++++++++
1 file changed, 1010 insertions(+)
create mode 100644 libnmap/test/files/full_sudo6.xml
diff --git a/libnmap/test/files/full_sudo6.xml b/libnmap/test/files/full_sudo6.xml
new file mode 100644
index 0000000..fd461c0
--- /dev/null
+++ b/libnmap/test/files/full_sudo6.xml
@@ -0,0 +1,1010 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cpe:/o:linux:linux_kernel:2.6.13
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cpe:/o:microsoft:windows
+cpe:/o:microsoft:windows
+
+
+
+cpe:/o:microsoft:windows_server_2008::beta3
+
+
+cpe:/o:microsoft:windows_7::-:professional
+
+
+cpe:/o:microsoft:windows
+
+
+cpe:/o:microsoft:windows_vista::-cpe:/o:microsoft:windows_vista::sp1
+cpe:/o:microsoft:windows_server_2008::sp1
+cpe:/o:microsoft:windows_7
+
+
+cpe:/o:microsoft:windows_vista::sp2
+cpe:/o:microsoft:windows_7::sp1
+cpe:/o:microsoft:windows_server_2008
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+cpe:/a:heimdal:kerberos
+cpe:/o:microsoft:windows
+cpe:/o:apple:mac_os_x
+
+
+
+cpe:/o:apple:mac_os_x:10.8
+cpe:/o:apple:iphone_os:5
+cpe:/o:apple:iphone_os:5
+
+
+
+
+
+
+
+
+
+
+
+
+
From a232762583d64a835632bee371031c7fdc557f78 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Tue, 13 May 2014 18:59:44 +0200
Subject: [PATCH 043/206] fixed delay issue. todo: full blown testing and merge
---
examples/nmap_task.py | 12 ++++++------
libnmap/process.py | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/examples/nmap_task.py b/examples/nmap_task.py
index f3cd419..ef29cf8 100644
--- a/examples/nmap_task.py
+++ b/examples/nmap_task.py
@@ -3,17 +3,17 @@
from libnmap.process import NmapProcess
from time import sleep
-
-nmap_proc = NmapProcess(targets="scanme.nmap.org", options="-sV")
-nmap_proc.run_background()
-while nmap_proc.is_alive():
+def mycallback(nmaptask):
nmaptask = nmap_proc.current_task
if nmaptask:
print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
nmaptask.status,
nmaptask.etc,
nmaptask.progress)
- sleep(2)
-print "rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary)
+nmap_proc = NmapProcess(targets="scanme.nmap.org",
+ options="-sV",
+ event_callback=mycallback)
+nmap_proc.run()
print nmap_proc.stdout
+print nmap_proc.stderr
diff --git a/libnmap/process.py b/libnmap/process.py
index b458f29..7d68401 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -282,7 +282,7 @@ def ioreader_routine(proc_stdout, io_queue, data_pushed, producing):
while(self.__nmap_proc.poll() is None or producing.value == 1):
if self.__process_killed.is_set():
break
- if producing.value == 1:
+ if producing.value == 1 and qout.empty():
try:
data_pushed.wait()
except KeyboardInterrupt:
From 1042db15d95de43243b7bd75976f96043bb60194 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Wed, 14 May 2014 19:18:47 +0200
Subject: [PATCH 044/206] fixed issue #28
---
libnmap/objects/service.py | 15 ++++++++++++++-
libnmap/parser.py | 16 +++++++++++++++-
libnmap/test/test_fp.py | 11 ++++++++++-
3 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/libnmap/objects/service.py b/libnmap/objects/service.py
index 95efb1a..af70f4d 100644
--- a/libnmap/objects/service.py
+++ b/libnmap/objects/service.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
from libnmap.diff import NmapDiff
+from libnmap.objects.os import CPE
class NmapService(object):
@@ -37,6 +38,11 @@ def __init__(self, portid, protocol='tcp', state=None,
self._state = state if state is not None else {}
self._service = service if service is not None else {}
+ self._cpelist = []
+ for _cpe in service['cpelist']:
+ _cpeobj = CPE(_cpe)
+ self._cpelist.append(_cpeobj)
+
self._owner = ''
if owner is not None and 'name' in owner:
self._owner = owner['name']
@@ -199,7 +205,7 @@ def banner(self):
:return: string
"""
- notrelevant = ['name', 'method', 'conf']
+ notrelevant = ['name', 'method', 'conf', 'cpelist']
b = ''
if 'method' in self._service and self._service['method'] == "probed":
b = " ".join([k + ": " + self._service[k]
@@ -207,6 +213,13 @@ def banner(self):
if k not in notrelevant])
return b
+ @property
+ def cpelist(self):
+ """
+ Accessor for list of CPE for this particular service
+ """
+ return self._cpelist
+
@property
def scripts_results(self):
"""
diff --git a/libnmap/parser.py b/libnmap/parser.py
index 4f0eca7..6142cc5 100644
--- a/libnmap/parser.py
+++ b/libnmap/parser.py
@@ -394,7 +394,7 @@ def _parse_xml_port(cls, scanport_data):
if xport.tag == 'state':
_state = cls.__format_attributes(xport)
elif xport.tag == 'service':
- _service = cls.__format_attributes(xport)
+ _service = cls.__parse_service(xport)
elif xport.tag == 'owner':
_owner = cls.__format_attributes(xport)
elif xport.tag == 'script':
@@ -415,6 +415,20 @@ def _parse_xml_port(cls, scanport_data):
_service_extras)
return nport
+ @classmethod
+ def __parse_service(cls, xserv):
+ """
+ Parse tag to manage CPE object
+ """
+ _service = cls.__format_attributes(xserv)
+ _cpelist = []
+ for _servnode in xserv:
+ if _servnode.tag == 'cpe':
+ _cpe_string = _servnode.text
+ _cpelist.append(_cpe_string)
+ _service['cpelist'] = _cpelist
+ return _service
+
@classmethod
def __parse_extraports(cls, extraports_data):
"""
diff --git a/libnmap/test/test_fp.py b/libnmap/test/test_fp.py
index 1167e01..3941c18 100644
--- a/libnmap/test/test_fp.py
+++ b/libnmap/test/test_fp.py
@@ -15,6 +15,7 @@ def setUp(self):
{ 'file': "%s/%s" % (fdir, 'files/1_hosts_down.xml'), 'os': 0}]
self.flist = self.flist_full
self.flist_os = {'nv6': {'file': "%s/%s" % (fdir, 'files/full_sudo6.xml'), 'os': 0},
+ 'fullscan': { 'file': "%s/%s" % (fdir, 'files/fullscan.xml'), 'os': 0},
'nv5': { 'file': "%s/%s" % (fdir, 'files/os_scan5.xml'), 'os': 0}}
def test_fp(self):
@@ -114,9 +115,17 @@ def test_fpv5(self):
self.assertEqual(h1.os.fingerprint, fpval)
self.assertEqual(h1.os.fingerprints, fparray)
+ def test_cpeservice(self):
+ cpelist = ['cpe:/a:openbsd:openssh:5.9p1','cpe:/o:linux:linux_kernel']
+ rep = NmapParser.parse_fromfile(self.flist_os['fullscan']['file'])
+ h1 = rep.hosts.pop()
+ s = h1.services[0]
+ self.assertEqual(s.cpelist[0].cpestring, cpelist[0])
+ self.assertEqual(s.cpelist[1].cpestring, cpelist[1])
+
if __name__ == '__main__':
test_suite = ['test_fp', 'test_fpv6', 'test_osmatches_new', 'test_osclasses_new',
- 'test_fpv5', 'test_osmatches_old']
+ 'test_fpv5', 'test_osmatches_old', 'test_cpeservice']
suite = unittest.TestSuite(map(TestNmapFP, test_suite))
test_result = unittest.TextTestRunner(verbosity=2).run(suite)
From 9d5c463c8c947eacebab5f4b4a293195c5ff6e1a Mon Sep 17 00:00:00 2001
From: Ronald
Date: Wed, 14 May 2014 23:53:06 +0200
Subject: [PATCH 045/206] Fix for issue 28 and added code samples
---
CHANGES.txt | 1 +
examples/check_cpe.py | 31 +++++++++++++++++++++++++++++++
examples/os_fingerprint.py | 21 +++++++++++++++++++++
libnmap/objects/host.py | 11 +++++++++++
libnmap/objects/os.py | 28 ++++++++++++++++++++++++++++
libnmap/objects/service.py | 7 ++++---
setup.py | 2 +-
7 files changed, 97 insertions(+), 4 deletions(-)
create mode 100644 examples/check_cpe.py
create mode 100644 examples/os_fingerprint.py
diff --git a/CHANGES.txt b/CHANGES.txt
index b11b470..5dbc0f0 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,4 @@
+v0.4.9, 14/05/2014 -- Fix for issue 28 and added code samples
v0.4.8, 05/05/2014 -- Changes in OS fingerprint data API
- NmapHost now holds its OS fingerprint data in NmapHost.os
(NmapOSFingerpring object)
diff --git a/examples/check_cpe.py b/examples/check_cpe.py
new file mode 100644
index 0000000..03f62d5
--- /dev/null
+++ b/examples/check_cpe.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+
+from libnmap.parser import NmapParser
+
+rep = NmapParser.parse_fromfile('libnmap/test/files/full_sudo6.xml')
+
+print("Nmap scan discovered {0}/{1} hosts up".format(rep.hosts_up,
+ rep.hosts_total))
+for _host in rep.hosts:
+ if _host.is_up():
+ print("+ Host: {0} {1}".format(_host.address,
+ " ".join(_host.hostnames)))
+
+ # get CPE from service if available
+ for s in _host.services:
+ print " Service: {0}/{1} ({2})".format(s.port,
+ s.protocol,
+ s.state)
+ # NmapService.cpelist returns an array of CPE objects
+ for _serv_cpe in s.cpelist:
+ print " CPE: {0}".format(_serv_cpe.cpestring)
+
+ if _host.os_fingerprinted:
+ print " OS Fingerprints"
+ for osm in _host.os.osmatches:
+ print(" Found Match:{0} ({1}%)".format(osm.name,
+ osm.accuracy))
+ # NmapOSMatch.get_cpe() method return an array of string
+ # unlike NmapOSClass.cpelist which returns an array of CPE obj
+ for cpe in osm.get_cpe():
+ print("\t CPE: {0}".format(cpe))
diff --git a/examples/os_fingerprint.py b/examples/os_fingerprint.py
new file mode 100644
index 0000000..523e226
--- /dev/null
+++ b/examples/os_fingerprint.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+from libnmap.parser import NmapParser
+
+rep = NmapParser.parse_fromfile('libnmap/test/files/os_scan6.xml')
+
+print("{0}/{1} hosts up".format(rep.hosts_up, rep.hosts_total))
+for _host in rep.hosts:
+ if _host.is_up():
+ print("{0} {1}".format(_host.address, " ".join(_host.hostnames)))
+ if _host.os_fingerprinted:
+ print("OS Fingerprint:")
+ msg = ''
+ for osm in _host.os.osmatches:
+ print("Found Match:{0} ({1}%)".format(osm.name, osm.accuracy))
+ for osc in osm.osclasses:
+ print("\tOS Class: {0}".format(osc.description))
+ for cpe in osc.cpelist:
+ print("\tCPE: {0}".format(cpe.cpestring))
+ else:
+ print "No fingerprint available"
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 084241a..195531f 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -200,6 +200,17 @@ def status(self, statusdict):
"""
self._status = statusdict
+ def is_up(self):
+ """
+ method to determine if host is up or not
+
+ :return: bool
+ """
+ rval = False
+ if self.status == 'up':
+ rval = True
+ return rval
+
@property
def hostnames(self):
"""
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index 32db210..d77eb1e 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -144,6 +144,21 @@ def accuracy(self):
"""
return int(self._accuracy)
+ def get_cpe(self):
+ """
+ This method return a list of cpe stings and not CPE objects as
+ the NmapOSClass.cpelist property. This method is a helper to
+ simplify data management.
+
+ For more advanced handling of CPE data, use NmapOSClass.cpelist
+ and use the methods from CPE class
+ """
+ _cpelist = []
+ for osc in self.osclasses:
+ for cpe in osc.cpelist:
+ _cpelist.append(cpe.cpestring)
+ return _cpelist
+
def __repr__(self):
rval = "{0}: {1}".format(self.name, self.accuracy)
for _osclass in self._osclasses:
@@ -239,6 +254,19 @@ def type(self):
"""
return self._type
+ @property
+ def description(self):
+ """
+ Accessor helper which returns a concataned string of
+ the valuable attributes from NmapOSClass object
+
+ :return: string
+ """
+ rval = "{0}: {1}, {2}".format(self.type, self.vendor, self.osfamily)
+ if len(self.osgen):
+ rval += "({0})".format(self.osgen)
+ return rval
+
def __repr__(self):
rval = "{0}: {1}, {2}".format(self.type, self.vendor, self.osfamily)
if len(self.osgen):
diff --git a/libnmap/objects/service.py b/libnmap/objects/service.py
index af70f4d..c68325d 100644
--- a/libnmap/objects/service.py
+++ b/libnmap/objects/service.py
@@ -39,9 +39,10 @@ def __init__(self, portid, protocol='tcp', state=None,
self._service = service if service is not None else {}
self._cpelist = []
- for _cpe in service['cpelist']:
- _cpeobj = CPE(_cpe)
- self._cpelist.append(_cpeobj)
+ if 'cpelist' in self._service:
+ for _cpe in self._service['cpelist']:
+ _cpeobj = CPE(_cpe)
+ self._cpelist.append(_cpeobj)
self._owner = ''
if owner is not None and 'name' in owner:
diff --git a/setup.py b/setup.py
index becacdc..a136336 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
setup(
name='python-libnmap',
- version='0.4.8',
+ version='0.4.9',
author='Ronald Bister',
author_email='mini.pelle@gmail.com',
packages=['libnmap', 'libnmap.plugins', 'libnmap.objects'],
From ac30f05b5494c7e80d6091381c3363ed27dd548f Mon Sep 17 00:00:00 2001
From: Mike Boutillier
Date: Thu, 15 May 2014 12:38:50 +0000
Subject: [PATCH 046/206] Add the ability to give the full qualified path
this allow the caller to define wich nmap binary to use
in case :
- nmap is not in the path
- more than one nmap on the system
---
examples/proc_nmap_like.py | 11 +++++++++--
libnmap/process.py | 17 +++++++++++++----
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/examples/proc_nmap_like.py b/examples/proc_nmap_like.py
index cfd5e2a..b6df71c 100644
--- a/examples/proc_nmap_like.py
+++ b/examples/proc_nmap_like.py
@@ -4,8 +4,8 @@
# start a new nmap scan on localhost with some specific options
-def do_scan(targets, options):
- nm = NmapProcess(targets, options)
+def do_scan(targets, options, fqp=None):
+ nm = NmapProcess(targets, options, fqp=fqp)
rc = nm.run()
if rc != 0:
print "nmap scan failed: %s" % (nm.stderr)
@@ -51,3 +51,10 @@ def print_scan(nmap_report):
if __name__ == "__main__":
report = do_scan("127.0.0.1", "-sV")
print_scan(report)
+ # test with full path to bin
+ # /usr/bin/nmap
+ report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/nmap")
+ print_scan(report)
+ # /usr/bin/lol --> will throw exception
+ report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/lol")
+ print_scan(report)
diff --git a/libnmap/process.py b/libnmap/process.py
index 5e5a76b..4e6a804 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -27,7 +27,7 @@ class NmapProcess(Thread):
parsed out via the NmapParser class from libnmap.parser module.
"""
def __init__(self, targets="127.0.0.1",
- options="-sT", event_callback=None, safe_mode=True):
+ options="-sT", event_callback=None, safe_mode=True, fqp=None):
"""
Constructor of NmapProcess class.
@@ -47,6 +47,9 @@ def __init__(self, targets="127.0.0.1",
:param safe_mode: parameter to protect unsafe options like -oN, -oG,
-iL, -oA,...
+ :param fqp: full qualified path, if None, nmap will be searched
+ in the PATH
+
:return: NmapProcess object
"""
@@ -57,10 +60,16 @@ def __init__(self, targets="127.0.0.1",
unsafe_opts = set(['-oG', '-oN', '-iL', '-oA', '-oS', '-oX',
'--iflist', '--resume', '--stylesheet',
'--datadir'])
-
- self.__nmap_binary_name = "nmap"
+ if fqp:
+ if os.path.isfile(fqp) and os.access(fqp, os.X_OK):
+ self.__nmap_binary = fqp
+ else:
+ raise EnvironmentError(1, "wrong path or not executable", fqp)
+ else:
+ self.__nmap_binary_name = "nmap"
+ self.__nmap_binary = self._whereis(self.__nmap_binary_name)
self.__nmap_fixed_options = "-oX - -vvv --stats-every 2s"
- self.__nmap_binary = self._whereis(self.__nmap_binary_name)
+
if self.__nmap_binary is None:
raise EnvironmentError(1, "nmap is not installed or could "
"not be found in system path")
From 8acbf31de9b4ad7456cca21ccea8cf5cfd373292 Mon Sep 17 00:00:00 2001
From: Mike Boutillier
Date: Thu, 15 May 2014 12:50:39 +0000
Subject: [PATCH 047/206] comment all but one mongo version
This will reduce our footprint on travis by reducing testing build
testing again so many version of mongo is useless
---
.travis.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 8b1bac7..bfb357e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,9 +6,9 @@ python:
# - "3.2" Not ready yet
# command to install dependencies
env:
- - MONGO_VERSION=1.2.12
- - MONGO_VERSION=1.3.2
- - MONGO_VERSION=1.3.7
+# - MONGO_VERSION=1.2.12
+# - MONGO_VERSION=1.3.2
+# - MONGO_VERSION=1.3.7
- MONGO_VERSION=2.4.3
services: mongodb
From 4527959c4ed2b7ce0cc61c5809c417a955f6dcae Mon Sep 17 00:00:00 2001
From: Mike Boutillier
Date: Thu, 15 May 2014 16:48:21 +0000
Subject: [PATCH 048/206] move sample to process-stressbox
---
.../test/process-stressbox/check_fqp_nmap.py | 63 +++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100644 libnmap/test/process-stressbox/check_fqp_nmap.py
diff --git a/libnmap/test/process-stressbox/check_fqp_nmap.py b/libnmap/test/process-stressbox/check_fqp_nmap.py
new file mode 100644
index 0000000..3b2c0e2
--- /dev/null
+++ b/libnmap/test/process-stressbox/check_fqp_nmap.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+from libnmap.process import NmapProcess
+from libnmap.parser import NmapParser, NmapParserException
+
+
+# start a new nmap scan on localhost with some specific options
+def do_scan(targets, options, fqp=None):
+ nm = NmapProcess(targets, options, fqp=fqp)
+ rc = nm.run()
+ if rc != 0:
+ print "nmap scan failed: %s" % (nm.stderr)
+
+ try:
+ parsed = NmapParser.parse(nm.stdout)
+ except NmapParserException as e:
+ print "Exception raised while parsing scan: %s" % (e.msg)
+
+ return parsed
+
+
+# print scan results from a nmap report
+def print_scan(nmap_report):
+ print "Starting Nmap {0} ( http://nmap.org ) at {1}".format(
+ nmap_report._nmaprun['version'],
+ nmap_report._nmaprun['startstr'])
+
+ for host in nmap_report.hosts:
+ if len(host.hostnames):
+ tmp_host = host.hostnames.pop()
+ else:
+ tmp_host = host.address
+
+ print "Nmap scan report for {0} ({1})".format(
+ tmp_host,
+ host.address)
+ print "Host is {0}.".format(host.status)
+ print " PORT STATE SERVICE"
+
+ for serv in host.services:
+ pserv = "{0:>5s}/{1:3s} {2:12s} {3}".format(
+ str(serv.port),
+ serv.protocol,
+ serv.state,
+ serv.service)
+ if len(serv.banner):
+ pserv += " ({0})".format(serv.banner)
+ print pserv
+ print nmap_report.summary
+
+
+if __name__ == "__main__":
+ report = do_scan("127.0.0.1", "-sV")
+ print_scan(report)
+ # test with full path to bin
+ # /usr/bin/nmap
+ report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/nmap")
+ print_scan(report)
+ # /usr/bin/lol --> will throw exception
+ try:
+ report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/lol")
+ print_scan(report)
+ except Exception as exc:
+ print exc
From 277ffb951ede1a8137e40c7f06738fee73b6a6f0 Mon Sep 17 00:00:00 2001
From: Mike Boutillier
Date: Thu, 15 May 2014 16:51:08 +0000
Subject: [PATCH 049/206] move sample to process-stressbox... again!
---
examples/proc_nmap_like.py | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/examples/proc_nmap_like.py b/examples/proc_nmap_like.py
index b6df71c..cfd5e2a 100644
--- a/examples/proc_nmap_like.py
+++ b/examples/proc_nmap_like.py
@@ -4,8 +4,8 @@
# start a new nmap scan on localhost with some specific options
-def do_scan(targets, options, fqp=None):
- nm = NmapProcess(targets, options, fqp=fqp)
+def do_scan(targets, options):
+ nm = NmapProcess(targets, options)
rc = nm.run()
if rc != 0:
print "nmap scan failed: %s" % (nm.stderr)
@@ -51,10 +51,3 @@ def print_scan(nmap_report):
if __name__ == "__main__":
report = do_scan("127.0.0.1", "-sV")
print_scan(report)
- # test with full path to bin
- # /usr/bin/nmap
- report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/nmap")
- print_scan(report)
- # /usr/bin/lol --> will throw exception
- report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/lol")
- print_scan(report)
From 98630eb8aa22a49c01605b4bd759d2595097e93a Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sat, 17 May 2014 12:54:56 +0200
Subject: [PATCH 050/206] v0.5.0, 17/05/2014 -- Rewrite of NmapProcess
- removed Threads to read stdout/stderr -
replaced by Process - use of semaphore to not consume CPU
while looping - added NmapTask class
- added NmapProcess.current_task - added
NmapProcess.tasks list - fixed bug in NmapProcess.state
- note NmapProcess.is_alive() is not recommended
---
CHANGES.txt | 4 ++-
TODO | 4 +--
examples/nmap_task_bg.py | 18 ++++++++++++
examples/proc_async.py | 2 +-
libnmap/process.py | 28 ++++++++++++-------
.../process-stressbox/multi_nmap_process.py | 7 +++--
.../multi_nmap_process_background.py | 8 ++++--
libnmap/test/process-stressbox/proc_async.py | 2 +-
libnmap/test/process-stressbox/stop_scan.py | 21 ++++++++++++++
libnmap/test/process-stressbox/stressback.py | 2 +-
setup.py | 3 +-
11 files changed, 76 insertions(+), 23 deletions(-)
create mode 100644 examples/nmap_task_bg.py
create mode 100644 libnmap/test/process-stressbox/stop_scan.py
diff --git a/CHANGES.txt b/CHANGES.txt
index e8d713e..3502be2 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,10 +1,12 @@
-v0.4.7, 02/05/2014 -- Rewrite of NmapProcess
+v0.5.0, 17/05/2014 -- Rewrite of NmapProcess
- removed Threads to read stdout/stderr
- replaced by Process
- use of semaphore to not consume CPU while looping
- added NmapTask class
- added NmapProcess.current_task
- added NmapProcess.tasks list
+ - fixed bug in NmapProcess.state
+ - note NmapProcess.is_alive() is not recommended
v0.4.6, 06/04/2014 -- minor fix
- corrected missing incomplete parameter on parse_fromfile
and parse_fromstring
diff --git a/TODO b/TODO
index 1983640..de0f0d3 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,5 @@
-- review OS fingerprint API and add NmapOSFP class
-- add unit test for os fingerprint class
+- improve API for NSE scripts
+- add support for post,pre and host scripts
- support for python3
- complete unit tests with coverall support
- support for windows
diff --git a/examples/nmap_task_bg.py b/examples/nmap_task_bg.py
new file mode 100644
index 0000000..37bf982
--- /dev/null
+++ b/examples/nmap_task_bg.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+
+from libnmap.process import NmapProcess
+from time import sleep
+
+
+nmap_proc = NmapProcess(targets="scanme.nmap.org", options="-sV")
+nmap_proc.run_background()
+while nmap_proc.is_running():
+ nmaptask = nmap_proc.current_task
+ if nmaptask:
+ print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
+ nmaptask.status,
+ nmaptask.etc,
+ nmaptask.progress)
+print "rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary)
+print nmap_proc.stdout
+print nmap_proc.stderr
diff --git a/examples/proc_async.py b/examples/proc_async.py
index 6732b2b..542a2d0 100644
--- a/examples/proc_async.py
+++ b/examples/proc_async.py
@@ -6,7 +6,7 @@
nmap_proc = NmapProcess(targets="scanme.nmap.org", options="-sT")
nmap_proc.run_background()
-while nmap_proc.is_alive():
+while nmap_proc.is_running():
print "Nmap Scan running: ETC: {0} DONE: {1}%".format(nmap_proc.etc,
nmap_proc.progress)
sleep(2)
diff --git a/libnmap/process.py b/libnmap/process.py
index 7d68401..0d8c8b7 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -4,6 +4,7 @@
import shlex
import subprocess
import multiprocessing
+import signal
from threading import Thread
from xml.dom import pulldom
import warnings
@@ -114,8 +115,9 @@ def _run_init(self):
self.__nmap_command_line = self.get_command_line()
# API usable in callback function
self.__nmap_proc = None
+ self.__qout = None
self.__nmap_rc = 0
- self.__state = self.READY
+ self.__state = self.RUNNING
self.__starttime = 0
self.__endtime = 0
self.__version = ''
@@ -246,6 +248,8 @@ def ioreader_routine(proc_stdout, io_queue, data_pushed, producing):
"""
producing.value = 1
for streamline in iter(proc_stdout.readline, b''):
+ if self.__process_killed.is_set():
+ break
if streamline is not None:
try:
io_queue.put(streamline)
@@ -258,7 +262,7 @@ def ioreader_routine(proc_stdout, io_queue, data_pushed, producing):
self._run_init()
producing = multiprocessing.Value('i', 1)
data_pushed = multiprocessing.Event()
- qout = multiprocessing.Queue()
+ self.__qout = multiprocessing.Queue()
_tmp_cmdline = shlex.split(self.__nmap_command_line)
try:
@@ -268,7 +272,7 @@ def ioreader_routine(proc_stdout, io_queue, data_pushed, producing):
bufsize=0)
ioreader = multiprocessing.Process(target=ioreader_routine,
args=(self.__nmap_proc.stdout,
- qout,
+ self.__qout,
data_pushed,
producing))
ioreader.start()
@@ -282,13 +286,13 @@ def ioreader_routine(proc_stdout, io_queue, data_pushed, producing):
while(self.__nmap_proc.poll() is None or producing.value == 1):
if self.__process_killed.is_set():
break
- if producing.value == 1 and qout.empty():
+ if producing.value == 1 and self.__qout.empty():
try:
data_pushed.wait()
except KeyboardInterrupt:
break
try:
- thread_stream = qout.get_nowait()
+ thread_stream = self.__qout.get_nowait()
except Empty:
pass
except KeyboardInterrupt:
@@ -301,8 +305,8 @@ def ioreader_routine(proc_stdout, io_queue, data_pushed, producing):
data_pushed.clear()
ioreader.join()
# queue clean-up
- while not qout.empty():
- self.__stdout += qout.get_nowait()
+ while not self.__qout.empty():
+ self.__stdout += self.__qout.get_nowait()
self.__stderr += self.__nmap_proc.stderr.read()
self.__nmap_rc = self.__nmap_proc.poll()
@@ -321,6 +325,7 @@ def run_background(self):
run nmap scan in background as a thread.
For privileged scans, consider NmapProcess.sudo_run_background()
"""
+ self.__state = self.RUNNING
super(NmapProcess, self).start()
def is_running(self):
@@ -361,7 +366,10 @@ def stop(self):
Send KILL -15 to the nmap subprocess and gently ask the threads to
stop.
"""
- self.__nmap_proc.terminate()
+ self.__state = self.CANCELLED
+ if self.__nmap_proc.poll() is None:
+ self.__nmap_proc.kill()
+ self.__qout.cancel_join_thread()
self.__process_killed.set()
def __process_event(self, eventdata):
@@ -612,10 +620,10 @@ def main():
def mycallback(nmapscan=None):
if nmapscan.is_running() and nmapscan.current_task:
ntask = nmapscan.current_task
- print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(ntask.name,
+ print("Task {0} ({1}): ETC: {2} DONE: {3}%".format(ntask.name,
ntask.status,
ntask.etc,
- ntask.progress)
+ ntask.progress))
nm = NmapProcess("scanme.nmap.org",
options="-A",
event_callback=mycallback)
diff --git a/libnmap/test/process-stressbox/multi_nmap_process.py b/libnmap/test/process-stressbox/multi_nmap_process.py
index 8788933..3a89afd 100644
--- a/libnmap/test/process-stressbox/multi_nmap_process.py
+++ b/libnmap/test/process-stressbox/multi_nmap_process.py
@@ -12,9 +12,10 @@ def start_all(nmprocs):
def summarize(nmprocs):
for nmp in nmprocs:
- print "rc: {0} output: {1}".format(nmp.rc, nmp.summary)
-
-nm_targets = ["localhost", "localhost", "localhost"]
+ print "rc: {0} output: {1}".format(nmp.rc, len(nmp.stdout))
+
+nm_targets = []
+for h in range(20): nm_targets.append("localhost")
nm_opts = "-sT"
nm_procs = [make_nmproc_obj(t, nm_opts) for t in nm_targets]
diff --git a/libnmap/test/process-stressbox/multi_nmap_process_background.py b/libnmap/test/process-stressbox/multi_nmap_process_background.py
index ee8ef33..dfd3484 100644
--- a/libnmap/test/process-stressbox/multi_nmap_process_background.py
+++ b/libnmap/test/process-stressbox/multi_nmap_process_background.py
@@ -10,13 +10,15 @@ def start_all_bg(nmprocs):
for nmp in nmprocs: nmp.run_background()
def any_running(nmprocs):
- return any([nmp.is_alive() for nmp in nmprocs])
+ return any([nmp.is_running() for nmp in nmprocs])
def summarize(nmprocs):
for nmp in nmprocs:
print "rc: {0} output: {1} stdout len: {2}".format(nmp.rc, nmp.summary, len(nmp.stdout))
-
-nm_targets = ["localhost", "localhost", "localhost"]
+
+nm_targets = []
+for h in range(10):
+ nm_targets.append("localhost")
nm_opts = "-sT"
nm_procs = [make_nmproc_obj(t, nm_opts) for t in nm_targets]
diff --git a/libnmap/test/process-stressbox/proc_async.py b/libnmap/test/process-stressbox/proc_async.py
index 4727dbe..b1511c5 100644
--- a/libnmap/test/process-stressbox/proc_async.py
+++ b/libnmap/test/process-stressbox/proc_async.py
@@ -6,7 +6,7 @@
nmap_proc = NmapProcess(targets="scanme.nmap.org", options="-sT")
nmap_proc.run_background()
-while nmap_proc.is_alive():
+while nmap_proc.is_running():
nmaptask = nmap_proc.current_task
if nmaptask:
print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
diff --git a/libnmap/test/process-stressbox/stop_scan.py b/libnmap/test/process-stressbox/stop_scan.py
new file mode 100644
index 0000000..fbd399d
--- /dev/null
+++ b/libnmap/test/process-stressbox/stop_scan.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+
+from libnmap.process import NmapProcess
+from time import sleep
+
+
+nmap_proc = NmapProcess(targets="scanme.nmap.org", options="-sV")
+nmap_proc.run_background()
+while nmap_proc.is_running():
+ nmaptask = nmap_proc.current_task
+ if nmaptask:
+ print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
+ nmaptask.status,
+ nmaptask.etc,
+ nmaptask.progress)
+ sleep(3)
+ nmap_proc.stop()
+
+print "rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary)
+print nmap_proc.stdout
+print nmap_proc.stderr
diff --git a/libnmap/test/process-stressbox/stressback.py b/libnmap/test/process-stressbox/stressback.py
index 52ebad5..020c971 100644
--- a/libnmap/test/process-stressbox/stressback.py
+++ b/libnmap/test/process-stressbox/stressback.py
@@ -10,7 +10,7 @@ def start_all_bg(nmprocs):
for nmp in nmprocs: nmp.run_background()
def any_running(nmprocs):
- return any([nmp.is_alive() for nmp in nmprocs])
+ return any([nmp.is_running() for nmp in nmprocs])
def summarize(nmprocs):
for nmp in nmprocs:
diff --git a/setup.py b/setup.py
index fddfd2e..c461082 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
setup(
name='python-libnmap',
- version='0.4.7',
+ version='0.5.0',
author='Ronald Bister',
author_email='mini.pelle@gmail.com',
packages=['libnmap', 'libnmap.plugins', 'libnmap.objects'],
@@ -16,6 +16,7 @@
long_description=long_description,
classifiers=["Development Status :: 5 - Production/Stable",
"Environment :: Console",
+ "Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Topic :: System :: Networking"]
From 66a859c792aa88762ef724a870c7c4ed6c89a22f Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sat, 17 May 2014 13:43:53 +0200
Subject: [PATCH 051/206] fixed pyflakes errors
---
examples/nmap_task.py | 1 -
examples/nmap_task_bg.py | 2 --
libnmap/process.py | 1 -
3 files changed, 4 deletions(-)
diff --git a/examples/nmap_task.py b/examples/nmap_task.py
index ef29cf8..ccc4e1c 100644
--- a/examples/nmap_task.py
+++ b/examples/nmap_task.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python
from libnmap.process import NmapProcess
-from time import sleep
def mycallback(nmaptask):
nmaptask = nmap_proc.current_task
diff --git a/examples/nmap_task_bg.py b/examples/nmap_task_bg.py
index 37bf982..47013a9 100644
--- a/examples/nmap_task_bg.py
+++ b/examples/nmap_task_bg.py
@@ -1,8 +1,6 @@
#!/usr/bin/env python
from libnmap.process import NmapProcess
-from time import sleep
-
nmap_proc = NmapProcess(targets="scanme.nmap.org", options="-sV")
nmap_proc.run_background()
diff --git a/libnmap/process.py b/libnmap/process.py
index 7064c81..f4d40a4 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -4,7 +4,6 @@
import shlex
import subprocess
import multiprocessing
-import signal
from threading import Thread
from xml.dom import pulldom
import warnings
From b6ce410b2b168e1068c3cfea18d35aeddd3ce322 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 26 May 2014 23:30:41 +0200
Subject: [PATCH 052/206] Added basic API for class CPE
---
CHANGES.txt | 4 +++
libnmap/objects/cpe.py | 58 +++++++++++++++++++++++++++++++++++++
libnmap/objects/os.py | 24 +---------------
libnmap/test/test_cpe.py | 62 ++++++++++++++++++++++++++++++++++++++++
setup.py | 2 +-
5 files changed, 126 insertions(+), 24 deletions(-)
create mode 100644 libnmap/objects/cpe.py
create mode 100644 libnmap/test/test_cpe.py
diff --git a/CHANGES.txt b/CHANGES.txt
index 934b217..870e89f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,7 @@
+v0.5.1, 26/05/2014 -- Added basic API for class CPE
+ - interface similar to python-cpe for more
+ advanced usage of CPE, I strongly recommend you
+ to use python-cpe. Nice code, good doc.
v0.5.0, 17/05/2014 -- Rewrite of NmapProcess
- removed Threads to read stdout/stderr
- replaced by Process
diff --git a/libnmap/objects/cpe.py b/libnmap/objects/cpe.py
new file mode 100644
index 0000000..66eb431
--- /dev/null
+++ b/libnmap/objects/cpe.py
@@ -0,0 +1,58 @@
+
+class CPE(object):
+ """
+ CPE class offers an API for basic CPE objects.
+ These objects could be found in NmapService or in tag
+ within NmapHost.
+
+ :todo: interpret CPE string and provide appropriate API
+ """
+ def __init__(self, cpestring):
+ self._cpestring = cpestring
+ self.cpedict = {}
+
+ zk = ['cpe', 'part', 'vendor', 'product', 'version',
+ 'update', 'edition', 'language']
+ self._cpedict = dict((k, '') for k in zk)
+ splitup = cpestring.split(':')
+ self._cpedict.update(dict(zip(zk, splitup)))
+
+ @property
+ def cpestring(self):
+ """
+ Accessor for the full CPE string.
+ """
+ return self._cpestring
+
+ def __repr__(self):
+ return self._cpestring
+
+ def get_part(self):
+ return self._cpedict['part']
+
+ def get_vendor(self):
+ return self._cpedict['vendor']
+
+ def get_product(self):
+ return self._cpedict['product']
+
+ def get_version(self):
+ return self._cpedict['version']
+
+ def get_update(self):
+ return self._cpedict['update']
+
+ def get_edition(self):
+ return self._cpedict['edition']
+
+ def get_language(self):
+ return self._cpedict['language']
+
+ def is_application(self):
+ return (self.get_part() == '/a')
+
+ def is_hardware(self):
+ return (self.get_part() == '/h')
+
+ def is_operating_system(self):
+ return (self.get_part() == '/o')
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index d77eb1e..47cad68 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -1,27 +1,5 @@
import warnings
-
-
-class CPE(object):
- """
- CPE class offers an API for basic CPE objects.
- These objects could be found in NmapService or in tag
- within NmapHost.
-
- :todo: interpret CPE string and provide appropriate API
- """
- def __init__(self, cpestring):
- self._cpestring = cpestring
-
- @property
- def cpestring(self):
- """
- Accessor for the full CPE string.
- """
- return self._cpestring
-
- def __repr__(self):
- return self._cpestring
-
+from libnmap.objects.cpe import CPE
class OSFPPortUsed(object):
"""
diff --git a/libnmap/test/test_cpe.py b/libnmap/test/test_cpe.py
new file mode 100644
index 0000000..5399118
--- /dev/null
+++ b/libnmap/test/test_cpe.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+
+from libnmap.objects.os import CPE
+import unittest
+import os
+
+
+class TestNmapFP(unittest.TestCase):
+ def setUp(self):
+ self.cpelist = ['cpe:/a:apache:http_server:2.2.22',
+ 'cpe:/a:heimdal:kerberos',
+ 'cpe:/a:openbsd:openssh:5.9p1',
+ 'cpe:/o:apple:iphone_os:5',
+ 'cpe:/o:apple:mac_os_x:10.8',
+ 'cpe:/o:apple:mac_os_x',
+ 'cpe:/o:linux:linux_kernel:2.6.13',
+ 'cpe:/o:linux:linux_kernel',
+ 'cpe:/o:microsoft:windows_7',
+ 'cpe:/o:microsoft:windows_7::-:professional',
+ 'cpe:/o:microsoft:windows_7::sp1',
+ 'cpe:/o:microsoft:windows',
+ 'cpe:/o:microsoft:windows_server_2008::beta3',
+ 'cpe:/o:microsoft:windows_server_2008',
+ 'cpe:/o:microsoft:windows_server_2008::sp1',
+ 'cpe:/o:microsoft:windows_vista::-',
+ 'cpe:/o:microsoft:windows_vista::sp1',
+ 'cpe:/o:microsoft:windows_vista::sp2']
+
+ def test_cpe(self):
+ apa = CPE(self.cpelist[0])
+
+ self.assertTrue(apa.is_application())
+ self.assertFalse(apa.is_hardware())
+ self.assertFalse(apa.is_operating_system())
+
+
+ win = CPE(self.cpelist[12])
+ self.assertEqual(win.get_vendor(), 'microsoft')
+ self.assertEqual(win.get_product(), 'windows_server_2008')
+ self.assertEqual(win.get_version(), '')
+ self.assertEqual(win.get_update(), 'beta3')
+ self.assertEqual(win.get_edition(), '')
+ self.assertEqual(win.get_language(), '')
+
+ def test_full_cpe(self):
+ cpestr = 'cpe:/a:mozilla:firefox:2.0::osx:es-es'
+ resdict = { 'part':'/a', 'vendor':"mozilla", 'product':"firefox", 'version':"2.0", 'update':'', 'edition':"osx", 'language':'es-es' }
+ ocpe = CPE(cpestr)
+ objdict = {'part': ocpe.get_part(),
+ 'vendor': ocpe.get_vendor(),
+ 'product': ocpe.get_product(),
+ 'version': ocpe.get_version(),
+ 'update': ocpe.get_update(),
+ 'language': ocpe.get_language(),
+ 'edition': ocpe.get_edition()
+ }
+ self.assertEqual(objdict, resdict)
+
+if __name__ == '__main__':
+ test_suite = ['test_cpe', 'test_full_cpe']
+ suite = unittest.TestSuite(map(TestNmapFP, test_suite))
+ test_result = unittest.TextTestRunner(verbosity=2).run(suite)
diff --git a/setup.py b/setup.py
index c461082..46dea70 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
setup(
name='python-libnmap',
- version='0.5.0',
+ version='0.5.1',
author='Ronald Bister',
author_email='mini.pelle@gmail.com',
packages=['libnmap', 'libnmap.plugins', 'libnmap.objects'],
From e73757eb6c428b8ace62c1df41a39eb52131fbd8 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 26 May 2014 23:49:54 +0200
Subject: [PATCH 053/206] documented CPE API
---
libnmap/objects/cpe.py | 30 ++++++++++++++++++++++++++++++
libnmap/objects/os.py | 1 +
2 files changed, 31 insertions(+)
diff --git a/libnmap/objects/cpe.py b/libnmap/objects/cpe.py
index 66eb431..12a9928 100644
--- a/libnmap/objects/cpe.py
+++ b/libnmap/objects/cpe.py
@@ -28,31 +28,61 @@ def __repr__(self):
return self._cpestring
def get_part(self):
+ """
+ Returns the cpe part (/o, /h, /a)
+ """
return self._cpedict['part']
def get_vendor(self):
+ """
+ Returns the vendor name
+ """
return self._cpedict['vendor']
def get_product(self):
+ """
+ Returns the product name
+ """
return self._cpedict['product']
def get_version(self):
+ """
+ Returns the version of the cpe
+ """
return self._cpedict['version']
def get_update(self):
+ """
+ Returns the update version
+ """
return self._cpedict['update']
def get_edition(self):
+ """
+ Returns the cpe edition
+ """
return self._cpedict['edition']
def get_language(self):
+ """
+ Returns the cpe language
+ """
return self._cpedict['language']
def is_application(self):
+ """
+ Returns True if cpe describes an application
+ """
return (self.get_part() == '/a')
def is_hardware(self):
+ """
+ Returns True if cpe describes a hardware
+ """
return (self.get_part() == '/h')
def is_operating_system(self):
+ """
+ Returns True if cpe describes an operating system
+ """
return (self.get_part() == '/o')
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index 47cad68..13850c1 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -1,6 +1,7 @@
import warnings
from libnmap.objects.cpe import CPE
+
class OSFPPortUsed(object):
"""
Port used class: this enables the user of NmapOSFingerprint class
From 6c139c1d10461d4d4e60cfa3f0096a9319c146e1 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 26 May 2014 23:54:55 +0200
Subject: [PATCH 054/206] fixed pep8
---
libnmap/test/test_cpe.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/libnmap/test/test_cpe.py b/libnmap/test/test_cpe.py
index 5399118..080cc00 100644
--- a/libnmap/test/test_cpe.py
+++ b/libnmap/test/test_cpe.py
@@ -2,7 +2,6 @@
from libnmap.objects.os import CPE
import unittest
-import os
class TestNmapFP(unittest.TestCase):
From 6be7a979fbd7474f6e14d82bc0da66d497021383 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Fri, 30 May 2014 16:34:39 +0200
Subject: [PATCH 055/206] added documentation for NmapTask
---
docs/index.rst | 2 +-
docs/process.rst | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/docs/index.rst b/docs/index.rst
index c1b5e58..f66b236 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -10,7 +10,7 @@ libnmap is a python toolkit for manipulating nmap. It currently offers the follo
- parse: enables you to parse nmap reports or scan results (only XML so far) from a file, a string,...
- report: enables you to manipulate a parsed scan result and de/serialize scan results in a json format
- diff: enables you to see what changed between two scans
-- common: contains basic nmap objects like NmapHost and NmapService. It is to note that each object can be "diff()ed" with another similar object.
+- objects: contains basic nmap objects like NmapHost and NmapService. It is to note that each object can be "diff()ed" with another similar object.
- plugins: enables you to support datastores for your scan results directly in the "NmapReport" object from report module
- mongodb: only plugin implemented so far, ultra basic, for POC purpose only
diff --git a/docs/process.rst b/docs/process.rst
index 69a592c..b2eb46f 100644
--- a/docs/process.rst
+++ b/docs/process.rst
@@ -1,6 +1,50 @@
libnmap.process
===============
+Purpose of libnmap.process
+--------------------------
+
+The purpose of this module is to enable the lib users to launch and control nmap scans. This module will consequently fire the nmap command following the specified parameters provided in the constructor.
+
+It is to note that this module will not perform a full inline parsing of the data. Only specific events are parsed and exploitable via either a callback function defined by the user and provided in the constructor; either by running the process in the background and accessing the NmapProcess attributes will the scan is running.
+
+To run an nmap scan, you need to:
+
+- instanciate NmapProcess
+- call the run*() methods
+
+Raw results of the scans will be available in the following properties:
+
+- NmapProcess.stdout: string, XML output
+- NmapProcess.stderr: string, text error message from nmap process
+
+Processing of events
+--------------------
+
+While Nmap is running, some events are process and parsed. This would enable you to:
+
+- evaluate estimated time to completion and progress in percentage
+- find out which task is running and how many nmap task have been executed
+- know the start time and nmap version
+
+As you may know, depending on the nmap options you specified, nmap will execute several tasks like "DNS Resolve", "Ping Scan", "Connect Scan", "NSE scripts",... This is of course independent from libnmap but the lib is able to parse these tasks and will instanciate a NmapTask object for any task executed. The list of executed task is available via the following properties:
+
+- NmapProcess.tasks: list of NmapTask object (executed nmap tasks)
+- NmapProcess.current_task: returns the currently running NmapTask
+
+You will find below the list of attributes you can use when dealing with NmapTask:
+
+- name: task name (check nmap documentation for the complete list)
+- etc: unix timestamp of estimated time to completion
+- progress: estimated percentage of task completion
+- percent: estimated percentage of task completion (same as progress)
+- remaining: estimated number of seconds to completion
+- status: status of the task ('started' or 'ended')
+- starttime: unix timestamp of when the task started
+- endtime: unix timestamp of when the task ended, 0 if not completed yet
+- extrainfo: extra information stored for specific tasks
+- updated: unix timestamp of last data update for this task
+
Using libnmap.process
---------------------
@@ -67,3 +111,10 @@ NmapProcess methods
.. automodule:: libnmap.process
.. autoclass:: NmapProcess
:members:
+
+NmapTask methods
+-------------------
+
+.. automodule:: libnmap.process
+.. autoclass:: NmapTask
+ :members:
From d24a9afb4d10255f92d6f32c254790fb5a1fe15d Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 2 Jun 2014 16:49:50 +0200
Subject: [PATCH 056/206] adapted process documentation
---
docs/process.rst | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/docs/process.rst b/docs/process.rst
index b2eb46f..08ee925 100644
--- a/docs/process.rst
+++ b/docs/process.rst
@@ -18,6 +18,12 @@ Raw results of the scans will be available in the following properties:
- NmapProcess.stdout: string, XML output
- NmapProcess.stderr: string, text error message from nmap process
+To instanciate a NmapProcess instance, call the constructor with appropriate parameters:
+.. automodule:: libnmap.process
+.. autoclass:: NmapProcess
+ :members: __init__
+
+
Processing of events
--------------------
From d6829e8486bb5368b4790eff877e4482423c1407 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 2 Jun 2014 17:00:57 +0200
Subject: [PATCH 057/206] updated doc
---
docs/process.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/docs/process.rst b/docs/process.rst
index 08ee925..536c209 100644
--- a/docs/process.rst
+++ b/docs/process.rst
@@ -21,7 +21,8 @@ Raw results of the scans will be available in the following properties:
To instanciate a NmapProcess instance, call the constructor with appropriate parameters:
.. automodule:: libnmap.process
.. autoclass:: NmapProcess
- :members: __init__
+ :members:
+ .. automethod:: __init__
Processing of events
From c82d5c777af69b8557a109b0813acfd1f634e72d Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 2 Jun 2014 17:03:50 +0200
Subject: [PATCH 058/206] updated doc
---
docs/process.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/process.rst b/docs/process.rst
index 536c209..ef0a8c8 100644
--- a/docs/process.rst
+++ b/docs/process.rst
@@ -19,6 +19,7 @@ Raw results of the scans will be available in the following properties:
- NmapProcess.stderr: string, text error message from nmap process
To instanciate a NmapProcess instance, call the constructor with appropriate parameters:
+
.. automodule:: libnmap.process
.. autoclass:: NmapProcess
:members:
From 50d5dd974d66e8390a5863fc5104b52fb5bc5caf Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 2 Jun 2014 17:19:53 +0200
Subject: [PATCH 059/206] updated doc
---
docs/process.rst | 8 --------
1 file changed, 8 deletions(-)
diff --git a/docs/process.rst b/docs/process.rst
index ef0a8c8..b2eb46f 100644
--- a/docs/process.rst
+++ b/docs/process.rst
@@ -18,14 +18,6 @@ Raw results of the scans will be available in the following properties:
- NmapProcess.stdout: string, XML output
- NmapProcess.stderr: string, text error message from nmap process
-To instanciate a NmapProcess instance, call the constructor with appropriate parameters:
-
-.. automodule:: libnmap.process
-.. autoclass:: NmapProcess
- :members:
- .. automethod:: __init__
-
-
Processing of events
--------------------
From 7e7ca42c559567689192c36b329d9336d4dab006 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 2 Jun 2014 17:56:46 +0200
Subject: [PATCH 060/206] updated doc
---
docs/cpe.rst | 14 ++++++++++++++
docs/nmaphost.rst | 14 ++++++++++++++
docs/nmapreport.rst | 14 ++++++++++++++
docs/nmapservice.rst | 14 ++++++++++++++
docs/objects.rst | 22 +++++-----------------
docs/os.rst | 35 +++++++++++++++++++++++++++++++++++
docs/parser.rst | 25 +++++++++++++++++++++++--
docs/process.rst | 6 ++++++
8 files changed, 125 insertions(+), 19 deletions(-)
create mode 100644 docs/cpe.rst
create mode 100644 docs/nmaphost.rst
create mode 100644 docs/nmapreport.rst
create mode 100644 docs/nmapservice.rst
create mode 100644 docs/os.rst
diff --git a/docs/cpe.rst b/docs/cpe.rst
new file mode 100644
index 0000000..65bbe9f
--- /dev/null
+++ b/docs/cpe.rst
@@ -0,0 +1,14 @@
+libnmap.objects.service
+=======================
+
+Using libnmap.objects.cpe module
+--------------------------------
+
+TODO
+
+CPE methods
+-----------
+
+.. automodule:: libnmap.objects.cpe
+.. autoclass:: CPE
+ :members:
diff --git a/docs/nmaphost.rst b/docs/nmaphost.rst
new file mode 100644
index 0000000..ee4ad33
--- /dev/null
+++ b/docs/nmaphost.rst
@@ -0,0 +1,14 @@
+libnmap.objects.host
+====================
+
+Using libnmap.objects.host module
+---------------------------------
+
+TODO
+
+NmapHost methods
+----------------
+
+.. automodule:: libnmap.objects
+.. autoclass:: NmapHost
+ :members:
diff --git a/docs/nmapreport.rst b/docs/nmapreport.rst
new file mode 100644
index 0000000..fedcebe
--- /dev/null
+++ b/docs/nmapreport.rst
@@ -0,0 +1,14 @@
+libnmap.objects.report
+======================
+
+Using libnmap.objects.report module
+-----------------------------------
+
+TODO
+
+NmapReport methods
+------------------
+
+.. automodule:: libnmap.objects
+.. autoclass:: NmapReport
+ :members:
diff --git a/docs/nmapservice.rst b/docs/nmapservice.rst
new file mode 100644
index 0000000..e56d7db
--- /dev/null
+++ b/docs/nmapservice.rst
@@ -0,0 +1,14 @@
+libnmap.objects.service
+=======================
+
+Using libnmap.objects.service module
+------------------------------------
+
+TODO
+
+NmapService methods
+-------------------
+
+.. automodule:: libnmap.objects
+.. autoclass:: NmapService
+ :members:
diff --git a/docs/objects.rst b/docs/objects.rst
index 96cbd22..9a9ac9a 100644
--- a/docs/objects.rst
+++ b/docs/objects.rst
@@ -10,6 +10,11 @@ This module contains the definition and API of all "NmapObjects" which enables u
2. NmapHost
3. NmapService
+The three objects above are the most common one that one would manipulate. For more advanced usage, the following objects might be useful
+
+1. NmapOSFingerprint (contains: NmapOSMatch, NmapOSClass, OSFPPortUsed)
+2. CPE (Common platform enumeration contained in NmapService or NmapOSClass)
+
The following structure applies by default:
NmapReport contains:
@@ -33,20 +38,3 @@ of the same type.
If you read the code you'll see the dirty trick with id() which ensures that proper objects are being compared. The logic of diff will certainly change overtime but the API (i/o) will be kept as is.
For more info on diff, please check the module's `documentation _`.
-
-NmapReport methods
-------------------
-
-.. automodule:: libnmap.objects
-.. autoclass:: NmapReport
- :members:
-
-NmapHost methods
-----------------
-.. autoclass:: NmapHost
- :members:
-
-NmapService methods
--------------------
-.. autoclass:: NmapService
- :members:
diff --git a/docs/os.rst b/docs/os.rst
new file mode 100644
index 0000000..e86c49a
--- /dev/null
+++ b/docs/os.rst
@@ -0,0 +1,35 @@
+libnmap.objects.os
+==================
+
+Using libnmap.objects.os module
+-------------------------------
+
+TODO
+
+NmapOSFingerprint methods
+-------------------------
+
+.. automodule:: libnmap.objects.os
+.. autoclass:: NmapOSFingerprint
+ :members:
+
+NmapOSMatch methods
+-------------------
+
+.. automodule:: libnmap.objects.os
+.. autoclass:: NmapOSMatch
+ :members:
+
+NmapOSClass methods
+-------------------
+
+.. automodule:: libnmap.objects.os
+.. autoclass:: NmapOSClass
+ :members:
+
+OSFPPortUsed methods
+--------------------
+
+.. automodule:: libnmap.objects.os
+.. autoclass:: OSFPPortUsed
+ :members:
diff --git a/docs/parser.rst b/docs/parser.rst
index fade961..99725eb 100644
--- a/docs/parser.rst
+++ b/docs/parser.rst
@@ -1,11 +1,32 @@
libnmap.parser
==============
-Using libnmap.parser module
----------------------------
+Purpose of libnmap.parser
+-------------------------
This modules enables you to parse nmap scans' output. For now on, only XML parsing is supported. NmapParser is a factory which will return a NmapReport, NmapHost or NmapService object.
All these objects' API are documented.
+
+The module is capable of parsing:
+
+- a complete nmap XML scan report
+- an incomplete/interrupted nmap XML scan report
+- partial nmap xml tags: , and
+
+Input the above capabilities could be either a string or a file path.
+
+Based on the provided data, NmapParse.parse() could return the following:
+
+- NmapReport object: in case a full nmap xml/dict report was prodivded
+- NmapHost object: in case a nmap xml section was provided
+- NmapService object: in case a nmap xml section was provided
+- Python dict with following keys: ports and extraports; python lists.
+
+Using libnmap.parser module
+---------------------------
+
+NmapParser parse the whole data and returns nmap objects usable via their documented API.
+
The NmapParser should never be instanciated and only the following methods should be called:
- NmapParser.parse(string)
diff --git a/docs/process.rst b/docs/process.rst
index b2eb46f..08ee925 100644
--- a/docs/process.rst
+++ b/docs/process.rst
@@ -18,6 +18,12 @@ Raw results of the scans will be available in the following properties:
- NmapProcess.stdout: string, XML output
- NmapProcess.stderr: string, text error message from nmap process
+To instanciate a NmapProcess instance, call the constructor with appropriate parameters:
+.. automodule:: libnmap.process
+.. autoclass:: NmapProcess
+ :members: __init__
+
+
Processing of events
--------------------
From 34e17e9d4d183894fa328cf280b7be7819ac681b Mon Sep 17 00:00:00 2001
From: Ronald
Date: Tue, 3 Jun 2014 00:28:40 +0200
Subject: [PATCH 061/206] updated documentation. fixed sphinx.rst errors.
---
MANIFEST | 29 ++++++++++++++++
docs/index.rst | 8 +++++
docs/{ => objects}/cpe.rst | 4 +--
docs/{ => objects}/nmaphost.rst | 0
docs/{ => objects}/nmapreport.rst | 0
docs/{ => objects}/nmapservice.rst | 0
docs/{ => objects}/os.rst | 3 --
docs/process.rst | 9 ++---
libnmap/objects/os.py | 7 ++--
libnmap/parser.py | 54 ++++++++++++++----------------
libnmap/plugins/s3.py | 4 ++-
libnmap/process.py | 14 ++++----
12 files changed, 83 insertions(+), 49 deletions(-)
create mode 100644 MANIFEST
rename docs/{ => objects}/cpe.rst (77%)
rename docs/{ => objects}/nmaphost.rst (100%)
rename docs/{ => objects}/nmapreport.rst (100%)
rename docs/{ => objects}/nmapservice.rst (100%)
rename docs/{ => objects}/os.rst (82%)
diff --git a/MANIFEST b/MANIFEST
new file mode 100644
index 0000000..dd4b0bf
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,29 @@
+# file GENERATED by distutils, do NOT edit
+CHANGES.txt
+LICENSE.txt
+README.rst
+TODO
+setup.py
+docs/diff.rst
+docs/index.rst
+docs/objects.rst
+docs/parser.rst
+docs/plugins_s3.rst
+docs/process.rst
+libnmap/__init__.py
+libnmap/diff.py
+libnmap/parser.py
+libnmap/process.py
+libnmap/reportjson.py
+libnmap/objects/__init__.py
+libnmap/objects/cpe.py
+libnmap/objects/host.py
+libnmap/objects/os.py
+libnmap/objects/report.py
+libnmap/objects/service.py
+libnmap/plugins/__init__.py
+libnmap/plugins/backendplugin.py
+libnmap/plugins/backendpluginFactory.py
+libnmap/plugins/mongodb.py
+libnmap/plugins/s3.py
+libnmap/plugins/sql.py
diff --git a/docs/index.rst b/docs/index.rst
index f66b236..7e89213 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -11,6 +11,13 @@ libnmap is a python toolkit for manipulating nmap. It currently offers the follo
- report: enables you to manipulate a parsed scan result and de/serialize scan results in a json format
- diff: enables you to see what changed between two scans
- objects: contains basic nmap objects like NmapHost and NmapService. It is to note that each object can be "diff()ed" with another similar object.
+
+ - report: contains NmapReport class definition
+ - host: contains NmapHost class definition
+ - service: contains NmapService class definition
+ - os: contains NmapOSFingerprint class definition and some other classes like NmapOSMatch, NmapOSClass,...
+ - cpe: contains CPE class defdinition
+
- plugins: enables you to support datastores for your scan results directly in the "NmapReport" object from report module
- mongodb: only plugin implemented so far, ultra basic, for POC purpose only
@@ -35,6 +42,7 @@ The different modules are documented below:
process
parser
objects
+ objects/*
diff
plugins_s3
diff --git a/docs/cpe.rst b/docs/objects/cpe.rst
similarity index 77%
rename from docs/cpe.rst
rename to docs/objects/cpe.rst
index 65bbe9f..9f13d8f 100644
--- a/docs/cpe.rst
+++ b/docs/objects/cpe.rst
@@ -1,5 +1,5 @@
-libnmap.objects.service
-=======================
+libnmap.objects.cpe
+===================
Using libnmap.objects.cpe module
--------------------------------
diff --git a/docs/nmaphost.rst b/docs/objects/nmaphost.rst
similarity index 100%
rename from docs/nmaphost.rst
rename to docs/objects/nmaphost.rst
diff --git a/docs/nmapreport.rst b/docs/objects/nmapreport.rst
similarity index 100%
rename from docs/nmapreport.rst
rename to docs/objects/nmapreport.rst
diff --git a/docs/nmapservice.rst b/docs/objects/nmapservice.rst
similarity index 100%
rename from docs/nmapservice.rst
rename to docs/objects/nmapservice.rst
diff --git a/docs/os.rst b/docs/objects/os.rst
similarity index 82%
rename from docs/os.rst
rename to docs/objects/os.rst
index e86c49a..23fa536 100644
--- a/docs/os.rst
+++ b/docs/objects/os.rst
@@ -16,20 +16,17 @@ NmapOSFingerprint methods
NmapOSMatch methods
-------------------
-.. automodule:: libnmap.objects.os
.. autoclass:: NmapOSMatch
:members:
NmapOSClass methods
-------------------
-.. automodule:: libnmap.objects.os
.. autoclass:: NmapOSClass
:members:
OSFPPortUsed methods
--------------------
-.. automodule:: libnmap.objects.os
.. autoclass:: OSFPPortUsed
:members:
diff --git a/docs/process.rst b/docs/process.rst
index 08ee925..9ae83f7 100644
--- a/docs/process.rst
+++ b/docs/process.rst
@@ -18,11 +18,7 @@ Raw results of the scans will be available in the following properties:
- NmapProcess.stdout: string, XML output
- NmapProcess.stderr: string, text error message from nmap process
-To instanciate a NmapProcess instance, call the constructor with appropriate parameters:
-.. automodule:: libnmap.process
-.. autoclass:: NmapProcess
- :members: __init__
-
+To instanciate a NmapProcess instance, call the constructor with appropriate parameters
Processing of events
--------------------
@@ -118,9 +114,10 @@ NmapProcess methods
.. autoclass:: NmapProcess
:members:
+ .. automethod:: __init__
+
NmapTask methods
-------------------
-.. automodule:: libnmap.process
.. autoclass:: NmapTask
:members:
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index 13850c1..87ff2d4 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -294,8 +294,11 @@ def get_osmatch(self, osclass_obj):
object in order to respect the common interface for
the nmap xml version < 1.04 and >= 1.04
- :return: an NmapOSMatch object matching with the NmapOSClass
- provided in parameter (match is performed based on accuracy)
+ This method will return an NmapOSMatch object matching with
+ the NmapOSClass provided in parameter
+ (match is performed based on accuracy)
+
+ :return: NmapOSMatch object
"""
rval = None
for _osmatch in self.__osmatches:
diff --git a/libnmap/parser.py b/libnmap/parser.py
index 6142cc5..03e5ee7 100644
--- a/libnmap/parser.py
+++ b/libnmap/parser.py
@@ -11,22 +11,21 @@ class NmapParser(object):
def parse(cls, nmap_data=None, data_type='XML', incomplete=False):
"""
Generic class method of NmapParser class.
+
The data to be parsed does not need to be a complete nmap
scan report. You can possibly give ...
or XML tags.
- :param nmap_data: any portion of nmap scan result.
-
- nmap_data should always be a string representing a part
+ :param nmap_data: any portion of nmap scan result. \
+ nmap_data should always be a string representing a part \
or a complete nmap scan report.
-
:type nmap_data: string
:param data_type: specifies the type of data to be parsed.
:type data_type: string ("XML"|"JSON"|"YAML").
- :param incomplete: enable you to parse interrupted nmap scans
- and/or incomplete nmap xml blocks by adding a at
+ :param incomplete: enable you to parse interrupted nmap scans \
+ and/or incomplete nmap xml blocks by adding a at \
the end of the scan.
:type incomplete: boolean
@@ -51,12 +50,12 @@ def _parse_xml(cls, nmap_data=None, incomplete=False):
In this case: XML. This method is called by cls.parse class
method and receives nmap scan results data (in XML).
- :param nmap_data: any portion of nmap scan result can be given
- as argument. nmap_data should always be a string representing
+ :param nmap_data: any portion of nmap scan result can be given \
+ as argument. nmap_data should always be a string representing \
a part or a complete nmap scan report.
:type nmap_data: string
- This method checks which portion of a nmap scan is given
+ This method checks which portion of a nmap scan is given \
as argument.
It could be:
@@ -66,12 +65,12 @@ def _parse_xml(cls, nmap_data=None, incomplete=False):
4. a list of hosts: tag (TODO)
5. a list of ports: tag
- :param incomplete: enable you to parse interrupted nmap scans
- and/or incomplete nmap xml blocks by adding a at
+ :param incomplete: enable you to parse interrupted nmap scans \
+ and/or incomplete nmap xml blocks by adding a at \
the end of the scan.
-
:type incomplete: boolean
- :return: NmapObject (NmapHost, NmapService or NmapReport)
+
+ :return: NmapObject (NmapHost, NmapService or NmapReport) \
or a list of NmapObject
"""
@@ -140,19 +139,18 @@ def _parse_xml_report(cls, root=None):
@classmethod
def parse_fromstring(cls, nmap_data, data_type="XML", incomplete=False):
"""
- Call generic cls.parse() method and ensure that a string is
+ Call generic cls.parse() method and ensure that a string is \
passed on as argument. If not, an exception is raised.
- :param nmap_data: Same as for parse(), any portion of nmap scan.
-
+ :param nmap_data: Same as for parse(), any portion of nmap scan. \
Reports could be passed as argument. Data type _must_ be a string.
:type nmap_data: string
:param data_type: Specifies the type of data passed on as argument.
- :param incomplete: enable you to parse interrupted nmap scans
- and/or incomplete nmap xml blocks by adding a at
+ :param incomplete: enable you to parse interrupted nmap scans \
+ and/or incomplete nmap xml blocks by adding a at \
the end of the scan.
:type incomplete: boolean
@@ -169,20 +167,18 @@ def parse_fromfile(cls, nmap_report_path,
data_type="XML",
incomplete=False):
"""
- Call generic cls.parse() method and ensure that a correct file
+ Call generic cls.parse() method and ensure that a correct file \
path is given as argument. If not, an exception is raised.
- :param nmap_data: Same as for parse().
-
- Any portion of nmap scan reports could be passed as argument.
-
- Data type _must be a valid path to a file containing
+ :param nmap_data: Same as for parse(). \
+ Any portion of nmap scan reports could be passed as argument. \
+ Data type _must be a valid path to a file containing \
nmap scan results.
:param data_type: Specifies the type of serialization in the file.
- :param incomplete: enable you to parse interrupted nmap scans
- and/or incomplete nmap xml blocks by adding a at
+ :param incomplete: enable you to parse interrupted nmap scans \
+ and/or incomplete nmap xml blocks by adding a at \
the end of the scan.
:type incomplete: boolean
@@ -200,9 +196,9 @@ def parse_fromfile(cls, nmap_report_path,
@classmethod
def parse_fromdict(cls, rdict):
"""
- Strange method which transforms a python dict
- representation of a NmapReport and turns it into an
- NmapReport object.
+ Strange method which transforms a python dict \
+ representation of a NmapReport and turns it into an \
+ NmapReport object. \
Needs to be reviewed and possibly removed.
:param rdict: python dict representation of an NmapReport
diff --git a/libnmap/plugins/s3.py b/libnmap/plugins/s3.py
index fb1531c..53588de 100644
--- a/libnmap/plugins/s3.py
+++ b/libnmap/plugins/s3.py
@@ -1,11 +1,13 @@
#!/usr/bin/env python
"""
:mod:`libnmap.plugin.s3` -- S3 Backend Plugin
-===================================
+=============================================
.. module:: libnmap.plugin.s3
+
:platform: Linux
:synopsis: a plugin is representation of a S3 backend using boto
+
.. moduleauthor:: Ronald Bister
.. moduleauthor:: Mike Boutillier
"""
diff --git a/libnmap/process.py b/libnmap/process.py
index f4d40a4..3f0ad02 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -44,6 +44,7 @@ def __init__(self, name, starttime=0, extrainfo=''):
class NmapProcess(Thread):
"""
NmapProcess is a class which wraps around the nmap executable.
+
Consequently, in order to run an NmapProcess, nmap should be installed
on the host running the script. By default NmapProcess will produce
the output of the nmap scan in the nmap XML format. This could be then
@@ -54,23 +55,24 @@ def __init__(self, targets="127.0.0.1",
"""
Constructor of NmapProcess class.
- :param targets: hosts to be scanned. Could be a string of hosts
+ :param targets: hosts to be scanned. Could be a string of hosts \
separated with a coma or a python list of hosts/ip.
:type targets: string or list
- :param options: list of nmap options to be applied to scan.
+ :param options: list of nmap options to be applied to scan. \
These options are all documented in nmap's man pages.
- :param event_callback: callable function which will be ran
- each time nmap process outputs data. This function will receive
+ :param event_callback: callable function which will be ran \
+ each time nmap process outputs data. This function will receive \
two parameters:
+
1. the nmap process object
2. the data produced by nmap process. See readme for examples.
- :param safe_mode: parameter to protect unsafe options like -oN, -oG,
+ :param safe_mode: parameter to protect unsafe options like -oN, -oG, \
-iL, -oA,...
- :param fqp: full qualified path, if None, nmap will be searched
+ :param fqp: full qualified path, if None, nmap will be searched \
in the PATH
:return: NmapProcess object
From 25eced86c409e98c439696310bcae314964cdeeb Mon Sep 17 00:00:00 2001
From: Ronald
Date: Mon, 16 Jun 2014 17:32:01 +0200
Subject: [PATCH 062/206] add support for python3: testing
---
.gitignore | 2 +
.travis.yml | 3 +-
MANIFEST | 5 +++
examples/check_cpe.py | 9 +++--
examples/diff_sample1.py | 5 ++-
examples/diff_sample2.py | 13 ++++---
examples/json_serialize.py | 8 ++--
examples/nmap_task.py | 10 +++--
examples/nmap_task_bg.py | 11 +++---
examples/os_fingerprint.py | 3 +-
examples/proc_async.py | 7 ++--
examples/proc_nmap_like.py | 37 +++++++++++--------
libnmap/__init__.py | 4 +-
libnmap/diff.py | 2 +-
libnmap/objects/__init__.py | 2 +
libnmap/objects/cpe.py | 2 +
libnmap/objects/host.py | 5 ++-
libnmap/objects/os.py | 2 +
libnmap/objects/report.py | 9 ++---
libnmap/objects/service.py | 18 ++++++---
libnmap/parser.py | 6 ++-
libnmap/plugins/backendpluginFactory.py | 4 +-
libnmap/plugins/mongodb.py | 2 +-
libnmap/plugins/s3.py | 4 +-
libnmap/process.py | 7 +++-
libnmap/reportjson.py | 4 +-
.../test/process-stressbox/check_fqp_nmap.py | 29 ++++++++-------
.../test/process-stressbox/proc_nmap_like.py | 20 +++++-----
libnmap/test/process-stressbox/stressback.py | 3 +-
libnmap/test/process-stressbox/stresstest.py | 6 +--
libnmap/test/test_backend_plugin_factory.py | 1 +
libnmap/test/test_cpe.py | 1 +
libnmap/test/test_fp.py | 1 +
libnmap/test/test_host.py | 1 +
libnmap/test/test_new_parser.py | 1 +
libnmap/test/test_parser.py | 4 +-
libnmap/test/test_report.py | 5 ++-
libnmap/test/test_report_diff.py | 1 +
libnmap/test/test_service.py | 1 +
setup.py | 6 ++-
tox.ini | 5 +++
41 files changed, 168 insertions(+), 101 deletions(-)
create mode 100644 tox.ini
diff --git a/.gitignore b/.gitignore
index e493d62..fdece38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,5 @@ nosetests.xml
.project
.pydevproject
.swp
+
+__pycache__
diff --git a/.travis.yml b/.travis.yml
index bfb357e..261ac4e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,8 @@ python:
# - "2.5" Not needed EL can use epel to upgrade to 2.6
- "2.6"
- "2.7"
-# - "3.2" Not ready yet
+ - "3.3"
+ - "3.4"
# command to install dependencies
env:
# - MONGO_VERSION=1.2.12
diff --git a/MANIFEST b/MANIFEST
index dd4b0bf..0d5ef07 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -10,6 +10,11 @@ docs/objects.rst
docs/parser.rst
docs/plugins_s3.rst
docs/process.rst
+docs/objects/cpe.rst
+docs/objects/nmaphost.rst
+docs/objects/nmapreport.rst
+docs/objects/nmapservice.rst
+docs/objects/os.rst
libnmap/__init__.py
libnmap/diff.py
libnmap/parser.py
diff --git a/examples/check_cpe.py b/examples/check_cpe.py
index 03f62d5..da6f4e6 100644
--- a/examples/check_cpe.py
+++ b/examples/check_cpe.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.parser import NmapParser
@@ -13,15 +14,15 @@
# get CPE from service if available
for s in _host.services:
- print " Service: {0}/{1} ({2})".format(s.port,
+ print(" Service: {0}/{1} ({2})".format(s.port,
s.protocol,
- s.state)
+ s.state))
# NmapService.cpelist returns an array of CPE objects
for _serv_cpe in s.cpelist:
- print " CPE: {0}".format(_serv_cpe.cpestring)
+ print(" CPE: {0}".format(_serv_cpe.cpestring))
if _host.os_fingerprinted:
- print " OS Fingerprints"
+ print(" OS Fingerprints")
for osm in _host.os.osmatches:
print(" Found Match:{0} ({1}%)".format(osm.name,
osm.accuracy))
diff --git a/examples/diff_sample1.py b/examples/diff_sample1.py
index 3973261..d838fea 100644
--- a/examples/diff_sample1.py
+++ b/examples/diff_sample1.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.parser import NmapParser
@@ -18,11 +19,11 @@
service1_items_changed = changed_service1.diff(changed_service2).changed()
for diff_attr in service1_items_changed:
- print "diff({0}, {1}) [{2}:{3}] [{4}:{5}]".format(changed_service1.id,
+ print("diff({0}, {1}) [{2}:{3}] [{4}:{5}]".format(changed_service1.id,
changed_service2.id,
diff_attr,
getattr(changed_service1,
diff_attr),
diff_attr,
getattr(changed_service2,
- diff_attr))
+ diff_attr)))
diff --git a/examples/diff_sample2.py b/examples/diff_sample2.py
index 09cb8c6..093bd63 100644
--- a/examples/diff_sample2.py
+++ b/examples/diff_sample2.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.parser import NmapParser
@@ -19,9 +20,9 @@ def print_diff_added(obj1, obj2, added):
subobj1 = obj1.get_host_byid(nested[1])
elif nested[0] == 'NmapService':
subobj1 = obj1.get_service_byid(nested[1])
- print "+ {0}".format(subobj1)
+ print("+ {0}".format(subobj1))
else:
- print "+ {0} {1}: {2}".format(obj1, akey, getattr(obj1, akey))
+ print("+ {0} {1}: {2}".format(obj1, akey, getattr(obj1, akey)))
def print_diff_removed(obj1, obj2, removed):
@@ -32,9 +33,9 @@ def print_diff_removed(obj1, obj2, removed):
subobj2 = obj2.get_host_byid(nested[1])
elif nested[0] == 'NmapService':
subobj2 = obj2.get_service_byid(nested[1])
- print "- {0}".format(subobj2)
+ print("- {0}".format(subobj2))
else:
- print "- {0} {1}: {2}".format(obj2, rkey, getattr(obj2, rkey))
+ print("- {0} {1}: {2}".format(obj2, rkey, getattr(obj2, rkey)))
def print_diff_changed(obj1, obj2, changes):
@@ -49,9 +50,9 @@ def print_diff_changed(obj1, obj2, changes):
subobj2 = obj2.get_service_byid(nested[1])
print_diff(subobj1, subobj2)
else:
- print "~ {0} {1}: {2} => {3}".format(obj1, mkey,
+ print("~ {0} {1}: {2} => {3}".format(obj1, mkey,
getattr(obj2, mkey),
- getattr(obj1, mkey))
+ getattr(obj1, mkey)))
def print_diff(obj1, obj2):
diff --git a/examples/json_serialize.py b/examples/json_serialize.py
index f329bc1..3068fdb 100644
--- a/examples/json_serialize.py
+++ b/examples/json_serialize.py
@@ -1,3 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
from libnmap.parser import NmapParser
from libnmap.reportjson import ReportDecoder, ReportEncoder
import json
@@ -6,8 +9,7 @@
# create a json object from an NmapReport instance
nmap_report_json = json.dumps(nmap_report_obj, cls=ReportEncoder)
-print nmap_report_json
+print(nmap_report_json)
# create a NmapReport instance from a json object
nmap_report_obj = json.loads(nmap_report_json, cls=ReportDecoder)
-print nmap_report_obj
-
+print(nmap_report_obj)
diff --git a/examples/nmap_task.py b/examples/nmap_task.py
index ccc4e1c..09b6859 100644
--- a/examples/nmap_task.py
+++ b/examples/nmap_task.py
@@ -1,18 +1,20 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.process import NmapProcess
+
def mycallback(nmaptask):
nmaptask = nmap_proc.current_task
if nmaptask:
- print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
+ print("Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
nmaptask.status,
nmaptask.etc,
- nmaptask.progress)
+ nmaptask.progress))
nmap_proc = NmapProcess(targets="scanme.nmap.org",
options="-sV",
event_callback=mycallback)
nmap_proc.run()
-print nmap_proc.stdout
-print nmap_proc.stderr
+print(nmap_proc.stdout)
+print(nmap_proc.stderr)
diff --git a/examples/nmap_task_bg.py b/examples/nmap_task_bg.py
index 47013a9..af26533 100644
--- a/examples/nmap_task_bg.py
+++ b/examples/nmap_task_bg.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.process import NmapProcess
@@ -7,10 +8,10 @@
while nmap_proc.is_running():
nmaptask = nmap_proc.current_task
if nmaptask:
- print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
+ print("Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
nmaptask.status,
nmaptask.etc,
- nmaptask.progress)
-print "rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary)
-print nmap_proc.stdout
-print nmap_proc.stderr
+ nmaptask.progress))
+print("rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary))
+print(nmap_proc.stdout)
+print(nmap_proc.stderr)
diff --git a/examples/os_fingerprint.py b/examples/os_fingerprint.py
index 523e226..d4dcaf7 100644
--- a/examples/os_fingerprint.py
+++ b/examples/os_fingerprint.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.parser import NmapParser
@@ -18,4 +19,4 @@
for cpe in osc.cpelist:
print("\tCPE: {0}".format(cpe.cpestring))
else:
- print "No fingerprint available"
+ print("No fingerprint available")
diff --git a/examples/proc_async.py b/examples/proc_async.py
index 542a2d0..40beef4 100644
--- a/examples/proc_async.py
+++ b/examples/proc_async.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.process import NmapProcess
from time import sleep
@@ -7,8 +8,8 @@
nmap_proc = NmapProcess(targets="scanme.nmap.org", options="-sT")
nmap_proc.run_background()
while nmap_proc.is_running():
- print "Nmap Scan running: ETC: {0} DONE: {1}%".format(nmap_proc.etc,
- nmap_proc.progress)
+ print("Nmap Scan running: ETC: {0} DONE: {1}%".format(nmap_proc.etc,
+ nmap_proc.progress))
sleep(2)
-print "rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary)
+print("rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary))
diff --git a/examples/proc_nmap_like.py b/examples/proc_nmap_like.py
index cfd5e2a..c57f731 100644
--- a/examples/proc_nmap_like.py
+++ b/examples/proc_nmap_like.py
@@ -1,28 +1,32 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
from libnmap.process import NmapProcess
from libnmap.parser import NmapParser, NmapParserException
# start a new nmap scan on localhost with some specific options
def do_scan(targets, options):
- nm = NmapProcess(targets, options)
- rc = nm.run()
+ parsed = None
+ nmproc = NmapProcess(targets, options)
+ rc = nmproc.run()
if rc != 0:
- print "nmap scan failed: %s" % (nm.stderr)
+ print("nmap scan failed: {0}".format(nmproc.stderr))
+ print(type(nmproc.stdout))
try:
- parsed = NmapParser.parse(nm.stdout)
+ parsed = NmapParser.parse(nmproc.stdout)
except NmapParserException as e:
- print "Exception raised while parsing scan: %s" % (e.msg)
+ print("Exception raised while parsing scan: {0}".format(e.msg))
return parsed
# print scan results from a nmap report
def print_scan(nmap_report):
- print "Starting Nmap {0} ( http://nmap.org ) at {1}".format(
- nmap_report._nmaprun['version'],
- nmap_report._nmaprun['startstr'])
+ print("Starting Nmap {0} ( http://nmap.org ) at {1}".format(
+ nmap_report.version,
+ nmap_report.started))
for host in nmap_report.hosts:
if len(host.hostnames):
@@ -30,11 +34,11 @@ def print_scan(nmap_report):
else:
tmp_host = host.address
- print "Nmap scan report for {0} ({1})".format(
+ print("Nmap scan report for {0} ({1})".format(
tmp_host,
- host.address)
- print "Host is {0}.".format(host.status)
- print " PORT STATE SERVICE"
+ host.address))
+ print("Host is {0}.".format(host.status))
+ print(" PORT STATE SERVICE")
for serv in host.services:
pserv = "{0:>5s}/{1:3s} {2:12s} {3}".format(
@@ -44,10 +48,13 @@ def print_scan(nmap_report):
serv.service)
if len(serv.banner):
pserv += " ({0})".format(serv.banner)
- print pserv
- print nmap_report.summary
+ print(pserv)
+ print(nmap_report.summary)
if __name__ == "__main__":
report = do_scan("127.0.0.1", "-sV")
- print_scan(report)
+ if report:
+ print_scan(report)
+ else:
+ print("No results returned")
diff --git a/libnmap/__init__.py b/libnmap/__init__.py
index b9eaba2..ff92f57 100644
--- a/libnmap/__init__.py
+++ b/libnmap/__init__.py
@@ -1,6 +1,8 @@
+# -*- coding: utf-8 -*-
+
__author__ = 'Ronald Bister, Mike Boutillier'
__credits__ = ['Ronald Bister', 'Mike Boutillier']
__maintainer__ = 'Ronald Bister'
__email__ = 'mini.pelle@gmail.com'
__license__ = 'CC-BY'
-__version__ = '0.2'
+__version__ = '0.5.1'
diff --git a/libnmap/diff.py b/libnmap/diff.py
index 2deec7b..4a958f5 100644
--- a/libnmap/diff.py
+++ b/libnmap/diff.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+# -*- coding: utf-8 -*-
class DictDiffer(object):
diff --git a/libnmap/objects/__init__.py b/libnmap/objects/__init__.py
index 756b18d..7432109 100644
--- a/libnmap/objects/__init__.py
+++ b/libnmap/objects/__init__.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
from libnmap.objects.report import NmapReport
from libnmap.objects.host import NmapHost
from libnmap.objects.service import NmapService
diff --git a/libnmap/objects/cpe.py b/libnmap/objects/cpe.py
index 12a9928..aa38b85 100644
--- a/libnmap/objects/cpe.py
+++ b/libnmap/objects/cpe.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
class CPE(object):
"""
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 195531f..03181c9 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -1,4 +1,5 @@
-#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
from libnmap.diff import NmapDiff
from libnmap.objects.os import NmapOSFingerprint
@@ -456,7 +457,7 @@ def get_dict(self):
:return dict
"""
- d = dict([("%s::%s" % (s.__class__.__name__, str(s.id)),
+ d = dict([("{0}::{1}".format(s.__class__.__name__, str(s.id)),
hash(s))
for s in self.services])
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index 87ff2d4..514dea1 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
import warnings
from libnmap.objects.cpe import CPE
diff --git a/libnmap/objects/report.py b/libnmap/objects/report.py
index e4430d4..9c48a94 100644
--- a/libnmap/objects/report.py
+++ b/libnmap/objects/report.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.diff import NmapDiff
@@ -294,10 +294,9 @@ def get_dict(self):
:return: dict
"""
- rdict = dict([("%s::%s" % (_host.__class__.__name__,
- str(_host.id)),
- hash(_host))
- for _host in self.hosts])
+ rdict = dict([("{0}::{1}".format(_host.__class__.__name__,
+ str(_host.id)),
+ hash(_host)) for _host in self.hosts])
rdict.update({'commandline': self.commandline,
'version': self.version,
'scan_type': self.scan_type,
diff --git a/libnmap/objects/service.py b/libnmap/objects/service.py
index c68325d..631bcec 100644
--- a/libnmap/objects/service.py
+++ b/libnmap/objects/service.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.diff import NmapDiff
from libnmap.objects.os import CPE
@@ -206,13 +206,19 @@ def banner(self):
:return: string
"""
- notrelevant = ['name', 'method', 'conf', 'cpelist']
+ notrelevant = ['name', 'method', 'conf', 'cpelist',
+ 'servicefp', 'tunnel']
+ relevant = ['product', 'version', 'extrainfo']
b = ''
+ skeys = self._service.keys()
if 'method' in self._service and self._service['method'] == "probed":
- b = " ".join([k + ": " + self._service[k]
- for k in self._service.keys()
- if k not in notrelevant])
- return b
+ for relk in relevant:
+ if relk in skeys:
+ b += '{0}: {1} '.format(relk, self._service[relk])
+ for mkey in skeys:
+ if mkey not in notrelevant and mkey not in relevant:
+ b += '{0}: {1} '.format(mkey, self._service[mkey])
+ return b.rstrip()
@property
def cpelist(self):
diff --git a/libnmap/parser.py b/libnmap/parser.py
index 03e5ee7..2c1bd37 100644
--- a/libnmap/parser.py
+++ b/libnmap/parser.py
@@ -1,4 +1,6 @@
-#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+
try:
import xml.etree.cElementTree as ET
except ImportError:
@@ -208,7 +210,7 @@ def parse_fromdict(cls, rdict):
"""
nreport = {}
- if rdict.keys()[0] == '__NmapReport__':
+ if list(rdict.keys())[0] == '__NmapReport__':
r = rdict['__NmapReport__']
nreport['_runstats'] = r['_runstats']
nreport['_scaninfo'] = r['_scaninfo']
diff --git a/libnmap/plugins/backendpluginFactory.py b/libnmap/plugins/backendpluginFactory.py
index a49d4c3..84cc250 100644
--- a/libnmap/plugins/backendpluginFactory.py
+++ b/libnmap/plugins/backendpluginFactory.py
@@ -19,7 +19,7 @@ def create(cls, plugin_name="mongodb", **kwargs):
:return: NmapBackend (abstract class on top of all plugin)
"""
backendplugin = None
- plugin_path = "libnmap.plugins.%s" % (plugin_name)
+ plugin_path = "libnmap.plugins.{0}".format(plugin_name)
__import__(plugin_path)
pluginobj = sys.modules[plugin_path]
pluginclasses = inspect.getmembers(pluginobj, inspect.isclass)
@@ -28,5 +28,5 @@ def create(cls, plugin_name="mongodb", **kwargs):
try:
backendplugin = classobj(**kwargs)
except Exception as error:
- print "Cannot create Backend: %s" % (error)
+ print("Cannot create Backend: {0}".format(error))
return backendplugin
diff --git a/libnmap/plugins/mongodb.py b/libnmap/plugins/mongodb.py
index 11f2143..6bd1ee5 100644
--- a/libnmap/plugins/mongodb.py
+++ b/libnmap/plugins/mongodb.py
@@ -36,7 +36,7 @@ def insert(self, report):
try:
oid = self.collection.insert(json.loads(j))
except:
- print "MONGODB cannot insert"
+ print("MONGODB cannot insert")
raise
return str(oid)
diff --git a/libnmap/plugins/s3.py b/libnmap/plugins/s3.py
index 53588de..efb662e 100644
--- a/libnmap/plugins/s3.py
+++ b/libnmap/plugins/s3.py
@@ -88,7 +88,7 @@ def insert(self, report):
strjsonnmapreport = json.dumps(report, cls=ReportEncoder)
mykey.set_contents_from_string(strjsonnmapreport)
except:
- print "Bucket cannot insert"
+ print("Bucket cannot insert")
raise
return str(oid)
@@ -108,7 +108,7 @@ def get(self, str_report_id=None):
nmapreportjson = json.loads(mykey.get_contents_as_string())
nmapreport = NmapParser.parse_fromdict(nmapreportjson)
except S3ResponseError:
- print "Not Found"
+ print("Not Found")
return nmapreport
def getall(self, dict_filter=None):
diff --git a/libnmap/process.py b/libnmap/process.py
index 3f0ad02..fecda19 100644
--- a/libnmap/process.py
+++ b/libnmap/process.py
@@ -1,4 +1,6 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
import os
import pwd
import shlex
@@ -7,6 +9,7 @@
from threading import Thread
from xml.dom import pulldom
import warnings
+
try:
from Queue import Empty, Full
except ImportError:
@@ -262,7 +265,7 @@ def ioreader_routine(proc_stdout, io_queue, data_pushed, producing):
break
if streamline is not None:
try:
- io_queue.put(streamline)
+ io_queue.put(str(streamline.decode()))
except Full:
pass
data_pushed.set()
@@ -317,7 +320,7 @@ def ioreader_routine(proc_stdout, io_queue, data_pushed, producing):
# queue clean-up
while not self.__qout.empty():
self.__stdout += self.__qout.get_nowait()
- self.__stderr += self.__nmap_proc.stderr.read()
+ self.__stderr += str(self.__nmap_proc.stderr.read().decode())
self.__nmap_rc = self.__nmap_proc.poll()
if self.rc is None:
diff --git a/libnmap/reportjson.py b/libnmap/reportjson.py
index c559983..9bf6526 100644
--- a/libnmap/reportjson.py
+++ b/libnmap/reportjson.py
@@ -1,4 +1,6 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
import json
from libnmap.objects import NmapHost, NmapService, NmapReport
from libnmap.objects.os import NmapOSFingerprint, NmapOSMatch, NmapOSClass
@@ -17,7 +19,7 @@ def default(self, obj):
'NmapService': NmapService,
'NmapReport': NmapReport}
if isinstance(obj, tuple(otype.values())):
- key = '__%s__' % obj.__class__.__name__
+ key = ('__{0}__').format(obj.__class__.__name__)
return {key: obj.__dict__}
return json.JSONEncoder.default(self, obj)
diff --git a/libnmap/test/process-stressbox/check_fqp_nmap.py b/libnmap/test/process-stressbox/check_fqp_nmap.py
index 3b2c0e2..6035b84 100644
--- a/libnmap/test/process-stressbox/check_fqp_nmap.py
+++ b/libnmap/test/process-stressbox/check_fqp_nmap.py
@@ -5,24 +5,26 @@
# start a new nmap scan on localhost with some specific options
def do_scan(targets, options, fqp=None):
+ parsed = None
nm = NmapProcess(targets, options, fqp=fqp)
rc = nm.run()
if rc != 0:
- print "nmap scan failed: %s" % (nm.stderr)
+ print("nmap scan failed: {0}".format(nm.stderr))
+ print(nm.stdout)
try:
parsed = NmapParser.parse(nm.stdout)
except NmapParserException as e:
- print "Exception raised while parsing scan: %s" % (e.msg)
+ print("Exception raised while parsing scan: {0}".format(e.msg))
return parsed
# print scan results from a nmap report
def print_scan(nmap_report):
- print "Starting Nmap {0} ( http://nmap.org ) at {1}".format(
- nmap_report._nmaprun['version'],
- nmap_report._nmaprun['startstr'])
+ print("Starting Nmap {0} ( http://nmap.org ) at {1}".format(
+ nmap_report.version,
+ nmap_report.started))
for host in nmap_report.hosts:
if len(host.hostnames):
@@ -30,11 +32,11 @@ def print_scan(nmap_report):
else:
tmp_host = host.address
- print "Nmap scan report for {0} ({1})".format(
- tmp_host,
- host.address)
- print "Host is {0}.".format(host.status)
- print " PORT STATE SERVICE"
+ print("Nmap scan report for {0} ({1})".format(
+ tmp_host,
+ host.address))
+ print("Host is {0}.".format(host.status))
+ print(" PORT STATE SERVICE")
for serv in host.services:
pserv = "{0:>5s}/{1:3s} {2:12s} {3}".format(
@@ -44,12 +46,13 @@ def print_scan(nmap_report):
serv.service)
if len(serv.banner):
pserv += " ({0})".format(serv.banner)
- print pserv
- print nmap_report.summary
+ print(pserv)
+ print(nmap_report.summary)
if __name__ == "__main__":
report = do_scan("127.0.0.1", "-sV")
+ print(report)
print_scan(report)
# test with full path to bin
# /usr/bin/nmap
@@ -60,4 +63,4 @@ def print_scan(nmap_report):
report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/lol")
print_scan(report)
except Exception as exc:
- print exc
+ print(exc)
diff --git a/libnmap/test/process-stressbox/proc_nmap_like.py b/libnmap/test/process-stressbox/proc_nmap_like.py
index cfd5e2a..5399b66 100644
--- a/libnmap/test/process-stressbox/proc_nmap_like.py
+++ b/libnmap/test/process-stressbox/proc_nmap_like.py
@@ -8,21 +8,21 @@ def do_scan(targets, options):
nm = NmapProcess(targets, options)
rc = nm.run()
if rc != 0:
- print "nmap scan failed: %s" % (nm.stderr)
+ print("nmap scan failed: {0}".format(nm.stderr))
try:
parsed = NmapParser.parse(nm.stdout)
except NmapParserException as e:
- print "Exception raised while parsing scan: %s" % (e.msg)
+ print("Exception raised while parsing scan: {0}".format(e.msg))
return parsed
# print scan results from a nmap report
def print_scan(nmap_report):
- print "Starting Nmap {0} ( http://nmap.org ) at {1}".format(
+ print("Starting Nmap {0} ( http://nmap.org ) at {1}".format(
nmap_report._nmaprun['version'],
- nmap_report._nmaprun['startstr'])
+ nmap_report._nmaprun['startstr']))
for host in nmap_report.hosts:
if len(host.hostnames):
@@ -30,11 +30,11 @@ def print_scan(nmap_report):
else:
tmp_host = host.address
- print "Nmap scan report for {0} ({1})".format(
+ print("Nmap scan report for {0} ({1})".format(
tmp_host,
- host.address)
- print "Host is {0}.".format(host.status)
- print " PORT STATE SERVICE"
+ host.address))
+ print("Host is {0}.".format(host.status))
+ print(" PORT STATE SERVICE")
for serv in host.services:
pserv = "{0:>5s}/{1:3s} {2:12s} {3}".format(
@@ -44,8 +44,8 @@ def print_scan(nmap_report):
serv.service)
if len(serv.banner):
pserv += " ({0})".format(serv.banner)
- print pserv
- print nmap_report.summary
+ print(pserv)
+ print(nmap_report.summary)
if __name__ == "__main__":
diff --git a/libnmap/test/process-stressbox/stressback.py b/libnmap/test/process-stressbox/stressback.py
index 020c971..ee14edc 100644
--- a/libnmap/test/process-stressbox/stressback.py
+++ b/libnmap/test/process-stressbox/stressback.py
@@ -14,7 +14,8 @@ def any_running(nmprocs):
def summarize(nmprocs):
for nmp in nmprocs:
- print "rc: {0} output: {1}".format(nmp.rc, len(nmp.stdout))
+ print("rc: {0} output: {1}".format(nmp.rc, len(nmp.stdout)))
+ print(nmp.stdout)
nb_targets = 10
nm_target = "localhost"
diff --git a/libnmap/test/process-stressbox/stresstest.py b/libnmap/test/process-stressbox/stresstest.py
index c1afa33..6de045a 100644
--- a/libnmap/test/process-stressbox/stresstest.py
+++ b/libnmap/test/process-stressbox/stresstest.py
@@ -5,11 +5,11 @@
nm = NmapProcess('127.0.0.1', '-sP')
rc = nm.run()
if rc != 0:
- print "nmap scan failed: %s" % (nm.stderr)
+ print("nmap scan failed: {0}".format(nm.stderr))
try:
report = NmapParser.parse(nm.stdout)
except NmapParserException as e:
- print "Exception raised while parsing scan: %s" % (e.msg)
+ print("Exception raised while parsing scan: {0}".format(e.msg))
-print len(nm.stdout)
+print(len(nm.stdout))
diff --git a/libnmap/test/test_backend_plugin_factory.py b/libnmap/test/test_backend_plugin_factory.py
index 3b4d962..2c983c5 100644
--- a/libnmap/test/test_backend_plugin_factory.py
+++ b/libnmap/test/test_backend_plugin_factory.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import unittest
import os
diff --git a/libnmap/test/test_cpe.py b/libnmap/test/test_cpe.py
index 080cc00..06d1ae2 100644
--- a/libnmap/test/test_cpe.py
+++ b/libnmap/test/test_cpe.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
from libnmap.objects.os import CPE
import unittest
diff --git a/libnmap/test/test_fp.py b/libnmap/test/test_fp.py
index 3941c18..8c6dd0b 100644
--- a/libnmap/test/test_fp.py
+++ b/libnmap/test/test_fp.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import unittest
import os
diff --git a/libnmap/test/test_host.py b/libnmap/test/test_host.py
index 4af38f3..7e90535 100644
--- a/libnmap/test/test_host.py
+++ b/libnmap/test/test_host.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import unittest
from libnmap.parser import NmapParser
diff --git a/libnmap/test/test_new_parser.py b/libnmap/test/test_new_parser.py
index f0d3947..a863c5b 100644
--- a/libnmap/test/test_new_parser.py
+++ b/libnmap/test/test_new_parser.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import unittest
from libnmap.parser import NmapParser, NmapParserException
diff --git a/libnmap/test/test_parser.py b/libnmap/test/test_parser.py
index ac81846..d940969 100644
--- a/libnmap/test/test_parser.py
+++ b/libnmap/test/test_parser.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import unittest
import os
@@ -144,7 +145,6 @@ def test_class_port_parser(self):
self.assertEqual(p.reason_ttl, "253")
self.assertEqual(p.reason_ip, "109.133.192.1")
-
def test_port_except(self):
self.assertRaises(ValueError,
NmapParser.parse,
@@ -173,7 +173,7 @@ def test_port_except(self):
def test_parser_generic(self):
plist = NmapParser.parse_fromstring(self.ports_string)
for p in plist:
- print p
+ print(p)
if __name__ == '__main__':
test_suite = ['test_class_parser', 'test_class_ports_parser',
diff --git a/libnmap/test/test_report.py b/libnmap/test/test_report.py
index d2f0f8f..8e1740e 100644
--- a/libnmap/test/test_report.py
+++ b/libnmap/test/test_report.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import unittest
import os
@@ -54,8 +55,8 @@ def setUp(self):
'631': 'product: CUPS version: 1.4',
'3306':
'product: MySQL version: 5.1.61',
- '22': ("product: OpenSSH extrainfo:"
- " protocol 2.0 version: 5.3"),
+ '22': ("product: OpenSSH version: 5.3"
+ " extrainfo: protocol 2.0"),
'25': ("product: Postfix smtpd"
" hostname: jambon.localdomain"),
'111': ''}}]
diff --git a/libnmap/test/test_report_diff.py b/libnmap/test/test_report_diff.py
index f76286d..d052b7e 100644
--- a/libnmap/test/test_report_diff.py
+++ b/libnmap/test/test_report_diff.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import unittest
import os
diff --git a/libnmap/test/test_service.py b/libnmap/test/test_service.py
index a4d4dea..1d3a7aa 100644
--- a/libnmap/test/test_service.py
+++ b/libnmap/test/test_service.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import unittest
from libnmap.parser import NmapParser
diff --git a/setup.py b/setup.py
index 46dea70..45c04cd 100644
--- a/setup.py
+++ b/setup.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
from distutils.core import setup
with open("README.rst") as rfile:
@@ -5,7 +6,7 @@
setup(
name='python-libnmap',
- version='0.5.1',
+ version='0.5.2',
author='Ronald Bister',
author_email='mini.pelle@gmail.com',
packages=['libnmap', 'libnmap.plugins', 'libnmap.objects'],
@@ -19,5 +20,8 @@
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.3",
+ "Programming Language :: Python :: 3.4",
"Topic :: System :: Networking"]
)
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..21271f9
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,5 @@
+[tox]
+envlist = py27,py34
+[testenv]
+deps=nose
+commands=nosetests
From 9197286306af7b0a3183e18647836cd16d66f7fa Mon Sep 17 00:00:00 2001
From: Ronald
Date: Wed, 18 Jun 2014 01:58:46 +0200
Subject: [PATCH 063/206] Added support for python 2 and 3
---
.travis.yml | 6 ++----
README.rst | 12 +++++++++++-
libnmap/test/process-stressbox/check_fqp_nmap.py | 7 +++----
libnmap/test/process-stressbox/multi_nmap_process.py | 2 +-
.../multi_nmap_process_background.py | 4 ++--
libnmap/test/process-stressbox/proc_async.py | 8 ++++----
libnmap/test/process-stressbox/stop_scan.py | 10 +++++-----
setup.py | 2 +-
8 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 261ac4e..bb3601e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,12 +17,10 @@ services: mongodb
install:
- "pip install pep8 --use-mirrors"
- "pip install pyflakes --use-mirrors"
- - "pip install boto --use-mirrors"
+# - "pip install boto --use-mirrors" # disabled: since boto not supporting py3
- "pip install pymongo sqlalchemy MySQL-python --use-mirrors"
- - "pip install coveralls"
+ - "pip install coveralls"
- "python setup.py install"
-# - "pip install -r requirements.txt --use-mirrors"
-# # command to run tests
before_script:
- "pep8 . --exclude test,docs,examples"
- "pyflakes ."
diff --git a/README.rst b/README.rst
index 52ca750..e9a6fca 100644
--- a/README.rst
+++ b/README.rst
@@ -35,7 +35,7 @@ The lib currently offers the following modules:
- mongodb: insert/get/getAll/delete
- sqlalchemy: insert/get/getAll/delete
- - aws s3: insert/get/getAll/delete
+ - aws s3: insert/get/getAll/delete (not supported for python3 since boto is not supporting py3)
- csv: todo (easy to implement)
- elastic search: todo
@@ -57,6 +57,16 @@ Below the list of optional dependencies:
- `pymongo`_
- `boto`_
+Python Support
+--------------
+
+The libnmap code is tested against the following python interpreters:
+
+- Python 2.6
+- Python 2.7
+- Python 3.3
+- Python 3.4
+
Install
-------
diff --git a/libnmap/test/process-stressbox/check_fqp_nmap.py b/libnmap/test/process-stressbox/check_fqp_nmap.py
index 6035b84..cfd9db2 100644
--- a/libnmap/test/process-stressbox/check_fqp_nmap.py
+++ b/libnmap/test/process-stressbox/check_fqp_nmap.py
@@ -11,7 +11,6 @@ def do_scan(targets, options, fqp=None):
if rc != 0:
print("nmap scan failed: {0}".format(nm.stderr))
- print(nm.stdout)
try:
parsed = NmapParser.parse(nm.stdout)
except NmapParserException as e:
@@ -51,16 +50,16 @@ def print_scan(nmap_report):
if __name__ == "__main__":
- report = do_scan("127.0.0.1", "-sV")
- print(report)
+ report = do_scan("127.0.0.1", "-sT")
print_scan(report)
# test with full path to bin
# /usr/bin/nmap
- report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/nmap")
+ report = do_scan("127.0.0.1", "-sT", fqp="/usr/bin/nmap")
print_scan(report)
# /usr/bin/lol --> will throw exception
try:
report = do_scan("127.0.0.1", "-sV", fqp="/usr/bin/lol")
+ print("lolbin")
print_scan(report)
except Exception as exc:
print(exc)
diff --git a/libnmap/test/process-stressbox/multi_nmap_process.py b/libnmap/test/process-stressbox/multi_nmap_process.py
index 3a89afd..d861de3 100644
--- a/libnmap/test/process-stressbox/multi_nmap_process.py
+++ b/libnmap/test/process-stressbox/multi_nmap_process.py
@@ -12,7 +12,7 @@ def start_all(nmprocs):
def summarize(nmprocs):
for nmp in nmprocs:
- print "rc: {0} output: {1}".format(nmp.rc, len(nmp.stdout))
+ print("rc: {0} output: {1}".format(nmp.rc, len(nmp.stdout)))
nm_targets = []
for h in range(20): nm_targets.append("localhost")
diff --git a/libnmap/test/process-stressbox/multi_nmap_process_background.py b/libnmap/test/process-stressbox/multi_nmap_process_background.py
index dfd3484..1e2faef 100644
--- a/libnmap/test/process-stressbox/multi_nmap_process_background.py
+++ b/libnmap/test/process-stressbox/multi_nmap_process_background.py
@@ -14,7 +14,7 @@ def any_running(nmprocs):
def summarize(nmprocs):
for nmp in nmprocs:
- print "rc: {0} output: {1} stdout len: {2}".format(nmp.rc, nmp.summary, len(nmp.stdout))
+ print("rc: {0} output: {1} stdout len: {2}".format(nmp.rc, nmp.summary, len(nmp.stdout)))
nm_targets = []
for h in range(10):
@@ -25,7 +25,7 @@ def summarize(nmprocs):
start_all_bg(nm_procs)
while any_running(nm_procs):
- print "Nmap Scan running..."
+ print("Nmap Scan running...")
sleep(2)
summarize(nm_procs)
diff --git a/libnmap/test/process-stressbox/proc_async.py b/libnmap/test/process-stressbox/proc_async.py
index b1511c5..f588d2f 100644
--- a/libnmap/test/process-stressbox/proc_async.py
+++ b/libnmap/test/process-stressbox/proc_async.py
@@ -9,11 +9,11 @@
while nmap_proc.is_running():
nmaptask = nmap_proc.current_task
if nmaptask:
- print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
+ print("Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
nmaptask.status,
nmaptask.etc,
- nmaptask.progress)
+ nmaptask.progress))
sleep(0.5)
-print "rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary)
-print nmap_proc.stdout
+print("rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary))
+print(nmap_proc.stdout)
diff --git a/libnmap/test/process-stressbox/stop_scan.py b/libnmap/test/process-stressbox/stop_scan.py
index fbd399d..10c01bd 100644
--- a/libnmap/test/process-stressbox/stop_scan.py
+++ b/libnmap/test/process-stressbox/stop_scan.py
@@ -9,13 +9,13 @@
while nmap_proc.is_running():
nmaptask = nmap_proc.current_task
if nmaptask:
- print "Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
+ print("Task {0} ({1}): ETC: {2} DONE: {3}%".format(nmaptask.name,
nmaptask.status,
nmaptask.etc,
- nmaptask.progress)
+ nmaptask.progress))
sleep(3)
nmap_proc.stop()
-print "rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary)
-print nmap_proc.stdout
-print nmap_proc.stderr
+print("rc: {0} output: {1}".format(nmap_proc.rc, nmap_proc.summary))
+print(nmap_proc.stdout)
+print(nmap_proc.stderr)
diff --git a/setup.py b/setup.py
index 45c04cd..8f8d6de 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@
setup(
name='python-libnmap',
- version='0.5.2',
+ version='0.6',
author='Ronald Bister',
author_email='mini.pelle@gmail.com',
packages=['libnmap', 'libnmap.plugins', 'libnmap.objects'],
From c1f489f2af95366408bce97267a2777e75e546ec Mon Sep 17 00:00:00 2001
From: Ronald
Date: Wed, 18 Jun 2014 03:38:09 +0200
Subject: [PATCH 064/206] added test case for process.py
---
.travis.yml | 1 +
libnmap/__init__.py | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index bb3601e..1f894a7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -25,6 +25,7 @@ before_script:
- "pep8 . --exclude test,docs,examples"
- "pyflakes ."
- mysql -e 'create database poulet;'
+ - "apt-get install nmap"
script: nosetests --with-coverage --cover-package=libnmap
after_success:
coveralls
diff --git a/libnmap/__init__.py b/libnmap/__init__.py
index ff92f57..d4985e7 100644
--- a/libnmap/__init__.py
+++ b/libnmap/__init__.py
@@ -5,4 +5,4 @@
__maintainer__ = 'Ronald Bister'
__email__ = 'mini.pelle@gmail.com'
__license__ = 'CC-BY'
-__version__ = '0.5.1'
+__version__ = '0.6'
From e42a4583a00c0a582ef1e6304a495339a8689858 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Wed, 18 Jun 2014 03:49:38 +0200
Subject: [PATCH 065/206] adapted travis for nmap install
---
.travis.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 1f894a7..6e5797f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,6 +14,9 @@ env:
services: mongodb
+before_install:
+ - "sudo apt-get update -qq"
+ - "sudo apt-get install nmap -qq"
install:
- "pip install pep8 --use-mirrors"
- "pip install pyflakes --use-mirrors"
@@ -25,7 +28,6 @@ before_script:
- "pep8 . --exclude test,docs,examples"
- "pyflakes ."
- mysql -e 'create database poulet;'
- - "apt-get install nmap"
script: nosetests --with-coverage --cover-package=libnmap
after_success:
coveralls
From b35524208ff2c535033b8e1037f5f4a8ffb70f94 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Wed, 18 Jun 2014 05:47:22 +0200
Subject: [PATCH 066/206] remove mysqldb connector for pymysql: py3 support
---
.travis.yml | 3 ++-
libnmap/plugins/sql.py | 15 +++++++++++----
libnmap/test/test_backend_plugin_factory.py | 3 ++-
tox.ini | 3 +++
4 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 6e5797f..2a019ef 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,7 +21,8 @@ install:
- "pip install pep8 --use-mirrors"
- "pip install pyflakes --use-mirrors"
# - "pip install boto --use-mirrors" # disabled: since boto not supporting py3
- - "pip install pymongo sqlalchemy MySQL-python --use-mirrors"
+# - "pip install pymongo sqlalchemy MySQL-python --use-mirrors" # disabled MySQL-python (not py3 compatible)
+ - "pip install pymongo sqlalchemy pymysql --use-mirrors"
- "pip install coveralls"
- "python setup.py install"
before_script:
diff --git a/libnmap/plugins/sql.py b/libnmap/plugins/sql.py
index 9523300..aad2f52 100644
--- a/libnmap/plugins/sql.py
+++ b/libnmap/plugins/sql.py
@@ -103,8 +103,10 @@ def __init__(self, **kwargs):
def insert(self, nmap_report):
"""
insert NmapReport in the backend
+
:param NmapReport:
- :return: the ident of the object in the backend for future usage
+
+ :returns: the ident of the object in the backend for future usage \
or None
"""
sess = self.Session()
@@ -118,8 +120,10 @@ def insert(self, nmap_report):
def get(self, report_id=None):
"""
retreive a NmapReport from the backend
+
:param id: str
- :return: NmapReport
+
+ :returns: NmapReport
"""
if report_id is None:
raise ValueError
@@ -131,8 +135,9 @@ def get(self, report_id=None):
def getall(self):
"""
- :return: collection of tuple (id,NmapReport)
:param filter: Nice to have implement a filter capability
+
+ :returns: collection of tuple (id,NmapReport)
"""
sess = self.Session()
nmapreportList = []
@@ -146,8 +151,10 @@ def getall(self):
def delete(self, report_id=None):
"""
Remove a report from the backend
+
:param id: str
- :return: The number of rows deleted
+
+ :returns: The number of rows deleted
"""
if report_id is None:
raise ValueError
diff --git a/libnmap/test/test_backend_plugin_factory.py b/libnmap/test/test_backend_plugin_factory.py
index 2c983c5..2573c67 100644
--- a/libnmap/test/test_backend_plugin_factory.py
+++ b/libnmap/test/test_backend_plugin_factory.py
@@ -60,7 +60,8 @@ def setUp(self):
'url': 'sqlite:////tmp/reportdb.sql',
'echo': False},
{'plugin_name': 'sql',
- 'url': 'mysql+mysqldb://root@localhost/poulet',
+ #'url': 'mysql+mysqldb://root@localhost/poulet', (mySQL-Python not supporting python3)
+ 'url': 'mysql+pymysql://root@localhost/poulet',
'echo': False},
#Walrus
###{'plugin_name': 's3',
diff --git a/tox.ini b/tox.ini
index 21271f9..68fc97a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -2,4 +2,7 @@
envlist = py27,py34
[testenv]
deps=nose
+ pymongo
+ sqlalchemy
+ pymysql
commands=nosetests
From 7c61ee6eeb780a734e30c0385f98fb0285129dbb Mon Sep 17 00:00:00 2001
From: Ronald
Date: Wed, 18 Jun 2014 06:46:53 +0200
Subject: [PATCH 067/206] proposed fix for mysql plugin: migrate type
LargeBinary to Text
---
libnmap/plugins/sql.py | 4 ++--
libnmap/test/test_backend_plugin_factory.py | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/libnmap/plugins/sql.py b/libnmap/plugins/sql.py
index aad2f52..f0942c6 100644
--- a/libnmap/plugins/sql.py
+++ b/libnmap/plugins/sql.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
from sqlalchemy import create_engine
from sqlalchemy.schema import Column
-from sqlalchemy.types import Integer, DateTime, LargeBinary
+from sqlalchemy.types import Integer, DateTime, LargeBinary, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
@@ -53,7 +53,7 @@ class Reports(Base):
id = Column('report_id', Integer, primary_key=True)
inserted = Column('inserted', DateTime(), default='now')
- report_json = Column('report_json', LargeBinary)
+ report_json = Column('report_json', Text(convert_unicode=True))
def __init__(self, obj_NmapReport):
self.inserted = datetime.fromtimestamp(obj_NmapReport.endtime)
diff --git a/libnmap/test/test_backend_plugin_factory.py b/libnmap/test/test_backend_plugin_factory.py
index 2573c67..48da242 100644
--- a/libnmap/test/test_backend_plugin_factory.py
+++ b/libnmap/test/test_backend_plugin_factory.py
@@ -128,6 +128,7 @@ def test_backend_get(self):
result_list.append(backend.get(rep_id))
#print result_list[0]
#print self.reportList[0]
+ i=0
self.assertEqual(len(result_list), len(self.reportList))
self.assertEqual((result_list), (self.reportList))
id_list = []
From 4de764e00eda34a1b4a414200e1dad35502aa5ce Mon Sep 17 00:00:00 2001
From: Ronald
Date: Wed, 18 Jun 2014 07:01:10 +0200
Subject: [PATCH 068/206] removed flake errors
---
libnmap/plugins/sql.py | 2 +-
libnmap/test/test_backend_plugin_factory.py | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/libnmap/plugins/sql.py b/libnmap/plugins/sql.py
index f0942c6..4c18cea 100644
--- a/libnmap/plugins/sql.py
+++ b/libnmap/plugins/sql.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
from sqlalchemy import create_engine
from sqlalchemy.schema import Column
-from sqlalchemy.types import Integer, DateTime, LargeBinary, Text
+from sqlalchemy.types import Integer, DateTime, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
diff --git a/libnmap/test/test_backend_plugin_factory.py b/libnmap/test/test_backend_plugin_factory.py
index 48da242..2573c67 100644
--- a/libnmap/test/test_backend_plugin_factory.py
+++ b/libnmap/test/test_backend_plugin_factory.py
@@ -128,7 +128,6 @@ def test_backend_get(self):
result_list.append(backend.get(rep_id))
#print result_list[0]
#print self.reportList[0]
- i=0
self.assertEqual(len(result_list), len(self.reportList))
self.assertEqual((result_list), (self.reportList))
id_list = []
From bd60f1f884680cbbcae5a4d37f8869caf73a7dbe Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sun, 29 Jun 2014 00:29:35 +0200
Subject: [PATCH 069/206] fixed bug with sqlite on py3
---
libnmap/plugins/backendpluginFactory.py | 2 +-
libnmap/plugins/mongodb.py | 3 +--
libnmap/plugins/s3.py | 5 ++---
libnmap/plugins/sql.py | 12 +++++++-----
tox.ini | 2 +-
5 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/libnmap/plugins/backendpluginFactory.py b/libnmap/plugins/backendpluginFactory.py
index 84cc250..b840363 100644
--- a/libnmap/plugins/backendpluginFactory.py
+++ b/libnmap/plugins/backendpluginFactory.py
@@ -28,5 +28,5 @@ def create(cls, plugin_name="mongodb", **kwargs):
try:
backendplugin = classobj(**kwargs)
except Exception as error:
- print("Cannot create Backend: {0}".format(error))
+ raise Exception("Cannot create Backend: {0}".format(error))
return backendplugin
diff --git a/libnmap/plugins/mongodb.py b/libnmap/plugins/mongodb.py
index 6bd1ee5..657029d 100644
--- a/libnmap/plugins/mongodb.py
+++ b/libnmap/plugins/mongodb.py
@@ -36,8 +36,7 @@ def insert(self, report):
try:
oid = self.collection.insert(json.loads(j))
except:
- print("MONGODB cannot insert")
- raise
+ raise Exception("Failed to insert nmap object in MongoDB")
return str(oid)
def get(self, str_report_id=None):
diff --git a/libnmap/plugins/s3.py b/libnmap/plugins/s3.py
index efb662e..5805daa 100644
--- a/libnmap/plugins/s3.py
+++ b/libnmap/plugins/s3.py
@@ -88,8 +88,7 @@ def insert(self, report):
strjsonnmapreport = json.dumps(report, cls=ReportEncoder)
mykey.set_contents_from_string(strjsonnmapreport)
except:
- print("Bucket cannot insert")
- raise
+ raise Exception("Failed to add nmap object in s3 bucket")
return str(oid)
def get(self, str_report_id=None):
@@ -108,7 +107,7 @@ def get(self, str_report_id=None):
nmapreportjson = json.loads(mykey.get_contents_as_string())
nmapreport = NmapParser.parse_fromdict(nmapreportjson)
except S3ResponseError:
- print("Not Found")
+ pass
return nmapreport
def getall(self, dict_filter=None):
diff --git a/libnmap/plugins/sql.py b/libnmap/plugins/sql.py
index 4c18cea..57f1415 100644
--- a/libnmap/plugins/sql.py
+++ b/libnmap/plugins/sql.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
from sqlalchemy import create_engine
from sqlalchemy.schema import Column
-from sqlalchemy.types import Integer, DateTime, Text
+from sqlalchemy.types import Integer, DateTime, LargeBinary
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
@@ -53,15 +53,17 @@ class Reports(Base):
id = Column('report_id', Integer, primary_key=True)
inserted = Column('inserted', DateTime(), default='now')
- report_json = Column('report_json', Text(convert_unicode=True))
+ report_json = Column('report_json', LargeBinary())
def __init__(self, obj_NmapReport):
self.inserted = datetime.fromtimestamp(obj_NmapReport.endtime)
- self.report_json = json.dumps(obj_NmapReport,
- cls=ReportEncoder)
+ dumped_json = json.dumps(obj_NmapReport,
+ cls=ReportEncoder)
+ self.report_json = bytes(dumped_json.encode('UTF-8'))
def decode(self):
- nmap_report_obj = json.loads(self.report_json,
+ json_decoded = self.report_json.decode('utf-8')
+ nmap_report_obj = json.loads(json_decoded,
cls=ReportDecoder)
return nmap_report_obj
diff --git a/tox.ini b/tox.ini
index 68fc97a..8ea1651 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py27,py34
+envlist = py27,py32
[testenv]
deps=nose
pymongo
From d8cdc0aa236864a7cbb38106712e4c61d6a36e83 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sun, 29 Jun 2014 00:53:33 +0200
Subject: [PATCH 070/206] libnmap fully supports python2.6 -> 3.4
---
libnmap/__init__.py | 2 +-
setup.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libnmap/__init__.py b/libnmap/__init__.py
index d4985e7..431a582 100644
--- a/libnmap/__init__.py
+++ b/libnmap/__init__.py
@@ -5,4 +5,4 @@
__maintainer__ = 'Ronald Bister'
__email__ = 'mini.pelle@gmail.com'
__license__ = 'CC-BY'
-__version__ = '0.6'
+__version__ = '0.6.1'
diff --git a/setup.py b/setup.py
index 8f8d6de..83af514 100644
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@
setup(
name='python-libnmap',
- version='0.6',
+ version='0.6.1',
author='Ronald Bister',
author_email='mini.pelle@gmail.com',
packages=['libnmap', 'libnmap.plugins', 'libnmap.objects'],
From bb741f017e9d83404a68e985236fa531656fe4c5 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sun, 29 Jun 2014 23:41:06 +0200
Subject: [PATCH 071/206] elastic search plugin and example code to push data
---
examples/es_plugin.py | 18 +++++++++
examples/kibana.py | 90 +++++++++++++++++++++++++++++++++++++++++++
libnmap/plugins/es.py | 67 ++++++++++++++++++++++++++++++++
3 files changed, 175 insertions(+)
create mode 100644 examples/es_plugin.py
create mode 100644 examples/kibana.py
create mode 100644 libnmap/plugins/es.py
diff --git a/examples/es_plugin.py b/examples/es_plugin.py
new file mode 100644
index 0000000..e2de9da
--- /dev/null
+++ b/examples/es_plugin.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+
+from libnmap.parser import NmapParser
+from libnmap.reportjson import ReportDecoder
+from libnmap.plugins.es import NmapElasticsearchPlugin
+from datetime import datetime
+import json
+
+nmap_report = NmapParser.parse_fromfile('libnmap/test/files/1_hosts.xml')
+mindex = datetime.fromtimestamp(nmap_report.started).strftime('%Y-%m-%d')
+db = NmapElasticsearchPlugin(index=mindex)
+dbid = db.insert(nmap_report)
+nmap_json = db.get(dbid)
+
+nmap_obj = json.loads(json.dumps(nmap_json), cls=ReportDecoder)
+print(nmap_obj)
+#print(db.getall())
+
diff --git a/examples/kibana.py b/examples/kibana.py
new file mode 100644
index 0000000..b9ece8a
--- /dev/null
+++ b/examples/kibana.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from libnmap.parser import NmapParser
+from libnmap.reportjson import ReportDecoder
+from libnmap.plugins.es import NmapElasticsearchPlugin
+from datetime import datetime
+import json
+
+
+def report_store(nmap_report, database):
+ jhostlist = []
+ for nmap_host in nmap_report.hosts:
+ jhost = host_store(nmap_host, database)
+ jhostlist.append(jhost)
+
+ for jhost in jhostlist:
+ database.insert(jhost, doc_type="NmapHost")
+
+ return jhostlist
+
+
+def get_os(nmap_host):
+ rval = {'os': '', 'accuracy': 0}
+ if nmap_host.is_up() and nmap_host.os_fingerprinted:
+ os_list = []
+ for osm in nmap_host.os.osmatches:
+ os_list.append({"os": osm.name, "accuracy": osm.accuracy})
+ os_list.sort(key=lambda x: x['accuracy'], reverse=True)
+
+ if len(os_list):
+ rval.update(os_list[0])
+ return rval
+
+
+def host_store(nmap_host, database):
+ host_keys = ["starttime", "endtime", "address", "hostnames",
+ "ipv4", "ipv6", "mac", "status"]
+ jhost = {}
+ for hkey in host_keys:
+ if hkey == "starttime" or hkey == "endtime":
+ val = getattr(nmap_host, hkey)
+ jhost[hkey] = int(val) if len(val) else 0
+ else:
+ jhost[hkey] = getattr(nmap_host, hkey)
+
+ for nmap_service in nmap_host.services:
+ reportitems = item_store(nmap_service, database)
+
+ for ritem in reportitems:
+ ritem.update(jhost)
+ database.insert(ritem, doc_type="ReportItem")
+
+ jhost.update(get_os(nmap_host))
+ return jhost
+
+def item_store(nmap_service, database):
+ service_keys = ["port", "protocol", "state"]
+ ritems = []
+
+ # create report item for basic port scan
+ jservice = {}
+ for skey in service_keys:
+ jservice[skey] = getattr(nmap_service, skey)
+ jservice['type'] = 'port-scan'
+ jservice['service'] = nmap_service.service
+ jservice['service-data'] = nmap_service.banner
+ ritems.append(jservice)
+
+ # create report items from nse script output
+ for nse_item in nmap_service.scripts_results:
+ jnse = {}
+ for skey in service_keys:
+ jnse[skey] = getattr(nmap_service, skey)
+ jnse['type'] = 'nse-script'
+ jnse['service'] = nse_item['id']
+ jnse['service-data'] = nse_item['output']
+ ritems.append(jnse)
+
+ return ritems
+
+
+xmlscans = ['../libnmap/test/files/1_hosts.xml', '../libnmap/test/files/full_sudo6.xml']
+for xmlscan in xmlscans:
+ nmap_report = NmapParser.parse_fromfile(xmlscan)
+
+ if nmap_report:
+ mindex = datetime.fromtimestamp(nmap_report.started).strftime('%Y-%m-%d')
+ db = NmapElasticsearchPlugin(index=mindex)
+ j = report_store(nmap_report, db)
diff --git a/libnmap/plugins/es.py b/libnmap/plugins/es.py
new file mode 100644
index 0000000..7ce3869
--- /dev/null
+++ b/libnmap/plugins/es.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+
+import json
+
+from libnmap.reportjson import ReportDecoder, ReportEncoder
+from libnmap.plugins.backendplugin import NmapBackendPlugin
+from elasticsearch import Elasticsearch
+from datetime import datetime
+
+
+class NmapElasticsearchPlugin(NmapBackendPlugin):
+ """
+ This class enables the user to store and manipulate nmap reports \
+ in a elastic search db.
+ """
+ def __init__(self, index=None):
+ if index is None:
+ self.index = datetime.now().strftime('%Y-%m-%d')
+ else:
+ self.index = index
+ self._esapi = Elasticsearch()
+
+ def insert(self, report, doc_type=None):
+ """
+ insert NmapReport in the backend
+ :param NmapReport:
+ :return: str the ident of the object in the backend for
+ future usage
+ or None
+ """
+ if doc_type is None:
+ doc_type = 'NmapReport'
+ j = json.dumps(report, cls=ReportEncoder)
+ res = self._esapi.index(
+ index=self.index,
+ doc_type=doc_type,
+ body=json.loads(j))
+ rc = res['_id']
+ return rc
+
+ def delete(self, id):
+ """
+ delete NmapReport if the backend
+ :param id: str
+ """
+ raise NotImplementedError
+
+ def get(self, id):
+ """
+ retreive a NmapReport from the backend
+ :param id: str
+ :return: NmapReport
+ """
+ res = self._esapi.get(index=self.index, doc_type="NmapReport", id=id)['_source']
+ return res
+
+
+ def getall(self, filter=None):
+ """
+ :return: collection of tuple (id,NmapReport)
+ :param filter: Nice to have implement a filter capability
+ """
+ rsearch = self._esapi.search(index=self.index, body={"query": {"match_all": {}}})
+ print("--------------------")
+ print(type(rsearch))
+ print(rsearch)
+ print("------------")
From 1b9ad5e573f3cfe93167405e00643e824d94af2b Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sat, 5 Jul 2014 10:30:47 +0000
Subject: [PATCH 072/206] fixed kibana import script and added method for cpe
list
---
examples/kibana.py | 67 ++++++++++++++++++++++++-------------------
libnmap/objects/os.py | 7 +++++
libnmap/plugins/es.py | 5 ++--
3 files changed, 46 insertions(+), 33 deletions(-)
diff --git a/examples/kibana.py b/examples/kibana.py
index b9ece8a..6710594 100644
--- a/examples/kibana.py
+++ b/examples/kibana.py
@@ -2,59 +2,62 @@
# -*- coding: utf-8 -*-
from libnmap.parser import NmapParser
-from libnmap.reportjson import ReportDecoder
-from libnmap.plugins.es import NmapElasticsearchPlugin
+from elasticsearch import Elasticsearch
from datetime import datetime
-import json
+import pygeoip
-def report_store(nmap_report, database):
- jhostlist = []
+def store_report(nmap_report, database, index):
+ rval = True
for nmap_host in nmap_report.hosts:
- jhost = host_store(nmap_host, database)
- jhostlist.append(jhost)
+ rv = store_reportitem(nmap_host, database, index)
+ if rv is False:
+ print("Failed to store host {0} in elasticsearch".format(nmap_host.address))
+ rval = False
- for jhost in jhostlist:
- database.insert(jhost, doc_type="NmapHost")
-
- return jhostlist
+ return rval
def get_os(nmap_host):
- rval = {'os': '', 'accuracy': 0}
+ rval = {'vendor': 'unknown', 'product': 'unknown'}
if nmap_host.is_up() and nmap_host.os_fingerprinted:
- os_list = []
- for osm in nmap_host.os.osmatches:
- os_list.append({"os": osm.name, "accuracy": osm.accuracy})
- os_list.sort(key=lambda x: x['accuracy'], reverse=True)
-
- if len(os_list):
- rval.update(os_list[0])
+ cpelist = nmap_host.os.os_cpelist()
+ if len(cpelist):
+ mcpe = cpelist.pop()
+ rval.update({'vendor': mcpe.get_vendor(), 'product': mcpe.get_product()})
return rval
-def host_store(nmap_host, database):
+def get_geoip_code(address):
+ gi = pygeoip.GeoIP('/usr/share/GeoIP/GeoIP.dat')
+ return gi.country_code_by_addr(address)
+
+
+def store_reportitem(nmap_host, database, index):
host_keys = ["starttime", "endtime", "address", "hostnames",
"ipv4", "ipv6", "mac", "status"]
jhost = {}
for hkey in host_keys:
if hkey == "starttime" or hkey == "endtime":
val = getattr(nmap_host, hkey)
- jhost[hkey] = int(val) if len(val) else 0
+ jhost[hkey] = datetime.fromtimestamp(int(val) if len(val) else 0)
else:
jhost[hkey] = getattr(nmap_host, hkey)
+ jhost.update({'country': get_geoip_code(nmap_host.address)})
+ jhost.update(get_os(nmap_host))
for nmap_service in nmap_host.services:
- reportitems = item_store(nmap_service, database)
+ reportitems = get_item(nmap_service)
for ritem in reportitems:
ritem.update(jhost)
- database.insert(ritem, doc_type="ReportItem")
-
- jhost.update(get_os(nmap_host))
+ database.index(index=index,
+ doc_type="NmapItem",
+ body=ritem)
return jhost
-def item_store(nmap_service, database):
+
+def get_item(nmap_service):
service_keys = ["port", "protocol", "state"]
ritems = []
@@ -80,11 +83,15 @@ def item_store(nmap_service, database):
return ritems
-xmlscans = ['../libnmap/test/files/1_hosts.xml', '../libnmap/test/files/full_sudo6.xml']
+xmlscans = ['../libnmap/test/files/1_hosts.xml',
+ '../libnmap/test/files/full_sudo6.xml',
+ '/vagrant/nmap_switches.xml',
+ '/vagrant/nmap-5hosts.xml'
+ ]
for xmlscan in xmlscans:
nmap_report = NmapParser.parse_fromfile(xmlscan)
if nmap_report:
- mindex = datetime.fromtimestamp(nmap_report.started).strftime('%Y-%m-%d')
- db = NmapElasticsearchPlugin(index=mindex)
- j = report_store(nmap_report, db)
+ index = "nmap.{0}".format(datetime.fromtimestamp(int(nmap_report.started)).strftime('nmap.%Y-%m-%d'))
+ db = Elasticsearch()
+ j = store_report(nmap_report, db, index)
diff --git a/libnmap/objects/os.py b/libnmap/objects/os.py
index 514dea1..9e52fcc 100644
--- a/libnmap/objects/os.py
+++ b/libnmap/objects/os.py
@@ -376,6 +376,13 @@ def osclass(self, min_accuracy=90):
os_array.append(_ftstr)
return os_array
+ def os_cpelist(self):
+ cpelist = []
+ for _osmatch in self.osmatches:
+ for oclass in _osmatch.osclasses:
+ cpelist.extend(oclass.cpelist)
+ return cpelist
+
def __repr__(self):
rval = ""
for _osmatch in self.osmatches:
diff --git a/libnmap/plugins/es.py b/libnmap/plugins/es.py
index 7ce3869..749953c 100644
--- a/libnmap/plugins/es.py
+++ b/libnmap/plugins/es.py
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
import json
-
-from libnmap.reportjson import ReportDecoder, ReportEncoder
+from libnmap.reportjson import ReportEncoder
from libnmap.plugins.backendplugin import NmapBackendPlugin
from elasticsearch import Elasticsearch
from datetime import datetime
@@ -15,7 +14,7 @@ class NmapElasticsearchPlugin(NmapBackendPlugin):
"""
def __init__(self, index=None):
if index is None:
- self.index = datetime.now().strftime('%Y-%m-%d')
+ self.index = "nmap.{0}".format(datetime.now().strftime('%Y-%m-%d'))
else:
self.index = index
self._esapi = Elasticsearch()
From a9ba459d02ce7b51311f5903f5f5d23ed008675c Mon Sep 17 00:00:00 2001
From: orf
Date: Mon, 8 Sep 2014 12:24:05 +0100
Subject: [PATCH 073/206] Fix TypeError in extraports_* functions
Sometimes there is no extraports tag. In this case a TypeError is raised, which is confusing. Either a proper exception (MissingExtraports or something) should be raised, or None returned. This patch does the latter.
---
libnmap/objects/host.py | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 03181c9..391b80f 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -434,9 +434,12 @@ def extraports_state(self):
dictionnary containing state and amount of extra ports scanned
for which a common state, usually, closed was discovered.
- :return: dict with keys 'state' and 'count'
+ :return: dict with keys 'state' and 'count' or None
"""
_xtrports = self._extras['extraports']
+ if _xtrports is None:
+ return None
+
return {'state': _xtrports['state'], 'count': _xtrports['count']}
@property
@@ -445,9 +448,13 @@ def extraports_reasons(self):
dictionnary containing reasons why extra ports scanned
for which a common state, usually, closed was discovered.
- :return: array of dict containing keys 'state' and 'count'
+ :return: array of dict containing keys 'state' and 'count' or None
"""
- return self._extras['extraports']['reasons']
+ r = self._extras['extraports']
+ if r is None:
+ return None
+
+ return r['reasons']
def get_dict(self):
"""
From ba3ae6ff0904511ac5e0f49eef8863382b2ca61f Mon Sep 17 00:00:00 2001
From: orf
Date: Mon, 8 Sep 2014 12:26:36 +0100
Subject: [PATCH 074/206] Update host.py
---
libnmap/objects/host.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 391b80f..f45ce8e 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -436,7 +436,7 @@ def extraports_state(self):
:return: dict with keys 'state' and 'count' or None
"""
- _xtrports = self._extras['extraports']
+ _xtrports = self._extras.get('extraports', None)
if _xtrports is None:
return None
@@ -450,7 +450,7 @@ def extraports_reasons(self):
:return: array of dict containing keys 'state' and 'count' or None
"""
- r = self._extras['extraports']
+ r = self._extras.get('extraports', None)
if r is None:
return None
From 7be7f5950f997bd56f1f3d10b37a6c4a5af07c20 Mon Sep 17 00:00:00 2001
From: orf
Date: Thu, 11 Sep 2014 10:55:35 +0100
Subject: [PATCH 075/206] Update host.py
---
libnmap/objects/host.py | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index f45ce8e..3706ec4 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -437,9 +437,10 @@ def extraports_state(self):
:return: dict with keys 'state' and 'count' or None
"""
_xtrports = self._extras.get('extraports', None)
+
if _xtrports is None:
return None
-
+
return {'state': _xtrports['state'], 'count': _xtrports['count']}
@property
@@ -450,11 +451,9 @@ def extraports_reasons(self):
:return: array of dict containing keys 'state' and 'count' or None
"""
- r = self._extras.get('extraports', None)
- if r is None:
- return None
-
- return r['reasons']
+ r = self._extras.get('extraports', {})
+
+ return r.get('reasons', None)
def get_dict(self):
"""
From 24196eaf6846afc11ec767eb98969e8bae082f1d Mon Sep 17 00:00:00 2001
From: loopmachine
Date: Fri, 10 Oct 2014 17:35:59 -0400
Subject: [PATCH 076/206] Fixed NmapService.tunnel handling
---
libnmap/objects/service.py | 2 +-
libnmap/test/test_service.py | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/libnmap/objects/service.py b/libnmap/objects/service.py
index 631bcec..6e134df 100644
--- a/libnmap/objects/service.py
+++ b/libnmap/objects/service.py
@@ -64,7 +64,7 @@ def __init__(self, portid, protocol='tcp', state=None,
if 'servicefp' in self._service:
self._servicefp = self._service['servicefp']
if 'tunnel' in self._service:
- self._servicefp = self._service['tunnel']
+ self._tunnel = self._service['tunnel']
self._service_extras = []
if service_extras is not None:
diff --git a/libnmap/test/test_service.py b/libnmap/test/test_service.py
index 1d3a7aa..4d0ec01 100644
--- a/libnmap/test/test_service.py
+++ b/libnmap/test/test_service.py
@@ -160,6 +160,11 @@
"""
+port_tunnel = """
+
+
+
+"""
class TestNmapService(unittest.TestCase):
def setUp(self):
@@ -243,6 +248,10 @@ def test_owner(self):
serviceowner = NmapParser.parse(port_owner)
self.assertEqual(serviceowner.owner, "edwige")
+ def test_tunnel(self):
+ servicetunnel = NmapParser.parse(port_tunnel)
+ self.assertEqual(servicetunnel.tunnel, "ssl")
+
if __name__ == '__main__':
test_suite = ['test_port_state_changed', 'test_port_state_unchanged',
From 7303a5e3d0154adeb152561030875d8d786ef2ca Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sat, 22 Nov 2014 17:58:45 +0000
Subject: [PATCH 077/206] fix bug #43
---
libnmap/objects/host.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 3706ec4..1ae0669 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -316,7 +316,7 @@ def os_fingerprint(self):
"""
rval = ''
if self.os is not None:
- rval = self.os.fingerprints.join("\n")
+ rval = "\n".join(self.os.fingerprints)
return rval
def os_ports_used(self):
From 1e0c3526f2724e009c8a03ae4f6ef00404dda542 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sat, 22 Nov 2014 18:07:51 +0000
Subject: [PATCH 078/206] issue 42: added NmapHost.vendor
---
libnmap/objects/host.py | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/libnmap/objects/host.py b/libnmap/objects/host.py
index 1ae0669..ffa3596 100644
--- a/libnmap/objects/host.py
+++ b/libnmap/objects/host.py
@@ -40,6 +40,7 @@ def __init__(self, starttime='', endtime='', address=None, status=None,
self._ipv4_addr = None
self._ipv6_addr = None
self._mac_addr = None
+ self._vendor = None
for addr in address:
if addr['addrtype'] == "ipv4":
self._ipv4_addr = addr['addr']
@@ -47,6 +48,8 @@ def __init__(self, starttime='', endtime='', address=None, status=None,
self._ipv6_addr = addr['addr']
elif addr['addrtype'] == 'mac':
self._mac_addr = addr['addr']
+ if 'vendor' in addr:
+ self._vendor = addr['vendor']
self._main_address = self._ipv4_addr or self._ipv6_addr or ''
self._address = address
@@ -147,8 +150,10 @@ def address(self, addrdict):
self._ipv4_addr = addrdict['addr']
elif addrdict['addrtype'] == 'ipv6':
self._ipv6_addr = addrdict['addr']
- if addrdict['addrtype'] == 'mac':
+ elif addrdict['addrtype'] == 'mac':
self._mac_addr = addrdict['addr']
+ if 'vendor' in addrdict:
+ self._vendor = addrdict['vendor']
self._main_address = self._ipv4_addr or self._ipv6_addr or ''
self._address = addrdict
@@ -171,6 +176,15 @@ def mac(self):
"""
return self._mac_addr or ''
+ @property
+ def vendor(self):
+ """
+ Accessor for the vendor attribute of the scanned host
+
+ :return: string (vendor) of empty string if no vendor defined
+ """
+ return self._vendor or ''
+
@property
def ipv6(self):
"""
From cb188a369cc852320a12d76d8954d62b5b0da178 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sat, 22 Nov 2014 18:15:38 +0000
Subject: [PATCH 079/206] issue37: added NmapService.service_dict
---
libnmap/objects/service.py | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/libnmap/objects/service.py b/libnmap/objects/service.py
index 6e134df..11d4726 100644
--- a/libnmap/objects/service.py
+++ b/libnmap/objects/service.py
@@ -177,12 +177,21 @@ def reason_ttl(self):
@property
def service(self):
"""
- Accessor for service dictionnary.
+ Accessor for service name.
- :return: dict or None
+ :return: string or empty
"""
return self._service['name'] if 'name' in self._service else ''
+ @property
+ def service_dict(self):
+ """
+ Accessor for service dictionary.
+
+ :return: dict or None
+ """
+ return self._service
+
def open(self):
"""
Tells if the port was open or not
From 7268a4ee957e4081675e5fb1095a98f8260a3959 Mon Sep 17 00:00:00 2001
From: Ronald
Date: Sat, 22 Nov 2014 20:01:01 +0000
Subject: [PATCH 080/206] added kibana/es example and fixed cpe
---
README.rst | 6 ++++++
examples/{kibana.py => elastikibana.py} | 13 ++++++++-----
examples/kibanalibnmap.png | Bin 0 -> 321878 bytes
3 files changed, 14 insertions(+), 5 deletions(-)
rename examples/{kibana.py => elastikibana.py} (87%)
create mode 100644 examples/kibanalibnmap.png
diff --git a/README.rst b/README.rst
index e9a6fca..2a2d756 100644
--- a/README.rst
+++ b/README.rst
@@ -85,6 +85,12 @@ Examples
Some codes samples are available in the examples directory or in the `documentation`_.
+Among other example, you notice an sample code pushing nmap scan reports in an ElasticSearch instance and allowing you to create fancy dashboards in Kibana like the screenshot below:
+
+..image:: https://raw.github.com/savon-noir/python-libnmap/master/examples/kibanalibnmap.png
+ :alt: Kibanane
+ :align: center
+
Contributors
------------
diff --git a/examples/kibana.py b/examples/elastikibana.py
similarity index 87%
rename from examples/kibana.py
rename to examples/elastikibana.py
index 6710594..4b9774b 100644
--- a/examples/kibana.py
+++ b/examples/elastikibana.py
@@ -12,7 +12,8 @@ def store_report(nmap_report, database, index):
for nmap_host in nmap_report.hosts:
rv = store_reportitem(nmap_host, database, index)
if rv is False:
- print("Failed to store host {0} in elasticsearch".format(nmap_host.address))
+ print("Failed to store host {0} in "
+ "elasticsearch".format(nmap_host.address))
rval = False
return rval
@@ -24,7 +25,8 @@ def get_os(nmap_host):
cpelist = nmap_host.os.os_cpelist()
if len(cpelist):
mcpe = cpelist.pop()
- rval.update({'vendor': mcpe.get_vendor(), 'product': mcpe.get_product()})
+ rval.update({'vendor': mcpe.get_vendor(),
+ 'product': mcpe.get_product()})
return rval
@@ -86,12 +88,13 @@ def get_item(nmap_service):
xmlscans = ['../libnmap/test/files/1_hosts.xml',
'../libnmap/test/files/full_sudo6.xml',
'/vagrant/nmap_switches.xml',
- '/vagrant/nmap-5hosts.xml'
- ]
+ '/vagrant/nmap-5hosts.xml']
+
for xmlscan in xmlscans:
nmap_report = NmapParser.parse_fromfile(xmlscan)
if nmap_report:
- index = "nmap.{0}".format(datetime.fromtimestamp(int(nmap_report.started)).strftime('nmap.%Y-%m-%d'))
+ rep_date = datetime.fromtimestamp(int(nmap_report.started))
+ index = "nmap-{0}".format(rep_date.strftime('%Y-%m-%d'))
db = Elasticsearch()
j = store_report(nmap_report, db, index)
diff --git a/examples/kibanalibnmap.png b/examples/kibanalibnmap.png
new file mode 100644
index 0000000000000000000000000000000000000000..8d5bed4ee9415308196b4a6166c5521e6a12aff6
GIT binary patch
literal 321878
zcmd432UJsC*De~07?F~o(gcA30!o$M5rZ@VK>_K#OYgly=u)H?1pxs8>77XLAiX!~
zy%RcTqwjbA_aFB==l$*&_uO$ZFl<+L*4}%TXFhYTxd?hKD~^jziVXsRa3v++3Lp^1
zH3)?62Sx`*X7eeXC$!Cm+fHwXCs;RERLpivT%)=nN@Ke)v&)`G74
zTqIcP-iOB$;$Iw1K4ZcOL|noS)9GO{ukYW2zx`&%ib3P;N8|d;zVPV6YvpKlgQ0%s
z+I?kkLlqSk=D2KSX(R7YT}3?^8H3)qe}0*m<(*C+{QJk#S`^&G>L!$Cl9+7!zLq`E
zH9Dktu!np+{L6hv?Cj1c2kw0_`QJaMA@@Xy1LhA-UkxrM>n)`4P9>?wq*!dXJJ4i$
zeZTNPW|@5YYt~M!WJn_`PFkN);^P&vhdbT#GmGh)cDCZ>)C{-$mQd%MG8li&Du4CM
z4-%kr;wCi6!Mif%WQ2!$Ok|Lq#9vG<$w0}7oGmmV{cG0XeIhzPR-C4lgM_RO-nLeL
z+e+>#dj9FD$SnyeG@a8+51B!cKldts)rkN@(Yz24=v5jF=HOe42Avlc1?vz8^sTVV
zMB9e{Td_1)LP3obVwhfDyHDX>U?e3v{DcM5O9TY=B!*JKF64n@OvJ7$@Yyvfl+x#q
z6!%BH5u#wYekc@rfe(ek8gWIzpt8mbn$BXQVPJat_|6CGBpEuL
z7RC^-HLjEfdpL}+4D8{{_QeduSrCc1gD$d|SitrYMtIK${K2~SHMTUt1@<#61%icY
zUU`n;CLF5R&%Zt#;1lVey>KWLREag9?yT6bA?g;%UoQ5XM*1kY55Yf
z)cNr#0|NsS)3D{Ihk%%gVZklB$p^&-T{gWeTJ>ZhEp{5>aF{6k1OtI!BgFPM9r-q%
zAs*p;u$&^`Jg{ab#Q=p~(E)0jr=SAFG7J4D>)O4GE`s@#>{Sl?_iL|}?L2x(zk*Z^
zRywn;nWoejwF#uaeuC;SF27&!#m+Zpy{pz2Ts4mvJ~9j^^|Y_9eZE@~7%_vIR>@bL
z7HVo0&`8pfbeW_8)LswhXx@YNG?8Lzk
z);V>g%W3!g&RUhx&Y9bIduUmje3sdAW4
z3|UlA{|dTCrH@|HhyVGPn*Y_Te0im>~H9B@`pTavy)f}Lf&f(A*XjM
zTx3=FinNk2>5!%F$Dt9ujugjdEcfzW8M&&`g%-RLRYS}5*LP&5O(>=A
za;iD4N6YnG?pJO*ph5rTJ4$d&5PT?Kts;_IT(j1xNG?qX_aPSv=K(+
zf_KsI6=|_EF%cvXQ2w*Umx;pSjn%ncf+eGA{QEmi?mT8=tB%1X<;=*c)rDjHvTLbP
zdxm(Wy&OY(VrjGf>Md%=8V5szZKM<1+wx;+jhdPFqf?9ZN9@W$ps;|Z
zc{PiwmL;35sj3piJSBFc-p$d%*>dyAL=F?1qxE56fQJn4#+w}>Y!L8Jp_b=hmdveN
zx9-u&cK7wAJu?7QtaygnL0T`o3~WL}QvXx%oFhU!Q^@^@q;~JmTCp7U;HljiT)4Fu
z#(#Q+?RZ&VSnBe`=z5=s|M2wLuUrSmy5l~s>WeL-9Shf*SJB;DwtO+kNRh8`g%IwQ
z)4<|j3$03H$tIg3-5Tzz&1`lqH>Dc)H1TAuvi!;8uQDYVQjo~>DS`Z%4QXYZ_v?xM
zn=?B6%ri3oZYfct6plIUdPoHtTPZ
zVK|IPo-DCAz*pzySndWOjzzD#QNi{U4_1`S`Ax@5=MDPmxXpXh`B(}q
zG^yN%x5N0$JkOR{9<2{$%N{m`Z)sW9>6^EymA%O0_E3F|=;a~YXX%+ye@8rIkLC3j
zueng6N;gT=YYX23^vpw+%47ZO>hk