Rewrite legacy code to C++ for checking privilege 20/284720/12
authorInkyun Kil <inkyun.kil@samsung.com>
Thu, 24 Nov 2022 07:31:13 +0000 (16:31 +0900)
committerInkyun Kil <inkyun.kil@samsung.com>
Thu, 8 Dec 2022 06:20:45 +0000 (15:20 +0900)
For SRP, codes for checking privilege should be separated from module code

Change-Id: Ief43c480ec42a42147edc26f4d3f237f42032b08
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
12 files changed:
packaging/esd.spec
src/modules/dbus_event/dbus_event_module.cc
src/modules/dbus_event/dbus_event_module.hh
src/modules/dbus_event/privilege_checker.cc [new file with mode: 0644]
src/modules/dbus_event/privilege_checker.hh [new file with mode: 0644]
tests/mock/cynara_mock.cc [new file with mode: 0644]
tests/mock/cynara_mock.h [new file with mode: 0644]
tests/mock/eventsystem_mock.h
tests/mock/security_manager_mock.cc [new file with mode: 0644]
tests/mock/security_manager_mock.h [new file with mode: 0644]
tests/unit_tests/src/test_privilege_checker.cc [new file with mode: 0644]
tests/unit_tests/src/test_vconf_handler.cc

index a4c2315..96642cd 100644 (file)
@@ -93,7 +93,7 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
 make %{?jobs:-j%jobs}
 
 %check
-ctest -v
+ctest -V
 
 %install
 rm -rf %{buildroot}
@@ -158,6 +158,7 @@ ln -sf ../esd.service %{buildroot}%{_unitdir}/multi-user.target.wants/esd.servic
 %manifest %{name}.manifest
 %license LICENSE
 %{_moddir}/mod/libesd-mod-dbus-event.so
+
 #################################################
 # unittests
 #################################################
index 1077f59..b825c5e 100644 (file)
 #include <tzplatform_config.h>
 #include <cert-svc/ccert.h>
 #include <cert-svc/cinstance.h>
-#include <cynara-client.h>
-#include <cynara-creds-gdbus.h>
-#include <cynara-session.h>
-#include <security-manager.h>
 #include "log.hh"
 #include "dbus_event_module.hh"
 
@@ -60,20 +56,6 @@ const char *event_launch_support_list[] = {
   SYS_EVENT_WIFI_STATE
 };
 
