Add API for getting privilege provider 93/118893/4
authorDariusz Michaluk <d.michaluk@samsung.com>
Mon, 13 Mar 2017 14:12:18 +0000 (15:12 +0100)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 15 Mar 2017 15:28:56 +0000 (16:28 +0100)
Change-Id: Ide1db72fc1338947dc6d8ce6c835dd5e42aad340

src/client/client-security-manager.cpp
src/common/include/protocols.h
src/common/include/service_impl.h
src/common/service_impl.cpp
src/include/app-runtime.h
src/server/service/include/service.h
src/server/service/service.cpp

index 792c03612c72b8bbda0b9a62bfb2ba53074200e5..6366ab6ef3fc15dd7528f4959e46af6910263986 100644 (file)
@@ -1589,3 +1589,48 @@ int security_manager_shm_open(const char *name, int oflag, mode_t mode, const ch
         return -1;
     });
 }
+
+SECURITY_MANAGER_API
+int security_manager_identify_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 (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())
+            return request.getStatus();
+
+        std::pair<std::string, std::string> provider;
+        request.recv(provider);
+        std::string appNameString = provider.first;
+        std::string pkgNameString = provider.second;
+
+        if (appNameString.empty() || pkgNameString.empty()) {
+            LogError("Unexpected empty appName or pkgName");
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        if (app_name && !(*app_name = strdup(appNameString.c_str()))) {
+            LogError("Memory allocation in strdup failed.");
+            return SECURITY_MANAGER_ERROR_MEMORY;
+        }
+
+        if (pkg_name && !(*pkg_name = strdup(pkgNameString.c_str()))) {
+            LogError("Memory allocation in strdup failed.");
+            if (app_name) {
+                free(*app_name);
+                *app_name = NULL;
+            }
+            return SECURITY_MANAGER_ERROR_MEMORY;
+        }
+
+        return SECURITY_MANAGER_SUCCESS;
+    });
+}
\ No newline at end of file
index d2f57dee825fbf120e1d27ffd7c175f134addc98..76dba456cf542cc24652fb20654b4c8539eedb4c 100644 (file)
@@ -89,6 +89,7 @@ enum class SecurityModuleCall
     GROUPS_FOR_UID,
     LABEL_FOR_PROCESS,
     SHM_APP_NAME,
+    GET_PRIVILEGE_PROVIDER,
     NOOP = 0x90,
 };
 
index 609df3975b7f8761bdfb62717be3fe76ef3f4845..ab0ad0365aa2bcb955331c3f9b6da51e5a6176d9 100644 (file)
@@ -247,6 +247,19 @@ public:
     int shmAppName(const Credentials &creds,
                    const std::string &shmName,
                    const std::string &appName);
+
+    /**
+     * Retrieves the app_id/pkg_id associated with given privilege and uid.
+     *
+     * @param[in]  privilege privilege name
+     * @param[in]  uid       user identifier
+     * @param[out] provider  returned pair of app_id and pkg_id
+     *
+     * @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);
+
 private:
     bool authenticate(const Credentials &creds, const std::string &privilege);
 
index 6982b0852a4ce29e1315f732b8a4d0b4b5aa0e4f..08d8cd3b1cc08eed3d46b59ea43c28ecff009aef 100644 (file)
@@ -1692,4 +1692,26 @@ 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)
+{
+    std::string appName, pkgName;
+    try {
+        m_privilegeDb.GetAppForAppDefinedPrivilege(std::make_pair(privilege, 0), uid, appName);
+        m_privilegeDb.GetAppPkgName(appName, pkgName);
+        if (appName.empty() || pkgName.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);
+        }
+    } 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);
+    return SECURITY_MANAGER_SUCCESS;
+}
+
 } /* namespace SecurityManager */
index 6e1f03b3493b4861d6f87c00188c20902407355b..207737486665c857afc1f9127d6ce0846bd1ccdc 100644 (file)
@@ -219,6 +219,25 @@ 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
+ *
+ * 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.
+ * Either app_id or pkg_id may be NULL. NULL-ed argument will be ignored.
+ * If both app_id and pkg_id are NULL then SECURITY_MANAGER_ERROR_INPUT_PARAM will be returned.
+ * When privilege/uid is incorrect or not related to any package, this function will
+ * return SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT.
+ *
+ * \param[in]   privilege  Privilege name
+ * \param[in]   uid        User identifier
+ * \param[out]  pkg_id     Package id of the provider application
+ * \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);
+
 #ifdef __cplusplus
 }
 #endif
index 90c8ed8d93bd596c1e55b71ba580eb828ce7e141..537dc6fd7a097d2b27654ee64a4f864bcb2f7d45 100644 (file)
@@ -202,6 +202,14 @@ private:
      * @param  creds  credentials of the requesting process
      */
     void processShmAppName(MessageBuffer &recv, MessageBuffer &send, const Credentials &creds);
+
+    /**
+     * Process getting provider(app_id, pkg_id) of privilege
+     *
+     * @param  buffer Raw received data buffer
+     * @param  send   Raw data buffer to be sent
+     */
+    void processGetPrivilegeProvider(MessageBuffer &buffer, MessageBuffer &send);
 };
 
 } // namespace SecurityManager
index e28c600344a730491cbaf4e1171c0ec064e27fb6..ef78f45a551971c3542a4310fdcb096ba3aecb5e 100644 (file)
@@ -150,6 +150,10 @@ 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);
+                    break;
                 default:
                     LogError("Invalid call: " << call_type_int);
                     Throw(ServiceException::InvalidAction);
@@ -420,4 +424,19 @@ void Service::processShmAppName(MessageBuffer &recv, MessageBuffer &send, const
     Serialization::Serialize(send, ret);
 }
 
+void Service::processGetPrivilegeProvider(MessageBuffer &buffer, MessageBuffer &send)
+{
+    int ret;
+    std::string privilege;
+    uid_t uid;
+    std::pair<std::string, std::string> provider;
+
+    Deserialization::Deserialize(buffer, privilege);
+    Deserialization::Deserialize(buffer, uid);
+    ret = serviceImpl.getPrivilegeProvider(privilege, uid, provider);
+    Serialization::Serialize(send, ret);
+    if (ret == SECURITY_MANAGER_SUCCESS)
+        Serialization::Serialize(send, provider);
+}
+
 } // namespace SecurityManager