Extract communication functions to common library
[platform/core/security/security-manager.git] / src / client / client-security-manager.cpp
index 5f84f16..4d6fecb 100644 (file)
@@ -19,7 +19,8 @@
  */
 /*
  * @file        client-security-manager.cpp
- * @author      Pawel Polawski (p.polawski@samsung.com)
+ * @author      Pawel Polawski <p.polawski@samsung.com>
+ * @author      Rafal Krypa <r.krypa@samsung.com>
  * @version     1.0
  * @brief       This file contain client side implementation of security-manager API
  */
 #include <cstdio>
 #include <utility>
 
+#include <unistd.h>
+#include <grp.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/xattr.h>
 #include <sys/smack.h>
+#include <sys/capability.h>
 
 #include <dpl/log/log.h>
 #include <dpl/exception.h>
-
+#include <smack-labels.h>
 #include <message-buffer.h>
 #include <client-common.h>
 #include <protocols.h>
-#include <smack-common.h>
+#include <service_impl.h>
+#include <connection.h>
 
 #include <security-manager.h>
+#include <client-offline.h>
+
+static const char *EMPTY = "";
 
+/**
+ * Mapping of lib_retcode error codes to theirs strings equivalents
+ */
+static std::map<enum lib_retcode, std::string> lib_retcode_string_map = {
+    {SECURITY_MANAGER_SUCCESS, "Success"},
+    {SECURITY_MANAGER_ERROR_UNKNOWN, "Unknown error"},
+    {SECURITY_MANAGER_ERROR_INPUT_PARAM, "Invalid function parameter was given"},
+    {SECURITY_MANAGER_ERROR_MEMORY, "Memory allocation error"},
+    {SECURITY_MANAGER_ERROR_REQ_NOT_COMPLETE, "Incomplete data in application request"},
+    {SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED, "User does not have sufficient "
+                                                   "rigths to perform an operation"},
+    {SECURITY_MANAGER_ERROR_ACCESS_DENIED, "Insufficient privileges"},
+};
 
+SECURITY_MANAGER_API
+const char *security_manager_strerror(enum lib_retcode rc)
+{
+    try {
+        return lib_retcode_string_map.at(rc).c_str();
+    } catch (const std::out_of_range &e) {
+        return "Unknown error code";
+    }
+}
 
 SECURITY_MANAGER_API
 int security_manager_app_inst_req_new(app_inst_req **pp_req)
@@ -52,7 +86,7 @@ int security_manager_app_inst_req_new(app_inst_req **pp_req)
     } catch (std::bad_alloc& ex) {
         return SECURITY_MANAGER_ERROR_MEMORY;
     }
-
+    (*pp_req)->uid = geteuid();
 
     return SECURITY_MANAGER_SUCCESS;
 }
@@ -64,6 +98,18 @@ void security_manager_app_inst_req_free(app_inst_req *p_req)
 }
 
 SECURITY_MANAGER_API
