Implement and use template methods for serialization of multiple variables
[platform/core/security/security-manager.git] / src / client / client-security-manager.cpp
index 87b0a74..a995aa0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Contact: Rafal Krypa <r.krypa@samsung.com>
  *
@@ -26,6 +26,8 @@
  */
 
 #include <cstdio>
+#include <functional>
+#include <memory>
 #include <utility>
 
 #include <unistd.h>
@@ -44,6 +46,9 @@
 #include <client-common.h>
 #include <protocols.h>
 #include <service_impl.h>
+#include <connection.h>
+#include <zone-utils.h>
+
 #include <security-manager.h>
 #include <client-offline.h>
 
@@ -166,17 +171,13 @@ int security_manager_app_install(const app_inst_req *p_req)
         int retval;
         ClientOffline offlineMode;
         if (offlineMode.isOffline()) {
-            retval = SecurityManager::ServiceImpl::appInstall(*p_req, geteuid());
+            retval = SecurityManager::ServiceImpl::appInstall(*p_req, geteuid(), false);
         } else {
             MessageBuffer send, recv;
 
             //put data into buffer
-            Serialization::Serialize(send, (int)SecurityModuleCall::APP_INSTALL);
-            Serialization::Serialize(send, p_req->appId);
-            Serialization::Serialize(send, p_req->pkgId);
-            Serialization::Serialize(send, p_req->privileges);
-            Serialization::Serialize(send, p_req->appPaths);
-            Serialization::Serialize(send, p_req->uid);
+            Serialization::Serialize(send, (int)SecurityModuleCall::APP_INSTALL,
+                p_req->appId, p_req->pkgId, p_req->privileges, p_req->appPaths, p_req->uid);
 
             //send buffer to server
             retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
@@ -218,8 +219,8 @@ int security_manager_app_uninstall(const app_inst_req *p_req)
             return SECURITY_MANAGER_ERROR_REQ_NOT_COMPLETE;
 
         //put data into buffer
-        Serialization::Serialize(send, (int)SecurityModuleCall::APP_UNINSTALL);
-        Serialization::Serialize(send, p_req->appId);
+        Serialization::Serialize(send, (int)SecurityModuleCall::APP_UNINSTALL,
+            p_req->appId);
 
         //send buffer to server
         int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
@@ -259,8 +260,8 @@ int security_manager_get_app_pkgid(char **pkg_id, const char *app_id)
         }
 
         //put data into buffer
-        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_PKGID));
-        Serialization::Serialize(send, std::string(app_id));
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_PKGID),
+            std::string(app_id));
 
         //send buffer to server
         int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
@@ -363,7 +364,19 @@ int security_manager_set_process_label_from_appid(const char *app_id)
     if (smack_smackfs_path() == NULL)
         return SECURITY_MANAGER_SUCCESS;
 
-    if (SecurityManager::generateAppLabel(std::string(app_id), appLabel) == false) {
+    // FIXME Below modifications related to zones are temporary. Remove when Smack Namespaces
+    //       are implemented.
+    std::string zoneId;
+    if (!getZoneIdFromPid(getpid(), zoneId)) {
+        LogError("Failed to get ID of zone");
+        return SECURITY_MANAGER_ERROR_REQ_NOT_COMPLETE;
+    }
+
+    try {
+        appLabel = SecurityManager::zoneSmackLabelGenerate(
+                SecurityManager::SmackLabels::generateAppLabel(app_id), zoneId);
+
+    } catch (...) {
         LogError("Failed to generate smack label for appId: " << app_id);
         return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
     }
@@ -394,8 +407,8 @@ int security_manager_set_process_groups_from_appid(const char *app_id)
         }
 
         //put data into buffer
-        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_GROUPS));
-        Serialization::Serialize(send, std::string(app_id));
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_GROUPS),
+            std::string(app_id));
 
         //send buffer to server
         int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
