Add a tool for accessing encrypted database 51/47251/5
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 1 Sep 2015 11:05:10 +0000 (13:05 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 3 Sep 2015 13:07:16 +0000 (15:07 +0200)
[Problem] No way of debugging an encrypted database
[Solution] Tool added

[Verification] Run:
ckm_db_tool
ckm_db_tool 0
ckm_db_tool 0 <sql_command>
ckm_db_tool <uid> <password>
    > .tables
    > .schema
    > <sql_command>
    > help
    > exit
ckm_db_tool <uid> <password> <sql_command>

Change-Id: I87662831808b0397b01db1e54c38b4dc4ad69129

12 files changed:
packaging/key-manager.spec
src/manager/dpl/db/include/dpl/db/sql_connection.h
src/manager/dpl/db/src/sql_connection.cpp
src/manager/service/ckm-logic.h
src/manager/service/db-crypto.h
tools/CMakeLists.txt
tools/ckm_db_tool/CMakeLists.txt [new file with mode: 0644]
tools/ckm_db_tool/ckm-logic-ext.cpp [new file with mode: 0644]
tools/ckm_db_tool/ckm-logic-ext.h [new file with mode: 0644]
tools/ckm_db_tool/ckm_db_tool.cpp [new file with mode: 0644]
tools/ckm_db_tool/db-crypto-ext.cpp [new file with mode: 0644]
tools/ckm_db_tool/db-crypto-ext.h [new file with mode: 0644]

index d39cdbd..fb90bc0 100644 (file)
@@ -289,6 +289,7 @@ fi
 %{_datadir}/ckm-db-test/XML_1_wrong.xsd
 %{_datadir}/ckm-db-test/XML_2_structure.xml
 %{_bindir}/ckm_so_loader
+%{_bindir}/ckm_db_tool
 
 %files -n key-manager-pam-plugin
 %defattr(-,root,root,-)
index 4492dec..6b89a16 100644 (file)
@@ -55,6 +55,24 @@ class SqlConnection
         DECLARE_EXCEPTION_TYPE(Base, InvalidArguments)
     };
 
+    /**
+     * Output of SQL command
+     */
+    class Output {
+    public:
+        typedef std::vector<std::string> Row;
+        typedef std::vector<Row> Rows;
+
+        static int Callback(void*,int,char**,char**);
+        const Row& GetNames() const { return m_names; }
+        const Rows& GetValues() const { return m_values; }
+    private:
+        void SetResults(int columns, char** values, char** names);
+
+        Row m_names;
+        Rows m_values;
+    };
+
     typedef int ColumnIndex;
     typedef int ArgumentIndex;
 
@@ -502,6 +520,17 @@ class SqlConnection
     void ExecCommand(const char *format, ...);
 
     /**
+     * Execute SQL command without result
+     *
+     * @param output  The output of SQL command will be stored in this object
+     *                if it's no NULL.
+     * @param format
+     * @param ...
+     */
+    //To prevent sql injection do not use this method for direct sql execution
+    void ExecCommand(Output* output, const char *format, ...);
+
+    /**
      * Execute BEGIN; command to start new transaction
      *
      */
@@ -541,6 +570,9 @@ class SqlConnection
      * @return Row ID
      */
     RowID GetLastInsertRowID() const;
+
+  private:
+    void ExecCommandHelper(Output* out, const char *format, va_list args);
 };
 } // namespace DB
 } // namespace CKM
index 110eca0..29b684e 100644 (file)
 
 namespace {
 const int MAX_RETRY = 10;
+
+struct ScopedVaList {
+    ~ScopedVaList() { va_end(args); }
+    va_list args;
+};
+
+#define scoped_va_start(name, param) ScopedVaList name; va_start(name.args, param);
 }
 
 namespace CKM {
@@ -841,7 +848,26 @@ SqlConnection::~SqlConnection()
     }
 }
 
