Add privilege checker when it's applied mode
authorJinWang An <jinwang.an@samsung.com>
Thu, 5 Dec 2019 02:32:13 +0000 (11:32 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Wed, 18 Mar 2020 08:53:50 +0000 (17:53 +0900)
17 files changed:
example/rule/tizen_ex_rule.xml
packaging/modes.spec
schema/tizen_action_rule.xsd
supervisor/Action.cpp
supervisor/Action.h
supervisor/ActionRule.cpp
supervisor/ActionRule.h
supervisor/CMakeLists.txt
supervisor/ClientPrivilege.cpp [new file with mode: 0644]
supervisor/ClientPrivilege.h [new file with mode: 0644]
supervisor/ModeManager.cpp
supervisor/ModeManager.h
supervisor/RequestHandler.cpp
supervisor/RuleManager.cpp
supervisor/RuleManager.h
supervisor/TActionRule.h
unittest/CMakeLists.txt

index 9f69422acbf5d21ee9f227c6d60ef224a4e0a2ac..34334ef3e6f4115554d81cebe633c637a9034e98 100644 (file)
       <alias name="PRINT_TWO">2</alias>
       <alias name="PRINT_THREE">3</alias>
       <alias name="PRINT_FOUR">4</alias>
+      <privilege>http://tizen.org/privilege/systemsettings.admin</privilege>
       <desc>It prints integer value</desc>
       <domain>System</domain>
     </rule>
     <rule name="test.printBool" type="bool" since="6.0" plugin="test">
       <alias name="on">1</alias>
       <alias name="off">0</alias>
+      <privilege>http://tizen.org/privilege/systemsettings.admin</privilege>
       <desc>It prints boolean value</desc>
       <domain>System</domain>
     </rule>
     <rule name="test.sleep" type="int" since="6.0" plugin="test">
+      <privilege>http://tizen.org/privilege/systemsettings.admin</privilege>
       <desc>Sleep</desc>
       <domain>System</domain>
     </rule>
index 6dec3e413e086c98becec86dcf0d47dfd2569c8c..6a60091bd3097bcbaff4aa2a4ec85ae66dbd9847 100644 (file)
@@ -17,6 +17,9 @@ BuildRequires: pkgconfig(libxml-2.0)
 BuildRequires: pkgconfig(vconf)
 BuildRequires: pkgconfig(capi-network-wifi-manager)
 BuildRequires: pkgconfig(gmock)
+BuildRequires: pkgconfig(cynara-client)
+BuildRequires: pkgconfig(cynara-creds-gdbus)
+BuildRequires: pkgconfig(cynara-session)
 
 %description
 The modes(Mode Supervisor) manages configurations which is described at a mode.
index ee629c5bb810981a1fc8fde75505d0723267a299..94d1c7ec261143cbdb3ebf00028331f2c73b004b 100644 (file)
@@ -20,6 +20,7 @@
                       </xs:complexType>
                     </xs:element>
                     <xs:element minOccurs="0" name="conflict" type="xs:string" />
+                    <xs:element minOccurs="0" name="privilege" type="xs:string"/>
                     <xs:element name="desc" type="xs:string" />
                     <xs:element name="domain" type="o:domainT" />
                   </xs:sequence>
index d2bb431500b6405c75df0ce04ce8dd8764236e90..89b7e1c09d299e930c945b7333fc7ef2170b5f80 100644 (file)
@@ -97,6 +97,16 @@ void Action::setPlugin(Plugin *pi)
        plugin = pi;
 }
 
