Prepare database to store license 35/127535/6
authorBartlomiej Grzelewski <b.grzelewski@samsung.com>
Wed, 26 Apr 2017 13:38:55 +0000 (15:38 +0200)
committerBartlomiej Grzelewski <b.grzelewski@samsung.com>
Fri, 12 May 2017 13:13:34 +0000 (15:13 +0200)
Security-manager does not use license directly. Licenses
will be used by license-manager. Security manager just store
information about it's location and information about
dependencies between licenses and app defined privileges.

In current api both provider and client may store license.
License stored by provider should be treated more as a key
that will be used to verify signature stored as client license.

Change-Id: If54724aa7daf49be727aab67ac614047f035a05a

18 files changed:
db/db.sql
src/client/client-common.cpp
src/client/client-security-manager.cpp
src/cmd/security-manager-cmd.cpp
src/common/cynara.cpp
src/common/include/cynara.h
src/common/include/privilege_db.h
src/common/include/protocols.h
src/common/include/service_impl.h
src/common/privilege_db.cpp
src/common/service_impl.cpp
src/dpl/core/include/dpl/serialization.h
src/include/app-manager.h
src/include/app-runtime.h
src/license-manager/agent/agent_logic.cpp
src/server/service/include/service.h
src/server/service/service.cpp
test/test_privilege_db_app_defined_privileges.cpp

index 75feaf08eaa0d7d9c27fc7d4cb1bd03da3f2080f..abc6258a302f6cb2a96bb93e12133d54db84646a 100644 (file)
--- a/db/db.sql
+++ b/db/db.sql
@@ -67,9 +67,28 @@ app_id INTEGER NOT NULL,
 uid INTEGER NOT NULL,
 privilege VARCHAR NOT NULL,
 type INTEGER NOT NULL CHECK (type >= 0 AND type <= 1),
+license VARCHAR,
 FOREIGN KEY (app_id, uid) REFERENCES user_app (app_id, uid) ON UPDATE CASCADE ON DELETE CASCADE
 );
 
+-- TODO CREATE INDEX + performance tests required
+-- CREATE INDEX IF NOT EXISTS app_defined_privilege_index ON app_defined_privilege (app_id, uid);
+
+-- This table contains privilege name that is also stored in
+-- app_defined_privilege table.
+-- It's time to consider using INTEGER instead VARCHAR and store
+-- all names of privilege in new table (We will skip this in POC).
+CREATE TABLE IF NOT EXISTS client_license (
+app_id INTEGER NOT NULL,
+uid INTEGER NOT NULL,
+privilege VARCHAR NOT NULL,
+license VARCHAR NOT NULL,
+FOREIGN KEY(app_id, uid) REFERENCES user_app (app_id, uid) ON UPDATE CASCADE ON DELETE CASCADE
+);
+
+-- TODO CREATE INDEX + performance tests required
+-- CREATE INDEX IF NOT EXISTS client_license_index ON client_license (app_id, uid);
+
 DROP VIEW IF EXISTS user_app_pkg_view;
 CREATE VIEW user_app_pkg_view AS
 SELECT
@@ -214,10 +233,10 @@ SELECT
     name AS app_name,
     uid,
     privilege,
-    type
+    type,
+    license
 FROM app_defined_privilege
-LEFT JOIN app USING (app_id)
-LEFT JOIN user_app USING (app_id, uid);
+LEFT JOIN app USING (app_id);
 
 DROP TRIGGER IF EXISTS app_defined_privilege_view_insert_trigger;
 CREATE TRIGGER app_defined_privilege_view_insert_trigger
@@ -231,8 +250,8 @@ BEGIN
     WHERE NOT EXISTS (SELECT 1 FROM user_app_pkg_view
                       WHERE uid=NEW.uid AND app_name=NEW.app_name);
 
-    INSERT OR IGNORE INTO app_defined_privilege (app_id, uid, privilege, type)
-    VALUES ((SELECT app_id FROM app WHERE name=NEW.app_name), NEW.uid, NEW.privilege, NEW.type);
+    INSERT OR IGNORE INTO app_defined_privilege (app_id, uid, privilege, type, license)
+    VALUES ((SELECT app_id FROM app WHERE name=NEW.app_name), NEW.uid, NEW.privilege, NEW.type, NEW.license);
 END;
 
 DROP TRIGGER IF EXISTS app_defined_privilege_view_delete_trigger;
@@ -243,4 +262,34 @@ BEGIN
     WHERE app_id=(SELECT app_id FROM app WHERE name=OLD.app_name) AND uid=OLD.uid;
 END;
 
+DROP VIEW IF EXISTS client_license_view;
+CREATE VIEW client_license_view AS
+SELECT
+    name AS app_name,
+    uid,
+    privilege,
+    license
+FROM client_license
+LEFT JOIN app USING (app_id);
+
+DROP TRIGGER IF EXISTS client_license_view_insert_trigger;
+CREATE TRIGGER client_license_view_insert_trigger
+INSTEAD OF INSERT ON client_license_view
+BEGIN
+    SELECT RAISE(ABORT, 'Application was not found')
+    WHERE NOT EXISTS (SELECT 1 FROM user_app_pkg_view
+                      WHERE uid=NEW.uid AND app_name=NEW.app_name);
+
+    INSERT OR IGNORE INTO client_license (app_id, uid, privilege, license)
+    VALUES ((SELECT app_id FROM app WHERE name=NEW.app_name), NEW.uid, NEW.privilege, NEW.license);
+END;
+
+DROP TRIGGER IF EXISTS client_license_view_delete_trigger;
+CREATE TRIGGER client_license_view_delete_trigger
+INSTEAD OF DELETE ON client_license_view
+BEGIN
+    DELETE FROM client_license
+    WHERE app_id=(SELECT app_id FROM app WHERE name=OLD.app_name) AND uid=OLD.uid;
+END;
+
 COMMIT TRANSACTION;
index bce0cc82dbdf9d83076762f2a5ab3ce361d6a35d..143f4865583b6c6762499a5749f1c8f1b0a06c98 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include <iostream>
+#include <cxxabi.h>
 
 #include <fcntl.h>
 #include <poll.h>