+int security_manager_app_inst_req_set_uid(app_inst_req *p_req,
+                                          const uid_t uid)
+{
+    if (!p_req)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    p_req->uid = uid;
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
 int security_manager_app_inst_req_set_app_id(app_inst_req *p_req, const char *app_id)
 {
     if (!p_req || !app_id)
@@ -111,7 +157,6 @@ SECURITY_MANAGER_API
 int security_manager_app_install(const app_inst_req *p_req)
 {
     using namespace SecurityManager;
-    MessageBuffer send, recv;
 
     return try_catch([&] {
         //checking parameters
@@ -120,27 +165,40 @@ int security_manager_app_install(const app_inst_req *p_req)
         if (p_req->appId.empty() || p_req->pkgId.empty())
             return SECURITY_MANAGER_ERROR_REQ_NOT_COMPLETE;
 
-        //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);
+        int retval;
+        ClientOffline offlineMode;
+        if (offlineMode.isOffline()) {
+            retval = SecurityManager::ServiceImpl::appInstall(*p_req, geteuid());
+        } 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);
+
+            //send buffer to server
+            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;
+            }
 
-        //send buffer to server
-        int retval = sendToServer(SERVICE_SOCKET_INSTALLER, 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);
         }
-
-        //receive response from server
-        Deserialization::Deserialize(recv, retval);
         switch(retval) {
             case SECURITY_MANAGER_API_SUCCESS:
                 return SECURITY_MANAGER_SUCCESS;
             case SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED:
                 return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
+            case SECURITY_MANAGER_API_ERROR_ACCESS_DENIED:
+                return SECURITY_MANAGER_ERROR_ACCESS_DENIED;
+            case SECURITY_MANAGER_API_ERROR_INPUT_PARAM:
+                return SECURITY_MANAGER_ERROR_INPUT_PARAM;
             default:
                 return SECURITY_MANAGER_ERROR_UNKNOWN;
         }
@@ -166,7 +224,7 @@ int security_manager_app_uninstall(const app_inst_req *p_req)
         Serialization::Serialize(send, p_req->appId);
 
         //send buffer to server
-        int retval = sendToServer(SERVICE_SOCKET_INSTALLER, send.Pop(), recv);
+        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;
@@ -207,7 +265,7 @@ int security_manager_get_app_pkgid(char **pkg_id, const char *app_id)
         Serialization::Serialize(send, std::string(app_id));
 
         //send buffer to server
-        int retval = sendToServer(SERVICE_SOCKET_INSTALLER, send.Pop(), recv);
+        int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
         if (retval != SECURITY_MANAGER_API_SUCCESS) {
             LogDebug("Error in sendToServer. Error code: " << retval);
             return SECURITY_MANAGER_ERROR_UNKNOWN;
@@ -235,38 +293,70 @@ int security_manager_get_app_pkgid(char **pkg_id, const char *app_id)
     });
 }
 
