diff --git a/CHANGES.txt b/CHANGES.txt index c8ed515..73194bc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,8 @@ +v0.4.7, 03/05/2014 -- minor fix for issue25 + - fixed exception when optional service tag is not present + in tag + - added support for if present in : + accessible via NmapService.owner v0.4.6, 06/04/2014 -- minor fix - corrected missing incomplete parameter on parse_fromfile and parse_fromstring diff --git a/libnmap/objects/service.py b/libnmap/objects/service.py index 870dafa..95efb1a 100644 --- a/libnmap/objects/service.py +++ b/libnmap/objects/service.py @@ -11,7 +11,7 @@ class NmapService(object): available or not. Like banner or extra datas from NSE (nmap scripts). """ def __init__(self, portid, protocol='tcp', state=None, - service=None, service_extras=None): + service=None, owner=None, service_extras=None): """ Constructor @@ -37,6 +37,10 @@ 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._owner = '' + if owner is not None and 'name' in owner: + self._owner = owner['name'] + self._reason = '' self._reason_ip = '' self._reason_ttl = '' @@ -170,7 +174,7 @@ def service(self): :return: dict or None """ - return self._service['name'] if 'name' in self._service else None + return self._service['name'] if 'name' in self._service else '' def open(self): """ @@ -180,6 +184,13 @@ def open(self): """ return 'state' in self._state and self._state['state'] == 'open' + @property + def owner(self): + """ + Accessor for service owner if available + """ + return self._owner + @property def banner(self): """ diff --git a/libnmap/parser.py b/libnmap/parser.py index 54f14bf..88a3dc2 100644 --- a/libnmap/parser.py +++ b/libnmap/parser.py @@ -386,6 +386,7 @@ def _parse_xml_port(cls, scanport_data): _state = None _service = None + _owner = None _service_scripts = [] _service_extras = {} for xport in xelement: @@ -393,21 +394,23 @@ def _parse_xml_port(cls, scanport_data): _state = cls.__format_attributes(xport) elif xport.tag == 'service': _service = cls.__format_attributes(xport) + elif xport.tag == 'owner': + _owner = cls.__format_attributes(xport) elif xport.tag == 'script': _script_dict = cls.__parse_script(xport) _service_scripts.append(_script_dict) _service_extras['scripts'] = _service_scripts - if(_portid is None or _protocol is None - or _state is None or _service is None): + if(_portid is None or _protocol is None or _state is None): raise NmapParserException("XML tag is incomplete. One " "of the following tags is missing: " - "portid, protocol state or service.") + "portid, protocol or state or tag.") nport = NmapService(_portid, _protocol, _state, _service, + _owner, _service_extras) return nport diff --git a/libnmap/test/test_service.py b/libnmap/test/test_service.py index 67fdfd2..a4d4dea 100644 --- a/libnmap/test/test_service.py +++ b/libnmap/test/test_service.py @@ -146,6 +146,19 @@ """ +port_noservice = """ + + +""" + +port_owner = """ + + + + +""" + class TestNmapService(unittest.TestCase): def setUp(self): @@ -221,6 +234,15 @@ def test_diff_reason(self): ddict = nservice12.diff(nservice13) self.assertEqual(ddict.changed(), set(['reason'])) + def test_noservice(self): + noservice = NmapParser.parse(port_noservice) + self.assertEqual(noservice.service, "") + + def test_owner(self): + serviceowner = NmapParser.parse(port_owner) + self.assertEqual(serviceowner.owner, "edwige") + + if __name__ == '__main__': test_suite = ['test_port_state_changed', 'test_port_state_unchanged', 'test_port_service_changed', 'test_eq_service',