-void SqlConnection::ExecCommand(const char *format, ...)
+int SqlConnection::Output::Callback(void* param, int columns, char** values, char** names)
+{
+    if(param)
+        static_cast<Output*>(param)->SetResults(columns, values, names);
+    return 0;
+}
+
+void SqlConnection::Output::SetResults(int columns, char** values, char** names)
+{
+    if (m_names.empty()) {
+        for (int i=0;i<columns;i++)
+            m_names.push_back(names[i] ? names[i] : "NULL");
+    }
+    Row row;
+    for (int i=0;i<columns;i++)
+        row.push_back(values[i] ? values[i] : "NULL");
+    m_values.push_back(std::move(row));
+}
+
+void SqlConnection::ExecCommandHelper(Output* out, const char* format, va_list args)
 {
     if (m_connection == NULL) {
         LogError("Cannot execute command. Not connected to DB!");
@@ -853,37 +879,27 @@ void SqlConnection::ExecCommand(const char *format, ...)
         ThrowMsg(Exception::SyntaxError, "Null statement");
     }
 
-    char *rawBuffer;
-
-    va_list args;
-    va_start(args, format);
-
-    if (vasprintf(&rawBuffer, format, args) == -1) {
-        rawBuffer = NULL;
-    }
-
-    va_end(args);
+    char *query;
 
-    CharUniquePtr buffer(rawBuffer);
-
-    if (!buffer) {
+    if (vasprintf(&query, format, args) == -1) {
         LogError("Failed to allocate statement string");
         return;
     }
 
-    LogPedantic("Executing SQL command: " << buffer.get());
+    CharUniquePtr queryPtr(query);
+
+    LogPedantic("Executing SQL command: " << queryPtr.get());
 
     // Notify all after potentially synchronized database connection access
     ScopedNotifyAll notifyAll(m_synchronizationObject.get());
 
     for (int i = 0; i < MAX_RETRY; i++) {
         char *errorBuffer;
-
         int ret = sqlcipher3_exec(m_connection,
-                               buffer.get(),
-                               NULL,
-                               NULL,
-                               &errorBuffer);
+                                  queryPtr.get(),
+                                  out ? &Output::Callback : NULL,
+                                  out,
+                                  &errorBuffer);
 
         std::string errorMsg;
 
@@ -919,6 +935,20 @@ void SqlConnection::ExecCommand(const char *format, ...)
     ThrowMsg(Exception::InternalError, "sqlite permanently busy");
 }
 
+void SqlConnection::ExecCommand(Output* out, const char *format, ...)
+{
+    scoped_va_start(svl, format);
+
+    ExecCommandHelper(out, format, svl.args);
+}
+
+void SqlConnection::ExecCommand(const char *format, ...)
+{
+    scoped_va_start(svl, format);
+
+    ExecCommandHelper(NULL, format, svl.args);
+}
+
 SqlConnection::DataCommandUniquePtr SqlConnection::PrepareDataCommand(
     const char *format,
     ...)
index c73fc74..336b346 100644 (file)
@@ -208,6 +208,9 @@ public:
                          const Password& pass,
                          Crypto::GKeyShPtr& key);
 
+protected:
+    int unlockSystemDB();
+
 private:
 
     // select private/system database depending on asking uid and owner label.
@@ -215,7 +218,6 @@ private:
     UserData & selectDatabase(const Credentials &incoming_cred,
                               const Label       &incoming_label);
 
-    int unlockSystemDB();
     int unlockDatabase(uid_t            user,
                        const Password & password);
 
@@ -380,10 +382,12 @@ private:
 
     int loadAppKey(UserData& handle, const Label& appLabel);
 
-    std::map<uid_t, UserData> m_userDataMap;
     AccessControl m_accessControl;
     Crypto::Decider m_decider;
     //FileLock m_lock;
+
+protected:
+    std::map<uid_t, UserData> m_userDataMap;
 };
 
 } // namespace CKM
index 193570d..fca997c 100644 (file)
@@ -210,8 +210,9 @@ namespace DB {
                 bool m_inTransaction;
             };
 
