Skip to content

Commit b9b8134

Browse files
committed
* Raise Exception if nmap scan return non zero exit code
* Add "sudo" for scan types, which require root privileges automatically
1 parent c3ed5cd commit b9b8134

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

nmap3/exceptions.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,7 @@ class NmapXMLParserError(Exception):
4141
def __init__(self, message="Unable to parse xml output"):
4242
self.message = message
4343
super().__init__(message)
44-
44+
45+
class NmapExecutionError(Exception):
46+
"""Exception raised when en error occurred during nmap call"""
47+

nmap3/nmap3.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from nmap3.nmapparser import NmapCommandParser
3232
from xml.etree import ElementTree as ET
3333
from xml.etree.ElementTree import ParseError
34-
from nmap3.exceptions import NmapNotInstalledError, NmapXMLParserError
34+
from nmap3.exceptions import NmapNotInstalledError, NmapXMLParserError, NmapExecutionError
3535
import xml
3636

3737
__author__ = 'Wangolo Joel (info@nmapper.com)'
@@ -58,13 +58,23 @@ def __init__(self, path=None):
5858
self.top_ports = dict()
5959
self.parser = NmapCommandParser(None)
6060
self.raw_ouput = None
61+
self.as_root = False
62+
63+
def require_root(self, required=True):
64+
"""
65+
Call this method to add "sudo" in front of nmap call
66+
"""
67+
self.as_root = required
6168

6269
def default_command(self):
6370
"""
6471
Returns the default nmap command
6572
that will be chained with all others
6673
eg nmap -oX -
6774
"""
75+
if self.as_root:
76+
return self.default_command_privileged()
77+
6878
return self.default_args.format(nmap=self.nmaptool, outarg="-oX")
6979

7080
def default_command_privileged(self):
@@ -244,19 +254,23 @@ def run_command(self, cmd):
244254
245255
@param: cmd--> the command we want run eg /usr/bin/nmap -oX - nmmapper.com --top-ports 10
246256
"""
247-
if(os.path.exists(self.nmaptool)):
248-
sub_proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
257+
if (os.path.exists(self.nmaptool)):
258+
print(cmd)
259+
sub_proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
249260
try:
250261
output, errs = sub_proc.communicate()
251262
except Exception as e:
252263
sub_proc.kill()
253-
raise(e)
264+
raise (e)
254265
else:
266+
if 0 != sub_proc.returncode:
267+
raise NmapExecutionError(errs.decode('utf8'))
268+
255269
# Response is bytes so decode the output and return
256270
return output.decode('utf8').strip()
257271
else:
258272
raise NmapNotInstalledError()
259-
273+
260274
def get_xml_et(self, command_output):
261275
"""
262276
@ return xml ET
@@ -330,6 +344,8 @@ def nmap_fin_scan(self, target, args=None):
330344
@cmd nmap -sF 192.168.178.1
331345
332346
"""
347+
self.require_root()
348+
333349
xml_root = self.scan_command(self.fin_scan, target=target, args=args)
334350

335351
fin_results = self.parser.parse_nmap_idlescan(xml_root)
@@ -342,6 +358,7 @@ def nmap_syn_scan(self, target, args=None):
342358
343359
@cmd nmap -sS 192.168.178.1
344360
"""
361+
self.require_root()
345362
xml_root = self.scan_command(self.sync_scan, target=target, args=args)
346363

347364
# Use the top_port_parser
@@ -368,9 +385,11 @@ def nmap_udp_scan(self, target, args=None):
368385
369386
@cmd nmap -sU 192.168.178.1
370387
"""
388+
self.require_root()
389+
371390
if(args):
372391
assert(isinstance(args, str)), "Expected string got {0} instead".format(type(args))
373-
392+
374393
xml_root = self.scan_command(self.udp_scan, target=target, args=args)
375394

376395
tcp_results = self.parser.filter_top_ports(xml_root)

0 commit comments

Comments
 (0)