| 1 | # Copyright (C) 2007 Insecure.Com LLC. |
|---|
| 2 | # |
|---|
| 3 | # Authors: Guilherme Polo <ggpolo@gmail.com> |
|---|
| 4 | # |
|---|
| 5 | # This program is free software; you can redistribute it and/or modify |
|---|
| 6 | # it under the terms of the GNU General Public License as published by |
|---|
| 7 | # the Free Software Foundation; either version 2 of the License, or |
|---|
| 8 | # (at your option) any later version. |
|---|
| 9 | # |
|---|
| 10 | # This program is distributed in the hope that it will be useful, |
|---|
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | # GNU General Public License for more details. |
|---|
| 14 | # |
|---|
| 15 | # You should have received a copy of the GNU General Public License |
|---|
| 16 | # along with this program; if not, write to the Free Software |
|---|
| 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
|---|
| 18 | # USA |
|---|
| 19 | |
|---|
| 20 | import os |
|---|
| 21 | from ConfigParser import ConfigParser |
|---|
| 22 | |
|---|
| 23 | from umitCore.Paths import Path |
|---|
| 24 | from umitDB.Retrieve import InventoryRetrieve |
|---|
| 25 | |
|---|
| 26 | UMITDB = Path.umitdb_ng |
|---|
| 27 | |
|---|
| 28 | class InventoryLoad(InventoryRetrieve): |
|---|
| 29 | """ |
|---|
| 30 | Load Inventories data to be used in Network Inventory. |
|---|
| 31 | """ |
|---|
| 32 | |
|---|
| 33 | def __init__(self): |
|---|
| 34 | InventoryRetrieve.__init__(self, UMITDB) |
|---|
| 35 | |
|---|
| 36 | self.invdata = None |
|---|
| 37 | self.database_stat = None |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | def load_from_db(self): |
|---|
| 41 | """ |
|---|
| 42 | Load all inventories from database and return a dict in this format: |
|---|
| 43 | |
|---|
| 44 | inv_data = {'inventory A': set([(ipv4addr A, ipv6addr A, macaddr A, |
|---|
| 45 | (hostnameA, hostnameB, ..), |
|---|
| 46 | osmatch A), |
|---|
| 47 | (ipv4addr B, ipv6addr B, macaddr B, |
|---|
| 48 | (hostnameC, ..), osmatch B), ... |
|---|
| 49 | ]), |
|---|
| 50 | 'inventory B': ... |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | Each item inside set represent a host inside the 'inventory name'. |
|---|
| 54 | """ |
|---|
| 55 | |
|---|
| 56 | inv_data = { } |
|---|
| 57 | |
|---|
| 58 | # Grab Inventories names |
|---|
| 59 | # from schemas file |
|---|
| 60 | schemas = ConfigParser() |
|---|
| 61 | schemas.read(Path.sched_schemas) |
|---|
| 62 | |
|---|
| 63 | for section in schemas.sections(): |
|---|
| 64 | if schemas.get(section, 'addtoinv') in ('1', '2'): |
|---|
| 65 | inv_data[section] = set() |
|---|
| 66 | # from database |
|---|
| 67 | invs = self.get_inventories_names() |
|---|
| 68 | for i in invs: |
|---|
| 69 | if not i[0] in inv_data: |
|---|
| 70 | # inventory created from umit interface |
|---|
| 71 | inv_data[i[0]] = set() |
|---|
| 72 | |
|---|
| 73 | # check if database haven't changed since last time |
|---|
| 74 | if self.database_stat == os.stat(UMITDB).st_mtime: |
|---|
| 75 | # data has been loaded already, maybe a new Inventory was |
|---|
| 76 | # added in schemas file only, let me check here: |
|---|
| 77 | n_invs = set(inv_data.keys()).difference(set(self.invdata.keys())) |
|---|
| 78 | for new_i in n_invs: |
|---|
| 79 | self.invdata[new_i] = set() |
|---|
| 80 | |
|---|
| 81 | # return cached data with new inventories if any |
|---|
| 82 | return self.invdata |
|---|
| 83 | |
|---|
| 84 | self.database_stat = os.stat(UMITDB).st_mtime |
|---|
| 85 | |
|---|
| 86 | # ToDo: it would be good to do some kind of caching here or in |
|---|
| 87 | # database, so we can stop doing so many queries. |
|---|
| 88 | |
|---|
| 89 | # Retrieve hosts for each Inventory |
|---|
| 90 | for inv in inv_data.keys(): |
|---|
| 91 | invid = self.get_inventory_id_for_name(inv) |
|---|
| 92 | |
|---|
| 93 | if not invid: |
|---|
| 94 | # this Inventory has been created but it is not on database |
|---|
| 95 | # yet because no scan has been finished yet. |
|---|
| 96 | continue |
|---|
| 97 | |
|---|
| 98 | scans_ids = self.get_scans_id_for_inventory(invid) |
|---|
| 99 | |
|---|
| 100 | if not scans_ids: |
|---|
| 101 | # this Inventory has no associated scans with it, one possible |
|---|
| 102 | # reason: all scans for the Inventory were deleted |
|---|
| 103 | continue |
|---|
| 104 | |
|---|
| 105 | for scan in scans_ids: |
|---|
| 106 | scan_hosts = set() # will store hosts in current scan |
|---|
| 107 | |
|---|
| 108 | # retrieve hosts id for each scan |
|---|
| 109 | hosts = self.get_hosts_id_for_scan_from_db(scan[0]) |
|---|
| 110 | hosts = [h[0] for h in hosts] |
|---|
| 111 | |
|---|
| 112 | if len(hosts) <= len(inv_data[inv]): |
|---|
| 113 | # no new hosts found |
|---|
| 114 | continue |
|---|
| 115 | |
|---|
| 116 | #for host in self.get_hosts_id_for_scan_from_db(scan[0]): |
|---|
| 117 | for host in hosts: |
|---|
| 118 | |
|---|
| 119 | os_host = self.get_osshort_for_host_from_db(host) |
|---|
| 120 | ipv4addr = self.get_ipv4_for_host_from_db(host) |
|---|
| 121 | ipv6addr = self.get_ipv6_for_host_from_db(host) |
|---|
| 122 | macaddr = self.get_mac_for_host_from_db(host) |
|---|
| 123 | hostnames = self.get_hostnames_for_host_from_db(host) |
|---|
| 124 | |
|---|
| 125 | scan_hosts.add((ipv4addr, ipv6addr, macaddr, hostnames, |
|---|
| 126 | os_host)) |
|---|
| 127 | |
|---|
| 128 | if scan_hosts != inv_data[inv] and \ |
|---|
| 129 | len(scan_hosts) > len(inv_data[inv]): # new hosts found |
|---|
| 130 | inv_data[inv] = scan_hosts |
|---|
| 131 | |
|---|
| 132 | self.invdata = inv_data |
|---|
| 133 | return inv_data |
|---|