diff options
author | Bartlomiej Grzelewski <b.grzelewski@samsung.com> | 2017-08-02 14:21:44 +0200 |
---|---|---|
committer | Krzysztof Jackiewicz <k.jackiewicz@samsung.com> | 2018-08-06 08:33:28 +0000 |
commit | 3f269161226259db05411999e54b6f3ea33bda53 (patch) | |
tree | a4012523c06d508614247188f162fd1fbf220265 | |
parent | ac4e965a376dfdd05fcc4cc1661f74bffac2aea4 (diff) | |
download | key-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.spec | 1 | ||||
-rw-r--r-- | src/manager/service/db-crypto.h | 6 | ||||
-rw-r--r-- | tools/ckm_db_tool/CMakeLists.txt | 23 | ||||
-rw-r--r-- | tools/ckm_db_tool/ckm-logic-ext.cpp | 32 | ||||
-rw-r--r-- | tools/ckm_db_tool/ckm-logic-ext.h | 4 | ||||
-rw-r--r-- | tools/ckm_db_tool/ckm_db_merge.cpp | 193 | ||||
-rw-r--r-- | tools/ckm_db_tool/ckm_db_tool.cpp | 221 | ||||
-rw-r--r-- | tools/ckm_db_tool/db-crypto-ext.cpp | 30 | ||||
-rw-r--r-- | tools/ckm_db_tool/db-crypto-ext.h | 3 | ||||
-rw-r--r-- | tools/ckm_db_tool/db-wrapper.cpp | 138 | ||||
-rw-r--r-- | tools/ckm_db_tool/db-wrapper.h | 55 |
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 + |