Add access control code to the CKM.
[platform/core/security/key-manager.git] / src / manager / service / db-crypto.cpp
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.cpp
18  * @author      Zofia Abramowska (z.abramowska@samsung.com)
19  * @version     1.0
20  * @brief       Implementation of encrypted db access layer
21  */
22
23 #include <db-crypto.h>
24 #include <dpl/db/sql_connection.h>
25 #include <dpl/log/log.h>
26 #include <ckm/ckm-error.h>
27
28 #pragma GCC diagnostic push
29 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
30
31 namespace {
32     const char *main_table = "CKM_TABLE";
33     const char *key_table = "KEY_TABLE";
34     const char *permission_table = "PERMISSION_TABLE";
35
36 // CKM_TABLE (alias TEXT, label TEXT, restricted INT, exportable INT, dataType INT,
37 //            algorithmType INT, encryptionScheme INT, iv BLOB, dataSize INT, data BLOB)
38
39     const char *db_create_main_cmd =
40             "CREATE TABLE CKM_TABLE("
41             "   alias TEXT NOT NULL,"
42             "   label TEXT NOT NULL,"
43             "   exportable INTEGER NOT NULL,"
44             "   dataType INTEGER NOT NULL,"
45             "   algorithmType INTEGER NOT NULL,"
46             "   encryptionScheme INTEGER NOT NULL,"
47             "   iv BLOB NOT NULL,"
48             "   dataSize INTEGER NOT NULL,"
49             "   data BLOB NOT NULL,"
50             "   tag BLOB NOT NULL,"
51             "   PRIMARY KEY(alias)"
52             ");";
53
54
55     const char *insert_main_cmd =
56             "INSERT INTO CKM_TABLE("
57             //      1   2       3
58             "   alias, label, exportable,"
59             //      4           5           6
60             "   dataType, algorithmType, encryptionScheme,"
61             //  7       8       9    10
62             "   iv, dataSize, data, tag) "
63             "VALUES("
64             "   ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
65
66     const char *select_alias_cmd =
67             //                                   1              2
68             "SELECT * FROM CKM_TABLE WHERE alias=? AND dataType=?; ";
69
70     const char *select_check_alias_cmd =
71             //                                          1
72             "SELECT dataType FROM CKM_TABLE WHERE alias=?;";
73
74     const char *select_check_global_alias_cmd =
75             //                                       1
76             "SELECT label FROM CKM_TABLE WHERE alias=?;";
77
78     const char *select_key_alias_cmd =
79             //                                   1
80             "SELECT * FROM CKM_TABLE WHERE alias=?"
81             //                     2     3
82             " AND dataType BETWEEN ? AND ?;";
83
84     const char *select_key_type_cmd =
85             "SELECT alias FROM CKM_TABLE WHERE "
86             //                1
87                 " dataType >= ? AND "
88             //                2
89                 " dataType <= ?;";
90
91     const char *select_type_cmd =
92             //                                          1
93             "SELECT alias FROM CKM_TABLE WHERE dataType=?;";
94
95     const char *delete_alias_cmd =
96             //                                 1
97             "DELETE FROM CKM_TABLE WHERE alias=?;";
98
99     const char *delete_data_with_key_cmd =
100             //                                 1
101             "DELETE FROM CKM_TABLE WHERE label=?;";
102
103 // KEY_TABLE (label TEXT, key BLOB)
104
105     const char *db_create_key_cmd =
106             "CREATE TABLE KEY_TABLE("
107             "   label TEXT PRIMARY KEY,"
108             "   key BLOB NOT NULL"
109             ");";
110
111     const char *insert_key_cmd =
112             "INSERT INTO KEY_TABLE(label, key) VALUES (?, ?);";
113     const char *select_key_cmd =
114             "SELECT key FROM KEY_TABLE WHERE label=?;";
115     const char *delete_key_cmd =
116             "DELETE FROM KEY_TABLE WHERE label=?";
117
118
119 // PERMISSION_TABLE (label TEXT, label TEXT, access_flags TEXT)
120
121     const char *db_create_permission_cmd =
122             "CREATE TABLE PERMISSION_TABLE("
123             "   alias TEXT NOT NULL,"
124             "   label TEXT NOT NULL,"
125             "   accessFlags TEXT NOT NULL,"
126             "   FOREIGN KEY(alias) REFERENCES CKM_TABLE(alias) ON DELETE CASCADE,"
127             "   PRIMARY KEY(label)"
128             ");";
129
130     const char *set_permission_alias_cmd =
131             "REPLACE INTO PERMISSION_TABLE(alias, label, accessFlags) VALUES (?, ?, ?);";
132
133     const char *select_permission_cmd =
134             //                                                    1           2
135             "SELECT accessFlags FROM PERMISSION_TABLE WHERE alias=? AND label=?;";
136
137     const char *delete_permission_cmd =
138             //                                        1           2
139             "DELETE FROM PERMISSION_TABLE WHERE alias=? AND label=?;";
140 }
141
142 namespace CKM {
143 using namespace DB;
144     DBCrypto::DBCrypto(const std::string& path,
145                          const RawBuffer &rawPass) {
146         m_connection = NULL;
147         m_inUserTransaction = false;
148         Try {
149             m_connection = new SqlConnection(path, SqlConnection::Flag::Option::CRW);
150             m_connection->SetKey(rawPass);
151             m_connection->ExecCommand("VACUUM;");
152             initDatabase();
153         } Catch(SqlConnection::Exception::ConnectionBroken) {
154             LogError("Couldn't connect to database: " << path);
155             ReThrow(DBCrypto::Exception::InternalError);
156         } Catch(SqlConnection::Exception::InvalidArguments) {
157             LogError("Couldn't set the key for database");
158             ReThrow(DBCrypto::Exception::InternalError);
159         } Catch(SqlConnection::Exception::SyntaxError) {
160             LogError("Couldn't initiate the database");
161             ReThrow(DBCrypto::Exception::InternalError);
162         } Catch(SqlConnection::Exception::InternalError) {
163             LogError("Couldn't create the database");
164             ReThrow(DBCrypto::Exception::InternalError);
165         }
166     }
167
168     DBCrypto::DBCrypto(DBCrypto &&other) :
169             m_connection(other.m_connection),
170             m_inUserTransaction(other.m_inUserTransaction){
171         other.m_connection = NULL;
172         other.m_inUserTransaction = false;
173     }
174
175     DBCrypto::~DBCrypto() {
176         delete m_connection;
177     }
178
179     DBCrypto& DBCrypto::operator=(DBCrypto&& other) {
180         if (this == &other)
181             return *this;
182         delete m_connection;
183
184         m_connection = other.m_connection;
185         other.m_connection = NULL;
186
187         m_inUserTransaction = other.m_inUserTransaction;
188         other.m_inUserTransaction = false;
189
190         return *this;
191     }
192
193     void DBCrypto::createTable(
194             const char* create_cmd,
195             const char *table_name)
196     {
197         Try {
198             m_connection->ExecCommand(create_cmd);
199         } Catch(SqlConnection::Exception::SyntaxError) {
200             LogError("Couldn't create table : " << table_name << "!");
201             throw;
202         } Catch(SqlConnection::Exception::InternalError) {
203             LogError("Sqlite got into infinite busy state");
204             throw;
205         }
206     }
207
208     void DBCrypto::initDatabase() {
209         Transaction transaction(this);
210         if(!m_connection->CheckTableExist(main_table)) {
211             createTable(db_create_main_cmd, main_table);
212         }
213         if(!m_connection->CheckTableExist(key_table)) {
214             createTable(db_create_key_cmd, key_table);
215         }
216         if(!m_connection->CheckTableExist(permission_table)) {
217             createTable(db_create_permission_cmd, permission_table);
218         }
219         transaction.commit();
220     }
221
222     std::string DBCrypto::getLabelForAlias(const std::string& alias) const {
223         SqlConnection::DataCommandUniquePtr checkCmd =
224                 m_connection->PrepareDataCommand(select_check_global_alias_cmd);
225         checkCmd->BindString(1, alias.c_str());
226         if(checkCmd->Step()) {
227             return checkCmd->GetColumnString(0);
228         } else
229             return std::string();
230     }
231     bool DBCrypto::checkGlobalAliasExist(const std::string& alias) const {
232         std::string label = this->getLabelForAlias(alias);
233         if(label.empty() == false) {
234             LogDebug("Global alias '" << alias  << "' exists already for label " << label);
235             return true;
236         } else
237             return false;
238     }
239
240     bool DBCrypto::checkAliasExist(const std::string& alias) const {
241         SqlConnection::DataCommandUniquePtr checkCmd =
242                 m_connection->PrepareDataCommand(select_check_alias_cmd);
243         checkCmd->BindString(1, alias.c_str());
244         if(checkCmd->Step()) {
245             LogDebug("Private alias '" << alias  << "' exists already for type "
246                     << checkCmd->GetColumnInteger(0));
247             return true;
248         } else
249             return false;
250     }
251
252     void DBCrypto::saveDBRow(const DBRow &row){
253         Try {
254
255             //Sqlite does not support partial index in our version,
256             //so we do it by hand
257             Transaction transaction(this);
258             if(checkAliasExist(row.alias)) {
259                 ThrowMsg(DBCrypto::Exception::AliasExists,
260                         "Alias exists for alias: " << row.alias);
261             }
262
263             SqlConnection::DataCommandUniquePtr insertCommand =
264                     m_connection->PrepareDataCommand(insert_main_cmd);
265             insertCommand->BindString(1, row.alias.c_str());
266             insertCommand->BindString(2, row.smackLabel.c_str());
267             insertCommand->BindInteger(3, row.exportable);
268             insertCommand->BindInteger(4, static_cast<int>(row.dataType));
269             insertCommand->BindInteger(5, static_cast<int>(row.algorithmType));
270             insertCommand->BindInteger(6, row.encryptionScheme);
271             insertCommand->BindBlob(7, row.iv);
272             insertCommand->BindInteger(8, row.dataSize);
273             insertCommand->BindBlob(9, row.data);
274             insertCommand->BindBlob(10, row.tag);
275
276             insertCommand->Step();
277             transaction.commit();
278             return;
279
280         } Catch(SqlConnection::Exception::SyntaxError) {
281             LogError("Couldn't prepare insert statement");
282         } Catch(SqlConnection::Exception::InternalError) {
283             LogError("Couldn't execute insert statement");
284         }
285         ThrowMsg(DBCrypto::Exception::InternalError,
286                 "Couldn't save DBRow");
287     }
288
289     DBRow DBCrypto::getRow(const SqlConnection::DataCommandUniquePtr &selectCommand) {
290         DBRow row;
291         row.alias = selectCommand->GetColumnString(0);
292         row.smackLabel = selectCommand->GetColumnString(1);
293         row.exportable = selectCommand->GetColumnInteger(2);
294         row.dataType = static_cast<DBDataType>(selectCommand->GetColumnInteger(3));
295         row.algorithmType = static_cast<DBCMAlgType>(selectCommand->GetColumnInteger(4));
296         row.encryptionScheme = selectCommand->GetColumnInteger(5);
297         row.iv = selectCommand->GetColumnBlob(6);
298         row.dataSize = selectCommand->GetColumnInteger(7);
299         row.data = selectCommand->GetColumnBlob(8);
300         row.tag = selectCommand->GetColumnBlob(9);
301         return row;
302     }
303
304     std::string DBCrypto::getPermissionsForAliasAndLabel(const Alias &alias, const std::string &label) const
305     {
306         Try{
307             SqlConnection::DataCommandUniquePtr selectCommand =
308                             m_connection->PrepareDataCommand(select_permission_cmd);
309             selectCommand->BindString(1, alias.c_str());
310             selectCommand->BindString(2, label.c_str());
311
312             if(selectCommand->Step())
313                 return selectCommand->GetColumnString(0);
314
315             return std::string();
316         } Catch (SqlConnection::Exception::InvalidColumn) {
317             LogError("Select statement invalid column error");
318         } Catch (SqlConnection::Exception::SyntaxError) {
319             LogError("Couldn't prepare select statement");
320         } Catch (SqlConnection::Exception::InternalError) {
321             LogError("Couldn't execute select statement");
322         }
323         return std::string();
324     }
325
326
327     bool    DBCrypto::rowAccessControlCheck(const Alias &alias,
328                                             const std::string &owner_label,
329                                             const std::string &clnt_label,
330                                             DBCrypto::DBOperationType access_type) const
331     {
332         // owner of the entry have all the permissions by default
333         // check if requesting client is the entry owner - if so, exit (permission granted)
334         if(owner_label == clnt_label)
335             return true;
336
337         // perform permissions DB query
338         std::string permission_string = this->getPermissionsForAliasAndLabel(alias, clnt_label);
339
340         // check if requested operation is in the permission string
341         LogDebug("pair <" << alias << "," << clnt_label << "> permission rights: \"" << permission_string << "\"");
342         if(permission_string.find(access_type) != std::string::npos)
343             return true;
344
345         return false;
346     }
347     bool    DBCrypto::rowAccessControlCheck(const DBRow & input_row,
348                                             const std::string &clnt_label,
349                                             DBCrypto::DBOperationType access_type) const
350     {
351         return this->rowAccessControlCheck(input_row.alias, input_row.smackLabel, clnt_label, access_type);
352     }
353
354
355     DBCrypto::DBRowOptional DBCrypto::getDBRow(
356         const Alias &alias,
357         const std::string &clnt_label,
358         DBDataType type)
359     {
360         Try {
361             Transaction transaction(this);
362             SqlConnection::DataCommandUniquePtr selectCommand =
363                     m_connection->PrepareDataCommand(select_alias_cmd);
364             selectCommand->BindString(1, alias.c_str());
365             selectCommand->BindInteger(2, static_cast<int>(type));
366
367             if(selectCommand->Step())
368             {
369                 // extract data
370                 DBRow current_row = getRow(selectCommand);
371
372                 // check access rights here
373                 if( ! this->rowAccessControlCheck(current_row, clnt_label, DBCrypto::DB_OPERATION_READ) )
374                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested operation");
375
376                 // finalize DB operations
377                 transaction.commit();
378
379                 // all okay, proceed
380                 return DBRowOptional(current_row);
381             } else {
382                 return DBRowOptional();
383             }
384         } Catch (SqlConnection::Exception::InvalidColumn) {
385             LogError("Select statement invalid column error");
386         } Catch (SqlConnection::Exception::SyntaxError) {
387             LogError("Couldn't prepare select statement");
388         } Catch (SqlConnection::Exception::InternalError) {
389             LogError("Couldn't execute select statement");
390         }
391         ThrowMsg(DBCrypto::Exception::InternalError,
392                 "Couldn't get row for type " << static_cast<int>(type) <<
393                 " alias " << alias << " using client label " << clnt_label);
394     }
395
396     DBCrypto::DBRowOptional DBCrypto::getKeyDBRow(
397         const Alias &alias,
398         const std::string &clnt_label)
399     {
400         Try{
401             Transaction transaction(this);
402             SqlConnection::DataCommandUniquePtr selectCommand =
403                     m_connection->PrepareDataCommand(select_key_alias_cmd);
404             selectCommand->BindString(1, alias.c_str());
405             selectCommand->BindInteger(2, static_cast<int>(DBDataType::DB_KEY_FIRST));
406             selectCommand->BindInteger(3, static_cast<int>(DBDataType::DB_KEY_LAST));
407
408             if(selectCommand->Step())
409             {
410                 // extract data
411                 DBRow current_row = getRow(selectCommand);
412
413                 // check access rights here
414                 if( ! this->rowAccessControlCheck(current_row, clnt_label, DBCrypto::DB_OPERATION_READ) )
415                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested operation");
416
417                 // finalize DB operations
418                 transaction.commit();
419
420                 // all okay, proceed
421                 return DBRowOptional(current_row);
422             } else {
423                 return DBRowOptional();
424             }
425         } Catch (SqlConnection::Exception::InvalidColumn) {
426             LogError("Select statement invalid column error");
427         } Catch (SqlConnection::Exception::SyntaxError) {
428             LogError("Couldn't prepare select statement");
429         } Catch (SqlConnection::Exception::InternalError) {
430             LogError("Couldn't execute select statement");
431         }
432         ThrowMsg(DBCrypto::Exception::InternalError,
433                 "Couldn't get Key for alias " << alias
434                 << " using client label " << clnt_label);
435     }
436
437     void DBCrypto::getSingleType(
438             DBDataType type,
439             AliasVector& aliases) const
440     {
441         Try{
442             SqlConnection::DataCommandUniquePtr selectCommand =
443                             m_connection->PrepareDataCommand(select_type_cmd);
444             selectCommand->BindInteger(1, static_cast<int>(type));
445
446             while(selectCommand->Step()) {
447                 Alias alias;
448                 alias = selectCommand->GetColumnString(0);
449                 aliases.push_back(alias);
450             }
451             return;
452         } Catch (SqlConnection::Exception::InvalidColumn) {
453             LogError("Select statement invalid column error");
454         } Catch (SqlConnection::Exception::SyntaxError) {
455             LogError("Couldn't prepare select statement");
456         } Catch (SqlConnection::Exception::InternalError) {
457             LogError("Couldn't execute select statement");
458         }
459         ThrowMsg(DBCrypto::Exception::InternalError,
460                 "Couldn't get type " << static_cast<int>(type));
461     }
462
463     void DBCrypto::getAliases(
464         DBDataType type,
465         AliasVector& aliases)
466     {
467         getSingleType(type, aliases);
468     }
469
470
471     void DBCrypto::getKeyAliases(AliasVector &aliases)
472     {
473         Try{
474             Transaction transaction(this);
475             SqlConnection::DataCommandUniquePtr selectCommand =
476                             m_connection->PrepareDataCommand(select_key_type_cmd);
477             selectCommand->BindInteger(1, static_cast<int>(DBDataType::DB_KEY_FIRST));
478             selectCommand->BindInteger(2, static_cast<int>(DBDataType::DB_KEY_LAST));
479
480             while(selectCommand->Step()) {
481                 Alias alias;
482                 alias = selectCommand->GetColumnString(0);
483                 aliases.push_back(alias);
484             }
485             transaction.commit();
486             return;
487         } Catch (SqlConnection::Exception::InvalidColumn) {
488             LogError("Select statement invalid column error");
489         } Catch (SqlConnection::Exception::SyntaxError) {
490             LogError("Couldn't prepare select statement");
491         } Catch (SqlConnection::Exception::InternalError) {
492             LogError("Couldn't execute select statement");
493         }
494         ThrowMsg(DBCrypto::Exception::InternalError, "Couldn't get key aliases");
495     }
496
497     bool DBCrypto::deleteDBRow(const Alias &alias, const std::string &clnt_label)
498     {
499         Try {
500             Transaction transaction(this);
501
502             std::string owner_label = getLabelForAlias(alias);
503             if( ! owner_label.empty() )
504             {
505                 // check access rights here
506                 if( ! this->rowAccessControlCheck(alias, owner_label, clnt_label, DBCrypto::DB_OPERATION_REMOVE) )
507                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested remove operation");
508
509                 // if here, access right is granted - proceed with removal
510                 // note: PERMISSION_TABLE entry will be deleted automatically by SQL (cascade relation between tables)
511                 SqlConnection::DataCommandUniquePtr deleteCommand =
512                         m_connection->PrepareDataCommand(delete_alias_cmd);
513                 deleteCommand->BindString(1, alias.c_str());
514                 deleteCommand->Step();
515
516                 transaction.commit();
517                 return true;
518             }
519             else
520             {
521                 LogError("Error: no such alias: " << alias);
522                 return false;
523             }
524         } Catch (SqlConnection::Exception::SyntaxError) {
525             LogError("Couldn't prepare delete statement");
526         } Catch (SqlConnection::Exception::InternalError) {
527             LogError("Couldn't execute delete statement");
528         }
529         ThrowMsg(DBCrypto::Exception::InternalError,
530                 "Couldn't delete DBRow for alias " << alias << " using client label " << clnt_label);
531     }
532
533     void DBCrypto::saveKey(
534             const std::string& label,
535             const RawBuffer &key)
536     {
537         Try {
538             Transaction transaction(this);
539             SqlConnection::DataCommandUniquePtr insertCommand =
540                     m_connection->PrepareDataCommand(insert_key_cmd);
541             insertCommand->BindString(1, label.c_str());
542             insertCommand->BindBlob(2, key);
543             insertCommand->Step();
544             transaction.commit();
545             return;
546         } Catch (SqlConnection::Exception::SyntaxError) {
547             LogError("Couldn't prepare insert key statement");
548         } Catch (SqlConnection::Exception::InternalError) {
549             LogError("Couldn't execute insert statement");
550         }
551         ThrowMsg(DBCrypto::Exception::InternalError,
552                 "Couldn't save key for label " << label);
553     }
554
555     DBCrypto::RawBufferOptional DBCrypto::getKey(
556             const std::string& label)
557     {
558         Try {
559             Transaction transaction(this);
560             SqlConnection::DataCommandUniquePtr selectCommand =
561                     m_connection->PrepareDataCommand(select_key_cmd);
562             selectCommand->BindString(1, label.c_str());
563
564             if (selectCommand->Step()) {
565                 transaction.commit();
566                 return RawBufferOptional(
567                         selectCommand->GetColumnBlob(0));
568             } else {
569                 transaction.commit();
570                 return RawBufferOptional();
571             }
572
573         } Catch (SqlConnection::Exception::InvalidColumn) {
574             LogError("Select statement invalid column error");
575         } Catch (SqlConnection::Exception::SyntaxError) {
576             LogError("Couldn't prepare insert key statement");
577         } Catch (SqlConnection::Exception::InternalError) {
578             LogError("Couldn't execute insert statement");
579         }
580         ThrowMsg(DBCrypto::Exception::InternalError,
581                 "Couldn't get key for label " << label);
582     }
583
584     void DBCrypto::deleteKey(const std::string& label) {
585         Try {
586             Transaction transaction(this);
587
588             SqlConnection::DataCommandUniquePtr deleteCommand =
589                     m_connection->PrepareDataCommand(delete_key_cmd);
590             deleteCommand->BindString(1, label.c_str());
591             deleteCommand->Step();
592
593             SqlConnection::DataCommandUniquePtr deleteData =
594                 m_connection->PrepareDataCommand(delete_data_with_key_cmd);
595             deleteData->BindString(1, label.c_str());
596             deleteData->Step();
597
598             transaction.commit();
599             return;
600         } Catch (SqlConnection::Exception::SyntaxError) {
601             LogError("Couldn't prepare insert key statement");
602         } Catch (SqlConnection::Exception::InternalError) {
603             LogError("Couldn't execute insert statement");
604         }
605         ThrowMsg(DBCrypto::Exception::InternalError,
606                 "Couldn't delete key for label " << label);
607     }
608
609
610     int DBCrypto::setAccessRights(  const std::string& clnt_label,
611                                     const Alias& alias,
612                                     const std::string& accessor_label,
613                                     const AccessRight value_to_set)
614     {
615         Try {
616             Transaction transaction(this);
617
618             // check if label is present
619             std::string owner_label = getLabelForAlias(alias);
620             if( ! owner_label.empty() )
621             {
622                 // owner can not add permissions to itself
623                 if(owner_label.compare(accessor_label) == 0)
624                     ThrowMsg(Exception::InvalidArgs, "Invalid accessor label: equal to owner label");
625
626                 // check access rights here - only owner can modify permissions
627                 if(owner_label != clnt_label)
628                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested write operation");
629
630                 // if here, access right is granted - proceed to set permissions
631                 SqlConnection::DataCommandUniquePtr setPermissionCommand =
632                         m_connection->PrepareDataCommand(set_permission_alias_cmd);
633                 setPermissionCommand->BindString(1, alias.c_str());
634                 setPermissionCommand->BindString(2, accessor_label.c_str());
635                 setPermissionCommand->BindString(3, toDBAccessRight(value_to_set));
636                 setPermissionCommand->Step();
637                 transaction.commit();
638                 return CKM_API_SUCCESS;
639             }
640             else
641             {
642                 LogError("Error: no such alias: " << alias);
643                 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
644             }
645         } Catch (SqlConnection::Exception::SyntaxError) {
646             LogError("Couldn't prepare set statement");
647         } Catch (SqlConnection::Exception::InternalError) {
648             LogError("Couldn't execute set statement");
649         }
650         ThrowMsg(DBCrypto::Exception::InternalError,
651                 "Couldn't set permissions for alias " << alias << " using client label " << clnt_label);
652     }
653
654     int DBCrypto::clearAccessRights(const std::string& clnt_label,
655                                     const Alias& alias,
656                                     const std::string& accessor_label)
657     {
658         Try {
659             Transaction transaction(this);
660
661             std::string owner_label = getLabelForAlias(alias);
662             if( ! owner_label.empty() )
663             {
664                 // check access rights here - only owner can modify permissions
665                 if(owner_label != clnt_label)
666                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested write operation");
667
668                 // check if permission for <label, accessor_label> is defined - otherwise nothing to drop
669                 if( this->getPermissionsForAliasAndLabel(alias, accessor_label).empty() )
670                     ThrowMsg(Exception::InvalidArgs, "Permission not found");
671
672                 // if here, access right is granted - proceed to delete permissions
673                 SqlConnection::DataCommandUniquePtr deletePermissionCommand =
674                         m_connection->PrepareDataCommand(delete_permission_cmd);
675                 deletePermissionCommand->BindString(1, alias.c_str());
676                 deletePermissionCommand->BindString(2, accessor_label.c_str());
677                 deletePermissionCommand->Step();
678                 transaction.commit();
679                 return CKM_API_SUCCESS;
680             }
681             else
682             {
683                 LogError("Error: no such alias: " << alias);
684                 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
685             }
686         } Catch (SqlConnection::Exception::SyntaxError) {
687             LogError("Couldn't prepare delete statement");
688         } Catch (SqlConnection::Exception::InternalError) {
689             LogError("Couldn't execute delete statement");
690         }
691         ThrowMsg(DBCrypto::Exception::InternalError,
692                 "Couldn't delete permissions for alias " << alias << " using client label " << clnt_label);
693     }
694
695 } // CKM
696
697 #pragma GCC diagnostic pop