+void Action::setPrivilege(const std::string &val)
+{
+       privilege = val;
+}
+
+std::string Action::getPrivilege()
+{
+       return privilege;
+}
+
 void Action::valueChangedCallback(void *userData)
 {
        Action *action = (Action*)userData;
index ae9973447fc0eda71b4cd4f0106843fa2b08e8d1..64abbaba15ad9b61270da68c10faabe43108fc33 100644 (file)
@@ -50,6 +50,8 @@ public:
        void setType(ActionType val);
        ActionType getType();
        void setPlugin(Plugin *pi);
+       void setPrivilege(const std::string &val);
+       std::string getPrivilege();
        virtual int setValue(const std::string &val) = 0;
        virtual std::string getStringOfValue() = 0;
        virtual int apply() = 0;
@@ -66,6 +68,7 @@ protected:
        PluginAction *piAction;
 private:
        std::string id;
+       std::string privilege;
        bool stopOnErr;
        ActionRestrict restriction;
 };
index 07444c64014427ed3033958aefb575186c4eb02f..92e83575e3f0c51590ad11860757a0e990552b92 100644 (file)
@@ -34,3 +34,8 @@ std::string ActionRule::getPlugin()
 {
        return plugin;
 }
+
+void ActionRule::setPrivilege(const std::string &priv)
+{
+       privilege = priv;
+}
index 191315dc1a3d4f6d72b668d86fd45248746a7259..8fbb9b378565f271dd4f2a60821538d35c0728d5 100644 (file)
@@ -28,10 +28,12 @@ public:
        std::string getName();
        std::string getPlugin();
        void setPlugin(const std::string &pi);
+       void setPrivilege(const std::string &priv);
        virtual Action* makeAction() = 0;
        virtual int addAlias(const std::string &alias, const std::string &value) = 0;
 protected:
        std::string ruleName;
+       std::string privilege;
 private:
        std::string plugin;
        // TODO:: handle conflict List, since, description, version
index 3afd7fbc419ec3795c84531c384ec5378adef208..1aed2490a1e727ec75e22697259753b1a6d6e142 100644 (file)
@@ -4,7 +4,7 @@ SET(DAEMON_SRCS ${DAEMON_SRCS} ${CMAKE_SOURCE_DIR}/common/dbus.c)
 SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/common/dbus.c
        PROPERTIES GENERATED TRUE)
 
-SET(PKG_MODULES gio-2.0 dlog gio-unix-2.0 libxml-2.0)
+SET(PKG_MODULES gio-2.0 dlog gio-unix-2.0 libxml-2.0 cynara-client cynara-creds-gdbus cynara-session)
 
 pkg_check_modules(daemon_pkgs REQUIRED ${PKG_MODULES})
 FOREACH(flag ${daemon_pkgs_CFLAGS_OTHER})
