Adapt SQLConnection to sqlcipher
[platform/core/security/key-manager.git] / src / manager / dpl / db / include / dpl / db / sql_connection.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        sql_connection.h
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of SQL connection
21  */
22 #ifndef CKM_SQL_CONNECTION_H
23 #define CKM_SQL_CONNECTION_H
24
25 #include <dpl/noncopyable.h>
26 #include <dpl/exception.h>
27 #include <dpl/availability.h>
28 #include <memory>
29 #include <boost/optional.hpp>
30 #include <dpl/string.h>
31 #include <dpl/log/log.h>
32 #include <sqlcipher.h>
33 #include <string>
34 #include <dpl/assert.h>
35 #include <stdint.h>
36 #include <vector>
37
38 namespace CKM {
39 namespace DB {
40 /**
41  * SQL connection class
42  */
43 class SqlConnection
44 {
45   public:
46     /**
47      * SQL Exception classes
48      */
49     class Exception
50     {
51       public:
52         DECLARE_EXCEPTION_TYPE(CKM::Exception, Base)
53         DECLARE_EXCEPTION_TYPE(Base, SyntaxError)
54         DECLARE_EXCEPTION_TYPE(Base, ConnectionBroken)
55         DECLARE_EXCEPTION_TYPE(Base, InternalError)
56         DECLARE_EXCEPTION_TYPE(Base, InvalidColumn)
57         DECLARE_EXCEPTION_TYPE(Base, InvalidArguments)
58     };
59
60     typedef int ColumnIndex;
61     typedef int ArgumentIndex;
62
63     /*
64      * SQL processed data command
65      */
66     class DataCommand :
67         private Noncopyable
68     {
69       private:
70         SqlConnection *m_masterConnection;
71         sqlcipher3_stmt *m_stmt;
72
73         void CheckBindResult(int result);
74         void CheckColumnIndex(SqlConnection::ColumnIndex column);
75
76         DataCommand(SqlConnection *connection, const char *buffer);
77
78         friend class SqlConnection;
79
80       public:
81         virtual ~DataCommand();
82
83         /**
84          * Bind null to the prepared statement argument
85          *
86          * @param position Index of argument to bind value to
87          */
88         void BindNull(ArgumentIndex position);
89
90         /**
91          * Bind int to the prepared statement argument
92          *
93          * @param position Index of argument to bind value to
94          * @param value Value to bind
95          */
96         void BindInteger(ArgumentIndex position, int value);
97
98         /**
99          * Bind int8_t to the prepared statement argument
100          *
101          * @param position Index of argument to bind value to
102          * @param value Value to bind
103          */
104         void BindInt8(ArgumentIndex position, int8_t value);
105
106         /**
107          * Bind int16 to the prepared statement argument
108          *
109          * @param position Index of argument to bind value to
110          * @param value Value to bind
111          */
112         void BindInt16(ArgumentIndex position, int16_t value);
113
114         /**
115          * Bind int32 to the prepared statement argument
116          *
117          * @param position Index of argument to bind value to
118          * @param value Value to bind
119          */
120         void BindInt32(ArgumentIndex position, int32_t value);
121
122         /**
123          * Bind int64 to the prepared statement argument
124          *
125          * @param position Index of argument to bind value to
126          * @param value Value to bind
127          */
128         void BindInt64(ArgumentIndex position, int64_t value);
129
130         /**
131          * Bind float to the prepared statement argument
132          *
133          * @param position Index of argument to bind value to
134          * @param value Value to bind
135          */
136         void BindFloat(ArgumentIndex position, float value);
137
138         /**
139          * Bind double to the prepared statement argument
140          *
141          * @param position Index of argument to bind value to
142          * @param value Value to bind
143          */
144         void BindDouble(ArgumentIndex position, double value);
145
146         /**
147          * Bind string to the prepared statement argument
148          *
149          * @param position Index of argument to bind value to
150          * @param value Value to bind
151          */
152         void BindString(ArgumentIndex position, const char *value);
153
154         /**
155          * Bind string to the prepared statement argument
156          *
157          * @param position Index of argument to bind value to
158          * @param value Value to bind
159          */
160         void BindString(ArgumentIndex position, const String& value);
161
162         /**
163          * Bind optional int to the prepared statement argument.
164          * If optional is not set null will be bound
165          *
166          * @param position Index of argument to bind value to
167          * @param value Value to bind
168          */
169         void BindInteger(ArgumentIndex position, const boost::optional<int> &value);
170
171         /**
172          * Bind optional int8 to the prepared statement argument.
173          * If optional is not set null will be bound
174          *
175          * @param position Index of argument to bind value to
176          * @param value Value to bind
177          */
178         void BindInt8(ArgumentIndex position, const boost::optional<int8_t> &value);
179
180         /**
181          * Bind optional int16 to the prepared statement argument.
182          * If optional is not set null will be bound
183          *
184          * @param position Index of argument to bind value to
185          * @param value Value to bind
186          */
187         void BindInt16(ArgumentIndex position, const boost::optional<int16_t> &value);
188
189         /**
190          * Bind optional int32 to the prepared statement argument.
191          * If optional is not set null will be bound
192          *
193          * @param position Index of argument to bind value to
194          * @param value Value to bind
195          */
196         void BindInt32(ArgumentIndex position, const boost::optional<int32_t> &value);
197
198         /**
199          * Bind optional int64 to the prepared statement argument.
200          * If optional is not set null will be bound
201          *
202          * @param position Index of argument to bind value to
203          * @param value Value to bind
204          */
205         void BindInt64(ArgumentIndex position, const boost::optional<int64_t> &value);
206
207         /**
208          * Bind optional float to the prepared statement argument.
209          * If optional is not set null will be bound
210          *
211          * @param position Index of argument to bind value to
212          * @param value Value to bind
213          */
214         void BindFloat(ArgumentIndex position, const boost::optional<float> &value);
215
216         /**
217          * Bind optional double to the prepared statement argument.
218          * If optional is not set null will be bound
219          *
220          * @param position Index of argument to bind value to
221          * @param value Value to bind
222          */
223         void BindDouble(ArgumentIndex position, const boost::optional<double> &value);
224
225         /**
226          * Bind optional string to the prepared statement argument.
227          * If optional is not set null will be bound
228          *
229          * @param position Index of argument to bind value to
230          * @param value Value to bind
231          */
232         void BindString(ArgumentIndex position, const boost::optional<String> &value);
233
234         /**
235          * Execute the prepared statement and/or move
236          * to the next row of the result
237          *
238          * @return True when there was a row returned
239          */
240         bool Step();
241
242         /**
243          * Reset prepared statement's arguments
244          * All parameters will become null
245          */
246         void Reset();
247
248         /**
249          * Checks whether column value is null
250          *
251          * @throw Exception::InvalidColumn
252          */
253         bool IsColumnNull(ColumnIndex column);
254
255         /**
256          * Get integer value from column in current row.
257          *
258          * @throw Exception::InvalidColumn
259          */
260         int GetColumnInteger(ColumnIndex column);
261
262         /**
263          * Get int8 value from column in current row.
264          *
265          * @throw Exception::InvalidColumn
266          */
267         int8_t GetColumnInt8(ColumnIndex column);
268
269         /**
270          * Get int16 value from column in current row.
271          *
272          * @throw Exception::InvalidColumn
273          */
274         int16_t GetColumnInt16(ColumnIndex column);
275         /**
276          * Get int32 value from column in current row.
277          *
278          * @throw Exception::InvalidColumn
279          */
280         int32_t GetColumnInt32(ColumnIndex column);
281
282         /**
283          * Get int64 value from column in current row.
284          *
285          * @throw Exception::InvalidColumn
286          */
287         int64_t GetColumnInt64(ColumnIndex column);
288
289         /**
290          * Get float value from column in current row.
291          *
292          * @throw Exception::InvalidColumn
293          */
294         float GetColumnFloat(ColumnIndex column);
295
296         /**
297          * Get double value from column in current row.
298          *
299          * @throw Exception::InvalidColumn
300          */
301         double GetColumnDouble(ColumnIndex column);
302
303         /**
304          * Get string value from column in current row.
305          *
306          * @throw Exception::InvalidColumn
307          */
308         std::string GetColumnString(ColumnIndex column);
309
310         /**
311          * Get optional integer value from column in current row.
312          *
313          * @throw Exception::InvalidColumn
314          */
315         boost::optional<int> GetColumnOptionalInteger(ColumnIndex column);
316
317         /**
318          * Get optional int8 value from column in current row.
319          *
320          * @throw Exception::InvalidColumn
321          */
322         boost::optional<int8_t> GetColumnOptionalInt8(ColumnIndex column);
323
324         /**
325          * Get optional int16value from column in current row.
326          *
327          * @throw Exception::InvalidColumn
328          */
329         boost::optional<int16_t> GetColumnOptionalInt16(ColumnIndex column);
330
331         /**
332          * Get optional int32 value from column in current row.
333          *
334          * @throw Exception::InvalidColumn
335          */
336         boost::optional<int32_t> GetColumnOptionalInt32(ColumnIndex column);
337
338         /**
339          * Get optional int64 value from column in current row.
340          *
341          * @throw Exception::InvalidColumn
342          */
343         boost::optional<int64_t> GetColumnOptionalInt64(ColumnIndex column);
344
345         /**
346          * Get optional float value from column in current row.
347          *
348          * @throw Exception::InvalidColumn
349          */
350         boost::optional<float> GetColumnOptionalFloat(ColumnIndex column);
351
352         /**
353          * Get optional double value from column in current row.
354          *
355          * @throw Exception::InvalidColumn
356          */
357         boost::optional<double> GetColumnOptionalDouble(ColumnIndex column);
358
359         /**
360          * Get optional string value from column in current row.
361          *
362          * @throw Exception::InvalidColumn
363          */
364         boost::optional<String> GetColumnOptionalString(ColumnIndex column);
365     };
366
367     // Move on copy semantics
368     typedef std::auto_ptr<DataCommand> DataCommandAutoPtr;
369
370     // Open flags
371     class Flag
372     {
373       public:
374         enum Option
375         {
376             RO = SQLCIPHER_OPEN_NOMUTEX | SQLCIPHER_OPEN_READONLY,
377             RW = SQLCIPHER_OPEN_NOMUTEX | SQLCIPHER_OPEN_READWRITE, 
378             CRW = RW | SQLCIPHER_OPEN_CREATE
379         };
380     };
381
382     // RowID
383     typedef sqlcipher3_int64 RowID;
384
385     /**
386      * Synchronization object used to synchronize SQL connection
387      * to the same database across different threads and processes
388      */
389     class SynchronizationObject
390     {
391       public:
392         virtual ~SynchronizationObject() {}
393
394         /**
395          * Synchronizes SQL connection for multiple clients.
396          */
397         virtual void Synchronize() = 0;
398
399         /**
400          * Notify all waiting clients that the connection is no longer locked.
401          */
402         virtual void NotifyAll() = 0;
403     };
404
405   protected:
406     sqlcipher3 *m_connection;
407
408     // Options
409
410     // Stored data procedures
411     int m_dataCommandsCount;
412
413     // Synchronization object
414     std::unique_ptr<SynchronizationObject> m_synchronizationObject;
415
416     bool m_isKeySet;
417
418     virtual void Connect(const std::string &address,
419                          Flag::Option = Flag::RO);
420     virtual void Disconnect();
421
422     void TurnOnForeignKeys();
423
424     static SynchronizationObject *AllocDefaultSynchronizationObject();
425
426   public:
427     /**
428      * Open SQL connection
429      *
430      * Synchronization is archieved by using provided asynchronization object.
431      * If synchronizationObject is set to NULL, so synchronization is performed.
432      * Ownership of the synchronization object is transfered to sql connection
433      * object.
434      *
435      * @param address Database file name
436      * @param flags Open flags
437      * @param synchronizationObject A synchronization object to use.
438      */
439     explicit SqlConnection(const std::string &address = std::string(),
440                            Flag::Option options = Flag::RO,
441                            SynchronizationObject *synchronizationObject =
442                                AllocDefaultSynchronizationObject());
443
444     /**
445      * Destructor
446      */
447     virtual ~SqlConnection();
448
449     /**
450      * Added extension for encryption functionality:
451      *
452      * SetKey gives sqlcipher key, which will be used to encrypt the database
453      * This function will only fail because of invalid arguments. To check if
454      * database can be opened with provided key, it is necessary to perform
455      * some operation on the database (i.e. read from it) and confirm if it
456      * succeeds.
457      * Password must have length >= 1.
458      *
459      * @param rawPass password given in raw binary format
460      */
461     void SetKey(const std::vector<unsigned char> &rawPass);
462
463     /**
464      * ResetKey is used for changing key used for database encryption.
465      * If key was already set by using SetKey, this function will only change it.
466      * If no key was yet set, this function first will set key with rawPassOld and
467      * then change it to rawPassNew.
468      * Same rules for failing apply as for SetKey.
469      * Both password must have length >=1.
470      *
471      * @param rawPassOld current password for encryption in raw binary format
472      * @param rawPassNew new password for encryption in raw binary format
473      *
474      */
475     void ResetKey(const std::vector<unsigned char> &rawPassOld,
476                   const std::vector<unsigned char> &rawPassNew);
477
478     /**
479      * Execute SQL command without result
480      *
481      * @param format
482      * @param ...
483      */
484     void ExecCommand(const char *format, ...) CKM_DEPRECATED_WITH_MESSAGE(
485             "To prevent sql injection do not use this \
486              method for direct sql execution");
487
488     /**
489      * Execute BEGIN; command to start new transaction
490      *
491      */
492     void BeginTransaction();
493
494     /**
495      * Execute ROLLBACK; command to discard changes made
496      *
497      */
498     void RollbackTransaction();
499
500     /**
501      * Execute COMMIT; command to commit changes in database
502      *
503      */
504     void CommitTransaction();
505
506     /**
507      * Prepare stored procedure
508      *
509      * @param format SQL statement
510      * @return Data command representing stored procedure
511      */
512     DataCommandAutoPtr PrepareDataCommand(const char *format, ...);
513
514     /**
515      * Check whether given table exists
516      *
517      * @param tableName Name of the table to check
518      * @return True if given table name exists
519      */
520     bool CheckTableExist(const char *tableName);
521
522     /**
523      * Get last insert operation new row id
524      *
525      * @return Row ID
526      */
527     RowID GetLastInsertRowID() const;
528 };
529 } // namespace DB
530 } // namespace CKM
531
532 #endif // CKM_SQL_CONNECTION_H