Rewrite and fix CynaraAdmin::SetPolicies
[platform/core/security/security-manager.git] / src / common / service_impl.cpp
index feedde5..fb0a0e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Contact: Rafal Krypa <r.krypa@samsung.com>
  *
@@ -27,6 +27,7 @@
 #include <grp.h>
 #include <limits.h>
 #include <pwd.h>
+#include <sys/socket.h>
 
 #include <cstring>
 #include <algorithm>
 #include <dpl/log/log.h>
 #include <tzplatform_config.h>
 
+#include <config.h>
 #include "protocols.h"
 #include "privilege_db.h"
 #include "cynara.h"
 #include "smack-rules.h"
 #include "smack-labels.h"
 #include "security-manager.h"
+#include "zone-utils.h"
 
 #include "service_impl.h"
+#include "master-req.h"
 
 namespace SecurityManager {
-namespace ServiceImpl {
 
 static const std::string ADMIN_PRIVILEGE = "http://tizen.org/privilege/systemsettings.admin";
 static const std::string SELF_PRIVILEGE = "http://tizen.org/privilege/systemsettings";
@@ -64,7 +67,6 @@ static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr,
         policyEntry.user = uidStr;
     };
 
-    std::string client;
     int level;
 
     if (policyEntry.currentLevel.empty()) { //for admin
@@ -116,13 +118,10 @@ static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr,
         policyEntry.user = CYNARA_ADMIN_WILDCARD;
     if (!policyEntry.privilege.compare(SECURITY_MANAGER_ANY))
         policyEntry.privilege = CYNARA_ADMIN_WILDCARD;
-    if (policyEntry.appId.compare(SECURITY_MANAGER_ANY))
-        generateAppLabel(policyEntry.appId, client);
-    else
-        client = CYNARA_ADMIN_WILDCARD;
 
     cyap = std::move(CynaraAdminPolicy(
-        client,
+        policyEntry.appId.compare(SECURITY_MANAGER_ANY) ?
+            SmackLabels::generateAppLabel(policyEntry.appId) : CYNARA_ADMIN_WILDCARD,
         policyEntry.user,
         policyEntry.privilege,
         level,
@@ -133,7 +132,15 @@ static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr,
 }
 } // end of anonymous namespace
 
-static uid_t getGlobalUserId(void)
+ServiceImpl::ServiceImpl()
+{
+}
+
+ServiceImpl::~ServiceImpl()
+{
+}
+
+uid_t ServiceImpl::getGlobalUserId(void)
 {
     static uid_t globaluid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
     return globaluid;
@@ -144,7 +151,7 @@ static uid_t getGlobalUserId(void)
  * @param  uid            peer's uid - may be changed during process
  * @param  cynaraUserStr  string to which cynara user parameter will be put
  */
-static void checkGlobalUser(uid_t &uid, std::string &cynaraUserStr)
+void ServiceImpl::checkGlobalUser(uid_t &uid, std::string &cynaraUserStr)
 {
     static uid_t globaluid = getGlobalUserId();
     if (uid == 0 || uid == globaluid) {
@@ -154,36 +161,67 @@ static void checkGlobalUser(uid_t &uid, std::string &cynaraUserStr)
         cynaraUserStr = std::to_string(static_cast<unsigned int>(uid));
     }
 }
-static inline bool isSubDir(const char *parent, const char *subdir)
+
+bool ServiceImpl::isSubDir(const char *parent, const char *subdir)
 {
     while (*parent && *subdir)
         if (*parent++ != *subdir++)
             return false;
 
-    return (*subdir == '/');
+    return (*subdir == '/' || *parent == *subdir);
 }
 
-static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
+bool ServiceImpl::getUserAppDir(const uid_t &uid, std::string &userAppDir)
 {
-    struct passwd *pwd;
-    do {
-        errno = 0;
-        pwd = getpwuid(uid);
-        if (!pwd && errno != EINTR) {
-            LogError("getpwuid failed with '" << uid
-                    << "' as parameter: " << strerror(errno));
-            return false;
-        }
-    } while (!pwd);
+    struct tzplatform_context *tz_ctx = nullptr;
 
-    std::unique_ptr<char, std::function<void(void*)>> home(
-        realpath(pwd->pw_dir, NULL), free);
-    if (!home.get()) {
-            LogError("realpath failed with '" << pwd->pw_dir
-                    << "' as parameter: " << strerror(errno));
+    if (tzplatform_context_create(&tz_ctx))
             return false;
+
+    if (tzplatform_context_set_user(tz_ctx, uid)) {
+        tzplatform_context_destroy(tz_ctx);
+        tz_ctx = nullptr;
+        return false;
     }
 
+    enum tzplatform_variable id =
+            (uid == getGlobalUserId()) ? TZ_SYS_RW_APP : TZ_USER_APP;
+    const char *appDir = tzplatform_context_getenv(tz_ctx, id);
+    if (!appDir) {
+        tzplatform_context_destroy(tz_ctx);
+        tz_ctx = nullptr;
+        return false;
+    }
+
+    userAppDir = appDir;
+
+    tzplatform_context_destroy(tz_ctx);
+    tz_ctx = nullptr;
+
+    return true;
+}
+
+bool ServiceImpl::installRequestAuthCheck(const app_inst_req &req, uid_t uid, std::string &appPath)
+{
+    std::string userHome;
+    std::string userAppDir;
+    std::stringstream correctPath;
+
+    if (uid != getGlobalUserId())
+        LogDebug("Installation type: single user");
+    else
+        LogDebug("Installation type: global installation");
+
+    if (!getUserAppDir(uid, userAppDir)) {
+        LogError("Failed getting app dir for user uid: " << uid);
+        return false;
+    }
+
+    appPath = userAppDir;
+    correctPath.clear();
+    correctPath << userAppDir << "/" << req.pkgId;
+    LogDebug("correctPath: " << correctPath.str());
+
     for (const auto &appPath : req.appPaths) {
         std::unique_ptr<char, std::function<void(void*)>> real_path(
             realpath(appPath.first.c_str(), NULL), free);
@@ -193,27 +231,49 @@ static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid)
             return false;
         }
         LogDebug("Requested path is '" << appPath.first.c_str()
-                << "'. User's HOME is '" << pwd->pw_dir << "'");
-        if (!isSubDir(home.get(), real_path.get())) {
-            LogWarning("User's apps may have registered folders only in user's home dir");
+                << "'. User's APPS_DIR is '" << userAppDir << "'");
+        if (!isSubDir(correctPath.str().c_str(), real_path.get())) {
+            LogWarning("Installation is outside correct path: " << correctPath.str() << "," << real_path.get());
             return false;
         }
+    }
+    return true;
+}
 
-        app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
-        if (pathType == SECURITY_MANAGER_PATH_PUBLIC) {
-            LogWarning("Only root can register SECURITY_MANAGER_PATH_PUBLIC path");
-            return false;
-        }
+bool ServiceImpl::getZoneId(std::string &zoneId)
+{
+    if (!getZoneIdFromPid(getpid(), zoneId)) {
+        LogError("Failed to get zone ID from current PID");
+        return false;
+    }
+
+    // This function should be called under slave mode only - assumes, that we work inside zone
+    if (zoneId == ZONE_HOST) {
+        LogError("We should not run in host - refusing request");
+        return false;
     }
+
     return true;
 }
 
-int appInstall(const app_inst_req &req, uid_t uid)
+int ServiceImpl::appInstall(const app_inst_req &req, uid_t uid, bool isSlave)
 {
     std::vector<std::string> addedPermissions;
     std::vector<std::string> removedPermissions;
     std::vector<std::string> pkgContents;
     std::string uidstr;
+    std::string appPath;
+    std::string appLabel;
+    std::string pkgLabel;
+
+    std::string zoneId;
+    if (isSlave) {
+        if (!getZoneId(zoneId)) {
+            LogError("Failed to get Zone ID.");
+            return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+        }
+    }
+
     if (uid) {
         if (uid != req.uid) {
             LogError("User " << uid <<
@@ -226,32 +286,18 @@ int appInstall(const app_inst_req &req, uid_t uid)
     }
     checkGlobalUser(uid, uidstr);
 
-    if (!installRequestAuthCheck(req, uid)) {
+    if (!installRequestAuthCheck(req, uid, appPath)) {
         LogError("Request from uid " << uid << " for app installation denied");
         return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
     }
 
-    std::string smackLabel;
-    if (!generateAppLabel(req.appId, smackLabel)) {
-        LogError("Cannot generate Smack label for application: " << req.appId);
-        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
-    }
-
-    LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
-            << ", generated smack label: " << smackLabel);
-
-    // create null terminated array of strings for permissions
-    std::unique_ptr<const char *[]> pp_permissions(new const char* [req.privileges.size() + 1]);
-    for (size_t i = 0; i < req.privileges.size(); ++i) {
-        LogDebug("  Permission = " << req.privileges[i]);
-        pp_permissions[i] = req.privileges[i].c_str();
-    }
-    pp_permissions[req.privileges.size()] = nullptr;
-
     try {
-        std::vector<std::string> oldAppPrivileges;
+        appLabel = zoneSmackLabelGenerate(SmackLabels::generateAppLabel(req.appId), zoneId);
+        /* NOTE: we don't use pkgLabel here, but generate it for pkgId validation */
+        pkgLabel = zoneSmackLabelGenerate(SmackLabels::generatePkgLabel(req.pkgId), zoneId);
         LogDebug("Install parameters: appId: " << req.appId << ", pkgId: " << req.pkgId
-                 << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
+                 << ", uidstr " << uidstr
+                 << ", app label: " << appLabel << ", pkg label: " << pkgLabel);
 
         PrivilegeDb::getInstance().BeginTransaction();
         std::string pkg;
@@ -261,13 +307,23 @@ int appInstall(const app_inst_req &req, uid_t uid)
             PrivilegeDb::getInstance().RollbackTransaction();
             return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
         }
-        PrivilegeDb::getInstance().GetAppPrivileges(req.appId, uid, oldAppPrivileges);
+
         PrivilegeDb::getInstance().AddApplication(req.appId, req.pkgId, uid);
         PrivilegeDb::getInstance().UpdateAppPrivileges(req.appId, uid, req.privileges);
         /* Get all application ids in the package to generate rules withing the package */
         PrivilegeDb::getInstance().GetAppIdsForPkgId(req.pkgId, pkgContents);
-        CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, uidstr, oldAppPrivileges,
-                                         req.privileges);
+
+        if (isSlave) {
+            int ret = MasterReq::CynaraPolicyUpdate(req.appId, uidstr, req.privileges);
+            if (ret != SECURITY_MANAGER_API_SUCCESS) {
+                PrivilegeDb::getInstance().RollbackTransaction();
+                LogError("Error while processing request on master: " << ret);
+                return ret;
+            }
+        } else {
+            CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, uidstr, req.privileges);
+        }
+
         PrivilegeDb::getInstance().CommitTransaction();
         LogDebug("Application installation commited to database");
     } catch (const PrivilegeDb::Exception::IOError &e) {
@@ -281,35 +337,55 @@ int appInstall(const app_inst_req &req, uid_t uid)
         PrivilegeDb::getInstance().RollbackTransaction();
         LogError("Error while setting Cynara rules for application: " << e.DumpToString());
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    } catch (const SmackException::InvalidLabel &e) {
+        PrivilegeDb::getInstance().RollbackTransaction();
+        LogError("Error while generating Smack labels: " << e.DumpToString());
+        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
     } catch (const std::bad_alloc &e) {
         PrivilegeDb::getInstance().RollbackTransaction();
         LogError("Memory allocation while setting Cynara rules for application: " << e.what());
-        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+        return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
     }
 
-    // register paths
-    for (const auto &appPath : req.appPaths) {
-        const std::string &path = appPath.first;
-        app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
-        int result = setupPath(req.appId, path, pathType);
-
-        if (!result) {
-            LogError("setupPath() failed");
-            return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    try {
+        if (!req.appPaths.empty())
+            SmackLabels::setupAppBasePath(req.pkgId, appPath);
+
+        // register paths
+        for (const auto &appPath : req.appPaths) {
+            const std::string &path = appPath.first;
+            app_install_path_type pathType = static_cast<app_install_path_type>(appPath.second);
+            SmackLabels::setupPath(req.pkgId, path, pathType, zoneId);
         }
-    }
 
-    LogDebug("Adding Smack rules for new appId: " << req.appId << " with pkgId: "
-            << req.pkgId << ". Applications in package: " << pkgContents.size());
-    if (!SmackRules::installApplicationRules(req.appId, req.pkgId, pkgContents)) {
-        LogError("Failed to apply package-specific smack rules");
+        if (isSlave) {
+            LogDebug("Requesting master to add rules for new appId: " << req.appId << " with pkgId: "
+                    << req.pkgId << ". Applications in package: " << pkgContents.size());
+            int ret = MasterReq::SmackInstallRules(req.appId, req.pkgId, pkgContents);
+            if (ret != SECURITY_MANAGER_API_SUCCESS) {
+                LogError("Master failed to apply package-specific smack rules: " << ret);
+                return ret;
+            }
+        } else {
+            LogDebug("Adding Smack rules for new appId: " << req.appId << " with pkgId: "
+                    << req.pkgId << ". Applications in package: " << pkgContents.size());
+            SmackRules::installApplicationRules(req.appId, req.pkgId, pkgContents);
+        }
+    } catch (const SmackException::Base &e) {
+        LogError("Error while applying Smack policy for application: " << e.DumpToString());
+        return SECURITY_MANAGER_API_ERROR_SETTING_FILE_LABEL_FAILED;
+    } catch (const SecurityManager::Exception &e) {
+        LogError("Security Manager exception: " << e.DumpToString());
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    }catch (const std::bad_alloc &e) {
+        LogError("Memory allocation error: " << e.what());
+        return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
     }
 
     return SECURITY_MANAGER_API_SUCCESS;
 }
 
-int appUninstall(const std::string &appId, uid_t uid)
+int ServiceImpl::appUninstall(const std::string &appId, uid_t uid, bool isSlave)
 {
     std::string pkgId;
     std::string smackLabel;
@@ -319,9 +395,15 @@ int appUninstall(const std::string &appId, uid_t uid)
     std::string uidstr;
     checkGlobalUser(uid, uidstr);
 
-    try {
-        std::vector<std::string> oldAppPrivileges;
+    std::string zoneId;
+    if (isSlave) {
+        if (!getZoneId(zoneId)) {
+            LogError("Failed to get Zone ID.");
+            return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+        }
+    }
 
+    try {
         PrivilegeDb::getInstance().BeginTransaction();
         if (!PrivilegeDb::getInstance().GetAppPkgId(appId, pkgId)) {
             LogWarning("Application " << appId <<
@@ -329,24 +411,28 @@ int appUninstall(const std::string &appId, uid_t uid)
             PrivilegeDb::getInstance().RollbackTransaction();
             appExists = false;
         } else {
-
+            smackLabel = zoneSmackLabelGenerate(SmackLabels::generateAppLabel(appId), zoneId);
             LogDebug("Uninstall parameters: appId: " << appId << ", pkgId: " << pkgId
                      << ", uidstr " << uidstr << ", generated smack label: " << smackLabel);
 
-            if (!generateAppLabel(appId, smackLabel)) {
-                LogError("Cannot generate Smack label for package: " << pkgId);
-                return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
-            }
-
             /* Before we remove the app from the database, let's fetch all apps in the package
                 that this app belongs to, this will allow us to remove all rules withing the
                 package that the app appears in */
             PrivilegeDb::getInstance().GetAppIdsForPkgId(pkgId, pkgContents);
-            PrivilegeDb::getInstance().GetAppPrivileges(appId, uid, oldAppPrivileges);
             PrivilegeDb::getInstance().UpdateAppPrivileges(appId, uid, std::vector<std::string>());
             PrivilegeDb::getInstance().RemoveApplication(appId, uid, removePkg);
-            CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, uidstr, oldAppPrivileges,
-                                             std::vector<std::string>());
+
+            if (isSlave) {
+                int ret = MasterReq::CynaraPolicyUpdate(appId, uidstr, std::vector<std::string>());
+                if (ret != SECURITY_MANAGER_API_SUCCESS) {
+                    PrivilegeDb::getInstance().RollbackTransaction();
+                    LogError("Error while processing request on master: " << ret);
+                    return ret;
+                }
+            } else {
+                CynaraAdmin::getInstance().UpdateAppPolicy(smackLabel, uidstr, std::vector<std::string>());
+            }
+
             PrivilegeDb::getInstance().CommitTransaction();
             LogDebug("Application uninstallation commited to database");
         }
@@ -361,32 +447,51 @@ int appUninstall(const std::string &appId, uid_t uid)
         PrivilegeDb::getInstance().RollbackTransaction();
         LogError("Error while setting Cynara rules for application: " << e.DumpToString());
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    } catch (const SmackException::InvalidLabel &e) {
+        PrivilegeDb::getInstance().RollbackTransaction();
+        LogError("Error while generating Smack labels: " << e.DumpToString());
+        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
     } catch (const std::bad_alloc &e) {
         PrivilegeDb::getInstance().RollbackTransaction();
         LogError("Memory allocation while setting Cynara rules for application: " << e.what());
-        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+        return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
     }
 
     if (appExists) {
+        try {
+            if (isSlave) {
+                LogDebug("Delegating Smack rules removal for deleted pkgId " << pkgId <<
+                         " to master");
+                int ret = MasterReq::SmackUninstallRules(appId, pkgId, pkgContents, removePkg);
+                if (ret != SECURITY_MANAGER_API_SUCCESS) {
+                    LogError("Error while processing uninstall request on master: " << ret);
+                    return ret;
+                }
+            } else {
+                if (removePkg) {
+                    LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
+                    SmackRules::uninstallPackageRules(pkgId);
+                }
 
-        if (removePkg) {
-            LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
-            if (!SmackRules::uninstallPackageRules(pkgId)) {
-                LogError("Error on uninstallation of package-specific smack rules");
-                return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+                LogDebug ("Removing smack rules for deleted appId " << appId);
+                SmackRules::uninstallApplicationRules(appId, pkgId, pkgContents, zoneId);
             }
-        }
-        LogDebug ("Removing smack rules for deleted appId " << appId);
-        if (!SmackRules::uninstallApplicationRules(appId, pkgId, pkgContents)) {
-            LogError("Error during uninstallation of application-specific smack rules");
+        } catch (const SmackException::Base &e) {
+            LogError("Error while removing Smack rules for application: " << e.DumpToString());
+            return SECURITY_MANAGER_API_ERROR_SETTING_FILE_LABEL_FAILED;
+        } catch (const SecurityManager::Exception &e) {
+            LogError("Security Manager error: " << e.DumpToString());
             return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+        } catch (const std::bad_alloc &e) {
+            LogError("Memory allocation error: " << e.what());
+            return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
         }
     }
 
     return SECURITY_MANAGER_API_SUCCESS;
 }
 
-int getPkgId(const std::string &appId, std::string &pkgId)
+int ServiceImpl::getPkgId(const std::string &appId, std::string &pkgId)
 {
     LogDebug("appId: " << appId);
 
@@ -405,8 +510,18 @@ int getPkgId(const std::string &appId, std::string &pkgId)
     return SECURITY_MANAGER_API_SUCCESS;
 }
 
-int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_set<gid_t> &gids)
+int ServiceImpl::getAppGroups(const std::string &appId, uid_t uid, pid_t pid, bool isSlave,
+        std::unordered_set<gid_t> &gids)
 {
+    // FIXME Temporary solution, see below
+    std::string zoneId;
+    if (isSlave) {
+        if (!getZoneId(zoneId)) {
+            LogError("Failed to get Zone ID.");
+            return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+        }
+    }
+
     try {
         std::string pkgId;
         std::string smackLabel;
@@ -420,10 +535,10 @@ int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_
             return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
         }
         LogDebug("pkgId: " << pkgId);
-        if (!generatePkgLabel(pkgId, smackLabel)) {
-            LogError("Cannot generate Smack label for pkgId: " << pkgId);
-            return SECURITY_MANAGER_API_ERROR_NO_SUCH_OBJECT;
-        }
+
+        // FIXME getAppGroups should work without generating zone-specific labels when
+        //       Smack Namespaces will work
+        smackLabel = zoneSmackLabelGenerate(SmackLabels::generateAppLabel(appId), zoneId);
         LogDebug("smack label: " << smackLabel);
 
         std::vector<std::string> privileges;
@@ -433,7 +548,7 @@ int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_
         PrivilegeDb::getInstance().GetPkgPrivileges(pkgId, getGlobalUserId(), privileges);
         /*privileges needs to be sorted and with no duplications - for cynara sake*/
         std::inplace_merge(privileges.begin(), privileges.begin() + tmp, privileges.end());
-        privileges.erase( unique( privileges.begin(), privileges.end() ), privileges.end() );
+        privileges.erase(unique(privileges.begin(), privileges.end()), privileges.end());
 
         for (const auto &privilege : privileges) {
             std::vector<std::string> gidsTmp;
@@ -441,9 +556,9 @@ int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_
             if (!gidsTmp.empty()) {
                 LogDebug("Considering privilege " << privilege << " with " <<
                     gidsTmp.size() << " groups assigned");
+                // TODO: create method in Cynara class for fetching all privileges of an application
                 if (Cynara::getInstance().check(smackLabel, privilege, uidStr, pidStr)) {
-                    for_each(gidsTmp.begin(), gidsTmp.end(), [&] (std::string group)
-                    {
+                    for_each(gidsTmp.begin(), gidsTmp.end(), [&] (std::string group) {
                         struct group *grp = getgrnam(group.c_str());
                         if (grp == NULL) {
                                 LogError("No such group: " << group.c_str());
@@ -462,6 +577,9 @@ int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_
     } catch (const CynaraException::Base &e) {
         LogError("Error while querying Cynara for permissions: " << e.DumpToString());
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    } catch (const SmackException::InvalidLabel &e) {
+        LogError("Error while generating Smack labels: " << e.DumpToString());
+        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
     } catch (const std::bad_alloc &e) {
         LogError("Memory allocation failed: " << e.what());
         return SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
@@ -470,20 +588,30 @@ int getAppGroups(const std::string &appId, uid_t uid, pid_t pid, std::unordered_
     return SECURITY_MANAGER_API_SUCCESS;
 }
 
-int userAdd(uid_t uidAdded, int userType, uid_t uid)
+int ServiceImpl::userAdd(uid_t uidAdded, int userType, uid_t uid, bool isSlave)
 {
     if (uid != 0)
         return SECURITY_MANAGER_API_ERROR_AUTHENTICATION_FAILED;
 
-    try {
-        CynaraAdmin::getInstance().UserInit(uidAdded, static_cast<security_manager_user_type>(userType));
-    } catch (CynaraException::InvalidParam &e) {
-        return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
+    if (isSlave) {
+        int ret = MasterReq::CynaraUserInit(uidAdded,
+                                            static_cast<security_manager_user_type>(userType));
+        if (ret != SECURITY_MANAGER_API_SUCCESS) {
+            LogError("Master failed to initialize user " << uidAdded << " of type " << userType);
+            return ret;
+        }
+    } else {
+        try {
+            CynaraAdmin::getInstance().UserInit(uidAdded, static_cast<security_manager_user_type>(userType));
+        } catch (CynaraException::InvalidParam &e) {
+            return SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
+        }
     }
+
     return SECURITY_MANAGER_API_SUCCESS;
 }
 
-int userDelete(uid_t uidDeleted, uid_t uid)
+int ServiceImpl::userDelete(uid_t uidDeleted, uid_t uid, bool isSlave)
 {
     int ret = SECURITY_MANAGER_API_SUCCESS;
     if (uid != 0)
@@ -499,19 +627,27 @@ int userDelete(uid_t uidDeleted, uid_t uid)
     }
 
     for (auto &app: userApps) {
-        if (appUninstall(app, uidDeleted) != SECURITY_MANAGER_API_SUCCESS) {
+        if (appUninstall(app, uidDeleted, isSlave) != SECURITY_MANAGER_API_SUCCESS) {
         /*if uninstallation of this app fails, just go on trying to uninstall another ones.
         we do not have anything special to do about that matter - user will be deleted anyway.*/
             ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
         }
     }
 
-    CynaraAdmin::getInstance().UserRemove(uidDeleted);
+    if (isSlave) {
+        int ret = MasterReq::CynaraUserRemove(uidDeleted);
+        if (ret) {
+            LogError("Master failed to delete user " << uidDeleted);
+            return ret;
+        }
+    } else {
+        CynaraAdmin::getInstance().UserRemove(uidDeleted);
+    }
 
     return ret;
 }
 
-int policyUpdate(const std::vector<policy_entry> &policyEntries, uid_t uid, pid_t pid, const std::string &smackLabel)
+int ServiceImpl::policyUpdate(const std::vector<policy_entry> &policyEntries, uid_t uid, pid_t pid, const std::string &smackLabel)
 {
     enum {
         NOT_CHECKED,
@@ -571,7 +707,7 @@ int policyUpdate(const std::vector<policy_entry> &policyEntries, uid_t uid, pid_
     return SECURITY_MANAGER_API_SUCCESS;
 }
 
-int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pid_t pid,
+int ServiceImpl::getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pid_t pid,
     const std::string &smackLabel, std::vector<policy_entry> &policyEntries)
 {
     try {
@@ -593,14 +729,9 @@ int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pi
         std::vector<CynaraAdminPolicy> listOfPolicies;
 
         //convert appId to smack label
-        std::string appLabel;
-        if (!filter.appId.compare(SECURITY_MANAGER_ANY))
-            appLabel = CYNARA_ADMIN_ANY;
-        else
-            generateAppLabel(filter.appId, appLabel);
-
-        std::string user = (!filter.user.compare(SECURITY_MANAGER_ANY))? CYNARA_ADMIN_ANY: filter.user;
-        std::string privilege = (!filter.privilege.compare(SECURITY_MANAGER_ANY))? CYNARA_ADMIN_ANY: filter.privilege;
+        std::string appLabel = filter.appId.compare(SECURITY_MANAGER_ANY) ? SmackLabels::generateAppLabel(filter.appId) : CYNARA_ADMIN_ANY;
+        std::string user = filter.user.compare(SECURITY_MANAGER_ANY) ? filter.user : CYNARA_ADMIN_ANY;
+        std::string privilege = filter.privilege.compare(SECURITY_MANAGER_ANY) ? filter.privilege : CYNARA_ADMIN_ANY;
 
         LogDebug("App: " << filter.appId << ", Label: " << appLabel);
 
@@ -644,7 +775,7 @@ int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pi
 
             policy_entry pe;
 
-            pe.appId = strcmp(policy.client, CYNARA_ADMIN_WILDCARD) ? generateAppNameFromLabel(policy.client) : SECURITY_MANAGER_ANY;
+            pe.appId = strcmp(policy.client, CYNARA_ADMIN_WILDCARD) ? SmackLabels::generateAppNameFromLabel(policy.client) : SECURITY_MANAGER_ANY;
             pe.user =  strcmp(policy.user, CYNARA_ADMIN_WILDCARD) ? policy.user : SECURITY_MANAGER_ANY;
             pe.privilege = strcmp(policy.privilege, CYNARA_ADMIN_WILDCARD) ? policy.privilege : pe.privilege = SECURITY_MANAGER_ANY;
             pe.currentLevel = CynaraAdmin::getInstance().convertToPolicyDescription(policy.result);
@@ -674,6 +805,9 @@ int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pi
     } catch (const CynaraException::Base &e) {
         LogError("Error while listing Cynara rules: " << e.DumpToString());
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    } catch (const SmackException::InvalidLabel &e) {
+        LogError("Error while generating Smack labels: " << e.DumpToString());
+        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
     } catch (const std::bad_alloc &e) {
         LogError("Memory allocation error while listing Cynara rules: " << e.what());
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
@@ -683,7 +817,7 @@ int getConfiguredPolicy(bool forAdmin, const policy_entry &filter, uid_t uid, pi
     return SECURITY_MANAGER_API_SUCCESS;
 }
 
-int getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::string &smackLabel, std::vector<policy_entry> &policyEntries)
+int ServiceImpl::getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::string &smackLabel, std::vector<policy_entry> &policyEntries)
 {
     try {
         std::string uidStr = std::to_string(uid);
@@ -736,11 +870,11 @@ int getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::strin
 
             for (const std::string &appId : listOfApps) {
                 LogDebug("App: " << appId);
-                std::string smackLabelForApp;
+                std::string smackLabelForApp = SmackLabels::generateAppLabel(appId);
                 std::vector<std::string> listOfPrivileges;
 
-                generateAppLabel(appId, smackLabelForApp);
                 // FIXME: also fetch privileges of global applications
+                // FIXME: fetch privileges from cynara, drop PrivilegeDb::GetAppPrivileges
                 PrivilegeDb::getInstance().GetAppPrivileges(appId, uid, listOfPrivileges);
 
                 if (filter.privilege.compare(SECURITY_MANAGER_ANY)) {
@@ -790,6 +924,9 @@ int getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::strin
     } catch (const CynaraException::Base &e) {
         LogError("Error while listing Cynara rules: " << e.DumpToString());
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    } catch (const SmackException::InvalidLabel &e) {
+        LogError("Error while generating Smack labels: " << e.DumpToString());
+        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
     } catch (const std::bad_alloc &e) {
         LogError("Memory allocation error while listing Cynara rules: " << e.what());
         return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
@@ -798,7 +935,7 @@ int getPolicy(const policy_entry &filter, uid_t uid, pid_t pid, const std::strin
     return SECURITY_MANAGER_API_SUCCESS;
 }
 
-int policyGetDesc(std::vector<std::string> &levels)
+int ServiceImpl::policyGetDesc(std::vector<std::string> &levels)
 {
     int ret = SECURITY_MANAGER_API_SUCCESS;
 
@@ -821,5 +958,64 @@ int policyGetDesc(std::vector<std::string> &levels)
     return ret;
 }
 
-} /* namespace ServiceImpl */
+int ServiceImpl::getPrivilegesMappings(const std::string &version_from,
+                          const std::string &version_to,
+                          const std::vector<std::string> &privileges,
+                          std::vector<std::string> &mappings)
+{
+    int errorRet;
+    try {
+        std::string finalVersionTo;
+        if (version_to.empty()) {
+            finalVersionTo = Config::PRIVILEGE_VERSION;
+        } else {
+            finalVersionTo = version_to;
+        }
+
+        PrivilegeDb::getInstance().BeginTransaction();
+        if (privileges.size() == 0) {
+            PrivilegeDb::getInstance().GetDefaultMapping(version_from, finalVersionTo, mappings);
+        } else if ( privileges.size() == 1) {
+            PrivilegeDb::getInstance().GetPrivilegeMappings(version_from, finalVersionTo,
+                                                            privileges.front(), mappings);
+        } else {
+            PrivilegeDb::getInstance().GetPrivilegesMappings(version_from, finalVersionTo,
+                                                             privileges, mappings);
+        }
+        PrivilegeDb::getInstance().CommitTransaction();
+        return SECURITY_MANAGER_API_SUCCESS;
+    } catch (const PrivilegeDb::Exception::IOError &e) {
+        LogError("Cannot access application database: " << e.DumpToString());
+        errorRet = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    } catch (const PrivilegeDb::Exception::InternalError &e) {
+        LogError("Error while getting privilege mapping from database: " << e.DumpToString());
+        errorRet = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    } catch (const std::bad_alloc &e) {
+        LogError("Memory allocation failed: " << e.what());
+        errorRet = SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
+    } catch (const std::exception &e) {
+        LogError("Some exception thrown : " << e.what());
+        errorRet = SECURITY_MANAGER_API_ERROR_UNKNOWN;
+    } catch (...) {
+        LogError("Unknown exception thrown");
+        errorRet = SECURITY_MANAGER_API_ERROR_UNKNOWN;
+    }
+    PrivilegeDb::getInstance().RollbackTransaction();
+    return errorRet;
+}
+
+int ServiceImpl::policyGetGroups(std::vector<std::string> &groups)
+{
+    int ret = SECURITY_MANAGER_API_SUCCESS;
+
+    try {
+        PrivilegeDb::getInstance().GetGroups(groups);
+    } catch (const PrivilegeDb::Exception::Base &e) {
+        LogError("Error while getting groups from database: " << e.DumpToString());
+        return SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    }
+
+    return ret;
+}
+
 } /* namespace SecurityManager */