summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartlomiej Grzelewski <b.grzelewski@samsung.com>2017-08-02 14:21:44 +0200
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>2018-08-06 08:33:28 +0000
commit3f269161226259db05411999e54b6f3ea33bda53 (patch)
treea4012523c06d508614247188f162fd1fbf220265
parentac4e965a376dfdd05fcc4cc1661f74bffac2aea4 (diff)
downloadkey-manager-3f269161226259db05411999e54b6f3ea33bda53.tar.gz
key-manager-3f269161226259db05411999e54b6f3ea33bda53.tar.bz2
key-manager-3f269161226259db05411999e54b6f3ea33bda53.zip
Test version of ckm_db_merge
ckm_db_merge allows to read database and copy it's contents to other one. ckm_db_merge supports db since versions 0.1.14. Please note: both databases will be automatically migrated to the newest schema. Change-Id: I5cec9dfdc2ab75a2ccd5156b0bb05cb46d134480
-rw-r--r--packaging/key-manager.spec1
-rw-r--r--src/manager/service/db-crypto.h6
-rw-r--r--tools/ckm_db_tool/CMakeLists.txt23
-rw-r--r--tools/ckm_db_tool/ckm-logic-ext.cpp32
-rw-r--r--tools/ckm_db_tool/ckm-logic-ext.h4
-rw-r--r--tools/ckm_db_tool/ckm_db_merge.cpp193
-rw-r--r--tools/ckm_db_tool/ckm_db_tool.cpp221
-rw-r--r--tools/ckm_db_tool/db-crypto-ext.cpp30
-rw-r--r--tools/ckm_db_tool/db-crypto-ext.h3
-rw-r--r--tools/ckm_db_tool/db-wrapper.cpp138
-rw-r--r--tools/ckm_db_tool/db-wrapper.h55
11 files changed, 520 insertions, 186 deletions
diff --git a/packaging/key-manager.spec b/packaging/key-manager.spec
index fe470a77..aead73a4 100644
--- a/packaging/key-manager.spec
+++ b/packaging/key-manager.spec
@@ -322,5 +322,6 @@ fi
%{bin_dir}/ckm-tests-internal
%{bin_dir}/ckm_so_loader
%{bin_dir}/ckm_db_tool
+%{bin_dir}/ckm_db_merge
%{bin_dir}/ckm_generate_db
%test_dir
diff --git a/src/manager/service/db-crypto.h b/src/manager/service/db-crypto.h
index 3fbacf6e..f4021c32 100644
--- a/src/manager/service/db-crypto.h
+++ b/src/manager/service/db-crypto.h
@@ -200,6 +200,9 @@ public:
protected:
SqlConnection *m_connection;
+ Row getRow(
+ const SqlConnection::DataCommandUniquePtr &selectCommand) const;
+
private:
bool m_inUserTransaction;
@@ -219,9 +222,6 @@ private:
ScriptOptional getScript(const std::string &scriptName) const;
ScriptOptional getMigrationScript(int db_version) const;
- Row getRow(
- const SqlConnection::DataCommandUniquePtr &selectCommand) const;
-
void createTable(
const char *create_cmd,
const char *table_name);
diff --git a/tools/ckm_db_tool/CMakeLists.txt b/tools/ckm_db_tool/CMakeLists.txt
index 7b78c1a9..4a47a1dc 100644
--- a/tools/ckm_db_tool/CMakeLists.txt
+++ b/tools/ckm_db_tool/CMakeLists.txt
@@ -1,4 +1,5 @@
SET(CKM_DB_TOOL "ckm_db_tool")
+SET(CKM_DB_MERGE "ckm_db_merge")
SET(KEY_MANAGER_PATH ${PROJECT_SOURCE_DIR}/src/manager)
IF (TZ_BACKEND_ENABLED)
@@ -36,10 +37,10 @@ INCLUDE_DIRECTORIES(
${KEY_MANAGER_PATH}/crypto
)
-SET(CKM_DB_TOOL_SOURCES
- ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm_db_tool.cpp
+SET(CKM_DB_TOOLS_SOURCES
${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/db-crypto-ext.cpp
${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm-logic-ext.cpp
+ ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/db-wrapper.cpp
${KEY_MANAGER_PATH}/crypto/platform/decider.cpp
${KEY_MANAGER_PATH}/crypto/sw-backend/internals.cpp
${KEY_MANAGER_PATH}/crypto/sw-backend/obj.cpp
@@ -80,8 +81,8 @@ SET(CKM_DB_TOOL_SOURCES
)
IF(TZ_BACKEND_ENABLED)
-SET(CKM_DB_TOOL_SOURCES
- ${CKM_DB_TOOL_SOURCES}
+SET(CKM_DB_TOOLS_SOURCES
+ ${CKM_DB_TOOLS_SOURCES}
${KEY_MANAGER_PATH}/crypto/tz-backend/internals.cpp
${KEY_MANAGER_PATH}/crypto/tz-backend/obj.cpp
${KEY_MANAGER_PATH}/crypto/tz-backend/store.cpp
@@ -92,7 +93,7 @@ ENDIF()
LINK_DIRECTORIES(${CKM_DB_TOOL_DEP_LIBRARY_DIRS})
-ADD_EXECUTABLE( ${CKM_DB_TOOL} ${CKM_DB_TOOL_SOURCES} )
+ADD_EXECUTABLE(${CKM_DB_TOOL} ${CKM_DB_TOOLS_SOURCES} ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm_db_tool.cpp)
IF(TZ_BACKEND_ENABLED)
SET(CKM_DB_TOOL_LINK_EXTRA_DEPS
@@ -110,8 +111,18 @@ TARGET_LINK_LIBRARIES(${CKM_DB_TOOL}
-ldl
)
+ADD_EXECUTABLE(${CKM_DB_MERGE} ${CKM_DB_TOOLS_SOURCES} ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm_db_merge.cpp)
+
+TARGET_LINK_LIBRARIES(${CKM_DB_MERGE}
+ ${CMAKE_THREAD_LIBS_INIT}
+ ${CKM_DB_TOOL_DEP_LIBRARIES}
+ ${TARGET_KEY_MANAGER_COMMON}
+ ${CKM_DB_TOOL_LINK_EXTRA_DEPS}
+ -ldl
+ )
+
#place for output file
-INSTALL(TARGETS ${CKM_DB_TOOL}
+INSTALL(TARGETS ${CKM_DB_TOOL} ${CKM_DB_MERGE}
DESTINATION ${BIN_DIR}
PERMISSIONS OWNER_READ
OWNER_WRITE
diff --git a/tools/ckm_db_tool/ckm-logic-ext.cpp b/tools/ckm_db_tool/ckm-logic-ext.cpp
index a82b5db6..6d64fc4c 100644
--- a/tools/ckm_db_tool/ckm-logic-ext.cpp
+++ b/tools/ckm_db_tool/ckm-logic-ext.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,15 +27,6 @@ namespace CKM {
DB::SqlConnection::Output CKMLogicExt::Execute(uid_t user,
const std::string &cmd)
{
- if (user < 5000 && !m_systemDbUnlocked) {
- if (CKM_API_SUCCESS != unlockSystemDB())
- ThrowErr(Exc::DatabaseLocked, "can not unlock system database");
-
- m_systemDbUnlocked = true;
- }
-
- DB::SqlConnection::Output output;
-
/*
* We need to access to DB::Crypto::m_connection to call Execute() on it. We don't want to mess
* with DB::Crypto too much so adding a friend and extending public interface was not an option.
@@ -47,7 +38,7 @@ DB::SqlConnection::Output CKMLogicExt::Execute(uid_t user,
DB::CryptoExt db(std::move(m_userDataMap[user].database));
try {
- output = db.Execute(cmd);
+ DB::SqlConnection::Output output = db.Execute(cmd);
m_userDataMap[user].database = std::move(*static_cast<DB::Crypto *>(&db));
return output;
} catch (const DB::SqlConnection::Exception::Base &e) {
@@ -56,6 +47,25 @@ DB::SqlConnection::Output CKMLogicExt::Execute(uid_t user,
}
}
+DB::RowVector CKMLogicExt::getRows(uid_t user)
+{
+ DB::CryptoExt db(std::move(m_userDataMap[user].database));
+
+ try {
+ DB::RowVector output = db.getRows();
+ m_userDataMap[user].database = std::move(*static_cast<DB::Crypto *>(&db));
+ return output;
+ } catch (const DB::SqlConnection::Exception::Base &e) {
+ m_userDataMap[user].database = std::move(*static_cast<DB::Crypto *>(&db));
+ throw;
+ }
+}
+
+void CKMLogicExt::saveRow(uid_t user, const DB::Row &row)
+{
+ m_userDataMap[user].database.saveRow(row);
+}
+
} // namespace CKM
diff --git a/tools/ckm_db_tool/ckm-logic-ext.h b/tools/ckm_db_tool/ckm-logic-ext.h
index ca6916f9..c9881791 100644
--- a/tools/ckm_db_tool/ckm-logic-ext.h
+++ b/tools/ckm_db_tool/ckm-logic-ext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,8 @@ struct CKMLogicExt : public CKMLogic {
CKMLogicExt() : m_systemDbUnlocked(false) {}
DB::SqlConnection::Output Execute(uid_t user, const std::string &cmd);
+ DB::RowVector getRows(uid_t user);
+ void saveRow(uid_t user, const DB::Row &row);
private:
bool m_systemDbUnlocked;
diff --git a/tools/ckm_db_tool/ckm_db_merge.cpp b/tools/ckm_db_tool/ckm_db_merge.cpp
new file mode 100644
index 00000000..17e308cf
--- /dev/null
+++ b/tools/ckm_db_tool/ckm_db_merge.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file ckm_db_merge.cpp
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ */
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <exception>
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include <db-wrapper.h>
+
+using namespace std;
+using namespace CKM;
+
+typedef function<bool(DB::Row &row)> RowFilter;
+typedef vector<RowFilter> RowFilterVector;
+
+bool printRow(const DB::Row &row) {
+ string iv(10, ' '), data(10, ' ');
+ for (std::size_t i=0; i < iv.size(); ++i) {
+ if (row.iv.size() > i) iv[i] = row.iv[i];
+ if (row.data.size() > i) data[i] = row.data[i];
+ }
+ cout << "Read row:";
+ cout << "\n Name: " << row.name;
+ cout << "\n Owner: " << row.ownerLabel;
+ cout << "\n Exportable: " << row.exportable;
+ cout << "\n Alg type: " << static_cast<int>(row.algorithmType);
+ cout << "\n Enc schema: " << row.encryptionScheme;
+ cout << "\n Data size: " << row.dataSize;
+ cout << "\n BackendId: " << static_cast<int>(row.backendId);
+ cout << "\n Data(first 10 chars): " << data;
+ cout << "\n IV(first 10 chars): " << iv;
+ cout << "\n";
+ return true;
+}
+
+void printUsage()
+{
+ cout << "Usage: ckm_db_merge [OPTION]\n";
+ cout << "Copy data from one key-manager database into other one.\n";
+ cout << "Options:\n";
+ cout << " -v, --verbose print additional data on screen\n";
+ cout << " -s, --source UID database UID from were data will be readed - default value 0\n";
+ cout << " -t, --target UID database UID to were data will be writen - default value 0\n";
+ cout << " -p, --spass PASSWORD password for source database - default empty string\n";
+ cout << " -r, --tpass PASSWORD password for target database - default emtpy string\n";
+ cout << " -o, --owner OWNER change the owner of information in database to OWNER\n";
+ cout << " -h, --help print this help on screen\n";
+ cout << "Example: Copy data from db-5001 to db-0 (system database) and change object owner to /System\n";
+ cout << " ckm_db_merge -s 5001 -t 0 -p !@#SDFCV -o \"/System\"\n";
+ cout << "Please note: This tool automatically updates databases to newest scheme!" << endl;
+}
+
+int mergeDatabase(
+ uid_t uid1,
+ const Password &pass1,
+ uid_t uid2,
+ const Password &pass2,
+ const RowFilterVector &filters)
+{
+ DbWrapper source(uid1, pass1);
+ DbWrapper target(uid2, pass2);
+
+ int ret;
+
+ if (CKM_API_SUCCESS != (ret = source.unlock())) { // this should migrate database to newest version
+ cerr << "Unlocking source database failed: " << ret << endl;
+ return 1;
+ }
+ if (CKM_API_SUCCESS != (ret = target.unlock())) { // this should migrate database to newest version
+ cerr << "Unlocking target database failed: " << ret << endl;
+ return 1;
+ }
+
+ DB::RowVector data = source.getRows();
+
+ // apply all filters to each row
+ for (auto &e : data) {
+ bool migrate = true;
+ for (auto &f : filters) {
+ migrate &= f(e);
+ }
+ if (migrate) {
+ try {
+ target.saveRow(e);
+ } catch (const CKM::DB::SqlConnection::Exception::Base &e) {
+ cerr << "Sql exception. Migration failed or object already exist in database: " << e.DumpToString() << endl;
+ }
+ }
+ }
+
+ source.lock();
+ target.lock();
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ Password password1, password2;
+ uid_t uid1 = 0, uid2 = 0;
+ string owner;
+ RowFilterVector filters;
+ try {
+ while (1) {
+ int option_index = 0;
+
+ static struct option long_options[] = {
+ {"verbose", no_argument, 0, 'v'},
+ {"source", required_argument, 0, 's'},
+ {"target", required_argument, 0, 't'},
+ {"spass", required_argument, 0, 'p'},
+ {"tpass", required_argument, 0, 'r'},
+ {"owner", required_argument, 0, 'o'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0 }
+ };
+ int c = getopt_long(argc, argv, "vs:t:p:r:o:h", long_options, &option_index);
+
+ if (-1 == c)
+ break;
+
+ switch (c) {
+ case 'v':
+ filters.push_back(printRow);
+ break;
+ case 's':
+ uid1 = stoi(optarg);
+ break;
+ case 't':
+ uid2 = stoi(optarg);
+ break;
+ case 'p':
+ password1 = optarg;
+ break;
+ case 'r':
+ password2 = optarg;
+ break;
+ case 'o':
+ owner = optarg; // I cannot pass optarg to lambda because it's pointer
+ filters.push_back([=](DB::Row &row) {row.ownerLabel = owner; return true;});
+ break;
+ case 'h':
+ printUsage();
+ return 0;
+ case '?':
+ case ':':
+ default:
+ printUsage();
+ return 1;
+ }
+ }
+
+ if (uid1 == uid2) {
+ cerr << "Source database and target database must be different!" << endl;
+ return 1;
+ }
+
+ return mergeDatabase(uid1, password1, uid2, password2, filters);
+ } catch (const CKM::DB::SqlConnection::Exception::InvalidColumn &e) {
+ cerr << "Invalid Column exception was catched. Probably migration failed. " << e.DumpToString() << endl;
+ } catch (const invalid_argument &e) {
+ cerr << "Argument could not be converted" << endl;
+ } catch (const out_of_range &e) {
+ cerr << "Out of range" << endl;
+ } catch (const exception &e) {
+ cerr << "Unexpected error: " << e.what() << endl;
+ } catch (...) {
+ cerr << "Unknown exception" << endl;
+ }
+
+ return 1;
+}
diff --git a/tools/ckm_db_tool/ckm_db_tool.cpp b/tools/ckm_db_tool/ckm_db_tool.cpp
index 672cd86d..2435ee33 100644
--- a/tools/ckm_db_tool/ckm_db_tool.cpp
+++ b/tools/ckm_db_tool/ckm_db_tool.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,147 +23,29 @@
#include <sstream>
#include <exception>
-#include <ckm-logic-ext.h>
+#include <getopt.h>
+#include <unistd.h>
-#include <ckm/ckm-type.h>
-#include <ckm/ckm-error.h>
-#include <message-buffer.h>
-#include <dpl/db/sql_connection.h>
-#include <exception.h>
+#include <db-wrapper.h>
using namespace std;
using namespace CKM;
-namespace {
-const size_t MAX_LEN = 32;
-const char ELLIPSIS[] = "...";
-const size_t ELLIPSIS_LEN = sizeof(ELLIPSIS) / sizeof(ELLIPSIS[0]);
-
-const char *const SQL_TABLES = "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";
-
-const char *const SQL_SCHEMA = "SELECT sql FROM "
- "(SELECT * FROM sqlcipher_master "
- "UNION ALL "
- "SELECT * FROM sqlcipher_temp_master) "
- "WHERE type!='meta' AND sql!='NULL'"
- "ORDER BY tbl_name, type DESC, name";
-} // namespace anonymous
-
-class DbWrapper {
-public:
- DbWrapper(uid_t uid, Password pw) : m_uid(uid), m_pw(pw) {}
-
- int unlock();
- void lock();
- void process(const string &cmd);
-
-private:
- void displayRow(const DB::SqlConnection::Output::Row &row, bool trim);
-
- uid_t m_uid;
- Password m_pw;
- CKMLogicExt m_logic;
-};
-
-int DbWrapper::unlock()
-{
- // no unlock for system db
- if (m_uid < 5000)
- return CKM_API_SUCCESS;
-
- int retCode;
- RawBuffer ret = m_logic.unlockUserKey(m_uid, m_pw);
- MessageBuffer buff;
- buff.Push(ret);
- buff.Deserialize(retCode);
- return retCode;
-}
-
-void DbWrapper::lock()
-{
- // no lock for system db
- if (m_uid < 5000)
- return;
-
- m_logic.lockUserKey(m_uid);
-}
-
-void DbWrapper::process(const string &acmd)
-{
- try {
- string cmd = acmd;
- bool trim = true;
-
- if (acmd == ".tables") {
- cmd = SQL_TABLES;
- trim = false;
- } else if (acmd == ".schema") {
- cmd = SQL_SCHEMA;
- trim = false;
- }
-
- DB::SqlConnection::Output output = m_logic.Execute(m_uid, cmd);
-
- if (output.GetNames().empty())
- return;
-
- displayRow(output.GetNames(), trim);
- cout << "--------------------------" << endl;
-
- for (const auto &row : output.GetValues()) {
- displayRow(row, trim);
- }
- } catch (const DB::SqlConnection::Exception::Base &e) {
- cerr << e.GetMessage() << endl;
- } catch (const Exc::Exception &e) {
- cerr << e.message() << endl;
- } catch (const std::exception &e) {
- cerr << e.what() << endl;
- } catch (...) {
- cerr << "Unexpected exception occurred" << endl;
- }
-}
-
-void DbWrapper::displayRow(const DB::SqlConnection::Output::Row &row, bool trim)
-{
- for (auto it = row.begin(); it != row.end(); it++) {
- std::string col = *it;
-
- if (trim && col.size() > MAX_LEN) {
- col.resize(MAX_LEN);
- col.replace(MAX_LEN - ELLIPSIS_LEN, ELLIPSIS_LEN, ELLIPSIS);
- }
-
- cout << col;
-
- if (it + 1 != row.end())
- cout << "|";
- }
-
- cout << endl;
-}
-
void usage()
{
- cout << "ckm_db_tool - the command line tool for accessing key-manager encrypted databases."
- << endl;
- cout << endl;
- cout << "Usage: ckm_db_tool uid [password] [sql_command]" << endl;
- cout << endl;
- cout << "uid (mandatory) User id as in <TZ_SYS_DATA>/ckm/db-<uid>" <<
- endl;
- cout << "password (optional) Password used for database encryption. For system database (uid < 5000) no password should be used."
- << endl;
- cout << "sql_command (optional) Sqlite3 command to execute on database. If empty the tool will enter interactive mode."
- << endl;
- cout << endl;
- cout << "Example:" << endl;
- cout << "cmd_db_tool 5000 user-pass \"select * from names\"" << endl;
+ cout << "Usage: ckm_db_tool [OPTION]\n";
+ cout << "The command line tool for accessing key-manager encrypted databases.\n";
+ cout << "Options:\n";
+ cout << " -u, --uid UID User id as in <TZ_SYS_DATA>/ckm/db-<uid> - default value 0\n";
+ cout << " -p, --pass PASSWORD Password used for database encryption. For system database (uid < 5000) no password should be used.\n";
+ cout << " -c, --cmd SQLCOMMAND Sqlite3 command to execute on database. If command not provided tool will enter interactive mode.\n";
+ cout << " -h, --help Shows this help.\n";
+ cout << "Example: Open database for user 5000 and select all data from table names\n";
+ cout << " cmd_db_tool -u 5000 -p P45W0RD \"select * from names\"\n";
+ cout << "Example: Open database for user 5001 in interactive mode\n";
+ cout << " cmd_db_tool -uid 5001 -p user-strong-password\n";
+ cout << "Example: Open database for user 0 in interactive mode\n";
+ cout << " cmd_db_tool" << endl;
}
void internalHelp()
@@ -179,43 +61,49 @@ void internalHelp()
int main(int argc, char *argv[])
{
try {
- if (argc < 2 || !argv[1]) {
- usage();
- return -1;
- }
-
- // read uid
- stringstream ss(argv[1]);
- uid_t uid;
+ uid_t uid = 0;
+ Password pass;
+ std::string argcmd;
+ while(1) {
+ int option_index = 0;
- if (!(ss >> uid)) {
- usage();
- return -1;
- }
+ static struct option long_options[] = {
+ {"uid", required_argument, 0, 'u'},
+ {"cmd", required_argument, 0, 'c'},
+ {"pass", required_argument, 0, 'p'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0 }
+ };
- int idx = 2;
+ int c = getopt_long(argc, argv, "u:c:p:h", long_options, &option_index);
- // read password
- Password pass;
+ if (-1 == c)
+ break;
- if (uid >= 5000) {
- if (argc > idx) {
- pass = argv[idx];
- idx++;
+ switch (c) {
+ default:
+ case ':':
+ case '?':
+ case 'h':
+ usage();
+ return 0;
+ case 'u':
+ uid = std::stoi(optarg);
+ break;
+ case 'c':
+ argcmd = optarg;
+ break;
+ case 'p':
+ pass = optarg;
+ break;
}
}
- // read sqlite3 command
- string argcmd;
-
- if (argc > idx)
- argcmd = argv[idx];
-
// unlock db
DbWrapper dbw(uid, pass);
- int retCode = dbw.unlock();
+ int retCode;
- if (retCode != CKM_API_SUCCESS) {
+ if (CKM_API_SUCCESS != (retCode = dbw.unlock())) {
cerr << "Unlocking database failed: " << retCode << endl;
return -1;
}
@@ -254,8 +142,15 @@ int main(int argc, char *argv[])
cout << "Database locked" << endl;
return 0;
+ } catch (const std::invalid_argument &e) {
+ cerr << "Argument could not be converted" << endl;
+ } catch (const std::out_of_range &e) {
+ cerr << "Out of range" << endl;
+ } catch (const std::exception &e) {
+ cerr << "Exception: " << e.what() << endl;
} catch (...) {
cerr << "Unexpected exception occurred" << endl;
- return -1;
}
+ return -1;
}
+
diff --git a/tools/ckm_db_tool/db-crypto-ext.cpp b/tools/ckm_db_tool/db-crypto-ext.cpp
index 26671451..90d5a4f6 100644
--- a/tools/ckm_db_tool/db-crypto-ext.cpp
+++ b/tools/ckm_db_tool/db-crypto-ext.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,9 @@
namespace CKM {
namespace DB {
+const char *DB_CMD_OBJECT_SELECT =
+ "SELECT * FROM [join_name_object_tables];";
+
SqlConnection::Output CryptoExt::Execute(const std::string &cmd)
{
SqlConnection::Output out;
@@ -38,5 +41,30 @@ SqlConnection::Output CryptoExt::Execute(const std::string &cmd)
m_connection->ExecCommand(&out, "%s", cmd.c_str());
return out;
}
+
+RowVector CryptoExt::getRows()
+{
+ try {
+ RowVector output;
+ SqlConnection::DataCommandUniquePtr selectCommand =
+ m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT);
+
+ while (selectCommand->Step()) {
+ // extract data
+ output.push_back(getRow(selectCommand));
+ }
+
+ return output;
+ } catch (const SqlConnection::Exception::InvalidColumn &) {
+ LogError("Select statement invalid column error");
+ } catch (const SqlConnection::Exception::SyntaxError &) {
+ LogError("Couldn't prepare select statement");
+ } catch (const SqlConnection::Exception::InternalError &) {
+ LogError("Couldn't execute select statement");
+ }
+
+ ThrowErr(Exc::DatabaseFailed, "Couldn't get row from database");
+}
+
} // namespace DB
} // namespace CKM
diff --git a/tools/ckm_db_tool/db-crypto-ext.h b/tools/ckm_db_tool/db-crypto-ext.h
index 5991af18..bb1eb357 100644
--- a/tools/ckm_db_tool/db-crypto-ext.h
+++ b/tools/ckm_db_tool/db-crypto-ext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@ struct CryptoExt : public Crypto {
CryptoExt(Crypto orig) : Crypto(std::move(orig)) {}
SqlConnection::Output Execute(const std::string &cmd);
+ RowVector getRows();
};
} // namespace DB
diff --git a/tools/ckm_db_tool/db-wrapper.cpp b/tools/ckm_db_tool/db-wrapper.cpp
new file mode 100644
index 00000000..e7027dbd
--- /dev/null
+++ b/tools/ckm_db_tool/db-wrapper.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file db-wrapper.cpp
+ * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ */
+#include <string>
+
+#include <db-wrapper.h>
+
+namespace {
+
+const size_t MAX_LEN = 32;
+const char ELLIPSIS[] = "...";
+const size_t ELLIPSIS_LEN = sizeof(ELLIPSIS) / sizeof(ELLIPSIS[0]);
+
+
+const char *const SQL_TABLES = "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";
+
+const char *const SQL_SCHEMA = "SELECT sql FROM "
+ "(SELECT * FROM sqlcipher_master "
+ "UNION ALL "
+ "SELECT * FROM sqlcipher_temp_master) "
+ "WHERE type!='meta' AND sql!='NULL'"
+ "ORDER BY tbl_name, type DESC, name";
+} // anonymous namespace
+
+namespace CKM {
+
+int DbWrapper::unlock()
+{
+ // no unlock for system db
+ if (m_uid == 0 && m_pw.empty())
+ return m_logic.unlockSystemDB();
+
+ int retCode;
+ RawBuffer ret = m_logic.unlockUserKey(m_uid, m_pw);
+ MessageBuffer buff;
+ buff.Push(ret);
+ buff.Deserialize(retCode);
+ return retCode;
+}
+
+void DbWrapper::lock()
+{
+ // no lock for system db
+ if (m_uid < 5000)
+ return;
+
+ m_logic.lockUserKey(m_uid);
+}
+
+void DbWrapper::process(const std::string &acmd)
+{
+ try {
+ std::string cmd = acmd;
+ bool trim = true;
+
+ if (acmd == ".tables") {
+ cmd = SQL_TABLES;
+ trim = false;
+ } else if (acmd == ".schema") {
+ cmd = SQL_SCHEMA;
+ trim = false;
+ }
+
+ DB::SqlConnection::Output output = m_logic.Execute(m_uid, cmd);
+
+ if (output.GetNames().empty())
+ return;
+
+ displayRow(output.GetNames(), trim);
+ std::cout << "--------------------------" << std::endl;
+
+ for (const auto &row : output.GetValues()) {
+ displayRow(row, trim);
+ }
+ } catch (const DB::SqlConnection::Exception::Base &e) {
+ std::cerr << e.GetMessage() << std::endl;
+ } catch (const Exc::Exception &e) {
+ std::cerr << e.message() << std::endl;
+ } catch (const std::exception &e) {
+ std::cerr << e.what() << std::endl;
+ } catch (...) {
+ std::cerr << "Unexpected exception occurred" << std::endl;
+ }
+}
+
+void DbWrapper::displayRow(const DB::SqlConnection::Output::Row &row, bool trim)
+{
+ for (auto it = row.begin(); it != row.end(); it++) {
+ std::string col = *it;
+
+ if (trim && col.size() > MAX_LEN) {
+ col.resize(MAX_LEN);
+ col.replace(MAX_LEN - ELLIPSIS_LEN, ELLIPSIS_LEN, ELLIPSIS);
+ }
+
+ std::cout << col;
+
+ if (it + 1 != row.end())
+ std::cout << "|";
+ }
+
+ std::cout << std::endl;
+}
+
+DB::RowVector DbWrapper::getRows()
+{
+ return m_logic.getRows(m_uid);
+}
+
+void DbWrapper::saveRow(const DB::Row &row)
+{
+ return m_logic.saveRow(m_uid, row);
+}
+
+} // namespace CKM
diff --git a/tools/ckm_db_tool/db-wrapper.h b/tools/ckm_db_tool/db-wrapper.h
new file mode 100644
index 00000000..2fa66534
--- /dev/null
+++ b/tools/ckm_db_tool/db-wrapper.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file db-wrapper.h
+ * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
+ * @version 1.0
+ */
+#pragma once
+
+#include <string>
+
+#include <ckm/ckm-type.h>
+#include <ckm/ckm-error.h>
+#include <message-buffer.h>
+#include <dpl/db/sql_connection.h>
+#include <ckm-logic-ext.h>
+
+#include <exception.h>
+
+namespace CKM {
+
+class DbWrapper {
+public:
+ DbWrapper(uid_t uid, Password pw) : m_uid(uid), m_pw(pw) {}
+
+ int unlock();
+ void lock();
+ void process(const std::string &cmd);
+ DB::RowVector getRows();
+ void saveRow(const DB::Row &row);
+
+private:
+ void displayRow(const DB::SqlConnection::Output::Row &row, bool trim);
+
+ uid_t m_uid;
+ Password m_pw;
+ CKMLogicExt m_logic;
+};
+
+} // namespace CKM
+