root/trunk/umit/gui/radialnet/GraphBuilder.py @ 5096

Revision 5096, 13.7 kB (checked in by luis, 4 years ago)

Adding trace support in NmapParser?. Fixing #339

Line 
1# -*- coding: utf-8 -*-
2# Copyright (C) 2008 Adriano Monteiro Marques.
3#
4# Author: João Paulo de Souza Medeiros <ignotus21@gmail.com>
5#         Luis A. Bastiao Silva <luis.kop@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21"""
22
23A GraphBuilder is a class that make a Graph across NmapParser
24
25"""
26
27from umit.core.radialnet.Graph import *
28from umit.gui.radialnet.RadialNet import NetNode
29
30
31COLORS = [(0.0, 1.0, 0.0),
32          (1.0, 1.0, 0.0),
33          (1.0, 0.0, 0.0)]
34
35BASE_RADIUS = 5.5
36NONE_RADIUS = 4.5
37
38
39
40class GraphBuilder(Graph):
41    def __init__(self):
42        Graph.__init__(self)
43       
44    def __set_default_values(self, node):
45           
46        node.set_info({'ip':'0.0.0.0', 'hostname':'Umit'})
47        node.set_draw_info({'color':(1,0,0),
48                            'radius':BASE_RADIUS,
49                            'line-width':3,
50                            'line-color':(0.5,0,0)})
51       
52       
53    def __calc_vulnerability_level(self, node, host):
54        """
55        """
56        ports = host.ports
57        number_ports = len(host.ports)
58   
59        node.set_info({'number_of_scanned_ports': number_ports})
60   
61        if number_ports < 3:
62            node.set_info({'vulnerability_score': 0})
63   
64        elif number_ports < 7:
65            node.set_info({'vulnerability_score': 1})
66   
67        else:
68            node.set_info({'vulnerability_score': 2})
69   
70    def __set_node_info(self, node, host):
71        """
72        """
73        node.set_info({'host_reference': host})
74   
75        # getting vulnerability score
76        self.__calc_vulnerability_level(node, host)
77   
78        radius = BASE_RADIUS + node.get_info('number_of_scanned_ports') / 2
79        node.set_draw_info({'color':COLORS[\
80            node.get_info('vulnerability_score')],\
81                            'radius':radius})
82   
83        # getting address and hostnames
84        for addr in host.address:
85            if addr['addrtype'] == 'ipv4':
86                host_addresses = addr
87                break
88        else:
89            host_addresses = {}
90        if host_addresses.has_key('vendor') and host_addresses['vendor'] == '':
91            host_addresses['vendor'] = None
92
93        addresses = list()
94   
95        addresses.append(host_addresses)
96   
97        node.set_info({'addresses': addresses})
98        node.set_info({'ip': addresses[0]['addr']})
99   
100        host_hostnames = host.hostnames
101        if host_hostnames:
102            hostnames = list()
103            for host_hostname in host_hostnames:
104                hostnames.append(host_hostname.copy())
105
106            node.set_info({'hostnames': hostnames})
107            node.set_info({'hostname': hostnames[0]['name']})
108   
109        # getting uptime
110        #xml_uptime = host.search_children('uptime', True)
111        host_uptime = host.get_uptime()
112        if host_uptime != {}:
113            node.set_info({'uptime': host_uptime})
114   
115        # getting os fingerprint information
116   
117        os = {}
118
119        host_osfingerprint = host.osfingerprint
120        host_osclasses = host.osclass
121        host_osmatches = host.osmatch
122        host_portsused = host.portused
123        os['fingerprint'] = ""
124        if host_osfingerprint and host_osfingerprint[0].has_key('fingerprint'):
125            os['fingerprint'] = host_osfingerprint[0]['fingerprint']
126
127        if len(host_osclasses) > 0:
128
129            types = ['router', 'wap', 'switch', 'firewall']
130
131            for _type in types:
132                if _type in host_osclasses[0]['type'].lower():
133                    node.set_info({'device_type': _type})
134
135            os_classes = []
136
137            for host_osclass in host_osclasses:
138
139                os_class = {}
140
141                os_class['type'] = host_osclass['type']
142                os_class['vendor'] = host_osclass['vendor']
143                os_class['accuracy'] = int(host_osclass['accuracy'])
144                os_class['os_family'] = host_osclass['osfamily']
145
146                if host_osclass.has_key('osgen'):
147                    os_class['os_gen'] = host_osclass['osgen']
148
149                os_classes.append(os_class)
150
151            os['classes'] = os_classes
152        if len(host_osmatches) > 0:
153            os_matches = []
154
155            for host_osmatch in host_osmatches:
156
157                os_match = {}
158                os_match['name'] = host_osmatch['name']
159                if host_osmatch.get('accuracy', None):
160                    os_match['accuracy'] = int(host_osmatch['accuracy'])
161                # TODO/FIXME:
162                #os_match['db_line'] = int(host_osmatch['line'])
163                os_match['db_line'] = 0 
164                os_matches.append(os_match)
165
166            os['matches'] = os_matches
167        if len(host_portsused) > 0:
168
169            os_portsused = []
170
171            for host_portused in host_portsused:
172                host_portused['protocol'] = host_portused['proto']
173                host_portused['id'] = int(host_portused['portid'])
174                os_portsused.append(host_portused)
175
176            os['used_ports'] = os_portsused
177
178        node.set_info({'os': os})
179   
180        # getting (copies of) sequences information
181        host_tcpsequence = host.tcpsequence.copy()
182        host_ipidsequence = host.ipidsequence.copy()
183        host_tcptssequence = host.tcptssequence.copy()
184       
185        sequences = {}
186   
187        if host_tcpsequence:
188            if host_tcpsequence['index']:
189                host_tcpsequence['index'] = int(host_tcpsequence['index'])
190            host_tcpsequence['values'] = host_tcpsequence['values'].split(',')
191            sequences['tcp'] = host_tcpsequence
192   
193        if host_ipidsequence:
194            ip_id = host_ipidsequence
195            ip_id['values'] = host_ipidsequence['values'].split(',')
196   
197            sequences['ip_id'] = ip_id
198   
199        if host_tcptssequence:
200            if host_tcptssequence.get('values', None):
201                host_tcptssequence['values'] = \
202                        host_tcptssequence['values'].split(',')
203   
204            sequences['tcp_ts'] = host_tcptssequence
205
206        node.set_info({'sequences': sequences})
207   
208        # host is host filtered
209        filtered = False
210       
211        host_filtered = host.status['state']
212        if host_filtered=="filtered":
213            filtered=True
214       
215        ## Search in ports
216        filtered_ports = host.get_filtered_ports()
217       
218   
219        if filtered or filtered_ports > 0:
220            node.set_info({'filtered': True})
221   
222        # getting ports information
223
224        host_ports = host.ports
225        host_extraports = host.extraports
226        ports = []
227
228        for port in host_ports:
229            port = port.copy() # Do not change the original port
230            port['id'] = int(port['portid'])
231            # TODO: Not ready to integrate right now
232            #for script in xml_scripts:
233                #scripts.append(dict())
234                #for key in script.get_keys():
235                    #scripts[-1][key] = script.get_attr(key)
236
237            service = {}
238            # TODO: Get another information - NmapParser update need.
239            if 'name' in port:
240                service['name'] = port.pop('name')
241                service['version'] = port.pop('version', '')
242                service['method'] = port.pop('method', '')
243                service['product'] = port.pop('product', '')
244                service['extrainfo'] = port.pop('extrainfo', '')
245                service['conf'] = port.pop('conf', '')
246
247            port['state'] = {'state': port['state']}
248            port['scripts'] = {}
249            port['service'] = service
250
251            ports.append(port)
252
253        node.set_info({'ports':ports})
254
255        all_extraports = list()
256        #print host_extraports
257        for extraports in host_extraports:
258            extraports = extraports.copy() # Do not change the original eport
259            extraports['count'] = int(extraports['count'])
260            extraports['reason'] = list()
261            extraports['all_reason'] = list()
262   
263           
264            # TODO: implement this
265           
266            #xml_extrareasons = xml_extraport.search_children('extrareasons',
267                                                             #deep=True)
268   
269            #for extrareason in xml_extrareasons:
270   
271                #extraports['reason'].append(extrareason.get_attr('reason'))
272                #extraports['all_reason'].append(dict())
273           
274                #for key in extrareason.get_keys():
275   
276                    #value = extrareason.get_attr(key)
277   
278                    #if key == 'count':
279                        #value = int(value)
280   
281                    #extraports['all_reason'][-1][key] = value
282   
283            all_extraports.append(extraports)
284   
285        node.set_info({'extraports':all_extraports})
286   
287        # getting traceroute information
288        trace = host.trace.copy()
289        if trace and trace['hop']:
290   
291            host_hops = trace['hop']
292            hops = []
293   
294            for host_hop in host_hops:
295                hop = host_hop.copy()
296                hostname = host_hop.get('host', None)
297                hop['ttl'] = int(hop['ttl'])
298                hop['host'] = (hostname, '')[hostname is None]
299                if 'host' in hop:
300                    hop.pop('host')
301   
302                hops.append(hop)
303   
304            trace['hops'] = hops
305            trace['protocol'] = trace['proto']
306   
307            node.set_info({'trace':trace})
308
309       
310    def make(self, parse):
311        """
312        Make a Graph
313        """
314        #Get Hosts
315        hosts = parse.get_hosts()
316       
317        nodes = list()
318        index = 1
319       
320        # setting initial reference host
321        nodes.append(NetNode(0))
322        node = nodes[-1]
323
324        self.__set_default_values(node)
325       
326        # for each host in hosts just mount the graph
327        for host in hosts:
328            trace = host.trace.copy()
329            # if host has traceroute information mount graph
330            if trace and trace['hop']:
331               
332                prev_node = nodes[0]
333               
334                hops = trace['hop']
335                ttls = [int(hop['ttl']) for hop in hops]
336               
337                # getting nodes of host by ttl
338                for ttl in range(1, max(ttls) + 1):
339                    if ttl in ttls:
340                        _hop = host.get_hop_by_ttl(ttl)
341                        if _hop == None:
342                            continue
343                        hop = _hop.copy()
344                        for node in nodes:
345                            if hop['ipaddr'] == node.get_info('ip'):
346                                break
347   
348                        else:
349   
350                            nodes.append(NetNode(index))
351                            node = nodes[-1]
352                            index += 1
353   
354                            node.set_draw_info({'valid':True})
355                            node.set_info({'ip':hop['ipaddr']})
356                            node.set_draw_info({'color':(1,1,1),
357                                                'radius':NONE_RADIUS})
358                            if hop.has_key('host') and hop['host'] is not None:
359                                node.set_info(\
360                                    {'host':hop['host']})
361   
362                        rtt = hop['rtt']
363   
364                        if rtt != '--':
365                            self.set_connection(node, prev_node, float(rtt))
366   
367                        else:
368                            self.set_connection(node, prev_node)
369   
370                    else:
371   
372                        nodes.append(NetNode(index))
373                        node = nodes[-1]
374                        index += 1
375   
376                        node.set_draw_info({'valid':False})
377                        node.set_info({'ip':None, 'host':None})
378                        node.set_draw_info({'color':(1,1,1), \
379                                            'radius':NONE_RADIUS})
380   
381                        self.set_connection(node, prev_node)
382   
383                    prev_node = node                   
384           
385        # for each full scanned host
386        for host in hosts:
387   
388            for addr in host.address:
389                if addr['addrtype'] == 'ipv4':
390                    ip = addr
391                    break
392            else:
393                ip = {}
394            for node in nodes:
395                if ip.has_key('addr') and ip['addr'] == node.get_info('ip'):
396                    break
397   
398            else:
399   
400                nodes.append(NetNode(index))
401                node = nodes[-1]
402                index += 1
403   
404                node.set_draw_info({'no_route':True})
405   
406                self.set_connection(node, nodes[0])
407   
408            node.set_draw_info({'valid':True})
409            node.set_info({'scanned':True})
410            self.__set_node_info(node, host)
411   
412        self.set_nodes(nodes)
413        self.set_main_node_by_id(0)
414       
415
416# Test Develpment
417def main():
418    from umit.core.NmapParser import NmapParser
419    parser = NmapParser("../../umit-within-radialnet/RadialNet2/share/sample/nmap_example.xml")
420    #parser = NmapParser("RadialNet2/share/sample/no_trace.xml")
421    parser.parse()
422   
423    graph = GraphBuilder()
424    graph.make(parser)
425   
426
427if __name__=="__main__":
428    main()
429
430
431
Note: See TracBrowser for help on using the browser.