Add a tool for accessing encrypted database
[platform/core/security/key-manager.git] / src / manager / service / db-crypto.h
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        db-crypto.h
18  * @author      Zofia Abramowska (z.abramowska@samsung.com)
19  * @version     1.0
20  * @brief       Header of encrypted db access layer
21  */
22
23 #ifndef DB_CRYPTO_H
24 #define DB_CRYPTO_H
25
26 #include <vector>
27 #include <string>
28
29 #include <dpl/db/sql_connection.h>
30
31 #include <ckm/ckm-type.h>
32 #include <db-row.h>
33 #include <permission.h>
34 #include <protocols.h>
35
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
38
39 namespace CKM {
40 namespace DB {
41     class Crypto {
42          public:
43             typedef boost::optional<Row> RowOptional;
44             typedef boost::optional<RawBuffer> RawBufferOptional;
45             class Exception
46             {
47             public:
48                 DECLARE_EXCEPTION_TYPE(CKM::Exception, Base)
49                 DECLARE_EXCEPTION_TYPE(Base, InternalError)
50                 DECLARE_EXCEPTION_TYPE(Base, TransactionError)
51                 DECLARE_EXCEPTION_TYPE(Base, InvalidArgs)
52             };
53             Crypto() :
54                 m_connection(NULL),
55                 m_inUserTransaction(false)
56               {};
57             // user name instead of path?
58             Crypto(const std::string &path, const RawBuffer &rawPass);
59             Crypto(const Crypto &other) = delete;
60             Crypto(Crypto &&other);
61
62             Crypto& operator=(const Crypto& ) = delete;
63             Crypto& operator=(Crypto&& other);
64
65             virtual ~Crypto();
66
67             void saveRow(
68                     const Row &row);
69
70             void saveRows(
71                     const Name &name,
72                     const Label &owner,
73                     const RowVector &rows);
74
75             bool isNameLabelPresent(
76                     const Name &name,
77                     const Label &owner) const;
78
79             RowOptional getRow(
80                     const Name &name,
81                     const Label &ownerLabel,
82                     DataType type);
83
84             RowOptional getRow(
85                     const Name &name,
86                     const Label &ownerLabel,
87                     DataType typeRangeStart,
88                     DataType typeRangeStop);
89
90             void getRows(
91                     const Name &name,
92                     const Label &ownerLabel,
93                     DataType type,
94                     RowVector &output);
95
96             void getRows(
97                     const Name &name,
98                     const Label &ownerLabel,
99                     DataType typeRangeStart,
100                     DataType typeRangeStop,
101                     RowVector &output);
102
103             void listNames(
104                     const Label &smackLabel,
105                     LabelNameVector& labelNameVector,
106                     DataType type);
107
108             void listNames(
109                     const Label &smackLabel,
110                     LabelNameVector& labelNameVector,
111                     DataType typeRangeStart,
112                     DataType typeRangeStop);
113
114             bool deleteRow(
115                     const Name &name,
116                     const Label &ownerLabel);
117
118             std::string getSchema();
119
120             std::string getContent();
121
122             // keys
123             void saveKey(const Label& label, const RawBuffer &key);
124             RawBufferOptional getKey(const Label& label);
125             void deleteKey(const Label& label);
126
127
128             // permissions
129             void setPermission(
130                     const Name &name,
131                     const Label &ownerLabel,
132                     const Label &accessorLabel,
133                     const PermissionMask permissionMask);
134
135             PermissionMaskOptional getPermissionRow(
136                     const Name &name,
137                     const Label &ownerLabel,
138                     const Label &accessorLabel) const;
139
140
141             // transactions
142             int beginTransaction();
143             int commitTransaction();
144             int rollbackTransaction();
145
146             class Transaction {
147             public:
148                 Transaction(Crypto *db)
149                     : m_db(db),
150                       m_inTransaction(false) {
151                     if(!m_db->m_inUserTransaction) {
152                         Try {
153                             m_db->m_connection->ExecCommand("BEGIN EXCLUSIVE");
154                             m_db->m_inUserTransaction = true;
155                             m_inTransaction = true;
156                         } Catch (SqlConnection::Exception::InternalError) {
157                             LogError("sqlite got into infinite busy state");
158                             ReThrow(Crypto::Exception::TransactionError);
159                         } Catch (SqlConnection::Exception::Base) {
160                             LogError("Couldn't begin transaction");
161                             ReThrow(Crypto::Exception::TransactionError);
162                         }
163                     }
164                 }
165                 void commit() {
166                     if(m_inTransaction) {
167                         Try {
168                             m_db->m_connection->CommitTransaction();
169                             m_db->m_inUserTransaction = false;
170                             m_inTransaction = false;
171                         } Catch (SqlConnection::Exception::InternalError) {
172                             LogError("sqlite got into infinite busy state");
173                             ReThrow(Crypto::Exception::TransactionError);
174                         } Catch (SqlConnection::Exception::Base) {
175                             LogError("Couldn't commit transaction");
176                             ReThrow(Crypto::Exception::TransactionError);
177                         }
178                     }
179                 }
180                 void rollback() {
181                     if(m_inTransaction) {
182                         Try {
183                             m_db->m_connection->RollbackTransaction();
184                             m_db->m_inUserTransaction = false;
185                             m_inTransaction = false;
186                         } Catch (SqlConnection::Exception::InternalError) {
187                             LogError("sqlite got into infinite busy state");
188                             ReThrow(Crypto::Exception::TransactionError);
189                         } Catch (SqlConnection::Exception::Base) {
190                             LogError("Couldn't rollback transaction");
191                             ReThrow(Crypto::Exception::TransactionError);
192                         }
193                     }
194                 }
195                 ~Transaction() {
196                     Try {
197                         if(m_inTransaction) {
198                             m_db->m_inUserTransaction = false;
199                             m_db->m_connection->RollbackTransaction();
200                         }
201                     } Catch (SqlConnection::Exception::InternalError) {
202                         LogError("sqlite got into infinite busy state");
203                         ReThrow(Crypto::Exception::TransactionError);
204                     } Catch (SqlConnection::Exception::Base) {
205                         LogError("Transaction rollback failed!");
206                     }
207                 }
208             private:
209                 Crypto *m_db;
210                 bool m_inTransaction;
211             };
212
213          protected:
214             SqlConnection* m_connection;
215          private:
216             bool m_inUserTransaction;
217
218             void resetDB();
219             void initDatabase();
220             void createDBSchema();
221             /**
222              * return current database version
223              *
224              * @param[out] schemaVersion    if success, will contain DB schema version code
225              *
226              * @return false on DB empty or corrupted, true if information read
227              */
228             bool getDBVersion(int & schemaVersion);
229             typedef boost::optional<std::string> ScriptOptional;
230             ScriptOptional getScript(const std::string &scriptName) const;
231             ScriptOptional getMigrationScript(int db_version) const;
232
233             Row getRow(
234                     const SqlConnection::DataCommandUniquePtr &selectCommand) const;
235
236             void createTable(
237                     const char *create_cmd,
238                     const char *table_name);
239
240             void createView(
241                     const char* create_cmd);
242
243             class SchemaInfo {
244             public:
245                 explicit SchemaInfo(const Crypto *db) : m_db(db) {}
246
247                 void        setVersionInfo();
248                 bool        getVersionInfo(int & version) const;
249
250             private:
251                 const Crypto *m_db;
252             };
253
254         public:
255             class NameTable {
256             public:
257                 explicit NameTable(SqlConnection* connection) : m_connection(connection) {}
258
259                 void addRow(
260                         const Name &name,
261                         const Label &ownerLabel);
262
263                 void deleteRow(
264                         const Name &name,
265                         const Label &ownerLabel);
266
267                 void deleteAllRows(
268                         const Label &ownerLabel);
269
270                 bool isPresent(
271                         const Name &name,
272                         const Label &ownerLabel) const;
273
274             private:
275                 SqlConnection* m_connection;
276             };
277
278             class ObjectTable {
279             public:
280                 explicit ObjectTable(SqlConnection* connection) : m_connection(connection) {}
281
282                 void addRow(
283                         const Row &row);
284
285             private:
286                 SqlConnection* m_connection;
287             };
288
289             class PermissionTable {
290             public:
291                 explicit PermissionTable(SqlConnection* connection) : m_connection(connection) {}
292
293                 void setPermission(
294                         const Name &name,
295                         const Label &ownerLabel,
296                         const Label &accessorLabel,
297                         const PermissionMask permissionMask);
298
299                 PermissionMaskOptional getPermissionRow(
300                         const Name &name,
301                         const Label &ownerLabel,
302                         const Label &accessorLabel) const;
303
304             private:
305                 SqlConnection* m_connection;
306             };
307     };
308 } // namespace DB
309 } // namespace CKM
310
311 #pragma GCC diagnostic pop
312 #endif //DB_CRYPTO_H
313