diff --git a/supervisor/ClientPrivilege.cpp b/supervisor/ClientPrivilege.cpp
new file mode 100644 (file)
index 0000000..d208806
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 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.
+ * 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.
+ */
+#include "ClientPrivilege.h"
+
+#include <string>
+#include <cynara-client.h>
+#include <cynara-session.h>
+#include <cynara-creds-gdbus.h>
+#include "common/dbus.h"
+#include "mdss.h"
+
+MODES_NAMESPACE_USE;
+
+ClientPrivilege::ClientPrivilege(GDBusMethodInvocation *invocation)
+       : handle(NULL), conf(NULL), client(NULL), user(NULL), clientSession(NULL)
+{
+       int pid;
+       GDBusConnection *conn = g_dbus_method_invocation_get_connection(invocation);
+       // Do not free this string, it is owned by connection
+       const char *senderUniqueName = g_dbus_method_invocation_get_sender(invocation);
+
+
+       int ret = cynara_creds_gdbus_get_user(conn, senderUniqueName, USER_METHOD_DEFAULT, &user);
+       if (ret != CYNARA_API_SUCCESS)
+               ERR("cynara_creds_gdbus_get_user() Fail(%d)", ret);
+
+       ret = cynara_creds_gdbus_get_client(conn, senderUniqueName, CLIENT_METHOD_DEFAULT, &client);
+       if (ret != CYNARA_API_SUCCESS)
+               ERR("cynara_creds_gdbus_get_client() Fail(%d)", ret);
+
+       ret = cynara_creds_gdbus_get_pid(conn, senderUniqueName, &pid);
+       if (ret != CYNARA_API_SUCCESS)
+               ERR("cynara_creds_gdbus_get_pid() Fail(%d)", ret);
+
+       clientSession = cynara_session_from_pid(pid);
+       if (NULL == clientSession)
+               ERR("cynara_session_from_pid() Fail()");
+
+       ret = cynara_configuration_create(&conf);
+       if (ret != CYNARA_API_SUCCESS)
+               ERR("cynara_configuration_create() Fail(%d)", ret);
+
+       ret = cynara_configuration_set_cache_size(conf, 100);
+       if (ret != CYNARA_API_SUCCESS) {
+               ERR("cynara_configuration_set_cache_size() Fail(%d)", ret);
+               cynara_configuration_destroy(conf);
+       }
+
+       ret = cynara_initialize(&handle, conf);
+       if (ret != CYNARA_API_SUCCESS) {
+               ERR("cynara_initialize() Fail(%d)", ret);
+               cynara_configuration_destroy(conf);
+       }
+}
+
+ClientPrivilege::~ClientPrivilege()
+{
+       cynara_configuration_destroy(conf);
+       cynara_finish(handle);
+       free(client);
+       free(user);
+       free(clientSession);
+}
+
+int ClientPrivilege::check(Mode &mode)
+{
+       std::list<std::shared_ptr<Action>>::iterator it;
+       auto actionList = mode.getActionList();
+       for (it = actionList.begin(); it != actionList.end(); it++) {
+               std::string priv = (*it)->getPrivilege();
+               //No Privilege = Allow All
+               if (priv.empty())
+                       continue;
+               int ret = cynara_check(handle, client, clientSession, user, priv.c_str());
+               if (CYNARA_API_ACCESS_ALLOWED != ret) {
+                       ERR("Action(%s) priv.check(%s) Fail(%d)", (*it)->getRuleName().c_str(), (*it)->getPrivilege().c_str(), ret);
+                       if (ret == CYNARA_API_ACCESS_DENIED)
+                               return MODES_ERROR_PERMISSION_DENIED;
+                       else
+                               return MODES_ERROR_SYSTEM;
+               }
+       }
+       DBG("Success!");
+       return MODES_ERROR_NONE;
+}
diff --git a/supervisor/ClientPrivilege.h b/supervisor/ClientPrivilege.h
new file mode 100644 (file)
index 0000000..c163a0f
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 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.
+ * 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.
+ */
+#pragma once
+
+#include <string>
+#include <cynara-client.h>
+#include "Mode.h"
+#include "mdss.h"
+#include "common/dbus.h"
+
+MODES_NAMESPACE_BEGIN
+
+class ClientPrivilege {
+public:
+       ClientPrivilege(GDBusMethodInvocation *invocation);
+       ~ClientPrivilege();
+       int check(Mode &mode);
+private:
+       cynara *handle;
+       cynara_configuration *conf;
+       char *client;
+       char *user;
+       char *clientSession;
+};
+
+MODES_NAMESPACE_END
index 5719a212ac5e3b7eb692d7fa7244b35a2f285992..5bf5f580fbb0c912071a31514dcb6fc4b85ad5d3 100644 (file)
@@ -76,7 +76,7 @@ void ModeManager::addModeName(ModeParser *parser, const string &path)
        DBG("[%d] modeName : %s, modePath : %s", modeMap.size(), modeName.c_str(), path.c_str());
 }
 