-SECURITY_MANAGER_API
-int security_manager_set_process_label_from_binary(const char *path)
+static bool setup_smack(const char *label)
 {
-    char *smack_label;
-    int ret;
+    int labelSize = strlen(label);
 
-    LogDebug("security_manager_set_process_label_from_binary() called");
+    // Set Smack label for open socket file descriptors
 
-    if (smack_smackfs_path() == NULL)
-        return SECURITY_MANAGER_SUCCESS;
-
-    if (path == NULL) {
-        LogError("security_manager_set_process_label_from_binary: path is NULL");
-        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    std::unique_ptr<DIR, std::function<int(DIR*)>> dir(
+        opendir("/proc/self/fd"), closedir);
+    if (!dir.get()) {
+        LogError("Unable to read list of open file descriptors: " <<
+            strerror(errno));
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
     }
 
-    ret = SecurityManager::getSmackLabelFromBinary(&smack_label, path);
-    if (ret == SECURITY_MANAGER_SUCCESS && smack_label != NULL) {
-        if (smack_set_label_for_self(smack_label) != 0) {
-            ret = SECURITY_MANAGER_ERROR_UNKNOWN;
-            LogError("Failed to set smack label " << smack_label << " for current process");
+    do {
+        errno = 0;
+        struct dirent *dirEntry = readdir(dir.get());
+        if (dirEntry == nullptr) {
+            if (errno == 0) // NULL return value also signals end of directory
+                break;
+
+            LogError("Unable to read list of open file descriptors: " <<
+                strerror(errno));
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        // Entries with numerical names specify file descriptors, ignore the rest
+        if (!isdigit(dirEntry->d_name[0]))
+            continue;
+
+        struct stat statBuf;
+        int fd = atoi(dirEntry->d_name);
+        int ret = fstat(fd, &statBuf);
+        if (ret != 0) {
+            LogWarning("fstat failed on file descriptor " << fd << ": " <<
+                strerror(errno));
+            continue;
         }
-        free(smack_label);
-    }
+        if (S_ISSOCK(statBuf.st_mode)) {
+            ret = fsetxattr(fd, XATTR_NAME_SMACKIPIN, label, labelSize, 0);
+            if (ret != 0) {
+                LogError("Setting Smack label failed on file descriptor " <<
+                    fd << ": " << strerror(errno));
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+            }
 
-    return ret;
+            ret = fsetxattr(fd, XATTR_NAME_SMACKIPOUT, label, labelSize, 0);
+            if (ret != 0) {
+                LogError("Setting Smack label failed on file descriptor " <<
+                    fd << ": " << strerror(errno));
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+            }
+        }
+    } while (true);
+
+    // Set Smack label of current process
+    smack_set_label_for_self(label);
+
+    return SECURITY_MANAGER_SUCCESS;
 }
 
 SECURITY_MANAGER_API
 int security_manager_set_process_label_from_appid(const char *app_id)
 {
-    char *pkg_id;
     int ret;
     std::string appLabel;
 
@@ -275,23 +365,604 @@ int security_manager_set_process_label_from_appid(const char *app_id)
     if (smack_smackfs_path() == NULL)
         return SECURITY_MANAGER_SUCCESS;
 
-    ret = security_manager_get_app_pkgid(&pkg_id, app_id);
-    if (ret != SECURITY_MANAGER_SUCCESS) {
+    try {
+        appLabel = SecurityManager::SmackLabels::generateAppLabel(app_id);
+    } catch (...) {
+        LogError("Failed to generate smack label for appId: " << app_id);
+        return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
+    }
+
+    if ((ret = setup_smack(appLabel.c_str())) != SECURITY_MANAGER_SUCCESS) {
+        LogError("Failed to set smack label " << appLabel << " for current process");
         return ret;
     }
 
-    if (SecurityManager::generateAppLabel(std::string(pkg_id), appLabel)) {
-        if (smack_set_label_for_self(appLabel.c_str()) != 0) {
-            LogError("Failed to set smack label " << appLabel << " for current process");
-            ret = SECURITY_MANAGER_ERROR_UNKNOWN;
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_set_process_groups_from_appid(const char *app_id)
+{
+    using namespace SecurityManager;
+    MessageBuffer send, recv;
+    int ret;
+
+    LogDebug("security_manager_set_process_groups_from_appid() called");
+
+    return try_catch([&] {
+        //checking parameters
+
+        if (app_id == nullptr) {
+            LogError("app_id is NULL");
+            return SECURITY_MANAGER_ERROR_INPUT_PARAM;
         }
+
+        //put data into buffer
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::APP_GET_GROUPS));
+        Serialization::Serialize(send, std::string(app_id));
+
+        //send buffer to server
+        int retval = sendToServer(SERVICE_SOCKET, send.Pop(), recv);
+        if (retval != SECURITY_MANAGER_API_SUCCESS) {
+            LogDebug("Error in sendToServer. Error code: " << retval);
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        //receive response from server
+        Deserialization::Deserialize(recv, retval);
+        if (retval != SECURITY_MANAGER_API_SUCCESS) {
+            LogError("Failed to get list of groups from security-manager service. Error code: " << retval);
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        //How many new groups?
+        int newGroupsCnt;
+        Deserialization::Deserialize(recv, newGroupsCnt);
+
+        //And how many groups do we belong to already?
+        int oldGroupsCnt;
+        ret = getgroups(0, nullptr);
+        if (ret == -1) {
+            LogError("Unable to get list of current supplementary groups: " <<
+                strerror(errno));
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+        oldGroupsCnt = ret;
+
+        //Allocate an array for both old and new groups gids
+        std::unique_ptr<gid_t[]> groups(new gid_t[oldGroupsCnt + newGroupsCnt]);
+        if (!groups.get()) {
+            LogError("Memory allocation failed.");
+            return SECURITY_MANAGER_ERROR_MEMORY;
+        }
+
+        //Get the old groups from process
+        ret = getgroups(oldGroupsCnt, groups.get());
+        if (ret == -1) {
+            LogError("Unable to get list of current supplementary groups: " <<
+                strerror(errno));
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        //Get the new groups from server response
+        for (int i = 0; i < newGroupsCnt; ++i) {
+            gid_t gid;
+            Deserialization::Deserialize(recv, gid);
+            groups.get()[oldGroupsCnt + i] = gid;
+            LogDebug("Adding process to group " << gid);
+        }
+
+        //Apply the modified groups list
+        ret = setgroups(oldGroupsCnt + newGroupsCnt, groups.get());
+        if (ret == -1) {
+            LogError("Unable to get list of current supplementary groups: " <<
+                strerror(errno));
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+
+        return SECURITY_MANAGER_SUCCESS;
+    });
+}
+
+SECURITY_MANAGER_API
+int security_manager_drop_process_privileges(void)
+{
+    LogDebug("security_manager_drop_process_privileges() called");
+
+    int ret;
+    cap_t cap = cap_init();
+    if (!cap) {
+        LogError("Unable to allocate capability object");
+        return SECURITY_MANAGER_ERROR_MEMORY;
+    }
+
+    ret = cap_clear(cap);
+    if (ret) {
+        LogError("Unable to initialize capability object");
+        cap_free(cap);
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
+    }
+
+    ret = cap_set_proc(cap);
+    if (ret) {
+        LogError("Unable to drop process capabilities");
+        cap_free(cap);
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
     }
-    else {
-        ret = SECURITY_MANAGER_ERROR_UNKNOWN;
+
+    cap_free(cap);
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_prepare_app(const char *app_id)
+{
+    LogDebug("security_manager_prepare_app() called");
+    int ret;
+
+    ret = security_manager_set_process_label_from_appid(app_id);
+    if (ret != SECURITY_MANAGER_SUCCESS)
+        return ret;
+
+    ret = security_manager_set_process_groups_from_appid(app_id);
+    if (ret != SECURITY_MANAGER_SUCCESS) {
+        LogWarning("Unable to setup process groups for application. Privileges with direct access to resources will not work.");
+        ret = SECURITY_MANAGER_SUCCESS;
     }
 
-    free(pkg_id);
+    ret = security_manager_drop_process_privileges();
     return ret;
 }
 
+SECURITY_MANAGER_API
+int security_manager_user_req_new(user_req **pp_req)
+{
+    if (!pp_req)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    try {
+        *pp_req = new user_req;
+    } catch (std::bad_alloc& ex) {
+        return SECURITY_MANAGER_ERROR_MEMORY;
+    }
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+void security_manager_user_req_free(user_req *p_req)
+{
+    delete p_req;
+}
+
+SECURITY_MANAGER_API
+int security_manager_user_req_set_uid(user_req *p_req, uid_t uid)
+{
+    if (!p_req)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    p_req->uid = uid;
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_user_req_set_user_type(user_req *p_req, security_manager_user_type utype)
+{
+    if (!p_req)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    p_req->utype = static_cast<int>(utype);
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_user_add(const user_req *p_req)
+{
+    using namespace SecurityManager;
+    if (!p_req)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    return try_catch([&] {
+        int retval;
+        ClientOffline offlineMode;
+        if (offlineMode.isOffline()) {
+            retval = SecurityManager::ServiceImpl::userAdd(p_req->uid, p_req->utype, geteuid());
+        } 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);
+
+            //send buffer to server
+            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:
+            return SECURITY_MANAGER_SUCCESS;
+        case SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED:
+            return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
+        default:
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+    });
+}
 
+SECURITY_MANAGER_API
+int security_manager_user_delete(const user_req *p_req)
+{
+    using namespace SecurityManager;
+    MessageBuffer send, recv;
+    if (!p_req)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    return try_catch([&] {
+
+        //put data into buffer
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::USER_DELETE));
+
+        Serialization::Serialize(send, p_req->uid);
+
+
+        //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:
+            return SECURITY_MANAGER_SUCCESS;
+        case SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED:
+            return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
+        default:
+            return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+    });
+}
+
+
+/***************************POLICY***************************************/
+
+SECURITY_MANAGER_API
+int security_manager_policy_update_req_new(policy_update_req **pp_req)
+{
+    if (!pp_req)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    try {
+        *pp_req = new policy_update_req;
+    } catch (std::bad_alloc& ex) {
+        return SECURITY_MANAGER_ERROR_MEMORY;
+    }
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+void security_manager_policy_update_req_free(policy_update_req *p_req)
+{
+    delete p_req;
+}
+
+SECURITY_MANAGER_API
+int security_manager_policy_update_send(policy_update_req *p_req)
+{
+    using namespace SecurityManager;
+    MessageBuffer send, recv;
+
+    if (p_req == nullptr || p_req->units.size() == 0)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    return try_catch([&] {
+
+        //put request into buffer
+        Serialization::Serialize(send, static_cast<int>(SecurityModuleCall::POLICY_UPDATE));
+        Serialization::Serialize(send, p_req->units);
+
+        //send it 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:
+                return SECURITY_MANAGER_SUCCESS;
+            case SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED:
+                return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
+            case SECURITY_MANAGER_API_ERROR_ACCESS_DENIED:
+                return SECURITY_MANAGER_ERROR_ACCESS_DENIED;
+            default:
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+    });
+}
+
+static inline int security_manager_get_policy_internal(
+        SecurityManager::SecurityModuleCall call_type,
+        policy_entry *p_filter,
+        policy_entry ***ppp_privs_policy,
+        size_t *p_size)
+{
+    using namespace SecurityManager;
+    MessageBuffer send, recv;
+
+    if (ppp_privs_policy == nullptr
+        || p_size == nullptr
+        || p_filter == nullptr)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    return try_catch([&] {
+        //put request into buffer
+        Serialization::Serialize(send, static_cast<int>(call_type));
+        Serialization::Serialize(send, *p_filter);
+        //send it 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: {
+                //extract and allocate buffers for privs policy entries
+                int entriesCnt = 0;
+                policy_entry **entries = nullptr;
+                try {
+                    Deserialization::Deserialize(recv, entriesCnt);
+                    entries = new policy_entry*[entriesCnt]();
+                    for (int i = 0; i < entriesCnt; ++i) {
+                        entries[i] = new policy_entry;
+                        Deserialization::Deserialize(recv, entries[i]);
+                    };
+                } catch (...) {
+                    LogError("Error while parsing server response");
+                    for (int i = 0; i < entriesCnt; ++i)
+                        delete(entries[i]);
+                    delete[] entries;
+                    return SECURITY_MANAGER_ERROR_UNKNOWN;
+                }
+                *p_size = entriesCnt;
+                *ppp_privs_policy = entries;
+                return SECURITY_MANAGER_SUCCESS;
+            }
+            case SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED:
+                return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
+
+            case SECURITY_MANAGER_API_ERROR_ACCESS_DENIED:
+                return SECURITY_MANAGER_ERROR_ACCESS_DENIED;
+
+            default:
+                return SECURITY_MANAGER_ERROR_UNKNOWN;
+        }
+    });
+}
+
+SECURITY_MANAGER_API
+int security_manager_get_configured_policy_for_admin(
+        policy_entry *p_filter,
+        policy_entry ***ppp_privs_policy,
+        size_t *p_size)
+{
+    return security_manager_get_policy_internal(SecurityModuleCall::GET_CONF_POLICY_ADMIN, p_filter, ppp_privs_policy, p_size);
+}
+
+SECURITY_MANAGER_API
+int security_manager_get_configured_policy_for_self(
+        policy_entry *p_filter,
+        policy_entry ***ppp_privs_policy,
+        size_t *p_size)
+{
+    return security_manager_get_policy_internal(SecurityModuleCall::GET_CONF_POLICY_SELF, p_filter, ppp_privs_policy, p_size);
+}
+
+SECURITY_MANAGER_API
+int security_manager_get_policy(
+        policy_entry *p_filter,
+        policy_entry ***ppp_privs_policy,
+        size_t *p_size)
+{
+    return security_manager_get_policy_internal(SecurityModuleCall::GET_POLICY, p_filter, ppp_privs_policy, p_size);
+};
+
+SECURITY_MANAGER_API
+int security_manager_policy_entry_new(policy_entry **p_entry)
+{
+    if (!p_entry)
+        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
+
+    try {
+        *p_entry = new policy_entry;
+    } catch (std::bad_alloc& ex) {
+        return SECURITY_MANAGER_ERROR_MEMORY;
+    }
+
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+void security_manager_policy_entry_free(policy_entry *p_entry)
+{
+    delete p_entry;
+}
+
+SECURITY_MANAGER_API
+int security_manager_policy_entry_set_application(policy_entry *p_entry, const char *app_id)
+{
+    if (!p_entry)
+        return  SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    p_entry->appId = app_id;
+    return  SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_policy_entry_set_user(policy_entry *p_entry, const char *user)
+{
+    if (!p_entry)
+        return  SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    p_entry->user = user;
+    return  SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_policy_entry_set_privilege(policy_entry *p_entry, const char *privilege)
+{
+    if (!p_entry)
+        return  SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    p_entry->privilege = privilege;
+    return  SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_policy_entry_set_level(policy_entry *p_entry, const char *policy_level)
+{
+    if (!p_entry)
+        return  SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    p_entry->currentLevel = policy_level;
+    p_entry->maxLevel = EMPTY;
+    return  SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_policy_entry_admin_set_level(policy_entry *p_entry, const char *policy_level)
+{
+    if (!p_entry)
+        return  SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    p_entry->maxLevel = policy_level;
+    p_entry->currentLevel = EMPTY;
+    return  SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+int security_manager_policy_update_req_add_entry(policy_update_req *p_req, const policy_entry *p_entry)
+{
+    if (!p_entry || !p_req)
+        return  SECURITY_MANAGER_ERROR_INPUT_PARAM;
+    p_req->units.push_back(p_entry);
+
+    return  SECURITY_MANAGER_SUCCESS;
+}
+
+SECURITY_MANAGER_API
+const char *security_manager_policy_entry_get_user(policy_entry *p_entry)
+{
+    return p_entry ? p_entry->user.c_str() : nullptr;
+}
+
+SECURITY_MANAGER_API
+const char *security_manager_policy_entry_get_application(policy_entry *p_entry)
+{
+    return p_entry ? p_entry->appId.c_str() : nullptr;
+}
+SECURITY_MANAGER_API
+const char *security_manager_policy_entry_get_privilege(policy_entry *p_entry)
+{
+    return p_entry ? p_entry->privilege.c_str() : nullptr;
+}
+SECURITY_MANAGER_API
+const char *security_manager_policy_entry_get_level(policy_entry *p_entry)
+{
+    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)
+{
+    return p_entry ? p_entry->maxLevel.c_str() : nullptr;
+}
+
+SECURITY_MANAGER_API
+void security_manager_policy_entries_free(policy_entry *p_entries, const size_t size)
+{
+    for (size_t i = 0; i < size; i++) {
+        delete &p_entries[i];
+    }
+    delete [] p_entries;
+}
+
+SECURITY_MANAGER_API
+int security_manager_policy_levels_get(char ***levels, size_t *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);
+
+        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)
+{
+    for (unsigned int i = 0; i < levels_count; i++)
+        free(levels[i]);
+
+    delete[] levels;
+}