summaryrefslogtreecommitdiff
path: root/monitor/josef_leveldb.py
blob: ef6437e34206e2e16fed28178c54a29202cdff7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#!/usr/bin/python
# -*- coding: utf-8 -*-     

import sys
from josef_lib import *
import leveldb
import ast

SEP = ";"
dbs = {}





def match_domain(d1, d2):
    # Exact match
    if str(d1) == str(d2):
        return True
    
    # Wildcard match
    d1l = d1.split('.')
    d2l = d2.split('.')

    if d1l[0] == '*':
        if d1l[1:] == d2l[-(len(d1l)-1):]:
            return True

    if d2l[0] == '*':
        if d2l[1:] == d1l[-(len(d2l)-1):]:
            return True

    # No match
    return False


def db_open(fn='./cert_db'):
    global dbs
    if fn in dbs:
        return dbs[fn]
    else:
        db = leveldb.LevelDB(fn)
        dbs[fn] = db
        return db

def db_close():
    for db in dbs:
        del db        

def db_append(db, key, val):
    if db is None:
        print "ERROR: NO DATABASE SET!"
        return

    try:
        tmp = db.Get(key)
    except KeyError:
        tmp = ""
    tmpl = tmp.split(SEP)
    if val in tmpl:
        pass
    else:
        tmpl.append(val)
        # print "Storing:",key,SEP.join(tmpl)
        db.Put(key,SEP.join(tmpl))

def db_add_domain_2(db_dir, key_in, val_in, db_in=None):
    if db_in == None:
        val = "###" + ast.literal_eval(val_in)["leaf_hash"]
        cert_db = db_open(db_dir + "certificates")
        # print "Storing: ",val,val_in
        cert_db.Put(val, val_in)

        key_list  = key_in.split('/')[0].split(',')[0].split('.')
        if key_list[-1] == "com":
            key  = '.'.join(key_list[:-1])
            db = db_open(db_dir + key_list[-1])
        else:
            key  = '.'.join(key_list)
            db = db_open(db_dir + "other")
    else:
        db = db_in 
        key = key_in
        val = val_in

    try:
        tmp = db.Get(key)
        tmpl = tmp.split(SEP)
        if val in tmpl:
            return
        else:
            tmpl.append(val)
            # print "Storing: ",key,SEP.join(tmpl)
            db.Put(key,SEP.join(tmpl))
            
    except KeyError:
        # print "Storing: ",key,SEP.join([val])
        db.Put(key,SEP.join([val]))
        new_key = key.split('.',1)[-1]
        if new_key != key:
            db_add_domain_2(db_dir,new_key,key, db)


def db_add_certs(db_dir, data):
    if db_dir is None:
        print "ERROR: NO DATABASE SET!"
        return

    for cert in data:
        try:
            db_add_domain_2(db_dir, cert["subject"].split("CN=")[1], str(cert))
        except IndexError:
            pass
        try:
            for line in cert["SAN"].split("DNS:")[1:]:
                db_add_domain_2(db_dir, line, str(cert))
        except KeyError:
            pass
        except IndexError:
            pass


def db_lookup_domain(db_dir, domain):
    domain_list = domain.split('.')
    res = []

    if domain_list[-1] == "com":
        db = db_open(db_dir + domain_list[-1])
        domain_list = domain_list[:-1]
        key  = '.'.join(domain_list)
    else:
        key  = '.'.join(domain)
        db = db_open(db_dir + "other")

    cur_domain = domain_list.pop()
    try:
        intermediate = db.Get(cur_domain).split(SEP)
    except KeyError:
        return []

    last = False
    one_more = False
    while True:
        try:
            intermediate.remove("")
        except ValueError:
            pass

        try:
            cur_domain = domain_list.pop() + "." + cur_domain
        except IndexError:
            break
        # Prune
        next_level = []
        for item in intermediate:
            if match_domain(cur_domain, item):
                try:
                    tmp = db.Get(item).split(SEP)
                    for tmp_item in tmp:
                        # This is really not a good solution...
                        if tmp_item[0:3] == "###":
                            res.append(tmp_item[3:])
                        else:
                            next_level.append(tmp_item)
                except KeyError:
                    pass
        intermediate = next_level

    certs = []
    cert_db = db_open(db_dir + "certificates")
    for item in res:
        tmp = cert_db.Get("###" + str(item))
        certs.append(tmp)

    return certs