root/trunk/umitCore/NmapParser.py @ 1306

Revision 1306, 47.7 kB (checked in by boltrix, 6 years ago)

More work on installers, umitCore.Paths and umitCore.Logging which now has been renamed to umitCore.UmitLogging?. Windows installers are working fine, yet, a script updating the Paths's configuration is need as well as more test on it. Also, Linux installers seens to be working fine. The Mac OS X App generator is half-way done, and have some issues while importing cairo yet. Also, hardcoded the paths to umitCore.Paths and made a basic test suite to ensure that it is working. More testing is needed, and probably some minor bugs shal raise.

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4# Copyright (C) 2005 Insecure.Com LLC.
5#
6# Author: Adriano Monteiro Marques <py.adriano@gmail.com>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22import re
23import os
24import os.path
25import time
26
27from types import StringTypes
28from xml.sax import make_parser
29from xml.sax.handler import ContentHandler
30from xml.sax.saxutils import XMLGenerator
31from xml.sax.xmlreader import AttributesImpl as Attributes
32
33from umitCore.I18N import _
34from umitCore.UmitLogging import log
35
36months = ('',_('January'),
37             _('February'),
38             _('March'),
39             _('April'),
40             _('May'),
41             _('June'),
42             _('July'),
43             _('August'),
44             _('September'),
45             _('October'),
46             _('November'),
47             _('December'),)
48
49class HostInfo(object):
50    def __init__(self, id):
51        self.id = id
52   
53    # Host ID
54    def get_id(self):
55        if self._id != 0:
56            return self._id
57        raise Exception("Id was not set yet.")
58
59    def set_id(self, id):
60        if type(id) == type(0):
61            self._id = id
62        elif type(id) in StringTypes:
63            try:
64                self._id = int(id)
65            except:
66                raise Exception("Id invalid! Id must be an integer, but received \
67this instead: '%s'" % str(id))
68        else:
69            raise Exception("Id invalid! Id must be an integer, but received \
70this instead: '%s'" % str(id))
71   
72    # TCP SEQUENCE
73    def set_tcpsequence(self, sequence):
74        if type(sequence) == type([]):
75            self._tcpsequence = sequence[0]
76        else:
77            self._tcpsequence = sequence
78   
79    def get_tcpsequence(self):
80        if self._tcpsequence:
81            return self._tcpsequence
82        return {}
83
84    # TCPTS SEQUENCE
85    def set_tcptssequence(self, sequence):
86        if type(sequence) == type([]):
87            self._tcptssequence = sequence[0]
88        else:
89            self._tcptssequence = sequence
90   
91    def get_tcptssequence(self):
92        if self._tcptssequence:
93            return self._tcptssequence
94        return {}
95
96    # VENDOR
97    def get_vendor(self):
98        try:return self._mac['vendor']
99        except:return _('Unknown')
100
101    # IP ID SEQUENCE
102    def set_ipidsequence(self, sequence):
103        if type(sequence) == type([]):
104            self._ipidsequence = sequence[0]
105        else:
106            self._ipidsequence = sequence
107   
108    def get_ipidsequence(self):
109        if self._ipidsequence:
110            return self._ipidsequence
111        return {}
112
113    # OS CLASSES
114    def set_osclasses(self, classes):
115        self._osclasses = classes
116   
117    def get_osclasses(self):
118        return self._osclasses
119   
120    # OS MATCH
121    def set_osmatch(self, match):
122        if type(match) == type([]):
123            self._osmatch = match[0]
124        else:
125            self._osmatch = match
126   
127    def get_osmatch(self):
128        if self._osmatch:
129            return self._osmatch
130        return {}
131
132    # PORTS USED
133    def set_ports_used(self, ports):
134        self._ports_used = ports
135   
136    def get_ports_used(self):
137        return self._ports_used
138
139    # UPTIME
140    # FORMAT: {"seconds":"", "lastboot":""}
141    def set_uptime(self, uptime):
142        self._uptime = uptime
143   
144    def get_uptime(self):
145        if self._uptime:
146            return self._uptime
147       
148        # Avoid empty dict return
149        return {"seconds":"", "lastboot":""}
150
151    # PORTS
152    def set_ports(self, port_list):
153        self._ports = port_list
154   
155    def get_ports(self):
156        return self._ports
157
158    # HOSTNAMES
159    def set_hostnames(self, hostname_list):
160        self._hostnames = hostname_list
161   
162    def get_hostnames(self):
163        return self._hostnames
164
165    # IP
166    def set_ip_address(self, addr):
167        log.warning(_("umitCore.NmapParser.set_ip_address deprecated! Use \
168umitCore.NmapParser.set_ip instead."))
169        self.set_ip(addr)
170   
171    def get_ip_address(self):
172        log.warning(_("umitCore.NmapParser.get_ip_address deprecated! Use \
173umitCore.NmapParser.get_ip instead."))
174        return self.get_ip()
175
176    def set_ip(self, addr):
177        self._ip = addr
178
179    def get_ip(self):
180        return self._ip
181
182    # COMMENT
183    def get_comment(self):
184        return self._comment
185   
186    def set_comment(self, comment):
187        self._comment = comment
188
189    # MAC
190    def set_mac_address(self, addr):
191        log.warning(_("umitCore.NmapParser.set_mac_address deprecated! Use \
192umitCore.NmapParser.set_mac instead."))
193        self.set_mac(addr)
194   
195    def get_mac_address(self):
196        log.warning(_("umitCore.NmapParser.get_mac_address deprecated! Use \
197umitCore.NmapParser.get_mac instead."))
198        return self.get_mac()
199
200    def set_mac(self, addr):
201        self._mac = addr
202
203    def get_mac(self):
204        return self._mac
205
206    # IPv6
207    def set_ipv6_address(self, addr):
208        log.warning(_("umitCore.NmapParser.set_ipv6_address deprecated! Use \
209umitCore.NmapParser.set_ipv6 instead."))
210        self.set_ipv6(addr)
211   
212    def get_ipv6_address(self):
213        log.warning(_("umitCore.NmapParser.get_ipv6_address deprecated! Use \
214umitCore.NmapParser.get_ipv6 instead."))
215        return self.get_ipv6()
216
217    def set_ipv6(self, addr):
218        self._ipv6 = addr
219
220    def get_ipv6(self):
221        return self._ipv6
222
223    # STATE
224    def set_state(self, status):
225        self._state = status
226   
227    def get_state(self):
228        return self._state
229
230    # HOSTNAME
231    def get_hostname(self):
232        hostname = ''
233        try:
234            hostname = self._hostnames[0]['hostname'] + ' '
235        except:
236            pass
237
238        # FIXME: Check if i can return the 'addr' key directly from get_ip, get_ipv6 and get_mac
239        if self.ip:
240            hostname += self._ip['addr']
241        elif self.ipv6:
242            hostname += self._ipv6['addr']
243        elif self.mac:
244            hostname += self._mac['addr']
245        else:
246            hostname = _('Unknown Host')
247       
248        return hostname
249
250    def get_open_ports(self):
251        ports = self.get_ports()
252        open = 0
253       
254        for i in ports:
255            port = i['port']
256            for p in port:
257                if re.findall('open', p['port_state']):
258                    open+=1
259       
260        return open
261   
262    def get_filtered_ports(self):
263        ports = self.get_ports()
264        filtered = 0
265       
266        for i in ports:
267            port = i['port']
268            for p in port:
269                if re.findall('filtered', p['port_state']):
270                    filtered+=1
271 
272        return filtered
273   
274    def get_closed_ports(self):
275        ports = self.get_ports()
276        closed = 0
277       
278        for i in ports:
279            port = i['port']
280            for p in port:
281                if re.findall('closed', p['port_state']):
282                    closed+=1
283       
284        return closed
285   
286    def get_scanned_ports(self):
287        ports = self.get_ports()
288        scanned = 0
289       
290        for i in ports:
291            port = i['port']
292            for p in port:
293                scanned+=1
294       
295        return scanned
296
297    def get_services(self):
298        services = []
299        for port in self.ports:
300            for p in port.get("port", []):
301                services.append({"service_name":p.get("service_name", _("unknown")),
302                                 "portid":p.get("portid", ""),
303                                 "service_version":p.get("service_version",
304                                                         _("Unknown version")),
305                                 "service_product":p.get("service_product", ""),
306                                 "port_state":p.get("port_state", _("Unknown")),
307                                 "protocol":p.get("protocol", "")})
308        return services
309
310    # Properties
311    id = property(get_id, set_id)
312    tcpsequence = property(get_tcpsequence, set_tcpsequence)
313    osclasses = property(get_osclasses, set_osclasses)
314    osmatch = property(get_osmatch, set_osmatch)
315    ports = property(get_ports, set_ports)
316    ports_used = property(get_ports_used, set_ports_used)
317    uptime = property(get_uptime, set_uptime)
318    hostnames = property(get_hostnames, set_hostnames)
319    tcptssequence = property(get_tcptssequence, set_tcptssequence)
320    ipidsequence = property(get_ipidsequence, set_ipidsequence)
321    ip = property(get_ip, set_ip)
322    ipv6 = property(get_ipv6, set_ipv6)
323    mac = property(get_mac, set_mac)
324    state = property(get_state, set_state)
325    comment = property(get_comment, set_comment)
326    services = property(get_services)
327
328    _id = 0
329    _tcpsequence = {}
330    _osclasses = []
331    _osmatch = []
332    _ports = []
333    _ports_used = []
334    _uptime = {}
335    _hostnames = []
336    _tcptssequence = {}
337    _ipidsequence = {}
338    _ip = {}
339    _ipv6 = {}
340    _mac = {}
341    _state = ''
342    _comment = ''
343
344
345class ParserBasics(object):
346    def __init__ (self):
347        self.nmap = {'nmaprun':{},\
348                     'scaninfo':[],\
349                     'verbose':'',\
350                     'debugging':'',\
351                     'hosts':[],\
352                     'runstats':{}}
353
354    def set_host_comment(self, host_id, comment):
355        for host in self.nmap['hosts']:
356            if host.id == host_id:
357                host.comment = comment
358                break
359        else:
360            raise Exception("Comment could not be saved! Host not \
361found at NmapParser!")
362
363    def get_host_comment(self, host_id):
364        for host in self.nmap.get('hosts', []):
365            if host.id == host_id:
366                return host.comment
367        else:
368            raise Exception("Comment could not be saved! Host not \
369found at NmapParser!")
370
371    def get_profile(self):
372        return self.nmap['nmaprun'].get('profile', '')
373
374    def set_profile(self, profile):
375        self.nmap['nmaprun']['profile'] = profile
376   
377    def get_profile_name(self):
378        return self.nmap['nmaprun'].get('profile_name', '')
379
380    def set_profile_name(self, name):
381        self.nmap['nmaprun']['profile_name'] = name
382   
383    def get_profile_description(self):
384        return self.nmap['nmaprun'].get('description', '')
385
386    def set_profile_description(self, description):
387        self.nmap['nmaprun']['description'] = description
388   
389    def get_profile_hint(self):
390        return self.nmap['nmaprun'].get('hint', '')
391
392    def set_profile_hint(self, hint):
393        self.nmap['nmaprun']['hint'] = hint
394   
395    def get_profile_annotation(self):
396        return self.nmap['nmaprun'].get('annotation', '')
397
398    def set_profile_annotation(self, annotation):
399        self.nmap['nmaprun']['annotation'] = annotation
400   
401    def get_profile_options(self):
402        options = self.nmap['nmaprun'].get('options', '')
403        if type(options) == type([]):
404            return ','.join(options)
405        elif type(options) in StringTypes:
406            return options
407
408    def set_profile_options(self, options):
409        if (type(options) == type([])) or (type(options) in StringTypes):
410            self.nmap['nmaprun']['options'] = options
411        elif type(options) == type({}):
412            self.nmap['nmaprun']['options'] = options.keys()
413        else:
414            raise Exception("Profile option error: wrong argument format! \
415Need a string or list.")
416   
417    def get_target(self):
418        return self.nmap['nmaprun'].get('target', '')
419
420    def set_target(self, target):
421        self.nmap['nmaprun']['target'] = target
422
423    def get_nmap_output(self):
424        return self.nmap['nmaprun'].get('nmap_output', '')
425
426    def set_nmap_output(self, nmap_output):
427        self.nmap['nmaprun']['nmap_output'] = nmap_output
428   
429    def get_debugging_level (self):
430        return self.nmap.get('debugging', '')
431
432    def set_debugging_level(self, level):
433        self.nmap['debugging'] = level
434   
435    def get_verbose_level (self):
436        return self.nmap.get('verbose', '')
437
438    def set_verbose_level(self, level):
439        self.nmap['verbose'] = level
440   
441    def get_scaninfo(self):
442        return self.nmap.get('scaninfo', '')
443
444    def set_scaninfo(self, info):
445        self.nmap['scaninfo'] = info
446   
447    def get_services_scanned (self):
448        if self._services_scanned == None:
449            return self._services_scanned
450       
451        services = []
452        for scan in self.nmap.get('scaninfo', []):
453            services.append(scan['services'])
454
455        self._services_scanned = ','.join(services)
456        return self._services_scanned
457
458    def set_services_scanned (self, services_scanned):
459        self._services_scanned = services_scanned
460
461    def get_nmap_command (self):
462        return self._verify_output_options(self.nmap['nmaprun'].get('args', ''))
463
464    def set_nmap_command(self, command):
465        self.nmap['nmaprun']['args'] = self._verify_output_options(command)
466
467    def get_scan_type (self):
468        types = []
469        for t in self.nmap.get('scaninfo', []):
470            types.append(t['type'])
471        return types
472
473    def get_protocol (self):
474        protocols = []
475        for proto in self.nmap.get('scaninfo', []):
476            protocols.append(proto['protocol'])
477        return protocols
478
479    def get_num_services (self):
480        if self._num_services == None:
481            return self._num_services
482       
483        num = 0
484        for n in self.nmap.get('scaninfo', []):
485            num += int(n['numservices'])
486
487        self._num_services = num
488        return self._num_services
489
490    def set_num_services (self, num_services):
491        self._num_services = num_services
492
493    def get_date (self):
494        epoch = int(self.nmap['nmaprun'].get('start', '0'))
495        return time.localtime (epoch)
496
497    def get_start(self):
498        return self.nmap['nmaprun'].get('start', '0')
499
500    def set_start(self, start):
501        self.nmap['nmaprun']['start'] = start
502
503    def set_date(self, date):
504        if type(date) == type(int):
505            self.nmap['nmaprun']['start'] = date
506        else:
507            raise Exception("Wrong date format. Date should be saved \
508in epoch format!")
509   
510    def get_open_ports(self):
511        ports = 0
512
513        for h in self.nmap.get('hosts', []):
514            ports += h.get_open_ports()
515
516        return ports
517
518    def get_filtered_ports(self):
519        ports = 0
520
521        for h in self.nmap.get('hosts', []):
522            ports += h.get_filtered_ports()
523       
524        for extra in self.list_extraports:
525            if extra["state"] == "filtered":
526                ports += int(extra["count"])
527
528        log.debug(">>> EXTRAPORTS: %s" % str(self.list_extraports))
529
530        return ports
531
532    def get_closed_ports(self):
533        ports = 0
534       
535        for h in self.nmap['hosts']:
536            ports += h.get_closed_ports()
537
538        for extra in self.list_extraports:
539            if extra["state"] == "closed":
540                ports += int(extra["count"])
541
542        return ports
543
544    def get_formated_date(self):
545        date = self.get_date()
546        return "%s %s, %s - %s:%s" % (months[date[1]], 
547                                      str(date[2]), 
548                                      str(date[0]),
549                                      str(date[3]).zfill(2), 
550                                      str(date[4]).zfill(2))
551
552    def get_scanner (self):
553        return self.nmap['nmaprun'].get('scanner', '')
554
555    def set_scanner(self, scanner):
556        self.nmap['nmaprun']['scanner'] = scanner
557   
558    def get_scanner_version (self):
559        return self.nmap['nmaprun'].get('version', '')
560
561    def set_scanner_version(self, version):
562        self.nmap['nmaprun']['version'] = version
563
564    # IPv4
565    def get_ipv4_addresses (self):
566        log.warning(_("umitCore.NmapParser.get_ipv4_address deprecated! Use \
567umitCore.NmapParser.get_ipv4 instead."))
568        return self.get_ipv4()
569
570    def get_ipv4(self):
571        addresses = []
572        for host in self.nmap.get('hosts', []):
573            try:
574                addresses.append(host.get_ip().get('addr', ''))
575            except:
576                pass
577       
578        return addresses
579
580    # MAC
581    def get_mac_addresses (self):
582        log.warning(_("umitCore.NmapParser.get_mac_address deprecated! Use \
583umitCore.NmapParser.get_mac instead."))
584        return self.get_mac()
585
586    def get_mac(self):
587        addresses = []
588        for host in self.nmap.get('hosts', []):
589            try:
590                addresses.append(host.get_mac().get('addr', ''))
591            except:
592                pass
593       
594        return addresses
595
596    # IPv6
597    def get_ipv6_addresses (self):
598        log.warning(_("umitCore.NmapParser.get_ipv6_address deprecated! Use \
599umitCore.NmapParser.get_ipv6 instead."))
600        return self.get_ipv6()
601
602    def get_ipv6(self):
603        addresses = []
604        for host in self.nmap.get('hosts', []):
605            try:
606                addresses.append(host.get_ipv6().get('addr', ''))
607            except:
608                pass
609
610        return addresses
611
612    def get_hostnames (self):
613        hostnames = []
614        for host in self.nmap.get('hosts', []):
615            hostnames += host.get_hostnames()
616        return hostnames
617
618    def get_ports(self):
619        ports = []
620        for port in self.nmap.get('hosts', []):
621            ports.append(port.get_ports())
622       
623        return ports
624
625    def get_hosts(self):
626        return self.nmap.get('hosts', None)
627
628    def get_runstats(self):
629        return self.nmap.get('runstats', None)
630
631    def set_runstats(self, stats):
632        self.nmap['runstats'] = stats
633   
634    def get_hosts_down(self):
635        return int(self.nmap['runstats'].get('hosts_down', '0'))
636
637    def set_hosts_down(self, down):
638        self.nmap['runstats']['hosts_down'] = int(down)
639   
640    def get_hosts_up(self):
641        return int(self.nmap['runstats'].get('hosts_up', '0'))
642
643    def set_hosts_up(self, up):
644        self.nmap['runstats']['hosts_up'] = int(up)
645   
646    def get_hosts_scanned(self):
647        return int(self.nmap['runstats'].get('hosts_scanned', '0'))
648
649    def set_hosts_scanned(self, scanned):
650        self.nmap['runstats']['hosts_scanned'] = int(scanned)
651   
652    def get_finish_time (self):
653        return time.localtime(int(self.nmap['runstats'].get('finished_time',
654                                                            '0')))
655
656    def set_finish_time(self, finish):
657        self.nmap['runstats']['finished_time'] = int(finish)
658
659    def get_finish_epoc_time(self):
660        return int(self.nmap['runstats'].get('finished_time', '0'))
661
662    def set_finish_epoc_time(self, time):
663        self.nmap['runstats']['finished_time'] = time
664
665    def get_scan_name(self):
666        return self.nmap.get("scan_name", "")
667
668    def set_scan_name(self, scan_name):
669        self.nmap["scan_name"] = scan_name
670   
671    def get_formated_finish_date(self):
672        date = self.get_finish_time()
673        return "%s %s, %s - %s:%s" % (months[date[1]], 
674                                      str(date[2]), 
675                                      str(date[0]),
676                                      str(date[3]).zfill(2), 
677                                      str(date[4]).zfill(2))
678
679    def _verify_output_options (self, command):
680        found = re.findall ('(-o[XGASN]{1}) {0,1}', command)
681        splited = command.split (' ')
682       
683        if found:
684            for option in found:
685                pos = splited.index(option)
686                del(splited[pos+1])
687                del(splited[pos])
688       
689        return ' '.join (splited)
690
691    def get_comments(self):
692        return [host.comment for host in self.nmap['hosts']]
693
694    profile = property(get_profile, set_profile)
695    profile_name = property(get_profile_name, set_profile_name)
696    profile_description = property(get_profile_description, 
697                                   set_profile_description)
698    profile_hint = property(get_profile_hint, set_profile_hint)
699    profile_annotation = property(get_profile_annotation, 
700                                  set_profile_annotation)
701    profile_options = property(get_profile_options, set_profile_options)
702    target = property(get_target, set_target)
703    nmap_output = property(get_nmap_output, set_nmap_output)
704    debugging_level = property(get_debugging_level, set_debugging_level)
705    verbose_level = property(get_verbose_level, set_verbose_level)
706    scaninfo = property(get_scaninfo, set_scaninfo)
707    services_scanned = property(get_services_scanned, set_services_scanned)
708    nmap_command = property(get_nmap_command, set_nmap_command)
709    scan_type = property(get_scan_type)
710    protocol = property(get_protocol)
711    num_services = property(get_num_services, set_num_services)
712    date = property(get_date, set_date)
713    open_ports = property(get_open_ports)
714    filtered_ports = property(get_filtered_ports)
715    closed_ports = property(get_closed_ports)
716    formated_date = property(get_formated_date)
717    scanner = property(get_scanner, set_scanner)
718    scanner_version = property(get_scanner_version, set_scanner_version)
719    ipv4 = property(get_ipv4)
720    mac = property(get_mac)
721    ipv6 = property(get_ipv6)
722    hostnames = property(get_hostnames)
723    ports = property(get_ports)
724    hosts = property(get_hosts)
725    runstats = property(get_runstats, set_runstats)
726    hosts_down = property(get_hosts_down, set_hosts_down)
727    hosts_up = property(get_hosts_up, set_hosts_up)
728    hosts_scanned = property(get_hosts_scanned, set_hosts_scanned)
729    finish_time = property(get_finish_time, set_finish_time)
730    finish_epoc_time = property(get_finish_epoc_time, set_finish_epoc_time)
731    formated_finish_date = property(get_formated_finish_date)
732    comments = property(get_comments)
733    start = property(get_start, set_start)
734    scan_name = property(get_scan_name, set_scan_name)
735
736    _num_services = None
737    _services_scanned = None
738
739
740class NmapParserSAX(ParserBasics, ContentHandler):
741    def __init__(self):
742        ParserBasics.__init__(self)
743        self.id_sequence = 0
744
745        self.in_run_stats = False
746        self.in_host = False
747        self.in_ports = False
748        self.in_port = False
749        self.in_os = False
750
751        self.nmap_xml_file = None
752
753    def set_parser(self, parser):
754        self.parser = parser
755
756    def set_xml_file(self, nmap_xml_file):
757        self.nmap_xml_file = nmap_xml_file
758
759    def parse(self):
760        if self.nmap_xml_file:
761            if type(self.nmap_xml_file) in StringTypes:
762                self.parser.parse(self.nmap_xml_file)
763            else:
764                log.debug(">>> XML content: %s" % self.nmap_xml_file.read())
765                self.nmap_xml_file.seek(0)
766                self.parser.parse(self.nmap_xml_file)
767
768                # Closing file to avoid problems with file descriptors
769                self.nmap_xml_file.close()
770        else:
771            raise Exception("There's no file to be parsed!")
772
773    def _parse_nmaprun(self, attrs):
774        run_tag = "nmaprun"
775       
776        self.nmap[run_tag]["nmap_output"] = attrs.get("nmap_output", "")
777        self.nmap[run_tag]["profile"] = attrs.get("profile", "")
778        self.nmap[run_tag]["profile_name"] = attrs.get("profile_name", "")
779        self.nmap[run_tag]["hint"] = attrs.get("hint", "")
780        self.nmap[run_tag]["description"] = attrs.get("description", "")
781        self.nmap[run_tag]["annotation"] = attrs.get("annotation", "")
782        self.nmap[run_tag]["options"] = attrs.get("options", "")
783        self.nmap[run_tag]["target"] = attrs.get("target", "")
784        self.nmap[run_tag]["start"] = attrs.get("start", "")
785        self.nmap[run_tag]["args"] = attrs.get("args", "")
786        self.nmap[run_tag]["scanner"] = attrs.get("scanner", "")
787        self.nmap[run_tag]["version"] = attrs.get("version", "")
788        self.nmap[run_tag]["xmloutputversion"] = attrs.get("xmloutputversion", 
789                                                           "")
790        self.nmap["scan_name"] = attrs.get("scan_name", "")
791
792    def _parse_scaninfo(self, attrs):
793        dic = {}
794       
795        dic["type"] = attrs.get("type", "")
796        dic["protocol"] = attrs.get("protocol", "")
797        dic["numservices"] = attrs.get("numservices", "")
798        dic["services"] = attrs.get("services", "")
799       
800        self.nmap["scaninfo"].append(dic)
801
802    def _parse_verbose(self, attrs):
803        self.nmap["verbose"] = attrs.get("level", "")
804
805    def _parse_debugging(self, attrs):
806        self.nmap["debugging"] = attrs.get("level", "")
807
808    def _parse_runstats_finished(self, attrs):
809        self.nmap["runstats"]["finished_time"] = attrs.get("time", "")
810
811    def _parse_runstats_hosts(self, attrs):
812        self.nmap["runstats"]["hosts_up"] = attrs.get("up", "")
813        self.nmap["runstats"]["hosts_down"] = attrs.get("down", "")
814        self.nmap["runstats"]["hosts_scanned"] = attrs.get("total", "")
815
816    def generate_id(self):
817        self.id_sequence += 1
818        return self.id_sequence
819
820    def _parse_host(self, attrs):
821        self.host_info = HostInfo(self.generate_id())
822        self.host_info.comment = attrs.get("comment", "")
823
824    def _parse_host_status(self, attrs):
825        self.host_info.set_state(attrs.get("state", ""))
826
827    def _parse_host_address(self, attrs):
828        address_attributes = {"type":attrs.get("addrtype", ""),
829                              "vendor":attrs.get("vendor", ""),
830                              "addr":attrs.get("addr", "")}
831
832        if address_attributes["type"] == "ipv4":
833            self.host_info.set_ip(address_attributes)
834        elif address_attributes["type"] == "ipv6":
835            self.host_info.set_ipv6(address_attributes)
836        elif address_attributes["type"] == "mac":
837            self.host_info.set_mac(address_attributes)
838
839    def _parse_host_hostname(self, attrs):
840        self.list_hostnames.append({"hostname":attrs.get("name", ""),
841                                    "hostname_type":attrs.get("type", "")})
842
843    def _parse_host_extraports(self, attrs):
844        self.list_extraports.append({"state":attrs.get("state", ""),
845                                     "count":attrs.get("count", "")})
846
847    def _parse_host_port(self, attrs):
848        self.dic_port = {"protocol":attrs.get("protocol", ""), 
849                         "portid":attrs.get("portid", "")}
850
851    def _parse_host_port_state(self, attrs):
852        self.dic_port["port_state"] = attrs.get("state", "")
853
854    def _parse_host_port_service(self, attrs):
855        self.dic_port["service_name"] = attrs.get("name", "")
856        self.dic_port["service_method"] = attrs.get("method", "")
857        self.dic_port["service_conf"] = attrs.get("conf", "")
858        self.dic_port["service_product"] = attrs.get("product", "")
859        self.dic_port["service_version"] = attrs.get("version", "")
860        self.dic_port["service_extrainfo"] = attrs.get("extrainfo", "")
861
862    def _parse_host_osmatch(self, attrs):
863        self.host_info.set_osmatch(self._parsing(attrs, ['name', 'accuracy']))
864
865    def _parse_host_portused(self, attrs):
866        self.list_portused.append(self._parsing(attrs, 
867                                                ['state','proto','portid']))
868
869    def _parse_host_osclass(self, attrs):
870        self.list_osclass.append(self._parsing(attrs, ['type',
871                                                       'vendor',
872                                                       'osfamily',
873                                                       'osgen',
874                                                       'accuracy']))
875
876    def _parsing(self, attrs, attrs_list):
877        # Returns a dict with the attributes of a given tag with the
878        # atributes names as keys and their respective values
879        dic = {}
880        for at in attrs_list:
881            dic[at] = attrs.get(at, "")
882        return dic
883
884    def _parse_host_uptime(self, attrs):
885        self.host_info.set_uptime(self._parsing(attrs, ["seconds", "lastboot"]))
886
887
888    def _parse_host_tcpsequence(self, attrs):
889        self.host_info.set_tcpsequence(self._parsing(attrs, ['index',
890                                                             'class',
891                                                             'difficulty',
892                                                             'values']))
893   
894    def _parse_host_tcptssequence(self, attrs):
895        self.host_info.set_tcptssequence(self._parsing(attrs, ['class',
896                                                               'values']))
897
898    def _parse_host_ipidsequence(self, attrs):
899        self.host_info.set_ipidsequence(self._parsing(attrs, ['class',
900                                                              'values']))
901
902    def startElement(self, name, attrs):
903        if name == "nmaprun":
904            self._parse_nmaprun(attrs)
905        elif name == "scaninfo":
906            self._parse_scaninfo(attrs)
907        elif name == "verbose":
908            self._parse_verbose(attrs)
909        elif name == "debugging":
910            self._parse_debugging(attrs)
911        elif name == "runstats":
912            self.in_run_stats = True
913        elif self.in_run_stats and name == "finished":
914            self._parse_runstats_finished(attrs)
915        elif self.in_run_stats and name == "hosts":
916            self._parse_runstats_hosts(attrs)
917        elif name == "host":
918            self.in_host = True
919            self._parse_host(attrs)
920            self.list_ports = []
921        elif self.in_host and name == "status":
922            self._parse_host_status(attrs)
923        elif self.in_host and name == "address":
924            self._parse_host_address(attrs)
925        elif self.in_host and name == "hostnames":
926            self.in_hostnames = True
927            self.list_hostnames = []
928        elif self.in_host and self.in_hostnames and name == "hostname":
929            self._parse_host_hostname(attrs)
930        elif self.in_host and name == "ports":
931            self.list_extraports = []
932            self.list_port = []
933            self.in_ports = True
934        elif self.in_host and self.in_ports and name == "extraports":
935            self._parse_host_extraports(attrs)
936        elif self.in_host and self.in_ports and name == "port":
937            self.in_port = True
938            self._parse_host_port(attrs)
939        elif self.in_host and self.in_ports and \
940             self.in_port and name == "state":
941            self._parse_host_port_state(attrs)
942        elif self.in_host and self.in_ports and \
943             self.in_port and name == "service":
944            self._parse_host_port_service(attrs)
945        elif self.in_host and name == "os":
946            self.in_os = True
947            self.list_portused = []
948            self.list_osclass = []
949        elif self.in_host and self.in_os and name == "osmatch":
950            self._parse_host_osmatch(attrs)
951        elif self.in_host and self.in_os and name == "portused":
952            self._parse_host_portused(attrs)
953        elif self.in_host and self.in_os and name == "osclass":
954            self._parse_host_osclass(attrs)
955        elif self.in_host and name == "uptime":
956            self._parse_host_uptime(attrs)
957        elif self.in_host and name == "tcpsequence":
958            self._parse_host_tcpsequence(attrs)
959        elif self.in_host and name == "tcptssequence":
960            self._parse_host_tcptssequence(attrs)
961        elif self.in_host and name == "ipidsequence":
962            self._parse_host_ipidsequence(attrs)
963
964
965    def endElement(self, name):
966        if name == "runstats":
967            self.in_run_stats = False
968        elif name == "host":
969            self.in_host = False
970            self.host_info.set_ports(self.list_ports)
971            self.nmap["hosts"].append(self.host_info)
972            del(self.list_ports)
973        elif self.in_host and name == "hostnames":
974            self.in_hostnames = False
975            self.host_info.set_hostnames(self.list_hostnames)
976        elif self.in_host and name == "ports":
977            self.in_ports = False
978            self.list_ports.append({"extraports":self.list_extraports,
979                                    "port":self.list_port})
980        elif self.in_host and self.in_ports and name == "port":
981            self.in_port = False
982            self.list_port.append(self.dic_port)
983            del(self.dic_port)
984        elif self.in_host and self.in_os and name == "os":
985            self.in_os = False
986            self.host_info.set_ports_used(self.list_portused)
987            self.host_info.set_osclasses(self.list_osclass)
988
989            del(self.list_portused)
990            del(self.list_osclass)
991
992    def write_xml(self, xml_file):
993        xml_file = self._verify_file(xml_file)
994        self.write_parser = XMLGenerator(xml_file)
995
996        # First, start the document:
997        self.write_parser.startDocument()
998
999        # Nmaprun element:
1000        self._write_nmaprun()
1001
1002        # Scaninfo element:
1003        self._write_scaninfo()
1004
1005        # Verbose element:
1006        self._write_verbose()
1007
1008        # Debugging element:
1009        self._write_debugging()
1010
1011        # Hosts elements:
1012        self._write_hosts()
1013
1014        # Runstats element:
1015        self._write_runstats()
1016
1017        # End of the xml file:
1018        self.write_parser.endElement("nmaprun")
1019        self.write_parser.endDocument()
1020
1021    def _write_runstats(self):
1022        ##################
1023        # Runstats element
1024        self.write_parser.startElement("runstats", Attributes(dict()))
1025
1026        ## Finished element
1027        self.write_parser.startElement("finished",
1028                        Attributes(dict(time = str(self.finish_epoc_time))))
1029        self.write_parser.endElement("finished")
1030
1031        ## Hosts element
1032        self.write_parser.startElement("hosts",
1033                            Attributes(dict(up = str(self.hosts_up),
1034                                            down = str(self.hosts_down),
1035                                            total = str(self.hosts_scanned))))
1036        self.write_parser.endElement("hosts")
1037
1038
1039        self.write_parser.endElement("runstats")
1040        # End of Runstats element
1041        #########################
1042
1043    def _write_hosts(self):
1044        for host in self.hosts:
1045            # Start host element
1046            self.write_parser.startElement("host",
1047                                Attributes(dict(comment=host.comment)))
1048
1049            # Status element
1050            self.write_parser.startElement("status",
1051                                Attributes(dict(state=host.state)))
1052            self.write_parser.endElement("status")
1053
1054
1055            ##################
1056            # Address elements
1057            ## IPv4
1058            if type(host.ip) == type({}):
1059                self.write_parser.startElement("address",
1060                            Attributes(dict(addr=host.ip.get("addr", ""),
1061                                        vendor=host.ip.get("vendor", ""),
1062                                        addrtype=host.ip.get("type", ""))))
1063                self.write_parser.endElement("address")
1064
1065            ## IPv6
1066            if type(host.ipv6) == type({}):
1067                self.write_parser.startElement("address",
1068                            Attributes(dict(addr=host.ipv6.get("addr", ""),
1069                                        vendor=host.ipv6.get("vendor", ""),
1070                                        addrtype=host.ipv6.get("type", ""))))
1071                self.write_parser.endElement("address")
1072
1073            ## MAC
1074            if type(host.mac) == type({}):
1075                self.write_parser.startElement("address",
1076                            Attributes(dict(addr=host.mac.get("addr", ""),
1077                                        vendor=host.mac.get("vendor", ""),
1078                                        addrtype=host.mac.get("type", ""))))
1079                self.write_parser.endElement("address")
1080            # End of Address elements
1081            #########################
1082
1083
1084            ###################
1085            # Hostnames element
1086            self.write_parser.startElement("hostnames", Attributes({}))
1087
1088            for hname in host.hostnames:
1089                if type(hname) == type({}):
1090                    self.write_parser.startElement("hostname",
1091                            Attributes(dict(name = hname.get("hostname", ""),
1092                                        type = hname.get("hostname_type", ""))))
1093                   
1094                    self.write_parser.endElement("hostname")
1095
1096            self.write_parser.endElement("hostnames")
1097            # End of Hostnames element
1098            ##########################
1099
1100
1101            ###############
1102            # Ports element
1103            self.write_parser.startElement("ports", Attributes({}))
1104
1105            for ps in host.ports:
1106                ## Extraports elements
1107                for ext in ps["extraports"]:
1108                    if type(ext) == type({}):
1109                        self.write_parser.startElement("extraports",
1110                            Attributes(dict(count = ext.get("count", ""),
1111                                            state = ext.get("state", ""))))
1112                        self.write_parser.endElement("extraports")
1113
1114                ## Port elements
1115                for p in ps["port"]:
1116                    if type(p) == type({}):
1117                        self.write_parser.startElement("port",
1118                            Attributes(dict(portid = p.get("portid", ""),
1119                                            protocol = p.get("protocol", ""))))
1120
1121                        ### Port state
1122                        self.write_parser.startElement("state",
1123                            Attributes(dict(state=p.get("port_state", ""))))
1124                        self.write_parser.endElement("state")
1125
1126                        ### Port service info
1127                        self.write_parser.startElement("service",
1128                            Attributes(dict(conf = p.get("service_conf", ""),
1129                                    method = p.get("service_method", ""),
1130                                    name = p.get("service_name", ""),
1131                                    product = p.get("service_product", ""),
1132                                    version = p.get("service_version", ""),
1133                                    extrainfo = p.get("service_extrainfo", "")\
1134                                )))
1135                        self.write_parser.endElement("service")
1136
1137                        self.write_parser.endElement("port")
1138
1139            self.write_parser.endElement("ports")
1140            # End of Ports element
1141            ######################
1142
1143
1144            ############
1145            # OS element
1146            self.write_parser.startElement("os", Attributes({}))
1147           
1148            ## Ports used elements
1149            for pu in host.ports_used:
1150                if type(pu) == type({}):
1151                    self.write_parser.startElement("portused",
1152                                Attributes(dict(state = pu.get("state", ""),
1153                                                proto = pu.get("proto", ""),
1154                                                portid = pu.get("portid", ""))))
1155                    self.write_parser.endElement("portused")
1156
1157            ## Osclass elements
1158            for oc in host.osclasses:
1159                if type(oc) == type({}):
1160                    self.write_parser.startElement("osclass",
1161                        Attributes(dict(vendor = oc.get("vendor", ""),
1162                                        osfamily = oc.get("osfamily", ""),
1163                                        type = oc.get("type", ""),
1164                                        osgen = oc.get("osgen", ""),
1165                                        accuracy = oc.get("accuracy", ""))))
1166                    self.write_parser.endElement("osclass")
1167
1168            ## Osmatch elements
1169            if type(host.osmatch) == type({}):
1170                self.write_parser.startElement("osmatch",
1171                    Attributes(dict(name = host.osmatch.get("name", ""),
1172                                accuracy = host.osmatch.get("accuracy", ""))))
1173                self.write_parser.endElement("osmatch")
1174
1175            self.write_parser.endElement("os")
1176            # End of OS element
1177            ###################
1178
1179            # Uptime element
1180            if type(host.uptime) == type({}):
1181                self.write_parser.startElement("uptime",
1182                    Attributes(dict(seconds = host.uptime.get("seconds", ""),
1183                                lastboot = host.uptime.get("lastboot", ""))))
1184                self.write_parser.endElement("uptime")
1185
1186            #####################
1187            # Sequences elementes
1188            ## TCP Sequence element
1189            # Cannot use dict() here, because of the 'class' attribute.
1190            if type(host.tcpsequence) == type({}):
1191                self.write_parser.startElement("tcpsequence",
1192                    Attributes({"index":host.tcpsequence.get("index", ""),
1193                            "class":host.tcpsequence.get("class", ""),
1194                            "difficulty":host.tcpsequence.get("difficulty", ""),
1195                            "values":host.tcpsequence.get("values", "")}))
1196                self.write_parser.endElement("tcpsequence")
1197
1198            ## IP ID Sequence element
1199            if type(host.ipidsequence) == type({}):
1200                self.write_parser.startElement("ipidsequence",
1201                    Attributes({"class":host.ipidsequence.get("class", ""),
1202                                "values":host.ipidsequence.get("values", "")}))
1203                self.write_parser.endElement("ipidsequence")
1204
1205            ## TCP TS Sequence element
1206            if type(host.tcptssequence) == type({}):
1207                self.write_parser.startElement("tcptssequence",
1208                    Attributes({"class":host.tcptssequence.get("class", ""),
1209                            "values":host.tcptssequence.get("values", "")}))
1210                self.write_parser.endElement("tcptssequence")
1211            # End of sequences elements
1212            ###########################
1213
1214            # End host element
1215            self.write_parser.endElement("host")
1216
1217    def _write_debugging(self):
1218        self.write_parser.startElement("debugging", Attributes(dict(
1219                                            level=str(self.debugging_level))))
1220        self.write_parser.endElement("debugging")
1221
1222    def _write_verbose(self):
1223        self.write_parser.startElement("verbose", Attributes(dict(
1224                                            level=str(self.verbose_level))))
1225        self.write_parser.endElement("verbose")
1226
1227    def _write_scaninfo(self):
1228        for scan in self.scaninfo:
1229            if type(scan) == type({}):
1230                self.write_parser.startElement("scaninfo",
1231                    Attributes(dict(type = scan.get("type", ""),
1232                                    protocol = scan.get("protocol", ""),
1233                                    numservices = scan.get("numservices", ""),
1234                                    services = scan.get("services", ""))))
1235                self.write_parser.endElement("scaninfo")
1236
1237    def _write_nmaprun(self):
1238        self.write_parser.startElement("nmaprun",
1239                Attributes(dict(annotation = str(self.profile_annotation),
1240                                args = str(self.nmap_command),
1241                                description = str(self.profile_description),
1242                                hint = str(self.profile_hint),
1243                                nmap_output = str(self.nmap_output),
1244                                options = str(self.profile_options),
1245                                profile = str(self.profile),
1246                                profile_name = str(self.profile_name),
1247                                scanner = str(self.scanner),
1248                                start = str(self.start),
1249                                startstr = str(self.formated_date),
1250                                target = str(self.target),
1251                                version = str(self.scanner_version),
1252                                scan_name = str(self.scan_name))))
1253
1254    def _verify_file(self, xml_file):
1255        if type(xml_file) in StringTypes:
1256            if os.access(os.path.split(xml_file)[0], os.W_OK):
1257                xml_file = open(xml_file, "w")
1258                xml_file.seek(0)
1259                return xml_file
1260            else:
1261                raise Exception("Don't have write permissions to given path.")
1262        elif type(xml_file) not in StringTypes:
1263            try:
1264                mode = xml_file.mode
1265                if mode == "r+" or mode == "w" or mode == "w+":
1266                    xml_file.seek(0)
1267            except IOError:
1268                raise Exception("File descriptor is not able to write!")
1269            else:
1270                return xml_file
1271
1272
1273def nmap_parser_sax(nmap_xml_file=""):
1274    parser = make_parser()
1275    nmap_parser = NmapParserSAX()
1276   
1277    parser.setContentHandler(nmap_parser)
1278    nmap_parser.set_parser(parser)
1279    nmap_parser.set_xml_file(nmap_xml_file)
1280
1281    return nmap_parser
1282
1283NmapParser = nmap_parser_sax
1284
1285if __name__ == '__main__':
1286    file_to_parse = open("/home/adriano/umit/test/diff1.usr")
1287    file_to_write = open("/tmp/teste_write.xml", "w+")
1288   
1289    np = NmapParser(file_to_parse)
1290    np.parse()
1291
1292    from pprint import pprint
1293
1294    print "Comment:",
1295    pprint(np.nmap["hosts"][-1].comment)
1296    #comment = property(get_comment, set_comment)
1297
1298    print "TCP sequence:",
1299    pprint(np.nmap["hosts"][-1].tcpsequence)
1300    #tcpsequence = property(get_tcpsequence, set_tcpsequence)
1301
1302    print "TCP TS sequence:",
1303    pprint(np.nmap["hosts"][-1].tcptssequence)
1304    #tcptssequence = property(get_tcptssequence, set_tcptssequence)
1305
1306    print "IP ID sequence:",
1307    pprint(np.nmap["hosts"][-1].ipidsequence)
1308    #ipidsequence = property(get_ipidsequence, set_ipidsequence)
1309
1310    print "Uptime:",
1311    pprint(np.nmap["hosts"][-1].uptime)
1312    #uptime = property(get_uptime, set_uptime)
1313
1314    print "OS Match:",
1315    pprint(np.nmap["hosts"][-1].osmatch)
1316    #osmatch = property(get_osmatch, set_osmatch)
1317
1318    print "Ports:",
1319    pprint(np.nmap["hosts"][-1].ports)
1320    #ports = property(get_ports, set_ports)
1321
1322    print "Ports used:",
1323    pprint(np.nmap["hosts"][-1].ports_used)
1324    #ports_used = property(get_ports_used, set_ports_used)
1325
1326    print "OS Class:",
1327    pprint(np.nmap["hosts"][-1].osclasses)
1328    #osclasses = property(get_osclasses, set_osclasses)
1329
1330    print "Hostnames:",
1331    pprint(np.nmap["hosts"][-1].hostnames)
1332    #hostnames = property(get_hostnames, set_hostnames)
1333
1334    print "IP:",
1335    pprint(np.nmap["hosts"][-1].ip)
1336    #ip = property(get_ip, set_ip)
1337
1338    print "IPv6:",
1339    pprint(np.nmap["hosts"][-1].ipv6)
1340    #ipv6 = property(get_ipv6, set_ipv6)
1341
1342    print "MAC:",
1343    pprint(np.nmap["hosts"][-1].mac)
1344    #mac = property(get_mac, set_mac)
1345
1346    print "State:",
1347    pprint(np.nmap["hosts"][-1].state)
1348    #state = property(get_state, set_state)
1349
1350
1351    """
1352    print "Profile:", np.profile
1353    print "Profile name:", np.profile_name
1354    print "Profile description:", np.profile_description
1355    print "Profile hint:", np.profile_hint
1356    print "Profile annotation:", np.profile_annotation
1357    print "Profile options:", np.profile_options
1358    print "Target:", np.target
1359    print "Nmap output:", np.nmap_output
1360    print "Debugging:", np.debugging_level
1361    print "Verbose:", np.verbose_level
1362    print "Scaninfo:", np.scaninfo
1363    print "Services scanned:", np.services_scanned
1364    print "Nmap command:", np.nmap_command
1365    print "Scan type:", np.scan_type
1366    print "Protocol:", np.protocol
1367    print "Num services:", np.num_services
1368    print "Date:", np.date
1369    print "Open ports:", np.open_ports
1370    print "Filtered ports:", np.filtered_ports
1371    print "Closed ports:", np.closed_ports
1372    print "Formated date:", np.formated_date
1373    print "Scanner:", np.scanner
1374    print "Scanner version:", np.scanner_version
1375    print "IPv4:", np.ipv4
1376    print "MAC:", np.mac
1377    print "IPv6:", np.ipv6
1378    print "Hostnames", np.hostnames
1379    print "Ports:", np.ports
1380    print "Hosts:", np.hosts
1381    print "Runstats:", np.runstats
1382    print "Hosts down:", np.hosts_down
1383    print "Hosts up:", np.hosts_up
1384    print "Hosts scanned:", np.hosts_scanned
1385    print "Finished time:", np.finish_time
1386    print "Finished epoc time:", np.finish_epoc_time
1387    print "Formated finish date:", np.formated_finish_date
1388    print "Comments:", np.comments
1389    print "Start:", np.start
1390    """
Note: See TracBrowser for help on using the browser.