Privilege database access implementation 85/23385/4
authorKrzysztof Sasiak <k.sasiak@samsung.com>
Fri, 6 Jun 2014 14:11:08 +0000 (16:11 +0200)
committerKrzysztof Sasiak <k.sasiak@samsung.com>
Fri, 27 Jun 2014 20:38:10 +0000 (22:38 +0200)
Adding convenience methods for accessing privilege
database and performing queries on it.

Change-Id: I34d8986ec1315ce46f7f5bc462d746df81e7e432
Signed-off-by: Krzysztof Sasiak <k.sasiak@samsung.com>
src/server/CMakeLists.txt
src/server/db/include/privilege_db.h [new file with mode: 0644]
src/server/db/privilege_db.cpp [new file with mode: 0644]

index cb6ffd2..5d7db00 100644 (file)
@@ -24,6 +24,7 @@ INCLUDE_DIRECTORIES(
     ${SERVER_PATH}/include
     ${SERVER_PATH}/main/include
     ${SERVER_PATH}/service/include
+    ${SERVER_PATH}/db/include
     ${DPL_PATH}/core/include
     ${DPL_PATH}/log/include
     ${DPL_PATH}/db/include
@@ -38,6 +39,7 @@ SET(SERVER_SOURCES
     ${SERVER_PATH}/service/smack-common.cpp
     ${SERVER_PATH}/service/smack-rules.cpp
     ${SERVER_PATH}/service/installer.cpp
+    ${SERVER_PATH}/db/privilege_db.cpp
     ${DPL_PATH}/core/src/errno_string.cpp
     ${DPL_PATH}/core/src/string.cpp
     ${DPL_PATH}/db/src/naive_synchronization_object.cpp
diff --git a/src/server/db/include/privilege_db.h b/src/server/db/include/privilege_db.h
new file mode 100644 (file)
index 0000000..94f41f7
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * security-manager, database access
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Rafal Krypa <r.krypa@samsung.com>
+ *
+ * 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        privilege_db.h
+ * @author      Krzysztof Sasiak <k.sasiak@samsung.com>
+ * @version     1.0
+ * @brief       This file contains declaration of the API to privilges database.
+ */
+
+#include <cstdio>
+#include <list>
+#include <map>
+#include <stdbool.h>
+#include <string>
+
+#include <dpl/db/sql_connection.h>
+
+#ifndef PRIVILEGE_DB_H_
+#define PRIVILEGE_DB_H_
+
+namespace SecurityManager {
+
+typedef std::vector<std::string> TPermissionsList;
+
+enum class QueryType {
+    EGetPkgPermissions,
+    EAddApplication,
+    ERemoveApplication,
+    EAddAppPermissions,
+    ERemoveAppPermissions,
+    EPkgIdExists,
+};
+
+class PrivilegeDb {
+    /**
+     * PrivilegeDb database class
+     */
+
+private:
+    SecurityManager::DB::SqlConnection *mSqlConnection;
+    const std::map<QueryType, const char * const > Queries = {
+        { QueryType::EGetPkgPermissions, "SELECT permission_name FROM app_permission_view WHERE pkg_name=?"},
+        { QueryType::EAddApplication, "INSERT INTO app_pkg_view (app_name, pkg_name) VALUES (?, ?)" },
+        { QueryType::ERemoveApplication, "DELETE FROM app_pkg_view WHERE app_name=? AND pkg_name=?" },
+        { QueryType::EAddAppPermissions, "INSERT INTO app_permission_view (app_name, pkg_name, permission_name) VALUES (?, ?, ?)" },
+        { QueryType::ERemoveAppPermissions, "DELETE FROM app_permission_view WHERE app_name=? AND pkg_name=? AND permission_name=?" },
+        { QueryType::EPkgIdExists, "SELECT * FROM pkg WHERE name=?" }
+    };
+
+    /**
+     * Check if pkgId is already registered in database
+     *
+     * @param pkgId - package identifier
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     * @return true if pkgId exists in the database
+     *
+     */
+    bool PkgIdExists(const std::string &pkgId);
+
+    /**
+     * Check if there's a tuple of (appId, packageId) inside the database
+     *
+     * @param appId - application identifier
+     * @param pkgId - package identifier
+     * @param[out] currentPermissions - list of current permissions assigned to tuple (appId, pkgId)
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     * @return true on success, false on failure
+     */
+    bool GetPkgPermissions(const std::string &pkgId,
+            TPermissionsList &currentPermission);
+
+public:
+    class Exception
+    {
+      public:
+        DECLARE_EXCEPTION_TYPE(SecurityManager::Exception, Base)
+        DECLARE_EXCEPTION_TYPE(Base, IOError)
+        DECLARE_EXCEPTION_TYPE(Base, InternalError)
+    };
+
+    /**
+     * Constructor
+     * @exception DB::SqlConnection::Exception::IOError on problems with database access
+     *
+     */
+    PrivilegeDb(const std::string &path);
+    ~PrivilegeDb(void);
+
+    /**
+     * Begin transaction
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     *
+     */
+    void BeginTransaction(void);
+
+    /**
+     * Commit transaction
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     *
+     */
+    void CommitTransaction(void);
+
+    /**
+     * Rollback transaction
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     *
+     */
+    void RollbackTransaction(void);
+
+    /**
+     * Add an application into the database
+     *
+     * @param appId - application identifier
+     * @param pkgId - package identifier
+     * @param[out] pkgIdIsNew - return info if pkgId is new to the database
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     * @return true on success, false on failure
+     */
+    bool AddApplication(const std::string &appId, const std::string &pkgId,
+            bool &pkgIdIsNew);
+
+    /**
+     * Remove an application from the database
+     *
+     * @param appId - application identifier
+     * @param pkgId - package identifier
+     * @param[out] pkgIdIsNoMore - return info if pkgId is in the database
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     * @return true on success, false on failure
+     */
+    bool RemoveApplication(const std::string &appId, const std::string &pkgId,
+            bool &pkgIdIsNoMore);
+
+    /**
+     * Update permissions belonging to tuple (appId, pkgId)
+     *
+     * @param appId - application identifier
+     * @param pkgId - package identifier
+     * @param permissions - list of permissions to assign
+     * @param[out] addedPermissions - return list of added permissions
+     * @param[out] removedPermissions - return list of removed permissions
+     * @exception DB::SqlConnection::Exception::InternalError on internal error
+     * @return - true on success, false on failure
+     */
+    bool UpdatePermissions(const std::string &appId,
+            const std::string &pkgId, const TPermissionsList &permissions,
+            TPermissionsList &addedPermissions,
+            TPermissionsList &removedPermissions);
+
+};
+}
+;
+//namespace SecurityManager
+
+#endif // PRIVILEGE_DB_H_
diff --git a/src/server/db/privilege_db.cpp b/src/server/db/privilege_db.cpp
new file mode 100644 (file)
index 0000000..2fcad74
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * security-manager, database access
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Rafal Krypa <r.krypa@samsung.com>
+ *
+ * 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        privilege_db.cpp
+ * @author      Krzysztof Sasiak <k.sasiak@samsung.com>
+ * @version     0.1
+ * @brief       This file contains declaration of the API to privileges database.
+ */
+
+#include <cstdio>
+#include <set>
+#include <list>
+#include <string>
+#include <iostream>
+
+#include <dpl/log/log.h>
+#include "privilege_db.h"
+
+#define SET_CONTAINS(set,value) set.find(value)!=set.end()
+#define CATCH_STANDARD_EXCEPTIONS  \
+    catch (DB::SqlConnection::Exception::SyntaxError &e) { \
+        LogDebug("Syntax error in command: " << e.DumpToString()); \
+        ThrowMsg(PrivilegeDb::Exception::InternalError, \
+            "Syntax error in command: " << e.DumpToString()); \
+    } catch (DB::SqlConnection::Exception::InternalError &e) { \
+        LogDebug("Mysterious internal error in SqlConnection class" << e.DumpToString()); \
+        ThrowMsg(PrivilegeDb::Exception::InternalError, \
+            "Mysterious internal error in SqlConnection class: " << e.DumpToString()); \
+    }
+
+namespace SecurityManager {
+
+PrivilegeDb::PrivilegeDb(const std::string &path) {
+    try {
+        mSqlConnection = new DB::SqlConnection(path,
+                DB::SqlConnection::Flag::None,
+                DB::SqlConnection::Flag::RW);
+    } catch (DB::SqlConnection::Exception::Base &e) {
+        LogError("Database initialization error: " << e.DumpToString());
+        ThrowMsg(PrivilegeDb::Exception::IOError,
+                "Database initialization error:" << e.DumpToString());
+
+    };
+}
+
+PrivilegeDb::~PrivilegeDb() {
+    delete mSqlConnection;
+}
+;
+
+void PrivilegeDb::BeginTransaction(void) {
+    try {
+        mSqlConnection->BeginTransaction();
+    }CATCH_STANDARD_EXCEPTIONS;
+}
+
+void PrivilegeDb::CommitTransaction(void) {
+    try {
+        mSqlConnection->CommitTransaction();
+    }CATCH_STANDARD_EXCEPTIONS;
+}
+
+void PrivilegeDb::RollbackTransaction(void) {
+    try {
+        mSqlConnection->RollbackTransaction();
+    }CATCH_STANDARD_EXCEPTIONS;
+}
+
+bool PrivilegeDb::PkgIdExists(const std::string &pkgId) {
+
+    try {
+        DB::SqlConnection::DataCommandAutoPtr command =
+                mSqlConnection->PrepareDataCommand(
+                        Queries.at(QueryType::EPkgIdExists));
+        command->BindString(1, pkgId.c_str());
+        if (command->Step()) {
+            LogPedantic("PkgId: " << pkgId << " found in database");
+            command->Reset();
+            return true;
+        };
+
+    }CATCH_STANDARD_EXCEPTIONS;
+
+    return false;
+}
+
+bool PrivilegeDb::AddApplication(const std::string &appId,
+        const std::string &pkgId, bool &pkgIdIsNew) {
+
+    pkgIdIsNew = !(this->PkgIdExists(pkgId));
+
+    try {
+        DB::SqlConnection::DataCommandAutoPtr command =
+                mSqlConnection->PrepareDataCommand(
+                        Queries.at(QueryType::EAddApplication));
+
+        command->BindString(1, appId.c_str());
+        command->BindString(2, pkgId.c_str());
+
+        if (command->Step()) {
+            LogPedantic("Unexpected SQLITE_ROW answer to query: " <<
+                    Queries.at(QueryType::EAddApplication));
+        };
+
+        command->Reset();
+        LogPedantic( "Added appId: " << appId << ", pkgId: " << pkgId);
+
+        return true;
+
+    }CATCH_STANDARD_EXCEPTIONS;
+    return false;
+
+}
+
+bool PrivilegeDb::RemoveApplication(const std::string &appId,
+        const std::string &pkgId, bool &pkgIdIsNoMore) {
+
+    try {
+        DB::SqlConnection::DataCommandAutoPtr command =
+                mSqlConnection->PrepareDataCommand(
+                        Queries.at(QueryType::ERemoveApplication));
+
+        command->BindString(1, appId.c_str());
+        command->BindString(2, pkgId.c_str());
+
+        if (command->Step()) {
+            LogPedantic("Unexpected SQLITE_ROW answer to query: " <<
+                    Queries.at(QueryType::ERemoveApplication));
+        };
+
+        command->Reset();
+        LogPedantic( "Removed appId: " << appId << ", pkgId: " << pkgId);
+
+        pkgIdIsNoMore = !(this->PkgIdExists(pkgId));
+
+        return true;
+
+    }CATCH_STANDARD_EXCEPTIONS;
+    return false;
+
+}
+
+bool PrivilegeDb::GetPkgPermissions(const std::string &pkgId,
+        TPermissionsList &currentPermissions) {
+    try {
+        DB::SqlConnection::DataCommandAutoPtr command =
+                mSqlConnection->PrepareDataCommand(
+                        Queries.at(QueryType::EGetPkgPermissions));
+        command->BindString(1, pkgId.c_str());
+
+        while (command->Step()) {
+            std::string permission = command->GetColumnString(0);
+            LogPedantic ("Got permission: "<< permission);
+            currentPermissions.push_back(permission);
+        };
+
+        return true;
+    }CATCH_STANDARD_EXCEPTIONS;
+
+    return false;
+
+}
+
+bool PrivilegeDb::UpdatePermissions(const std::string &appId,
+        const std::string &pkgId, const TPermissionsList &permissions,
+        TPermissionsList &addedPermissions,
+        TPermissionsList &removedPermissions) {
+
+    DB::SqlConnection::DataCommandAutoPtr command;
+
+    TPermissionsList curPermissions = TPermissionsList();
+    if (!this->GetPkgPermissions(pkgId, curPermissions))
+        return false;
+
+    try {
+        //Data compilation
+        std::set<std::string> permissionsSet = std::set<
+                std::string>(permissions.begin(), permissions.end());
+        std::set<std::string> curPermissionsSet = std::set<
+                std::string>(curPermissions.begin(), curPermissions.end());
+
+        std::list < std::string > tmpPermissions = std::list < std::string
+                > (permissions.begin(), permissions.end());
+        tmpPermissions.merge (std::list < std::string
+                >(curPermissions.begin(), curPermissions.end()));
+        tmpPermissions.unique ();
+
+        for (auto permission : tmpPermissions) {
+            if ((SET_CONTAINS(permissionsSet, permission)) && !(SET_CONTAINS(curPermissionsSet, permission))) {
+                addedPermissions.push_back(permission);
+            }
+            if (!(SET_CONTAINS(permissionsSet, permission)) && (SET_CONTAINS(curPermissionsSet, permission))) {
+                removedPermissions.push_back(permission);
+            }
+
+        }
+
+        //adding missing permissions
+        for (auto addedPermission : addedPermissions) {
+            command = mSqlConnection->PrepareDataCommand(
+                    Queries.at(QueryType::EAddAppPermissions));
+            command->BindString(1, appId.c_str());
+            command->BindString(2, pkgId.c_str());
+            command->BindString(3, addedPermission.c_str());
+
+            if (command->Step())
+                LogPedantic("Unexpected SQLITE_ROW answer to query: " <<
+                        Queries.at(QueryType::EAddAppPermissions));
+
+            command->Reset();
+            LogPedantic(
+                    "Added appId: " << appId << ", pkgId: " << pkgId << ", permission: " << addedPermission);
+
+        }
+
+        //removing unwanted permissions
+        for (auto removedPermission : removedPermissions) {
+            command = mSqlConnection->PrepareDataCommand(
+                    Queries.at(QueryType::ERemoveAppPermissions));
+            command->BindString(1, appId.c_str());
+            command->BindString(2, pkgId.c_str());
+            command->BindString(3, removedPermission.c_str());
+
+            if (command->Step())
+                LogPedantic("Unexpected SQLITE_ROW answer to query: " <<
+                        Queries.at(QueryType::EAddAppPermissions));
+
+            LogPedantic(
+                    "Removed appId: " << appId << ", pkgId: " << pkgId << ", permission: " << removedPermission);
+        }
+
+        return true;
+
+    }CATCH_STANDARD_EXCEPTIONS;
+
+    return false;
+}
+} //namespace SecurityManager