-int ModeManager::applyMode(const string &modeName)
+int ModeManager::applyMode(const string &modeName, ClientPrivilege &priv)
 {
        auto found = modeMap.find(modeName);
        if (modeMap.end() == found) {
@@ -99,15 +99,21 @@ int ModeManager::applyMode(const string &modeName)
                        return MODES_ERROR_CONFLICT;
                }
 
+               int ret = priv.check(mode);
+               if (MODES_ERROR_NONE != ret) {
+                       ERR("priv.check() Fail(%d)", ret);
+                       return ret;
+               }
+
                if (Mode::MODE_ONESHOT == mode.getModeType()) {
-                       int ret = mode.applyOneShot();
+                       ret = mode.applyOneShot();
                        if (MODES_ERROR_NONE != ret) {
                                ERR("mode(%s) apply() Fail", mode.getName().c_str());
                                mode.undo();
                                return ret;
                        }
                } else {
-                       int ret = mode.apply();
+                       ret = mode.apply();
                        if (MODES_ERROR_NONE != ret) {
                                ERR("mode(%s) apply() Fail", mode.getName().c_str());
                                mode.undo();
index e20f456c81049b4356f891de52e5aa45a2cb8f10..feccb1767f3d146168756f411872d87d65ec0233 100644 (file)
@@ -22,6 +22,7 @@
 #include "PluginManager.h"
 #include "RuleManager.h"
 #include "ModeCareTaker.h"
+#include "ClientPrivilege.h"
 
 #ifndef MODES_MODE_DEFAULT_DIR
 #define MODES_MODE_DEFAULT_DIR "/usr/share/modes/mode"
@@ -37,7 +38,7 @@ public:
        void setOptions(const std::set<std::string> &modeDirs, const std::string &xsdFile, const std::string &undoInfoDir);
        void init();
        void addModeDirectory(const std::string &dirPath);
-       int applyMode(const std::string &modeName);
+       int applyMode(const std::string &modeName, ClientPrivilege &priv);
        int registerMode(const Mode &mode);
        int undoMode(const std::string &modeName);
        std::list<std::tuple<std::string, int>> getModes();
index 2c87dad451f5c9a73f69318530a94fd2834ec50d..6ae2e4c8405b89ed4cca341b8bdc09f7adb897e0 100644 (file)
@@ -17,6 +17,7 @@
 #include "mdss.h"
 #include "ModesEx.h"
 #include "common/dbus_def.h"
+#include "ClientPrivilege.h"
 
 MODES_NAMESPACE_USE;
 
@@ -42,7 +43,8 @@ gboolean RequestHandler::applyModeHandler(mdsDbus *object, GDBusMethodInvocation
 
        DBG("mode name = %s", modeName);
 
-       int ret = modeMgr->applyMode(modeName);
+       ClientPrivilege privInfo(invocation);
+       int ret = modeMgr->applyMode(modeName, privInfo);
 
        mds_dbus_complete_apply_mode(object, invocation, ret);
        if (MODES_ERROR_NONE == ret)
index 5a56c9d083713d4d12e132782b650ccb0e8b7feb..6047f4716c90c54c73ac31656d72e19534e3bb51 100644 (file)
@@ -32,6 +32,7 @@ const xmlChar* const RuleManager::RULE_TAGS[] = {
        (xmlChar*)"plugin",
        (xmlChar*)"alias",
        (xmlChar*)"conflict",
+       (xmlChar*)"privilege",
 };
 
 void RuleManager::makeRuleMap()
@@ -100,6 +101,13 @@ void RuleManager::parseElement(xmlNodePtr cur, ActionRule *actionRule)
 
                xmlFree(value);
                xmlFree(alias);
+       } else if (MDS_EQUAL == xmlStrcmp(cur->name, RULE_TAGS[TagElemPrivilege])) {
+               char *value = (char*)xmlNodeGetContent(cur);
+               if (NULL == value) {
+                       ERR("%s : No value", RULE_TAGS[TagElemPrivilege]);
+                       return;
+               }
+               actionRule->setPrivilege(value);
        } else if (MDS_EQUAL == xmlStrcmp(cur->name, RULE_TAGS[TagElemConflict])) {
                // TODO: enhanced feature
                DBG("TBD(%s)", cur->name);
index 15c80ebb57e738ff4c6a1c61eb22ebc7225e80c9..50035f7eaeac517c30e7fe16ffcc2d143e19e231 100644 (file)
@@ -33,6 +33,7 @@ public:
                TagAttPlugin,
                TagElemAlias,
                TagElemConflict,
+               TagElemPrivilege,
                TagMax
        };
 
index 3f60c083146e63bae2c8029e9e361196ced98e38..6dea12cc8638ce1a1af6fda4f51494e332e5477c 100644 (file)
@@ -37,6 +37,7 @@ public:
        {
                TAction<T> *action = new TAction<T>(ruleName);
                action->setValueAliases(valueAliasList);
+               action->setPrivilege(privilege);
 
                return action;
        }
index d68daeb303c3ab0294f8a5b538ee35abc3c25af0..14b5d25bc8b492a30b29b20e152175e62a38b929 100644 (file)
@@ -5,13 +5,12 @@ ADD_DEFINITIONS("-DMDS_TEST")
 SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/common/dbus.c
     PROPERTIES GENERATED TRUE)
 
-pkg_check_modules(gtest_pkgs REQUIRED dlog glib-2.0 gio-2.0 gio-unix-2.0 libxml-2.0 gmock)
+pkg_check_modules(gtest_pkgs REQUIRED dlog glib-2.0 gio-2.0 gio-unix-2.0 libxml-2.0 gmock cynara-client cynara-creds-gdbus cynara-session)
 INCLUDE_DIRECTORIES(${gtest_pkgs_INCLUDE_DIRS})
 LINK_DIRECTORIES(${gtest_pkgs_LIBRARY_DIRS})
 
 SET(SUPERVISOR_DIR "${CMAKE_SOURCE_DIR}/supervisor/" )
 FILE(GLOB SRC "modes_test_main.cpp")
-
 #=======================================================================================#
 SET(GTEST_NOTI "modes-gtest-noti")
 SET(GTEST_NOTI_SRCS modes_test_noti.cpp)
@@ -50,6 +49,7 @@ FILE(GLOB GTEST_MODEMGR_SRCS
                ${SUPERVISOR_DIR}/Action.cpp
                ${SUPERVISOR_DIR}/ActionRule.cpp
                ${SUPERVISOR_DIR}/RuleManager.cpp
+               ${SUPERVISOR_DIR}/ClientPrivilege.cpp
                ${SUPERVISOR_DIR}/Mode.cpp
                ${SUPERVISOR_DIR}/ModesEx.cpp
                ${SUPERVISOR_DIR}/PluginManager.cpp
@@ -57,6 +57,7 @@ FILE(GLOB GTEST_MODEMGR_SRCS
                modes_test_modemgr.cpp
        )
 ADD_EXECUTABLE(${GTEST_MODEMGR} ${SRC} ${GTEST_MODEMGR_SRCS})
+ADD_DEPENDENCIES(${GTEST_MODEMGR} GENERATED_DBUS_CODE)
 TARGET_LINK_LIBRARIES(${GTEST_MODEMGR} ${gtest_pkgs_LIBRARIES} dl)
 INSTALL(TARGETS ${GTEST_MODEMGR} DESTINATION ${TEST_INSTALL_DIR})
 
@@ -76,6 +77,7 @@ SET(GTEST_PARSER "modes-gtest-parser")
 FILE(GLOB GTEST_PARSER_SRCS
                ${SUPERVISOR_DIR}/XMLParser.cpp
                ${SUPERVISOR_DIR}/PluginManager.cpp
+               ${SUPERVISOR_DIR}/ClientPrivilege.cpp
                ${SUPERVISOR_DIR}/Action.cpp
                ${SUPERVISOR_DIR}/ActionRule.cpp
                ${SUPERVISOR_DIR}/RuleManager.cpp
@@ -87,6 +89,7 @@ FILE(GLOB GTEST_PARSER_SRCS
                modes_test_parser.cpp
        )
 ADD_EXECUTABLE(${GTEST_PARSER} ${SRC} ${GTEST_PARSER_SRCS})
+ADD_DEPENDENCIES(${GTEST_PARSER} GENERATED_DBUS_CODE)
 TARGET_LINK_LIBRARIES(${GTEST_PARSER} ${gtest_pkgs_LIBRARIES} dl)
 INSTALL(TARGETS ${GTEST_PARSER} DESTINATION ${TEST_INSTALL_DIR})
 #=======================================================================================#
@@ -100,12 +103,14 @@ FILE(GLOB GTEST_GENERATOR_SRCS
                ${SUPERVISOR_DIR}/Action.cpp
                ${SUPERVISOR_DIR}/ModesEx.cpp
                ${SUPERVISOR_DIR}/PluginManager.cpp
+               ${SUPERVISOR_DIR}/ClientPrivilege.cpp
                ${SUPERVISOR_DIR}/RuleManager.cpp
                ${SUPERVISOR_DIR}/ActionRule.cpp
                ${SUPERVISOR_DIR}/ValueChecker.cpp
                "modes_test_generator.cpp"
        )
 ADD_EXECUTABLE(${GTEST_GENERATOR} ${SRC} ${GTEST_GENERATOR_SRCS})
+ADD_DEPENDENCIES(${GTEST_GENERATOR} GENERATED_DBUS_CODE)
 TARGET_LINK_LIBRARIES(${GTEST_GENERATOR} ${gtest_pkgs_LIBRARIES} dl)
 INSTALL(TARGETS ${GTEST_GENERATOR} DESTINATION ${TEST_INSTALL_DIR})
 
@@ -120,6 +125,7 @@ FILE(GLOB GTEST_CONFLICT_SRCS
                ${SUPERVISOR_DIR}/ModeXMLParser.cpp
                ${SUPERVISOR_DIR}/XMLParser.cpp
                ${SUPERVISOR_DIR}/ModesEx.cpp
+               ${SUPERVISOR_DIR}/ClientPrivilege.cpp
                ${SUPERVISOR_DIR}/ModesXMLTag.cpp
                ${SUPERVISOR_DIR}/PluginManager.cpp
                ${SUPERVISOR_DIR}/RuleManager.cpp
@@ -128,6 +134,7 @@ FILE(GLOB GTEST_CONFLICT_SRCS
                modes_test_conflict.cpp
        )
 ADD_EXECUTABLE(${GTEST_CONFLICT} ${SRC} ${GTEST_CONFLICT_SRCS})
+ADD_DEPENDENCIES(${GTEST_CONFLICT} GENERATED_DBUS_CODE)
 TARGET_LINK_LIBRARIES(${GTEST_CONFLICT} ${gtest_pkgs_LIBRARIES} dl)
 INSTALL(TARGETS ${GTEST_CONFLICT} DESTINATION ${TEST_INSTALL_DIR})
 #=======================================================================================#
@@ -138,10 +145,12 @@ FILE(GLOB GTEST_RULE_SRCS
                ${SUPERVISOR_DIR}/ActionRule.cpp
                ${SUPERVISOR_DIR}/ModesEx.cpp
                ${SUPERVISOR_DIR}/Mode.cpp
+               ${SUPERVISOR_DIR}/ClientPrivilege.cpp
                ${SUPERVISOR_DIR}/Action.cpp
                ${SUPERVISOR_DIR}/ValueChecker.cpp
                modes_test_rulemgr.cpp
        )
 ADD_EXECUTABLE(${GTEST_RULEMGR} ${SRC} ${GTEST_RULE_SRCS})
+ADD_DEPENDENCIES(${GTEST_RULEMGR} GENERATED_DBUS_CODE)
 TARGET_LINK_LIBRARIES(${GTEST_RULEMGR} ${gtest_pkgs_LIBRARIES})
 INSTALL(TARGETS ${GTEST_RULEMGR} DESTINATION ${TEST_INSTALL_DIR})