-         private:
+         protected:
             SqlConnection* m_connection;
+         private:
             bool m_inUserTransaction;
 
             void resetDB();
index f1df926..8764fad 100644 (file)
@@ -46,3 +46,4 @@ INSTALL(TARGETS ${CKM_TOOL}
                 WORLD_EXECUTE
      )
 
+ADD_SUBDIRECTORY(ckm_db_tool)
\ No newline at end of file
diff --git a/tools/ckm_db_tool/CMakeLists.txt b/tools/ckm_db_tool/CMakeLists.txt
new file mode 100644 (file)
index 0000000..065fafe
--- /dev/null
@@ -0,0 +1,92 @@
+SET(CKM_DB_TOOL "ckm_db_tool")
+SET(KEY_MANAGER_PATH ${PROJECT_SOURCE_DIR}/src/manager)
+
+PKG_CHECK_MODULES(CKM_DB_TOOL_DEP
+    REQUIRED
+    openssl
+    libsmack
+    libcrypto
+    capi-base-common
+    capi-system-info
+    vconf
+    libxml-2.0
+    )
+
+FIND_PACKAGE(Threads REQUIRED)
+
+INCLUDE_DIRECTORIES(
+    ${CKM_DB_TOOL_DEP_INCLUDE_DIRS}
+    ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/
+    ${KEY_MANAGER_PATH}/main
+    ${KEY_MANAGER_PATH}/common
+    ${KEY_MANAGER_PATH}/service
+    ${KEY_MANAGER_PATH}/initial-values
+    ${KEY_MANAGER_PATH}/sqlcipher
+    ${KEY_MANAGER_PATH}/dpl/core/include
+    ${KEY_MANAGER_PATH}/dpl/log/include
+    ${KEY_MANAGER_PATH}/dpl/db/include
+    ${KEY_MANAGER_PATH}/crypto
+    )
+
+SET(CKM_DB_TOOL_SOURCES
+    ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm_db_tool.cpp
+    ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/db-crypto-ext.cpp
+    ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm-logic-ext.cpp
+
+    ${KEY_MANAGER_PATH}/main/generic-socket-manager.cpp
+    ${KEY_MANAGER_PATH}/main/socket-manager.cpp
+    ${KEY_MANAGER_PATH}/main/smack-check.cpp
+    ${KEY_MANAGER_PATH}/main/thread-service.cpp
+    ${KEY_MANAGER_PATH}/main/socket-2-id.cpp
+    ${KEY_MANAGER_PATH}/service/certificate-store.cpp
+    ${KEY_MANAGER_PATH}/service/certificate-config.cpp
+    ${KEY_MANAGER_PATH}/service/digest.cpp
+    ${KEY_MANAGER_PATH}/service/file-lock.cpp
+    ${KEY_MANAGER_PATH}/service/access-control.cpp
+    ${KEY_MANAGER_PATH}/service/ckm-logic.cpp
+    ${KEY_MANAGER_PATH}/service/key-provider.cpp
+    ${KEY_MANAGER_PATH}/service/crypto-logic.cpp
+    ${KEY_MANAGER_PATH}/service/db-crypto.cpp
+    ${KEY_MANAGER_PATH}/service/file-system.cpp
+    ${KEY_MANAGER_PATH}/initial-values/parser.cpp
+    ${KEY_MANAGER_PATH}/initial-values/BufferHandler.cpp
+    ${KEY_MANAGER_PATH}/initial-values/CertHandler.cpp
+    ${KEY_MANAGER_PATH}/initial-values/DataHandler.cpp
+    ${KEY_MANAGER_PATH}/initial-values/KeyHandler.cpp
+    ${KEY_MANAGER_PATH}/initial-values/PermissionHandler.cpp
+    ${KEY_MANAGER_PATH}/initial-values/InitialValueHandler.cpp
+    ${KEY_MANAGER_PATH}/initial-values/InitialValuesFile.cpp
+    ${KEY_MANAGER_PATH}/initial-values/xml-utils.cpp
+    ${KEY_MANAGER_PATH}/dpl/core/src/assert.cpp
+    ${KEY_MANAGER_PATH}/dpl/db/src/sql_connection.cpp
+    ${KEY_MANAGER_PATH}/dpl/db/src/naive_synchronization_object.cpp
+    ${KEY_MANAGER_PATH}/sqlcipher/sqlcipher.c
+    ${KEY_MANAGER_PATH}/crypto/sw-backend/key.cpp
+    ${KEY_MANAGER_PATH}/crypto/sw-backend/internals.cpp
+    ${KEY_MANAGER_PATH}/crypto/sw-backend/store.cpp
+    ${KEY_MANAGER_PATH}/crypto/platform/decider.cpp
+    ${KEY_MANAGER_PATH}/crypto/tz-backend/store.cpp
+    ${KEY_MANAGER_PATH}/main/socket-2-id-mockup.cpp
+    )
+
+ADD_EXECUTABLE( ${CKM_DB_TOOL} ${CKM_DB_TOOL_SOURCES} )
+
+TARGET_LINK_LIBRARIES(${CKM_DB_TOOL}
+    ${CMAKE_THREAD_LIBS_INIT}
+    ${CKM_DB_TOOL_DEP_LIBRARIES}
+    ${TARGET_KEY_MANAGER_COMMON}
+    -ldl
+    )
+
+#place for output file
+INSTALL(TARGETS ${CKM_DB_TOOL}
+    DESTINATION /usr/bin
+    PERMISSIONS OWNER_READ
+                OWNER_WRITE
+                OWNER_EXECUTE
+                GROUP_READ
+                GROUP_EXECUTE
+                WORLD_READ
+                WORLD_EXECUTE
+     )
+
diff --git a/tools/ckm_db_tool/ckm-logic-ext.cpp b/tools/ckm_db_tool/ckm-logic-ext.cpp
new file mode 100644 (file)
index 0000000..020c579
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2000 - 2015 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-logic-ext.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <ckm-logic-ext.h>
+#include <db-crypto-ext.h>
+
+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.
+     * That's why we need a derived class DB::CryptoExt. m_userDataMap must be left unchanged after
+     * this operation but DB::Crypto can't be copied. According to C++ standard static casting
+     * DB::Crypto pointer to DB::CryptoExt pointer is UB. Therefore DB::Crypto is temporarily moved
+     * into DB::CryptoExt and moved back to m_userDataMap after the call to Execute().
+     */
+    DB::CryptoExt db(std::move(m_userDataMap[user].database));
+    try {
+        output = db.Execute(cmd);
+        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;
+    }
+}
+
+} // namespace CKM
+
+
diff --git a/tools/ckm_db_tool/ckm-logic-ext.h b/tools/ckm_db_tool/ckm-logic-ext.h
new file mode 100644 (file)
index 0000000..515c41c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (c) 2000 - 2015 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-logic-ext.h
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#pragma once
+
+#include <string>
+#include <ckm-logic.h>
+#include <dpl/db/sql_connection.h>
+
+namespace CKM {
+struct CKMLogicExt : public CKMLogic {
+    CKMLogicExt() : m_systemDbUnlocked(false) {}
+
+    DB::SqlConnection::Output Execute(uid_t user, const std::string& cmd);
+
+private:
+    bool m_systemDbUnlocked;
+};
+} // namespace CKM
diff --git a/tools/ckm_db_tool/ckm_db_tool.cpp b/tools/ckm_db_tool/ckm_db_tool.cpp
new file mode 100644 (file)
index 0000000..2ef8fdf
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ *  Copyright (c) 2000 - 2015 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_tool.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <iostream>
+#include <sstream>
+#include <exception>
+
+#include <ckm-logic-ext.h>
+
+#include <ckm/ckm-type.h>
+#include <ckm/ckm-error.h>
+#include <message-buffer.h>
+#include <dpl/db/sql_connection.h>
+#include <exception.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) {
+        cout << e.GetMessage() << endl;
+    } catch (const Exc::Exception &e) {
+        cout << e.message() << endl;
+    } catch (const std::exception &e) {
+        cout << e.what() << endl;
+    } catch (...) {
+        cout << "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 /opt/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;
+}
+
+void internalHelp() {
+    cout << "[sqlite_command]  executes sqlite command on database" << endl;
+    cout << ".tables           shows a list of table names" << endl;
+    cout << ".schema           shows Sqlite3 command used to create tables in the database" << endl;
+    cout << "help              shows this help" << endl;
+    cout << "exit (Ctrl-D)     quits the program" << endl;
+}
+
+int main(int argc, char* argv[])
+{
+    if(argc < 2 || !argv[1]) {
+        usage();
+        return -1;
+    }
+
+    // read uid
+    stringstream ss(argv[1]);
+    uid_t uid;
+    if(!(ss >> uid)) {
+        usage();
+        return -1;
+    }
+
+    int idx = 2;
+
+    // read password
+    Password pass;
+    if(uid >= 5000) {
+        if(argc > idx) {
+            pass = argv[idx];
+            idx++;
+        }
+    }
+
+    // read sqlite3 command
+    string argcmd;
+    if(argc > idx)
+        argcmd = argv[idx];
+
+    // unlock db
+    DbWrapper dbw(uid, pass);
+    int retCode = dbw.unlock();
+    if (retCode != CKM_API_SUCCESS ) {
+        cout << "Unlocking database failed: " << retCode << endl;
+        return -1;
+    }
+    cout << "Database unlocked" << endl;
+
+    for(;;) {
+        string cmd;
+        if (argcmd.empty()) {
+            cout << "> ";
+            if(!getline(cin, cmd)) {
+                cout << "exit" << endl;
+                break; // EOF
+            }
+        } else {
+            cmd = argcmd;
+        }
+
+        if(cmd == "exit")
+            break;
+        if(cmd == "help") {
+            internalHelp();
+            continue;
+        }
+
+        dbw.process(cmd);
+
+        if(!argcmd.empty())
+            break;
+    }
+    dbw.lock();
+    cout << "Database locked" << endl;
+
+    return 0;
+}
diff --git a/tools/ckm_db_tool/db-crypto-ext.cpp b/tools/ckm_db_tool/db-crypto-ext.cpp
new file mode 100644 (file)
index 0000000..92518ac
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 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-crypto-ext.cpp
+ * @author      Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version     1.0
+ * @brief       Limited implementation of encrypted db access layer
+ */
+
+#include <db-crypto-ext.h>
+#include <dpl/exception.h>
+
+namespace CKM {
+namespace DB {
+
+SqlConnection::Output CryptoExt::Execute(const std::string& cmd) {
+    SqlConnection::Output out;
+    if(!m_connection) {
+        ThrowMsg(SqlConnection::Exception::ConnectionBroken, "Not connected to database");
+    }
+    m_connection->ExecCommand(&out, "%s", cmd.c_str());
+    return out;
+}
+} // namespace DB
+} // namespace CKM
diff --git a/tools/ckm_db_tool/db-crypto-ext.h b/tools/ckm_db_tool/db-crypto-ext.h
new file mode 100644 (file)
index 0000000..c4baeaf
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 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-crypto-ext.h
+ * @author      Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version     1.0
+ * @brief       Header of encrypted db access layer
+ */
+
+#pragma once
+
+#include <db-crypto.h>
+#include <string>
+#include <utility>
+#include <dpl/db/sql_connection.h>
+
+namespace CKM {
+namespace DB {
+struct CryptoExt : public Crypto {
+    CryptoExt(Crypto orig) : Crypto(std::move(orig)) {}
+
+    SqlConnection::Output Execute(const std::string& cmd);
+};
+
+} // namespace DB
+} // namespace CKM
+