-struct privilege_info {
-  const char *event_name;
-  const char *privilege_name;
-};
-
-const struct privilege_info privilege_check_list[] = {
-  {SYS_EVENT_DISPLAY_STATE, "http://tizen.org/privilege/display"},
-  {SYS_EVENT_WIFI_STATE, "http://tizen.org/privilege/network.get"},
-  {SYS_EVENT_INCOMMING_MSG, "http://tizen.org/privilege/message.read"},
-  {SYS_EVENT_OUTGOING_MSG, "http://tizen.org/privilege/message.read"}
-};
-
-int privilege_check_size = sizeof(privilege_check_list)/sizeof(struct privilege_info);
-
 const char *earlier_event_list[] = {
   SYS_EVENT_ESD_STATUS,
   SYS_EVENT_LOW_MEMORY,
@@ -170,26 +152,6 @@ typedef struct __esd_appctrl_cb_data {
 void __esd_event_handler(char *event_name, bundle *data, void *user_data);
 int __esd_add_appinfo_handler(const pkgmgrinfo_appinfo_h handle, void *data);
 
-cynara *r_cynara;
-
-int __esd_init_cynara() {
-  int ret;
-
-  ret  = cynara_initialize(&r_cynara, NULL);
-  if (ret != CYNARA_API_SUCCESS) {
-    _E("cynara initialize failed.");
-    return ret;
-  }
-
-  return 0;
-}
-
-void __esd_finish_cynara() {
-  if (r_cynara)
-    cynara_finish(r_cynara);
-  r_cynara = NULL;
-}
-
 void free_saved_event(struct __last_event_item *item) {
   if (!item)
     return;
@@ -513,63 +475,6 @@ int __esd_check_trusted_events(GDBusConnection *conn, const char *list_name) {
   return ES_R_OK;
 }
 
-int __esd_check_privilege_name(const char *event_name, char **privilege_name) {
-  int i = 0;
-
-  *privilege_name = NULL;
-
-  for (i = 0; i < privilege_check_size; i++) {
-    if (strcmp(event_name, privilege_check_list[i].event_name) == 0) {
-      *privilege_name = (char *)privilege_check_list[i].privilege_name;
-      _D("[%d] privilege_name(%s)", i, *privilege_name);
-      break;
-    }
-  }
-
-  return ES_R_OK;
-}
-
-bool __esd_check_valid_privilege_by_cynara(const char *appid, const char *client,
-  const char *session, const char *user, const char *privilege_name) {
-  int ret = 0;
-  bool has_privilege = false;
-
-  _D("check privilege, (%s, %s, %s, %s, %s)", appid, client, session, user, privilege_name);
-
-  ret = cynara_check(r_cynara, client, session, user, privilege_name);
-  if (ret == CYNARA_API_ACCESS_ALLOWED) {
-    _D("valid privilege");
-    has_privilege = true;
-  } else if (ret == CYNARA_API_ACCESS_DENIED) {
-    _E("invalid privilege");
-  } else {
-    _E("failed to check privilege, error(%d)", ret);
-  }
-
-  return has_privilege;
-}
-
-int __esd_check_app_privileged_event(uid_t uid, const char *appid, const char *pkgid, const char *event_name) {
-  char *privilege_name = NULL;
-  int ret = 0;
-  int result = 0;
-
-  _D("event_name(%s), uid(%d), appid(%s), pkgid(%s)", event_name, uid, appid, pkgid);
-
-  __esd_check_privilege_name(event_name, &privilege_name);
-
-  if (privilege_name) {
-    ret = security_manager_app_has_privilege(appid, privilege_name, uid, &result);
-    if (ret != SECURITY_MANAGER_SUCCESS)
-      _E("failed to check privilege(%d)", ret);
-    _D("result(%d)", result);
-  } else {
-    result = 1;
-  }
-
-  return result;
-}
-
 void __esd_print_appid_with_eventid(gpointer data, gpointer user_data) {
   esd_list_item_s *item = (esd_list_item_s *)data;
   char *event_name = (char *)user_data;
@@ -1360,7 +1265,7 @@ int __esd_appcontrol_cb(const char *operation,
         _D("appid(%s), event_name(%s)", appid, event_name);
         if (!__esd_check_event_launch_support(event_name))
           _E("failed to add item (not support event)");
-        else if (!__esd_check_app_privileged_event(uid, appid, pkgid, event_name))
+        else if (!esd::module::PrivilegeChecker::AppHasPrivilege(uid, std::string(appid), std::string(event_name)))
           _E("failed to add item (no privilege)");
         else if (__esd_add_launch_item(uid, event_name, appid, pkgid))
           _E("failed to add item");
@@ -1539,12 +1444,10 @@ bool DbusEventModule::Init() {
   pkgmgr_client *client;
   esd_pkgmgr_event *pkg_event;
 
-  __esd_init_cynara();
-
+  auto checker = std::make_unique<PrivilegeChecker>();
   client = pkgmgr_client_new(PC_LISTENING);
   if (client == NULL) {
     _E("set pkgmgr client failed");
-    __esd_finish_cynara();
     return false;
   }
 
@@ -1554,7 +1457,6 @@ bool DbusEventModule::Init() {
     ret = pkgmgr_client_free(client);
     if (ret != PKGMGR_R_OK)
       _E("pkgmgr_client_free failed(%d)", ret);
-    __esd_finish_cynara();
     return false;
   }
 
@@ -1565,11 +1467,11 @@ bool DbusEventModule::Init() {
     if (ret != PKGMGR_R_OK)
       _E("pkgmgr_client_free failed(%d)", ret);
     free(pkg_event);
-    __esd_finish_cynara();
     return false;
   }
 
   s_info.client = client;
+  checker_ = std::move(checker);
 
   _I("esd init done");
 
@@ -1650,8 +1552,7 @@ void DbusEventModule::Fini() {
       _E("pkgmgr_client_free failed(%d)", ret);
   }
 
-  __esd_finish_cynara();
-
+  checker_->Reset();
   _D("esd finalize end");
 }
 
@@ -2018,62 +1919,30 @@ void DbusEventModule::CheckPrivilegeValidMethodCall(GDBusConnection* connection,
     const gchar* sender, GVariant* parameters,
     GDBusMethodInvocation* invocation) {
   GVariant *param = NULL;
-  int result = 0;
+  int result = 1;
   char *event_name = NULL;
-  char *privilege_name = NULL;
   char app_id[128] = {0, };
   int sender_pid = 0;
   uid_t sender_uid = 0;
-  char *client = NULL;
-  char *session = NULL;
-  char *user = NULL;
-  int ret = 0;
+  std::string privilege_name;
 
   g_variant_get(parameters, "(&s)", &event_name);
-  __esd_check_privilege_name(event_name, &privilege_name);
-  _D("event_name(%s), privilege_name(%s)", event_name, privilege_name);
+  privilege_name = checker_->CheckPrivilegeName(std::string(event_name));
+  _D("event_name(%s), privilege_name(%s)", event_name, privilege_name.c_str());
 
-  if (privilege_name) {
+  if (!privilege_name.empty()) {
     sender_pid = __get_sender_pid(connection, sender);
     sender_uid = (uid_t)__get_sender_uid(connection, sender);
     if (__esd_get_appid_by_pid_for_uid(sender_pid, sender_uid, app_id, sizeof(app_id)) < 0) {
       result = ES_R_ERROR;
     } else {
-      ret = cynara_creds_gdbus_get_client(connection, sender, CLIENT_METHOD_DEFAULT, &client);
-      if (ret != CYNARA_API_SUCCESS) {
-        _E("failed to get client");
-        result = ES_R_EINVAL;
-        goto out;
-      }
-
-      ret = cynara_creds_gdbus_get_user(connection, sender, USER_METHOD_DEFAULT, &user);
-      if (ret != CYNARA_API_SUCCESS) {
-        _E("failed to get user");
-        result = ES_R_EINVAL;
-        goto out;
-      }
-
-      session = cynara_session_from_pid(sender_pid);
-      if (session == NULL) {
-        _E("failed to get session");
-        result = ES_R_EINVAL;
-        goto out;
-      }
-
-      _D("app_id(%s), client(%s), session(%s), user(%s)", app_id, client, session, user);
-      if (__esd_check_valid_privilege_by_cynara(app_id, client, session, user, privilege_name))
+      if(checker_->Check(connection, sender, sender_pid, privilege_name))
         result = 1;
       else
         result = ES_R_EINVAL;
     }
-  } else {
-    result = 1;
   }
 
-out:
-  g_free(client);
-  g_free(user);
-  g_free(session);
   param = g_variant_new("(i)", result);
   _D("event_name(%s), result(%d)", event_name, result);
   g_dbus_method_invocation_return_value(invocation, param);
index c4d6399..2a8361c 100644 (file)
@@ -23,6 +23,7 @@
 #include <imodule.hh>
 
 #include "vconf_event_handler.hh"
+#include "privilege_checker.hh"
 
 namespace esd::module {
 
@@ -91,6 +92,7 @@ class DbusEventModule : public api::IModule {
  private:
   api::ToolBox* tools_ = nullptr;
   std::unique_ptr<VconfEventHandler> vconf_handler_;
+  std::unique_ptr<PrivilegeChecker> checker_;
 };
 
 }  // namespace esd::module
diff --git a/src/modules/dbus_event/privilege_checker.cc b/src/modules/dbus_event/privilege_checker.cc
new file mode 100644 (file)
index 0000000..c3c5c4c
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 "privilege_checker.hh"
+
+#include <cynara-client.h>
+#include <cynara-creds-gdbus.h>
+#include <cynara-session.h>
+#include <eventsystem_internal.h>
+#include <security-manager.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <string>
+#include <iostream>
+#include <map>
+
+#include <log.hh>
+
+namespace {
+
+const std::map<std::string, std::string> kPrivilegeInfoMap = {
+  {std::string(SYS_EVENT_DISPLAY_STATE), std::string("http://tizen.org/privilege/display")},
+  {std::string(SYS_EVENT_WIFI_STATE), std::string("http://tizen.org/privilege/network.get")},
+  {std::string(SYS_EVENT_INCOMMING_MSG), std::string("http://tizen.org/privilege/message.read")},
+  {std::string(SYS_EVENT_OUTGOING_MSG), std::string("http://tizen.org/privilege/message.read")}
+};
+
+}  // namespace
+
+namespace esd::module {
+
+PrivilegeChecker::PrivilegeChecker() : cynara_(nullptr, cynara_finish) {
+  cynara* _cynara = nullptr;
+  int ret = cynara_initialize(&_cynara, nullptr);
+  if (ret != CYNARA_API_SUCCESS)
+    _E("init cynara failed: %d", ret);
+  else
+    cynara_.reset(_cynara);
+}
+
+PrivilegeChecker::~PrivilegeChecker() = default;
+
+bool PrivilegeChecker::Check(GDBusConnection* connection,
+    const gchar* sender, int sender_pid, std::string privilege) {
+  char *client = nullptr;
+  char *session = nullptr;
+  char *user = nullptr;
+  bool allowed = false;
+
+  if (!cynara_.get())
+    return allowed;
+
+  int ret = cynara_creds_gdbus_get_client(connection, sender,
+      CLIENT_METHOD_DEFAULT, &client);
+  if (ret != CYNARA_API_SUCCESS) {
+    _E("failed to get client");
+    return allowed;
+  }
+  std::unique_ptr<char, decltype(g_free)*> client_auto(client, g_free);
+
+  ret = cynara_creds_gdbus_get_user(connection, sender, USER_METHOD_DEFAULT,
+      &user);
+  if (ret != CYNARA_API_SUCCESS) {
+    _E("failed to get user");
+    return allowed;
+  }
+  std::unique_ptr<char, decltype(g_free)*> user_auto(user, g_free);
+
+  session = cynara_session_from_pid(sender_pid);
+  if (session == NULL) {
+    _E("failed to get session");
+    return allowed;
+  }
+  std::unique_ptr<char, decltype(g_free)*> session_auto(session, g_free);
+
+  ret = cynara_check(cynara_.get(), client, session, user, privilege.c_str());
+  if (ret == CYNARA_API_ACCESS_ALLOWED)
+    allowed = true;
+  else
+    _E("cynara access check(%s) failed: %d", privilege.c_str(), ret);
+
+  return allowed;
+}
+
+void PrivilegeChecker::Reset() {
+  cynara_.reset();
+}
+
+bool PrivilegeChecker::AppHasPrivilege(uid_t uid, std::string appid,
+    std::string event_name) {
+  int ret = 0;
+  int result = 0;
+
+  _D("event_name(%s), uid(%d), appid(%s)", event_name.c_str(), uid, appid.c_str());
+
+  std::string privilege_name = CheckPrivilegeName(event_name);
+  if (!privilege_name.empty()) {
+    ret = security_manager_app_has_privilege(appid.c_str(), privilege_name.c_str(),
+        uid, &result);
+    if (ret != SECURITY_MANAGER_SUCCESS)
+      _E("failed to check privilege(%d)", ret);
+    _D("result(%d)", result);
+  } else {
+    result = 1;
+  }
+
+  return result;
+}
+
+std::string PrivilegeChecker::CheckPrivilegeName(std::string event_name) {
+  const auto& it = kPrivilegeInfoMap.find(event_name);
+  if (it == kPrivilegeInfoMap.end())
+    return "";
+  else
+    return std::string(it->second);
+}
+
+}  // namespace esd::module
\ No newline at end of file
diff --git a/src/modules/dbus_event/privilege_checker.hh b/src/modules/dbus_event/privilege_checker.hh
new file mode 100644 (file)
index 0000000..d95c02a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 EVENTSYSTEM_MODULES_DBUS_EVENT_PRIVILEGE_CHECKER_HH_
+#define EVENTSYSTEM_MODULES_DBUS_EVENT_PRIVILEGE_CHECKER_HH_
+
+#include <gio/gio.h>
+#include <cynara-client.h>
+
+#include <string>
+#include <memory>
+
+namespace esd::module {
+
+class PrivilegeChecker {
+ public:
+  PrivilegeChecker();
+  PrivilegeChecker(const PrivilegeChecker&) = delete;
+  PrivilegeChecker& operator=(const PrivilegeChecker&) = delete;
+  ~PrivilegeChecker();
+  bool Check(GDBusConnection* connection,
+    const gchar* sender, int sender_pid, std::string privilege);
+  void Reset();
+
+  static bool AppHasPrivilege(uid_t uid, std::string appid, std::string event_name);
+  static std::string CheckPrivilegeName(std::string event_name);
+
+ private:
+  std::unique_ptr<cynara, decltype(cynara_finish)*> cynara_;
+};
+
+}  // namespace esd::module
+
+#endif  // EVENTSYSTEM_MODULES_DBUS_EVENT_PRIVILEGE_CHECKER_HH_
diff --git a/tests/mock/cynara_mock.cc b/tests/mock/cynara_mock.cc
new file mode 100644 (file)
index 0000000..90c34e5
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 "cynara_mock.h"
+#include "mock_hook.h"
+#include "test_fixture.h"
+
+extern "C" int cynara_finish(cynara* arg0) {
+  return MOCK_HOOK_P1(CynaraMock, cynara_finish, arg0);
+}
+
+extern "C" int cynara_check(cynara* arg0, const char* arg1, const char* arg2,
+    const char* arg3, const char* arg4) {
+  return MOCK_HOOK_P5(CynaraMock, cynara_check, arg0, arg1, arg2, arg3, arg4);
+}
+
+extern "C" int cynara_initialize(cynara** arg0, const cynara_configuration* arg1) {
+  return MOCK_HOOK_P2(CynaraMock, cynara_initialize, arg0, arg1);
+}
+
+extern "C" int cynara_creds_gdbus_get_user(GDBusConnection* arg0,
+    const gchar* arg1, enum cynara_user_creds arg2, gchar** arg3) {
+  return MOCK_HOOK_P4(CynaraMock, cynara_creds_gdbus_get_user, arg0, arg1,
+      arg2, arg3);
+}
+
+extern "C" int cynara_creds_gdbus_get_client(GDBusConnection* arg0,
+    const gchar* arg1, enum cynara_client_creds arg2, gchar** arg3) {
+  return MOCK_HOOK_P4(CynaraMock, cynara_creds_gdbus_get_client, arg0, arg1,
+      arg2, arg3);
+}
+
+extern "C" char* cynara_session_from_pid(pid_t arg0) {
+  return MOCK_HOOK_P1(CynaraMock, cynara_session_from_pid, arg0);
+}
+
diff --git a/tests/mock/cynara_mock.h b/tests/mock/cynara_mock.h
new file mode 100644 (file)
index 0000000..d5d0d4d
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 MOCK_CYNARA_MOCK_H_
+#define MOCK_CYNARA_MOCK_H_
+
+#include <cynara-client.h>
+#include <cynara-creds-gdbus.h>
+#include <gmock/gmock.h>
+
+#include "module_mock.h"
+
+class CynaraMock : public virtual ModuleMock {
+ public:
+  virtual ~CynaraMock() {}
+
+  MOCK_METHOD1(cynara_finish, int (cynara*));
+  MOCK_METHOD5(cynara_check,
+      int (cynara*, const char*, const char*, const char*, const char*));
+  MOCK_METHOD2(cynara_initialize, int (cynara**, const cynara_configuration*));
+  MOCK_METHOD4(cynara_creds_gdbus_get_user, int (GDBusConnection*,
+      const gchar*, enum cynara_user_creds, gchar**));
+  MOCK_METHOD4(cynara_creds_gdbus_get_client, int (GDBusConnection*,
+      const gchar*, enum cynara_client_creds, gchar**));
+  MOCK_METHOD1(cynara_session_from_pid, char* (pid_t));
+};
+
+#endif  // MOCK_CYNARA_MOCK_H_
\ No newline at end of file
index 75fa309..e2a9fb9 100644 (file)
@@ -27,7 +27,7 @@ class EventSystemMock : public virtual ModuleMock {
  public:
   virtual ~EventSystemMock() {}
 
-  MOCK_METHOD2(eventsystem_send_system_event, int (const char*, bundle*));
+  MOCK_METHOD2(eventsystem_send_system_event, int(const char*, bundle*));
 
 };
 
diff --git a/tests/mock/security_manager_mock.cc b/tests/mock/security_manager_mock.cc
new file mode 100644 (file)
index 0000000..478cc58
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 "security_manager_mock.h"
+#include "mock_hook.h"
+#include "test_fixture.h"
+
+extern "C" int security_manager_app_has_privilege(const char* arg0,
+    const char* arg1, uid_t arg2, int* arg3) {
+  return MOCK_HOOK_P4(SecurityManagerMock, security_manager_app_has_privilege,
+      arg0, arg1, arg2, arg3);
+}
\ No newline at end of file
diff --git a/tests/mock/security_manager_mock.h b/tests/mock/security_manager_mock.h
new file mode 100644 (file)
index 0000000..fcfa5e9
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 MOCK_SECURITY_MANAGER_MOCK_H_
+#define MOCK_SECURITY_MANAGER_MOCK_H_
+
+#include <security-manager.h>
+#include <gmock/gmock.h>
+
+#include "module_mock.h"
+
+class SecurityManagerMock : public virtual ModuleMock {
+ public:
+  virtual ~SecurityManagerMock() {}
+
+  MOCK_METHOD4(security_manager_app_has_privilege, int (const char*,
+      const char*, uid_t, int*));
+};
+
+#endif  // MOCK_SECURITY_MANAGER_MOCK_H_
\ No newline at end of file
diff --git a/tests/unit_tests/src/test_privilege_checker.cc b/tests/unit_tests/src/test_privilege_checker.cc
new file mode 100644 (file)
index 0000000..c4dbf3c
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+
+#include <eventsystem_internal.h>
+#include <security-manager.h>
+
+#include "cynara_mock.h"
+#include "security_manager_mock.h"
+#include "test_fixture.h"
+#include "privilege_checker.hh"
+
+
+// using namespace tizen_base;
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+namespace {
+
+class Mocks : public ::testing::NiceMock<CynaraMock>,
+              public ::testing::NiceMock<SecurityManagerMock>{};
+
+}  //namespace
+
+class PrivilegeCheckerTest : public TestFixture {
+ public:
+  PrivilegeCheckerTest() : TestFixture(std::make_unique<Mocks>()) {}
+  virtual ~PrivilegeCheckerTest() {}
+
+  virtual void SetUp() {
+    EXPECT_CALL(GetMock<CynaraMock>(),
+      cynara_initialize(_, _)).WillRepeatedly(
+          Invoke([this](cynara** cynara, const cynara_configuration* conf) {
+            *cynara = this->cynara_;
+            return CYNARA_API_SUCCESS;
+          }));
+
+    cynara_ = (cynara*)malloc(1);
+    checker_ = std::make_unique<esd::module::PrivilegeChecker>();
+  }
+
+  virtual void TearDown() {
+    EXPECT_CALL(GetMock<CynaraMock>(),
+      cynara_finish(_)).WillRepeatedly(Return(CYNARA_API_SUCCESS));
+    checker_.reset();
+    free(cynara_);
+  }
+
+  cynara* cynara_;
+  std::unique_ptr<esd::module::PrivilegeChecker> checker_;
+};
+
+TEST_F(PrivilegeCheckerTest, CheckPrivilegeName) {
+  std::string priv = checker_->CheckPrivilegeName(std::string(SYS_EVENT_WIFI_STATE));
+  EXPECT_NE(priv, "");
+}
+
+TEST_F(PrivilegeCheckerTest, CheckPrivilegeName_N) {
+  std::string event_name("wifi_state");
+  std::string priv = checker_->CheckPrivilegeName(event_name);
+  EXPECT_EQ(priv, "");
+}
+
+TEST_F(PrivilegeCheckerTest, AppHasPrivilege) {
+  EXPECT_CALL(GetMock<SecurityManagerMock>(),
+      security_manager_app_has_privilege(_, _, _, _))
+          .WillOnce(DoAll(SetArgPointee<3>(1), Return(SECURITY_MANAGER_SUCCESS)));
+  uid_t uid = 5001;
+  std::string app_id("app_id");
+  std::string pkg_id("pkg_id");
+  bool ret = checker_->AppHasPrivilege(uid, app_id, SYS_EVENT_WIFI_STATE);
+  EXPECT_EQ(ret, true);
+}
+
+TEST_F(PrivilegeCheckerTest, Check) {
+  char* session = strdup("session");
+  EXPECT_CALL(GetMock<CynaraMock>(),
+      cynara_creds_gdbus_get_client(_, _, _, _))
+          .WillOnce(Return(CYNARA_API_SUCCESS));
+  EXPECT_CALL(GetMock<CynaraMock>(),
+      cynara_creds_gdbus_get_user(_, _, _, _))
+          .WillOnce(Return(CYNARA_API_SUCCESS));
+  EXPECT_CALL(GetMock<CynaraMock>(),
+      cynara_session_from_pid(_))
+          .WillOnce(Return(session));
+  EXPECT_CALL(GetMock<CynaraMock>(),
+      cynara_check(_, _, _, _, _))
+          .WillOnce(Return(CYNARA_API_ACCESS_ALLOWED));
+
+  std::string privilege("test");
+  bool ret = checker_->Check(nullptr, nullptr, 10, privilege);
+  EXPECT_EQ(ret, true);
+}
\ No newline at end of file
index 07d57b8..16d72b6 100644 (file)
 using ::testing::_;
 using ::testing::Return;
 
+namespace {
+
 class Mocks : public ::testing::NiceMock<EventSystemMock> {};
 
+} // namespace
+
 class VconfHandlerTest : public TestFixture {
  public:
   VconfHandlerTest() : TestFixture(std::make_unique<Mocks>()) {}
@@ -46,8 +50,7 @@ class VconfHandlerTest : public TestFixture {
 };
 
 TEST_F(VconfHandlerTest, SendSytemEvent) {
-EXPECT_CALL(GetMock<EventSystemMock>(),
-    eventsystem_send_system_event(_, _))
+  EXPECT_CALL(GetMock<EventSystemMock>(), eventsystem_send_system_event(_, _))
         .WillOnce(Return(ES_R_OK));
   bundle* b = bundle_create();
   int ret = handler_->SendSytemEvent(SYS_EVENT_WIFI_STATE, b,