@@ -56,9 +57,15 @@ int try_catch(const std::function<int()>& func)
 {
     try {
         return func();
+    } catch (abi::__forced_unwind &) {
+        throw;
     } catch (const Exception &e) {
         LogError("SecurityManager::Exception " << e.DumpToString());
         std::cerr << "SecurityManager::Exception " << e.DumpToString() << std::endl;
+    } catch (const std::bad_alloc &e) {
+        LogError("Memory allocation failed: " << e.what());
+        std::cerr << "Memory allocation failed: " << e.what() << std::endl;
+        return SECURITY_MANAGER_ERROR_MEMORY;
     } catch (const std::exception &e) {
         LogError("STD exception " << e.what());
         std::cerr << "STD exception " << e.what() << std::endl;
index 72ba4dc070da72e8f5fa937a4d0d568ef2531379..10abfbb4b8dade465a5f48e239ca90932111eb94 100644 (file)
@@ -34,6 +34,7 @@
 #include <utility>
 #include <atomic>
 #include <stdlib.h>
+#include <cxxabi.h>
 
 #include <unistd.h>
 #include <grp.h>
@@ -182,12 +183,22 @@ int security_manager_app_inst_req_set_pkg_id(app_inst_req *p_req, const char *pk
 SECURITY_MANAGER_API
 int security_manager_app_inst_req_add_privilege(app_inst_req *p_req, const char *privilege)
 {
-    if (!p_req || !privilege)
-        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    return security_manager_app_inst_req_add_client_privilege(p_req, privilege, nullptr);
+}
 
-    p_req->privileges.push_back(privilege);
+SECURITY_MANAGER_API
+int security_manager_app_inst_req_add_client_privilege(app_inst_req *p_req, const char *privilege, const char *license)
+{
+    return try_catch([&]() -> int {
+        if (!p_req || !privilege)
+            return SECURITY_MANAGER_ERROR_INPUT_PARAM;
 
-    return SECURITY_MANAGER_SUCCESS;
+        p_req->privileges.push_back(std::make_pair(
+              std::string(privilege),
+              license ? std::string(license) : std::string()));
+
+        return SECURITY_MANAGER_SUCCESS;
+    });
 }
 
 SECURITY_MANAGER_API
@@ -195,13 +206,14 @@ int security_manager_app_inst_req_add_app_defined_privilege(
         app_inst_req *p_req,
         const char *app_defined_privilege,
         const app_defined_privilege_type type,
-        const char *)
+        const char *license)
 {
     if (!p_req || !app_defined_privilege ||
-        type < SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED || type > SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED)
+        type < SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED || type > SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED ||
+        (type == SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED && !license))
         return SECURITY_MANAGER_ERROR_INPUT_PARAM;
 
-    p_req->appDefinedPrivileges.push_back(std::make_pair(app_defined_privilege, static_cast<int>(type)));
+    p_req->appDefinedPrivileges.push_back(std::make_tuple(app_defined_privilege, static_cast<int>(type), license));
 
     return SECURITY_MANAGER_SUCCESS;
 }
@@ -1592,26 +1604,33 @@ int security_manager_shm_open(const char *name, int oflag, mode_t mode, const ch
 }
 
 SECURITY_MANAGER_API
-int security_manager_identify_privilege_provider(const char *privilege, uid_t uid,
-                                                 char **pkg_name, char **app_name)
+int security_manager_get_app_defined_privilege_provider(
+        const char *privilege,
+        uid_t uid,
+        char **pkg_name,
+        char **app_name)
 {
     using namespace SecurityManager;
     return try_catch([&]() -> int {
         LogDebug(__PRETTY_FUNCTION__ << " called");
 
+        if (privilege == NULL) {
+            LogError("privilege could not be NULL");
+            return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+        }
+
         if (pkg_name == NULL && app_name == NULL) {
             LogError("Both pkg_name and app_name are NULL");
             return SECURITY_MANAGER_ERROR_INPUT_PARAM;
         }
 
-        ClientRequest request(SecurityModuleCall::GET_PRIVILEGE_PROVIDER);
-        if (request.send(std::string(privilege), uid).failed())
+        ClientRequest request(SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_PROVIDER);
+        if (request.send(uid, std::string(privilege)).failed())
             return request.getStatus();
 
-        std::pair<std::string, std::string> provider;
-        request.recv(provider);
-        std::string appNameString = provider.first;
-        std::string pkgNameString = provider.second;
+        std::string appNameString;
+        std::string pkgNameString;
+        request.recv(appNameString, pkgNameString);
 
         if (appNameString.empty() || pkgNameString.empty()) {
             LogError("Unexpected empty appName or pkgName");
@@ -1634,4 +1653,67 @@ int security_manager_identify_privilege_provider(const char *privilege, uid_t ui
 
         return SECURITY_MANAGER_SUCCESS;
     });
-}
\ No newline at end of file
+}
+
+SECURITY_MANAGER_API
+int security_manager_get_app_defined_privilege_license(
+        const char *privilege,
+        uid_t uid,
+        char **license)
+{
+    using namespace SecurityManager;
+    return try_catch([&]() -> int {
+        LogDebug(__PRETTY_FUNCTION__ << " called");
+
+        if (privilege == NULL || license == NULL) {
+            LogError("privilege, license could not be NULL");
+            return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+        }
+
+        ClientRequest request(SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_LICENSE);
+        if (request.send(uid, std::string(privilege)).failed())
+            return request.getStatus();
+
+        std::string licenseString;
+        request.recv(licenseString);
+
+        if (!(*license = strdup(licenseString.c_str()))) {
+            LogError("Memory allocation in strdup failed.");
+            return SECURITY_MANAGER_ERROR_MEMORY;
+        }
+
+        return SECURITY_MANAGER_SUCCESS;
+    });
+}
+
+SECURITY_MANAGER_API
+int security_manager_get_client_privilege_license(
+        const char *privilege,
+        const char *app_name,
+        uid_t uid,
+        char **license)
+{
+    return try_catch([&]() -> int {
+        using namespace SecurityManager;
+        LogDebug(__PRETTY_FUNCTION__ << " called");
+
+        if (privilege == NULL || app_name == NULL || license == NULL) {
+            LogError("privilege, app_name, license could not be NULL");
+            return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+        }
+
+        ClientRequest request(SecurityModuleCall::GET_CLIENT_PRIVILEGE_LICENSE);
+        if (request.send(std::string(app_name), uid, std::string(privilege)).failed())
+            return request.getStatus();
+
+        std::string licenseString;
+        request.recv(licenseString);
+
+        if (!(*license = strdup(licenseString.c_str()))) {
+            LogError("Memory allocation in strdup failed.");
+            return SECURITY_MANAGER_ERROR_MEMORY;
+        }
+
+        return SECURITY_MANAGER_SUCCESS;
+    });
+}
index c2c12c548f1cd20c0463541f13a35ff9a248399d..58fa4c613b3bb831efbcbe772e4cebb796e92426 100644 (file)
@@ -231,7 +231,10 @@ static void parseInstallOptions(int argc, char *argv[],
         }
     }
     if (vm.count("privilege")) {
-        req.privileges = vm["privilege"].as<std::vector<std::string> >();
+        auto privVector = vm["privilege"].as<std::vector<std::string > >();
+        for (auto &e : privVector)
+            req.privileges.push_back(std::make_pair(e, std::string()));
+
         if (req.privileges.empty()) {
             po::error e("Error in parsing privilege arguments.");
             throw e;
@@ -239,7 +242,7 @@ static void parseInstallOptions(int argc, char *argv[],
 #ifdef BUILD_TYPE_DEBUG
         LogDebug("Passed privileges:");
         for (const auto &p : req.privileges) {
-            LogDebug("    " << p);
+            LogDebug("    " << p.first);
         }
 #endif
     }
index 886817d99852ac3c27cedc3490c32472853218a8..cad1989eb04bef7ebc7585bc9e4dfaee7313383a 100644 (file)
@@ -341,8 +341,8 @@ void CynaraAdmin::updateAppPolicy(
     bool global,
     uid_t uid,
     const std::vector<std::string> &privileges,
-    const std::vector<std::pair<std::string, int>> &oldAppDefinedPrivileges,
-    const std::vector<std::pair<std::string, int>> &newAppDefinedPrivileges,
+    const AppDefinedPrivilegesVector &oldAppDefinedPrivileges,
+    const AppDefinedPrivilegesVector &newAppDefinedPrivileges,
     bool policyRemove)
 {
     std::vector<CynaraAdminPolicy> oldPolicies;
@@ -431,26 +431,26 @@ void CynaraAdmin::updateAppPolicy(
     std::vector<CynaraAdminPolicy> oldUntrustedPolicies;
     std::vector<CynaraAdminPolicy> oldLicensedPolicies;
 
-    for (const std::pair<std::string, int> &p : oldAppDefinedPrivileges) {
-        switch (p.second) {
+    for (const AppDefinedPrivilege &p : oldAppDefinedPrivileges) {
+        switch (std::get<1>(p)) {
             case SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED:
                 listPolicies(Buckets.at(Bucket::APPDEFINED), CYNARA_ADMIN_WILDCARD, cynaraUser,
-                             p.first, oldUntrustedPolicies);
+                             std::get<0>(p), oldUntrustedPolicies);
                 break;
             case SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED:
                 listPolicies(Buckets.at(Bucket::APPDEFINED), CYNARA_ADMIN_WILDCARD, cynaraUser,
-                             p.first, oldLicensedPolicies);
+                             std::get<0>(p), oldLicensedPolicies);
                 break;
         }
     }
 
-    for (const std::pair<std::string, int> &p : newAppDefinedPrivileges) {
-        switch (p.second) {
+    for (const AppDefinedPrivilege &p : newAppDefinedPrivileges) {
+        switch (std::get<1>(p)) {
             case SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED:
-                untrustedPrivileges.push_back(p.first);
+                untrustedPrivileges.push_back(std::get<0>(p));
                 break;
             case SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED:
-                licensedPrivileges.push_back(p.first);
+                licensedPrivileges.push_back(std::get<0>(p));
                 break;
         }
     }
index c2ac5902570e410d22f226a8d3b84d228b0fc97f..41f9081c7bd3fdc5b3cdf770b502294d8841f6cc 100644 (file)
@@ -37,6 +37,7 @@
 #include <sys/eventfd.h>
 
 #include "security-manager.h"
+#include "privilege_db.h"
 
 namespace SecurityManager {
 
@@ -140,8 +141,8 @@ public:
      */
     void updateAppPolicy(const std::string &label, bool global, uid_t uid,
         const std::vector<std::string> &privileges,
-        const std::vector<std::pair<std::string, int>> &oldAppDefinedPrivileges,
-        const std::vector<std::pair<std::string, int>> &newAppDefinedPrivileges,
+        const AppDefinedPrivilegesVector &oldAppDefinedPrivileges,
+        const AppDefinedPrivilegesVector &newAppDefinedPrivileges,
         bool policyRemove = false);
 
     /**
index d95d82d55da0c28d96aef6c1b937156bc68b5057..6d305fa86e285ec082dae7482932f37023c47b10 100644 (file)
@@ -82,13 +82,18 @@ enum class StmtType {
     EIsPackageHybrid,
     EGetPackagesInfo,
     EAddAppDefinedPrivilege,
+    EAddClientPrivilege,
     ERemoveAppDefinedPrivileges,
+    ERemoveClientPrivileges,
     EGetAppDefinedPrivileges,
-    EGetAppForAppDefinedPrivilege,
+    EGetAppAndLicenseForAppDefinedPrivilege,
+    EGetLicenseForClientPrivilege,
+    EIsUserAppInstalled,
 };
 
-typedef std::pair<std::string, int> Privilege;
-typedef std::vector<Privilege> PrivilegesVector;
+// privilege, app_defined_privilege_type, license
+typedef std::tuple<std::string, int, std::string> AppDefinedPrivilege;
+typedef std::vector<AppDefinedPrivilege> AppDefinedPrivilegesVector;
 
 class PrivilegeDb {
     /**
@@ -142,10 +147,14 @@ private:
         { StmtType::EIsPackageSharedRO, "SELECT shared_ro FROM pkg WHERE name=?"},
         { StmtType::EIsPackageHybrid, "SELECT is_hybrid FROM pkg WHERE name=?"},
         { StmtType::EGetPackagesInfo, "SELECT name, shared_ro, is_hybrid FROM pkg"},
-        { StmtType::EAddAppDefinedPrivilege, "INSERT INTO app_defined_privilege_view (app_name, uid, privilege, type) VALUES (?, ?, ?, ?)"},
+        { StmtType::EAddAppDefinedPrivilege, "INSERT INTO app_defined_privilege_view (app_name, uid, privilege, type, license) VALUES (?, ?, ?, ?, ?)"},
+        { StmtType::EAddClientPrivilege, "INSERT INTO client_license_view (app_name, uid, privilege, license) VALUES (?, ?, ?, ?)"},
         { StmtType::ERemoveAppDefinedPrivileges, "DELETE FROM app_defined_privilege_view WHERE app_name = ? AND uid = ?"},
-        { StmtType::EGetAppDefinedPrivileges, "SELECT privilege, type FROM app_defined_privilege_view WHERE app_name = ? AND uid = ?"},
-        { StmtType::EGetAppForAppDefinedPrivilege, "SELECT app_name FROM app_defined_privilege_view WHERE privilege = ? AND uid = ?"},
+        { StmtType::ERemoveClientPrivileges, "DELETE FROM client_license_view WHERE app_name = ? AND uid = ?"},
+        { StmtType::EGetAppDefinedPrivileges, "SELECT privilege, type, license FROM app_defined_privilege_view WHERE app_name = ? AND uid = ?"},
+        { StmtType::EGetAppAndLicenseForAppDefinedPrivilege, "SELECT app_name, license FROM app_defined_privilege_view WHERE uid = ? AND privilege = ?"},
+        { StmtType::EGetLicenseForClientPrivilege, "SELECT license FROM client_license_view WHERE app_name = ? AND uid = ? AND privilege = ? "},
+        { StmtType::EIsUserAppInstalled, "SELECT count(*) FROM user_app_pkg_view WHERE app_name = ? AND uid = ?"},
     };
 
     /**
@@ -541,7 +550,7 @@ public:
     void GetPackagesInfo(std::vector<PkgInfo> &packages);
 
     /**
-     * Add new privilege defined by application
+     * Add new privilege and license defined by application
      *
      * @param[in] appName - application identifier
      * @param[in] uid - user identifier
@@ -550,7 +559,7 @@ public:
      * @exception PrivilegeDb::Exception::InternalError on internal error
      * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
      */
-    void AddAppDefinedPrivilege(const std::string &appName, uid_t uid, const Privilege &privilege);
+    void AddAppDefinedPrivilege(const std::string &appName, uid_t uid, const AppDefinedPrivilege &privilege);
 
     /**
      * Add vector of privileges defined by application
@@ -562,10 +571,24 @@ public:
      * @exception PrivilegeDb::Exception::InternalError on internal error
      * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
      */
-    void AddAppDefinedPrivileges(const std::string &appName, uid_t uid, const PrivilegesVector &privileges);
+    void AddAppDefinedPrivileges(const std::string &appName, uid_t uid, const AppDefinedPrivilegesVector &privileges);
 
     /**
-     * Remove privileges defined by application
+     * Add privilege and license used by client application
+     *
+     * @param[in] appName - application identifier
+     * @param[in] uid - user identifier
+     * @param[in] privilege - privilege identifier
+     * @param[in] license - license
+     *
+     * @exception PrivilegeDb::Exception::InternalError on internal error
+     * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+     */
+    void AddClientPrivilege(const std::string &appName, uid_t uid, const std::string &privilege,
+                            const std::string &license);
+
+    /**
+     * Remove privileges/licenses defined by application
      *
      * @param[in] appName - application identifier
      * @param[in] uid - user identifier
@@ -575,6 +598,17 @@ public:
      */
     void RemoveAppDefinedPrivileges(const std::string &appName, uid_t uid);
 
+    /**
+     * Remove privileges/licenses used by client application
+     *
+     * @param[in] appName - application identifier
+     * @param[in] uid - user identifier
+     *
+     * @exception PrivilegeDb::Exception::InternalError on internal error
+     * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+     */
+    void RemoveClientPrivileges(const std::string &appName, uid_t uid);
+
     /**
      * Retrieve vector of pairs with privilege (1st value) and privilege type (2nd value)
      *
@@ -585,19 +619,43 @@ public:
      * @exception PrivilegeDb::Exception::InternalError on internal error
      * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
      */
-    void GetAppDefinedPrivileges(const std::string &appName, uid_t uid, PrivilegesVector &privileges);
+    void GetAppDefinedPrivileges(const std::string &appName, uid_t uid, AppDefinedPrivilegesVector &privileges);
 
     /**
-     * Retrieve application which define privilege
+     * Retrieve application and license of application which define privilege
      *
-     * @param[in]  privilege - privilege identifier
      * @param[in]  uid - user identifier
+     * @param[in]  privilege - privilege identifier
      * @param[out] appName - application identifier
+     * @param[out] license - verification factor required by license-manager
+     *
+     * @exception PrivilegeDb::Exception::InternalError on internal error
+     * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+     */
+    void GetAppAndLicenseForAppDefinedPrivilege(uid_t uid, const std::string &privilege,
+                                                std::string &appName, std::string &license);
+
+    /**
+     * Retrieve license of client application
+     *
+     * @param[in]  appName - application identifier
+     * @param[in]  uid - user identifier
+     * @param[in]  privilege - privilege identifier
+     * @param[out] license - verification factor required by license-manager
+     *
+     * @exception PrivilegeDb::Exception::InternalError on internal error
+     * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+     */
+    void GetLicenseForClientPrivilege(const std::string &appName, uid_t uid, const std::string &privilege,
+                                      std::string &license);
+
+    /**
+     * Check whether user has installed application
      *
      * @exception PrivilegeDb::Exception::InternalError on internal error
      * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
      */
-    void GetAppForAppDefinedPrivilege(const Privilege &privilege, uid_t uid, std::string &appName);
+    bool IsUserAppInstalled(const std::string& appName, uid_t uid);
 };
 
 } //namespace SecurityManager
index 76dba456cf542cc24652fb20654b4c8539eedb4c..4b7adc805517b562e9d50037ca0f1d3c94b19474 100644 (file)
@@ -36,8 +36,8 @@ typedef std::vector<std::pair<std::string, int>> pkg_paths;
 struct app_inst_req {
     std::string appName;
     std::string pkgName;
-    std::vector<std::string> privileges;
-    std::vector<std::pair<std::string, int>> appDefinedPrivileges;
+    std::vector<std::pair<std::string, std::string>> privileges;
+    std::vector<std::tuple<std::string, int, std::string>> appDefinedPrivileges;
     pkg_paths pkgPaths;
     uid_t uid;
     std::string tizenVersion;
@@ -89,7 +89,9 @@ enum class SecurityModuleCall
     GROUPS_FOR_UID,
     LABEL_FOR_PROCESS,
     SHM_APP_NAME,
-    GET_PRIVILEGE_PROVIDER,
+    GET_APP_DEFINED_PRIVILEGE_PROVIDER,
+    GET_APP_DEFINED_PRIVILEGE_LICENSE,
+    GET_CLIENT_PRIVILEGE_LICENSE,
     NOOP = 0x90,
 };
 
index 07f475cf5d6aad0460f4619d963c6b4b8a5aab7e..11eec4891095c3a1eb56485af578cfc15a485e90 100644 (file)
@@ -251,14 +251,41 @@ public:
     /**
      * Retrieves the app_id/pkg_id associated with given privilege and uid.
      *
+     * @param[in]  uid       user identifier
+     * @param[in]  privilege privilege name
+     * @param[out] appName  returns app_id
+     * @param[out] pkgName  returns pkg_id
+     *
+     * @return API return code, as defined in protocols.h
+     */
+    int getAppDefinedPrivilegeProvider(uid_t uid, const std::string &privilege,
+                                       std::string &appName, std::string &pkgName);
+
+    /**
+     * Retrieves the license associated with given privilege and uid.
+     *
+     * @param[in]  uid       user identifier
      * @param[in]  privilege privilege name
+     * @param[out] license   returns license information connected with privilege
+     *
+     * @return API return code, as defined in protocols.h
+     */
+    int getAppDefinedPrivilegeLicense(uid_t uid, const std::string &privilege,
+                                      std::string &license);
+
+    /**
+     * Retrieves the license associated with given privilege and uid.
+     *
+     * @param[in]  appName   application identifier
      * @param[in]  uid       user identifier
-     * @param[out] provider  returned pair of app_id and pkg_id
+     * @param[in]  privilege privilege name
+     * @param[out] license   returns license information connected with privilege
      *
      * @return API return code, as defined in protocols.h
      */
-    int getPrivilegeProvider(const std::string &privilege, uid_t uid,
-                             std::pair<std::string, std::string> &provider);
+    int getClientPrivilegeLicense(const std::string &appName, uid_t uid,
+                                  const std::string &privilege,
+                                  std::string &license);
 
 private:
     bool authenticate(const Credentials &creds, const std::string &privilege);
index 930d52347f422412c2d2347d98707e2fbd5d7e01..ad6f90d2e61a6b06cfea71a6f16e1d956faa3ebd 100644 (file)
@@ -588,27 +588,54 @@ void PrivilegeDb::GetPackagesInfo(std::vector<PkgInfo> &packages)
      });
 }
 
-void PrivilegeDb::AddAppDefinedPrivilege(const std::string &appName, uid_t uid, const Privilege &privilege)
+void PrivilegeDb::AddAppDefinedPrivilege(const std::string &appName, uid_t uid,
+                                         const AppDefinedPrivilege &privilege)
 {
     try_catch<void>([&] {
         auto command = getStatement(StmtType::EAddAppDefinedPrivilege);
         command->BindString(1, appName);
         command->BindInteger(2, uid);
-        command->BindString(3, privilege.first);
-        command->BindInteger(4, privilege.second);
+        command->BindString(3, std::get<0>(privilege));
+        command->BindInteger(4, std::get<1>(privilege));
+        command->BindString(5, std::get<2>(privilege));
 
-        if (command->Step())
-            LogDebug("Added privilege: " << privilege.first << " defined by: " << appName <<
-                     " and user: " << uid);
+        if (command->Step()) {
+            LogDebug("Unexpected SQLITE_ROW answer to query: " <<
+                     Queries.at(StmtType::EAddAppDefinedPrivilege));
+        }
+
+        LogDebug("Added privilege: " << std::get<0>(privilege) << " defined by: " << appName <<
+                 " and user: " << uid);
      });
 }
 
-void PrivilegeDb::AddAppDefinedPrivileges(const std::string &appName, uid_t uid, const PrivilegesVector &privileges)
+void PrivilegeDb::AddAppDefinedPrivileges(const std::string &appName, uid_t uid,
+                                          const AppDefinedPrivilegesVector &privileges)
 {
     for (const auto &privilege : privileges)
         AddAppDefinedPrivilege(appName, uid, privilege);
 }
 
+void PrivilegeDb::AddClientPrivilege(const std::string &appName, uid_t uid, const std::string &privilege,
+                                     const std::string &license)
+{
+    try_catch<void>([&] {
+        auto command = getStatement(StmtType::EAddClientPrivilege);
+        command->BindString(1, appName);
+        command->BindInteger(2, uid);
+        command->BindString(3, privilege);
+        command->BindString(4, license);
+
+        if (command->Step()) {
+            LogDebug("Unexpected SQLITE_ROW answer to query: " <<
+                     Queries.at(StmtType::EAddClientPrivilege));
+        }
+
+        LogDebug("Added privilege: " << privilege << " license: " << license <<
+                 "defined by: " << appName << " and user: " << uid);
+     });
+}
+
 void PrivilegeDb::RemoveAppDefinedPrivileges(const std::string &appName, uid_t uid)
 {
     try_catch<void>([&] {
@@ -616,12 +643,33 @@ void PrivilegeDb::RemoveAppDefinedPrivileges(const std::string &appName, uid_t u
         command->BindString(1, appName);
         command->BindInteger(2, uid);
 
-        if (command->Step())
-            LogDebug("Removed privileges defined by: " << appName << " and user: " << uid);
+        if (command->Step()) {
+            LogDebug("Unexpected SQLITE_ROW answer to query: " <<
+                     Queries.at(StmtType::ERemoveAppDefinedPrivileges));
+        };
+
+        LogDebug("Removed privileges defined by: " << appName << " and user: " << uid);
+     });
+}
+
+void PrivilegeDb::RemoveClientPrivileges(const std::string &appName, uid_t uid)
+{
+    try_catch<void>([&] {
+        auto command = getStatement(StmtType::ERemoveClientPrivileges);
+        command->BindString(1, appName);
+        command->BindInteger(2, uid);
+
+        if (command->Step()) {
+            LogDebug("Unexpected SQLITE_ROW answer to query: " <<
+                     Queries.at(StmtType::ERemoveClientPrivileges));
+        };
+
+        LogDebug("Removed privileges used by: " << appName << " and user: " << uid);
      });
 }
 
-void PrivilegeDb::GetAppDefinedPrivileges(const std::string &appName, uid_t uid, PrivilegesVector &privileges)
+void PrivilegeDb::GetAppDefinedPrivileges(const std::string &appName, uid_t uid,
+                                          AppDefinedPrivilegesVector &privileges)
 {
     try_catch<void>([&] {
         privileges.clear();
@@ -632,28 +680,69 @@ void PrivilegeDb::GetAppDefinedPrivileges(const std::string &appName, uid_t uid,
         while (command->Step()) {
             auto privilege = command->GetColumnString(0);
             auto type = command->GetColumnInteger(1);
+            auto license = command->GetColumnString(2);
             LogDebug("App: " << appName << " installed by: " << uid << " defines privilege: " << privilege);
-            privileges.push_back(std::make_pair(privilege, type));
+            privileges.push_back(std::make_tuple<>(privilege, type, license));
         }
     });
 }
 
-void PrivilegeDb::GetAppForAppDefinedPrivilege(const Privilege &privilege, uid_t uid, std::string &appName)
+void PrivilegeDb::GetAppAndLicenseForAppDefinedPrivilege(uid_t uid, const std::string &privilege,
+                                                         std::string &appName, std::string &license)
 {
     try_catch<void>([&] {
         appName.clear();
+        license.clear();
 
-        auto command = getStatement(StmtType::EGetAppForAppDefinedPrivilege);
-        command->BindString(1, privilege.first);
-        command->BindInteger(2, uid);
+        auto command = getStatement(StmtType::EGetAppAndLicenseForAppDefinedPrivilege);
+        command->BindInteger(1, uid);
+        command->BindString(2, privilege);
 
-        if (command->Step())
+        if (command->Step()) {
             appName = command->GetColumnString(0);
+            license = command->GetColumnString(1);
+        }
 
         if (!appName.empty())
-            LogDebug("Privilege: " << privilege.first << " defined by " << appName);
+            LogDebug("Privilege: " << privilege << " defined by " << appName);
+        else
+            LogDebug("Privilege: " << privilege << " not exist");
+    });
+}
+
+void PrivilegeDb::GetLicenseForClientPrivilege(const std::string &appName, uid_t uid,
+                                               const std::string &privilege, std::string &license)
+{
+    try_catch<void>([&] {
+        license.clear();
+
+        auto command = getStatement(StmtType::EGetLicenseForClientPrivilege);
+        command->BindString(1, appName);
+        command->BindInteger(2, uid);
+        command->BindString(3, privilege);
+
+        if (command->Step())
+            license = command->GetColumnString(0);
+
+        if (license.empty())
+            LogDebug("License not found for app: " << appName << " privilege: " << privilege << " uid: " << uid);
         else
-            LogDebug("Privilege: " << privilege.first << " not exist");
+            LogDebug("License found for app: " << appName << " privilege: " << privilege << " uid: " << uid << " License: " << license);
+    });
+}
+
+bool PrivilegeDb::IsUserAppInstalled(const std::string& appName, uid_t uid)
+{
+    return try_catch<bool>([&]() -> bool {
+        auto command = getStatement(StmtType::EIsUserAppInstalled);
+        command->BindString(1, appName);
+        command->BindInteger(2, uid);
+        int isInstalled = 0;
+
+        if (command->Step())
+            isInstalled = command->GetColumnInteger(0);
+
+        return (isInstalled > 0);
     });
 }
 
index 400af140c0da9426bdc7aae50de26beca2f3141a..a87ece403a34aafea5c048fee4029d6e218c48c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2014-2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Contact: Rafal Krypa <r.krypa@samsung.com>
  *
@@ -508,6 +508,12 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
     bool hasSharedRO = isSharedRO(req.pkgPaths);
 
     try {
+        std::vector<std::string> privilegeList;
+        privilegeList.reserve(req.privileges.size());
+
+        for (auto &e : req.privileges)
+            privilegeList.push_back(e.first);
+
         setRequestDefaultValues(req.uid, req.installationType);
 
         LogDebug("Install parameters: appName: " << req.appName << ", pkgName: " << req.pkgName
@@ -533,17 +539,23 @@ int ServiceImpl::appInstall(const Credentials &creds, app_inst_req &&req)
         getPkgLabels(req.pkgName, pkgLabels);
         m_privilegeDb.GetPkgAuthorId(req.pkgName, authorId);
 
-        PrivilegesVector oldAppDefinedPrivileges;
+        AppDefinedPrivilegesVector oldAppDefinedPrivileges;
         m_privilegeDb.GetAppDefinedPrivileges(req.appName, req.uid, oldAppDefinedPrivileges);
 
         bool global = req.installationType == SM_APP_INSTALL_GLOBAL ||
                       req.installationType == SM_APP_INSTALL_PRELOADED;
-        m_cynaraAdmin.updateAppPolicy(appLabel, global, req.uid, req.privileges,
+        m_cynaraAdmin.updateAppPolicy(appLabel, global, req.uid, privilegeList,
                                       oldAppDefinedPrivileges, req.appDefinedPrivileges);
 
         m_privilegeDb.RemoveAppDefinedPrivileges(req.appName, req.uid);
         m_privilegeDb.AddAppDefinedPrivileges(req.appName, req.uid, req.appDefinedPrivileges);
 
+        m_privilegeDb.RemoveClientPrivileges(req.appName, req.uid);
+        for (auto &e : req.privileges) {
+            if (!e.second.empty())
+                m_privilegeDb.AddClientPrivilege(req.appName, req.uid, e.first, e.second);
+        }
+
         if (hasSharedRO)
             m_privilegeDb.SetSharedROPackage(req.pkgName);
 
@@ -704,7 +716,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req)
                 }
         }
 
-        PrivilegesVector oldAppDefinedPrivileges;
+        AppDefinedPrivilegesVector oldAppDefinedPrivileges;
         m_privilegeDb.GetAppDefinedPrivileges(req.appName, req.uid, oldAppDefinedPrivileges);
 
         m_privilegeDb.RemoveApplication(req.appName, req.uid, removeApp, removePkg, removeAuthor);
@@ -715,7 +727,7 @@ int ServiceImpl::appUninstall(const Credentials &creds, app_inst_req &&req)
         bool global = req.installationType == SM_APP_INSTALL_GLOBAL ||
                       req.installationType == SM_APP_INSTALL_PRELOADED;
         m_cynaraAdmin.updateAppPolicy(processLabel, global, req.uid, std::vector<std::string>(),
-                                      oldAppDefinedPrivileges, std::vector<std::pair<std::string, int>>(), true);
+                                      oldAppDefinedPrivileges, AppDefinedPrivilegesVector(), true);
         trans.commit();
 
         LogDebug("Application uninstallation commited to database");
@@ -1702,30 +1714,73 @@ int ServiceImpl::shmAppName(const Credentials &creds, const std::string &shmName
     return SECURITY_MANAGER_SUCCESS;
 }
 
-int ServiceImpl::getPrivilegeProvider(const std::string &privilege, uid_t uid,
-                                      std::pair<std::string, std::string> &provider)
+int ServiceImpl::getAppDefinedPrivilegeProvider(uid_t uid, const std::string &privilege,
+                                                std::string &appName, std::string &pkgName)
 {
-    std::string appName, pkgName;
+    std::string appNameString, pkgNameString, licenseString;
     try {
-        m_privilegeDb.GetAppForAppDefinedPrivilege(std::make_pair(privilege, 0), uid, appName);
+        m_privilegeDb.GetAppAndLicenseForAppDefinedPrivilege(uid, privilege, appNameString, licenseString);
 
         // check if privilege is provided by globally installed application
-        if (appName.empty())
-            m_privilegeDb.GetAppForAppDefinedPrivilege(std::make_pair(privilege, 0), getGlobalUserId(), appName);
+        if (appNameString.empty())
+            m_privilegeDb.GetAppAndLicenseForAppDefinedPrivilege(getGlobalUserId(), privilege, appNameString, licenseString);
 
-        m_privilegeDb.GetAppPkgName(appName, pkgName);
-        if (appName.empty() || pkgName.empty()) {
+        m_privilegeDb.GetAppPkgName(appNameString, pkgNameString);
+        if (appNameString.empty() || pkgNameString.empty()) {
             LogWarning("Privilege " << privilege << " not found in database");
             return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
         } else {
-            LogDebug("Privilege: " << privilege << " provided by app: " << appName << ", pkg: " << pkgName);
+            LogDebug("Privilege: " << privilege << " provided by app: " << appNameString << ", pkg: " << pkgNameString);
         }
     } catch (const PrivilegeDb::Exception::Base &e) {
         LogError("Error while getting appName or pkgName from database: " << e.DumpToString());
         return SECURITY_MANAGER_ERROR_SERVER_ERROR;
     }
 
-    provider = std::make_pair(appName, pkgName);
+    appName = appNameString;
+    pkgName = pkgNameString;
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+int ServiceImpl::getAppDefinedPrivilegeLicense(uid_t uid, const std::string &privilege,
+                                                std::string &license)
+{
+    std::string appNameString, licenseString;
+    try {
+        m_privilegeDb.GetAppAndLicenseForAppDefinedPrivilege(uid, privilege, appNameString, licenseString);
+
+        // check if privilege is provided by globally installed application
+        if (appNameString.empty())
+            m_privilegeDb.GetAppAndLicenseForAppDefinedPrivilege(getGlobalUserId(), privilege, appNameString, licenseString);
+
+        if (licenseString.empty())
+            return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
+    } catch (const PrivilegeDb::Exception::Base &e) {
+        LogError("Error while getting license from database: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    }
+
+    license = licenseString;
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+int ServiceImpl::getClientPrivilegeLicense(const std::string &appName, uid_t uid, const std::string &privilege,
+                                           std::string &license)
+{
+    std::string licenseString;
+    try {
+        uid_t requestUid = m_privilegeDb.IsUserAppInstalled(appName, uid) ? uid : getGlobalUserId();
+
+        m_privilegeDb.GetLicenseForClientPrivilege(appName, requestUid, privilege, licenseString);
+
+        if (licenseString.empty())
+            return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT;
+    } catch (const PrivilegeDb::Exception::Base &e) {
+        LogError("Error while getting license for app: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    }
+
+    license = licenseString;
     return SECURITY_MANAGER_SUCCESS;
 }
 
index 096aa93b6c124443720e0e3a2176a837fb4ba1df..b553876afc31833c548ae8ccc984c785310b31af 100644 (file)
@@ -26,6 +26,7 @@
 #include <list>
 #include <map>
 #include <memory>
+#include <tuple>
 
 namespace SecurityManager {
 // Abstract data stream buffer
@@ -186,6 +187,21 @@ struct Serialization {
         Serialize(stream, *p);
     }
 
+    // TODO template version without limit on tuple size
+    // std::tuple
+    template <typename A, typename B, typename C>
+    static void Serialize(IStream& stream, const std::tuple<A, B, C>& t)
+    {
+        Serialize(stream, std::get<0>(t));
+        Serialize(stream, std::get<1>(t));
+        Serialize(stream, std::get<2>(t));
+    }
+    template <typename A, typename B, typename C>
+    static void Serialize(IStream& stream, const std::tuple<A, B, C>* const t)
+    {
+        Serialize(stream, *t);
+    }
+
     // std::map
     template <typename K, typename T>
     static void Serialize(IStream& stream, const std::map<K, T>& map)
@@ -379,6 +395,22 @@ struct Deserialization {
         Deserialize(stream, *p);
     }
 
+    // TODO template version without limit on tuple size
+    // std::tuple
+    template <typename A, typename B, typename C>
+    static void Deserialize(IStream& stream, std::tuple<A, B, C>& t)
+    {
+        Deserialize(stream, std::get<0>(t));
+        Deserialize(stream, std::get<1>(t));
+        Deserialize(stream, std::get<2>(t));
+    }
+    template <typename A, typename B, typename C>
+    static void Deserialize(IStream& stream, std::tuple<A, B, C>*& t)
+    {
+        t = new std::tuple<A, B, C>;
+        Deserialize(stream, *t);
+    }
+
     // std::map
     template <typename K, typename T>
     static void Deserialize(IStream& stream, std::map<K, T>& map)
index ef37dad93e00c962795cea3947ec62fb9d892157..71fe1dde3444cfae92d90a99fbb6d2163abaf85c 100644 (file)
@@ -73,20 +73,48 @@ int security_manager_app_inst_req_set_pkg_id(app_inst_req *p_req, const char *pk
  * This function is used to add privilege to app_inst_req structure,
  * it can be called multiple times
  *
+ * \deprecated This function is deprecated. Use
+ *             security_manager_app_inst_req_add_client_privilege() instead.
+ *
  * \param[in] p_req      Pointer handling app_inst_req structure
  * \param[in] privilege  Application privilege
  * \return API return code or error code
  */
-int security_manager_app_inst_req_add_privilege(app_inst_req *p_req, const char *privilege);
+int security_manager_app_inst_req_add_privilege(
+        app_inst_req *p_req,
+        const char *privilege) __attribute__((deprecated(
+            "Use security_manager_app_inst_req_add_client_privilege() instead")));
+
+/**
+ * This function is used to add privilege and license to app_inst_req structure,
+ * it can be called multiple times.
+ *
+ * \param[in] p_req      Pointer handling app_inst_req structure
+ * \param[in] privilege  Application privilege
+ * \param[in] license    Requirements for license-manager. For type
+ *                       SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED this parameter
+ *                       must be NULL. For type SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSE
+ *                       this parameter may contain path to public_key/certificate (or
+ *                       other document) used during varification process.
+ * \return API return code or error code
+ */
+int security_manager_app_inst_req_add_client_privilege(
+        app_inst_req *p_req,
+        const char *privilege,
+        const char *license);
 
 /**
- * This function is used to add privilege defined by application to app_inst_req structure,
+ * This function is used to add privilege and license defined by application to app_inst_req structure,
  * it can be called multiple times
  *
  * \param[in] p_req                 Pointer handling app_inst_req structure
  * \param[in] app_defined_privilege Privilege defined by application
  * \param[in] type                  Privilege type
- * \param[in] license               Unused parameter
+ * \param[in] license               Requirements for license-manager. For type
+ *                                  SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED this parameter
+ *                                  must be NULL. For type SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSE
+ *                                  this parameter may contain path to public_key/certificate (or
+ *                                  other document) used during varification process.
  * \return API return code or error code
  */
 int security_manager_app_inst_req_add_app_defined_privilege(
index 207737486665c857afc1f9127d6ce0846bd1ccdc..945b6a9c079334fe0d4531d96f8052d86c82fba9 100644 (file)
@@ -220,7 +220,7 @@ int security_manager_app_has_privilege(const char *app_id, const char *privilege
 int security_manager_shm_open(const char *name, int oflag, mode_t mode, const char *app_id);
 
 /**
- * Get package and application id of an application which provides privilege
+ * Get package id and application id of an application which provides privilege.
  *
  * On successful call pkg_id and app_id should be freed when caller is done with them.
  * Both pkg_id and app_id are allocated with malloc() so they should be freed with free() function.
@@ -235,8 +235,50 @@ int security_manager_shm_open(const char *name, int oflag, mode_t mode, const ch
  * \param[out]  app_id     Application id of the provider application
  * \return API return code or error code
  */
-int security_manager_identify_privilege_provider(const char *privilege, uid_t uid,
-                                                 char **pkg_id, char **app_id);
+int security_manager_get_app_defined_privilege_provider(const char *privilege,
+                                                        uid_t uid,
+                                                        char **pkg_id,
+                                                        char **app_id);
+
+/**
+ * Get license of an application which provides privilege.
+ *
+ * On successful call license should be freed when caller is done with them.
+ * license is allocated with malloc() so should be freed with free() function.
+ * When privilege/uid is incorrect or not related to any license, this function will
+ * return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT.
+ *
+ * \param[in]   privilege  Privilege name
+ * \param[in]   uid        User identifier
+ * \param[out]  license    Data used to verify if client may use this privilege.
+ *                         If privilege type is SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED this
+ *                         value will be set to NULL.
+ * \return API return code or error code
+ */
+int security_manager_get_app_defined_privilege_license(const char *privilege,
+                                                       uid_t uid,
+                                                       char **license);
+
+/**
+ * Extract license from application that requested access to privilege.
+ *
+ * On successful call license should be freed when caller is done with them.
+ * license parameter will be allocated with malloc so it should be freed with free() function.
+ * When privilege/app_id/uid is incorrect or not related to any license, this function will
+ * return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT.
+ *
+ * \param[in]  privilege   Privilege name
+ * \param[in]  app_id      Id of application that request access to privilege.
+ * \param[in]  uid         User identifier
+ * \param[out] license     Data that will be used to verify access to privilege. If privilege
+ *                         type is SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED this value will be
+ *                         set to NULL.
+ * \return API return code or error code
+ */
+int security_manager_get_client_privilege_license(const char *privilege,
+                                                  const char *app_id,
+                                                  uid_t uid,
+                                                  char **license);
 
 #ifdef __cplusplus
 }
index 7fe77c8abe80f6109e99323fa5b8962797d7b9c4..18988c6c61d335be4ab61ebea63c01d181b7129f 100644 (file)
@@ -33,18 +33,24 @@ std::string AgentLogic::process(const std::string &data) {
     std::string smack, privilege;
     int uid;
     ss >> smack >> uid >> privilege;
-    char *pkgId = nullptr, *appId = nullptr;
+    char *pkgId = nullptr, *appId = nullptr, *licensePath = nullptr;
 
-    security_manager_identify_privilege_provider(
+    security_manager_get_app_defined_privilege_provider(
             privilege.c_str(),
             uid,
             &pkgId,
             &appId);
 
+    security_manager_get_app_defined_privilege_license(
+            privilege.c_str(),
+            uid,
+            &licensePath);
+
     ALOGD("App: %s Uid: %d Priv: %s", smack.c_str(), uid, privilege.c_str());
     ALOGD("Privilege: %s is Provided by: %s/%s", privilege.c_str(), appId, pkgId);
     free(pkgId);
     free(appId);
+    free(licensePath);
 
     std::stringstream out;
     out << 1;
index 537dc6fd7a097d2b27654ee64a4f864bcb2f7d45..8d547284dc575e1d075b4b84d0f90ce0a552694b 100644 (file)
@@ -209,7 +209,23 @@ private:
      * @param  buffer Raw received data buffer
      * @param  send   Raw data buffer to be sent
      */
-    void processGetPrivilegeProvider(MessageBuffer &buffer, MessageBuffer &send);
+    void processGetAppDefinedPrivilegeProvider(MessageBuffer &buffer, MessageBuffer &send);
+
+    /**
+     * Process getting license of privilege
+     *
+     * @param  buffer Raw received data buffer
+     * @param  send   Raw data buffer to be sent
+     */
+    void processGetAppDefinedPrivilegeLicense(MessageBuffer &buffer, MessageBuffer &send);
+
+    /**
+     * Process getting license of privilege
+     *
+     * @param  buffer Raw received data buffer
+     * @param  send   Raw data buffer to be sent
+     */
+    void processGetClientPrivilegeLicense(MessageBuffer &buffer, MessageBuffer &send);
 };
 
 } // namespace SecurityManager
index ef78f45a551971c3542a4310fdcb096ba3aecb5e..1450c95a031b5765ae0b558aa958dfae71764189 100644 (file)
@@ -150,9 +150,17 @@ bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer,
                 case SecurityModuleCall::SHM_APP_NAME:
                     processShmAppName(buffer, send, creds);
                     break;
-                case SecurityModuleCall::GET_PRIVILEGE_PROVIDER:
-                    LogDebug("call_type: SecurityModuleCall::GET_PRIVILEGE_PROVIDER");
-                    processGetPrivilegeProvider(buffer, send);
+                case SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_PROVIDER:
+                    LogDebug("call_type: SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_PROVIDER");
+                    processGetAppDefinedPrivilegeProvider(buffer, send);
+                    break;
+                case SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_LICENSE:
+                    LogDebug("call_type: SecurityModuleCall::GET_APP_DEFINED_PRIVILEGE_LICENSE");
+                    processGetAppDefinedPrivilegeLicense(buffer, send);
+                    break;
+                case SecurityModuleCall::GET_CLIENT_PRIVILEGE_LICENSE:
+                    LogDebug("call_type: SecurityModuleCall::GET_CLIENT_PRIVILEGE_PROVIDER");
+                    processGetClientPrivilegeLicense(buffer, send);
                     break;
                 default:
                     LogError("Invalid call: " << call_type_int);
@@ -424,19 +432,43 @@ void Service::processShmAppName(MessageBuffer &recv, MessageBuffer &send, const
     Serialization::Serialize(send, ret);
 }
 
-void Service::processGetPrivilegeProvider(MessageBuffer &buffer, MessageBuffer &send)
+void Service::processGetAppDefinedPrivilegeProvider(MessageBuffer &buffer, MessageBuffer &send)
 {
     int ret;
-    std::string privilege;
+    std::string privilege, appName, pkgName;
+    uid_t uid;
+
+    Deserialization::Deserialize(buffer, uid, privilege);
+    ret = serviceImpl.getAppDefinedPrivilegeProvider(uid, privilege, appName, pkgName);
+    Serialization::Serialize(send, ret);
+    if (ret == SECURITY_MANAGER_SUCCESS)
+        Serialization::Serialize(send, appName, pkgName);
+}
+
+void Service::processGetAppDefinedPrivilegeLicense(MessageBuffer &buffer, MessageBuffer &send)
+{
+    int ret;
+    std::string privilege, license;
+    uid_t uid;
+
+    Deserialization::Deserialize(buffer, uid, privilege);
+    ret = serviceImpl.getAppDefinedPrivilegeLicense(uid, privilege, license);
+    Serialization::Serialize(send, ret);
+    if (ret == SECURITY_MANAGER_SUCCESS)
+        Serialization::Serialize(send, license);
+}
+
+void Service::processGetClientPrivilegeLicense(MessageBuffer &buffer, MessageBuffer &send)
+{
+    int ret;
+    std::string appName, privilege, license;
     uid_t uid;
-    std::pair<std::string, std::string> provider;
 
-    Deserialization::Deserialize(buffer, privilege);
-    Deserialization::Deserialize(buffer, uid);
-    ret = serviceImpl.getPrivilegeProvider(privilege, uid, provider);
+    Deserialization::Deserialize(buffer, appName, uid, privilege);
+    ret = serviceImpl.getClientPrivilegeLicense(appName, uid, privilege, license);
     Serialization::Serialize(send, ret);
     if (ret == SECURITY_MANAGER_SUCCESS)
-        Serialization::Serialize(send, provider);
+        Serialization::Serialize(send, license);
 }
 
 } // namespace SecurityManager
index 6faf30ddd85bf4644072033e6907c2ed4c05ab8e..e111fa604614ae36f52e6d9b8fbfd54b0127fd0b 100644 (file)
@@ -33,19 +33,20 @@ namespace {
 
 struct AppDefinedPrivilegeFixture : public PrivilegeDBFixture {
     void checkAppDefinedPrivileges(const std::string &app, uid_t uid,
-                                   const PrivilegesVector &expected);
+                                   const AppDefinedPrivilegesVector &expected);
 };
 
 void AppDefinedPrivilegeFixture::checkAppDefinedPrivileges(const std::string &app, uid_t uid,
-                                                           const PrivilegesVector &expected)
+                                                           const AppDefinedPrivilegesVector &expected)
 {
-    PrivilegesVector privileges;
+    AppDefinedPrivilegesVector privileges;
     testPrivDb->GetAppDefinedPrivileges(app, uid, privileges);
     BOOST_REQUIRE_MESSAGE(privileges.size() == expected.size(), "Vector sizes differ");
 
     for (unsigned int i = 0; i < privileges.size(); ++i) {
-        BOOST_REQUIRE(privileges[i].first == expected[i].first);
-        BOOST_REQUIRE(privileges[i].second ==  expected[i].second);
+        BOOST_REQUIRE(std::get<0>(privileges[i]) == std::get<0>(expected[i]));
+        BOOST_REQUIRE(std::get<1>(privileges[i]) == std::get<1>(expected[i]));
+        BOOST_REQUIRE(std::get<2>(privileges[i]) == std::get<2>(expected[i]));
     }
 }
 
@@ -56,9 +57,13 @@ BOOST_FIXTURE_TEST_SUITE(PRIVILEGE_DB_TEST_APP_DEFINED_PRIVILEGES, AppDefinedPri
 BOOST_AUTO_TEST_CASE(T1300_app_defined_privileges)
 {
     // add some privileges
-    PrivilegesVector privileges;
-    privileges.push_back(std::make_pair("org.tizen.my_app.gps", SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED));
-    privileges.push_back(std::make_pair("org.tizen.my_app.sso", SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED));
+    AppDefinedPrivilegesVector privileges;
+    privileges.push_back(std::make_tuple("org.tizen.my_app.gps",
+                                         SM_APP_DEFINED_PRIVILEGE_TYPE_UNTRUSTED,
+                                         ""));
+    privileges.push_back(std::make_tuple("org.tizen.my_app.sso",
+                                         SM_APP_DEFINED_PRIVILEGE_TYPE_LICENSED,
+                                         "/opt/data/my_app/res/license"));
 
     // non-existing application
     checkAppDefinedPrivileges(app(1), uid(1), {});
@@ -77,16 +82,22 @@ BOOST_AUTO_TEST_CASE(T1300_app_defined_privileges)
     BOOST_REQUIRE_NO_THROW(testPrivDb->AddAppDefinedPrivilege(app(1), uid(1), privileges[0]));
 
     // check non-existing privilege
-    std::string appName;
-    BOOST_REQUIRE_NO_THROW(testPrivDb->GetAppForAppDefinedPrivilege(privileges[1], uid(1), appName));
+    std::string appName, license;
+    BOOST_REQUIRE_NO_THROW(
+        testPrivDb->GetAppAndLicenseForAppDefinedPrivilege(uid(1), std::get<0>(privileges[1]),
+                                                           appName, license));
     BOOST_REQUIRE(appName.empty());
+    BOOST_REQUIRE(license.empty());
 
     // first application defines second privilege
     BOOST_REQUIRE_NO_THROW(testPrivDb->AddAppDefinedPrivilege(app(1), uid(1), privileges[1]));
 
     // check existing privilege application name
-    BOOST_REQUIRE_NO_THROW(testPrivDb->GetAppForAppDefinedPrivilege(privileges[1], uid(1), appName));
+    BOOST_REQUIRE_NO_THROW(
+        testPrivDb->GetAppAndLicenseForAppDefinedPrivilege(uid(1), std::get<0>(privileges[1]),
+                                                           appName, license));
     BOOST_REQUIRE(appName == app(1));
+    BOOST_REQUIRE(license == std::get<2>(privileges[1]));
 
     // check first application privileges
     checkAppDefinedPrivileges(app(1), uid(1), privileges);