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