root/trunk/umitCore/UmitDB.py @ 3879

Revision 3879, 9.3 kB (checked in by getxsick, 4 years ago)

Added extra information for users if sqlite is not installed and fixed grammar bug

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Copyright (C) 2005-2006 Insecure.Com LLC.
5# Copyright (C) 2007-2008 Adriano Monteiro Marques
6#
7# Author: Adriano Monteiro Marques <adriano@umitproject.org>
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
23import md5
24
25from umitCore.I18N import _
26
27sqlite = None
28OperationalError = None
29try:
30    from pysqlite2 import dbapi2 as sqlite
31    from pysqlite2.dbapi2 import OperationalError
32except ImportError:
33    try:
34        # In case this script is being running under python2.5 with sqlite3
35        import sqlite3 as sqlite
36    except ImportError:
37        raise ImportError(_("""No module named pysqlite2 or sqlite3.
38            Please install pysqlite2 or sqlite3."""))
39    from sqlite3 import OperationalError
40
41from time import time
42
43from umitCore.Paths import Path
44from umitCore.UmitLogging import log
45
46
47umitdb = ""
48
49try:
50    umitdb = Path.umitdb
51except:
52    import os.path
53    from BasePaths import base_paths
54   
55    umitdb = os.path.join(Path.config_dir, base_paths["umitdb"])
56    Path.umitdb = umitdb
57
58
59from os.path import exists, dirname
60from os import access, R_OK, W_OK
61
62
63using_memory = False
64connection = None
65try:
66    connection = sqlite.connect(umitdb)
67except OperationalError:
68    using_memory = True
69    connection = sqlite.connect(":memory:")
70
71
72class Table(object):
73    def __init__(self, table_name):
74        self.table_name = table_name
75        self.table_id = "%s_id" % table_name
76       
77        self.cursor = connection.cursor()
78   
79    def get_item(self, item_name):
80        if self.__getattribute__("_%s" % item_name):
81            return self.__getattribute__("_%s" % item_name)
82
83        sql = "SELECT %s FROM %s WHERE %s_id = %s" % (item_name,
84                                                      self.table_name,
85                                                      self.table_name,
86                                           self.__getattribute__(self.table_id))
87
88        self.cursor.execute(sql)
89       
90        self.__setattr__("_%s" % item_name, self.cursor.fetchall()[0][0])
91        return self.__getattribute__("_%s" % item_name)
92
93    def set_item(self, item_name, item_value):
94        if item_value == self.__getattribute__("_%s" % item_name):
95            return None
96       
97        sql = "UPDATE %s SET %s = ? WHERE %s_id = %s" % (self.table_name,
98                                                         item_name,
99                                                         self.table_name,
100                                           self.__getattribute__(self.table_id))
101        self.cursor.execute(sql, (item_value,))
102        connection.commit()
103        self.__setattr__("_%s" % item_name, item_value)
104
105    def insert(self, **kargs):
106        sql = "INSERT INTO %s ("
107        for k in kargs.keys():
108            sql += k
109            sql += ", "
110        else:
111            sql = sql[:][:-2]
112            sql += ") VALUES ("
113           
114        for v in xrange(len(kargs.values())):
115            sql += "?, "
116        else:
117            sql = sql[:][:-2]
118            sql += ")"
119
120        sql %= self.table_name
121       
122        self.cursor.execute(sql, tuple(kargs.values()))
123        connection.commit()
124
125        sql = "SELECT MAX(%s_id) FROM %s;" % (self.table_name, self.table_name)
126        self.cursor.execute(sql)
127        return self.cursor.fetchall()[0][0]
128
129class UmitDB(object):
130    def __init__(self):
131        self.cursor = connection.cursor()
132
133    def create_db(self):
134        drop_string = ("DROP TABLE scans;",)
135       
136        try:
137            for d in drop_string:
138                self.cursor.execute(d)
139        except:
140            connection.rollback()
141        else:
142            connection.commit()
143
144       
145        creation_string = ("""CREATE TABLE scans (scans_id INTEGER \
146                                                  PRIMARY KEY AUTOINCREMENT,
147                                                  scan_name TEXT,
148                                                  nmap_xml_output TEXT,
149                                                  digest TEXT,
150                                                  date INTEGER)""",)
151
152        for c in creation_string:
153            self.cursor.execute(c)
154            connection.commit()
155
156    def add_scan(self, **kargs):
157        return Scans(**kargs)
158
159    def get_scans_ids(self):
160        sql = "SELECT scans_id FROM scans;"
161        self.cursor.execute(sql)
162        return [sid[0] for sid in self.cursor.fetchall()]
163
164    def get_scans(self):
165        scans_ids = self.get_scans_ids()
166        for sid in scans_ids:
167            yield Scans(scans_id=sid)
168
169    def cleanup(self, save_time):
170        log.debug(">>> Cleanning up data base.")
171        log.debug(">>> Removing results olders than %s seconds" % save_time)
172        self.cursor.execute("SELECT scans_id FROM scans WHERE date < ?",
173                            (time() - save_time,))
174       
175        for sid in [sid[0] for sid in self.cursor.fetchall()]:
176            log.debug(">>> Removing results with scans_id %s" % sid)
177            self.cursor.execute("DELETE FROM scans WHERE scans_id = ?", (sid, ))
178        else:
179            connection.commit()
180            log.debug(">>> Data base sucessfully cleanned up!")
181       
182
183class Scans(Table, object):
184    def __init__(self, **kargs):
185        Table.__init__(self, "scans")
186        if "scans_id" in kargs.keys():
187            self.scans_id = kargs["scans_id"]
188        else:
189            log.debug(">>>Ceating new scan result entry at data base")
190            fields = ["scan_name", "nmap_xml_output", "date"]
191           
192            for k in kargs.keys():
193                if k not in fields:
194                    raise Exception("Wrong table field passed to creation \
195method. '%s'" % k)
196
197            if "nmap_xml_output" not in kargs.keys() or \
198               not kargs["nmap_xml_output"]:
199                raise Exception("Can't save result without xml output")
200
201            if not self.verify_digest(md5.new(kargs["nmap_xml_output"]).\
202                                      hexdigest()):
203                raise Exception("XML output registered already!")
204           
205            self.scans_id = self.insert(**kargs)
206
207    def verify_digest(self, digest):
208        self.cursor.execute("SELECT scans_id FROM scans WHERE digest = ?",
209                            (digest, ))
210        result = self.cursor.fetchall()
211        if result:
212            return False
213        return True
214
215    def add_host(self, **kargs):
216        kargs.update({self.table_id:self.scans_id})
217        return Hosts(**kargs)
218
219    def get_hosts(self):
220        sql = "SELECT hosts_id FROM hosts WHERE scans_id= %s" % self.scans_id
221       
222        self.cursor.execute(sql)
223        result = self.cursor.fetchall()
224       
225        for h in result:
226            yield Hosts(hosts_id=h[0])
227
228    def get_scans_id(self):
229        return self._scans_id
230
231    def set_scans_id(self, scans_id):
232        if scans_id != self._scans_id:
233            self._scans_id = scans_id
234
235    def get_scan_name(self):
236        return self.get_item("scan_name")
237
238    def set_scan_name(self, scan_name):
239        self.set_item("scan_name", scan_name)
240
241    def get_nmap_xml_output(self):
242        return self.get_item("nmap_xml_output")
243
244    def set_nmap_xml_output(self, nmap_xml_output):
245        self.set_item("nmap_xml_output", nmap_xml_output)
246        self.set_item("digest", md5.new(nmap_xml_output).hexdigest())
247
248    def get_date(self):
249        return self.get_item("date")
250
251    def set_date(self, date):
252        self.set_item("date", date)
253   
254    scans_id = property(get_scans_id, set_scans_id)
255    scan_name = property(get_scan_name, set_scan_name)
256    nmap_xml_output = property(get_nmap_xml_output, set_nmap_xml_output)
257    date = property(get_date, set_date)
258   
259    _scans_id = None
260    _scan_name = None
261    _nmap_xml_output = None
262    _date = None
263
264
265######################################################################
266# Verify if data base exists and if it does have the required tables.
267# If something is wrong, re-create table
268def verify_db():
269    cursor = connection.cursor()
270    try:
271        cursor.execute("SELECT scans_id FROM scans WHERE date = 0")
272    except sqlite.OperationalError:
273        u = UmitDB()
274        u.create_db()
275verify_db()
276
277######################################################################
278
279if __name__ == "__main__":
280    from pprint import pprint
281    import psyco
282    psyco.profile()
283   
284    u = UmitDB()
285
286    #print "Creating Data Base"
287    #u.create_db()
288
289    #print "Creating new scan"
290    #s = u.add_scan(scan_name="Fake scan", nmap_xml_output="", date="007")
291
292    #s = Scans(scans_id=2)
293    #print s.scans_id
294    #print s.scan_name
295    #print s.nmap_xml_output
296    #print s.date
297   
298    sql = "SELECT * FROM scans;"
299    u.cursor.execute(sql)
300    print "Scans:",
301    pprint(u.cursor.fetchall())
Note: See TracBrowser for help on using the browser.