From 1292f6ebd110df620e45c94d923d33fc7a27fca3 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Thu, 12 Jun 2014 10:12:41 +0200 Subject: [PATCH] A DBUS API to move the files between containers [Bug/Feature] Add an ability for a container to request a file move to another container. Some minor fixes here and there. Added missing tests for utils/fs. A little revamp of DbusAccessory in ut-cm tests. [Cause] N/A [Solution] Implement a DBUS API and a simple move implementation. [Verification] Build, install, run tests, run server. Change-Id: I881f7b6079e38e3dd43d6fe34360457172047c2c Signed-off-by: Lukasz Pawelczyk --- common/config.hpp | 7 + common/utils/fs.cpp | 59 +++++- common/utils/fs.hpp | 12 ++ container-daemon/CMakeLists.txt | 2 +- packaging/security-containers.spec | 4 +- server/CMakeLists.txt | 1 + server/configs/containers/business.conf | 4 +- server/configs/containers/private.conf | 4 +- server/configs/daemon.conf | 1 + server/configs/libvirt-config/business.xml | 2 + server/configs/libvirt-config/private.xml | 2 + server/container-config.hpp | 17 +- server/container-connection.cpp | 15 ++ server/container-connection.hpp | 11 ++ server/container-dbus-definitions.hpp | 14 ++ server/container.cpp | 31 ++- server/container.hpp | 26 +++ server/containers-manager-config.hpp | 16 +- server/containers-manager.cpp | 109 +++++++++- server/containers-manager.hpp | 4 + .../ut-container-admin/containers/buggy.conf.in | 4 +- .../ut-container-admin/containers/missing.conf | 4 +- .../containers/test-no-shutdown.conf.in | 4 +- .../ut-container-admin/containers/test.conf.in | 4 +- .../configs/ut-container/containers/buggy.conf | 4 +- .../configs/ut-container/containers/test-dbus.conf | 4 +- .../configs/ut-container/containers/test.conf | 4 +- .../ut-containers-manager/buggy-daemon.conf | 1 + .../buggy-default-daemon.conf | 3 +- .../buggy-foreground-daemon.conf | 1 + .../containers/console1-dbus.conf | 4 +- .../ut-containers-manager/containers/console1.conf | 4 +- .../containers/console2-dbus.conf | 4 +- .../ut-containers-manager/containers/console2.conf | 4 +- .../containers/console3-dbus.conf | 4 +- .../ut-containers-manager/containers/console3.conf | 4 +- .../libvirt-config/console1-dbus.xml.in | 2 +- .../libvirt-config/console2-dbus.xml.in | 2 +- .../libvirt-config/console3-dbus.xml.in | 2 +- .../configs/ut-containers-manager/test-daemon.conf | 1 + .../ut-containers-manager/test-dbus-daemon.conf | 5 +- .../ut-network-admin/containers/buggy.conf.in | 4 +- .../ut-network-admin/containers/missing.conf | 4 +- .../ut-network-admin/containers/test.conf.in | 4 +- .../server/configs/ut-server/buggy-daemon.conf | 1 + .../configs/ut-server/containers/container1.conf | 4 +- .../configs/ut-server/containers/container2.conf | 4 +- .../configs/ut-server/containers/container3.conf | 4 +- .../server/configs/ut-server/test-daemon.conf | 1 + tests/unit_tests/server/ut-containers-manager.cpp | 219 ++++++++++++++++----- tests/unit_tests/utils/ut-fs.cpp | 83 ++++++++ 51 files changed, 636 insertions(+), 102 deletions(-) diff --git a/common/config.hpp b/common/config.hpp index 2ed11a6..0721de4 100644 --- a/common/config.hpp +++ b/common/config.hpp @@ -67,4 +67,11 @@ #define BOOST_PP_VARIADICS 1 #endif +// This has to be defined always when the boost has not been compiled +// using C++11. Headers detect that you are compiling using C++11 and +// blindly and wrongly assume that boost has been as well. +#ifndef BOOST_NO_CXX11_SCOPED_ENUMS +#define BOOST_NO_CXX11_SCOPED_ENUMS 1 +#endif + #endif // COMMON_CONFIG_HPP diff --git a/common/utils/fs.cpp b/common/utils/fs.cpp index 2bae7d6..421ff54 100644 --- a/common/utils/fs.cpp +++ b/common/utils/fs.cpp @@ -28,6 +28,7 @@ #include "utils/paths.hpp" #include "utils/exception.hpp" +#include #include #include #include @@ -135,20 +136,66 @@ bool umount(const std::string& path) bool isMountPoint(const std::string& path, bool& result) { - struct stat stat, parentStat; std::string parentPath = dirName(path); + bool newResult; + bool ret = hasSameMountPoint(path, parentPath, newResult); - if (::stat(path.c_str(), &stat)) { - LOGD("Failed to get stat of " << path << ": " << strerror(errno)); + result = !newResult; + return ret; +} + +bool hasSameMountPoint(const std::string& path1, const std::string& path2, bool& result) +{ + struct stat s1, s2; + + if (::stat(path1.c_str(), &s1)) { + LOGD("Failed to get stat of " << path1 << ": " << strerror(errno)); return false; } - if (::stat(parentPath.c_str(), &parentStat)) { - LOGD("Failed to get stat of " << parentPath << ": " << strerror(errno)); + if (::stat(path2.c_str(), &s2)) { + LOGD("Failed to get stat of " << path2 << ": " << strerror(errno)); return false; } - result = (stat.st_dev != parentStat.st_dev); + result = (s1.st_dev == s2.st_dev); + return true; +} + +bool moveFile(const std::string& src, const std::string& dst) +{ + bool bResult; + + namespace fs = boost::filesystem; + boost::system::error_code error; + + // The destination has to be a full path (including a file name) + // so it doesn't exist yet, we need to check upper level dir instead. + if (!hasSameMountPoint(src, dirName(dst), bResult)) { + LOGE("Failed to check the files' mount points"); + return false; + } + + if (bResult) { + fs::rename(src, dst, error); + if (error) { + LOGE("Failed to rename the file: " << error); + return false; + } + } else { + fs::copy_file(src, dst, error); + if (error) { + LOGE("Failed to copy the file: " << error); + return false; + } + fs::remove(src, error); + if (error) { + LOGE("Failed to remove the file: " << error); + fs::remove(dst, error); + return false; + } + } + return true; } diff --git a/common/utils/fs.hpp b/common/utils/fs.hpp index 8312393..9e69cbd 100644 --- a/common/utils/fs.hpp +++ b/common/utils/fs.hpp @@ -73,6 +73,18 @@ bool umount(const std::string& path); */ bool isMountPoint(const std::string& path, bool& result); +/** + * Checks whether the given paths are under the same mount point + */ +bool hasSameMountPoint(const std::string& path1, const std::string& path2, bool& result); + +/** + * Moves the file either by rename if under the same mount point + * or by copy&delete if under a different one. + * The destination has to be a full path including file name. + */ +bool moveFile(const std::string& src, const std::string& dst); + } // namespace utils } // namespace security_containers diff --git a/container-daemon/CMakeLists.txt b/container-daemon/CMakeLists.txt index d997ab7..3408f43 100644 --- a/container-daemon/CMakeLists.txt +++ b/container-daemon/CMakeLists.txt @@ -29,7 +29,7 @@ ADD_EXECUTABLE(${CONTAINER_DAEMON_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## -FIND_PACKAGE (Boost COMPONENTS program_options) +FIND_PACKAGE (Boost COMPONENTS program_options system filesystem) PKG_CHECK_MODULES(CONTAINER_DAEMON_DEPS REQUIRED gio-2.0 libsystemd-journal) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index d6bcc2c..3afbdd1 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -8,6 +8,7 @@ License: Apache-2.0 Group: Security/Other Summary: Daemon for managing containers BuildRequires: cmake +BuildRequires: boost-devel BuildRequires: libvirt-devel BuildRequires: libjson-devel BuildRequires: pkgconfig(glib-2.0) @@ -123,8 +124,6 @@ Development package including the header files for the client library Summary: Security Containers Containers Daemon Group: Security/Other Requires: security-containers = %{version}-%{release} -BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(libsystemd-journal) %description container-daemon Daemon running inside every container. @@ -144,7 +143,6 @@ Requires: security-containers = %{version}-%{release} Requires: security-containers-client = %{version}-%{release} Requires: python Requires: boost-test -BuildRequires: boost-devel %description tests Unit tests for both: server and client and integration tests. diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index b93b010..595ec72 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -29,6 +29,7 @@ ADD_EXECUTABLE(${SERVER_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## FIND_PACKAGE (Boost COMPONENTS program_options system filesystem regex) + PKG_CHECK_MODULES(SERVER_DEPS REQUIRED libvirt libvirt-glib-1.0 json gio-2.0 libsystemd-journal) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) diff --git a/server/configs/containers/business.conf b/server/configs/containers/business.conf index 8468e2c..fbd1bbb 100644 --- a/server/configs/containers/business.conf +++ b/server/configs/containers/business.conf @@ -4,5 +4,7 @@ "privilege" : 1, "config" : "../libvirt-config/business.xml", "networkConfig" : "../libvirt-config/business-network.xml", - "runMountPoint" : "/var/run/containers/business/run" + "runMountPoint" : "/var/run/containers/business/run", + "permittedToSend" : [ "/tmp/.*" ], + "permittedToRecv" : [ "/tmp/.*" ] } diff --git a/server/configs/containers/private.conf b/server/configs/containers/private.conf index 444638f..a12a847 100644 --- a/server/configs/containers/private.conf +++ b/server/configs/containers/private.conf @@ -4,5 +4,7 @@ "privilege" : 10, "config" : "../libvirt-config/private.xml", "networkConfig" : "../libvirt-config/private-network.xml", - "runMountPoint" : "/var/run/containers/private/run" + "runMountPoint" : "/var/run/containers/private/run", + "permittedToSend" : [ "/tmp/.*" ], + "permittedToRecv" : [ "/tmp/.*" ] } diff --git a/server/configs/daemon.conf b/server/configs/daemon.conf index 591e0b7..94af879 100644 --- a/server/configs/daemon.conf +++ b/server/configs/daemon.conf @@ -1,5 +1,6 @@ { "containerConfigs" : ["containers/private.conf", "containers/business.conf" ], + "containersPath" : "/opt/usr/containers", "foregroundId" : "private", "defaultId" : "private", "inputConfig" : {"enabled" : true, diff --git a/server/configs/libvirt-config/business.xml b/server/configs/libvirt-config/business.xml index 85e9a77..deaf000 100644 --- a/server/configs/libvirt-config/business.xml +++ b/server/configs/libvirt-config/business.xml @@ -101,11 +101,13 @@ + + diff --git a/server/configs/libvirt-config/private.xml b/server/configs/libvirt-config/private.xml index 7561bab..532cd76 100644 --- a/server/configs/libvirt-config/private.xml +++ b/server/configs/libvirt-config/private.xml @@ -101,11 +101,13 @@ + + diff --git a/server/container-config.hpp b/server/container-config.hpp index 2c12363..d5a3038 100644 --- a/server/container-config.hpp +++ b/server/container-config.hpp @@ -29,6 +29,7 @@ #include "config/fields.hpp" #include +#include namespace security_containers { @@ -67,6 +68,18 @@ struct ContainerConfig { */ std::string runMountPoint; + /** + * When you move a file out of the container (by move request) + * its path must match at least one of the regexps in this vector. + */ + std::vector permittedToSend; + + /** + * When you move a file to the container (by move request) + * its path must match at least one of the regexps in this vector. + */ + std::vector permittedToRecv; + CONFIG_REGISTER ( privilege, @@ -74,7 +87,9 @@ struct ContainerConfig { networkConfig, cpuQuotaForeground, cpuQuotaBackground, - runMountPoint + runMountPoint, + permittedToSend, + permittedToRecv ) }; diff --git a/server/container-connection.cpp b/server/container-connection.cpp index cf541f7..3ef2dd7 100644 --- a/server/container-connection.cpp +++ b/server/container-connection.cpp @@ -140,6 +140,12 @@ void ContainerConnection::setDisplayOffCallback(const DisplayOffCallback& callba mDisplayOffCallback = callback; } +void ContainerConnection::setFileMoveRequestCallback( + const FileMoveRequestCallback& callback) +{ + mFileMoveRequestCallback = callback; +} + void ContainerConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, @@ -159,6 +165,15 @@ void ContainerConnection::onMessageCall(const std::string& objectPath, result.setVoid(); } } + + if (methodName == api::METHOD_FILE_MOVE_REQUEST) { + const gchar* destination = NULL; + const gchar* path = NULL; + g_variant_get(parameters, "(&s&s)", &destination, &path); + if (mFileMoveRequestCallback) { + mFileMoveRequestCallback(destination, path, result); + } + } } void ContainerConnection::onSignalReceived(const std::string& senderBusName, diff --git a/server/container-connection.hpp b/server/container-connection.hpp index e0b2467..2f429ce 100644 --- a/server/container-connection.hpp +++ b/server/container-connection.hpp @@ -50,6 +50,11 @@ public: const std::string& message )> NotifyActiveContainerCallback; + typedef std::function FileMoveRequestCallback; + /** * Register notification request callback */ @@ -60,6 +65,11 @@ public: */ void setDisplayOffCallback(const DisplayOffCallback& callback); + /* + * Register file move request callback + */ + void setFileMoveRequestCallback(const FileMoveRequestCallback& callback); + /** * Send notification signal to this container */ @@ -76,6 +86,7 @@ private: OnNameLostCallback mOnNameLostCallback; NotifyActiveContainerCallback mNotifyActiveContainerCallback; DisplayOffCallback mDisplayOffCallback; + FileMoveRequestCallback mFileMoveRequestCallback; void onNameAcquired(); void onNameLost(); diff --git a/server/container-dbus-definitions.hpp b/server/container-dbus-definitions.hpp index 7fec0db..118a348 100644 --- a/server/container-dbus-definitions.hpp +++ b/server/container-dbus-definitions.hpp @@ -37,8 +37,17 @@ const std::string OBJECT_PATH = "/org/tizen/containers"; const std::string INTERFACE = "org.tizen.containers.manager"; const std::string METHOD_NOTIFY_ACTIVE_CONTAINER = "NotifyActiveContainer"; +const std::string METHOD_FILE_MOVE_REQUEST = "FileMoveRequest"; const std::string SIGNAL_NOTIFICATION = "Notification"; +const std::string FILE_MOVE_DESTINATION_NOT_FOUND = "FILE_MOVE_DESTINATION_NOT_FOUND"; +const std::string FILE_MOVE_WRONG_DESTINATION = "FILE_MOVE_WRONG_DESTINATION"; +const std::string FILE_MOVE_NO_PERMISSIONS_SEND = "FILE_MOVE_NO_PERMISSIONS_SEND"; +const std::string FILE_MOVE_NO_PERMISSIONS_RECEIVE = "FILE_MOVE_NO_PERMISSIONS_RECEIVE"; +const std::string FILE_MOVE_FAILED = "FILE_MOVE_FAILED"; +const std::string FILE_MOVE_SUCCEEDED = "FILE_MOVE_SUCCEEDED"; + + const std::string DEFINITION = "" " " @@ -46,6 +55,11 @@ const std::string DEFINITION = " " " " " " + " " + " " + " " + " " + " " " " " " " " diff --git a/server/container.cpp b/server/container.cpp index 2d7114f..ea45b39 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -54,6 +54,13 @@ Container::Container(const std::string& containerConfigPath) { config::loadFromFile(containerConfigPath, mConfig); + for (std::string r: mConfig.permittedToSend) { + mPermittedToSend.push_back(boost::regex(r)); + } + for (std::string r: mConfig.permittedToRecv) { + mPermittedToRecv.push_back(boost::regex(r)); + } + const std::string baseConfigPath = utils::dirName(containerConfigPath); mConfig.config = fs::absolute(mConfig.config, baseConfigPath).string(); mConfig.networkConfig = fs::absolute(mConfig.networkConfig, baseConfigPath).string(); @@ -79,6 +86,16 @@ Container::~Container() } } +const std::vector& Container::getPermittedToSend() const +{ + return mPermittedToSend; +} + +const std::vector& Container::getPermittedToRecv() const +{ + return mPermittedToRecv; +} + const std::string& Container::getId() const { Lock lock(mReconnectMutex); @@ -104,6 +121,9 @@ void Container::start() if (mDisplayOffCallback) { mConnection->setDisplayOffCallback(mDisplayOffCallback); } + if (mFileMoveCallback) { + mConnection->setFileMoveRequestCallback(mFileMoveCallback); + } // Send to the background only after we're connected, // otherwise it'd take ages. @@ -207,7 +227,6 @@ void Container::setNotifyActiveContainerCallback(const NotifyActiveContainerCall if (mConnection) { mConnection->setNotifyActiveContainerCallback(mNotifyCallback); } - } void Container::sendNotification(const std::string& container, @@ -232,5 +251,15 @@ void Container::setDisplayOffCallback(const DisplayOffCallback& callback) } } +void Container::setFileMoveRequestCallback(const FileMoveRequestCallback& callback) +{ + Lock lock(mReconnectMutex); + + mFileMoveCallback = callback; + if (mConnection) { + mConnection->setFileMoveRequestCallback(callback); + } +} + } // namespace security_containers diff --git a/server/container.hpp b/server/container.hpp index 5dbccad..7cc0c5b 100644 --- a/server/container.hpp +++ b/server/container.hpp @@ -35,6 +35,7 @@ #include #include #include +#include namespace security_containers { @@ -49,6 +50,21 @@ public: typedef ContainerConnection::NotifyActiveContainerCallback NotifyActiveContainerCallback; typedef ContainerConnection::DisplayOffCallback DisplayOffCallback; + typedef ContainerConnection::FileMoveRequestCallback FileMoveRequestCallback; + + /** + * Returns a vector of regexps defining files permitted to be + * send to other containers using file move functionality + */ + const std::vector& getPermittedToSend() const; + + /** + * Returns a vector of regexps defining files permitted to be + * send to other containers using file move functionality + */ + const std::vector& getPermittedToRecv() const; + + // ContainerAdmin API /** * Get the container id @@ -109,6 +125,8 @@ public: */ bool isPaused(); + // ContainerConnection API + /** * Register notification request callback */ @@ -130,8 +148,15 @@ public: const std::string& application, const std::string& message); + /** + * Register file move request callback + */ + void setFileMoveRequestCallback(const FileMoveRequestCallback& callback); + private: ContainerConfig mConfig; + std::vector mPermittedToSend; + std::vector mPermittedToRecv; std::unique_ptr mConnectionTransport; std::unique_ptr mNetworkAdmin; std::unique_ptr mAdmin; @@ -140,6 +165,7 @@ private: mutable std::recursive_mutex mReconnectMutex; NotifyActiveContainerCallback mNotifyCallback; DisplayOffCallback mDisplayOffCallback; + FileMoveRequestCallback mFileMoveCallback; void onNameLostCallback(); void reconnectHandler(); diff --git a/server/containers-manager-config.hpp b/server/containers-manager-config.hpp index 9f881c1..c890880 100644 --- a/server/containers-manager-config.hpp +++ b/server/containers-manager-config.hpp @@ -41,11 +41,6 @@ const std::string CONTAINERS_MANAGER_CONFIG_PATH = "/etc/security-containers/con struct ContainersManagerConfig { /** - * Parameters describing input device used to switch between containers - */ - InputConfig inputConfig; - - /** * List of containers' configs that we manage. * File paths can be relative to the ContainerManager config file. */ @@ -61,11 +56,22 @@ struct ContainersManagerConfig { */ std::string defaultId; + /** + * A path where the containers mount points reside. + */ + std::string containersPath; + + /* + * Parameters describing input device used to switch between containers + */ + InputConfig inputConfig; + CONFIG_REGISTER ( containerConfigs, foregroundId, defaultId, + containersPath, inputConfig ) }; diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 13ee3d4..44539da 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -24,6 +24,7 @@ #include "config.hpp" +#include "container-dbus-definitions.hpp" #include "containers-manager.hpp" #include "container-admin.hpp" #include "exception.hpp" @@ -32,6 +33,8 @@ #include "log/logger.hpp" #include "config/manager.hpp" +#include +#include #include #include #include @@ -40,6 +43,21 @@ namespace security_containers { +namespace { + +bool regexMatchVector(const std::string& str, const std::vector& v) +{ + for (const boost::regex& toMatch: v) { + if (boost::regex_match(str, toMatch)) { + return true; + } + } + + return false; +} + +} // namespace + ContainersManager::ContainersManager(const std::string& managerConfigPath): mDetachOnExit(false) { LOGD("Instantiating ContainersManager object..."); @@ -60,14 +78,13 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet std::string id = c->getId(); using namespace std::placeholders; c->setNotifyActiveContainerCallback(bind(&ContainersManager::notifyActiveContainerHandler, - this, - id, - _1, - _2)); + this, id, _1, _2)); c->setDisplayOffCallback(bind(&ContainersManager::displayOffHandler, - this, - id)); + this, id)); + + c->setFileMoveRequestCallback(std::bind(&ContainersManager::handleContainerMoveFileRequest, + this, id, _1, _2, _3)); mContainers.insert(ContainerMap::value_type(id, std::move(c))); } @@ -210,4 +227,84 @@ void ContainersManager::displayOffHandler(const std::string& /*caller*/) focus(mConfig.defaultId); } +void ContainersManager::handleContainerMoveFileRequest(const std::string& srcContainerId, + const std::string& dstContainerId, + const std::string& path, + dbus::MethodResultBuilder& result) +{ + // TODO: this implementation is only a placeholder. + // There are too many unanswered questions and security concerns: + // 1. What about mount namespace, host might not see the source/destination + // file. The file might be a different file from a host perspective. + // 2. Copy vs move (speed and security concerns over already opened FDs) + // 3. Access to source and destination files - DAC, uid/gig + // 4. Access to source and destintation files - MAC, smack + // 5. Destination file uid/gid assignment + // 6. Destination file smack label assignment + // 7. Verifiability of the source path + + // NOTE: other possible implementations include: + // 1. Sending file descriptors opened directly in each container through DBUS + // using something like g_dbus_message_set_unix_fd_list() + // 2. SCS forking and calling setns(MNT) in each container and opening files + // by itself, then passing FDs to the main process + // Now when the main process has obtained FDs (by either of those methods) + // it can do the copying by itself. + + LOGI("File move requested\n" + << "src: " << srcContainerId << "\n" + << "dst: " << dstContainerId << "\n" + << "path: " << path); + + ContainerMap::const_iterator srcIter = mContainers.find(srcContainerId); + if (srcIter == mContainers.end()) { + LOGE("Source container '" << srcContainerId << "' not found"); + return; + } + Container& srcContainer = *srcIter->second; + + ContainerMap::const_iterator dstIter = mContainers.find(dstContainerId); + if (dstIter == mContainers.end()) { + LOGE("Destination container '" << dstContainerId << "' not found"); + result.set(g_variant_new("(s)", api::FILE_MOVE_DESTINATION_NOT_FOUND.c_str())); + return; + } + Container& dstContanier = *dstIter->second; + + if (srcContainerId == dstContainerId) { + LOGE("Cannot send a file to yourself"); + result.set(g_variant_new("(s)", api::FILE_MOVE_WRONG_DESTINATION.c_str())); + return; + } + + if (!regexMatchVector(path, srcContainer.getPermittedToSend())) { + LOGE("Source container has no permissions to send the file: " << path); + result.set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_SEND.c_str())); + return; + } + + if (!regexMatchVector(path, dstContanier.getPermittedToRecv())) { + LOGE("Destination container has no permissions to receive the file: " << path); + result.set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_RECEIVE.c_str())); + return; + } + + namespace fs = boost::filesystem; + std::string srcPath = fs::absolute(srcContainerId, mConfig.containersPath).string() + path; + std::string dstPath = fs::absolute(dstContainerId, mConfig.containersPath).string() + path; + + if (!utils::moveFile(srcPath, dstPath)) { + LOGE("Failed to move the file: " << path); + result.set(g_variant_new("(s)", api::FILE_MOVE_FAILED.c_str())); + } else { + result.set(g_variant_new("(s)", api::FILE_MOVE_SUCCEEDED.c_str())); + try { + dstContanier.sendNotification(srcContainerId, path, api::FILE_MOVE_SUCCEEDED); + } catch (ServerException&) { + LOGE("Notification to '" << dstContainerId << "' has not been sent"); + } + } +} + + } // namespace security_containers diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index 316e7bb..1a1af88 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -86,6 +86,10 @@ private: const std::string& appliaction, const std::string& message); void displayOffHandler(const std::string& caller); + void handleContainerMoveFileRequest(const std::string& srcContainerId, + const std::string& dstContainerId, + const std::string& path, + dbus::MethodResultBuilder& result); }; diff --git a/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in b/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in index 8617125..e06bf63 100644 --- a/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in +++ b/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in @@ -4,5 +4,7 @@ "networkConfig" : "", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf b/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf index 9add4c3..55d6852 100644 --- a/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf +++ b/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf @@ -4,5 +4,7 @@ "networkConfig" : "", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in b/tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in index a7bccd0..6d01a50 100644 --- a/tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in +++ b/tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in @@ -4,5 +4,7 @@ "networkConfig" : "", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in b/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in index 0ad824e..518aa4c 100644 --- a/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in +++ b/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in @@ -4,5 +4,7 @@ "networkConfig" : "", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-container/containers/buggy.conf b/tests/unit_tests/server/configs/ut-container/containers/buggy.conf index fdb3ce8..d5ccd1e 100644 --- a/tests/unit_tests/server/configs/ut-container/containers/buggy.conf +++ b/tests/unit_tests/server/configs/ut-container/containers/buggy.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf b/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf index f4b38f9..fde05d8 100644 --- a/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf +++ b/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "/tmp/ut-container" + "runMountPoint" : "/tmp/ut-container", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-container/containers/test.conf b/tests/unit_tests/server/configs/ut-container/containers/test.conf index 458bca4..e1769c3 100644 --- a/tests/unit_tests/server/configs/ut-container/containers/test.conf +++ b/tests/unit_tests/server/configs/ut-container/containers/test.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf index a403aa8..8e89f50 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf @@ -2,6 +2,7 @@ "containerConfigs" : ["containers/console1.conf", "missing/file/path/missing.conf", "containers/console3.conf"], "foregroundId" : "ut-containers-manager-console1", "defaultId" : "ut-containers-manager-console1", + "containersPath" : "/tmp", "inputConfig" : {"enabled" : false, "device" : "/dev/doesnotexist", "code" : 139, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/buggy-default-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/buggy-default-daemon.conf index 39d56df..51b2bbd 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/buggy-default-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/buggy-default-daemon.conf @@ -1,7 +1,8 @@ { - "containerConfigs" : ["containers/console1-dbus.conf", "containers/console2-dbus.conf", "containers/console3-dbus.conf"], + "containerConfigs" : ["containers/console1.conf", "containers/console2.conf", "containers/console3.conf"], "foregroundId" : "ut-containers-manager-console1", "defaultId" : "in_no_way_there_is_a_valid_id_here", + "containersPath" : "/tmp", "inputConfig" : {"enabled" : false, "device" : "/dev/doesnotexist", "code" : 139, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf index e12964a..c62daad 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf @@ -2,6 +2,7 @@ "containerConfigs" : ["containers/console1.conf", "containers/console2.conf", "containers/console3.conf"], "foregroundId" : "this_id_does_not_exist", "defaultId" : "ut-containers-manager-console1", + "containersPath" : "/tmp", "inputConfig" : {"enabled" : false, "device" : "/dev/doesnotexist", "code" : 139, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console1-dbus.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1-dbus.conf index fc12fec..55dfeb5 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console1-dbus.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1-dbus.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network1.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "/tmp/ut-containers-manager/console1-dbus" + "runMountPoint" : "/tmp/ut-containers-manager/console1-dbus", + "permittedToSend" : [ "/tmp/.*", "/etc/secret2" ], + "permittedToRecv" : [ "/tmp/.*" ] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf index 47bbf5c..61668c8 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network1.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [ "/tmp/.*" ], + "permittedToRecv" : [ "/tmp/.*" ] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console2-dbus.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2-dbus.conf index 41988e6..713cb02 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console2-dbus.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2-dbus.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network2.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "/tmp/ut-containers-manager/console2-dbus" + "runMountPoint" : "/tmp/ut-containers-manager/console2-dbus", + "permittedToSend" : [ "/tmp/.*" ], + "permittedToRecv" : [ "/tmp/.*", "/etc/secret1" ] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf index 3bf1623..10e5cef 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network2.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [ "/tmp/.*" ], + "permittedToRecv" : [ "/tmp/.*" ] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console3-dbus.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3-dbus.conf index 8ebdfaa..70ff251 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console3-dbus.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3-dbus.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network3.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "/tmp/ut-containers-manager/console3-dbus" + "runMountPoint" : "/tmp/ut-containers-manager/console3-dbus", + "permittedToSend" : [ "/tmp/.*" ], + "permittedToRecv" : [ "/tmp/.*" ] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf index 0a90aff..8ccf55b 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network3.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [ "/tmp/.*" ], + "permittedToRecv" : [ "/tmp/.*" ] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console1-dbus.xml.in b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console1-dbus.xml.in index 7aea75f..6d24978 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console1-dbus.xml.in +++ b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console1-dbus.xml.in @@ -1,5 +1,5 @@ - ut-containers-manager-console1 + ut-containers-manager-console1-dbus 58184009-b278-4d01-975d-708393690084 102400 diff --git a/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console2-dbus.xml.in b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console2-dbus.xml.in index 0336d3d..5fe2996 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console2-dbus.xml.in +++ b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console2-dbus.xml.in @@ -1,5 +1,5 @@ - ut-containers-manager-console2 + ut-containers-manager-console2-dbus 3d18323e-4ada-4a1b-a907-836701891306 102400 diff --git a/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console3-dbus.xml.in b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console3-dbus.xml.in index 0b65ad4..be4d618 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console3-dbus.xml.in +++ b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console3-dbus.xml.in @@ -1,5 +1,5 @@ - ut-containers-manager-console3 + ut-containers-manager-console3-dbus 71cb8511-7474-4e90-865a-3360b7f77254 102400 diff --git a/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf index 4ffe017..7908dea 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf @@ -2,6 +2,7 @@ "containerConfigs" : ["containers/console1.conf", "containers/console2.conf", "containers/console3.conf"], "foregroundId" : "ut-containers-manager-console1", "defaultId" : "ut-containers-manager-console1", + "containersPath" : "/tmp", "inputConfig" : {"enabled" : false, "device" : "/dev/doesnotexist", "code" : 139, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/test-dbus-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/test-dbus-daemon.conf index ae59483..5466f3d 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/test-dbus-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/test-dbus-daemon.conf @@ -2,8 +2,9 @@ "containerConfigs" : ["containers/console1-dbus.conf", "containers/console2-dbus.conf", "containers/console3-dbus.conf"], - "foregroundId" : "ut-containers-manager-console1", - "defaultId" : "ut-containers-manager-console1", + "foregroundId" : "ut-containers-manager-console1-dbus", + "defaultId" : "ut-containers-manager-console1-dbus", + "containersPath" : "/tmp", "inputConfig" : {"enabled" : false, "device" : "/dev/doesnotexist", "code" : 139, diff --git a/tests/unit_tests/server/configs/ut-network-admin/containers/buggy.conf.in b/tests/unit_tests/server/configs/ut-network-admin/containers/buggy.conf.in index 1078859..be3f7c1 100644 --- a/tests/unit_tests/server/configs/ut-network-admin/containers/buggy.conf.in +++ b/tests/unit_tests/server/configs/ut-network-admin/containers/buggy.conf.in @@ -4,5 +4,7 @@ "networkConfig" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-network-admin/libvirt-config/buggy-network.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-network-admin/containers/missing.conf b/tests/unit_tests/server/configs/ut-network-admin/containers/missing.conf index cc31322..f418503 100644 --- a/tests/unit_tests/server/configs/ut-network-admin/containers/missing.conf +++ b/tests/unit_tests/server/configs/ut-network-admin/containers/missing.conf @@ -4,5 +4,7 @@ "networkConfig" : "", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-network-admin/containers/test.conf.in b/tests/unit_tests/server/configs/ut-network-admin/containers/test.conf.in index f680989..771a93b 100644 --- a/tests/unit_tests/server/configs/ut-network-admin/containers/test.conf.in +++ b/tests/unit_tests/server/configs/ut-network-admin/containers/test.conf.in @@ -4,5 +4,7 @@ "networkConfig" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-network-admin/libvirt-config/network.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf b/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf index 47b4450..41cfc2f 100644 --- a/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf +++ b/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf @@ -1,5 +1,6 @@ { "containerConfigs" : ["containers/container1.conf", "missing/file/path/missing.conf", "containers/container3.conf"], + "containersPath" : "/tmp", "foregroundId" : "ut-server-container1", "defaultId" : "ut-server-container1", "inputConfig" : {"enabled" : false, diff --git a/tests/unit_tests/server/configs/ut-server/containers/container1.conf b/tests/unit_tests/server/configs/ut-server/containers/container1.conf index 0b18659..952decf 100644 --- a/tests/unit_tests/server/configs/ut-server/containers/container1.conf +++ b/tests/unit_tests/server/configs/ut-server/containers/container1.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network1.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-server/containers/container2.conf b/tests/unit_tests/server/configs/ut-server/containers/container2.conf index b5bab4d..4e6de09 100644 --- a/tests/unit_tests/server/configs/ut-server/containers/container2.conf +++ b/tests/unit_tests/server/configs/ut-server/containers/container2.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network2.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-server/containers/container3.conf b/tests/unit_tests/server/configs/ut-server/containers/container3.conf index 3a1ae36..9170c54 100644 --- a/tests/unit_tests/server/configs/ut-server/containers/container3.conf +++ b/tests/unit_tests/server/configs/ut-server/containers/container3.conf @@ -4,5 +4,7 @@ "networkConfig" : "../libvirt-config/network3.xml", "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, - "runMountPoint" : "" + "runMountPoint" : "", + "permittedToSend" : [], + "permittedToRecv" : [] } diff --git a/tests/unit_tests/server/configs/ut-server/test-daemon.conf b/tests/unit_tests/server/configs/ut-server/test-daemon.conf index 360bab7..8935030 100644 --- a/tests/unit_tests/server/configs/ut-server/test-daemon.conf +++ b/tests/unit_tests/server/configs/ut-server/test-daemon.conf @@ -1,5 +1,6 @@ { "containerConfigs" : ["containers/container1.conf", "containers/container2.conf", "containers/container3.conf"], + "containersPath" : "/tmp", "foregroundId" : "ut-server-container1", "defaultId" : "ut-server-container1", "inputConfig" : {"enabled" : false, diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index 61eea40..0182cb8 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -37,14 +37,17 @@ #include "utils/glib-loop.hpp" #include "config/exception.hpp" #include "utils/latch.hpp" +#include "utils/fs.hpp" +#include +#include #include #include #include #include #include #include - +#include using namespace security_containers; using namespace security_containers::config; @@ -63,12 +66,13 @@ const int EVENT_TIMEOUT = 5000; const int TEST_DBUS_CONNECTION_CONTAINERS_COUNT = 3; const std::string PREFIX_CONSOLE_NAME = "ut-containers-manager-console"; const std::string TEST_APP_NAME = "testapp"; -const std::string TEST_MESSGAE = "testmessage"; +const std::string TEST_MESSAGE = "testmessage"; +const std::string FILE_CONTENT = "File content\n" + "Line 1\n" + "Line 2\n"; class DbusAccessory { public: - std::vector mReceivedSignalsSource; - DbusAccessory(int id) : mId(id), mClient(DbusConnection::create(acquireAddress())), @@ -110,12 +114,9 @@ public: mNameCondition.notify_one(); } - void signalSubscribe(Latch& referenceLatch) + void signalSubscribe(const DbusConnection::SignalCallback& callback) { - using namespace std::placeholders; - mClient->signalSubscribe(std::bind(&DbusAccessory::handler, - this, std::ref(referenceLatch), _1, _2, _3, _4, _5), - api::BUS_NAME); + mClient->signalSubscribe(callback, api::BUS_NAME); } void emitSignal(const std::string& objectPath, @@ -126,9 +127,9 @@ public: mClient->emitSignal(objectPath, interface, name, parameters); } - void callMethod() + void callMethodNotify() { - GVariant* parameters = g_variant_new("(ss)", TEST_APP_NAME.c_str(), TEST_MESSGAE.c_str()); + GVariant* parameters = g_variant_new("(ss)", TEST_APP_NAME.c_str(), TEST_MESSAGE.c_str()); mClient->callMethod(api::BUS_NAME, api::OBJECT_PATH, api::INTERFACE, @@ -137,9 +138,19 @@ public: "()"); } - std::string getContainerName() const + std::string callMethodMove(const std::string& dest, const std::string& path) { - return PREFIX_CONSOLE_NAME + std::to_string(mId); + GVariant* parameters = g_variant_new("(ss)", dest.c_str(), path.c_str()); + GVariantPtr result = mClient->callMethod(api::BUS_NAME, + api::OBJECT_PATH, + api::INTERFACE, + api::METHOD_FILE_MOVE_REQUEST, + parameters, + "(s)"); + + const gchar* retcode = NULL; + g_variant_get(result.get(), "(&s)", &retcode); + return std::string(retcode); } private: @@ -155,29 +166,6 @@ private: return "unix:path=/tmp/ut-containers-manager/console" + std::to_string(mId) + "-dbus/dbus/system_bus_socket"; } - - void handler(Latch& referenceLatch, - const std::string& /*senderBusName*/, - const std::string& objectPath, - const std::string& interface, - const std::string& signalName, - GVariant* parameters) - { - if (objectPath == api::OBJECT_PATH && - interface == api::INTERFACE && - signalName == api::SIGNAL_NOTIFICATION && - g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) { - - const gchar* container = NULL; - const gchar* application = NULL; - const gchar* message = NULL; - g_variant_get(parameters, "(&s&s&s)", &container, &application, &message); - mReceivedSignalsSource.push_back(container); - if (application == TEST_APP_NAME && message == TEST_MESSGAE) { - referenceLatch.set(); - } - } - } }; @@ -262,36 +250,65 @@ BOOST_AUTO_TEST_CASE(FocusTest) BOOST_AUTO_TEST_CASE(NotifyActiveContainerTest) { - Latch signalReceivedLatch; - ContainersManager cm(TEST_DBUS_CONFIG_PATH); cm.startAll(); - std::vector< std::unique_ptr > dbuses; + std::map> dbuses; for (int i = 1; i <= TEST_DBUS_CONNECTION_CONTAINERS_COUNT; ++i) { - dbuses.push_back(std::unique_ptr(new DbusAccessory(i))); + dbuses[i] = std::unique_ptr(new DbusAccessory(i)); } - for (auto& dbus : dbuses) { - dbus->signalSubscribe(signalReceivedLatch); + + Latch signalReceivedLatch; + std::map> signalReceivedSourcesMap; + auto handler = [](Latch& latch, + std::vector& receivedSignalSources, + const std::string& /*senderBusName*/, + const std::string& objectPath, + const std::string& interface, + const std::string& signalName, + GVariant* parameters) + { + if (objectPath == api::OBJECT_PATH && + interface == api::INTERFACE && + signalName == api::SIGNAL_NOTIFICATION && + g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) { + + const gchar* container = NULL; + const gchar* application = NULL; + const gchar* message = NULL; + g_variant_get(parameters, "(&s&s&s)", &container, &application, &message); + receivedSignalSources.push_back(container); + if (application == TEST_APP_NAME && message == TEST_MESSAGE) { + latch.set(); + } + } + }; + + using namespace std::placeholders; + for (int i = 1; i <= TEST_DBUS_CONNECTION_CONTAINERS_COUNT; ++i) { + dbuses[i]->signalSubscribe(std::bind(handler, + std::ref(signalReceivedLatch), + std::ref(signalReceivedSourcesMap[i]), + _1, _2, _3, _4, _5)); } for (auto& dbus : dbuses) { - dbus->callMethod(); + dbus.second->callMethodNotify(); } BOOST_CHECK(signalReceivedLatch.waitForN(dbuses.size() - 1, EVENT_TIMEOUT)); BOOST_CHECK(signalReceivedLatch.empty()); //check if there are no signals that was received more than once - for (const auto& source : dbuses[0]->mReceivedSignalsSource) { - BOOST_CHECK_EQUAL(std::count(dbuses[0]->mReceivedSignalsSource.begin(), - dbuses[0]->mReceivedSignalsSource.end(), - source), 1); + for (const auto& source : signalReceivedSourcesMap[1]) { + BOOST_CHECK_EQUAL(std::count(signalReceivedSourcesMap[1].begin(), + signalReceivedSourcesMap[1].end(), + source), 1); } //check if all signals was received by active container - BOOST_CHECK_EQUAL(dbuses[0]->mReceivedSignalsSource.size(), dbuses.size() - 1); + BOOST_CHECK_EQUAL(signalReceivedSourcesMap[1].size(), dbuses.size() - 1); //check if no signals was received by inactive container - for (size_t i = 1; i < dbuses.size(); ++i) { - BOOST_CHECK(dbuses[i]->mReceivedSignalsSource.empty()); + for (size_t i = 2; i <= dbuses.size(); ++i) { + BOOST_CHECK(signalReceivedSourcesMap[i].empty()); } dbuses.clear(); @@ -315,13 +332,13 @@ BOOST_AUTO_TEST_CASE(DisplayOffTest) std::unique_lock Lock(Mutex); std::condition_variable Condition; auto cond = [&cm]() -> bool { - return cm.getRunningForegroundContainerId() == "ut-containers-manager-console1"; + return cm.getRunningForegroundContainerId() == "ut-containers-manager-console1-dbus"; }; for (auto& client : clients) { // TEST SWITCHING TO DEFAULT CONTAINER // focus non-default container - BOOST_REQUIRE_NO_THROW(cm.focus("ut-containers-manager-console3")); + BOOST_REQUIRE_NO_THROW(cm.focus("ut-containers-manager-console3-dbus")); // emit signal from dbus connection BOOST_REQUIRE_NO_THROW(client->emitSignal(fake_power_manager_api::OBJECT_PATH, @@ -334,4 +351,102 @@ BOOST_AUTO_TEST_CASE(DisplayOffTest) } } +BOOST_AUTO_TEST_CASE(MoveFileTest) +{ + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + cm.startAll(); + + std::map> dbuses; + for (int i = 1; i <= 2; ++i) { + dbuses[i] = std::unique_ptr(new DbusAccessory(i)); + } + + Latch notificationLatch; + std::string notificationSource; + std::string notificationPath; + std::string notificationRetcode; + auto handler = [&](const std::string& /*senderBusName*/, + const std::string& objectPath, + const std::string& interface, + const std::string& signalName, + GVariant* parameters) + { + if (objectPath == api::OBJECT_PATH && + interface == api::INTERFACE && + signalName == api::SIGNAL_NOTIFICATION && + g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) { + + const gchar* source = NULL; + const gchar* path = NULL; + const gchar* retcode = NULL; + g_variant_get(parameters, "(&s&s&s)", &source, &path, &retcode); + + notificationSource = source; + notificationPath = path; + notificationRetcode = retcode; + notificationLatch.set(); + } + }; + + // subscribe the second (destination) container for notifications + dbuses.at(2)->signalSubscribe(handler); + + const std::string TMP = "/tmp"; + const std::string NO_PATH = "path_doesnt_matter_here"; + const std::string BUGGY_PATH = TMP + "/this_file_does_not_exist"; + const std::string BUGGY_CONTAINER = "this-container-does-not-exist"; + const std::string CONTAINER1 = "ut-containers-manager-console1-dbus"; + const std::string CONTAINER2 = "ut-containers-manager-console2-dbus"; + const std::string CONTAINER1PATH = TMP + "/" + CONTAINER1 + TMP; + const std::string CONTAINER2PATH = TMP + "/" + CONTAINER2 + TMP; + + // sending to a non existing container + BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(BUGGY_CONTAINER, NO_PATH), + api::FILE_MOVE_DESTINATION_NOT_FOUND); + BOOST_CHECK(notificationLatch.empty()); + + // sending to self + BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER1, NO_PATH), + api::FILE_MOVE_WRONG_DESTINATION); + BOOST_CHECK(notificationLatch.empty()); + + // no permission to send + BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER2, "/etc/secret1"), + api::FILE_MOVE_NO_PERMISSIONS_SEND); + BOOST_CHECK(notificationLatch.empty()); + + // no permission to receive + BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER2, "/etc/secret2"), + api::FILE_MOVE_NO_PERMISSIONS_RECEIVE); + BOOST_CHECK(notificationLatch.empty()); + + // non existing file + BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER2, BUGGY_PATH), + api::FILE_MOVE_FAILED); + BOOST_CHECK(notificationLatch.empty()); + + // a working scenario + namespace fs = boost::filesystem; + boost::system::error_code ec; + fs::remove_all(CONTAINER1PATH, ec); + fs::remove_all(CONTAINER2PATH, ec); + BOOST_REQUIRE(fs::create_directories(CONTAINER1PATH, ec)); + BOOST_REQUIRE(fs::create_directories(CONTAINER2PATH, ec)); + BOOST_REQUIRE(utils::saveFileContent(CONTAINER1PATH + "/file", FILE_CONTENT)); + + BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER2, TMP + "/file"), + api::FILE_MOVE_SUCCEEDED); + BOOST_CHECK(notificationLatch.wait(EVENT_TIMEOUT)); + BOOST_CHECK(notificationLatch.empty()); + BOOST_CHECK_EQUAL(notificationSource, CONTAINER1); + BOOST_CHECK_EQUAL(notificationPath, TMP + "/file"); + BOOST_CHECK_EQUAL(notificationRetcode, api::FILE_MOVE_SUCCEEDED); + BOOST_CHECK(!fs::exists(CONTAINER1PATH + "/file")); + BOOST_CHECK_EQUAL(utils::readFileContent(CONTAINER2PATH + "/file"), FILE_CONTENT); + + fs::remove_all(CONTAINER1PATH, ec); + fs::remove_all(CONTAINER2PATH, ec); +} + + BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/unit_tests/utils/ut-fs.cpp b/tests/unit_tests/utils/ut-fs.cpp index adc8797..8f7c965 100644 --- a/tests/unit_tests/utils/ut-fs.cpp +++ b/tests/unit_tests/utils/ut-fs.cpp @@ -30,17 +30,34 @@ #include "utils/exception.hpp" #include +#include +#include BOOST_AUTO_TEST_SUITE(UtilsFSSuite) using namespace security_containers; using namespace security_containers::utils; +namespace { + const std::string FILE_PATH = SC_TEST_CONFIG_INSTALL_DIR "/utils/ut-fs/file.txt"; const std::string FILE_CONTENT = "File content\n" "Line 1\n" "Line 2\n"; const std::string BUGGY_FILE_PATH = "/some/missing/file/path/file.txt"; +const std::string TMP_PATH = "/tmp"; +const std::string FILE_PATH_RANDOM = + boost::filesystem::unique_path("/tmp/testFile-%%%%").string(); +const std::string MOUNT_POINT_RANDOM_1 = + boost::filesystem::unique_path("/tmp/mountPoint-%%%%").string(); +const std::string MOUNT_POINT_RANDOM_2 = + boost::filesystem::unique_path("/tmp/mountPoint-%%%%").string(); +const std::string FILE_NAME_RANDOM_1 = + boost::filesystem::unique_path("testFile-%%%%").string(); +const std::string FILE_NAME_RANDOM_2 = + boost::filesystem::unique_path("testFile-%%%%").string(); + +} // namespace BOOST_AUTO_TEST_CASE(ReadFileContentTest) { @@ -48,4 +65,70 @@ BOOST_AUTO_TEST_CASE(ReadFileContentTest) BOOST_CHECK_THROW(readFileContent(BUGGY_FILE_PATH), UtilsException); } +BOOST_AUTO_TEST_CASE(SaveFileContentTest) +{ + BOOST_REQUIRE(saveFileContent(FILE_PATH_RANDOM, FILE_CONTENT)); + BOOST_CHECK_EQUAL(FILE_CONTENT, readFileContent(FILE_PATH)); + + boost::system::error_code ec; + boost::filesystem::remove(FILE_PATH_RANDOM, ec); +} + +BOOST_AUTO_TEST_CASE(MountPointTest) +{ + bool result; + namespace fs = boost::filesystem; + boost::system::error_code ec; + + BOOST_REQUIRE(fs::create_directory(MOUNT_POINT_RANDOM_1, ec)); + BOOST_REQUIRE(isMountPoint(MOUNT_POINT_RANDOM_1, result)); + BOOST_CHECK_EQUAL(result, false); + BOOST_REQUIRE(hasSameMountPoint(TMP_PATH, MOUNT_POINT_RANDOM_1, result)); + BOOST_CHECK_EQUAL(result, true); + + BOOST_REQUIRE(mountRun(MOUNT_POINT_RANDOM_1)); + BOOST_REQUIRE(isMountPoint(MOUNT_POINT_RANDOM_1, result)); + BOOST_CHECK_EQUAL(result, true); + BOOST_REQUIRE(hasSameMountPoint(TMP_PATH, MOUNT_POINT_RANDOM_1, result)); + BOOST_CHECK_EQUAL(result, false); + + BOOST_REQUIRE(umount(MOUNT_POINT_RANDOM_1)); + BOOST_REQUIRE(fs::remove(MOUNT_POINT_RANDOM_1, ec)); +} + +BOOST_AUTO_TEST_CASE(MoveFileTest) +{ + namespace fs = boost::filesystem; + boost::system::error_code ec; + std::string src, dst; + + // same mount point + src = TMP_PATH + "/" + FILE_NAME_RANDOM_1; + dst = TMP_PATH + "/" + FILE_NAME_RANDOM_2; + + BOOST_REQUIRE(saveFileContent(src, FILE_CONTENT)); + + BOOST_CHECK(moveFile(src, dst)); + BOOST_CHECK(!fs::exists(src)); + BOOST_CHECK_EQUAL(readFileContent(dst), FILE_CONTENT); + + BOOST_REQUIRE(fs::remove(dst)); + + // different mount point + src = TMP_PATH + "/" + FILE_NAME_RANDOM_1; + dst = MOUNT_POINT_RANDOM_2 + "/" + FILE_NAME_RANDOM_2; + + BOOST_REQUIRE(fs::create_directory(MOUNT_POINT_RANDOM_2, ec)); + BOOST_REQUIRE(mountRun(MOUNT_POINT_RANDOM_2)); + BOOST_REQUIRE(saveFileContent(src, FILE_CONTENT)); + + BOOST_CHECK(moveFile(src, dst)); + BOOST_CHECK(!fs::exists(src)); + BOOST_CHECK_EQUAL(readFileContent(dst), FILE_CONTENT); + + BOOST_REQUIRE(fs::remove(dst)); + BOOST_REQUIRE(umount(MOUNT_POINT_RANDOM_2)); + BOOST_REQUIRE(fs::remove(MOUNT_POINT_RANDOM_2, ec)); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4