2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @author Zofia Abramowska (z.abramowska@samsung.com)
20 * @brief Implementation of encrypted db access layer
25 #include <db-crypto.h>
26 #include <dpl/db/sql_connection.h>
27 #include <dpl/log/log.h>
28 #include <ckm/ckm-error.h>
30 #pragma GCC diagnostic push
31 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
34 const CKM::PermissionMask DEFAULT_PERMISSIONS =
35 static_cast<CKM::PermissionMask>(CKM::Permission::READ | CKM::Permission::REMOVE);
37 const char *SCRIPTS_PATH = "/usr/share/ckm/scripts/";
39 enum DBVersion : int {
42 /* ... since version 3, there is no need to manually
43 * recognize database version.
44 * Remember only that if doing changes to the database,
45 * increment and update DB_VERSION_CURRENT,
46 * then provide migration mechanism!
48 DB_VERSION_CURRENT = 4
51 const char *SCRIPT_CREATE_SCHEMA = "create_schema";
52 const char *SCRIPT_DROP_ALL_ITEMS = "drop_all";
53 const char *SCRIPT_MIGRATE = "migrate_";
55 // common substitutions:
60 // 104 - permissionLabel
61 // 105 - permissionMask
62 const char *DB_CMD_SCHEMA_SET =
63 "REPLACE INTO SCHEMA_INFO(name, value) "
64 " VALUES(?101, ?103);";
66 const char *DB_CMD_SCHEMA_GET =
67 "SELECT * FROM SCHEMA_INFO WHERE name=?101;";
69 const char *DB_SCHEMA_VERSION_FIELD = "schema_version";
72 const char *DB_CMD_NAME_INSERT =
75 " VALUES(?101, ?102);";
77 const char *DB_CMD_NAME_COUNT_ROWS =
78 "SELECT COUNT(idx) FROM NAMES WHERE name=?101 AND label=?102;";
80 const char *DB_CMD_NAME_DELETE =
81 "DELETE FROM NAMES WHERE name=?101 AND label=?102;";
83 const char *DB_CMD_NAME_DELETE_BY_LABEL =
84 "DELETE FROM NAMES WHERE label=?102;";
87 const char *DB_CMD_OBJECT_INSERT =
88 "INSERT INTO OBJECTS("
89 " exportable, dataType,"
90 " algorithmType, encryptionScheme,"
91 " iv, dataSize, data, tag, idx, backendId) "
92 " VALUES(?001, ?002, ?003, ?004, ?005, "
94 " (SELECT idx FROM NAMES WHERE name=?101 and label=?102),"
98 const char *DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL =
99 "SELECT * FROM [join_name_object_tables] "
100 " WHERE (dataType BETWEEN ?001 AND ?002) "
101 " AND name=?101 and label=?102;";
104 const char *DB_CMD_KEY_INSERT =
105 "INSERT INTO KEYS(label, key) VALUES (?, ?);";
106 const char *DB_CMD_KEY_SELECT =
107 "SELECT key FROM KEYS WHERE label=?;";
108 const char *DB_CMD_KEY_DELETE =
109 "DELETE FROM KEYS WHERE label=?";
112 const char *DB_CMD_PERMISSION_SET = // SQLite does not support updating views
113 "REPLACE INTO PERMISSIONS(permissionLabel, permissionMask, idx) "
114 " VALUES (?104, ?105, (SELECT idx FROM NAMES WHERE name=?101 and label=?102));";
116 const char *DB_CMD_PERMISSION_SELECT =
117 "SELECT permissionMask FROM [join_name_permission_tables] "
118 " WHERE permissionLabel=?104 "
119 " AND name=?101 and label=?102;";
121 const char *DB_CMD_PERMISSION_DELETE = // SQLite does not support updating views
122 "DELETE FROM PERMISSIONS WHERE permissionLabel=?104 AND "
123 " idx=(SELECT idx FROM NAMES WHERE name=?101 and label=?102);";
127 * GROUP BY is necessary because of the following case:
128 * -There are several permissions to L1, N1 (label, name) from other accessors. When listing
129 * objects accessible by L1 the query will produce one result (L1, N1) for each allowed
130 * accessor but GROUP BY will reduce them to one so L1 will have (L1, N1) on its list only once
132 const char *DB_CMD_NAME_SELECT_BY_TYPE_AND_PERMISSION =
133 "SELECT label, name FROM [join_all_tables] "
134 " WHERE dataType>=?001 AND dataType<=?002 "
135 " AND permissionLabel=?104 AND permissionMask&?004!=0 GROUP BY idx;";
140 Crypto::Crypto(const std::string& path, const RawBuffer &rawPass)
143 m_inUserTransaction = false;
145 m_connection = new SqlConnection(path, SqlConnection::Flag::Option::CRW);
146 m_connection->SetKey(rawPass);
148 m_connection->ExecCommand("VACUUM;");
149 } Catch(SqlConnection::Exception::ConnectionBroken) {
150 LogError("Couldn't connect to database: " << path);
151 ReThrow(Crypto::Exception::InternalError);
152 } Catch(SqlConnection::Exception::InvalidArguments) {
153 LogError("Couldn't set the key for database");
154 ReThrow(Crypto::Exception::InternalError);
155 } Catch(SqlConnection::Exception::SyntaxError) {
156 LogError("Couldn't initiate the database");
157 ReThrow(Crypto::Exception::InternalError);
158 } Catch(SqlConnection::Exception::InternalError) {
159 LogError("Couldn't create the database");
160 ReThrow(Crypto::Exception::InternalError);
164 Crypto::Crypto(Crypto &&other) :
165 m_connection(other.m_connection),
166 m_inUserTransaction(other.m_inUserTransaction)
168 other.m_connection = NULL;
169 other.m_inUserTransaction = false;
176 Crypto& Crypto::operator=(Crypto&& other) {
181 m_connection = other.m_connection;
182 other.m_connection = NULL;
184 m_inUserTransaction = other.m_inUserTransaction;
185 other.m_inUserTransaction = false;
190 void Crypto::createTable(
191 const char* create_cmd,
192 const char *table_name)
195 m_connection->ExecCommand(create_cmd);
196 } Catch(SqlConnection::Exception::SyntaxError) {
197 LogError("Couldn't create table : " << table_name << "!");
199 } Catch(SqlConnection::Exception::InternalError) {
200 LogError("Sqlite got into infinite busy state");
205 void Crypto::createView(
206 const char* create_cmd)
209 m_connection->ExecCommand(create_cmd);
210 } Catch(SqlConnection::Exception::SyntaxError) {
211 LogError("Couldn't create view!");
213 } Catch(SqlConnection::Exception::InternalError) {
214 LogError("Sqlite got into infinite busy state");
219 bool Crypto::getDBVersion(int & schemaVersion)
221 SchemaInfo SchemaInfo(this);
222 if(SchemaInfo.getVersionInfo(schemaVersion)) {
223 LogDebug("Current DB version: " << schemaVersion);
228 LogDebug("No DB version known or DB not present");
230 // special case: old CKM_TABLE exists
231 if(m_connection->CheckTableExist("CKM_TABLE")) {
232 schemaVersion = DB_VERSION_1;
236 // special case: new scheme exists, but no SCHEMA_INFO table present
237 else if(m_connection->CheckTableExist("NAME_TABLE")) {
238 schemaVersion = DB_VERSION_2;
242 // not recognized - proceed with an empty DBs
246 void Crypto::initDatabase()
248 // run migration if old database is present
250 if( getDBVersion(schemaVersion)==false || // DB empty or corrupted
251 schemaVersion > DB_VERSION_CURRENT) // or too new scheme
253 LogDebug("no database or database corrupted, initializing the DB");
259 LogDebug("DB migration from version " << schemaVersion << " to version " << DB_VERSION_CURRENT << " started.");
260 Transaction transaction(this);
261 for(int vi=schemaVersion; vi<DB_VERSION_CURRENT; vi++)
263 ScriptOptional script = getMigrationScript(vi);
266 LogError("Error, script to migrate database from version: " << vi <<
267 " to version: " << vi+1 << " not available, resetting the DB");
272 LogInfo("migrating from version " << vi << " to version " << vi+1);
273 m_connection->ExecCommand((*script).c_str());
275 // update DB version info
276 SchemaInfo SchemaInfo(this);
277 SchemaInfo.setVersionInfo();
278 transaction.commit();
282 Crypto::ScriptOptional Crypto::getScript(const std::string &scriptName) const
284 std::string scriptPath = SCRIPTS_PATH + scriptName + std::string(".sql");
285 std::ifstream is(scriptPath);
287 LogError("Script " << scriptPath << " not found!");
288 return ScriptOptional();
291 std::istreambuf_iterator<char> begin(is),end;
292 return ScriptOptional(std::string(begin, end));
295 Crypto::ScriptOptional Crypto::getMigrationScript(int db_version) const
297 std::string scriptPath = std::string(SCRIPT_MIGRATE) + std::to_string(db_version);
298 return getScript(scriptPath);
301 void Crypto::createDBSchema() {
302 Transaction transaction(this);
304 ScriptOptional script = getScript(SCRIPT_CREATE_SCHEMA);
307 std::string errmsg = "Can not create the database schema: no initialization script";
309 ThrowMsg(Exception::InternalError, errmsg);
312 m_connection->ExecCommand((*script).c_str());
313 SchemaInfo SchemaInfo(this);
314 SchemaInfo.setVersionInfo();
315 transaction.commit();
318 void Crypto::resetDB() {
319 Transaction transaction(this);
320 ScriptOptional script = getScript(SCRIPT_DROP_ALL_ITEMS);
323 std::string errmsg = "Can not clear the database: no clearing script";
325 ThrowMsg(Exception::InternalError, errmsg);
328 m_connection->ExecCommand((*script).c_str());
330 transaction.commit();
333 bool Crypto::isNameLabelPresent(const Name &name, const Label &owner) const {
335 NameTable nameTable(this->m_connection);
336 return nameTable.isPresent(name, owner);
337 } Catch(SqlConnection::Exception::SyntaxError) {
338 LogError("Couldn't prepare insert statement");
339 } Catch(SqlConnection::Exception::InternalError) {
340 LogError("Couldn't execute insert statement");
342 ThrowMsg(Crypto::Exception::InternalError,
343 "Couldn't check if name and label pair is present");
346 void Crypto::saveRows(const Name &name, const Label &owner, const RowVector &rows)
349 // transaction is present in the layer above
350 NameTable nameTable(this->m_connection);
351 ObjectTable objectTable(this->m_connection);
352 PermissionTable permissionTable(this->m_connection);
353 nameTable.addRow(name, owner);
354 for (const auto &i: rows)
355 objectTable.addRow(i);
356 permissionTable.setPermission(name,
359 static_cast<int>(DEFAULT_PERMISSIONS));
361 } Catch(SqlConnection::Exception::SyntaxError) {
362 LogError("Couldn't prepare insert statement");
363 } Catch(SqlConnection::Exception::InternalError) {
364 LogError("Couldn't execute insert statement: " << _rethrown_exception.GetMessage());
366 ThrowMsg(Crypto::Exception::InternalError,
367 "Couldn't save Row");
370 void Crypto::saveRow(const Row &row) {
372 // transaction is present in the layer above
373 NameTable nameTable(this->m_connection);
374 ObjectTable objectTable(this->m_connection);
375 PermissionTable permissionTable(this->m_connection);
376 nameTable.addRow(row.name, row.ownerLabel);
377 objectTable.addRow(row);
378 permissionTable.setPermission(row.name,
381 static_cast<int>(DEFAULT_PERMISSIONS));
383 } Catch(SqlConnection::Exception::SyntaxError) {
384 LogError("Couldn't prepare insert statement");
385 } Catch(SqlConnection::Exception::InternalError) {
386 LogError("Couldn't execute insert statement");
388 ThrowMsg(Crypto::Exception::InternalError,
389 "Couldn't save Row");
392 bool Crypto::deleteRow(
394 const Label &ownerLabel)
397 // transaction is present in the layer above
398 NameTable nameTable(this->m_connection);
399 if(nameTable.isPresent(name, ownerLabel))
401 nameTable.deleteRow(name, ownerLabel);
405 } Catch (SqlConnection::Exception::SyntaxError) {
406 LogError("Couldn't prepare delete statement");
407 } Catch (SqlConnection::Exception::InternalError) {
408 LogError("Couldn't execute delete statement");
410 ThrowMsg(Crypto::Exception::InternalError,
411 "Couldn't delete Row for name " << name << " using ownerLabel " << ownerLabel);
415 const SqlConnection::DataCommandUniquePtr &selectCommand) const {
417 row.name = selectCommand->GetColumnString(0);
418 row.ownerLabel = selectCommand->GetColumnString(1);
419 row.exportable = selectCommand->GetColumnInteger(2);
420 row.dataType = DataType(selectCommand->GetColumnInteger(3));
421 row.algorithmType = static_cast<DBCMAlgType>(selectCommand->GetColumnInteger(4));
422 row.encryptionScheme = selectCommand->GetColumnInteger(5);
423 row.iv = selectCommand->GetColumnBlob(6);
424 row.dataSize = selectCommand->GetColumnInteger(7);
425 row.data = selectCommand->GetColumnBlob(8);
426 row.tag = selectCommand->GetColumnBlob(9);
427 row.backendId = static_cast<CryptoBackend>(selectCommand->GetColumnInteger(11));
431 PermissionMaskOptional Crypto::getPermissionRow(
433 const Label &ownerLabel,
434 const Label &accessorLabel) const
437 PermissionTable permissionTable(this->m_connection);
438 return permissionTable.getPermissionRow(name, ownerLabel, accessorLabel);
439 } Catch (SqlConnection::Exception::InvalidColumn) {
440 LogError("Select statement invalid column error");
441 } Catch (SqlConnection::Exception::SyntaxError) {
442 LogError("Couldn't prepare select statement");
443 } Catch (SqlConnection::Exception::InternalError) {
444 LogError("Couldn't execute select statement");
446 return PermissionMaskOptional();
449 Crypto::RowOptional Crypto::getRow(
451 const Label &ownerLabel,
454 return getRow(name, ownerLabel, type, type);
457 Crypto::RowOptional Crypto::getRow(
459 const Label &ownerLabel,
460 DataType typeRangeStart,
461 DataType typeRangeStop)
464 SqlConnection::DataCommandUniquePtr selectCommand =
465 m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL);
466 selectCommand->BindInteger(1, typeRangeStart);
467 selectCommand->BindInteger(2, typeRangeStop);
469 // name table reference
470 selectCommand->BindString (101, name.c_str());
471 selectCommand->BindString (102, ownerLabel.c_str());
473 if(selectCommand->Step())
476 Row current_row = getRow(selectCommand);
479 return RowOptional(current_row);
481 return RowOptional();
483 } Catch (SqlConnection::Exception::InvalidColumn) {
484 LogError("Select statement invalid column error");
485 } Catch (SqlConnection::Exception::SyntaxError) {
486 LogError("Couldn't prepare select statement");
487 } Catch (SqlConnection::Exception::InternalError) {
488 LogError("Couldn't execute select statement");
490 ThrowMsg(Crypto::Exception::InternalError,
491 "Couldn't get row of type <" <<
492 static_cast<int>(typeRangeStart) << "," <<
493 static_cast<int>(typeRangeStop) << ">" <<
494 " name " << name << " with owner label " << ownerLabel);
497 void Crypto::getRows(
499 const Label &ownerLabel,
503 getRows(name, ownerLabel, type, type, output);
506 void Crypto::getRows(
508 const Label &ownerLabel,
509 DataType typeRangeStart,
510 DataType typeRangeStop,
514 SqlConnection::DataCommandUniquePtr selectCommand =
515 m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL);
516 selectCommand->BindInteger(1, typeRangeStart);
517 selectCommand->BindInteger(2, typeRangeStop);
519 // name table reference
520 selectCommand->BindString (101, name.c_str());
521 selectCommand->BindString (102, ownerLabel.c_str());
523 while(selectCommand->Step())
526 output.push_back(getRow(selectCommand));
529 } Catch (SqlConnection::Exception::InvalidColumn) {
530 LogError("Select statement invalid column error");
531 } Catch (SqlConnection::Exception::SyntaxError) {
532 LogError("Couldn't prepare select statement");
533 } Catch (SqlConnection::Exception::InternalError) {
534 LogError("Couldn't execute select statement");
536 ThrowMsg(Crypto::Exception::InternalError,
537 "Couldn't get row of type <" <<
538 static_cast<int>(typeRangeStart) << "," <<
539 static_cast<int>(typeRangeStop) << ">" <<
540 " name " << name << " with owner label " << ownerLabel);
543 void Crypto::listNames(
544 const Label &smackLabel,
545 LabelNameVector& labelNameVector,
548 listNames(smackLabel, labelNameVector, type, type);
551 void Crypto::listNames(
552 const Label &smackLabel,
553 LabelNameVector& labelNameVector,
554 DataType typeRangeStart,
555 DataType typeRangeStop)
558 Transaction transaction(this);
559 SqlConnection::DataCommandUniquePtr selectCommand =
560 m_connection->PrepareDataCommand(DB_CMD_NAME_SELECT_BY_TYPE_AND_PERMISSION);
561 selectCommand->BindInteger(1, static_cast<int>(typeRangeStart));
562 selectCommand->BindInteger(2, static_cast<int>(typeRangeStop));
563 selectCommand->BindString(104, smackLabel.c_str());
564 selectCommand->BindInteger(4, static_cast<int>(Permission::READ | Permission::REMOVE));
566 while(selectCommand->Step()) {
567 Label ownerLabel = selectCommand->GetColumnString(0);
568 Name name = selectCommand->GetColumnString(1);
569 labelNameVector.push_back(std::make_pair(ownerLabel, name));
572 } Catch (SqlConnection::Exception::InvalidColumn) {
573 LogError("Select statement invalid column error");
574 } Catch (SqlConnection::Exception::SyntaxError) {
575 LogError("Couldn't prepare select statement");
576 } Catch (SqlConnection::Exception::InternalError) {
577 LogError("Couldn't execute select statement");
579 ThrowMsg(Crypto::Exception::InternalError,
580 "Couldn't list names of type <" <<
581 static_cast<int>(typeRangeStart) << "," <<
582 static_cast<int>(typeRangeStop) << ">" <<
583 " accessible to client label " << smackLabel);
588 void Crypto::saveKey(
590 const RawBuffer &key)
593 SqlConnection::DataCommandUniquePtr insertCommand =
594 m_connection->PrepareDataCommand(DB_CMD_KEY_INSERT);
595 insertCommand->BindString(1, label.c_str());
596 insertCommand->BindBlob(2, key);
597 insertCommand->Step();
599 } Catch (SqlConnection::Exception::SyntaxError) {
600 LogError("Couldn't prepare insert key statement");
601 } Catch (SqlConnection::Exception::InternalError) {
602 LogError("Couldn't execute insert statement");
604 ThrowMsg(Crypto::Exception::InternalError,
605 "Couldn't save key for label " << label);
608 Crypto::RawBufferOptional Crypto::getKey(const Label& label)
611 SqlConnection::DataCommandUniquePtr selectCommand =
612 m_connection->PrepareDataCommand(DB_CMD_KEY_SELECT);
613 selectCommand->BindString(1, label.c_str());
615 if (selectCommand->Step()) {
616 return RawBufferOptional(
617 selectCommand->GetColumnBlob(0));
619 return RawBufferOptional();
622 } Catch (SqlConnection::Exception::InvalidColumn) {
623 LogError("Select statement invalid column error");
624 } Catch (SqlConnection::Exception::SyntaxError) {
625 LogError("Couldn't prepare insert key statement");
626 } Catch (SqlConnection::Exception::InternalError) {
627 LogError("Couldn't execute insert statement");
629 ThrowMsg(Crypto::Exception::InternalError,
630 "Couldn't get key for label " << label);
633 void Crypto::deleteKey(const Label& label) {
635 Transaction transaction(this);
637 SqlConnection::DataCommandUniquePtr deleteCommand =
638 m_connection->PrepareDataCommand(DB_CMD_KEY_DELETE);
639 deleteCommand->BindString(1, label.c_str());
640 deleteCommand->Step();
642 NameTable nameTable(this->m_connection);
643 nameTable.deleteAllRows(label);
645 transaction.commit();
647 } Catch (SqlConnection::Exception::SyntaxError) {
648 LogError("Couldn't prepare insert key statement");
649 } Catch (SqlConnection::Exception::InternalError) {
650 LogError("Couldn't execute insert statement");
652 ThrowMsg(Crypto::Exception::InternalError,
653 "Couldn't delete key for label " << label);
656 void Crypto::setPermission(
658 const Label& ownerLabel,
659 const Label& accessorLabel,
660 const PermissionMask permissionMask)
663 PermissionTable permissionTable(this->m_connection);
664 permissionTable.setPermission(name, ownerLabel, accessorLabel, permissionMask);
666 } Catch (SqlConnection::Exception::SyntaxError) {
667 LogError("Couldn't prepare set statement");
668 } Catch (SqlConnection::Exception::InternalError) {
669 LogError("Couldn't execute set statement");
671 ThrowMsg(Crypto::Exception::InternalError,
672 "Couldn't set permissions for name " << name );
676 void Crypto::SchemaInfo::setVersionInfo() {
677 SqlConnection::DataCommandUniquePtr insertContextCommand =
678 m_db->m_connection->PrepareDataCommand(DB_CMD_SCHEMA_SET);
679 insertContextCommand->BindString(101, DB_SCHEMA_VERSION_FIELD);
680 insertContextCommand->BindString(103, std::to_string(DB_VERSION_CURRENT).c_str());
681 insertContextCommand->Step();
684 bool Crypto::SchemaInfo::getVersionInfo(int & version) const
686 // Try..Catch mandatory here - we don't need to escalate the error
687 // if it happens - we just won't return the version, allowing CKM to work
689 SqlConnection::DataCommandUniquePtr selectCommand =
690 m_db->m_connection->PrepareDataCommand(DB_CMD_SCHEMA_GET);
691 selectCommand->BindString(101, DB_SCHEMA_VERSION_FIELD);
693 if(selectCommand->Step()) {
694 version = static_cast<int>(atoi(selectCommand->GetColumnString(1).c_str()));
697 } Catch (SqlConnection::Exception::InvalidColumn) {
698 LogError("Select statement invalid column error");
699 } Catch (SqlConnection::Exception::SyntaxError) {
700 LogError("Couldn't prepare select statement");
701 } Catch (SqlConnection::Exception::InternalError) {
702 LogError("Couldn't execute select statement");
707 void Crypto::PermissionTable::setPermission(
709 const Label& ownerLabel,
710 const Label& accessorLabel,
711 const PermissionMask permissionMask)
713 if(permissionMask == Permission::NONE)
716 SqlConnection::DataCommandUniquePtr deletePermissionCommand =
717 m_connection->PrepareDataCommand(DB_CMD_PERMISSION_DELETE);
718 deletePermissionCommand->BindString(104, accessorLabel.c_str());
719 deletePermissionCommand->BindString(101, name.c_str());
720 deletePermissionCommand->BindString(102, ownerLabel.c_str());
721 deletePermissionCommand->Step();
725 // add new permissions
726 SqlConnection::DataCommandUniquePtr setPermissionCommand =
727 m_connection->PrepareDataCommand(DB_CMD_PERMISSION_SET);
728 setPermissionCommand->BindString(104, accessorLabel.c_str());
729 setPermissionCommand->BindInteger(105, static_cast<int>(permissionMask));
730 setPermissionCommand->BindString(101, name.c_str());
731 setPermissionCommand->BindString(102, ownerLabel.c_str());
732 setPermissionCommand->Step();
736 PermissionMaskOptional Crypto::PermissionTable::getPermissionRow(
738 const Label &ownerLabel,
739 const Label &accessorLabel) const
741 SqlConnection::DataCommandUniquePtr selectCommand =
742 m_connection->PrepareDataCommand(DB_CMD_PERMISSION_SELECT);
743 selectCommand->BindString(104, accessorLabel.c_str());
745 // name table reference
746 selectCommand->BindString(101, name.c_str());
747 selectCommand->BindString(102, ownerLabel.c_str());
749 if(selectCommand->Step())
751 // there is entry for the <name, ownerLabel> pair
752 return PermissionMaskOptional(PermissionMask(selectCommand->GetColumnInteger(0)));
754 return PermissionMaskOptional();
757 void Crypto::NameTable::addRow(
759 const Label &ownerLabel)
762 SqlConnection::DataCommandUniquePtr insertNameCommand =
763 m_connection->PrepareDataCommand(DB_CMD_NAME_INSERT);
764 insertNameCommand->BindString (101, name.c_str());
765 insertNameCommand->BindString (102, ownerLabel.c_str());
766 insertNameCommand->Step();
769 void Crypto::NameTable::deleteRow(
771 const Label &ownerLabel)
773 SqlConnection::DataCommandUniquePtr deleteCommand =
774 m_connection->PrepareDataCommand(DB_CMD_NAME_DELETE);
775 deleteCommand->BindString(101, name.c_str());
776 deleteCommand->BindString(102, ownerLabel.c_str());
778 // Step() result code does not provide information whether
779 // anything was removed.
780 deleteCommand->Step();
783 void Crypto::NameTable::deleteAllRows(const Label &ownerLabel)
785 SqlConnection::DataCommandUniquePtr deleteData =
786 m_connection->PrepareDataCommand(DB_CMD_NAME_DELETE_BY_LABEL);
787 deleteData->BindString(102, ownerLabel.c_str());
789 // Step() result code does not provide information whether
790 // anything was removed.
794 bool Crypto::NameTable::isPresent(const Name &name, const Label &ownerLabel) const
796 SqlConnection::DataCommandUniquePtr checkCmd =
797 m_connection->PrepareDataCommand(DB_CMD_NAME_COUNT_ROWS);
798 checkCmd->BindString(101, name.c_str());
799 checkCmd->BindString(102, ownerLabel.c_str());
800 if(checkCmd->Step()) {
801 int element_count = checkCmd->GetColumnInteger(0);
802 LogDebug("Item name: " << name << " ownerLabel: " << ownerLabel <<
803 " hit count: " << element_count);
804 if(element_count > 0)
810 void Crypto::ObjectTable::addRow(const Row &row)
812 SqlConnection::DataCommandUniquePtr insertObjectCommand =
813 m_connection->PrepareDataCommand(DB_CMD_OBJECT_INSERT);
814 insertObjectCommand->BindInteger(1, row.exportable);
815 insertObjectCommand->BindInteger(2, static_cast<int>(row.dataType));
816 insertObjectCommand->BindInteger(3, static_cast<int>(row.algorithmType));
817 insertObjectCommand->BindInteger(4, row.encryptionScheme);
818 insertObjectCommand->BindBlob (5, row.iv);
819 insertObjectCommand->BindInteger(6, row.dataSize);
820 insertObjectCommand->BindBlob (7, row.data);
821 insertObjectCommand->BindBlob (8, row.tag);
822 insertObjectCommand->BindInteger(9, static_cast<int>(row.backendId));
824 // name table reference
825 insertObjectCommand->BindString (101, row.name.c_str());
826 insertObjectCommand->BindString (102, row.ownerLabel.c_str());
828 insertObjectCommand->Step();
831 std::string Crypto::getSchema() {
832 SqlConnection::DataCommandUniquePtr schema =
833 m_connection->PrepareDataCommand("SELECT sql FROM "
834 "(SELECT * FROM sqlcipher_master UNION ALL "
835 "SELECT * FROM sqlcipher_temp_master) "
836 "WHERE type!='meta' "
837 "ORDER BY tbl_name, type DESC, name;");
839 std::stringstream ss;
840 while(schema->Step()) {
841 ss << schema->GetColumnString(0) << std::endl;
846 std::string Crypto::getContent() {
847 SqlConnection::DataCommandUniquePtr tableSelect =
848 m_connection->PrepareDataCommand(
849 "SELECT name FROM sqlcipher_master "
850 "WHERE type IN ('table','view') AND name NOT LIKE 'sqlcipher_%' "
852 "SELECT name FROM sqlcipher_temp_master "
853 "WHERE type IN ('table','view') "
856 std::vector<std::string> tables;
857 while(tableSelect->Step()) {
858 tables.push_back(tableSelect->GetColumnString(0));
861 std::stringstream ss;
863 for (auto &e : tables) {
864 ss << "Table " << e << std::endl;
865 std::string query = "select * from " + e + ";";
866 SqlConnection::DataCommandUniquePtr result =
867 m_connection->PrepareDataCommand(query.c_str());
868 while(result->Step()) {
869 int maxColumn = result->GetColumnCount();
870 for (int i = 0; i < maxColumn; ++i) {
871 switch(result->GetColumnType(i)) {
873 ss << result->GetColumnInteger(i) << " | ";
876 ss << result->GetColumnFloat(i) << " | ";
879 ss << result->GetColumnString(i) << " | ";
883 auto buffer = result->GetColumnBlob(i);
884 ss << "BLOB (Size: " << buffer.size() << ") | ";
901 #pragma GCC diagnostic pop