@@ -562,16 +575,15 @@ int security_manager_user_add(const user_req *p_req)
         int retval;
         ClientOffline offlineMode;
         if (offlineMode.isOffline()) {
-            retval = SecurityManager::ServiceImpl::userAdd(p_req->uid, p_req->utype, geteuid());
+            retval = SecurityManager::ServiceImpl::userAdd(p_req->uid, p_req->utype, geteuid(),
+                                                           false);
         } else {
             MessageBuffer send, recv;
             //server is working
 
             //put data into buffer
-            Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::USER_ADD));
-
-            Serialization::Serialize(send, p_req->uid);
-            Serialization::Serialize(send, p_req->utype);
+            Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::USER_ADD),
+                p_req->uid, p_req->utype);
 
             //send buffer to server
             retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
@@ -604,10 +616,8 @@ int security_manager_user_delete(const user_req *p_req)
     return try_catch([&] {
 
         //put data into buffer
-        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::USER_DELETE));
-
-        Serialization::Serialize(send, p_req->uid);
-
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::USER_DELETE),
+            p_req->uid);
 
         //send buffer to server
         int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
@@ -665,8 +675,8 @@ int security_manager_policy_update_send(policy_update_req *p_req)
     return try_catch([&] {
 
         //put request into buffer
-        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::POLICY_UPDATE));
-        Serialization::Serialize(send, p_req->units);
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::POLICY_UPDATE),
+            p_req->units);
 
         //send it to server
         int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
