]>
Commit | Line | Data |
---|---|---|
8c4f590c MR |
1 | # -*- coding: utf-8 -*- |
2 | ||
3 | # Copyright (c) 2018 Michael Rasmussen <mir@datanom.net> | |
4 | ||
5 | # This file is part of SecureMail. | |
6 | ||
7 | # SecureMail 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 3 of the License, or | |
10 | # (at your option) any later version. | |
11 | # | |
12 | # SecureMail 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 SecureMail. If not, see <https://www.gnu.org/licenses/>. | |
19 | ||
7084ca4a | 20 | # sqlite |
6004ded9 MR |
21 | sqlite_sql = """create table account ( |
22 | id int auto_increment, | |
23 | token char(128) unique not null, | |
24 | cipher text not null, | |
25 | primary key (id))""" | |
26 | ||
d65fab5a | 27 | # mysql |
6004ded9 MR |
28 | mysql_sql = """create table account ( |
29 | id int auto_increment, | |
30 | token char(128) unique not null, | |
31 | cipher text not null, | |
32 | primary key (id))""" | |
33 | ||
d65fab5a | 34 | # postgresql |
6004ded9 MR |
35 | postgresql_sql = """create table account ( |
36 | id serial, | |
37 | token char(128) unique not null, | |
38 | cipher bytea not null, | |
39 | primary key (id))""" | |
d65fab5a MR |
40 | |
41 | import base64 | |
7084ca4a MR |
42 | from config import DBTYPE, DBNAME |
43 | try: | |
44 | from config import DBUID | |
45 | except ImportError: | |
46 | DBUID = 'backend' | |
47 | try: | |
48 | from config import DBPWD | |
49 | except ImportError: | |
50 | DBPWD = 'clV77B2ZJQxr' | |
51 | try: | |
52 | from config import DBHOST | |
53 | except ImportError: | |
54 | DBHOST = 'localhost' | |
55 | try: | |
56 | from config import DBPORT | |
57 | except ImportError: | |
58 | if DBTYPE == 'mysql': | |
59 | DBPORT = 3306 | |
60 | elif DBTYPE == 'postgresql': | |
61 | DBPORT = 5432 | |
d65fab5a | 62 | from cryptonize import Cryptonize |
8c4f590c MR |
63 | |
64 | class Singleton: | |
65 | def __init__(self, klass): | |
66 | self.klass = klass | |
67 | self.instance = None | |
68 | ||
69 | def __call__(self, *args, **kwargs): | |
70 | if self.instance == None: | |
71 | self.instance = self.klass(*args, **kwargs) | |
72 | return self.instance | |
73 | ||
74 | @Singleton | |
75 | class DB: | |
76 | conn = None | |
77 | ||
78 | def get_connection(self): | |
79 | if self.conn is None: | |
80 | if DBTYPE == 'mysql': | |
d65fab5a | 81 | import MySQLdb |
d5c0fb7f | 82 | self.conn = MySQLdb.connect(host=DBHOST, port=DBPORT, user=DBUID, passwd=DBPWD, db=DBNAME) |
8c4f590c MR |
83 | elif DBTYPE == 'postgresql': |
84 | import psycopg2 | |
85 | self.conn = psycopg2.connect(host=DBHOST, port=DBPORT, user=DBUID, password=DBPWD, dbname=DBNAME) | |
7084ca4a MR |
86 | elif DBTYPE == 'sqlite': |
87 | import apsw | |
88 | self.conn = apsw.Connection('./{0}.db'.format(DBNAME)) | |
d65fab5a MR |
89 | else: |
90 | raise ValueError('{0}: Unsupported database'.format(DBTYPE)) | |
8c4f590c MR |
91 | return self.conn |
92 | ||
93 | def __del__(self): | |
94 | if self.conn is not None: | |
95 | self.conn.close() | |
96 | ||
97 | class DBInterface: | |
98 | @staticmethod | |
99 | def load_user(key): | |
100 | conn = DB().get_connection() | |
101 | cursor = conn.cursor() | |
d65fab5a | 102 | cursor.execute("select a.cipher from account a where token = '{0}'".format(key)) |
8c4f590c MR |
103 | row = cursor.fetchone() |
104 | if row is None: | |
105 | obj = None | |
106 | else: | |
d65fab5a MR |
107 | c = Cryptonize() |
108 | msg = base64.b64decode(row[0]) | |
109 | obj = c.create_EncryptedMessage(msg) | |
8c4f590c MR |
110 | cursor.close() |
111 | ||
112 | return obj | |
113 | ||
114 | @staticmethod | |
115 | def store_user(key, cipher): | |
d65fab5a MR |
116 | if DBTYPE == 'mysql': |
117 | from MySQLdb import Error as DBError | |
118 | elif DBTYPE == 'postgresql': | |
119 | from psycopg2 import Error as DBError | |
7084ca4a MR |
120 | elif DBTYPE == 'sqlite': |
121 | from apsw import Error as DBError | |
8c4f590c MR |
122 | conn = DB().get_connection() |
123 | cursor = conn.cursor() | |
d65fab5a MR |
124 | raw = base64.b64encode(cipher) |
125 | try: | |
7084ca4a MR |
126 | if DBTYPE != 'sqlite': |
127 | cursor.execute("insert into account(token, cipher) values(%s, %s)", (key, raw)) | |
128 | conn.commit() | |
129 | else: | |
130 | cursor.execute('begin') | |
131 | cursor.execute("insert into account(token, cipher) values(?, ?)", (key, raw)) | |
132 | cursor.execute('commit') | |
d65fab5a MR |
133 | except DBError as e: |
134 | print (e) | |
7084ca4a MR |
135 | if DBTYPE != 'sqlite': |
136 | conn.rollback() | |
137 | else: | |
138 | cursor.execute('rollback') | |
d65fab5a MR |
139 | raise e |
140 | finally: | |
141 | cursor.close() | |
6004ded9 MR |
142 | |
143 | @staticmethod | |
144 | def create_database(): | |
145 | if DBTYPE == 'mysql': | |
146 | from MySQLdb import Error as DBError | |
147 | elif DBTYPE == 'postgresql': | |
148 | from psycopg2 import Error as DBError | |
149 | elif DBTYPE == 'sqlite': | |
150 | from apsw import Error as DBError | |
151 | conn = DB().get_connection() | |
152 | cursor = conn.cursor() | |
153 | try: | |
154 | if DBTYPE != 'sqlite': | |
155 | if DBTYPE == 'mysql': | |
156 | sql = mysql_sql | |
157 | elif DBTYPE == 'postgresql': | |
158 | sql = postgresql_sql | |
159 | cursor.execute(sql) | |
160 | conn.commit() | |
161 | else: | |
162 | cursor.execute('begin') | |
163 | cursor.execute(sqlite_sql) | |
164 | cursor.execute('commit') | |
165 | except DBError as e: | |
6004ded9 MR |
166 | if DBTYPE != 'sqlite': |
167 | conn.rollback() | |
168 | else: | |
169 | cursor.execute('rollback') | |
170 | raise e | |
171 | finally: | |
172 | cursor.close() | |
173 | ||
174 | def main(): | |
175 | from optparse import OptionParser | |
176 | ||
177 | usage = "usage: %prog [options] arg" | |
178 | parser = OptionParser(usage) | |
179 | parser.add_option("-c", "--create", action="store_true", dest="create", | |
180 | help="Create tables in database using config.py", default=False) | |
181 | parser.add_option("-v", "--verbose", action="store_true", dest="verbose", | |
182 | help="Run in verbose mode", default=False) | |
183 | (options, args) = parser.parse_args() | |
184 | ||
185 | if options.create: | |
186 | try: | |
187 | if options.verbose: | |
188 | print("Creating empty database") | |
189 | print("Database Engine: {0}".format(DBTYPE)) | |
190 | if DBTYPE != 'sqlite': | |
191 | print("Database Host: {0}".format(DBHOST)) | |
192 | print("Database Port: {0}".format(DBPORT)) | |
193 | else: | |
194 | print("Database File: ./{0}.db".format(DBNAME)) | |
195 | DBInterface.create_database() | |
196 | print("Database created") | |
197 | except Exception as e: | |
198 | print("Creating database failed!") | |
199 | print(e) | |
200 | ||
201 | if __name__ == '__main__': | |
202 | main() |