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