#
-# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2015-2019 Samsung Electronics Co., Ltd All Rights Reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
SET(KEY_STORAGE_PLUGIN_DIR "${CMAKE_INSTALL_LIBDIR}/ode-key-storage-plugin")
ENDIF(NOT DEFINED KEY_STORAGE_PLUGIN_DIR)
+IF(NOT DEFINED SOCKET_PATH)
+ SET(SOCKET_PATH "${RUN_DIR}/.ode.sock")
+ENDIF(NOT DEFINED SOCKET_PATH)
+
SET(KEY_STORAGE_PLUGIN "key-storage-plugin")
ADD_DEFINITIONS(-DKEY_STORAGE_PLUGIN_DIR="${KEY_STORAGE_PLUGIN_DIR}")
ADD_DEFINITIONS(-DKEY_STORAGE_PLUGIN_LIB="${CMAKE_SHARED_LIBRARY_PREFIX}${KEY_STORAGE_PLUGIN}${CMAKE_SHARED_LIBRARY_SUFFIX}")
ADD_DEFINITIONS(-DUG_WAYLAND)
+ADD_DEFINITIONS(-DSOCKET_PATH="${SOCKET_PATH}")
ADD_SUBDIRECTORY(${ODE_LIB})
ADD_SUBDIRECTORY(${ODE_KEY_STORAGE_PLUGIN})
/*
- * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "client.h"
-namespace {
-
-const std::string ODE_MANAGER_ADDRESS = "/tmp/.ode.sock";
-
-} // namespace
-
-
ClientContext::ClientContext() noexcept
{
}
int ClientContext::connect() noexcept
{
- return connect(ODE_MANAGER_ADDRESS);
+ return connect(SOCKET_PATH);
}
void ClientContext::disconnect() noexcept
%global key_storage_plugin_dir %{_libdir}/ode-key-storage-plugin/
%global softreset_dir /usr/system/RestoreDir/softreset/
%define upgrade_script_dir /usr/share/upgrade/scripts/
+%global socket_path %{TZ_SYS_RUN}/.ode.sock
%description
The ode package provides a daemon which is responsible for encrypting/decryption storages and secure erasing.
%defattr(644,root,root,755)
%attr(755,root,root) %{_bindir}/oded
%{_unitdir}/ode.service
-%{_unitdir}/multi-user.target.wants/ode.service
+%{_unitdir}/ode.socket
%attr(700,root,root) %{TZ_SYS_SBIN}/ode-admin-cli
%attr(700,root,root) %{softreset_dir}/ode_softreset.sh
%attr(750,root,system_share) %{TZ_SYS_SBIN}/ode-fota
-DAPP_SHARE_PACKAGES_DIR="%{TZ_SYS_RO_PACKAGES}" \
-DSOFTRESET_DIR="%{softreset_dir}" \
-DKEY_STORAGE_PLUGIN_DIR="%{key_storage_plugin_dir}" \
- -DUPGRADE_SCRIPT_DIR="%{upgrade_script_dir}"
+ -DUPGRADE_SCRIPT_DIR="%{upgrade_script_dir}" \
+ -DSOCKET_PATH="%{socket_path}"
make %{?jobs:-j%jobs}
%install
%make_install
-%install_service multi-user.target.wants ode.service
%clean
rm -rf %{buildroot}
+%pre
+if [ $1 = 2 ]; then
+ # upgrade
+ systemctl stop ode.service
+fi
+
%post
-systemctl daemon-reload
+systemctl enable ode.socket
if [ $1 = 1 ]; then
# installation
- systemctl start ode.service
+ systemctl start ode.socket
elif [ $1 = 2 ]; then
# update
- systemctl restart ode.service
+ systemctl daemon-reload
+ systemctl restart ode.socket
fi
%preun
if [ $1 = 0 ]; then
- # unistall
+ # uninstall
+ systemctl disable ode.socket
+ systemctl stop ode.socket
systemctl stop ode.service
fi
-%postun
-
## ODE Client Package ########################################################
%package -n libode
Summary: Library for Tizen device encryption and secure erase
)
CONFIGURE_FILE(systemd/${PROJECT_NAME}.service.in systemd/${PROJECT_NAME}.service)
+CONFIGURE_FILE(systemd/${PROJECT_NAME}.socket.in systemd/${PROJECT_NAME}.socket)
INSTALL(TARGETS ${SERVER_NAME} DESTINATION ${BIN_DIR})
-INSTALL(FILES systemd/${PROJECT_NAME}.service DESTINATION ${SYSTEMD_UNIT_DIR})
+INSTALL(FILES systemd/${PROJECT_NAME}.service systemd/${PROJECT_NAME}.socket DESTINATION ${SYSTEMD_UNIT_DIR})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/engine/encryption/dummy_password DESTINATION ${PROJECT_DATA_DIR})
INSTALL(DIRECTORY DESTINATION ${KEY_STORAGE_PLUGIN_DIR})
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
int ExternalEncryptionServer::setMountPassword(const std::string& password)
{
+ RequestLifetime rl(server);
+
return keyServer.get(engine->getSource(), password, mountKey);
}
int ExternalEncryptionServer::mount()
{
+ RequestLifetime rl(server);
+
if (mountKey.empty()) {
ERROR(SINK, "You need to call set_mount_password() first.");
return error::NoData;
BinaryData key = mountKey;
mountKey.clear();
- if (getState() != State::Encrypted) {
+ if (getStateInternal() != State::Encrypted) {
ERROR(SINK, "Cannot mount, SD card's state incorrect.");
return error::NoSuchDevice;
}
int ExternalEncryptionServer::umount()
{
- if (getState() != State::Encrypted) {
+ RequestLifetime rl(server);
+
+ if (getStateInternal() != State::Encrypted) {
ERROR(SINK, "Cannot umount, SD card's state incorrect.");
return error::NoSuchDevice;
}
int ExternalEncryptionServer::encrypt(const std::string &password, unsigned int options)
{
- if (getState() != State::Unencrypted) {
+ RequestLifetime rl(server);
+
+ if (getStateInternal() != State::Unencrypted) {
INFO(SINK, "Cannot encrypt, SD card's state incorrect.");
return error::NoSuchDevice;
}
if (ret != error::None)
return ret;
- auto encryptWorker = [masterKey, options, this]() {
+ auto encryptWorker = [masterKey, options, this](RequestLifetime&& rl) {
try {
INFO(SINK, "Closing all applications using external storage.");
killDependentApplications(EXTERNAL_PATH);
INFO(SINK, "Encryption started.");
engine->encrypt(masterKey, options);
- setOptions(options & getSupportedOptions());
+ setOptions(options & engine->getSupportedOptions());
INFO(SINK, "Encryption completed.");
::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "encrypted");
}
};
- std::thread asyncWork(encryptWorker);
+ std::thread asyncWork(encryptWorker, std::move(rl));
asyncWork.detach();
return error::None;
int ExternalEncryptionServer::decrypt(const std::string &password)
{
- if (getState() != State::Encrypted) {
+ RequestLifetime rl(server);
+
+ if (getStateInternal() != State::Encrypted) {
ERROR(SINK, "Cannot decrypt, SD card's state incorrect.");
return error::NoSuchDevice;
}
if (ret != error::None)
return ret;
- auto decryptWorker = [masterKey, this]() {
+ auto decryptWorker = [masterKey, this](RequestLifetime&& rl) {
try {
INFO(SINK, "Closing all applications using external storage.");
killDependentApplications(EXTERNAL_PATH);
}
};
- std::thread asyncWork(decryptWorker);
+ std::thread asyncWork(decryptWorker, std::move(rl));
asyncWork.detach();
return error::None;
int ExternalEncryptionServer::recovery()
{
- if (getState() == State::Unencrypted) {
+ RequestLifetime rl(server);
+
+ if (getStateInternal() == State::Unencrypted) {
return error::NoSuchDevice;
}
int ExternalEncryptionServer::getState()
{
+ RequestLifetime rl(server);
+
+ return getStateInternal();
+}
+
+unsigned int ExternalEncryptionServer::getSupportedOptions()
+{
+ RequestLifetime rl(server);
+
+ return engine->getSupportedOptions();
+}
+
+std::string ExternalEncryptionServer::getDevicePath() const
+{
+ RequestLifetime rl(server);
+
+ return engine->getSource();
+}
+
+int ExternalEncryptionServer::getStateInternal() const
+{
char *value = ::vconf_get_str(VCONFKEY_SDE_CRYPTO_STATE);
if (value == NULL) {
throw runtime::Exception("Failed to get vconf value.");
return State::NotSupported;
}
-unsigned int ExternalEncryptionServer::getSupportedOptions()
-{
- return engine->getSupportedOptions();
-}
-
-std::string ExternalEncryptionServer::getDevicePath() const
-{
- return engine->getSource();
-}
-
} // namespace ode
/*
- * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
std::string getDevicePath() const;
private:
+ int getStateInternal() const;
+
ServerContext& server;
std::unique_ptr<EXTERNAL_ENGINE> engine;
std::string source = findDevPath();
- if (getState() == State::Encrypted) {
+ if (getStateInternal() == State::Encrypted) {
//"error_partially_encrypted"
if (!FileFooter::exist(source) && !UpgradeSupport::checkUpgradeFlag()) {
// Trigger key migration process
int InternalEncryptionServer::setMountPassword(const std::string& password)
{
+ RequestLifetime rl(server);
+
const std::string& dev = engine->getSource();
// check if upgrade flag exists
int InternalEncryptionServer::mount(const std::vector<unsigned char> &mk, unsigned int options)
{
+ RequestLifetime rl(server);
+
if (mountKey.empty() && mk.empty()) {
ERROR(SINK, "You need to set master key first.");
return error::NoData;
BinaryData key = mk.empty() ? mountKey : mk;
mountKey.clear();
- if (getState() != State::Encrypted) {
+ if (getStateInternal() != State::Encrypted) {
ERROR(SINK, "Cannot mount, SD partition's state incorrect.");
return error::NoSuchDevice;
}
int InternalEncryptionServer::isMounted()
{
+ RequestLifetime rl(server);
+
int ret = 0;
try {
ret = engine->isMounted() ? 1 : 0;
int InternalEncryptionServer::umount()
{
- if (getState() != State::Encrypted) {
+ RequestLifetime rl(server);
+
+ if (getStateInternal() != State::Encrypted) {
ERROR(SINK, "Cannot umount, partition's state incorrect.");
return error::NoSuchDevice;
}
int InternalEncryptionServer::prepareEncryption(unsigned int options)
{
- if (getState() != State::Unencrypted) {
+ RequestLifetime rl(server);
+
+ if (getStateInternal() != State::Unencrypted) {
ERROR(SINK, "Cannot encrypt, partition's state incorrect.");
return error::NoSuchDevice;
}
return error::Unknown;
}
- setOptions(options & getSupportedOptions());
+ setOptions(options & engine->getSupportedOptions());
::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "prepared_encryption");
::sync();
int InternalEncryptionServer::prepareDecryption()
{
- if (getState() != State::Encrypted) {
+ RequestLifetime rl(server);
+
+ if (getStateInternal() != State::Encrypted) {
ERROR(SINK, "Cannot decrypt, partition's state incorrect.");
return error::NoSuchDevice;
}
int InternalEncryptionServer::encrypt(const std::string& password, unsigned int options)
{
- if (getState() != State::Unencrypted
- && getState() != State::PreparedEncryption) {
+ RequestLifetime rl(server);
+
+ int state = getStateInternal();
+ if (state != State::Unencrypted && state != State::PreparedEncryption) {
ERROR(SINK, "Cannot encrypt, partition's state incorrect.");
return error::NoSuchDevice;
}
if (ret != error::None)
return ret;
- auto encryptWorker = [masterKey, options, this]() {
+ auto encryptWorker = [masterKey, options, this](RequestLifetime&& rl) {
try {
if (::device_power_request_lock(POWER_LOCK_DISPLAY, 0) != 0)
ERROR(SINK, "Failed to request to lock display");
::sleep(1);
runtime::File file("/opt/etc/.odeprogress");
- if (getState() == State::Unencrypted) {
+ if (getStateInternal() == State::Unencrypted) {
/* For backward compatibility */
file.create(MODE_0640);
std::string source = engine->getSource();
INFO(SINK, "Unmounting internal storage.");
unmountInternalStorage(source);
}
- setOptions(options & getSupportedOptions());
+ setOptions(options & engine->getSupportedOptions());
}
INFO(SINK, "Encryption started.");
}
};
- std::thread asyncWork(encryptWorker);
+ std::thread asyncWork(encryptWorker, std::move(rl));
asyncWork.detach();
return error::None;
int InternalEncryptionServer::decrypt(const std::string& password)
{
- if (getState() != State::Encrypted
- && getState() != State::PreparedDecryption) {
+ RequestLifetime rl(server);
+
+ int state = getStateInternal();
+ if (state != State::Encrypted && state != State::PreparedDecryption) {
ERROR(SINK, "Cannot decrypt, partition's state incorrect.");
return error::NoSuchDevice;
}
if (ret != error::None)
return ret;
- auto decryptWorker = [masterKey, this]() {
+ auto decryptWorker = [masterKey, this](RequestLifetime&& rl) {
try {
if (::device_power_request_lock(POWER_LOCK_DISPLAY, 0) != 0)
ERROR(SINK, "Failed to request to lock display");
::sleep(1);
runtime::File file("/opt/etc/.odeprogress");
- if (getState() == State::Encrypted) {
+ if (getStateInternal() == State::Encrypted) {
/* For backward compatibility */
file.create(MODE_0640);
}
};
- std::thread asyncWork(decryptWorker);
+ std::thread asyncWork(decryptWorker, std::move(rl));
asyncWork.detach();
return error::None;
int InternalEncryptionServer::recovery()
{
- int state = getState();
+ RequestLifetime rl(server);
+
+ int state = getStateInternal();
if (state == State::Unencrypted)
return error::NoSuchDevice;
int InternalEncryptionServer::getState()
{
+ RequestLifetime rl(server);
+
+ return getStateInternal();
+}
+
+unsigned int InternalEncryptionServer::getSupportedOptions()
+{
+ RequestLifetime rl(server);
+
+ return engine->getSupportedOptions();
+}
+
+std::string InternalEncryptionServer::getDevicePath() const
+{
+ RequestLifetime rl(server);
+
+ return engine->getSource();
+}
+
+int InternalEncryptionServer::getStateInternal() const
+{
char *value = ::vconf_get_str(VCONFKEY_ODE_CRYPTO_STATE);
if (value == NULL) {
throw runtime::Exception("Failed to get vconf value.");
return State::NotSupported;
}
-unsigned int InternalEncryptionServer::getSupportedOptions()
-{
- return engine->getSupportedOptions();
-}
-
-std::string InternalEncryptionServer::getDevicePath() const
-{
- return engine->getSource();
-}
-
} // namespace ode
/*
- * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
private:
int migrateMasterKey(const std::string& dev, const std::string& password);
+ int getStateInternal() const;
private:
ServerContext& server;
/*
- * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
int KeyServer::isInitialized(const std::string& dev)
{
+ RequestLifetime rl(server);
+
if (dev.empty())
return error::InvalidParameter;
const std::string& password,
int params)
{
+ RequestLifetime rl(server);
+
BinaryData dummy;
return initAndGet(dev, password, params, dummy);
}
int KeyServer::remove(const std::string& dev, const std::string& password)
{
+ RequestLifetime rl(server);
+
if (dev.empty() || password.empty())
return error::InvalidParameter;
const std::string& curPassword,
const std::string& newPassword)
{
+ RequestLifetime rl(server);
if (dev.empty() || curPassword.empty() || newPassword.empty())
return error::InvalidParameter;
int KeyServer::verifyPassword(const std::string& dev,
const std::string& password)
{
+ RequestLifetime rl(server);
+
if (dev.empty() || password.empty())
return error::InvalidParameter;
int KeyServer::storeMasterKey(const std::string& dev,
const std::string& password)
{
+ RequestLifetime rl(server);
+
if (dev.empty() || password.empty())
return error::InvalidParameter;
int KeyServer::removeMasterKey(const std::string& dev)
{
+ RequestLifetime rl(server);
+
if (dev.empty())
return error::InvalidParameter;
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
int LuksServer::execute(bool sync, Luks::Operation op, const F& job)
{
auto worker = [=]() {
+ RequestLifetime rl(server);
+
int ret = error::Unknown;
try {
std::lock_guard<std::mutex> guardLock(opGuard);
/*
- * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
try {
ODEGMainLoop gmainloop;
ode::ServerContext server;
- server.start();
+ server.start(true);
} catch (std::exception &e) {
std::cerr << e.what() << std::endl;
return 1;
/*
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
int SecureEraseServer::clean(const std::string &name)
{
auto cleanWorker = [name, this]() {
+ RequestLifetime rl(server);
try {
std::string target = findDeviceByMountPoint(name);
engine->cleanDevice(target);
/*
- * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <cynara-client.h>
#include <sys/smack.h>
+#include <stdexcept>
+#include <chrono>
+#include <cassert>
+#include <thread>
+
#include "logger.h"
#include "file-sink.h"
#include "secure-erase.h"
namespace {
-const std::string ODE_MANAGER_ADDRESS = "/tmp/.ode.sock";
std::unique_ptr<FileLogSink> _sink = nullptr;
} // namespace
-ServerContext::ServerContext() : rmi::Service(ODE_MANAGER_ADDRESS)
+/*
+ * Timer thread fuction responsible for detecting a server inactivity period after which it will be
+ * stopped.
+ *
+ * Assumptions & acknowledgements:
+ * - Currently there are only 2 ways of stopping the oded server:
+ * - Timeout expiration implemented in the function below
+ * - Terminating with a signal (e.g. SIGTERM from systemd)
+ * - There's a risk of race condition for a request that has just been received (the program is
+ * somewhere between klay's epoll_wait() and mutex lock in ServerContext::requestStarted) while
+ * the timerFunc below detects the timeout and stops the server. In such case the newly received
+ * request will not be processed and client will be disconnected. For now this risk is accepted.
+ * To reduce it, the klay's socket & thread handling would have to be modified or replaced.
+ * - Request processing callbacks are currently called from one of klay's worker threads.
+ * - For requests that require longer processing additional threads are spawned by the server. The
+ * server is considered active as long as the request processing thread is running.
+ * - For debugging purpose, a manually started server is not considered inactive until a request
+ * arrives. In other words, the inactivity time measurement starts after a request is processed.
+ * - Spurious wakeups will not occur in sleep_for().
+ */
+void ServerContext::timerFunc()
+{
+ DEBUG(SINK, "Timer thread started");
+ bool requestArrived = false;
+ for(;;) {
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+
+ std::lock_guard<std::mutex> lock(timerMutex);
+ if (!requestArrived) {
+ if (!newRequests)
+ continue;
+
+ requestArrived = true;
+ }
+ if (!newRequests && currentRequests == 0)
+ break;
+
+ newRequests = false;
+ }
+ INFO(SINK, "Timeout reached. ODE server stopping.");
+ stop();
+}
+
+// This method may be called from different threads
+void ServerContext::requestStarted()
+{
+ std::lock_guard<std::mutex> lock(timerMutex);
+ currentRequests++;
+ newRequests = true;
+ DEBUG(SINK, "New request received. Current count: " << currentRequests);
+}
+
+// This method may be called from different threads
+void ServerContext::requestFinished()
+{
+ std::lock_guard<std::mutex> lock(timerMutex);
+ assert(currentRequests > 0);
+ currentRequests--;
+ DEBUG(SINK, "Request processed. Current count:" << currentRequests);
+}
+
+ServerContext::ServerContext() : rmi::Service(SOCKET_PATH), currentRequests(0), newRequests(false)
{
_sink.reset(new FileLogSink("ode.log"));
SINK = _sink.get();
luks.reset(new LuksServer(*this, *keys));
KeyGenerator::init();
+
+ std::thread timerThread(&ServerContext::timerFunc, this);
+ timerThread.detach();
}
ServerContext::~ServerContext()
{
INFO(SINK, "registerNotificationSubscriber");
INFO(SINK, name);
+
+ RequestLifetime rl(*this);
+
int fd = subscribeNotification(name);
/**
int ServerContext::unregisterNotificationSubscriber(const std::string& name, int id)
{
+ RequestLifetime rl(*this);
+
return unsubscribeNotification(name, id);
}
/*
- * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <string>
#include <memory>
+#include <mutex>
#include <klay/file-descriptor.h>
#include <klay/rmi/service.h>
runtime::FileDescriptor registerNotificationSubscriber(const std::string& name);
int unregisterNotificationSubscriber(const std::string& name, int id);
+ void requestStarted();
+ void requestFinished();
+
private:
+ void timerFunc();
+
std::unique_ptr<SecureEraseServer> secureErase;
std::unique_ptr<InternalEncryptionServer> internalEncryption;
std::unique_ptr<ExternalEncryptionServer> externalEncryption;
std::unique_ptr<LuksServer> luks;
std::unique_ptr<KeyServer> keys;
+
+ std::mutex timerMutex;
+ unsigned currentRequests;
+ bool newRequests;
+};
+
+class RequestLifetime {
+public:
+ explicit RequestLifetime(ServerContext& c) : ctx(&c) {
+ ctx->requestStarted();
+ }
+
+ RequestLifetime(RequestLifetime&& other) {
+ ctx = other.ctx;
+ other.ctx = NULL;
+ }
+
+ ~RequestLifetime() {
+ if (ctx)
+ ctx->requestFinished();
+ }
+
+ RequestLifetime(const RequestLifetime&) = delete;
+ RequestLifetime& operator=(const RequestLifetime&) = delete;
+
+private:
+ ServerContext* ctx;
};
} // namespace ode
[Unit]
Description=@PROJECT_NAME@ management daemon
-Before=deviced.service
+Requires=ode.socket
[Service]
SmackProcessLabel=System::Privileged
CapabilityBoundingSet=~CAP_MAC_OVERRIDE
EnvironmentFile=/run/tizen-system-env
EnvironmentFile=/run/xdg-root-env
-
-[Install]
-WantedBy=multi-user.target
--- /dev/null
+[Socket]
+ListenStream=@SOCKET_PATH@
+SmackLabelIPIn=*
+SmackLabelIPOut=@
+
+[Install]
+WantedBy=sockets.target