Implement master and slave mode
[platform/core/security/security-manager.git] / src / server / service / master-service.cpp
index 2afae00..f018abb 100644 (file)
 #include <dpl/serialization.h>
 
 #include "protocols.h"
+#include "zone-utils.h"
+#include "cynara.h"
 #include "master-service.h"
+#include "smack-rules.h"
+#include "smack-labels.h"
 #include "service_impl.h"
 
 namespace SecurityManager {
@@ -68,14 +72,66 @@ bool MasterService::processOne(const ConnectionID &conn, MessageBuffer &buffer,
         return false;
     }
 
+    // FIXME this part needs to be updated when Vasum is added to OBS. See zone-utils.h
+    std::string vsmZoneId;
+    if (!getZoneIdFromPid(pid, vsmZoneId)) {
+        LogError("Failed to extract Zone ID! Closing socket.");
+        m_serviceManager->Close(conn);
+        return false;
+    }
+
+    if (vsmZoneId == ZONE_HOST) {
+        LogError("Connection came from host - in master mode this should not happen! Closing.");
+        m_serviceManager->Close(conn);
+        return false;
+    }
+
+    LogInfo("Connection came from Zone " << vsmZoneId);
+
     if (IFACE == interfaceID) {
         Try {
             // deserialize API call type
             int call_type_int;
             Deserialization::Deserialize(buffer, call_type_int);
-            SecurityModuleCall call_type = static_cast<SecurityModuleCall>(call_type_int);
+            MasterSecurityModuleCall call_type = static_cast<MasterSecurityModuleCall>(call_type_int);
 
             switch (call_type) {
+                case MasterSecurityModuleCall::CYNARA_UPDATE_POLICY:
+                    LogDebug("call type MasterSecurityModuleCall::CYNARA_UPDATE_POLICY");
+                    processCynaraUpdatePolicy(buffer, send, vsmZoneId);
+                    break;
+                case MasterSecurityModuleCall::CYNARA_USER_INIT:
+                    LogDebug("call type MasterSecurityModuleCall::CYNARA_USER_INIT");
+                    processCynaraUserInit(buffer, send);
+                    break;
+                case MasterSecurityModuleCall::CYNARA_USER_REMOVE:
+                    LogDebug("call type MasterSecurityModuleCall::CYNARA_USER_REMOVE");
+                    processCynaraUserRemove(buffer, send);
+                    break;
+                case MasterSecurityModuleCall::POLICY_UPDATE:
+                    LogDebug("call type MasterSecurityModuleCall::POLICY_UPDATE");
+                    processPolicyUpdate(buffer, send);
+                    break;
+                case MasterSecurityModuleCall::GET_CONFIGURED_POLICY:
+                    LogDebug("call type MasterSecurityModuleCall::GET_CONFIGURED_POLICY");
+                    processGetConfiguredPolicy(buffer, send);
+                    break;
+                case MasterSecurityModuleCall::GET_POLICY:
+                    LogDebug("call type MasterSecurityModuleCall::GET_POLICY");
+                    processGetPolicy(buffer, send);
+                    break;
+                case MasterSecurityModuleCall::POLICY_GET_DESC:
+                    LogDebug("call type MasterSecurityModuleCall::POLICY_GET_DESC");
+                    processPolicyGetDesc(send);
+                    break;
+                case MasterSecurityModuleCall::SMACK_INSTALL_RULES:
+                    LogDebug("call type MasterSecurityModuleCall::SMACK_INSTALL_RULES");
+                    processSmackInstallRules(buffer, send, vsmZoneId);
+                    break;
+                case MasterSecurityModuleCall::SMACK_UNINSTALL_RULES:
+                    LogDebug("call type MasterSecurityModuleCall::SMACK_UNINSTALL_RULES");
+                    processSmackUninstallRules(buffer, send, vsmZoneId);
+                    break;
                 default:
                     LogError("Invalid call: " << call_type_int);
                     Throw(MasterServiceException::InvalidAction);
@@ -107,5 +163,252 @@ bool MasterService::processOne(const ConnectionID &conn, MessageBuffer &buffer,
     return retval;
 }
 
+void MasterService::processCynaraUpdatePolicy(MessageBuffer &buffer, MessageBuffer &send,
+        const std::string &zoneId)
+{
+    int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    std::string appId;
+    std::string uidstr;
+    std::vector<std::string> oldAppPrivileges, newAppPrivileges;
+    std::string appLabel, newLabel;
+
+    Deserialization::Deserialize(buffer, appId);
+    Deserialization::Deserialize(buffer, uidstr);
+    Deserialization::Deserialize(buffer, oldAppPrivileges);
+    Deserialization::Deserialize(buffer, newAppPrivileges);
+
+    appLabel = zoneSmackLabelGenerate(SmackLabels::generateAppLabel(appId), zoneId);
+
+    try {
+        CynaraAdmin::getInstance().UpdateAppPolicy(appLabel, uidstr, oldAppPrivileges,
+                                                   newAppPrivileges);
+    } catch (const CynaraException::Base &e) {
+        LogError("Error while setting Cynara rules for application: " << e.DumpToString());
+        goto out;
+    } catch (const std::bad_alloc &e) {
+        LogError("Memory allocation while setting Cynara rules for application: " << e.what());
+        ret = SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
+        goto out;
+    }
+
+    ret = SECURITY_MANAGER_API_SUCCESS;
+
+out:
+    Serialization::Serialize(send, ret);
+}
+
+void MasterService::processCynaraUserInit(MessageBuffer &buffer, MessageBuffer &send)
+{
+    int ret = SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
+    uid_t uidAdded;
+    int userType;
+
+    Deserialization::Deserialize(buffer, uidAdded);
+    Deserialization::Deserialize(buffer, userType);
+
+    try {
+        CynaraAdmin::getInstance().UserInit(uidAdded,
+                                            static_cast<security_manager_user_type>(userType));
+    } catch (CynaraException::InvalidParam &e) {
+        goto out;
+    }
+
+    ret = SECURITY_MANAGER_API_SUCCESS;
+out:
+    Serialization::Serialize(send, ret);
+}
+
+void MasterService::processCynaraUserRemove(MessageBuffer &buffer, MessageBuffer &send)
+{
+    int ret = SECURITY_MANAGER_API_ERROR_INPUT_PARAM;
+    uid_t uidDeleted;
+
+    Deserialization::Deserialize(buffer, uidDeleted);
+
+    try {
+        CynaraAdmin::getInstance().UserRemove(uidDeleted);
+    } catch (CynaraException::InvalidParam &e) {
+        goto out;
+    }
+
+    ret = SECURITY_MANAGER_API_SUCCESS;
+out:
+    Serialization::Serialize(send, ret);
+}
+
+void MasterService::processPolicyUpdate(MessageBuffer &buffer, MessageBuffer &send)
+{
+    int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    std::vector<policy_entry> policyEntries;
+    uid_t uid;
+    pid_t pid;
+    std::string smackLabel;
+
+    Deserialization::Deserialize(buffer, policyEntries);
+    Deserialization::Deserialize(buffer, uid);
+    Deserialization::Deserialize(buffer, pid);
+    Deserialization::Deserialize(buffer, smackLabel);
+
+    ret = ServiceImpl::policyUpdate(policyEntries, uid, pid, smackLabel);
+    Serialization::Serialize(send, ret);
+}
+
+void MasterService::processGetConfiguredPolicy(MessageBuffer &buffer, MessageBuffer &send)
+{
+    int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    bool forAdmin;
+    policy_entry filter;
+    uid_t uid;
+    pid_t pid;
+    std::string smackLabel;
+    std::vector<policy_entry> policyEntries;
+
+    Deserialization::Deserialize(buffer, forAdmin);
+    Deserialization::Deserialize(buffer, filter);
+    Deserialization::Deserialize(buffer, uid);
+    Deserialization::Deserialize(buffer, pid);
+    Deserialization::Deserialize(buffer, smackLabel);
+
+    ret = ServiceImpl::getConfiguredPolicy(forAdmin, filter, uid, pid, smackLabel, policyEntries);
+    Serialization::Serialize(send, ret);
+    if (ret == SECURITY_MANAGER_API_SUCCESS)
+        Serialization::Serialize(send, policyEntries);
+}
+
+void MasterService::processGetPolicy(MessageBuffer &buffer, MessageBuffer &send)
+{
+    (void) buffer;
+    int ret = SECURITY_MANAGER_API_ERROR_BAD_REQUEST;
+
+    // FIXME getPolicy is not ready to work in Master mode. Uncomment below code when getPolicy will
+    //       be implemented for Master.
+    /*
+    policy_entry filter;
+    uid_t uid;
+    pid_t pid;
+    std::string smackLabel;
+    std::vector<policy_entry> policyEntries;
+
+    Deserialization::Deserialize(buffer, filter);
+    Deserialization::Deserialize(buffer, uid);
+    Deserialization::Deserialize(buffer, pid);
+    Deserialization::Deserialize(buffer, smackLabel);
+
+    ret = ServiceImpl::getPolicy(filter, uid, pid, smackLabel, policyEntries);*/
+    Serialization::Serialize(send, ret);
+    /*if (ret == SECURITY_MANAGER_API_SUCCESS)
+        Serialization::Serialize(send, policyEntries);*/
+}
+
+void MasterService::processPolicyGetDesc(MessageBuffer &send)
+{
+    int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    std::vector<std::string> descriptions;
+
+    ret = ServiceImpl::policyGetDesc(descriptions);
+    Serialization::Serialize(send, ret);
+    if (ret == SECURITY_MANAGER_API_SUCCESS)
+        Serialization::Serialize(send, descriptions);
+}
+
+void MasterService::processSmackInstallRules(MessageBuffer &buffer, MessageBuffer &send,
+                                             const std::string &zoneId)
+{
+    int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    std::string appId, pkgId;
+    std::vector<std::string> pkgContents;
+
+    Deserialization::Deserialize(buffer, appId);
+    Deserialization::Deserialize(buffer, pkgId);
+    Deserialization::Deserialize(buffer, pkgContents);
+
+    try {
+        LogDebug("Adding Smack rules for new appId: " << appId << " with pkgId: "
+                << pkgId << ". Applications in package: " << pkgContents.size());
+        SmackRules::installApplicationRules(appId, pkgId, pkgContents, zoneId);
+
+        // FIXME implement zoneSmackLabelMap and check if works when Smack Namespaces are implemented
+        std::string zoneAppLabel = SmackLabels::generateAppLabel(appId);
+        std::string zonePkgLabel = SmackLabels::generatePkgLabel(pkgId);
+        std::string hostAppLabel = zoneSmackLabelGenerate(zoneAppLabel, zoneId);
+        std::string hostPkgLabel = zoneSmackLabelGenerate(zonePkgLabel, zoneId);
+
+        if (!zoneSmackLabelMap(hostAppLabel, zoneId, zoneAppLabel)) {
+            LogError("Failed to apply Smack label mapping for application " << appId);
+            goto out;
+        }
+
+        if (!zoneSmackLabelMap(hostPkgLabel, zoneId, zonePkgLabel)) {
+            LogError("Failed to apply Smack label mapping for package " << pkgId);
+            goto out;
+        }
+    } catch (const SmackException::Base &e) {
+        LogError("Error while adding Smack rules for application: " << e.DumpToString());
+        ret = SECURITY_MANAGER_API_ERROR_SETTING_FILE_LABEL_FAILED;
+        goto out;
+    } catch (const std::bad_alloc &e) {
+        LogError("Memory allocation error: " << e.what());
+        ret =  SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
+        goto out;
+    }
+
+    ret = SECURITY_MANAGER_API_SUCCESS;
+out:
+    Serialization::Serialize(send, ret);
+}
+
+void MasterService::processSmackUninstallRules(MessageBuffer &buffer, MessageBuffer &send,
+                                               const std::string &zoneId)
+{
+    int ret = SECURITY_MANAGER_API_ERROR_SERVER_ERROR;
+    std::string appId, pkgId;
+    std::vector<std::string> pkgContents;
+    bool removePkg = false;
+
+    Deserialization::Deserialize(buffer, appId);
+    Deserialization::Deserialize(buffer, pkgId);
+    Deserialization::Deserialize(buffer, pkgContents);
+    Deserialization::Deserialize(buffer, removePkg);
+
+    try {
+        if (removePkg) {
+            LogDebug("Removing Smack rules for deleted pkgId " << pkgId);
+            SmackRules::uninstallPackageRules(pkgId);
+        }
+
+        LogDebug ("Removing smack rules for deleted appId " << appId);
+        SmackRules::uninstallApplicationRules(appId, pkgId, pkgContents, zoneId);
+
+        // FIXME implement zoneSmackLabelUnmap and check if works when Smack Namespaces are implemented
+        std::string zoneAppLabel = SmackLabels::generateAppLabel(appId);
+        std::string zonePkgLabel = SmackLabels::generatePkgLabel(pkgId);
+        std::string hostAppLabel = zoneSmackLabelGenerate(zoneAppLabel, zoneId);
+        std::string hostPkgLabel = zoneSmackLabelGenerate(zonePkgLabel, zoneId);
+
+        if (!zoneSmackLabelUnmap(hostAppLabel, zoneId)) {
+            LogError("Failed to unmap Smack labels for application " << appId);
+            goto out;
+        }
+
+        if (removePkg) {
+            if (!zoneSmackLabelUnmap(hostPkgLabel, zoneId)) {
+                LogError("Failed to unmap Smack label for package " << pkgId);
+                goto out;
+            }
+        }
+    } catch (const SmackException::Base &e) {
+        LogError("Error while removing Smack rules for application: " << e.DumpToString());
+        ret = SECURITY_MANAGER_API_ERROR_SETTING_FILE_LABEL_FAILED;
+        goto out;
+    } catch (const std::bad_alloc &e) {
+        LogError("Memory allocation error: " << e.what());
+        ret =  SECURITY_MANAGER_API_ERROR_OUT_OF_MEMORY;
+        goto out;
+    }
+
+    ret = SECURITY_MANAGER_API_SUCCESS;
+out:
+    Serialization::Serialize(send, ret);
+}
 
 } // namespace SecurityManager