From 35ed8ea91594fe4c7f56ffe7401725b61e323341 Mon Sep 17 00:00:00 2001 From: Jaemin Ryu Date: Tue, 5 Jul 2016 15:31:08 +0900 Subject: [PATCH] Add privilege checking Change-Id: Iaecdc753f3012c1bcdcedd357edaf510f3c19972 Signed-off-by: Jaemin Ryu --- common/rmi/service.cpp | 18 ++++++++++-- common/rmi/service.h | 34 ++++++++++++++------- common/rmi/socket.cpp | 8 ++++- common/rmi/socket.h | 1 + packaging/device-policy-manager.spec | 2 ++ server/CMakeLists.txt | 2 ++ server/administration.cpp | 4 +-- server/application.cpp | 16 +++++----- server/bluetooth.cpp | 35 +++++++++++----------- server/location.cpp | 5 ++-- server/password.cpp | 57 ++++++++++++++++++------------------ server/privilege.h | 38 ++++++++++++++++++++++++ server/restriction.cpp | 38 ++++++++++++------------ server/security.cpp | 11 +++---- server/server.cpp | 40 +++++++++++++++++++++++-- server/server.h | 10 +++++-- server/storage.cpp | 3 +- server/wifi.cpp | 21 ++++++------- server/zone.cpp | 14 +++++---- server/zone/app-proxy.cpp | 18 ++++++------ server/zone/package-proxy.cpp | 8 ++--- server/zone/zone.cpp | 14 ++++----- tests/unit/rmi.cpp | 16 +++++----- 23 files changed, 269 insertions(+), 144 deletions(-) create mode 100644 server/privilege.h diff --git a/common/rmi/service.cpp b/common/rmi/service.cpp index c097ec5..317b427 100644 --- a/common/rmi/service.cpp +++ b/common/rmi/service.cpp @@ -67,6 +67,15 @@ Service::ConnectionRegistry::iterator Service::getConnectionIterator(const int i }); } +void Service::setPrivilegeChecker(const PrivilegeChecker& checker) +{ + auto check = [checker, this](const Credentials& cred, const std::string& privilege) { + return checker(cred, privilege); + }; + + onMethodCall = std::move(checker); +} + void Service::setNewConnectionCallback(const ConnectionCallback& connectionCallback) { auto callback = [connectionCallback, this](const std::shared_ptr& connection) { @@ -181,11 +190,14 @@ void Service::onMessageProcess(const std::shared_ptr& connection) // we should increase the reference count of the shared_ptr by capturing it as value auto process = [&, connection](Message& request) { try { - std::shared_ptr methodDispatcher = methodRegistry.at(request.target()); + std::shared_ptr methodContext = methodRegistry.at(request.target()); - // [TBD] Request authentication before dispatching method handler. processingContext = ProcessingContext(connection); - connection->send((*methodDispatcher)(request)); + if (onMethodCall(processingContext.credentials, methodContext->privilege) != true) { + throw runtime::Exception("Permission denied"); + } + + connection->send(methodContext->dispatcher(request)); } catch (std::exception& e) { try { // Forward the exception to the peer diff --git a/common/rmi/service.h b/common/rmi/service.h index cd0f8ef..0089d9b 100644 --- a/common/rmi/service.h +++ b/common/rmi/service.h @@ -48,23 +48,24 @@ #define PROTOTYPE_(D, N) SEQUENCE(D, N) #define PROTOTYPE(...) PROTOTYPE_(PLACEHOLDER, VAR_ARGS_SIZE(__VA_ARGS__)) -#define registerMethod(T, M, ...) \ +#define registerMethod(T, P, M, ...) \ setMethodHandler \ - (STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T, \ + (P, STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T, \ PROTOTYPE(TYPEOF(STRIP(STRIP(M)))))) -#define registerParametricMethod(T, M, ...) \ +#define registerParametricMethod(T, P, M, ...) \ setMethodHandler \ - (STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T, \ + (P, STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T, \ PROTOTYPE(TYPEOF(STRIP(STRIP(M)))))) -#define registerNonparametricMethod(T, M, ...) \ +#define registerNonparametricMethod(T, P, M, ...) \ setMethodHandler \ - (STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T)) + (P, STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T)) namespace rmi { typedef std::function ConnectionCallback; +typedef std::function PrivilegeChecker; class Service { public: @@ -77,11 +78,12 @@ public: void start(bool useGMainloop = false); void stop(); + void setPrivilegeChecker(const PrivilegeChecker& checker); void setNewConnectionCallback(const ConnectionCallback& callback); void setCloseConnectionCallback(const ConnectionCallback& callback); template - void setMethodHandler(const std::string& method, + void setMethodHandler(const std::string& privilege, const std::string& method, const typename MethodHandler::type& handler); void createNotification(const std::string& name); @@ -121,7 +123,18 @@ private: typedef std::function& connection)> CallbackDispatcher; typedef std::function MethodDispatcher; - typedef std::unordered_map> MethodRegistry; + + struct MethodContext { + MethodContext(const std::string& priv, MethodDispatcher&& disp) : + privilege(priv), dispatcher(std::move(disp)) + { + } + + std::string privilege; + MethodDispatcher dispatcher; + }; + + typedef std::unordered_map> MethodRegistry; typedef std::unordered_map NotificationRegistry; void onMessageProcess(const std::shared_ptr& connection); @@ -130,6 +143,7 @@ private: CallbackDispatcher onNewConnection; CallbackDispatcher onCloseConnection; + PrivilegeChecker onMethodCall; MethodRegistry methodRegistry; NotificationRegistry notificationRegistry; @@ -147,7 +161,7 @@ private: }; template -void Service::setMethodHandler(const std::string& method, +void Service::setMethodHandler(const std::string& privilege, const std::string& method, const typename MethodHandler::type& handler) { auto dispatchMethod = [handler](Message& message) { @@ -164,7 +178,7 @@ void Service::setMethodHandler(const std::string& method, throw runtime::Exception("Method handler already registered"); } - methodRegistry[method] = std::make_shared(std::move(dispatchMethod)); + methodRegistry[method] = std::make_shared(privilege, dispatchMethod); } template diff --git a/common/rmi/socket.cpp b/common/rmi/socket.cpp index b959e08..9a67556 100644 --- a/common/rmi/socket.cpp +++ b/common/rmi/socket.cpp @@ -44,13 +44,19 @@ void setCloseOnExec(int fd) Credentials getCredentials(int fd) { + socklen_t length = 256; + char buf[256]; struct ucred cred; socklen_t credsz = sizeof(cred); if (::getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &credsz)) { throw SocketException(runtime::GetSystemErrorMessage()); } - return {cred.pid, cred.uid, cred.gid}; + if (::getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &length)) { + throw SocketException(runtime::GetSystemErrorMessage()); + } + + return {cred.pid, cred.uid, cred.gid, buf}; } } // namespace diff --git a/common/rmi/socket.h b/common/rmi/socket.h index 015b6dd..19a8c6f 100644 --- a/common/rmi/socket.h +++ b/common/rmi/socket.h @@ -30,6 +30,7 @@ struct Credentials { pid_t pid; uid_t uid; gid_t gid; + std::string security; }; class Socket { diff --git a/packaging/device-policy-manager.spec b/packaging/device-policy-manager.spec index ef885db..4966854 100755 --- a/packaging/device-policy-manager.spec +++ b/packaging/device-policy-manager.spec @@ -34,6 +34,8 @@ BuildRequires: pkgconfig(capi-system-system-settings) BuildRequires: pkgconfig(notification) BuildRequires: pkgconfig(key-manager) BuildRequires: pkgconfig(libgum) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-session) %if "%{profile}" != "tv" BuildRequires: pkgconfig(capi-location-manager) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index d4d2df3..c4880ad 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -54,6 +54,8 @@ SET(DEPENDENCY glib-2.0 capi-network-bluetooth notification libgum + cynara-client + cynara-session ) INCLUDE("${TIZEN_PROFILE_NAME}.cmake") diff --git a/server/administration.cpp b/server/administration.cpp index c6e9dfb..6d7917a 100644 --- a/server/administration.cpp +++ b/server/administration.cpp @@ -24,8 +24,8 @@ namespace DevicePolicyManager { AdministrationPolicy::AdministrationPolicy(PolicyControlContext& ctx) : context(ctx) { - context.registerParametricMethod(this, (int)(AdministrationPolicy::registerPolicyClient)(std::string)); - context.registerParametricMethod(this, (int)(AdministrationPolicy::deregisterPolicyClient)(std::string)); + context.registerParametricMethod(this, "", (int)(AdministrationPolicy::registerPolicyClient)(std::string)); + context.registerParametricMethod(this, "", (int)(AdministrationPolicy::deregisterPolicyClient)(std::string)); } AdministrationPolicy::~AdministrationPolicy() diff --git a/server/application.cpp b/server/application.cpp index 6f8185d..9152a64 100644 --- a/server/application.cpp +++ b/server/application.cpp @@ -34,16 +34,16 @@ namespace DevicePolicyManager { ApplicationPolicy::ApplicationPolicy(PolicyControlContext& ctxt) : context(ctxt) { - context.registerNonparametricMethod(this, (int)(ApplicationPolicy::getModeRestriction)()); - context.registerParametricMethod(this, (int)(ApplicationPolicy::setModeRestriction)(int)); - context.registerParametricMethod(this, (int)(ApplicationPolicy::unsetModeRestriction)(int)); + context.registerNonparametricMethod(this, "", (int)(ApplicationPolicy::getModeRestriction)()); + context.registerParametricMethod(this, "", (int)(ApplicationPolicy::setModeRestriction)(int)); + context.registerParametricMethod(this, "", (int)(ApplicationPolicy::unsetModeRestriction)(int)); - context.registerParametricMethod(this, (int)(ApplicationPolicy::addPrivilegeToBlacklist)(int, std::string)); - context.registerParametricMethod(this, (int)(ApplicationPolicy::removePrivilegeFromBlacklist)(int, std::string)); - context.registerParametricMethod(this, (int)(ApplicationPolicy::checkPrivilegeIsBlacklisted)(int, std::string)); + context.registerParametricMethod(this, "", (int)(ApplicationPolicy::addPrivilegeToBlacklist)(int, std::string)); + context.registerParametricMethod(this, "", (int)(ApplicationPolicy::removePrivilegeFromBlacklist)(int, std::string)); + context.registerParametricMethod(this, "", (int)(ApplicationPolicy::checkPrivilegeIsBlacklisted)(int, std::string)); - context.registerParametricMethod(this, (int)(ApplicationPolicy::installPackage)(std::string)); - context.registerParametricMethod(this, (int)(ApplicationPolicy::uninstallPackage)(std::string)); + context.registerParametricMethod(this, "", (int)(ApplicationPolicy::installPackage)(std::string)); + context.registerParametricMethod(this, "", (int)(ApplicationPolicy::uninstallPackage)(std::string)); } ApplicationPolicy::~ApplicationPolicy() diff --git a/server/bluetooth.cpp b/server/bluetooth.cpp index 992e403..7ec7fe2 100644 --- a/server/bluetooth.cpp +++ b/server/bluetooth.cpp @@ -21,6 +21,7 @@ #include "bluetooth.hxx" #include "restriction.hxx" +#include "privilege.h" #include "policy-helper.h" #include "audit/logger.h" #include "dbus/connection.h" @@ -94,23 +95,23 @@ static void bluetoothAdapterStateChangedCallback(int result, bt_adapter_state_e BluetoothPolicy::BluetoothPolicy(PolicyControlContext& ctxt) : context(ctxt) { - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::setModeChangeState)(bool)); - ctxt.registerNonparametricMethod(this, (bool)(BluetoothPolicy::getModeChangeState)); - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::setDesktopConnectivityState)(bool)); - ctxt.registerNonparametricMethod(this, (bool)(BluetoothPolicy::getDesktopConnectivityState)); - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::setTetheringState)(bool)); - ctxt.registerNonparametricMethod(this, (bool)(BluetoothPolicy::getTetheringState)); - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::setPairingState)(bool)); - ctxt.registerNonparametricMethod(this, (bool)(BluetoothPolicy::getPairingState)); - - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::addDeviceToBlacklist)(std::string)); - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::removeDeviceFromBlacklist)(std::string)); - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::setDeviceRestriction)(bool)); - ctxt.registerNonparametricMethod(this, (bool)(BluetoothPolicy::isDeviceRestricted)); - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::addUuidToBlacklist)(std::string)); - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::removeUuidFromBlacklist)(std::string)); - ctxt.registerParametricMethod(this, (int)(BluetoothPolicy::setUuidRestriction)(bool)); - ctxt.registerNonparametricMethod(this, (bool)(BluetoothPolicy::isUuidRestricted)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::setModeChangeState)(bool)); + ctxt.registerNonparametricMethod(this, "", (bool)(BluetoothPolicy::getModeChangeState)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::setDesktopConnectivityState)(bool)); + ctxt.registerNonparametricMethod(this, "", (bool)(BluetoothPolicy::getDesktopConnectivityState)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::setTetheringState)(bool)); + ctxt.registerNonparametricMethod(this, "", (bool)(BluetoothPolicy::getTetheringState)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::setPairingState)(bool)); + ctxt.registerNonparametricMethod(this, "", (bool)(BluetoothPolicy::getPairingState)); + + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::addDeviceToBlacklist)(std::string)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::removeDeviceFromBlacklist)(std::string)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::setDeviceRestriction)(bool)); + ctxt.registerNonparametricMethod(this, "", (bool)(BluetoothPolicy::isDeviceRestricted)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::addUuidToBlacklist)(std::string)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::removeUuidFromBlacklist)(std::string)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_BLUETOOTH, (int)(BluetoothPolicy::setUuidRestriction)(bool)); + ctxt.registerNonparametricMethod(this, "", (bool)(BluetoothPolicy::isUuidRestricted)); ctxt.createNotification("bluetooth"); ctxt.createNotification("bluetooth-tethering"); diff --git a/server/location.cpp b/server/location.cpp index db8fac8..e095f91 100644 --- a/server/location.cpp +++ b/server/location.cpp @@ -18,6 +18,7 @@ #include "location.hxx" +#include "privilege.h" #include "policy-helper.h" #include "audit/logger.h" @@ -26,8 +27,8 @@ namespace DevicePolicyManager { LocationPolicy::LocationPolicy(PolicyControlContext& ctxt) : context(ctxt) { - context.registerParametricMethod(this, (int)(LocationPolicy::setLocationState)(int)); - context.registerNonparametricMethod(this, (int)(LocationPolicy::getLocationState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_LOCATION, (int)(LocationPolicy::setLocationState)(int)); + context.registerNonparametricMethod(this, "", (int)(LocationPolicy::getLocationState)); context.createNotification("location"); } diff --git a/server/password.cpp b/server/password.cpp index c7cb717..212b712 100644 --- a/server/password.cpp +++ b/server/password.cpp @@ -25,6 +25,7 @@ #include "password.hxx" +#include "privilege.h" #include "policy-helper.h" #include "auth/user.h" #include "audit/logger.h" @@ -189,34 +190,34 @@ int transformQualityFromDPMToAuth(const int dpm_quality, password_quality_type & } // namespace PasswordPolicy::PasswordPolicy(PolicyControlContext &ctxt) : - __context(ctxt) -{ - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setPasswordPolicyQuality)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getPasswordPolicyQuality)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setPasswordPolicyMinimumLength)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getPasswordPolicyMinimumLength)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setMinPasswordPolicyComplexChars)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getMinPasswordPolicyComplexChars)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setMaximumFailedPasswordPolicyForWipe)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getMaximumFailedPasswordPolicyForWipe)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setPasswordPolicyExpires)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getPasswordPolicyExpires)()); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setPasswordPolicyHistory)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getPasswordPolicyHistory)()); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setPasswordPolicyPattern)(std::string)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::resetPasswordPolicy)(std::string)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::enforcePasswordPolicyChange)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setMaxInactivityTimeDeviceLock)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getMaxInactivityTimeDeviceLock)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setPasswordPolicyStatus)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::deletePasswordPolicyPattern)); - ctxt.registerNonparametricMethod(this, (std::string)(PasswordPolicy::getPasswordPolicyPattern)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setMaximumCharacterOccurrences)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getMaximumCharacterOccurrences)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setMaximumNumericSequenceLength)(int)); - ctxt.registerNonparametricMethod(this, (int)(PasswordPolicy::getMaximumNumericSequenceLength)); - ctxt.registerParametricMethod(this, (int)(PasswordPolicy::setForbiddenStrings)(std::vector)); - ctxt.registerNonparametricMethod(this, (std::vector)(PasswordPolicy::getForbiddenStrings)); + __context(ctxt) +{ + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setPasswordPolicyQuality)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getPasswordPolicyQuality)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setPasswordPolicyMinimumLength)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getPasswordPolicyMinimumLength)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setMinPasswordPolicyComplexChars)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getMinPasswordPolicyComplexChars)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setMaximumFailedPasswordPolicyForWipe)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getMaximumFailedPasswordPolicyForWipe)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setPasswordPolicyExpires)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getPasswordPolicyExpires)()); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setPasswordPolicyHistory)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getPasswordPolicyHistory)()); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setPasswordPolicyPattern)(std::string)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::resetPasswordPolicy)(std::string)); + ctxt.registerNonparametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::enforcePasswordPolicyChange)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setMaxInactivityTimeDeviceLock)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getMaxInactivityTimeDeviceLock)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setPasswordPolicyStatus)(int)); + ctxt.registerNonparametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::deletePasswordPolicyPattern)); + ctxt.registerNonparametricMethod(this, "", (std::string)(PasswordPolicy::getPasswordPolicyPattern)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setMaximumCharacterOccurrences)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getMaximumCharacterOccurrences)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setMaximumNumericSequenceLength)(int)); + ctxt.registerNonparametricMethod(this, "", (int)(PasswordPolicy::getMaximumNumericSequenceLength)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_PASSWORD, (int)(PasswordPolicy::setForbiddenStrings)(std::vector)); + ctxt.registerNonparametricMethod(this, "", (std::vector)(PasswordPolicy::getForbiddenStrings)); ctxt.createNotification("password"); } diff --git a/server/privilege.h b/server/privilege.h new file mode 100644 index 0000000..a653b67 --- /dev/null +++ b/server/privilege.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __DPM_PRIVILEGE_H__ +#define __DPM_PRIVILEGE_H__ + +#define DPM_PRIVILEGE_LOCK "http://tizen.org/privilege/dpm.lock" +#define DPM_PRIVILEGE_CAMERA "http://tizen.org/privilege/dpm.camera" +#define DPM_PRIVILEGE_MICROPHONE "http://tizen.org/privilege/dpm.microphone" +#define DPM_PRIVILEGE_STORAGE "http://tizen.org/privilege/dpm.storage" +#define DPM_PRIVILEGE_LOCATION "http://tizen.org/privilege/dpm.location" +#define DPM_PRIVILEGE_CLIPBOARD "http://tizen.org/privilege/dpm.clipboard" +#define DPM_PRIVILEGE_DEBUGGING "http://tizen.org/privilege/dpm.debugging" +#define DPM_PRIVILEGE_WIFI "http://tizen.org/privilege/dpm.wifi" +#define DPM_PRIVILEGE_BLUETOOTH "http://tizen.org/privilege/dpm.bluetooth" +#define DPM_PRIVILEGE_USB "http://tizen.org/privilege/dpm.usb" +#define DPM_PRIVILEGE_MESSAGING "http://tizen.org/privilege/dpm.message" +#define DPM_PRIVILEGE_EMAIL "http://tizen.org/privilege/dpm.email" +#define DPM_PRIVILEGE_BROWSER "http://tizen.org/privilege/dpm.browser" +#define DPM_PRIVILEGE_WIPE "http://tizen.org/privilege/dpm.wipe" +#define DPM_PRIVILEGE_SECURITY "http://tizen.org/privilege/dpm.security" +#define DPM_PRIVILEGE_ZONE "http://tizen.org/privilege/dpm.zone" +#define DPM_PRIVILEGE_PASSWORD "http://tizen.org/privilege/dpm.password" + +#endif //__DPM_PRIVILEGE_H__ diff --git a/server/restriction.cpp b/server/restriction.cpp index 2ac5098..ebb6e6c 100644 --- a/server/restriction.cpp +++ b/server/restriction.cpp @@ -17,6 +17,8 @@ #include #include "restriction.hxx" + +#include "privilege.h" #include "policy-helper.h" #include "audit/logger.h" #include "dbus/connection.h" @@ -43,24 +45,24 @@ namespace DevicePolicyManager { RestrictionPolicy::RestrictionPolicy(PolicyControlContext& ctxt) : context(ctxt) { - context.registerParametricMethod(this, (int)(RestrictionPolicy::setCameraState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getCameraState)); - context.registerParametricMethod(this, (int)(RestrictionPolicy::setMicrophoneState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getMicrophoneState)); - context.registerParametricMethod(this, (int)(RestrictionPolicy::setClipboardState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getClipboardState)); - context.registerParametricMethod(this, (int)(RestrictionPolicy::setUsbDebuggingState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getUsbDebuggingState)); - context.registerParametricMethod(this, (int)(RestrictionPolicy::setUsbTetheringState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getUsbTetheringState)); - context.registerParametricMethod(this, (int)(RestrictionPolicy::setExternalStorageState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getExternalStorageState)); - context.registerParametricMethod(this, (int)(RestrictionPolicy::setPopImapEmailState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getPopImapEmailState)); - context.registerParametricMethod(this, (int)(RestrictionPolicy::setMessagingState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getMessagingState)); - context.registerParametricMethod(this, (int)(RestrictionPolicy::setBrowserState)(int)); - context.registerNonparametricMethod(this, (int)(RestrictionPolicy::getBrowserState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_CAMERA, (int)(RestrictionPolicy::setCameraState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getCameraState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_MICROPHONE, (int)(RestrictionPolicy::setMicrophoneState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getMicrophoneState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_CLIPBOARD, (int)(RestrictionPolicy::setClipboardState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getClipboardState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_DEBUGGING, (int)(RestrictionPolicy::setUsbDebuggingState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getUsbDebuggingState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_USB, (int)(RestrictionPolicy::setUsbTetheringState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getUsbTetheringState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_STORAGE, (int)(RestrictionPolicy::setExternalStorageState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getExternalStorageState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_EMAIL, (int)(RestrictionPolicy::setPopImapEmailState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getPopImapEmailState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_MESSAGING, (int)(RestrictionPolicy::setMessagingState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getMessagingState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_BROWSER, (int)(RestrictionPolicy::setBrowserState)(int)); + context.registerNonparametricMethod(this, "", (int)(RestrictionPolicy::getBrowserState)); context.createNotification("camera"); context.createNotification("clipboard"); diff --git a/server/security.cpp b/server/security.cpp index 3ef31a9..cc81e83 100755 --- a/server/security.cpp +++ b/server/security.cpp @@ -29,6 +29,7 @@ #include "security.hxx" +#include "privilege.h" #include "launchpad.h" #include "process.h" #include "filesystem.h" @@ -48,11 +49,11 @@ const std::string PROG_POWEROFF = "/usr/sbin/poweroff"; SecurityPolicy::SecurityPolicy(PolicyControlContext& ctxt) : context(ctxt) { - ctxt.registerNonparametricMethod(this, (int)(SecurityPolicy::lockoutScreen)); - ctxt.registerNonparametricMethod(this, (int)(SecurityPolicy::isInternalStorageEncrypted)); - ctxt.registerNonparametricMethod(this, (int)(SecurityPolicy::isExternalStorageEncrypted)); - ctxt.registerParametricMethod(this, (int)(SecurityPolicy::setInternalStorageEncryption)(bool)); - ctxt.registerParametricMethod(this, (int)(SecurityPolicy::setExternalStorageEncryption)(bool)); + ctxt.registerNonparametricMethod(this, DPM_PRIVILEGE_LOCK, (int)(SecurityPolicy::lockoutScreen)); + ctxt.registerNonparametricMethod(this, "", (int)(SecurityPolicy::isInternalStorageEncrypted)); + ctxt.registerNonparametricMethod(this, "", (int)(SecurityPolicy::isExternalStorageEncrypted)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_SECURITY, (int)(SecurityPolicy::setInternalStorageEncryption)(bool)); + ctxt.registerParametricMethod(this, DPM_PRIVILEGE_SECURITY, (int)(SecurityPolicy::setExternalStorageEncryption)(bool)); } SecurityPolicy::~SecurityPolicy() diff --git a/server/server.cpp b/server/server.cpp index 6dd3744..6bfce52 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -13,9 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License */ +#include + +#include +#include #include "server.h" +using namespace std::placeholders; + namespace { const std::string POLICY_MANAGER_ADDRESS = "/tmp/.device-policy-manager"; @@ -28,8 +34,10 @@ Server::Server() service.reset(new rmi::Service(POLICY_MANAGER_ADDRESS)); - service->registerParametricMethod(this, (FileDescriptor)(Server::registerNotificationSubscriber)(std::string)); - service->registerParametricMethod(this, (int)(Server::unregisterNotificationSubscriber)(std::string, int)); + service->setPrivilegeChecker(std::bind(&Server::checkPeerPrivilege, this, _1, _2)); + + service->registerParametricMethod(this, "", (FileDescriptor)(Server::registerNotificationSubscriber)(std::string)); + service->registerParametricMethod(this, "", (int)(Server::unregisterNotificationSubscriber)(std::string, int)); } Server::~Server() @@ -89,6 +97,34 @@ std::string Server::getPolicy(const std::string& name) const return policyStorage->getPolicy(name).getContent(); } +bool Server::checkPeerPrivilege(const rmi::Credentials& cred, const std::string& privilege) +{ + cynara *p_cynara; + + DEBUG("Peer security: " + cred.security); + + if (privilege.empty()) { + return true; + } + + if (::cynara_initialize(&p_cynara, NULL) != CYNARA_API_SUCCESS) { + ERROR("Failure in cynara API"); + return false; + } + + if (::cynara_check(p_cynara, cred.security.c_str(), "", + std::to_string(cred.uid).c_str(), + privilege.c_str()) != CYNARA_API_ACCESS_ALLOWED) { + ::cynara_finish(p_cynara); + ERROR("Access denied: " + cred.security + " : " + privilege); + return false; + } + + ::cynara_finish(p_cynara); + + return true; +} + Server& Server::instance() { static Server _instance_; diff --git a/server/server.h b/server/server.h index 9190afc..c616efb 100644 --- a/server/server.h +++ b/server/server.h @@ -23,6 +23,7 @@ #include "policy-storage.h" #include "file-descriptor.h" +#include "filesystem.h" #include "rmi/service.h" class Server { @@ -31,10 +32,10 @@ public: void terminate(); template - void setMethodHandler(const std::string& method, - const typename rmi::MethodHandler::type& handler) + void setMethodHandler(const std::string& privilege, const std::string& method, + const typename rmi::MethodHandler::type& handler) { - service->setMethodHandler(method, handler); + service->setMethodHandler(privilege, method, handler); } template @@ -71,12 +72,15 @@ public: FileDescriptor registerNotificationSubscriber(const std::string& name); int unregisterNotificationSubscriber(const std::string& name, int id); + bool checkPeerPrivilege(const rmi::Credentials& cred, const std::string& privilege); + static Server& instance(); private: Server(); ~Server(); + std::string securityLabel; std::unique_ptr policyStorage; std::unique_ptr service; }; diff --git a/server/storage.cpp b/server/storage.cpp index 125490e..2369a43 100644 --- a/server/storage.cpp +++ b/server/storage.cpp @@ -21,6 +21,7 @@ #include "storage.hxx" +#include "privilege.h" #include "policy-helper.h" #include "exception.h" @@ -105,7 +106,7 @@ void requestDeviceFormat(const std::string& devnode, int option) StoragePolicy::StoragePolicy(PolicyControlContext& ctx) : context(ctx) { - context.registerParametricMethod(this, (int)(StoragePolicy::wipeData)(int)); + context.registerParametricMethod(this, DPM_PRIVILEGE_WIPE, (int)(StoragePolicy::wipeData)(int)); } StoragePolicy::~StoragePolicy() diff --git a/server/wifi.cpp b/server/wifi.cpp index d47fc4d..ee52d32 100644 --- a/server/wifi.cpp +++ b/server/wifi.cpp @@ -26,6 +26,7 @@ #include "wifi.hxx" +#include "privilege.h" #include "policy-helper.h" #include "app-bundle.h" @@ -93,19 +94,19 @@ inline void applyBlocklistToConnectedAP() WifiPolicy::WifiPolicy(PolicyControlContext& ctx) : context(ctx) { - context.registerParametricMethod(this, (int)(WifiPolicy::setState)(bool)); - context.registerNonparametricMethod(this, (bool)(WifiPolicy::getState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_WIFI, (int)(WifiPolicy::setState)(bool)); + context.registerNonparametricMethod(this, "", (bool)(WifiPolicy::getState)); - context.registerParametricMethod(this, (int)(WifiPolicy::setHotspotState)(bool)); - context.registerNonparametricMethod(this, (bool)(WifiPolicy::getHotspotState)); + context.registerParametricMethod(this, DPM_PRIVILEGE_WIFI, (int)(WifiPolicy::setHotspotState)(bool)); + context.registerNonparametricMethod(this, "", (bool)(WifiPolicy::getHotspotState)); - context.registerParametricMethod(this, (int)(WifiPolicy::setProfileChangeRestriction)(bool)); - context.registerNonparametricMethod(this, (bool)(WifiPolicy::isProfileChangeRestricted)); + context.registerParametricMethod(this, DPM_PRIVILEGE_WIFI, (int)(WifiPolicy::setProfileChangeRestriction)(bool)); + context.registerNonparametricMethod(this, "", (bool)(WifiPolicy::isProfileChangeRestricted)); - context.registerParametricMethod(this, (int)(WifiPolicy::setNetworkAccessRestriction)(bool)); - context.registerNonparametricMethod(this, (bool)(WifiPolicy::isNetworkAccessRestricted)); - context.registerParametricMethod(this, (int)(WifiPolicy::addSsidToBlocklist)(std::string)); - context.registerParametricMethod(this, (int)(WifiPolicy::removeSsidFromBlocklist)(std::string)); + context.registerParametricMethod(this, DPM_PRIVILEGE_WIFI, (int)(WifiPolicy::setNetworkAccessRestriction)(bool)); + context.registerNonparametricMethod(this, "", (bool)(WifiPolicy::isNetworkAccessRestricted)); + context.registerParametricMethod(this, DPM_PRIVILEGE_WIFI, (int)(WifiPolicy::addSsidToBlocklist)(std::string)); + context.registerParametricMethod(this, "", (int)(WifiPolicy::removeSsidFromBlocklist)(std::string)); context.createNotification("wifi"); context.createNotification("wifi-hotspot"); diff --git a/server/zone.cpp b/server/zone.cpp index 19e63e7..56e847e 100755 --- a/server/zone.cpp +++ b/server/zone.cpp @@ -25,6 +25,8 @@ #include "zone.hxx" #include "zone/zone.hxx" +#include "privilege.h" + #include "error.h" #include "launchpad.h" #include "filesystem.h" @@ -60,12 +62,12 @@ bool isAllowedName(const std::string& name) { ZonePolicy::ZonePolicy(PolicyControlContext& ctx) : context(ctx) { - context.registerParametricMethod(this, (int)(ZonePolicy::createZone)(std::string, std::string)); - context.registerParametricMethod(this, (int)(ZonePolicy::removeZone)(std::string)); - context.registerParametricMethod(this, (int)(ZonePolicy::lockZone)(std::string)); - context.registerParametricMethod(this, (int)(ZonePolicy::unlockZone)(std::string)); - context.registerParametricMethod(this, (int)(ZonePolicy::getZoneState)(std::string)); - context.registerParametricMethod(this, (std::vector)(ZonePolicy::getZoneList)(int)); + context.registerParametricMethod(this, DPM_PRIVILEGE_ZONE, (int)(ZonePolicy::createZone)(std::string, std::string)); + context.registerParametricMethod(this, DPM_PRIVILEGE_ZONE, (int)(ZonePolicy::removeZone)(std::string)); + context.registerParametricMethod(this, DPM_PRIVILEGE_ZONE, (int)(ZonePolicy::lockZone)(std::string)); + context.registerParametricMethod(this, DPM_PRIVILEGE_ZONE, (int)(ZonePolicy::unlockZone)(std::string)); + context.registerParametricMethod(this, "", (int)(ZonePolicy::getZoneState)(std::string)); + context.registerParametricMethod(this, "", (std::vector)(ZonePolicy::getZoneList)(int)); context.createNotification("ZonePolicy::created"); context.createNotification("ZonePolicy::removed"); diff --git a/server/zone/app-proxy.cpp b/server/zone/app-proxy.cpp index 92d50d3..99d2200 100644 --- a/server/zone/app-proxy.cpp +++ b/server/zone/app-proxy.cpp @@ -45,17 +45,17 @@ int newIteratorId = 0; ZoneAppProxy::ZoneAppProxy(PolicyControlContext& ctx) : context(ctx) { - context.registerParametricMethod(this, (ZoneAppProxy::AppInfo)(ZoneAppProxy::getAppInfo)(std::string, std::string)); + context.registerParametricMethod(this, "", (ZoneAppProxy::AppInfo)(ZoneAppProxy::getAppInfo)(std::string, std::string)); - context.registerParametricMethod(this, (int)(ZoneAppProxy::createIterator)(std::string)); - context.registerParametricMethod(this, (ZoneAppProxy::AppInfo)(ZoneAppProxy::getIteratorValue)(int)); - context.registerParametricMethod(this, (bool)(ZoneAppProxy::nextIterator)(int)); - context.registerParametricMethod(this, (int)(ZoneAppProxy::destroyIterator)(int)); + context.registerParametricMethod(this, "", (int)(ZoneAppProxy::createIterator)(std::string)); + context.registerParametricMethod(this, "", (ZoneAppProxy::AppInfo)(ZoneAppProxy::getIteratorValue)(int)); + context.registerParametricMethod(this, "", (bool)(ZoneAppProxy::nextIterator)(int)); + context.registerParametricMethod(this, "", (int)(ZoneAppProxy::destroyIterator)(int)); - context.registerParametricMethod(this, (int)(ZoneAppProxy::launch)(std::string, ZoneAppProxy::Bundle)); - context.registerParametricMethod(this, (int)(ZoneAppProxy::resume)(std::string, std::string)); - context.registerParametricMethod(this, (int)(ZoneAppProxy::terminate)(std::string, std::string)); - context.registerParametricMethod(this, (int)(ZoneAppProxy::isRunning)(std::string, std::string)); + context.registerParametricMethod(this, "", (int)(ZoneAppProxy::launch)(std::string, ZoneAppProxy::Bundle)); + context.registerParametricMethod(this, "", (int)(ZoneAppProxy::resume)(std::string, std::string)); + context.registerParametricMethod(this, "", (int)(ZoneAppProxy::terminate)(std::string, std::string)); + context.registerParametricMethod(this, "", (int)(ZoneAppProxy::isRunning)(std::string, std::string)); } ZoneAppProxy::~ZoneAppProxy() diff --git a/server/zone/package-proxy.cpp b/server/zone/package-proxy.cpp index 7d2ca20..c490a36 100644 --- a/server/zone/package-proxy.cpp +++ b/server/zone/package-proxy.cpp @@ -29,11 +29,11 @@ namespace DevicePolicyManager { ZonePackageProxy::ZonePackageProxy(PolicyControlContext& ctx) : context(ctx) { - context.registerParametricMethod(this, (ZonePackageProxy::PackageInfo)(ZonePackageProxy::getPackageInfo)(std::string, std::string)); - context.registerParametricMethod(this, (std::vector)(ZonePackageProxy::getPackageList)(std::string)); + context.registerParametricMethod(this, "", (ZonePackageProxy::PackageInfo)(ZonePackageProxy::getPackageInfo)(std::string, std::string)); + context.registerParametricMethod(this, "", (std::vector)(ZonePackageProxy::getPackageList)(std::string)); - context.registerParametricMethod(this, (int)(ZonePackageProxy::install)(std::string, std::string)); - context.registerParametricMethod(this, (int)(ZonePackageProxy::uninstall)(std::string, std::string)); + context.registerParametricMethod(this, "", (int)(ZonePackageProxy::install)(std::string, std::string)); + context.registerParametricMethod(this, "", (int)(ZonePackageProxy::uninstall)(std::string, std::string)); } ZonePackageProxy::~ZonePackageProxy() diff --git a/server/zone/zone.cpp b/server/zone/zone.cpp index 8dc6410..0ec13b4 100644 --- a/server/zone/zone.cpp +++ b/server/zone/zone.cpp @@ -480,13 +480,13 @@ void notiProxyCallback(void *data, notification_type_e type, notification_op *op ZoneManager::ZoneManager(PolicyControlContext& ctx) : context(ctx) { - context.registerParametricMethod(this, (int)(ZoneManager::createZone)(std::string, std::string)); - context.registerParametricMethod(this, (int)(ZoneManager::removeZone)(std::string)); - context.registerParametricMethod(this, (int)(ZoneManager::lockZone)(std::string)); - context.registerParametricMethod(this, (int)(ZoneManager::unlockZone)(std::string)); - context.registerParametricMethod(this, (int)(ZoneManager::getZoneState)(std::string)); - context.registerParametricMethod(this, (std::vector)(ZoneManager::getZoneList)(int)); - context.registerParametricMethod(this, (int)(ZoneManager::resetZonePassword)(std::string, std::string)); + context.registerParametricMethod(this, "", (int)(ZoneManager::createZone)(std::string, std::string)); + context.registerParametricMethod(this, "", (int)(ZoneManager::removeZone)(std::string)); + context.registerParametricMethod(this, "", (int)(ZoneManager::lockZone)(std::string)); + context.registerParametricMethod(this, "", (int)(ZoneManager::unlockZone)(std::string)); + context.registerParametricMethod(this, "", (int)(ZoneManager::getZoneState)(std::string)); + context.registerParametricMethod(this, "", (std::vector)(ZoneManager::getZoneList)(int)); + context.registerParametricMethod(this, "", (int)(ZoneManager::resetZonePassword)(std::string, std::string)); context.createNotification("ZoneManager::created"); context.createNotification("ZoneManager::removed"); diff --git a/tests/unit/rmi.cpp b/tests/unit/rmi.cpp index 1033e78..4a58845 100644 --- a/tests/unit/rmi.cpp +++ b/tests/unit/rmi.cpp @@ -40,16 +40,16 @@ public: { service.reset(new rmi::Service(IPC_TEST_ADDRESS)); - service->registerMethod(this, (String)(TestServer::method1)(String)); - service->registerMethod(this, (String)(TestServer::method2)(String, String)); - service->registerMethod(this, (String)(TestServer::method3)(String, String, String)); - service->registerMethod(this, (String)(TestServer::method4)(String, String, String, String)); + service->registerMethod(this, "", (String)(TestServer::method1)(String)); + service->registerMethod(this, "", (String)(TestServer::method2)(String, String)); + service->registerMethod(this, "", (String)(TestServer::method3)(String, String, String)); + service->registerMethod(this, "", (String)(TestServer::method4)(String, String, String, String)); - service->registerMethod(this, (FileDescriptor)(TestServer::signalProvider)(std::string)); - service->registerMethod(this, (FileDescriptor)(TestServer::policyNotificationProvider)(std::string)); + service->registerMethod(this, "", (FileDescriptor)(TestServer::signalProvider)(std::string)); + service->registerMethod(this, "", (FileDescriptor)(TestServer::policyNotificationProvider)(std::string)); - service->registerNonparametricMethod(this, (int)(TestServer::sendSignal)()); - service->registerNonparametricMethod(this, (int)(TestServer::sendPolicyChangeNotification)()); + service->registerNonparametricMethod(this, "", (int)(TestServer::sendSignal)()); + service->registerNonparametricMethod(this, "", (int)(TestServer::sendPolicyChangeNotification)()); service->createNotification("TestPolicyChanged"); service->createNotification("TestSignal"); -- 2.7.4