@@ -706,8 +716,9 @@ static inline int security_manager_get_policy_internal(
 
     return try_catch([&] {
         //put request into buffer
-        Serialization::Serialize(send, static_cast<int>(call_type));
-        Serialization::Serialize(send, *p_filter);
+        Serialization::Serialize(send, static_cast<int>(call_type),
+            *p_filter);
+
         //send it to server
         int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
         if (retval != SECURITY_MANAGER_API_SUCCESS) {
@@ -716,13 +727,13 @@ static inline int security_manager_get_policy_internal(
         }
         //receive response from server
         Deserialization::Deserialize(recv, retval);
-        switch(retval) {
+        switch (retval) {
             case SECURITY_MANAGER_API_SUCCESS: {
                 //extract and allocate buffers for privs policy entries
                 int entriesCnt = 0;
                 policy_entry **entries = nullptr;
-                Deserialization::Deserialize(recv, entriesCnt);
                 try {
+                    Deserialization::Deserialize(recv, entriesCnt);
                     entries = new policy_entry*[entriesCnt]();
                     for (int i = 0; i < entriesCnt; ++i) {
                         entries[i] = new policy_entry;
@@ -732,7 +743,7 @@ static inline int security_manager_get_policy_internal(
                     LogError("Error while parsing server response");
                     for (int i = 0; i < entriesCnt; ++i)
                         delete(entries[i]);
-                    delete entries;
+                    delete[] entries;
                     return SECURITY_MANAGER_ERROR_UNKNOWN;
                 }
                 *p_size = entriesCnt;
@@ -859,44 +870,29 @@ int security_manager_policy_update_req_add_entry(policy_update_req *p_req, const
 SECURITY_MANAGER_API
 const char *security_manager_policy_entry_get_user(policy_entry *p_entry)
 {
-    if (p_entry)
-        return strdup(p_entry->user.c_str());
-    else
-        return nullptr;
+    return p_entry ? p_entry->user.c_str() : nullptr;
 }
 
 SECURITY_MANAGER_API
 const char *security_manager_policy_entry_get_application(policy_entry *p_entry)
 {
-    if (p_entry)
-        return strdup(p_entry->appId.c_str());
-    else
-        return nullptr;
+    return p_entry ? p_entry->appId.c_str() : nullptr;
 }
 SECURITY_MANAGER_API
 const char *security_manager_policy_entry_get_privilege(policy_entry *p_entry)
 {
-    if (p_entry)
-        return strdup(p_entry->privilege.c_str());
-    else
-        return nullptr;
+    return p_entry ? p_entry->privilege.c_str() : nullptr;
 }
 SECURITY_MANAGER_API
 const char *security_manager_policy_entry_get_level(policy_entry *p_entry)
 {
-    if (p_entry)
-        return strdup(p_entry->currentLevel.c_str());
-    else
-        return nullptr;
+    return p_entry ? p_entry->currentLevel.c_str() : nullptr;
 }
 
 SECURITY_MANAGER_API
 const char *security_manager_policy_entry_get_max_level(policy_entry *p_entry)
 {
-    if (p_entry)
-        return strdup(p_entry->maxLevel.c_str());
-    else
-        return nullptr;
+    return p_entry ? p_entry->maxLevel.c_str() : nullptr;
 }
 
 SECURITY_MANAGER_API
@@ -911,15 +907,245 @@ void security_manager_policy_entries_free(policy_entry *p_entries, const size_t
 SECURITY_MANAGER_API
 int security_manager_policy_levels_get(char ***levels, size_t *levels_count)
 {
-    (void)levels;
-    (void)levels_count;
+    using namespace SecurityManager;
+    MessageBuffer send, recv;
+    if (!levels || !levels_count)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    return try_catch([&] {
+
+        //put data into buffer
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::POLICY_GET_DESCRIPTIONS));
+
+        //send buffer to server
+        int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
+        if (retval != SECURITY_MANAGER_API_SUCCESS) {
+            LogError("Error in sendToServer. Error code: " << retval);
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        //receive response from server
+        Deserialization::Deserialize(recv, retval);
 
-    return 0;
+        switch(retval) {
+            case SECURITY_MANAGER_API_SUCCESS:
+                // success - continue
+                break;
+            case SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY:
+                return SECURITY_MANAGER_ERROR_MEMORY;
+            case SECURITY_MANAGER_API_ERROR_INPUT_PARAM:
+                return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+            default:
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        int count;
+        Deserialization::Deserialize(recv, count);
+        *levels_count = count;
+        LogInfo("Number of policy descriptions: " << *levels_count);
+
+        char **array = new char *[*levels_count];
+
+        for (unsigned int i = 0; i < *levels_count; ++i) {
+            std::string level;
+            Deserialization::Deserialize(recv, level);
+
+            if (level.empty()) {
+                LogError("Unexpected empty level");
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+            }
+
+            array[i] = strdup(level.c_str());
+            if (array[i] == nullptr)
+                return SECURITY_MANAGER_ERROR_MEMORY;
+        }
+
+        *levels = array;
+
+        return SECURITY_MANAGER_SUCCESS;
+    });
 }
 
 SECURITY_MANAGER_API
 void security_manager_policy_levels_free(char **levels, size_t levels_count)
 {
-    (void)levels;
-    (void)levels_count;
+    for (unsigned int i = 0; i < levels_count; i++)
+        free(levels[i]);
+
+    delete[] levels;
+}
+
+lib_retcode get_privileges_mapping(const std::string &from_version,
+                                   const std::string &to_version,
+                                   const std::vector<std::string> &privileges,
+                                   char ***privileges_mappings,
+                                   size_t *mappings_count)
+{
+    using namespace SecurityManager;
+    MessageBuffer send, recv;
+    Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::GET_PRIVILEGES_MAPPING));
+    Serialization::Serialize(send, from_version);
+    Serialization::Serialize(send, to_version);
+    Serialization::Serialize(send, privileges);
+
+    //send buffer to server
+    int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
+    if (retval != SECURITY_MANAGER_API_SUCCESS) {
+        LogError("Error in sendToServer. Error code: " << retval);
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
+    }
+
+    //receive response from server
+    Deserialization::Deserialize(recv, retval);
+
+    switch(retval) {
+        case SECURITY_MANAGER_API_SUCCESS:
+            // success - continue
+            break;
+        case SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY:
+            return SECURITY_MANAGER_ERROR_MEMORY;
+        case SECURITY_MANAGER_API_ERROR_INPUT_PARAM:
+            return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+        default:
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+    }
+
+    unsigned int count;
+    Deserialization::Deserialize(recv, count);
+    LogInfo("Number of privilege mappings: " << count);
+    size_t i = 0;
+    auto free_mapping = std::bind(security_manager_privilege_mapping_free,
+                                  std::placeholders::_1, std::ref(i));
+    std::unique_ptr<char *[], decltype (free_mapping)> mappings_ptr(new char *[count], free_mapping);
+
+    for (; i < count; ++i) {
+        std::string privilege_mapping;
+        Deserialization::Deserialize(recv, privilege_mapping);
+        if (privilege_mapping.empty()) {
+            LogError("Unexpected empty privilege mapping");
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        mappings_ptr.get()[i] = strdup(privilege_mapping.c_str());
+        if (mappings_ptr.get()[i] == nullptr)
+            return SECURITY_MANAGER_ERROR_MEMORY;
+    }
+
+    *privileges_mappings = mappings_ptr.release();
+    *mappings_count = count;
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_get_privileges_mapping(const char *from_version,
+                                             const char *to_version,
+                                             char const * const *privileges,
+                                             size_t privileges_count,
+                                             char ***privileges_mappings,
+                                             size_t *mappings_count)
+{
+    if (from_version == nullptr || privileges_mappings == nullptr || mappings_count == nullptr) {
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    }
+    return try_catch([&] {
+        std::vector<std::string> privilegesToMap;
+        if (privileges != nullptr) {
+            privilegesToMap.reserve(privileges_count);
+            privilegesToMap.insert(privilegesToMap.end(), privileges, privileges + privileges_count);
+        }
+        if (to_version == nullptr)
+            to_version = "";
+        LogDebug("security_manager_get_privileges_mapping() called with :"
+                 " from_version = " << from_version << " to_version = " << to_version <<
+                 " privileges_count " << privilegesToMap.size());
+
+        return get_privileges_mapping(from_version, to_version, privilegesToMap,
+                                      privileges_mappings, mappings_count);
+
+    });
+}
+SECURITY_MANAGER_API
+void security_manager_privilege_mapping_free(char **privileges_mappings, size_t mappings_count)
+{
+    for(size_t i = 0; i < mappings_count; i++)
+        free(privileges_mappings[i]);
+    delete [] privileges_mappings;
+}
+
+SECURITY_MANAGER_API
+int security_manager_groups_get(char ***groups, size_t *groups_count)
+{
+    using namespace SecurityManager;
+    MessageBuffer send, recv;
+    if (!groups || !groups_count)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    return try_catch([&] {
+
+        //put data into buffer
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::GROUPS_GET));
+
+        //send buffer to server
+        int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
+        if (retval != SECURITY_MANAGER_API_SUCCESS) {
+            LogError("Error in sendToServer. Error code: " << retval);
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        //receive response from server
+        Deserialization::Deserialize(recv, retval);
+
+        switch(retval) {
+            case SECURITY_MANAGER_API_SUCCESS:
+                // success - continue
+                break;
+            case SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY:
+                return SECURITY_MANAGER_ERROR_MEMORY;
+            case SECURITY_MANAGER_API_ERROR_INPUT_PARAM:
+                return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+            default:
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        std::vector<std::string> vgroups;
+        Deserialization::Deserialize(recv, vgroups);
+        const auto vgroups_size = vgroups.size();
+        LogInfo("Number of groups: " << vgroups_size);
+
+        std::unique_ptr<char *, std::function<void(char **)>> array(
+            static_cast<char **>(calloc(vgroups_size, sizeof(char *))),
+            std::bind(security_manager_groups_free, std::placeholders::_1, vgroups_size));
+
+        if (array == nullptr)
+            return SECURITY_MANAGER_ERROR_MEMORY;
+
+        for (size_t i = 0; i < vgroups_size; ++i) {
+            const auto &group = vgroups.at(i);
+
+            if (group.empty()) {
+                LogError("Unexpected empty group");
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+            }
+
+            array.get()[i] = strdup(group.c_str());
+            if (array.get()[i] == nullptr)
+                return SECURITY_MANAGER_ERROR_MEMORY;
+        }
+
+        *groups_count = vgroups_size;
+        *groups = array.release();
+
+        return SECURITY_MANAGER_SUCCESS;
+    });
+}
+
+SECURITY_MANAGER_API
+void security_manager_groups_free(char **groups, size_t groups_count)
+{
+    if (groups == nullptr)
+        return;
+
+    for (size_t i = 0; i < groups_count; i++)
+        free(groups[i]);
+
+    free(groups);
 }