* @brief Implementation of encrypted db access layer
*/
+#include <fstream>
+#include <sstream>
#include <db-crypto.h>
#include <dpl/db/sql_connection.h>
#include <dpl/log/log.h>
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
namespace {
- const char *main_table = "CKM_TABLE";
- const char *key_table = "KEY_TABLE";
- const char *permission_table = "PERMISSION_TABLE";
-
-// CKM_TABLE (name TEXT, label TEXT, restricted INT, exportable INT, dataType INT, algorithmType INT,
-// encryptionScheme INT, iv BLOB, dataSize INT, data BLOB, tag BLOB, idx INT )
-
- const char *db_create_main_cmd =
- "CREATE TABLE CKM_TABLE("
- " name TEXT NOT NULL,"
- " label TEXT NOT NULL,"
- " exportable INTEGER NOT NULL,"
- " dataType INTEGER NOT NULL,"
- " algorithmType INTEGER NOT NULL,"
- " encryptionScheme INTEGER NOT NULL,"
- " iv BLOB NOT NULL,"
- " dataSize INTEGER NOT NULL,"
- " data BLOB NOT NULL,"
- " tag BLOB NOT NULL,"
- " idx INTEGER PRIMARY KEY AUTOINCREMENT,"
- " UNIQUE(name, label)"
- "); CREATE INDEX ckm_index_label ON CKM_TABLE(label);"; // based on ANALYZE and performance test result
-
- const char *insert_main_cmd =
- "INSERT INTO CKM_TABLE("
- // 1 2 3
- " name, label, exportable,"
- // 4 5 6
- " dataType, algorithmType, encryptionScheme,"
- // 7 8 9 10
- " iv, dataSize, data, tag) "
- "VALUES("
- " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
-
- const char *select_name_cmd =
- "SELECT * FROM CKM_TABLE WHERE name=?001 AND label=?002 AND dataType=?003; ";
-
- const char *select_name_cmd_join =
- "SELECT * FROM CKM_TABLE WHERE name=?001 AND label=?002 AND dataType=?004 AND "
- " idx in (SELECT idx FROM PERMISSION_TABLE WHERE label = ?003); ";
-
- const char *select_check_name_cmd =
- "SELECT dataType FROM CKM_TABLE WHERE name=?001 AND label=?002;";
-
- const char *select_label_global_name_cmd =
- "SELECT count(*) FROM CKM_TABLE WHERE name=?001 AND label=?002; ";
-
-// const char *select_label_index_global_name_cmd =
-// // 1
-// "SELECT label, idx FROM CKM_TABLE WHERE name=?;";
-
- const char *select_key_name_cmd =
- "SELECT * FROM CKM_TABLE WHERE name=?001 AND label=?002"
- " AND dataType BETWEEN ?003 AND ?004;";
-
- const char *select_key_name_cmd_join =
- "SELECT * FROM CKM_TABLE WHERE name=?001 AND label=?002"
- " AND dataType BETWEEN ?004 AND ?005 "
- " AND idx in (SELECT idx FROM PERMISSION_TABLE WHERE label = ?003);";
-
- const char *select_count_rows_cmd =
- "SELECT COUNT(idx) FROM CKM_TABLE WHERE name=?001 AND label=?002;";
-
- const char *delete_name_cmd =
- "DELETE FROM CKM_TABLE WHERE name=?001 AND label=?002;";
-
- const char *delete_name_cmd_join =
- "DELETE FROM CKM_TABLE WHERE name=?001 AND label=?002 AND "
- " idx in (SELECT idx FROM PERMISSION_TABLE WHERE label=?003);";
-
-
- const char *delete_data_with_key_cmd =
- // 1
- "DELETE FROM CKM_TABLE WHERE label=?;";
-
-// KEY_TABLE (label TEXT, key BLOB)
-
- const char *db_create_key_cmd =
- "CREATE TABLE KEY_TABLE("
- " label TEXT PRIMARY KEY,"
- " key BLOB NOT NULL"
- ");";
-
- const char *insert_key_cmd =
- "INSERT INTO KEY_TABLE(label, key) VALUES (?, ?);";
- const char *select_key_cmd =
- "SELECT key FROM KEY_TABLE WHERE label=?;";
- const char *delete_key_cmd =
- "DELETE FROM KEY_TABLE WHERE label=?";
-
-
-// PERMISSION_TABLE (label TEXT, access_flags TEXT, idx INT)
-
- const char *db_create_permission_cmd =
- "CREATE TABLE PERMISSION_TABLE("
- " label TEXT NOT NULL,"
- " accessFlags TEXT NOT NULL,"
- " idx INTEGER NOT NULL,"
- " FOREIGN KEY(idx) REFERENCES CKM_TABLE(idx) ON DELETE CASCADE,"
- " PRIMARY KEY(label, idx)"
- "); CREATE INDEX perm_index_idx ON PERMISSION_TABLE(idx);"; // based on ANALYZE and performance test result
-
- const char *set_permission_name_cmd =
- "REPLACE INTO PERMISSION_TABLE(label, accessFlags, idx) "
- " VALUES (?001, ?002, "
- " (SELECT idx FROM CKM_TABLE WHERE name = ?003 and label = ?004)); ";
-
- const char *select_permission_cmd =
- "SELECT accessFlags FROM PERMISSION_TABLE WHERE label=?001 AND idx IN (SELECT idx FROM CKM_TABLE WHERE name=?002 AND label=?003);";
-
- const char *delete_permission_cmd =
- "DELETE FROM PERMISSION_TABLE WHERE label=?003 AND "
- " idx IN (SELECT idx FROM CKM_TABLE WHERE name = ?001 AND label = ?002); ";
-
-
-// CKM_TABLE x PERMISSION_TABLE
-
- const char *select_type_cross_cmd =
- "SELECT C.label, C.name FROM CKM_TABLE AS C LEFT JOIN PERMISSION_TABLE AS P ON C.idx = P.idx WHERE "
- "C.dataType=?001 AND (C.label=?002 OR (P.label=?002 AND P.accessFlags IS NOT NULL)) GROUP BY C.name;";
-
- const char *select_key_type_cross_cmd =
- "SELECT C.label, C.name FROM CKM_TABLE AS C LEFT JOIN PERMISSION_TABLE AS P ON C.idx=P.idx WHERE "
- " C.dataType>=?001 AND C.dataType<=?002 AND "
- "(C.label=?003 OR (P.label=?003 AND P.accessFlags IS NOT NULL)) GROUP BY C.name; ";
+ const CKM::PermissionMask DEFAULT_PERMISSIONS =
+ static_cast<CKM::PermissionMask>(CKM::Permission::READ | CKM::Permission::REMOVE);
+
+ const char *SCRIPTS_PATH = "/usr/share/ckm/scripts/";
+
+ enum DBVersion : int {
+ DB_VERSION_1 = 1,
+ DB_VERSION_2 = 2,
+ /* ... since version 3, there is no need to manually
+ * recognize database version.
+ * Remember only that if doing changes to the database,
+ * increment and update DB_VERSION_CURRENT,
+ * then provide migration mechanism!
+ */
+ DB_VERSION_CURRENT = 4
+ };
+
+ const char *SCRIPT_CREATE_SCHEMA = "create_schema";
+ const char *SCRIPT_DROP_ALL_ITEMS = "drop_all";
+ const char *SCRIPT_MIGRATE = "migrate_";
+
+ // common substitutions:
+ // 100 - idx
+ // 101 - name
+ // 102 - label
+ // 103 - value
+ // 104 - permissionLabel
+ // 105 - permissionMask
+ const char *DB_CMD_SCHEMA_SET =
+ "REPLACE INTO SCHEMA_INFO(name, value) "
+ " VALUES(?101, ?103);";
+
+ const char *DB_CMD_SCHEMA_GET =
+ "SELECT * FROM SCHEMA_INFO WHERE name=?101;";
+
+ const char *DB_SCHEMA_VERSION_FIELD = "schema_version";
+
+
+ const char *DB_CMD_NAME_INSERT =
+ "INSERT INTO NAMES("
+ " name, label) "
+ " VALUES(?101, ?102);";
+
+ const char *DB_CMD_NAME_COUNT_ROWS =
+ "SELECT COUNT(idx) FROM NAMES WHERE name=?101 AND label=?102;";
+
+ const char *DB_CMD_NAME_DELETE =
+ "DELETE FROM NAMES WHERE name=?101 AND label=?102;";
+
+ const char *DB_CMD_NAME_DELETE_BY_LABEL =
+ "DELETE FROM NAMES WHERE label=?102;";
+
+
+ const char *DB_CMD_OBJECT_INSERT =
+ "INSERT INTO OBJECTS("
+ " exportable, dataType,"
+ " algorithmType, encryptionScheme,"
+ " iv, dataSize, data, tag, idx, backendId) "
+ " VALUES(?001, ?002, ?003, ?004, ?005, "
+ " ?006, ?007, ?008,"
+ " (SELECT idx FROM NAMES WHERE name=?101 and label=?102),"
+ " ?009"
+ " );";
+
+ const char *DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL =
+ "SELECT * FROM [join_name_object_tables] "
+ " WHERE (dataType BETWEEN ?001 AND ?002) "
+ " AND name=?101 and label=?102;";
+
+
+ const char *DB_CMD_KEY_INSERT =
+ "INSERT INTO KEYS(label, key) VALUES (?, ?);";
+ const char *DB_CMD_KEY_SELECT =
+ "SELECT key FROM KEYS WHERE label=?;";
+ const char *DB_CMD_KEY_DELETE =
+ "DELETE FROM KEYS WHERE label=?";
+
+
+ const char *DB_CMD_PERMISSION_SET = // SQLite does not support updating views
+ "REPLACE INTO PERMISSIONS(permissionLabel, permissionMask, idx) "
+ " VALUES (?104, ?105, (SELECT idx FROM NAMES WHERE name=?101 and label=?102));";
+
+ const char *DB_CMD_PERMISSION_SELECT =
+ "SELECT permissionMask FROM [join_name_permission_tables] "
+ " WHERE permissionLabel=?104 "
+ " AND name=?101 and label=?102;";
+
+ const char *DB_CMD_PERMISSION_DELETE = // SQLite does not support updating views
+ "DELETE FROM PERMISSIONS WHERE permissionLabel=?104 AND "
+ " idx=(SELECT idx FROM NAMES WHERE name=?101 and label=?102);";
+
+
+ /*
+ * GROUP BY is necessary because of the following case:
+ * -There are several permissions to L1, N1 (label, name) from other accessors. When listing
+ * objects accessible by L1 the query will produce one result (L1, N1) for each allowed
+ * accessor but GROUP BY will reduce them to one so L1 will have (L1, N1) on its list only once
+ */
+ const char *DB_CMD_NAME_SELECT_BY_TYPE_AND_PERMISSION =
+ "SELECT label, name FROM [join_all_tables] "
+ " WHERE dataType>=?001 AND dataType<=?002 "
+ " AND permissionLabel=?104 AND permissionMask&?004!=0 GROUP BY idx;";
}
namespace CKM {
-using namespace DB;
- DBCrypto::DBCrypto(const std::string& path,
- const RawBuffer &rawPass) {
+namespace DB {
+ Crypto::Crypto(const std::string& path, const RawBuffer &rawPass)
+ {
m_connection = NULL;
m_inUserTransaction = false;
Try {
m_connection = new SqlConnection(path, SqlConnection::Flag::Option::CRW);
m_connection->SetKey(rawPass);
- m_connection->ExecCommand("VACUUM;");
initDatabase();
+ m_connection->ExecCommand("VACUUM;");
} Catch(SqlConnection::Exception::ConnectionBroken) {
LogError("Couldn't connect to database: " << path);
- ReThrow(DBCrypto::Exception::InternalError);
+ ReThrow(Crypto::Exception::InternalError);
} Catch(SqlConnection::Exception::InvalidArguments) {
LogError("Couldn't set the key for database");
- ReThrow(DBCrypto::Exception::InternalError);
+ ReThrow(Crypto::Exception::InternalError);
} Catch(SqlConnection::Exception::SyntaxError) {
LogError("Couldn't initiate the database");
- ReThrow(DBCrypto::Exception::InternalError);
+ ReThrow(Crypto::Exception::InternalError);
} Catch(SqlConnection::Exception::InternalError) {
LogError("Couldn't create the database");
- ReThrow(DBCrypto::Exception::InternalError);
+ ReThrow(Crypto::Exception::InternalError);
}
}
- DBCrypto::DBCrypto(DBCrypto &&other) :
+ Crypto::Crypto(Crypto &&other) :
m_connection(other.m_connection),
- m_inUserTransaction(other.m_inUserTransaction){
+ m_inUserTransaction(other.m_inUserTransaction)
+ {
other.m_connection = NULL;
other.m_inUserTransaction = false;
}
- DBCrypto::~DBCrypto() {
+ Crypto::~Crypto() {
delete m_connection;
}
- DBCrypto& DBCrypto::operator=(DBCrypto&& other) {
+ Crypto& Crypto::operator=(Crypto&& other) {
if (this == &other)
return *this;
delete m_connection;
return *this;
}
- void DBCrypto::createTable(
+ void Crypto::createTable(
const char* create_cmd,
const char *table_name)
{
}
}
- void DBCrypto::initDatabase() {
- Transaction transaction(this);
- if(!m_connection->CheckTableExist(main_table)) {
- createTable(db_create_main_cmd, main_table);
+ void Crypto::createView(
+ const char* create_cmd)
+ {
+ Try {
+ m_connection->ExecCommand(create_cmd);
+ } Catch(SqlConnection::Exception::SyntaxError) {
+ LogError("Couldn't create view!");
+ throw;
+ } Catch(SqlConnection::Exception::InternalError) {
+ LogError("Sqlite got into infinite busy state");
+ throw;
}
- if(!m_connection->CheckTableExist(key_table)) {
- createTable(db_create_key_cmd, key_table);
+ }
+
+ bool Crypto::getDBVersion(int & schemaVersion)
+ {
+ SchemaInfo SchemaInfo(this);
+ if(SchemaInfo.getVersionInfo(schemaVersion)) {
+ LogDebug("Current DB version: " << schemaVersion);
+ return true;
}
- if(!m_connection->CheckTableExist(permission_table)) {
- createTable(db_create_permission_cmd, permission_table);
+ else
+ {
+ LogDebug("No DB version known or DB not present");
+
+ // special case: old CKM_TABLE exists
+ if(m_connection->CheckTableExist("CKM_TABLE")) {
+ schemaVersion = DB_VERSION_1;
+ return true;
+ }
+
+ // special case: new scheme exists, but no SCHEMA_INFO table present
+ else if(m_connection->CheckTableExist("NAME_TABLE")) {
+ schemaVersion = DB_VERSION_2;
+ return true;
+ }
}
- transaction.commit();
+ // not recognized - proceed with an empty DBs
+ return false;
}
-// void DBCrypto::getLabelForName(const Name &name, Label & label) const {
-// SqlConnection::DataCommandUniquePtr checkCmd =
-// m_connection->PrepareDataCommand(select_label_global_name_cmd);
-// checkCmd->BindString(1, name.c_str());
-// if(checkCmd->Step()) {
-// label = checkCmd->GetColumnString(0);
-// } else
-// label.clear();
-// }
-
-// void DBCrypto::getLabelForName(const Name &name, Label & label, int & index) const
-// {
-// SqlConnection::DataCommandUniquePtr checkCmd =
-// m_connection->PrepareDataCommand(select_label_index_global_name_cmd);
-// checkCmd->BindString(1, name.c_str());
-// if(checkCmd->Step()) {
-// label = checkCmd->GetColumnString(0);
-// index = checkCmd->GetColumnInteger(1);
-// }
-// else
-// {
-// label.clear();
-// index = -1;
-// }
-// }
-
- bool DBCrypto::checkGlobalNameExist(const Name &name, const Label &ownerLabel) const {
- SqlConnection::DataCommandUniquePtr checkCmd =
- m_connection->PrepareDataCommand(select_label_global_name_cmd);
- checkCmd->BindString(1, name.c_str());
- checkCmd->BindString(2, ownerLabel.c_str());
- if(checkCmd->Step())
- return checkCmd->GetColumnInteger(0)?true:false;
- return false;
+ void Crypto::initDatabase()
+ {
+ // run migration if old database is present
+ int schemaVersion;
+ if( getDBVersion(schemaVersion)==false || // DB empty or corrupted
+ schemaVersion > DB_VERSION_CURRENT) // or too new scheme
+ {
+ LogDebug("no database or database corrupted, initializing the DB");
+ resetDB();
+ }
+ else
+ {
+ // migration needed
+ LogDebug("DB migration from version " << schemaVersion << " to version " << DB_VERSION_CURRENT << " started.");
+ Transaction transaction(this);
+ for(int vi=schemaVersion; vi<DB_VERSION_CURRENT; vi++)
+ {
+ ScriptOptional script = getMigrationScript(vi);
+ if(!script)
+ {
+ LogError("Error, script to migrate database from version: " << vi <<
+ " to version: " << vi+1 << " not available, resetting the DB");
+ resetDB();
+ break;
+ }
+
+ LogInfo("migrating from version " << vi << " to version " << vi+1);
+ m_connection->ExecCommand((*script).c_str());
+ }
+ // update DB version info
+ SchemaInfo SchemaInfo(this);
+ SchemaInfo.setVersionInfo();
+ transaction.commit();
+ }
}
- bool DBCrypto::checkNameExist(const Name &name, const Label &owner) const {
- SqlConnection::DataCommandUniquePtr checkCmd =
- m_connection->PrepareDataCommand(select_check_name_cmd);
- checkCmd->BindString(1, name.c_str());
- checkCmd->BindString(2, owner.c_str());
- if(checkCmd->Step()) {
- LogDebug("Private name '" << name << "' exists already for type "
- << checkCmd->GetColumnInteger(0));
- return true;
- } else
- return false;
+ Crypto::ScriptOptional Crypto::getScript(const std::string &scriptName) const
+ {
+ std::string scriptPath = SCRIPTS_PATH + scriptName + std::string(".sql");
+ std::ifstream is(scriptPath);
+ if(is.fail()) {
+ LogError("Script " << scriptPath << " not found!");
+ return ScriptOptional();
+ }
+
+ std::istreambuf_iterator<char> begin(is),end;
+ return ScriptOptional(std::string(begin, end));
}
- void DBCrypto::saveDBRow(const DBRow &row){
- Try {
+ Crypto::ScriptOptional Crypto::getMigrationScript(int db_version) const
+ {
+ std::string scriptPath = std::string(SCRIPT_MIGRATE) + std::to_string(db_version);
+ return getScript(scriptPath);
+ }
- //Sqlite does not support partial index in our version,
- //so we do it by hand
- Transaction transaction(this);
- if(checkNameExist(row.name, row.smackLabel)) {
- ThrowMsg(DBCrypto::Exception::NameExists,
- "Name exists for name: " << row.name);
- }
+ void Crypto::createDBSchema() {
+ Transaction transaction(this);
- SqlConnection::DataCommandUniquePtr insertCommand =
- m_connection->PrepareDataCommand(insert_main_cmd);
- insertCommand->BindString(1, row.name.c_str());
- insertCommand->BindString(2, row.smackLabel.c_str());
- insertCommand->BindInteger(3, row.exportable);
- insertCommand->BindInteger(4, static_cast<int>(row.dataType));
- insertCommand->BindInteger(5, static_cast<int>(row.algorithmType));
- insertCommand->BindInteger(6, row.encryptionScheme);
- insertCommand->BindBlob(7, row.iv);
- insertCommand->BindInteger(8, row.dataSize);
- insertCommand->BindBlob(9, row.data);
- insertCommand->BindBlob(10, row.tag);
+ ScriptOptional script = getScript(SCRIPT_CREATE_SCHEMA);
+ if(!script)
+ {
+ std::string errmsg = "Can not create the database schema: no initialization script";
+ LogError(errmsg);
+ ThrowMsg(Exception::InternalError, errmsg);
+ }
- insertCommand->Step();
- transaction.commit();
- return;
+ m_connection->ExecCommand((*script).c_str());
+ SchemaInfo SchemaInfo(this);
+ SchemaInfo.setVersionInfo();
+ transaction.commit();
+ }
+ void Crypto::resetDB() {
+ Transaction transaction(this);
+ ScriptOptional script = getScript(SCRIPT_DROP_ALL_ITEMS);
+ if(!script)
+ {
+ std::string errmsg = "Can not clear the database: no clearing script";
+ LogError(errmsg);
+ ThrowMsg(Exception::InternalError, errmsg);
+ }
+
+ m_connection->ExecCommand((*script).c_str());
+ createDBSchema();
+ transaction.commit();
+ }
+
+ bool Crypto::isNameLabelPresent(const Name &name, const Label &owner) const {
+ Try {
+ NameTable nameTable(this->m_connection);
+ return nameTable.isPresent(name, owner);
} Catch(SqlConnection::Exception::SyntaxError) {
LogError("Couldn't prepare insert statement");
} Catch(SqlConnection::Exception::InternalError) {
LogError("Couldn't execute insert statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't save DBRow");
+ ThrowMsg(Crypto::Exception::InternalError,
+ "Couldn't check if name and label pair is present");
}
- DBRow DBCrypto::getRow(const SqlConnection::DataCommandUniquePtr &selectCommand) {
- DBRow row;
- row.name = selectCommand->GetColumnString(0);
- row.smackLabel = selectCommand->GetColumnString(1);
- row.exportable = selectCommand->GetColumnInteger(2);
- row.dataType = static_cast<DBDataType>(selectCommand->GetColumnInteger(3));
- row.algorithmType = static_cast<DBCMAlgType>(selectCommand->GetColumnInteger(4));
- row.encryptionScheme = selectCommand->GetColumnInteger(5);
- row.iv = selectCommand->GetColumnBlob(6);
- row.dataSize = selectCommand->GetColumnInteger(7);
- row.data = selectCommand->GetColumnBlob(8);
- row.tag = selectCommand->GetColumnBlob(9);
- return row;
- }
-
- std::string DBCrypto::getPermissions(const Name &name, const Label &ownerLabel, const Label &smackLabel) const
+ void Crypto::saveRows(const Name &name, const Label &owner, const RowVector &rows)
{
- Try{
- SqlConnection::DataCommandUniquePtr selectCommand =
- m_connection->PrepareDataCommand(select_permission_cmd);
- selectCommand->BindString(1, smackLabel.c_str());
- selectCommand->BindString(2, name.c_str());
- selectCommand->BindString(3, ownerLabel.c_str());
-
- if(selectCommand->Step())
- return selectCommand->GetColumnString(0);
-
- return std::string();
- } Catch (SqlConnection::Exception::InvalidColumn) {
- LogError("Select statement invalid column error");
- } Catch (SqlConnection::Exception::SyntaxError) {
- LogError("Couldn't prepare select statement");
- } Catch (SqlConnection::Exception::InternalError) {
- LogError("Couldn't execute select statement");
+ Try {
+ // transaction is present in the layer above
+ NameTable nameTable(this->m_connection);
+ ObjectTable objectTable(this->m_connection);
+ PermissionTable permissionTable(this->m_connection);
+ nameTable.addRow(name, owner);
+ for (const auto &i: rows)
+ objectTable.addRow(i);
+ permissionTable.setPermission(name,
+ owner,
+ owner,
+ static_cast<int>(DEFAULT_PERMISSIONS));
+ return;
+ } Catch(SqlConnection::Exception::SyntaxError) {
+ LogError("Couldn't prepare insert statement");
+ } Catch(SqlConnection::Exception::InternalError) {
+ LogError("Couldn't execute insert statement: " << _rethrown_exception.GetMessage());
}
- return std::string();
+ ThrowMsg(Crypto::Exception::InternalError,
+ "Couldn't save Row");
}
- DBCrypto::DBRowOptional DBCrypto::getDBRow(
- const Name &name,
- const Label &ownerLabel,
- const Label &smackLabel,
- DBDataType type)
- {
- if (ownerLabel == smackLabel)
- return getDBRowSimple(name, ownerLabel, type);
- return getDBRowJoin(name, ownerLabel, smackLabel, type);
+ void Crypto::saveRow(const Row &row) {
+ Try {
+ // transaction is present in the layer above
+ NameTable nameTable(this->m_connection);
+ ObjectTable objectTable(this->m_connection);
+ PermissionTable permissionTable(this->m_connection);
+ nameTable.addRow(row.name, row.ownerLabel);
+ objectTable.addRow(row);
+ permissionTable.setPermission(row.name,
+ row.ownerLabel,
+ row.ownerLabel,
+ static_cast<int>(DEFAULT_PERMISSIONS));
+ return;
+ } Catch(SqlConnection::Exception::SyntaxError) {
+ LogError("Couldn't prepare insert statement");
+ } Catch(SqlConnection::Exception::InternalError) {
+ LogError("Couldn't execute insert statement");
+ }
+ ThrowMsg(Crypto::Exception::InternalError,
+ "Couldn't save Row");
}
- DBCrypto::DBRowOptional DBCrypto::getDBRowSimple(
- const Name &name,
- const Label &owner,
- DBDataType type)
+ bool Crypto::deleteRow(
+ const Name &name,
+ const Label &ownerLabel)
{
Try {
- Transaction transaction(this);
- SqlConnection::DataCommandUniquePtr selectCommand =
- m_connection->PrepareDataCommand(select_name_cmd);
- selectCommand->BindString(1, name.c_str());
- selectCommand->BindString(2, owner.c_str());
- selectCommand->BindInteger(3, static_cast<int>(type));
-
- if(selectCommand->Step())
+ // transaction is present in the layer above
+ NameTable nameTable(this->m_connection);
+ if(nameTable.isPresent(name, ownerLabel))
{
- // extract data
- DBRow current_row = getRow(selectCommand);
-
- // finalize DB operations
- transaction.commit();
-
- // all okay, proceed
- return DBRowOptional(current_row);
- } else {
- return DBRowOptional();
+ nameTable.deleteRow(name, ownerLabel);
+ return true;
}
- } Catch (SqlConnection::Exception::InvalidColumn) {
- LogError("Select statement invalid column error");
+ return false;
} Catch (SqlConnection::Exception::SyntaxError) {
- LogError("Couldn't prepare select statement");
+ LogError("Couldn't prepare delete statement");
} Catch (SqlConnection::Exception::InternalError) {
- LogError("Couldn't execute select statement");
+ LogError("Couldn't execute delete statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't get row for type " << static_cast<int>(type) <<
- " name " << name << " using client label " << owner);
+ ThrowMsg(Crypto::Exception::InternalError,
+ "Couldn't delete Row for name " << name << " using ownerLabel " << ownerLabel);
}
- DBCrypto::DBRowOptional DBCrypto::getDBRowJoin(
+ Row Crypto::getRow(
+ const SqlConnection::DataCommandUniquePtr &selectCommand) const {
+ Row row;
+ row.name = selectCommand->GetColumnString(0);
+ row.ownerLabel = selectCommand->GetColumnString(1);
+ row.exportable = selectCommand->GetColumnInteger(2);
+ row.dataType = DataType(selectCommand->GetColumnInteger(3));
+ row.algorithmType = static_cast<DBCMAlgType>(selectCommand->GetColumnInteger(4));
+ row.encryptionScheme = selectCommand->GetColumnInteger(5);
+ row.iv = selectCommand->GetColumnBlob(6);
+ row.dataSize = selectCommand->GetColumnInteger(7);
+ row.data = selectCommand->GetColumnBlob(8);
+ row.tag = selectCommand->GetColumnBlob(9);
+ row.backendId = static_cast<CryptoBackend>(selectCommand->GetColumnInteger(11));
+ return row;
+ }
+
+ PermissionMaskOptional Crypto::getPermissionRow(
const Name &name,
const Label &ownerLabel,
- const Label &smackLabel,
- DBDataType type)
+ const Label &accessorLabel) const
{
Try {
- Transaction transaction(this);
- SqlConnection::DataCommandUniquePtr selectCommand =
- m_connection->PrepareDataCommand(select_name_cmd_join);
- selectCommand->BindString(1, name.c_str());
- selectCommand->BindString(2, ownerLabel.c_str());
- selectCommand->BindString(3, smackLabel.c_str());
- selectCommand->BindInteger(4, static_cast<int>(type));
-
- if(selectCommand->Step())
- {
- // extract data
- DBRow current_row = getRow(selectCommand);
-
- // finalize DB operations
- transaction.commit();
-
- // all okay, proceed
- return DBRowOptional(current_row);
- } else {
- return DBRowOptional();
- }
+ PermissionTable permissionTable(this->m_connection);
+ return permissionTable.getPermissionRow(name, ownerLabel, accessorLabel);
} Catch (SqlConnection::Exception::InvalidColumn) {
LogError("Select statement invalid column error");
} Catch (SqlConnection::Exception::SyntaxError) {
} Catch (SqlConnection::Exception::InternalError) {
LogError("Couldn't execute select statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't get row for type " << static_cast<int>(type) <<
- " name " << name << " using client label " << smackLabel);
+ return PermissionMaskOptional();
}
- DBCrypto::DBRowOptional DBCrypto::getKeyDBRow(
+ Crypto::RowOptional Crypto::getRow(
const Name &name,
const Label &ownerLabel,
- const Label &smackLabel)
+ DataType type)
{
- if (ownerLabel == smackLabel)
- return getKeyDBRowSimple(name, ownerLabel);
- else
- return getKeyDBRowJoin(name, ownerLabel, smackLabel);
+ return getRow(name, ownerLabel, type, type);
}
- DBCrypto::DBRowOptional DBCrypto::getKeyDBRowSimple(
+ Crypto::RowOptional Crypto::getRow(
const Name &name,
- const Label &ownerLabel)
+ const Label &ownerLabel,
+ DataType typeRangeStart,
+ DataType typeRangeStop)
{
- Try{
- Transaction transaction(this);
+ Try {
SqlConnection::DataCommandUniquePtr selectCommand =
- m_connection->PrepareDataCommand(select_key_name_cmd);
- selectCommand->BindString(1, name.c_str());
- selectCommand->BindString(2, ownerLabel.c_str());
- selectCommand->BindInteger(3, static_cast<int>(DBDataType::DB_KEY_FIRST));
- selectCommand->BindInteger(4, static_cast<int>(DBDataType::DB_KEY_LAST));
+ m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL);
+ selectCommand->BindInteger(1, typeRangeStart);
+ selectCommand->BindInteger(2, typeRangeStop);
+
+ // name table reference
+ selectCommand->BindString (101, name.c_str());
+ selectCommand->BindString (102, ownerLabel.c_str());
if(selectCommand->Step())
{
// extract data
- DBRow current_row = getRow(selectCommand);
-
- // finalize DB operations
- transaction.commit();
+ Row current_row = getRow(selectCommand);
// all okay, proceed
- return DBRowOptional(current_row);
+ return RowOptional(current_row);
} else {
- return DBRowOptional();
+ return RowOptional();
}
} Catch (SqlConnection::Exception::InvalidColumn) {
LogError("Select statement invalid column error");
} Catch (SqlConnection::Exception::InternalError) {
LogError("Couldn't execute select statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't get Key for name " << name
- << " using client label " << ownerLabel);
+ ThrowMsg(Crypto::Exception::InternalError,
+ "Couldn't get row of type <" <<
+ static_cast<int>(typeRangeStart) << "," <<
+ static_cast<int>(typeRangeStop) << ">" <<
+ " name " << name << " with owner label " << ownerLabel);
}
- DBCrypto::DBRowOptional DBCrypto::getKeyDBRowJoin(
+ void Crypto::getRows(
const Name &name,
const Label &ownerLabel,
- const Label &smackLabel)
+ DataType type,
+ RowVector &output)
{
- Try{
- Transaction transaction(this);
- SqlConnection::DataCommandUniquePtr selectCommand =
- m_connection->PrepareDataCommand(select_key_name_cmd_join);
- selectCommand->BindString(1, name.c_str());
- selectCommand->BindString(2, ownerLabel.c_str());
- selectCommand->BindString(3, smackLabel.c_str());
- selectCommand->BindInteger(4, static_cast<int>(DBDataType::DB_KEY_FIRST));
- selectCommand->BindInteger(5, static_cast<int>(DBDataType::DB_KEY_LAST));
-
- if(selectCommand->Step())
- {
- // extract data
- DBRow current_row = getRow(selectCommand);
-
- // finalize DB operations
- transaction.commit();
-
- // all okay, proceed
- return DBRowOptional(current_row);
- } else {
- return DBRowOptional();
- }
- } Catch (SqlConnection::Exception::InvalidColumn) {
- LogError("Select statement invalid column error");
- } Catch (SqlConnection::Exception::SyntaxError) {
- LogError("Couldn't prepare select statement");
- } Catch (SqlConnection::Exception::InternalError) {
- LogError("Couldn't execute select statement");
- }
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't get Key for name " << name
- << " using client label " << smackLabel);
+ getRows(name, ownerLabel, type, type, output);
}
- void DBCrypto::getSingleType(
- const Label &clnt_label,
- DBDataType type,
- LabelNameVector& labelNameVector) const
+ void Crypto::getRows(
+ const Name &name,
+ const Label &ownerLabel,
+ DataType typeRangeStart,
+ DataType typeRangeStop,
+ RowVector &output)
{
- Try{
+ Try {
SqlConnection::DataCommandUniquePtr selectCommand =
- m_connection->PrepareDataCommand(select_type_cross_cmd);
- selectCommand->BindInteger(1, static_cast<int>(type));
- selectCommand->BindString(2, clnt_label.c_str());
+ m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL);
+ selectCommand->BindInteger(1, typeRangeStart);
+ selectCommand->BindInteger(2, typeRangeStop);
- while(selectCommand->Step()) {
- Label label = selectCommand->GetColumnString(0);
- Name name = selectCommand->GetColumnString(1);
- labelNameVector.push_back(std::make_pair(label, name));
+ // name table reference
+ selectCommand->BindString (101, name.c_str());
+ selectCommand->BindString (102, ownerLabel.c_str());
+
+ while(selectCommand->Step())
+ {
+ // extract data
+ output.push_back(getRow(selectCommand));
}
return;
} Catch (SqlConnection::Exception::InvalidColumn) {
} Catch (SqlConnection::Exception::InternalError) {
LogError("Couldn't execute select statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't get type " << static_cast<int>(type));
+ ThrowMsg(Crypto::Exception::InternalError,
+ "Couldn't get row of type <" <<
+ static_cast<int>(typeRangeStart) << "," <<
+ static_cast<int>(typeRangeStop) << ">" <<
+ " name " << name << " with owner label " << ownerLabel);
}
- void DBCrypto::getNames(
- const Label &clnt_label,
- DBDataType type,
- LabelNameVector& labelNameVector)
+ void Crypto::listNames(
+ const Label &smackLabel,
+ LabelNameVector& labelNameVector,
+ DataType type)
{
- getSingleType(clnt_label, type, labelNameVector);
+ listNames(smackLabel, labelNameVector, type, type);
}
-
- void DBCrypto::getKeyNames(const Label &clnt_label, LabelNameVector &labelNameVector)
+ void Crypto::listNames(
+ const Label &smackLabel,
+ LabelNameVector& labelNameVector,
+ DataType typeRangeStart,
+ DataType typeRangeStop)
{
Try{
Transaction transaction(this);
SqlConnection::DataCommandUniquePtr selectCommand =
- m_connection->PrepareDataCommand(select_key_type_cross_cmd);
- selectCommand->BindInteger(1, static_cast<int>(DBDataType::DB_KEY_FIRST));
- selectCommand->BindInteger(2, static_cast<int>(DBDataType::DB_KEY_LAST));
- selectCommand->BindString(3, clnt_label.c_str());
+ m_connection->PrepareDataCommand(DB_CMD_NAME_SELECT_BY_TYPE_AND_PERMISSION);
+ selectCommand->BindInteger(1, static_cast<int>(typeRangeStart));
+ selectCommand->BindInteger(2, static_cast<int>(typeRangeStop));
+ selectCommand->BindString(104, smackLabel.c_str());
+ selectCommand->BindInteger(4, static_cast<int>(Permission::READ | Permission::REMOVE));
while(selectCommand->Step()) {
- Label label = selectCommand->GetColumnString(0);
+ Label ownerLabel = selectCommand->GetColumnString(0);
Name name = selectCommand->GetColumnString(1);
- labelNameVector.push_back(std::make_pair(label, name));
+ labelNameVector.push_back(std::make_pair(ownerLabel, name));
}
- transaction.commit();
return;
} Catch (SqlConnection::Exception::InvalidColumn) {
LogError("Select statement invalid column error");
} Catch (SqlConnection::Exception::InternalError) {
LogError("Couldn't execute select statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError, "Couldn't get key names");
- }
-
- bool DBCrypto::deleteDBRow(const Name &name, const Label &ownerLabel, const Label &credLabel) {
- if (ownerLabel == credLabel)
- return deleteDBRowSimple(name, ownerLabel);
- return deleteDBRowJoin(name, ownerLabel, credLabel);
- }
-
- bool DBCrypto::deleteDBRowSimple(const Name &name, const Label &ownerLabel)
- {
- Try {
- Transaction transaction(this);
-
- if(countRows(name, ownerLabel) > 0)
- {
- SqlConnection::DataCommandUniquePtr deleteCommand =
- m_connection->PrepareDataCommand(delete_name_cmd);
- deleteCommand->BindString(1, name.c_str());
- deleteCommand->BindString(2, ownerLabel.c_str());
-
- // Step() result code does not provide information whether
- // anything was removed.
- deleteCommand->Step();
- transaction.commit();
-
- return true;
- }
- return false;
- } Catch (SqlConnection::Exception::SyntaxError) {
- LogError("Couldn't prepare delete statement");
- } Catch (SqlConnection::Exception::InternalError) {
- LogError("Couldn't execute delete statement");
- }
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't delete DBRow for name " << name << " using client label " << ownerLabel);
+ ThrowMsg(Crypto::Exception::InternalError,
+ "Couldn't list names of type <" <<
+ static_cast<int>(typeRangeStart) << "," <<
+ static_cast<int>(typeRangeStop) << ">" <<
+ " accessible to client label " << smackLabel);
}
- bool DBCrypto::deleteDBRowJoin(const Name &name, const Label &ownerLabel, const Label &smackLabel)
- {
- Try {
- Transaction transaction(this);
-
- if (!checkNameExist(name, ownerLabel))
- return false;
-
- std::string permissions = DBCrypto::getPermissions(name, ownerLabel, smackLabel);
- if(permissions.empty() == false)
- {
- // entry present, check if for reading or read/remove
- if(permissions.find(toDBAccessRight(AccessRight::AR_READ_REMOVE)) == std::string::npos)
- ThrowMsg(DBCrypto::Exception::PermissionDenied, "Client " << smackLabel << " can only read " <<
- ownerLabel << CKM::LABEL_NAME_SEPARATOR << name << ", remove forbidden");
-
- SqlConnection::DataCommandUniquePtr deleteCommand =
- m_connection->PrepareDataCommand(delete_name_cmd_join);
- deleteCommand->BindString(1, name.c_str());
- deleteCommand->BindString(2, ownerLabel.c_str());
- deleteCommand->BindString(3, smackLabel.c_str());
-
- // Step() result code does not provide information whether
- // anything was removed.
- deleteCommand->Step();
- transaction.commit();
-
- return true;
- }
- return false;
- } Catch (SqlConnection::Exception::SyntaxError) {
- LogError("Couldn't prepare delete statement");
- } Catch (SqlConnection::Exception::InternalError) {
- LogError("Couldn't execute delete statement");
- }
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't delete DBRow for name " << name << " using client label " << ownerLabel);
- }
- int DBCrypto::countRows(const Name &name, const Label &ownerLabel) {
- SqlConnection::DataCommandUniquePtr checkCmd =
- m_connection->PrepareDataCommand(select_count_rows_cmd);
- checkCmd->BindString(1, name.c_str());
- checkCmd->BindString(2, ownerLabel.c_str());
- if(checkCmd->Step()) {
- return checkCmd->GetColumnInteger(0);
- } else {
- LogDebug("Row does not exist for name=" << name << "and label=" << ownerLabel);
- return 0;
- }
- }
- void DBCrypto::saveKey(
+ void Crypto::saveKey(
const Label& label,
const RawBuffer &key)
{
Try {
- Transaction transaction(this);
SqlConnection::DataCommandUniquePtr insertCommand =
- m_connection->PrepareDataCommand(insert_key_cmd);
+ m_connection->PrepareDataCommand(DB_CMD_KEY_INSERT);
insertCommand->BindString(1, label.c_str());
insertCommand->BindBlob(2, key);
insertCommand->Step();
- transaction.commit();
return;
} Catch (SqlConnection::Exception::SyntaxError) {
LogError("Couldn't prepare insert key statement");
} Catch (SqlConnection::Exception::InternalError) {
LogError("Couldn't execute insert statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
+ ThrowMsg(Crypto::Exception::InternalError,
"Couldn't save key for label " << label);
}
- DBCrypto::RawBufferOptional DBCrypto::getKey(const Label& label)
+ Crypto::RawBufferOptional Crypto::getKey(const Label& label)
{
Try {
- Transaction transaction(this);
SqlConnection::DataCommandUniquePtr selectCommand =
- m_connection->PrepareDataCommand(select_key_cmd);
+ m_connection->PrepareDataCommand(DB_CMD_KEY_SELECT);
selectCommand->BindString(1, label.c_str());
if (selectCommand->Step()) {
- transaction.commit();
return RawBufferOptional(
selectCommand->GetColumnBlob(0));
} else {
- transaction.commit();
return RawBufferOptional();
}
} Catch (SqlConnection::Exception::InternalError) {
LogError("Couldn't execute insert statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
+ ThrowMsg(Crypto::Exception::InternalError,
"Couldn't get key for label " << label);
}
- void DBCrypto::deleteKey(const Label& label) {
+ void Crypto::deleteKey(const Label& label) {
Try {
Transaction transaction(this);
SqlConnection::DataCommandUniquePtr deleteCommand =
- m_connection->PrepareDataCommand(delete_key_cmd);
+ m_connection->PrepareDataCommand(DB_CMD_KEY_DELETE);
deleteCommand->BindString(1, label.c_str());
deleteCommand->Step();
- SqlConnection::DataCommandUniquePtr deleteData =
- m_connection->PrepareDataCommand(delete_data_with_key_cmd);
- deleteData->BindString(1, label.c_str());
- deleteData->Step();
+ NameTable nameTable(this->m_connection);
+ nameTable.deleteAllRows(label);
transaction.commit();
return;
} Catch (SqlConnection::Exception::InternalError) {
LogError("Couldn't execute insert statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
+ ThrowMsg(Crypto::Exception::InternalError,
"Couldn't delete key for label " << label);
}
- int DBCrypto::setAccessRights(
+ void Crypto::setPermission(
const Name &name,
const Label& ownerLabel,
const Label& accessorLabel,
- const AccessRight accessRights)
+ const PermissionMask permissionMask)
{
Try {
- Transaction transaction(this);
-
- // owner can not add permissions to itself
- if(ownerLabel.compare(accessorLabel) == 0)
- return CKM_API_ERROR_INPUT_PARAM;
-
- if (!checkNameExist(name, ownerLabel))
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
-
- SqlConnection::DataCommandUniquePtr setPermissionCommand =
- m_connection->PrepareDataCommand(set_permission_name_cmd);
- setPermissionCommand->BindString(1, accessorLabel.c_str());
- setPermissionCommand->BindString(2, toDBAccessRight(accessRights));
- setPermissionCommand->BindString(3, name.c_str());
- setPermissionCommand->BindString(4, ownerLabel.c_str());
- setPermissionCommand->Step();
- transaction.commit();
- return CKM_API_SUCCESS;
+ PermissionTable permissionTable(this->m_connection);
+ permissionTable.setPermission(name, ownerLabel, accessorLabel, permissionMask);
+ return;
} Catch (SqlConnection::Exception::SyntaxError) {
LogError("Couldn't prepare set statement");
} Catch (SqlConnection::Exception::InternalError) {
LogError("Couldn't execute set statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
+ ThrowMsg(Crypto::Exception::InternalError,
"Couldn't set permissions for name " << name );
}
- int DBCrypto::clearAccessRights(
- const Name &name,
- const Label &ownerLabel,
- const Label &accessorLabel)
+
+ void Crypto::SchemaInfo::setVersionInfo() {
+ SqlConnection::DataCommandUniquePtr insertContextCommand =
+ m_db->m_connection->PrepareDataCommand(DB_CMD_SCHEMA_SET);
+ insertContextCommand->BindString(101, DB_SCHEMA_VERSION_FIELD);
+ insertContextCommand->BindString(103, std::to_string(DB_VERSION_CURRENT).c_str());
+ insertContextCommand->Step();
+ }
+
+ bool Crypto::SchemaInfo::getVersionInfo(int & version) const
{
+ // Try..Catch mandatory here - we don't need to escalate the error
+ // if it happens - we just won't return the version, allowing CKM to work
Try {
- Transaction transaction(this);
-
- // owner can not add permissions to itself
- if(ownerLabel.compare(accessorLabel) == 0)
- return CKM_API_ERROR_INPUT_PARAM;
+ SqlConnection::DataCommandUniquePtr selectCommand =
+ m_db->m_connection->PrepareDataCommand(DB_CMD_SCHEMA_GET);
+ selectCommand->BindString(101, DB_SCHEMA_VERSION_FIELD);
- // check if CKM entry present
- if (!checkNameExist(name, ownerLabel)) {
- transaction.commit();
- return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+ if(selectCommand->Step()) {
+ version = static_cast<int>(atoi(selectCommand->GetColumnString(1).c_str()));
+ return true;
}
+ } Catch (SqlConnection::Exception::InvalidColumn) {
+ LogError("Select statement invalid column error");
+ } Catch (SqlConnection::Exception::SyntaxError) {
+ LogError("Couldn't prepare select statement");
+ } Catch (SqlConnection::Exception::InternalError) {
+ LogError("Couldn't execute select statement");
+ }
+ return false;
+ }
- // check if permission entry present
- if( DBCrypto::getPermissions(name, ownerLabel, accessorLabel).empty() )
- return CKM_API_ERROR_INPUT_PARAM;
-
+ void Crypto::PermissionTable::setPermission(
+ const Name &name,
+ const Label& ownerLabel,
+ const Label& accessorLabel,
+ const PermissionMask permissionMask)
+ {
+ if(permissionMask == Permission::NONE)
+ {
+ // clear permissions
SqlConnection::DataCommandUniquePtr deletePermissionCommand =
- m_connection->PrepareDataCommand(delete_permission_cmd);
- deletePermissionCommand->BindString(1, name.c_str());
- deletePermissionCommand->BindString(2, ownerLabel.c_str());
- deletePermissionCommand->BindString(3, accessorLabel.c_str());
+ m_connection->PrepareDataCommand(DB_CMD_PERMISSION_DELETE);
+ deletePermissionCommand->BindString(104, accessorLabel.c_str());
+ deletePermissionCommand->BindString(101, name.c_str());
+ deletePermissionCommand->BindString(102, ownerLabel.c_str());
deletePermissionCommand->Step();
- transaction.commit();
- return CKM_API_SUCCESS;
- } Catch (SqlConnection::Exception::SyntaxError) {
- LogError("Couldn't prepare delete statement");
- } Catch (SqlConnection::Exception::InternalError) {
- LogError("Couldn't execute delete statement");
}
- ThrowMsg(DBCrypto::Exception::InternalError,
- "Couldn't delete permissions for name " << name);
+ else
+ {
+ // add new permissions
+ SqlConnection::DataCommandUniquePtr setPermissionCommand =
+ m_connection->PrepareDataCommand(DB_CMD_PERMISSION_SET);
+ setPermissionCommand->BindString(104, accessorLabel.c_str());
+ setPermissionCommand->BindInteger(105, static_cast<int>(permissionMask));
+ setPermissionCommand->BindString(101, name.c_str());
+ setPermissionCommand->BindString(102, ownerLabel.c_str());
+ setPermissionCommand->Step();
+ }
}
+ PermissionMaskOptional Crypto::PermissionTable::getPermissionRow(
+ const Name &name,
+ const Label &ownerLabel,
+ const Label &accessorLabel) const
+ {
+ SqlConnection::DataCommandUniquePtr selectCommand =
+ m_connection->PrepareDataCommand(DB_CMD_PERMISSION_SELECT);
+ selectCommand->BindString(104, accessorLabel.c_str());
+
+ // name table reference
+ selectCommand->BindString(101, name.c_str());
+ selectCommand->BindString(102, ownerLabel.c_str());
+
+ if(selectCommand->Step())
+ {
+ // there is entry for the <name, ownerLabel> pair
+ return PermissionMaskOptional(PermissionMask(selectCommand->GetColumnInteger(0)));
+ }
+ return PermissionMaskOptional();
+ }
+
+ void Crypto::NameTable::addRow(
+ const Name &name,
+ const Label &ownerLabel)
+ {
+ // insert NAMES item
+ SqlConnection::DataCommandUniquePtr insertNameCommand =
+ m_connection->PrepareDataCommand(DB_CMD_NAME_INSERT);
+ insertNameCommand->BindString (101, name.c_str());
+ insertNameCommand->BindString (102, ownerLabel.c_str());
+ insertNameCommand->Step();
+ }
+
+ void Crypto::NameTable::deleteRow(
+ const Name &name,
+ const Label &ownerLabel)
+ {
+ SqlConnection::DataCommandUniquePtr deleteCommand =
+ m_connection->PrepareDataCommand(DB_CMD_NAME_DELETE);
+ deleteCommand->BindString(101, name.c_str());
+ deleteCommand->BindString(102, ownerLabel.c_str());
+
+ // Step() result code does not provide information whether
+ // anything was removed.
+ deleteCommand->Step();
+ }
+
+ void Crypto::NameTable::deleteAllRows(const Label &ownerLabel)
+ {
+ SqlConnection::DataCommandUniquePtr deleteData =
+ m_connection->PrepareDataCommand(DB_CMD_NAME_DELETE_BY_LABEL);
+ deleteData->BindString(102, ownerLabel.c_str());
+
+ // Step() result code does not provide information whether
+ // anything was removed.
+ deleteData->Step();
+ }
+
+ bool Crypto::NameTable::isPresent(const Name &name, const Label &ownerLabel) const
+ {
+ SqlConnection::DataCommandUniquePtr checkCmd =
+ m_connection->PrepareDataCommand(DB_CMD_NAME_COUNT_ROWS);
+ checkCmd->BindString(101, name.c_str());
+ checkCmd->BindString(102, ownerLabel.c_str());
+ if(checkCmd->Step()) {
+ int element_count = checkCmd->GetColumnInteger(0);
+ LogDebug("Item name: " << name << " ownerLabel: " << ownerLabel <<
+ " hit count: " << element_count);
+ if(element_count > 0)
+ return true;
+ }
+ return false;
+ }
+
+ void Crypto::ObjectTable::addRow(const Row &row)
+ {
+ SqlConnection::DataCommandUniquePtr insertObjectCommand =
+ m_connection->PrepareDataCommand(DB_CMD_OBJECT_INSERT);
+ insertObjectCommand->BindInteger(1, row.exportable);
+ insertObjectCommand->BindInteger(2, static_cast<int>(row.dataType));
+ insertObjectCommand->BindInteger(3, static_cast<int>(row.algorithmType));
+ insertObjectCommand->BindInteger(4, row.encryptionScheme);
+ insertObjectCommand->BindBlob (5, row.iv);
+ insertObjectCommand->BindInteger(6, row.dataSize);
+ insertObjectCommand->BindBlob (7, row.data);
+ insertObjectCommand->BindBlob (8, row.tag);
+ insertObjectCommand->BindInteger(9, static_cast<int>(row.backendId));
+
+ // name table reference
+ insertObjectCommand->BindString (101, row.name.c_str());
+ insertObjectCommand->BindString (102, row.ownerLabel.c_str());
+
+ insertObjectCommand->Step();
+ }
+
+ std::string Crypto::getSchema() {
+ SqlConnection::DataCommandUniquePtr schema =
+ m_connection->PrepareDataCommand("SELECT sql FROM "
+ "(SELECT * FROM sqlcipher_master UNION ALL "
+ "SELECT * FROM sqlcipher_temp_master) "
+ "WHERE type!='meta' "
+ "ORDER BY tbl_name, type DESC, name;");
+
+ std::stringstream ss;
+ while(schema->Step()) {
+ ss << schema->GetColumnString(0) << std::endl;
+ }
+ return ss.str();
+ }
+
+ std::string Crypto::getContent() {
+ SqlConnection::DataCommandUniquePtr tableSelect =
+ m_connection->PrepareDataCommand(
+ "SELECT name FROM sqlcipher_master "
+ "WHERE type IN ('table','view') AND name NOT LIKE 'sqlcipher_%' "
+ "UNION ALL "
+ "SELECT name FROM sqlcipher_temp_master "
+ "WHERE type IN ('table','view') "
+ "ORDER BY 1; ");
+
+ std::vector<std::string> tables;
+ while(tableSelect->Step()) {
+ tables.push_back(tableSelect->GetColumnString(0));
+ }
+
+ std::stringstream ss;
+
+ for (auto &e : tables) {
+ ss << "Table " << e << std::endl;
+ std::string query = "select * from " + e + ";";
+ SqlConnection::DataCommandUniquePtr result =
+ m_connection->PrepareDataCommand(query.c_str());
+ while(result->Step()) {
+ int maxColumn = result->GetColumnCount();
+ for (int i = 0; i < maxColumn; ++i) {
+ switch(result->GetColumnType(i)) {
+ case 1: // int64
+ ss << result->GetColumnInteger(i) << " | ";
+ break;
+ case 2: // float
+ ss << result->GetColumnFloat(i) << " | ";
+ break;
+ case 3: // string
+ ss << result->GetColumnString(i) << " | ";
+ break;
+ case 4: // Blob
+ {
+ auto buffer = result->GetColumnBlob(i);
+ ss << "BLOB (Size: " << buffer.size() << ") | ";
+ break;
+ }
+ case 5: // NULL
+ ss << "NULL | ";
+ break;
+ }
+ }
+ ss << std::endl;
+ }
+ }
+
+ return ss.str();
+ }
+} // namespace DB
} // namespace CKM
#pragma GCC diagnostic pop