From: Dariusz Michaluk Date: Mon, 15 Jun 2020 15:05:29 +0000 (+0200) Subject: Merge branch 'tizen' into ckm X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1653b62f71d1d54fe7fecb2d16dfa8d8365ce36b;hp=64360d7c6e10bdb6e23eadbca9799ca15144f960;p=platform%2Fcore%2Ftest%2Fsecurity-tests.git Merge branch 'tizen' into ckm Change-Id: Iecead619e756e6986f6677f88fdf6e596d6e40ef --- diff --git a/README b/README index ea2b291..a036712 100644 --- a/README +++ b/README @@ -120,8 +120,6 @@ tests-common Same as RUNNER_TEST_CHILD but run only with smack disabled. RUNNER_MULTIPROCESS_TEST_SMACK Same as RUNNER_TEST_MULTIPROCESS but run only with smack enabled. - RUNNER_MULTIPROCESS_TEST_NOSMACK - Same as RUNNER_TEST_MULTIPROCESS but run only with smack disabled. --Assert macros---------------------------------------------------------------- Used within test registering macros. diff --git a/packaging/security-tests.spec b/packaging/security-tests.spec index 76d554c..d7d6de7 100644 --- a/packaging/security-tests.spec +++ b/packaging/security-tests.spec @@ -30,7 +30,7 @@ BuildRequires: libcynara-creds-dbus-devel BuildRequires: libcynara-creds-gdbus-devel BuildRequires: libcynara-creds-sd-bus-devel BuildRequires: pkgconfig(libtzplatform-config) -BuildRequires: boost-devel +BuildRequires: pkgconfig(boost) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(libgum) >= 1.0.5 BuildRequires: pkgconfig(security-privilege-manager) @@ -45,6 +45,7 @@ Requires: toybox-symlinks-ping %global ckm_test_dir %{?TZ_SYS_SHARE:%TZ_SYS_SHARE/ckm-test/}%{!?TZ_SYS_SHARE:/usr/share/ckm-test/} %global ckm_rw_data_dir %{?TZ_SYS_DATA:%TZ_SYS_DATA/ckm/}%{!?TZ_SYS_DATA:/opt/data/ckm/} %global tz_backend_enabled %{?tz_backend:%tz_backend}%{!?tz_backend:OFF} +%global sm_test_dir %{?TZ_SYS_SHARE:%TZ_SYS_SHARE/security-manager-test}%{!?TZ_SYS_SHARE:/usr/share/security-manager-test} %description Security tests repository - for tests that can't be kept together with code. @@ -75,7 +76,8 @@ cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \ -DCKM_TEST_DIR=%{ckm_test_dir} \ -DCKM_RW_DATA_DIR=%{ckm_rw_data_dir} \ -DGLOBAL_APP_DIR=%{TZ_SYS_RW_APP} \ - -DLOCAL_APP_DIR="%{TZ_SYS_HOME}/security_test_user/apps_rw" + -DLOCAL_APP_DIR="%{TZ_SYS_HOME}/security_test_user/apps_rw" \ + -DSM_TEST_DIR="%{sm_test_dir}" make %{?jobs:-j%jobs} %pre @@ -135,6 +137,7 @@ echo "security-tests postinst done ..." %{_prefix}/share/yaca-test %dir %{_prefix}/share/security-tests-cleanup-test %{_prefix}/share/security-tests-cleanup-test/* +%{sm_test_dir} %postun id -u security_test_user 1>/dev/null 2>&1 && gum-utils -o -d --uid=`id -u security_test_user` diff --git a/src/ckm/ckm-common.cpp b/src/ckm/ckm-common.cpp index 714fa64..c50f2d6 100644 --- a/src/ckm/ckm-common.cpp +++ b/src/ckm/ckm-common.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2000-2020 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. @@ -383,7 +383,7 @@ void check_alias_list(const CKM::AliasVector& expected) } void check_alias_info_list_helper(const CKM::AliasPwdVector& expected, const CKM::AliasPwdVector& actual, - const std::string userSmackLabel) + const std::string &userSmackLabel) { std::string errorLogMsg; std::unordered_map aliasPwdMap; @@ -421,7 +421,7 @@ void check_alias_info_list_helper(const CKM::AliasPwdVector& expected, const CKM } } -void check_alias_info_list(const CKM::AliasPwdVector& expected, const std::string& userSmackLabel) +void check_alias_info_list(const CKM::AliasPwdVector& expected) { ckmc_alias_info_list_s *aliasInfoList = NULL; int ret = ckmc_get_data_alias_info_list(&aliasInfoList); @@ -447,7 +447,7 @@ void check_alias_info_list(const CKM::AliasPwdVector& expected, const std::strin it++; } ckmc_alias_info_list_all_free(aliasInfoList); - check_alias_info_list_helper(expected, actual, userSmackLabel); + check_alias_info_list_helper(expected, actual); } size_t count_aliases(alias_type_ type, size_t minimum_initial_element_count) diff --git a/src/ckm/ckm-common.h b/src/ckm/ckm-common.h index 69120c9..a61ffcf 100644 --- a/src/ckm/ckm-common.h +++ b/src/ckm/ckm-common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2000-2020 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. @@ -148,9 +148,8 @@ void reset_user_data(uid_t user_id, const char *passwd); ckmc_raw_buffer_s prepare_message_buffer(const char * input); void check_alias_list(const CKM::AliasVector& expected); void check_alias_info_list_helper(const CKM::AliasPwdVector& expected, const CKM::AliasPwdVector& actual, - const std::string userSmackLabel = ""); -void check_alias_info_list(const CKM::AliasPwdVector& expected, - const std::string& userSmackLabel = ""); + const std::string &userSmackLabel = {}); +void check_alias_info_list(const CKM::AliasPwdVector& expected); typedef enum { ALIAS_KEY, diff --git a/src/common/app_def_privilege.h b/src/common/app_def_privilege.h index d399dac..40d1d46 100644 --- a/src/common/app_def_privilege.h +++ b/src/common/app_def_privilege.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2018 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2020 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. @@ -32,6 +32,12 @@ public: PRIVACY, }; + Privilege(const char* systemPrivilege, Type type = UNSET, std::string license = std::string()) + : m_name(systemPrivilege) + , m_type(type) + , m_license(std::move(license)) + {} + Privilege(std::string systemPrivilege, Type type = UNSET, std::string license = std::string()) : m_name(std::move(systemPrivilege)) , m_type(type) @@ -66,6 +72,8 @@ public: operator std::string() const { return m_name; } + bool operator==(const std::string& other) const { return m_name == other; } + private: std::string m_name; Type m_type; diff --git a/src/common/app_install_helper.cpp b/src/common/app_install_helper.cpp index 1f6e0e8..cbc6a8d 100644 --- a/src/common/app_install_helper.cpp +++ b/src/common/app_install_helper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2020 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. @@ -159,12 +159,12 @@ std::string AppInstallHelper::getSharedROPath(int i, RootType type) const { return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::FILE, i, type); } -std::string AppInstallHelper::getAppId() const { - return m_appName + "_app_id"; +const std::string& AppInstallHelper::getAppId() const { + return m_appName; } -std::string AppInstallHelper::getPkgId() const { - return m_pkgName + "_pkg_id"; +const std::string& AppInstallHelper::getPkgId() const { + return m_pkgName; } void AppInstallHelper::setVersion(const std::string &version) { @@ -175,6 +175,10 @@ std::string AppInstallHelper::getVersion() const { return m_version; } +void AppInstallHelper::setUidGid(int uidGid) { + m_uidGid = uidGid; +} + int AppInstallHelper::getUID() const { return m_uidGid; } @@ -279,20 +283,6 @@ bool AppInstallHelper::getIsHybrid() const { return m_isHybrid; } -void AppInstallHelper::addPrivileges(const std::vector &privileges) { - for (auto &p : privileges) { - addPrivilege(Privilege(p)); - } -} - -std::vector AppInstallHelper::getPrivilegesNames() const { - std::vector privileges; - for (auto &p : m_privileges) { - privileges.push_back(p.getName()); - } - return privileges; -} - void AppInstallHelper::addPrivilege(Privilege privilege) { m_privileges.push_back(std::move(privilege)); } @@ -368,4 +358,3 @@ void AppInstallHelper::setInstallType(app_install_type type) { app_install_type AppInstallHelper::getInstallType() const { return m_installType; } - diff --git a/src/common/app_install_helper.h b/src/common/app_install_helper.h index cefeb71..cc59bc9 100644 --- a/src/common/app_install_helper.h +++ b/src/common/app_install_helper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2020 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. @@ -38,7 +38,7 @@ struct AppInstallHelper { bool isLocal, uid_t uid, std::string version = std::string()) - : m_appName(appNamePrefix), m_pkgName(pkgNamePrefix), m_isLocal(isLocal), m_uidGid(uid), m_version(version), + : m_appName(appNamePrefix + "_app_id"), m_pkgName(pkgNamePrefix + "_pkg_id"), m_isLocal(isLocal), m_uidGid(uid), m_version(version), m_installType(SM_APP_INSTALL_NONE), m_isHybrid(false), m_creatorPid(getpid()) {} @@ -74,8 +74,9 @@ struct AppInstallHelper { AppInstallHelper(AppInstallHelper &&other); // App info getters and setters - std::string getAppId() const; - std::string getPkgId() const; + const std::string& getAppId() const; + const std::string& getPkgId() const; + void setUidGid(int uidGid); int getUID() const; int getGID() const; void setVersion(const std::string &version); @@ -129,8 +130,6 @@ struct AppInstallHelper { const TypePathsMap& getFilesMap() const; // Privileges - std::vector getPrivilegesNames() const; // deprecated - void addPrivileges(const std::vector &privileges); // deprecated void addPrivilege(Privilege privilege); void addPrivileges(const PrivilegeVector &privileges); const PrivilegeVector& getPrivileges() const; @@ -163,8 +162,8 @@ protected: RootType rType = RootType::BASE); void createInstallDir(RootType type); - std::string m_appName; - std::string m_pkgName; + const std::string m_appName; + const std::string m_pkgName; bool m_isLocal; int m_uidGid; std::string m_version; diff --git a/src/common/scoped_installer.h b/src/common/scoped_installer.h index 82175ce..2eafe25 100644 --- a/src/common/scoped_installer.h +++ b/src/common/scoped_installer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -35,11 +35,13 @@ class ScopedInstaller { public: - ScopedInstaller(const AppInstallHelper &app, bool requestUid = true) + ScopedInstaller(const AppInstallHelper &app, + bool requestUid = true, + lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS) : m_appIds({app.getAppId()}), m_uid(app.getUID()), m_installType(app.getInstallType()), - m_shouldUninstall(true), + m_shouldUninstall(expectedResult == SECURITY_MANAGER_SUCCESS), m_requestUid(requestUid), m_creatorPid(getpid()) { @@ -67,7 +69,7 @@ public: for (const auto &priv : app.getAppDefinedPrivileges()) instReq.addAppDefinedPrivilege(priv); - SecurityManagerTest::Api::install(instReq); + SecurityManagerTest::Api::install(instReq, expectedResult); } ScopedInstaller(const std::vector &appIds, const std::string &pkgId) diff --git a/src/common/service_manager.cpp b/src/common/service_manager.cpp index 4441ace..cd27f31 100644 --- a/src/common/service_manager.cpp +++ b/src/common/service_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2013-2020 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. @@ -98,10 +98,10 @@ void ServiceManager::getUnitPath() DBus::MessageOut ServiceManager::newMethodCall(const std::string &method) { - return DBus::MessageOut(SYSTEMD_DESTINATION.c_str(), - SYSTEMD_PATH.c_str(), - SYSTEMD_MANAGER_INTERFACE.c_str(), - method.c_str()); + return DBus::MessageOut(SYSTEMD_DESTINATION, + SYSTEMD_PATH, + SYSTEMD_MANAGER_INTERFACE, + method); } std::string ServiceManager::handleObjectPathMsgReply(DBus::MessageIn &messageIn) diff --git a/src/common/sm_api.cpp b/src/common/sm_api.cpp index 4516755..dd1af2c 100644 --- a/src/common/sm_api.cpp +++ b/src/common/sm_api.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd. All rights reserved + * Copyright (c) 2014-2020 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. @@ -27,33 +27,13 @@ namespace Api { void install(const InstallRequest &request, lib_retcode expectedResult) { - uid_t uid = getuid(); - std::string dbPath = uid == 0 ? "/opt/dbspace/" : "/opt/dbspace/user/" + std::to_string(uid) + "/"; - - std::ostringstream command; - command << "/usr/bin/sqlite3 " - << dbPath << ".pkgmgr_parser.db " - << " \"insert into package_info (package, package_type, package_api_version," - << " install_location, mainapp_id, root_path, installed_storage)" - << " values ('" << request.getPkgId() << "', 'tpk', '" << request.getAppTizenVersion() - << "', 'auto', '" << request.getPkgId() << "', '/opt/usr/globallapps/" - << request.getPkgId() << "', 'installed_internal')\""; - int result = system(command.str().c_str()); - RUNNER_ASSERT_MSG(result == 0, "failed to set package_info: " << result); - - result = security_manager_app_install(request.get()); + int result = security_manager_app_install(request.get()); + RUNNER_ASSERT_MSG((lib_retcode)result == expectedResult, "installing app returned wrong value." - << " InstallRequest: [ " << request << "];" - << " Result: " << result << ";" - << " Expected result: " << expectedResult); - - command = std::ostringstream(); - command << "/usr/bin/sqlite3 " - << dbPath << ".pkgmgr_parser.db " - << " \"delete from package_info where package='" << request.getPkgId() << "'\""; - result = system(command.str().c_str()); - RUNNER_ASSERT_MSG(result == 0, "failed to unset package_info: " << result); + << " InstallRequest: [ " << request << "];" + << " Result: " << result << ";" + << " Expected result: " << expectedResult); } void update(const InstallRequest &request, lib_retcode expectedResult) diff --git a/src/common/sm_policy_request.cpp b/src/common/sm_policy_request.cpp index debda17..c129a76 100644 --- a/src/common/sm_policy_request.cpp +++ b/src/common/sm_policy_request.cpp @@ -20,6 +20,10 @@ namespace SecurityManagerTest { +constexpr char PolicyEntry::LEVEL_ALLOW[]; +constexpr char PolicyEntry::LEVEL_DENY[]; +constexpr char PolicyEntry::LEVEL_ASK_USER[]; + PolicyEntry::PolicyEntry() : m_appId(true, std::string(SECURITY_MANAGER_ANY)) , m_user(true, std::string(SECURITY_MANAGER_ANY)) diff --git a/src/common/sm_policy_request.h b/src/common/sm_policy_request.h index 4c12102..d1791a7 100644 --- a/src/common/sm_policy_request.h +++ b/src/common/sm_policy_request.h @@ -29,6 +29,10 @@ namespace SecurityManagerTest { class PolicyEntry { public: + static constexpr char LEVEL_ALLOW[] = "Allow"; + static constexpr char LEVEL_DENY[] = "Deny"; + static constexpr char LEVEL_ASK_USER[] = "Ask user"; + PolicyEntry(); PolicyEntry(const std::string &appId, diff --git a/src/common/sm_request.cpp b/src/common/sm_request.cpp index b6fa1a1..89ec04d 100644 --- a/src/common/sm_request.cpp +++ b/src/common/sm_request.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2020 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. @@ -44,6 +44,14 @@ InstallRequest::InstallRequest() RUNNER_ASSERT_MSG((lib_retcode)result == SECURITY_MANAGER_SUCCESS, "creation of new request failed. Result: " << result); RUNNER_ASSERT_MSG(m_req != nullptr, "creation of new request did not allocate memory"); + // platform level has the widest possible privilege spectrum available, hence using it for all apps + result = security_manager_app_inst_req_set_pkg_privilege_level(m_req, SM_PKG_PRIVILEGE_LEVEL_PLATFORM); + RUNNER_ASSERT_MSG((lib_retcode)result == SECURITY_MANAGER_SUCCESS, + "setting privilege level failed. Result: " << result); + // core seems to map to TPK, which is what we're mimicking + result = security_manager_app_inst_req_set_pkg_type(m_req, SM_PKG_TYPE_CORE); + RUNNER_ASSERT_MSG((lib_retcode)result == SECURITY_MANAGER_SUCCESS, + "setting package type. Result: " << result); } InstallRequest::~InstallRequest() diff --git a/src/common/tests_common.cpp b/src/common/tests_common.cpp index 235b062..b4d0d33 100644 --- a/src/common/tests_common.cpp +++ b/src/common/tests_common.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 - 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2013-2020 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. @@ -22,16 +22,12 @@ */ #include "tests_common.h" -#include #include #include #include #include #include -#include #include -#include -#include bool smack_check(void) { @@ -65,56 +61,6 @@ int drop_root_privileges(uid_t appUid, gid_t appGid) return 1; } -/* - * Add a new group to the current process groups. - */ -void add_process_group(const char* group_name) -{ - // get group ID by group name - group *gr = getgrnam(group_name); - RUNNER_ASSERT_ERRNO_MSG(gr != nullptr, "getgrnam failed on '" << group_name << "' group"); - const gid_t new_group_id = gr->gr_gid; - - // get number of groups that the current process belongs to - int ngroups = getgroups(0, nullptr); - - //allocate groups table + space for new group entry - std::vector groups(ngroups + 1); - getgroups(ngroups, groups.data()); - - // check if the process already belongs to the group - if (std::find(groups.begin(), groups.end(), new_group_id) != groups.end()) return; - - // add new group & apply change - groups[ngroups] = new_group_id; - int ret = setgroups(groups.size(), groups.data()); - RUNNER_ASSERT_ERRNO_MSG(ret == 0, "setgroups() failed"); -} - -/* - * Remove specific group from the current process groups. - */ -void remove_process_group(const char* group_name) -{ - // get group ID by group name - group *gr = getgrnam(group_name); - RUNNER_ASSERT_ERRNO_MSG(gr != nullptr, "getgrnam failed on '" << group_name << "' group"); - const gid_t new_group_id = gr->gr_gid; - - int ngroups = getgroups(0, nullptr); - std::vector groups(ngroups); - getgroups(ngroups, groups.data()); - - // remove group from the list - groups.erase(std::remove(groups.begin(), groups.end(), new_group_id), groups.end()); - - if (groups.size() != (size_t)ngroups) { - // apply change - int ret = setgroups(groups.size(), groups.data()); - RUNNER_ASSERT_ERRNO_MSG(ret == 0, "setgroups() failed"); - } -} - std::string formatCstr(const char *cstr) { if (!cstr) @@ -166,7 +112,7 @@ int files_compare(int fd1, int fd2) return result; } -void mkdirSafe(const std::string &path, mode_t mode) +static void mkdirSafe(const std::string &path, mode_t mode) { RUNNER_ASSERT_ERRNO_MSG(0 == mkdir(path.c_str(), mode) || errno == EEXIST, "mkdir for <" << path << "> with mode <" << mode << "> failed"); @@ -182,50 +128,6 @@ void mktreeSafe(const std::string &path, mode_t mode) mkdirSafe(path, mode); } -void creatSafe(const std::string &path, mode_t mode) -{ - RUNNER_ASSERT_ERRNO_MSG(-1 != creat(path.c_str(), mode), - "creat for <" << path << "> with mode <" << mode << "> failed"); -} - -void symlinkSafe(const std::string &targetPath, const std::string &linkPath) -{ - RUNNER_ASSERT_ERRNO_MSG(0 == symlink(targetPath.c_str(), linkPath.c_str()), - "symlink for <" << linkPath << "> to <" << targetPath << "> failed"); -} - -void removeDir(const std::string &path) -{ - DIR *d = opendir(path.c_str()); - - if (nullptr == d) { - RUNNER_ASSERT_ERRNO_MSG(errno == ENOENT, "opendir of <" << path << "> failed"); - return; - } - - struct dirent *dirEntry; - while (nullptr != (dirEntry = readdir(d))) { - std::string entryName(dirEntry->d_name); - if (entryName == "." || entryName == "..") - continue; - - std::string entryPath(path + "/" + entryName); - struct stat st; - - RUNNER_ASSERT_ERRNO_MSG(0 == lstat(entryPath.c_str(), &st), - "stat for <" << entryPath << "> failed"); - if (S_ISDIR(st.st_mode)) - removeDir(entryPath); - else - RUNNER_ASSERT_ERRNO_MSG(0 == unlink(entryPath.c_str()), - "unlink for <" << entryPath << "> failed"); - } - - closedir(d); - - RUNNER_ASSERT_ERRNO_MSG(0 == rmdir(path.c_str()), "rmdir for <" << path << "> failed"); -} - void waitPid(pid_t pid) { int status; diff --git a/src/common/tests_common.h b/src/common/tests_common.h index bfb46d9..da78ac9 100644 --- a/src/common/tests_common.h +++ b/src/common/tests_common.h @@ -34,28 +34,16 @@ #include #include #include -#include #include const uid_t APP_UID = 5001; const gid_t APP_GID = 100; -const uid_t APP_UID_2 = 5200; -const gid_t APP_GID_2 = 5200; -const uid_t DB_ALARM_UID = 6001; -const gid_t DB_ALARM_GID = 6001; -const std::string TMP_DIR("/tmp"); bool smack_check(void); int drop_root_privileges(uid_t appUid = APP_UID, gid_t appGid = APP_GID); -void add_process_group(const char* group_name); -void remove_process_group(const char* group_name); std::string formatCstr(const char *cstr); int files_compare(int fd1, int fd2); -void mkdirSafe(const std::string &path, mode_t mode); void mktreeSafe(const std::string &path, mode_t mode); -void creatSafe(const std::string &path, mode_t mode); -void symlinkSafe(const std::string &targetPath, const std::string &linkPath); -void removeDir(const std::string &path); void waitPid(pid_t pid); pid_t runInChild(const std::function &process); @@ -133,20 +121,4 @@ void runInChildParentWait(const std::function &process); } \ void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED) -#define RUNNER_MULTIPROCESS_TEST_NOSMACK(Proc, ...) \ - void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple); \ - void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple); \ - static int Static##Proc##Init() \ - { \ - if (!smack_check()) \ - DPL::Test::TestRunnerSingleton::Instance().RegisterTest( \ - new DPL::Test::TestCaseExtended<__VA_ARGS__>(#Proc, &Proc)); \ - return 0; \ - } \ - const int DPL_UNUSED Static##Proc##InitVar = Static##Proc##Init(); \ - void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple) { \ - DPL::Test::RunMultiProc(std::bind(Proc##Multi, optionalArgsTuple)); \ - } \ - void Proc##Multi(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED) - #endif diff --git a/src/cynara-tests/common/cynara_test_commons.cpp b/src/cynara-tests/common/cynara_test_commons.cpp index 91a93f4..483681f 100644 --- a/src/cynara-tests/common/cynara_test_commons.cpp +++ b/src/cynara-tests/common/cynara_test_commons.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2020 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. @@ -40,7 +40,7 @@ void loadServicePlugins(const DirectoryPaths &pluginDirectories) FileOperations::removeDirFiles(CynaraTestConsts::SERVICE_PLUGINS_DIR); for (const auto &dir : pluginDirectories) - FileOperations::copyCynaraFiles(dir.c_str(), CynaraTestConsts::SERVICE_PLUGINS_DIR); + FileOperations::copyCynaraFiles(dir, CynaraTestConsts::SERVICE_PLUGINS_DIR); } void restartCynaraService() diff --git a/src/cynara-tests/common/cynara_test_env.cpp b/src/cynara-tests/common/cynara_test_env.cpp index 7b9a1a9..7740f9d 100644 --- a/src/cynara-tests/common/cynara_test_env.cpp +++ b/src/cynara-tests/common/cynara_test_env.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2020 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. @@ -36,7 +36,7 @@ CynaraTestEnv::~CynaraTestEnv() void CynaraTestEnv::init(const std::string &testName) { - m_saveDir = TMP_DIR + "/" + testName; + m_saveDir = "/tmp/" + testName; m_dbSaveDir = m_saveDir + "/db"; m_defaultDir = "/etc/security-tests/db_patterns/default"; m_pluginsToInstallDir = "/opt/plugins_to_install"; diff --git a/src/cynara-tests/common/cynara_test_file_operations.cpp b/src/cynara-tests/common/cynara_test_file_operations.cpp index 1f7a5da..cf5b4c1 100644 --- a/src/cynara-tests/common/cynara_test_file_operations.cpp +++ b/src/cynara-tests/common/cynara_test_file_operations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015-2020 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. @@ -35,7 +35,9 @@ namespace FileOperations { -static int removeFile(const char *fpath, const struct stat * /*sb*/, +namespace { + +int removeFile(const char *fpath, const struct stat * /*sb*/, int tflag, struct FTW * /*ftwbuf*/) { if (tflag == FTW_F) @@ -45,18 +47,18 @@ static int removeFile(const char *fpath, const struct stat * /*sb*/, return 0; } -bool dirExists(const std::string &directory) +void syncElem(const std::string &filename, int flags, mode_t mode) { - struct stat st; - int ret = stat(directory.c_str(), &st); - if (ret == -1 && errno == ENOENT) { - return false; - } else if (ret == -1) { - RUNNER_ASSERT_ERRNO_MSG(false, "Cannot stat " << directory - << " not due to its nonexistence"); - } - RUNNER_ASSERT_MSG(st.st_mode & S_IFDIR, directory << " is not a directory"); - return true; + int fileFd = TEMP_FAILURE_RETRY(open(filename.c_str(), flags, mode)); + RUNNER_ASSERT_ERRNO_MSG(fileFd != -1, "open failed name=" << filename); + FdUniquePtr fdPtr(&fileFd); + + int ret = fsync(fileFd); + RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fsync failed name=" << filename); +} + +void syncDir(const std::string &dirname, mode_t mode = S_IRUSR | S_IWUSR) { + syncElem(dirname, O_DIRECTORY, mode); } void copyCynaraFile(const std::string &src, const std::string &dst) @@ -100,6 +102,22 @@ void copyCynaraFile(const std::string &src, const std::string &dst) RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fsync failed"); } +} // namespace + +bool dirExists(const std::string &directory) +{ + struct stat st; + int ret = stat(directory.c_str(), &st); + if (ret == -1 && errno == ENOENT) { + return false; + } else if (ret == -1) { + RUNNER_ASSERT_ERRNO_MSG(false, "Cannot stat " << directory + << " not due to its nonexistence"); + } + RUNNER_ASSERT_MSG(st.st_mode & S_IFDIR, directory << " is not a directory"); + return true; +} + void copyCynaraFiles(const std::string &source, const std::string &destination) { DIR *dirPtr = nullptr; @@ -121,20 +139,6 @@ void copyCynaraFiles(const std::string &source, const std::string &destination) syncDir(destination); } -void syncElem(const std::string &filename, int flags, mode_t mode) -{ - int fileFd = TEMP_FAILURE_RETRY(open(filename.c_str(), flags, mode)); - RUNNER_ASSERT_ERRNO_MSG(fileFd != -1, "open failed name=" << filename); - FdUniquePtr fdPtr(&fileFd); - - int ret = fsync(fileFd); - RUNNER_ASSERT_ERRNO_MSG(ret != -1, "fsync failed name=" << filename); -} - -void syncDir(const std::string &dirname, mode_t mode) { - syncElem(dirname, O_DIRECTORY, mode); -} - void makeDir(const std::string &directory) { RUNNER_ASSERT_ERRNO_MSG(!mkdir(directory.c_str(), S_IRWXU | S_IRWXG | S_IRWXO), diff --git a/src/cynara-tests/common/cynara_test_file_operations.h b/src/cynara-tests/common/cynara_test_file_operations.h index d3acdb8..d32008d 100644 --- a/src/cynara-tests/common/cynara_test_file_operations.h +++ b/src/cynara-tests/common/cynara_test_file_operations.h @@ -17,17 +17,13 @@ #ifndef CYNARA_TEST_FILE_OPERATIONS_H #define CYNARA_TEST_FILE_OPERATIONS_H -#include #include namespace FileOperations { bool dirExists(const std::string &directory); -void copyCynaraFile(const std::string &src, const std::string &dst); void copyCynaraFiles(const std::string &source, const std::string &destination); -void syncElem(const std::string &filename, int flags = O_RDONLY, mode_t mode = S_IRUSR | S_IWUSR); -void syncDir(const std::string &dirname, mode_t mode = S_IRUSR | S_IWUSR); void makeDir(const std::string &directory); void removeDirFiles(const std::string &dir); void removeDirIfExists(const std::string &dir); diff --git a/src/framework/include/dpl/exception.h b/src/framework/include/dpl/exception.h index eb5cfc7..214a8cf 100644 --- a/src/framework/include/dpl/exception.h +++ b/src/framework/include/dpl/exception.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2011-2020 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. @@ -114,12 +114,12 @@ class Exception static void DisplayKnownException(const Exception& e) { - LogUnhandledException(KnownExceptionToString(e).c_str()); + LogUnhandledException(KnownExceptionToString(e)); } static void DisplayUnknownException() { - LogUnhandledException(UnknownExceptionToString().c_str()); + LogUnhandledException(UnknownExceptionToString()); } Exception(const Exception &other) diff --git a/src/framework/src/test_results_collector_summary.cpp b/src/framework/src/test_results_collector_summary.cpp index efcaa31..b9bb8f2 100644 --- a/src/framework/src/test_results_collector_summary.cpp +++ b/src/framework/src/test_results_collector_summary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2020 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. @@ -76,7 +76,7 @@ void SummaryCollector::Finish() void SummaryCollector::writeStats(bool segfault) { - m_output.open(m_filename.c_str(), std::ofstream::out | std::ofstream::trunc); + m_output.open(m_filename, std::ofstream::out | std::ofstream::trunc); if (!m_output) { LogPedantic("Could not open file " << m_filename << " for writing"); return; diff --git a/src/security-manager-tests/CMakeLists.txt b/src/security-manager-tests/CMakeLists.txt index cf08aa4..703d034 100644 --- a/src/security-manager-tests/CMakeLists.txt +++ b/src/security-manager-tests/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved +# Copyright (c) 2014-2020 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. @@ -17,6 +17,11 @@ # @brief # +IF(NOT DEFINED SM_TEST_DIR) + SET(SM_TEST_DIR "${SHARE_INSTALL_PREFIX}/security-manager-test") +ENDIF(NOT DEFINED SM_TEST_DIR) +ADD_DEFINITIONS("-DSM_TEST_DIR=\"${SM_TEST_DIR}\"") + INCLUDE(FindPkgConfig) # Dependencies @@ -31,7 +36,8 @@ PKG_CHECK_MODULES(SEC_MGR_TESTS_DEP sqlite3 libcap dbus-1 - libgum) + libgum + boost) SET(TARGET_SEC_MGR_TESTS "security-manager-tests") @@ -52,12 +58,15 @@ SET(SEC_MGR_SOURCES ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_public_sharing.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_register_paths.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_shm.cpp + ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_smack_privileges.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_trusted_sharing.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_prepare_app.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/security_manager_tests.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/policy_configuration.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/sm_commons.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/template_parser.cpp + ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/scoped_app_launcher.cpp + ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/app_install_helper_ext.cpp ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_client.cpp ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_admin.cpp ${PROJECT_SOURCE_DIR}/src/cynara-tests/plugins/plugins.cpp @@ -100,4 +109,9 @@ INSTALL(DIRECTORY INSTALL(DIRECTORY ${PROJECT_SOURCE_DIR}/src/security-manager-tests/app_files/ DESTINATION ${LOCAL_APP_DIR} +) + +INSTALL(DIRECTORY + ${PROJECT_SOURCE_DIR}/src/security-manager-tests/smack-privileges + DESTINATION ${SM_TEST_DIR} ) \ No newline at end of file diff --git a/src/security-manager-tests/common/app_install_helper_ext.cpp b/src/security-manager-tests/common/app_install_helper_ext.cpp new file mode 100644 index 0000000..878dfc1 --- /dev/null +++ b/src/security-manager-tests/common/app_install_helper_ext.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2020 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 "app_install_helper_ext.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace { +constexpr char SMACK_RULES_PATH[] = "/sys/fs/smackfs/load2"; +constexpr char ANY_USER_REPRESENTATION[] = "anyuser";/*this may be actually any string*/ + +void assertNoLabelInRule(const AccessRequest &rule, const std::string &label) +{ + RUNNER_ASSERT_MSG(rule.object != label && rule.subject != label, + "Smack rule left after uninstallation process." << + " Subject: " << rule.subject << + " object: " << rule.object << + " access: " << rule.access); +} + +std::string accessOpposite(std::string &access) +{ + static const std::map accessMapping = {{'r', 0}, {'w', 1}, {'x', 2}, {'a', 3}, + {'t', 4}, {'l', 5}}; + // May write implies may lock + if (access.find('w') != std::string::npos && access.find('l') == std::string::npos) { + access.append("l"); + } + std::string oppositeAccess = "rwxatl"; + for (char c : access) { + oppositeAccess[accessMapping.at(c)] = '-'; + } + auto it = std::remove_if(oppositeAccess.begin(), oppositeAccess.end(), [](char c) {return c == '-';}); + oppositeAccess.erase(it, oppositeAccess.end()); + return oppositeAccess; +} + +void checkExactSmackAccesses(const std::string &subject, const std::string &object, + const std::string &access) +{ + std::string access_str(access); + auto no_access = accessOpposite(access_str); + for (char c : access_str) { + int ret = smack_have_access(subject.c_str(), object.c_str(), std::string(1, c).c_str()); + RUNNER_ASSERT_MSG(ret >= 0, "smack_have_access failed: <" << subject << ">, <" << object + << ">, <" << c << "> errno=" << strerror(errno)); + RUNNER_ASSERT_MSG(ret == 1, "Access " << c << " from " << subject << " to " + << object << " not given"); + } + + for (char c : no_access) { + int ret = smack_have_access(subject.c_str(), object.c_str(), std::string(1, c).c_str()); + RUNNER_ASSERT_MSG(ret >= 0, "smack_have_access failed: <" << subject << ">, <" << object + << ">, <" << c << "> errno=" << strerror(errno)); + RUNNER_ASSERT_MSG(ret == 0, "Access " << c << " from " << subject << " to " + << object << " unnecessarily given"); + } +} + +} // namespace anonymous + +namespace SecurityManagerTest +{ + +void AppInstallHelperExt::checkPrivileges(const PrivilegeVector &allowedPrivs, + const PrivilegeVector &deniedPrivs) const +{ + /* Privileges should be granted to all users if root installs app */ + auto user = (m_uidGid == 0 ? ANY_USER_REPRESENTATION : std::to_string(m_uidGid)); + + std::string smackLabel = generateProcessLabel(m_appName, m_pkgName, m_isHybrid); + + CynaraTestClient::Client ctc; + int result; + + for (auto &priv : allowedPrivs) { + ctc.check(smackLabel, "", user, priv.getName(), CYNARA_API_ACCESS_ALLOWED); + + Api::appHasPrivilege(m_appName, priv, m_uidGid, result); + RUNNER_ASSERT_MSG(result == 1, + "Application " << m_appName << " has no access to " << priv); + } + + for (auto &priv : deniedPrivs) { + ctc.check(smackLabel, "", user, priv.getName(), CYNARA_API_ACCESS_DENIED); + + Api::appHasPrivilege(m_appName, priv, m_uidGid, result); + RUNNER_ASSERT_MSG(result == 0, + "Application " << m_appName << " has unexpected access to " << priv); + } +} + +void AppInstallHelperExt::checkDeniedPrivileges(const PrivilegeVector &deniedPrivs) const +{ + checkPrivileges({}, deniedPrivs); +} + +void AppInstallHelperExt::checkGroupPrivileges(const PrivilegeVector &expectedPrivs) const +{ + static PolicyConfiguration policy; + + // get expected groups + auto expectedGids = policy.groupToGid(policy.privToGroup(expectedPrivs)); + RUNNER_ASSERT_MSG(expectedGids.size() == expectedPrivs.size(), + "Some privileges given were not found in the policy"); + std::sort(expectedGids.begin(), expectedGids.end()); + + // get current process groups + int ret = getgroups(0, nullptr); + RUNNER_ASSERT_MSG(ret != -1, "Unable to get supplementary groups"); + + std::vector actualGids(ret); + ret = getgroups(ret, actualGids.data()); + RUNNER_ASSERT_MSG(ret != -1, "Unable to get supplementary groups"); + + // remove groups unrelated to privileges + const auto allPrivGids = policy.getGid(); + auto notPrivGid = [&](gid_t gid){ + return std::find(allPrivGids.begin(), allPrivGids.end(), gid) == allPrivGids.end(); + }; + actualGids.erase(std::remove_if(actualGids.begin(), actualGids.end(), notPrivGid), + actualGids.end()); + std::sort(actualGids.begin(), actualGids.end()); + + // expected but not allowed + std::vector notAllowedGids; + std::set_difference(expectedGids.begin(), expectedGids.end(), + actualGids.begin(), actualGids.end(), + std::back_inserter(notAllowedGids)); + + RUNNER_ASSERT_MSG(notAllowedGids.empty(), + notAllowedGids.size() << " expected groups were not assigned"); + + // allowed but not expected + std::vector notDeniedGids; + std::set_difference(actualGids.begin(), actualGids.end(), + expectedGids.begin(), expectedGids.end(), + std::back_inserter(notDeniedGids)); + + RUNNER_ASSERT_MSG(notDeniedGids.empty(), + notDeniedGids.size() << " unexpected groups were assigned"); +} + +void AppInstallHelperExt:: checkSmackPrivileges(const PrivilegeVector &allowedPrivs, + const PrivilegeVector &deniedPrivs) const +{ + auto& smackPrivilegeRules = PolicyConfiguration::getSmackPrivRulesMap(); + + auto getPrivilegeRules = [&](const PrivilegeVector &privs) { + std::vector rules; + + for (auto &priv : privs) { + auto it = smackPrivilegeRules.find(priv); + RUNNER_ASSERT_MSG(it != smackPrivilegeRules.end(), priv << " is not a smack privilege"); + + rules.insert(rules.end(), it->second.begin(), it->second.end()); + } + return rules; + }; + + checkSmackAccesses(getPrivilegeRules(allowedPrivs)); + checkSmackAccesses(getPrivilegeRules(deniedPrivs), false); +} + +void AppInstallHelperExt::checkAfterInstall() const +{ + static const std::vector staticRules[] = + {parseSmackRulesFile(PolicyConfiguration::getPkgRulesFilePath()), + parseSmackRulesFile(PolicyConfiguration::getAppRulesFilePath())}; + + checkAppIdExistence(true); + + checkSmackAccesses(staticRules[m_isHybrid]); + + checkPrivileges(m_privileges, {}); +} + +void AppInstallHelperExt::checkAfterUninstall(bool removePkg) const +{ + checkAppIdExistence(false); + + if (removePkg) { + checkPkgSmackRulesAfterUninstall(); + } + // there should be no hybrid rules regardless of the app type + checkHybridAppSmackRulesAterUninstall(); + + checkDeniedPrivileges(m_privileges); +} + +void AppInstallHelperExt::checkSmackAccesses(std::vector rules, bool hasAccess) const +{ + const std::pair switchAliases[] = { + {"~PATH_RW~", generatePathRWLabel(m_pkgName)}, + {"~PATH_RO~", generatePathROLabel(m_pkgName)}, + {"~PROCESS~", generateProcessLabel(m_appName, m_pkgName, m_isHybrid)} + }; + + for (auto& rule : rules) { + if (rule.object == "~PATH_TRUSTED~") { + continue; + } + + for (const auto &alias : switchAliases) { + if (rule.subject == alias.first) { + rule.subject = alias.second; + } + if (rule.object == alias.first) { + rule.object = alias.second; + } + } + + if (!hasAccess) + rule.access = ""; + + // Special label that may occur in the template. Other special labels will not be used. + if (rule.object == "_") { + rule.access = "rx" + rule.access; + } + + checkExactSmackAccesses(rule.subject, rule.object, rule.access); + } +} + +void AppInstallHelperExt::checkPkgSmackRulesAfterUninstall() const +{ + const std::vector rules(std::move(parseSmackRulesFile(SMACK_RULES_PATH))); + const std::string labels[] = {generatePathRWLabel(m_pkgName), + generatePathROLabel(m_pkgName), + generateProcessLabel(m_appName, m_pkgName, true), + generateProcessLabel(m_appName, m_pkgName)}; + + for (const auto &rule : rules) { + for (const auto &label : labels) { + assertNoLabelInRule(rule, label); + } + } +} + +void AppInstallHelperExt::checkHybridAppSmackRulesAterUninstall() const +{ + const std::vector rules(parseSmackRulesFile(SMACK_RULES_PATH)); + const std::string appLabel = generateProcessLabel(m_appName, m_pkgName, true); + + for (const auto &rule : rules) { + assertNoLabelInRule(rule, appLabel); + } +} + +void AppInstallHelperExt::checkAppIdExistence(bool expected) const +{ + lib_retcode ret = expected ? SECURITY_MANAGER_SUCCESS : SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT; + std::string retPkgId = Api::getPkgId(m_appName, ret); + + if (expected) { + RUNNER_ASSERT_MSG(m_pkgName == retPkgId, + "The given appId does not belong to the given pkgId."); + } +} + +} // namespace SecurityManagerTest diff --git a/src/security-manager-tests/common/app_install_helper_ext.h b/src/security-manager-tests/common/app_install_helper_ext.h new file mode 100644 index 0000000..fd50ae7 --- /dev/null +++ b/src/security-manager-tests/common/app_install_helper_ext.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020 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 + +#include + +#include +#include +#include + +namespace SecurityManagerTest { + +class AppInstallHelperExt : public AppInstallHelper { +public: + using AppInstallHelper::AppInstallHelper; + + void checkPrivileges(const PrivilegeVector &allowedPrivs, + const PrivilegeVector &deniedPrivs) const; + void checkDeniedPrivileges(const PrivilegeVector &deniedPrivs) const; + void checkGroupPrivileges(const PrivilegeVector &allowedPrivs) const; + void checkSmackPrivileges(const PrivilegeVector &allowedPrivs, + const PrivilegeVector &deniedPrivs = {}) const; + void checkAfterInstall() const; + void checkAfterUninstall(bool removePkg = true) const; + + void checkSmackAccesses(std::vector rules, bool hasAccess = true) const; + +private: + void checkPkgSmackRulesAfterUninstall() const; + void checkHybridAppSmackRulesAterUninstall() const; + void checkAppIdExistence(bool expected) const; +}; + +} // namespace SecurityManagerTest diff --git a/src/security-manager-tests/common/policy_configuration.cpp b/src/security-manager-tests/common/policy_configuration.cpp index 1259b36..db34767 100644 --- a/src/security-manager-tests/common/policy_configuration.cpp +++ b/src/security-manager-tests/common/policy_configuration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -29,10 +30,62 @@ #define CONF_DIR "/usr/share/security-manager/policy/" #define CONF_GROUP_FILE "privilege-group.list" +#define CONF_SYSTEMD_PRIVS_FILE "privilege-managed-by-systemd-for-daemons.list" #define CONF_USER_TEMPLATE_FILE "usertype-%s.profile" namespace SecurityManagerTest { +namespace { + +PolicyConfiguration::SmackPrivRulesMap parsePrivilegeSmackList() { + constexpr char PRIVILEGE[] = "~PRIVILEGE~"; + PolicyConfiguration::SmackPrivRulesMap privilegeRules; + + std::ifstream templateFile(CONF_DIR "privilege-smack.list"); + + if (templateFile.fail()) + return privilegeRules; + + try { + std::string line; + while (getline(templateFile, line)) { + if (line.empty() || line[0] == '#') + continue; + + std::string privilege, label, rulesFileName; + std::istringstream stream(line); + stream >> privilege >> label >> rulesFileName; + + if (rulesFileName == "default") + rulesFileName = "priv-rules-default-template.smack"; + + std::ifstream rulesFile(std::string(CONF_DIR) + "privilege-mapping/" + rulesFileName); + std::string object, subject, access; + while (rulesFile >> subject >> object >> access) { + if (object.empty() || subject.empty()) + throw std::runtime_error("Malformed rule"); + + // ignore + if (object.front() != '~' || subject.front() != '~') + continue; + + if (object == PRIVILEGE) + object = label; + if (subject == PRIVILEGE) + subject = label; + privilegeRules[privilege].emplace_back(std::move(subject), + std::move(object), + std::move(access)); + } + } + } catch (const std::exception&) { + privilegeRules.clear(); + } + return privilegeRules; +} + +} // namespace anonymous + gid_t nameToGid(const char *name) { struct group entry, *gresult; char buffer[1024]; @@ -139,15 +192,20 @@ PolicyConfiguration::PrivVector PolicyConfiguration::loadPrivFile(const std::str return result; } -PolicyConfiguration::GroupVector PolicyConfiguration::privToGroup(const PolicyConfiguration::PrivVector &privVector) { - GroupVector result; - if (m_privGroupMap.empty()) - loadPrivGroupMap(); - for (auto &e : privVector) { - auto it = m_privGroupMap.find(e); - if (it == m_privGroupMap.end()) - continue; - result.push_back(it->second); +PolicyConfiguration::PrivVector PolicyConfiguration::getSystemdManagedPrivs() +{ + PolicyConfiguration::PrivVector result; + std::ifstream file(CONF_DIR CONF_SYSTEMD_PRIVS_FILE); + if (!file.is_open()) { + RUNNER_ASSERT_MSG(file.is_open(), + "Unable to read config file " << CONF_DIR CONF_SYSTEMD_PRIVS_FILE); + } + std::string line; + std::regex r("^(http(.*))"); + while (std::getline(file, line)) { + std::smatch m; + if (std::regex_search(line, m, r)) + result.emplace_back(m[1]); } return result; } @@ -168,5 +226,17 @@ void PolicyConfiguration::loadPrivGroupMap(void) { } } +std::string PolicyConfiguration::getPkgRulesFilePath() { + return CONF_DIR "pkg-rules-template.smack"; +} +std::string PolicyConfiguration::getAppRulesFilePath() { + return CONF_DIR "app-rules-template.smack"; +} + +const PolicyConfiguration::SmackPrivRulesMap& PolicyConfiguration::getSmackPrivRulesMap() { + const static auto smackPrivRulesMap = parsePrivilegeSmackList(); + return smackPrivRulesMap; +} + } // namespace SecurityManagerTest diff --git a/src/security-manager-tests/common/policy_configuration.h b/src/security-manager-tests/common/policy_configuration.h index d7bc1c1..cd89dc9 100644 --- a/src/security-manager-tests/common/policy_configuration.h +++ b/src/security-manager-tests/common/policy_configuration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -19,9 +19,12 @@ #include #include #include +#include #include +#include + namespace SecurityManagerTest { gid_t nameToGid(const char *name); @@ -32,6 +35,7 @@ public: typedef std::vector GroupVector; typedef std::vector PrivVector; typedef std::map PrivGroupMap; + typedef std::unordered_map> SmackPrivRulesMap; struct UserDescription { PrivVector privVector; @@ -50,12 +54,18 @@ public: UserDescription& getUserDescription(UserType userType); gid_t groupToGid(const std::string &gname); PrivGroupMap getPrivGroupMap(); - GroupVector privToGroup(const PrivVector &privVector); + PrivVector getSystemdManagedPrivs(); + + template + GroupVector privToGroup(const T &privVector); + GidVector groupToGid(const GroupVector &groupVector); -static bool getIsAskuserEnabled(); + static bool getIsAskuserEnabled(); + static std::string getPkgRulesFilePath(); + static std::string getAppRulesFilePath(); + static const SmackPrivRulesMap& getSmackPrivRulesMap(); private: - GidVector groupToGid(const GroupVector &groupVector); UserDescription loadUserDescription(UserType userType); PrivVector loadPrivFile(const std::string &path); void loadPrivGroupMap(void); @@ -65,6 +75,21 @@ private: std::map m_userDescriptionMap; }; +template +PolicyConfiguration::GroupVector PolicyConfiguration::privToGroup(const T &privVector) { + GroupVector result; + if (m_privGroupMap.empty()) + loadPrivGroupMap(); + for (auto &e : privVector) { + auto it = m_privGroupMap.find(e); + if (it == m_privGroupMap.end()) + continue; + result.push_back(it->second); + } + return result; +} + + } // namespace SecurityManagerTest #endif diff --git a/src/security-manager-tests/common/privilege_names.h b/src/security-manager-tests/common/privilege_names.h new file mode 100644 index 0000000..2c6e418 --- /dev/null +++ b/src/security-manager-tests/common/privilege_names.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 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 + +namespace PrivilegeNames { + +constexpr char PRIV_INTERNAL_AUDIO[] = "http://tizen.org/privilege/internal/device/audio"; +constexpr char PRIV_INTERNAL_DISPLAY[] = "http://tizen.org/privilege/internal/device/display"; +constexpr char PRIV_INTERNAL_USERMANAGEMENT[] = "http://tizen.org/privilege/internal/usermanagement"; +constexpr char PRIV_INTERNAL_VIDEO[] = "http://tizen.org/privilege/internal/device/video"; + +constexpr char PRIV_ACCOUNT_READ[] = "http://tizen.org/privilege/account.read"; +constexpr char PRIV_BLUETOOTH[] = "http://tizen.org/privilege/bluetooth"; +constexpr char PRIV_CALENDAR_READ[] = "http://tizen.org/privilege/calendar.read"; +constexpr char PRIV_CALENDAR_WRITE[] = "http://tizen.org/privilege/calendar.write"; +constexpr char PRIV_CALLHISTORY_READ[] = "http://tizen.org/privilege/callhistory.read"; +constexpr char PRIV_CAMERA[] = "http://tizen.org/privilege/camera"; +constexpr char PRIV_CONTACTS_READ[] = "http://tizen.org/privilege/contacts.read"; +constexpr char PRIV_CONTENT_WRITE[] = "http://tizen.org/privilege/content.write"; +constexpr char PRIV_DATASHARING[] = "http://tizen.org/privilege/datasharing"; +constexpr char PRIV_DISPLAY[] = "http://tizen.org/privilege/display"; +constexpr char PRIV_EMAIL[] = "http://tizen.org/privilege/email"; +constexpr char PRIV_EXTERNALSTORAGE[] = "http://tizen.org/privilege/externalstorage"; +constexpr char PRIV_HEALTHINFO[] = "http://tizen.org/privilege/healthinfo"; +constexpr char PRIV_INTERNET[] = "http://tizen.org/privilege/internet"; +constexpr char PRIV_LED[] = "http://tizen.org/privilege/led"; +constexpr char PRIV_LOCATION[] = "http://tizen.org/privilege/location"; +constexpr char PRIV_MEDIASTORAGE[] = "http://tizen.org/privilege/mediastorage"; +constexpr char PRIV_NFC[] = "http://tizen.org/privilege/nfc"; +constexpr char PRIV_NOTEXIST[] = "http://tizen.org/privilege/notexist"; +constexpr char PRIV_NOTIFICATION[] = "http://tizen.org/privilege/notification"; +constexpr char PRIV_POWER[] = "http://tizen.org/privilege/power"; +constexpr char PRIV_PUSH[] = "http://tizen.org/privilege/push"; +constexpr char PRIV_SYSTEMMONITOR[] = "http://tizen.org/privilege/systemmonitor"; +constexpr char PRIV_TELEPHONY[] = "http://tizen.org/privilege/telephony"; +constexpr char PRIV_VOLUME_SET[] = "http://tizen.org/privilege/volume.set"; +constexpr char PRIV_VPNSERVICE[] = "http://tizen.org/privilege/vpnservice"; +constexpr char PRIV_WIFIDIRECT[] = "http://tizen.org/privilege/wifidirect"; + +} diff --git a/src/security-manager-tests/common/scoped_app_launcher.cpp b/src/security-manager-tests/common/scoped_app_launcher.cpp new file mode 100644 index 0000000..6861bab --- /dev/null +++ b/src/security-manager-tests/common/scoped_app_launcher.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020 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 +#include +#include +#include +#include + +using namespace SecurityManagerTest; + +ScopedAppLauncher::ScopedAppLauncher(const AppInstallHelper& app, + const std::function& runInAppContext) : + m_uid(app.getUID()), + m_appId(app.getAppId()) +{ + m_pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(m_pid >= 0, "Fork failed"); + if (m_pid != 0) { + m_syncPipe.claimParentEp(); + m_syncPipe.wait(); + } else { + m_syncPipe.claimChildEp(); + + try { + RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(app.getUID(), app.getGID()) == 0, + "launcher failed"); + Api::prepareAppCandidate(); + Api::prepareApp(app.getAppId()); + runInAppContext(); + } catch (...) { + m_syncPipe.post(); + throw; + } + m_syncPipe.post(); + m_syncPipe.wait(); + exit(0); + } +} + +ScopedAppLauncher::~ScopedAppLauncher() +{ + SafeCleanup::run([this]{ + m_syncPipe.post(); + waitPid(m_pid); + Api::cleanupApp(m_appId, m_uid, m_pid); + }); +} diff --git a/src/security-manager-tests/common/scoped_app_launcher.h b/src/security-manager-tests/common/scoped_app_launcher.h new file mode 100644 index 0000000..133e7c8 --- /dev/null +++ b/src/security-manager-tests/common/scoped_app_launcher.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 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 + +#include +#include + +class ScopedAppLauncher final { +public: + explicit ScopedAppLauncher(const AppInstallHelper& app, + const std::function& runInAppContext = []{}); + ~ScopedAppLauncher(); + + ScopedAppLauncher(const ScopedAppLauncher&) = delete; + ScopedAppLauncher& operator=(const ScopedAppLauncher&) = delete; + +private: + SynchronizationPipe m_syncPipe; + pid_t m_pid; + const uid_t m_uid; + const std::string m_appId; +}; diff --git a/src/security-manager-tests/common/sm_commons.cpp b/src/security-manager-tests/common/sm_commons.cpp index 16db76c..ce822cd 100644 --- a/src/security-manager-tests/common/sm_commons.cpp +++ b/src/security-manager-tests/common/sm_commons.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 - 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016 - 2020 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. @@ -14,50 +14,37 @@ * limitations under the License. */ -#include #include #include #include -#include #include #include #include #include #include -#include -#include #include -#include -#include #include #include +#include #include #include -#include #include #include -#include #include #include #include #include -#include -#include + #include -#include #include "tzplatform.h" -#include #include #include using namespace SecurityManagerTest; -#define CONF_DIR "/usr/share/security-manager/policy/" -#define SMACK_RULES_PATH "/sys/fs/smackfs/load2" - #define ALLOW 0 #define DENY -1 @@ -161,190 +148,6 @@ int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/, return 0; } -void check_app_permissions(const std::string &app_id, const std::string &pkg_id, - const std::string &user, const privileges_t &allowed_privs, - const privileges_t &denied_privs, bool isHybrid) -{ - (void) pkg_id; - std::string smackLabel = generateProcessLabel(app_id, pkg_id, isHybrid); - - CynaraTestClient::Client ctc; - - for (auto &priv : allowed_privs) { - ctc.check(smackLabel.c_str(), "", user, priv.c_str(), CYNARA_API_ACCESS_ALLOWED); - } - - for (auto &priv : denied_privs) { - ctc.check(smackLabel.c_str(), "", user, priv.c_str(), CYNARA_API_ACCESS_DENIED); - } -} - -void sm_app_has_privileges(const AppInstallHelper &app, - const std::vector &privileges, - int expectedResult) -{ - for (auto const &privilege : privileges) { - int result; - Api::appHasPrivilege(app.getAppId(), privilege, app.getUID(), result); - RUNNER_ASSERT_MSG(result == expectedResult, "Application " << app.getAppId() - << " has unexpected access to " << privilege << ", is : " - << " should be : " << expectedResult ); - } -} - -static void check_app_smack_accesses(const std::string &appId, const std::string &pkgId, - bool isHybrid = false) -{ - static const std::vector rules[] = - {parseSmackRulesFile(CONF_DIR "pkg-rules-template.smack"), - parseSmackRulesFile(CONF_DIR "app-rules-template.smack")}; - - const std::pair switchAliases[] = - {std::make_pair("~PATH_RW~", generatePathRWLabel(pkgId)), - std::make_pair("~PATH_RO~", generatePathROLabel(pkgId)), - std::make_pair("~PATH_SHARED_RO~", getSharedROPathLabel()), - std::make_pair("~PROCESS~", generateProcessLabel(appId, pkgId, isHybrid))}; - - for (auto rule : rules[isHybrid]) { - if (rule.object == "~PATH_TRUSTED~") { - continue; - } - - for (const auto &alias : switchAliases) { - if (rule.subject == alias.first) { - rule.subject = alias.second; - } - if (rule.object == alias.first) { - rule.object = alias.second; - } - } - - if (rule.object == "_") { - rule.access = "rx" + rule.access; - } - - check_exact_smack_accesses(rule.subject, rule.object, rule.access); - } -} - -static void assert_no_label_in_rule(const AccessRequest &rule, const std::string &label) -{ - RUNNER_ASSERT_MSG(rule.object != label && rule.subject != label, - "Smack rule left after uninstallation process." << - " Subject: " << rule.subject << - " object: " << rule.object << - " access: " << rule.access); -} - -static void check_pkg_smack_rules_after_uninstall(const std::string &appId, const std::string &pkgId) -{ - const std::vector rules(std::move(parseSmackRulesFile(SMACK_RULES_PATH))); - const std::string labels[] = {generatePathRWLabel(pkgId), - generatePathROLabel(pkgId), - generateProcessLabel(appId, pkgId, true), - generateProcessLabel(appId, pkgId)}; - for (const auto &rule : rules) { - for (const auto &label : labels) { - assert_no_label_in_rule(rule, label); - } - } -} - -static void check_hybrid_app_smack_rules_after_uninstall(const std::string &appId, const std::string &pkgId) -{ - const std::vector rules(std::move(parseSmackRulesFile(SMACK_RULES_PATH))); - const std::string appLabel = generateProcessLabel(appId, pkgId, true); - for (const auto &rule : rules) { - assert_no_label_in_rule(rule, appLabel); - } -} - -static void check_app(const std::string &appId, const std::string &pkgId, - bool shouldBeInstalled, bool isHybrid, bool removePkg) -{ - char *retPkgId; - int ret = security_manager_get_app_pkgid(&retPkgId, appId.c_str()); - - if (shouldBeInstalled) { - RUNNER_ASSERT_MSG(ret == SECURITY_MANAGER_SUCCESS, "The given appId is not installed."); - - if (ret == SECURITY_MANAGER_SUCCESS) { - CStringPtr retPkgIdPtr(retPkgId); - RUNNER_ASSERT_MSG(strcmp(pkgId.c_str(), retPkgId) == 0, - "The given appId does not belong to the given pkgId."); - } - check_app_smack_accesses(appId, pkgId, isHybrid); - } else { - RUNNER_ASSERT_MSG(ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT, "The given appId is installed."); - - if (removePkg) { - check_pkg_smack_rules_after_uninstall(appId, pkgId); - } else if (isHybrid) { - check_hybrid_app_smack_rules_after_uninstall(appId, pkgId); - } - } -} - -void check_app_after_install(const std::string &app_id, const std::string &pkg_id, bool isHybrid) -{ - check_app(app_id, pkg_id, true, isHybrid, false); -} - -static void check_app_gids(const std::string &app_id, const std::vector &allowed_gids) -{ - int ret; - gid_t main_gid = getgid(); - std::unordered_set reference_gids(allowed_gids.begin(), allowed_gids.end()); - - // Reset supplementary groups - ret = setgroups(0, NULL); - RUNNER_ASSERT_MSG(ret != -1, "Unable to set supplementary groups"); - - Api::setProcessGroups(app_id); - - ret = getgroups(0, nullptr); - RUNNER_ASSERT_MSG(ret != -1, "Unable to get supplementary groups"); - - std::vector actual_gids(ret); - ret = getgroups(ret, actual_gids.data()); - RUNNER_ASSERT_MSG(ret != -1, "Unable to get supplementary groups"); - - for (const auto &gid : actual_gids) { - RUNNER_ASSERT_MSG(gid == main_gid || reference_gids.count(gid) > 0, - "Application shouldn't get access to group " << gid); - reference_gids.erase(gid); - } - - RUNNER_ASSERT_MSG(reference_gids.empty(), "Application didn't get access to some groups"); -} - -static const char *const ANY_USER_REPRESENTATION = "anyuser";/*this may be actually any string*/ - -void check_app_after_install(const std::string &app_id, const std::string &pkg_id, - const privileges_t &allowed_privs, - const privileges_t &denied_privs, - bool isHybrid) -{ - check_app(app_id, pkg_id, true, isHybrid, false); - /* Privileges should be granted to all users if root installs app */ - check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, allowed_privs, denied_privs, isHybrid); - - PolicyConfiguration policy; - const PolicyConfiguration::GroupVector allowed_groups = policy.privToGroup(allowed_privs); - RUNNER_ASSERT_MSG(allowed_groups.size() == allowed_privs.size(), - "Some privileges given were not found in the policy"); - - std::vector allowed_gids; - for (const auto &groupName : allowed_groups) { - errno = 0; - struct group* grp = getgrnam(groupName.c_str()); - RUNNER_ASSERT_ERRNO_MSG(grp, "Group: " << groupName << " not found"); - allowed_gids.push_back(grp->gr_gid); - } - - check_app_gids(app_id, allowed_gids); -} - void check_path(const std::string &path, const std::string &label, bool transmute, bool execute) { nftw_expected_label = label; nftw_expected_transmute = transmute; @@ -355,59 +158,6 @@ void check_path(const std::string &path, const std::string &label, bool transmut RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << path); } -void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, - bool isHybrid, bool removePkg) -{ - check_app(app_id, pkg_id, false, isHybrid, removePkg); -} - -void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, - const privileges_t &privileges, bool isHybrid, - bool removePkg) -{ - check_app(app_id, pkg_id, false, isHybrid, removePkg); - - /* Privileges should not be granted anymore to any user */ - check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, {}, privileges, isHybrid); -} - -std::string access_opposite(std::string &access) { - static const std::map access_mapping = {{'r', 0}, {'w', 1}, {'x', 2}, {'a', 3}, - {'t', 4}, {'l', 5}}; - // May write implies may lock - if (access.find('w') != std::string::npos && access.find('l') == std::string::npos) { - access.append("l"); - } - std::string access_opposite = "rwxatl"; - for (char c : access) { - access_opposite[access_mapping.at(c)] = '-'; - } - auto it = std::remove_if(access_opposite.begin(), access_opposite.end(), [](char c) {return c == '-';}); - access_opposite.erase(it, access_opposite.end()); - return access_opposite; -} - -void check_exact_smack_accesses(const std::string &subject, const std::string &object, - const std::string &access) { - std::string access_str(access); - auto no_access = access_opposite(access_str); - for (char c : access_str) { - int ret = smack_have_access(subject.c_str(), object.c_str(), std::string(1, c).c_str()); - RUNNER_ASSERT_MSG(ret >= 0, "smack_have_access failed: <" << subject << ">, <" << object - << ">, <" << c << "> errno=" << strerror(errno)); - RUNNER_ASSERT_MSG(ret == 1, "Access " << c << " from " << subject << " to " - << object << " not given"); - } - - for (char c : no_access) { - int ret = smack_have_access(subject.c_str(), object.c_str(), std::string(1, c).c_str()); - RUNNER_ASSERT_MSG(ret >= 0, "smack_have_access failed: <" << subject << ">, <" << object - << ">, <" << c << "> errno=" << strerror(errno)); - RUNNER_ASSERT_MSG(ret == 0, "Access " << c << " from " << subject << " to " - << object << " unnecessarily given"); - } -} - CapsSetsUniquePtr setCaps(const char *cap_string) { CapsSetsUniquePtr caps(cap_init()); diff --git a/src/security-manager-tests/common/sm_commons.h b/src/security-manager-tests/common/sm_commons.h index 6840281..427657d 100644 --- a/src/security-manager-tests/common/sm_commons.h +++ b/src/security-manager-tests/common/sm_commons.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -22,46 +22,19 @@ #include #include #include -#include - -#include #include #include #include -#include DEFINE_SMARTPTR(cap_free, _cap_struct, CapsSetsUniquePtr); const int FTW_MAX_FDS = 16; -typedef std::vector privileges_t; - int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/, int /*typeflag*/, struct FTW* /*ftwbuf*/); -void check_app_permissions(const std::string &app_id, const std::string &pkg_id, - const std::string &user, const privileges_t &allowed_privs, - const privileges_t &denied_privs, bool isHybrid = false); -void sm_app_has_privileges(const AppInstallHelper &app, - const std::vector &privileges, - int result); -void check_app_after_install(const std::string &app_id, const std::string &pkg_id, - bool isHybrid = false); -void check_app_after_install(const std::string &app_id, const std::string &pkg_id, - const privileges_t &allowed_privs, - const privileges_t &denied_privs, - bool isHybrid = false); void check_path(const std::string &path, const std::string &label, bool transmute = true, bool execute = false); -void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, - bool isHybrid = false, bool removePkg = false); -void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, - const privileges_t &privileges, bool isHybrid = false, - bool removePkg = false); -std::string access_opposite(std::string &access); -void check_exact_smack_accesses(const std::string &subject, - const std::string &object, - const std::string &access); CapsSetsUniquePtr setCaps(const char *cap_string); diff --git a/src/security-manager-tests/common/template_parser.h b/src/security-manager-tests/common/template_parser.h index 81a3674..a1bad46 100644 --- a/src/security-manager-tests/common/template_parser.h +++ b/src/security-manager-tests/common/template_parser.h @@ -18,6 +18,8 @@ * @author Alicja Kluczek * @brief Parsing function for smack rules templates */ +#pragma once + #include #include diff --git a/src/security-manager-tests/smack-privileges/backup/.dummy b/src/security-manager-tests/smack-privileges/backup/.dummy new file mode 100644 index 0000000..e69de29 diff --git a/src/security-manager-tests/smack-privileges/empty/privilege-mapping/.dummy b/src/security-manager-tests/smack-privileges/empty/privilege-mapping/.dummy new file mode 100644 index 0000000..e69de29 diff --git a/src/security-manager-tests/smack-privileges/internet-only/privilege-mapping/priv-rules-default-template.smack b/src/security-manager-tests/smack-privileges/internet-only/privilege-mapping/priv-rules-default-template.smack new file mode 100644 index 0000000..09c5be6 --- /dev/null +++ b/src/security-manager-tests/smack-privileges/internet-only/privilege-mapping/priv-rules-default-template.smack @@ -0,0 +1,2 @@ +~PROCESS~ ~PRIVILEGE~ w +~PRIVILEGE~ ~PROCESS~ w diff --git a/src/security-manager-tests/smack-privileges/internet-only/privilege-smack.list b/src/security-manager-tests/smack-privileges/internet-only/privilege-smack.list new file mode 100644 index 0000000..933b073 --- /dev/null +++ b/src/security-manager-tests/smack-privileges/internet-only/privilege-smack.list @@ -0,0 +1 @@ +http://tizen.org/privilege/internet System::Privilege::Internet default \ No newline at end of file diff --git a/src/security-manager-tests/smack-privileges/malformed/privilege-mapping/priv-rules-default-template.smack b/src/security-manager-tests/smack-privileges/malformed/privilege-mapping/priv-rules-default-template.smack new file mode 100644 index 0000000..09c5be6 --- /dev/null +++ b/src/security-manager-tests/smack-privileges/malformed/privilege-mapping/priv-rules-default-template.smack @@ -0,0 +1,2 @@ +~PROCESS~ ~PRIVILEGE~ w +~PRIVILEGE~ ~PROCESS~ w diff --git a/src/security-manager-tests/smack-privileges/malformed/privilege-smack.list b/src/security-manager-tests/smack-privileges/malformed/privilege-smack.list new file mode 100644 index 0000000..04ab381 --- /dev/null +++ b/src/security-manager-tests/smack-privileges/malformed/privilege-smack.list @@ -0,0 +1,3 @@ +http://tizen.org/privilege/internet System::Privilege::Internet default +http://tizen.org/privilege/camera System::Privilege::Camera the-fault +http://tizen.org/privilege/camera System::Privilege::Camera diff --git a/src/security-manager-tests/smack-privileges/multiple-privs/privilege-mapping/flawed-camera-template.smack b/src/security-manager-tests/smack-privileges/multiple-privs/privilege-mapping/flawed-camera-template.smack new file mode 100644 index 0000000..fb35c52 --- /dev/null +++ b/src/security-manager-tests/smack-privileges/multiple-privs/privilege-mapping/flawed-camera-template.smack @@ -0,0 +1,3 @@ +~PROCESS~ System::TEF r +~PROCESS~ ~PRIVILEGE~ w +~PRIVILEGE~ ~PROCESS~ w diff --git a/src/security-manager-tests/smack-privileges/multiple-privs/privilege-mapping/priv-rules-default-template.smack b/src/security-manager-tests/smack-privileges/multiple-privs/privilege-mapping/priv-rules-default-template.smack new file mode 100644 index 0000000..09c5be6 --- /dev/null +++ b/src/security-manager-tests/smack-privileges/multiple-privs/privilege-mapping/priv-rules-default-template.smack @@ -0,0 +1,2 @@ +~PROCESS~ ~PRIVILEGE~ w +~PRIVILEGE~ ~PROCESS~ w diff --git a/src/security-manager-tests/smack-privileges/multiple-privs/privilege-smack.list b/src/security-manager-tests/smack-privileges/multiple-privs/privilege-smack.list new file mode 100644 index 0000000..8a0bc4f --- /dev/null +++ b/src/security-manager-tests/smack-privileges/multiple-privs/privilege-smack.list @@ -0,0 +1,2 @@ +http://tizen.org/privilege/internet System::Privilege::Internet default +http://tizen.org/privilege/camera System::Privilege::Camera flawed-camera-template.smack diff --git a/src/security-manager-tests/test_cases.cpp b/src/security-manager-tests/test_cases.cpp index 8b7a7fc..93d6cea 100644 --- a/src/security-manager-tests/test_cases.cpp +++ b/src/security-manager-tests/test_cases.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 - 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -28,7 +28,6 @@ #include -#include #include #include #include @@ -45,38 +44,33 @@ #include #include #include +#include +#include +#include +#include using namespace SecurityManagerTest; - -namespace { -std::vector merge(const std::vector &one, const std::vector &two) { - std::vector sum; - sum.reserve(one.size() + two.size()); - sum.insert(sum.end(), one.begin(), one.end()); - sum.insert(sum.end(), two.begin(), two.end()); - return sum; -} -} +using namespace PrivilegeNames; RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER) RUNNER_TEST(security_manager_01a_app_double_install_double_uninstall) { - AppInstallHelper app("sm_test_01a_app"); + AppInstallHelperExt app("sm_test_01a_app"); { ScopedInstaller appInstall(app); - check_app_after_install(app.getAppId(), app.getPkgId()); + app.checkAfterInstall(); { ScopedInstaller appInstall2(app); - check_app_after_install(app.getAppId(), app.getPkgId()); + app.checkAfterInstall(); } - check_app_after_uninstall(app.getAppId(), app.getPkgId()); + app.checkAfterUninstall(); } } RUNNER_TEST(security_manager_01b_app_double_install_wrong_pkg_id) { - AppInstallHelper app("sm_test_01b"); + AppInstallHelperExt app("sm_test_01b"); { ScopedInstaller appInstall(app); @@ -86,17 +80,17 @@ RUNNER_TEST(security_manager_01b_app_double_install_wrong_pkg_id) Api::install(requestInst2, SECURITY_MANAGER_ERROR_INPUT_PARAM); - check_app_after_install(app.getAppId(), app.getPkgId()); + app.checkAfterInstall(); } - check_app_after_uninstall(app.getAppId(), app.getPkgId()); + app.checkAfterUninstall(); } RUNNER_TEST(security_manager_01c_app_uninstall_wrong_pkg_id) { - AppInstallHelper app("sm_test_01c"); + AppInstallHelperExt app("sm_test_01c"); ScopedInstaller appInstall(app); - check_app_after_install(app.getAppId(), app.getPkgId()); + app.checkAfterInstall(); InstallRequest requestUninst; requestUninst.setAppId(app.getAppId()); @@ -142,26 +136,20 @@ RUNNER_TEST(security_manager_01d_app_install_complicated_dir_tree) check_path(sharedRODir, getSharedROPathLabel()); } -RUNNER_TEST(security_manager_02_app_install_uninstall_full) +RUNNER_CHILD_TEST(security_manager_02_app_install_uninstall_full) { - privileges_t defaultPrivs = { - "http://tizen.org/privilege/internal/device/audio", - "http://tizen.org/privilege/internal/device/display", - "http://tizen.org/privilege/internal/device/video" - }; - privileges_t allowedPrivs = { - "http://tizen.org/privilege/camera", - "http://tizen.org/privilege/mediastorage" - }; - privileges_t someDeniedPrivs = { - "http://tizen.org/privilege/internet", - "http://tizen.org/privilege/externalstorage" + const PrivilegeVector defaultPrivs = { + PRIV_INTERNAL_AUDIO, + PRIV_INTERNAL_DISPLAY, + PRIV_INTERNAL_VIDEO, }; + const PrivilegeVector allowedPrivs = {PRIV_CAMERA, PRIV_MEDIASTORAGE}; + const PrivilegeVector someDeniedPrivs = {PRIV_INTERNET, PRIV_EXTERNALSTORAGE}; - privileges_t defaultAllowedPrivs = defaultPrivs; + PrivilegeVector defaultAllowedPrivs = defaultPrivs; defaultAllowedPrivs.insert(defaultAllowedPrivs.end(), allowedPrivs.begin(), allowedPrivs.end()); - AppInstallHelper app("sm_test_02"); + AppInstallHelperExt app("sm_test_02"); app.createPrivateDir(); app.createPrivateRODir(); app.createPublicDir(); @@ -170,8 +158,11 @@ RUNNER_TEST(security_manager_02_app_install_uninstall_full) { ScopedInstaller appInstall(app); - check_app_after_install(app.getAppId(), app.getPkgId(), - defaultAllowedPrivs, someDeniedPrivs); + app.checkAfterInstall(); + app.checkDeniedPrivileges(someDeniedPrivs); + { + ScopedAppLauncher launcher(app, [&]{ app.checkGroupPrivileges(defaultAllowedPrivs); }); + } check_path(app.getPrivateDir(), generatePathRWLabel(app.getPkgId())); check_path(app.getPrivateRODir(), generatePathROLabel(app.getPkgId()), false); @@ -179,7 +170,39 @@ RUNNER_TEST(security_manager_02_app_install_uninstall_full) check_path(app.getSharedRODir(), getSharedROPathLabel()); } - check_app_after_uninstall(app.getAppId(), app.getPkgId(), app.getPrivilegesNames()); + app.checkAfterUninstall(); +} + +RUNNER_CHILD_TEST(security_manager_02a_set_process_groups) +{ + const PrivilegeVector defaultPrivs = { + PRIV_INTERNAL_AUDIO, + PRIV_INTERNAL_DISPLAY, + PRIV_INTERNAL_VIDEO, + }; + const PrivilegeVector allowedPrivs = {PRIV_CAMERA, PRIV_MEDIASTORAGE}; + + auto defaultAllowedPrivs = defaultPrivs; + defaultAllowedPrivs.insert(defaultAllowedPrivs.end(), allowedPrivs.begin(), allowedPrivs.end()); + + AppInstallHelperExt app("sm_test_02a"); + app.addPrivileges(allowedPrivs); + { + ScopedInstaller appInstall(app); + + app.checkAfterInstall(); + + pid_t pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed"); + if (pid != 0) { + waitPid(pid); + } else { + Api::setProcessGroups(app.getAppId()); + app.checkGroupPrivileges(defaultAllowedPrivs); + exit(0); + } + } + app.checkAfterUninstall(); } RUNNER_CHILD_TEST_SMACK(security_manager_03_set_label_from_appid) @@ -242,58 +265,46 @@ RUNNER_CHILD_TEST_SMACK(security_manager_03_set_label_from_appid) RUNNER_CHILD_TEST(security_manager_04a_app_install_uninstall_by_app_user_for_self) { - const std::vector allowedPrivs = { - "http://tizen.org/privilege/bluetooth", - "http://tizen.org/privilege/power" - }; - const std::vector someDeniedPrivs = { - "http://tizen.org/privilege/display", - "http://tizen.org/privilege/nfc" - }; + const PrivilegeVector allowedPrivs = {PRIV_BLUETOOTH, PRIV_POWER}; + const PrivilegeVector someDeniedPrivs = {PRIV_DISPLAY, PRIV_NFC}; TemporaryTestUser testUser("sm_test_04a_user_name", GUM_USERTYPE_NORMAL); testUser.create(); - AppInstallHelper app("sm_test_04a", testUser.getUid()); + AppInstallHelperExt app("sm_test_04a", testUser.getUid()); app.addPrivileges(allowedPrivs); RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(testUser.getUid(), testUser.getGid()) == 0, "drop_root_privileges failed"); { ScopedInstaller appInstall(app, false); - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), - allowedPrivs, someDeniedPrivs); + app.checkAfterInstall(); + app.checkDeniedPrivileges(someDeniedPrivs); } - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), - {}, merge(allowedPrivs, someDeniedPrivs)); + app.checkAfterUninstall(); + app.checkDeniedPrivileges(someDeniedPrivs); } RUNNER_CHILD_TEST(security_manager_04b_app_install_by_root_for_app_user) { - const std::vector allowedPrivs = { - "http://tizen.org/privilege/internet", - "http://tizen.org/privilege/led" - }; - const std::vector someDeniedPrivs = { - "http://tizen.org/privilege/location", - "http://tizen.org/privilege/notification" - }; + const PrivilegeVector allowedPrivs = {PRIV_INTERNET, PRIV_LED}; + const PrivilegeVector someDeniedPrivs = {PRIV_LOCATION, PRIV_NOTIFICATION}; TemporaryTestUser testUser("sm_test_04b_user_name", GUM_USERTYPE_NORMAL); testUser.create(); - AppInstallHelper app("sm_test_04b", testUser.getUid()); + AppInstallHelperExt app("sm_test_04b", testUser.getUid()); app.addPrivileges(allowedPrivs); { ScopedInstaller appInstall(app); - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), - allowedPrivs, someDeniedPrivs); + app.checkAfterInstall(); + app.checkDeniedPrivileges(someDeniedPrivs); RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(testUser.getUid(), testUser.getGid()) == 0, "drop_root_privileges failed"); } - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), - {}, merge(allowedPrivs, someDeniedPrivs)); + app.checkAfterUninstall(); + app.checkDeniedPrivileges(someDeniedPrivs); } RUNNER_CHILD_TEST(security_manager_05_drop_process_capabilities) @@ -327,21 +338,15 @@ RUNNER_TEST(security_manager_06_install_app_offline) // TODO - check if app is uninstalled properly } -RUNNER_TEST(security_manager_07a_user_add_app_install) +RUNNER_CHILD_TEST(security_manager_07a_user_add_app_install) { - const std::vector allowedPrivs = { - "http://tizen.org/privilege/internet", - "http://tizen.org/privilege/led" - }; - const std::vector someDeniedPrivs = { - "http://tizen.org/privilege/location", - "http://tizen.org/privilege/notification" - }; + const PrivilegeVector allowedPrivs = {PRIV_INTERNET, PRIV_LED}; + const PrivilegeVector someDeniedPrivs = {PRIV_LOCATION, PRIV_NOTIFICATION}; TemporaryTestUser testUser("sm_test_07a_user_name", GUM_USERTYPE_NORMAL); testUser.create(); - AppInstallHelper app("sm_test_07a", testUser.getUid()); + AppInstallHelperExt app("sm_test_07a", testUser.getUid()); app.addPrivileges(allowedPrivs); InstallRequest req; @@ -352,16 +357,13 @@ RUNNER_TEST(security_manager_07a_user_add_app_install) req.addPrivilege(priv); } Api::install(req); - - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), - allowedPrivs, someDeniedPrivs); + app.checkAfterInstall(); + app.checkDeniedPrivileges(someDeniedPrivs); testUser.remove(); - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), - {}, merge(allowedPrivs, someDeniedPrivs)); - - // TODO - check if app is uninstalled + app.checkAfterUninstall(); + app.checkDeniedPrivileges(someDeniedPrivs); } RUNNER_TEST(security_manager_07b_user_add_offline) @@ -374,22 +376,20 @@ RUNNER_TEST(security_manager_07b_user_add_offline) TemporaryTestUser testUser("sm_test_07b_user_name", GUM_USERTYPE_NORMAL, true); testUser.create(); - AppInstallHelper app("sm_test_07b", testUser.getUid()); + AppInstallHelperExt app("sm_test_07b", testUser.getUid()); ScopedInstaller appInstall(app); serviceManager.startService(); - check_app_after_install(app.getAppId(), app.getPkgId()); + app.checkAfterInstall(); testUser.remove(); - check_app_after_uninstall(app.getAppId(), app.getPkgId()); + app.checkAfterUninstall(); } RUNNER_TEST(security_manager_08_user_double_add_double_remove) { - std::vector somePrivs = { - "http://tizen.org/privilege/internet", "http://tizen.org/privilege/led", - "http://tizen.org/privilege/location", "http://tizen.org/privilege/notification" - }; + const PrivilegeVector somePrivs = {PRIV_LED, PRIV_NOTIFICATION}; + // gumd TemporaryTestUser testUser("sm_test_08_user_name", GUM_USERTYPE_NORMAL); testUser.create(); @@ -400,17 +400,16 @@ RUNNER_TEST(security_manager_08_user_double_add_double_remove) addUserRequest.setUserType(SM_USER_TYPE_NORMAL); Api::addUser(addUserRequest); - AppInstallHelper app("sm_test_08", testUser.getUid()); + AppInstallHelperExt app("sm_test_08", testUser.getUid()); ScopedInstaller appInstall(app); - check_app_after_install(app.getAppId(), app.getPkgId()); - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), {}, somePrivs); + app.checkAfterInstall(); + app.checkDeniedPrivileges(somePrivs); // gumd testUser.remove(); - check_app_after_uninstall(app.getAppId(), app.getPkgId()); - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), {}, somePrivs); + app.checkAfterUninstall(); // security-manager UserRequest deleteUserRequest; @@ -420,168 +419,207 @@ RUNNER_TEST(security_manager_08_user_double_add_double_remove) RUNNER_TEST(security_manager_09_app_install_constraint_check) { - auto install = [](const TemporaryTestUser& user, - const char *pkgId, - const char *appId, - const char *version, - const char *author, - bool isHybrid, - enum lib_retcode expected, - bool uninstall = true) + auto install = [](const AppInstallHelperExt& app, bool success) { - InstallRequest request; - request.setAppId(appId); - request.setPkgId(pkgId); - request.setAppTizenVersion(version); - request.setAuthorId(author); - request.setUid(user.getUid()); - if (isHybrid) - request.setHybrid(); - Api::install(request, expected); - - if(expected == SECURITY_MANAGER_SUCCESS && uninstall) { - Api::uninstall(request); - } + auto expected = success ? SECURITY_MANAGER_SUCCESS : SECURITY_MANAGER_ERROR_INPUT_PARAM; + ScopedInstaller appInstall(app, true, expected); + if (success) + app.checkAfterInstall(); + return appInstall; }; - auto update = [](const TemporaryTestUser& user, - const char *pkgId, - const char *appId, - const char *version, - const char *author, - bool isHybrid, - enum lib_retcode expected, - bool uninstall = true) + auto update = [](const AppInstallHelperExt& app) { InstallRequest request; - request.setAppId(appId); - request.setPkgId(pkgId); - request.setAppTizenVersion(version); - request.setAuthorId(author); - request.setUid(user.getUid()); - if (isHybrid) + request.setAppId(app.getAppId()); + request.setPkgId(app.getPkgId()); + request.setAppTizenVersion(app.getVersion()); + request.setAuthorId(app.getAuthor()); + request.setUid(app.getUID()); + if (app.getIsHybrid()) request.setHybrid(); - Api::update(request, expected); - - if(expected == SECURITY_MANAGER_SUCCESS && uninstall) { - Api::uninstall(request); - } + Api::update(request); }; - std::array users{ - TemporaryTestUser{"sm_test_09_user_name_0", GUM_USERTYPE_NORMAL, false}, - TemporaryTestUser{"sm_test_09_user_name_1", GUM_USERTYPE_NORMAL, false} + TemporaryTestUser users[] = { + {"sm_test_09_user_name_0", GUM_USERTYPE_NORMAL, false}, + {"sm_test_09_user_name_1", GUM_USERTYPE_NORMAL, false} }; - for(auto& gu : users) + for (auto& gu : users) gu.create(); - const char *const pkgId[] = {"sm_test_09_pkg_id_0", "sm_test_09_pkg_id_1"}; - const char *const appId[] = {"sm_test_09_app_id_0", "sm_test_09_app_id_1"}; - const char *const version[] = {"sm_test_09_version_0", "sm_test_09_version_1"}; - const char *const author[] = {"sm_test_09_author_0", "sm_test_09_author_1"}; + const char *const pkgIdPrefix[] = {"sm_test_09_0", "sm_test_09_1"}; + const char *const appIdPrefix[] = {"sm_test_09_0", "sm_test_09_1"}; + const char *const version[] = {"sm_test_09_0_version", "sm_test_09_1_version"}; + const char *const author[] = {"sm_test_09_0_author", "sm_test_09_1_author"}; bool hybrid[] = {false, true}; - // uid_0, pkg_0, app_0, version_0, author_0, not hybrid - install(users[0], pkgId[0], appId[0], version[0], author[0], hybrid[0], SECURITY_MANAGER_SUCCESS, false); + std::list apps; + + auto make_helper = [&](size_t userIdx, + size_t pkgIdx, + size_t appIdx, + size_t verIdx, + size_t authorIdx, + size_t hybridIdx) -> AppInstallHelperExt& + { + apps.emplace_back(appIdPrefix[appIdx], pkgIdPrefix[pkgIdx], users[userIdx].getUid()); + apps.back().setAuthor(author[authorIdx]); + apps.back().setVersion(version[verIdx]); + if (hybrid[hybridIdx]) + apps.back().setHybrid(); + return apps.back(); + }; + + // uid_0, pkg_0, app_0, version_0, author_0, not hybrid -> ok + auto &app000000 = make_helper(0, 0, 0, 0, 0, 0); + auto i1 = install(app000000, true); + // uid_1, pkg_0, app_0, version_0, author_0, not hybrid -> ok (different uid) - install(users[1], pkgId[0], appId[0], version[0], author[0], hybrid[0], SECURITY_MANAGER_SUCCESS); - // uid_0, pkg_0, app_0, version_0, author_0, hybrid -> ok for update (different hybrid setting) - install(users[0], pkgId[0], appId[0], version[0], author[0], hybrid[1], SECURITY_MANAGER_ERROR_INPUT_PARAM); - update(users[0], pkgId[0], appId[0], version[0], author[0], hybrid[1], SECURITY_MANAGER_SUCCESS, false); + auto& app100000 = make_helper(1, 0, 0, 0, 0, 0); + install(app100000, true); + + // uid_0, pkg_0, app_0, version_0, author_0, hybrid -> conflicts with existing non hybrid app + auto& app000001 = make_helper(0, 0, 0, 0, 0, 1); + install(app000001, false); + + // uid_0, pkg_0, app_0, version_0, author_0, hybrid -> ok (app updated to hybrid) + update(app000001); + + // uid_0, pkg_0, app_0, version_0, author_0, hybrid -> ok (app installed again) + auto i2 = install(app000001, true); + + // uid_0, pkg_0, app_0, version_0, author_0, not hybrid -> conflicts with existing hybrid app + install(app000000, false); + // uid_0, pkg_0, app_1, version_0, author_0, hybrid -> ok (new app id) - install(users[0], pkgId[0], appId[1], version[0], author[0], hybrid[1], SECURITY_MANAGER_SUCCESS, false); - // uid_1, pkg_0, app_0, version_0, author_0, hybrid -> ok (different hybrid setting) - install(users[1], pkgId[0], appId[0], version[0], author[0], hybrid[1], SECURITY_MANAGER_SUCCESS, false); - // uid_1, pkg_0, app_0, version_0, author_1, not hybrid -> fail (author of app_0 must be the same) - install(users[1], pkgId[0], appId[0], version[0], author[1], hybrid[0], SECURITY_MANAGER_ERROR_INPUT_PARAM); - // uid_1, pkg_0, app_0, version_1, author_0, not hybrid -> ok (version upgrade and different hybrid setting) - install(users[1], pkgId[0], appId[0], version[1], author[0], hybrid[0], SECURITY_MANAGER_ERROR_INPUT_PARAM); - update(users[1], pkgId[0], appId[0], version[1], author[0], hybrid[0], SECURITY_MANAGER_SUCCESS); - // uid_1, pkg_1, app_0, version_0, author_0, not hybrid -> fail (pkg of app_0 must be the same) - install(users[1], pkgId[1], appId[0], version[0], author[0], hybrid[0], SECURITY_MANAGER_ERROR_INPUT_PARAM); - // uid_0, pkg_0, app_0, version_0, author_0, not hybrid -> ok (the same app again) - install(users[0], pkgId[0], appId[0], version[0], author[0], hybrid[0], SECURITY_MANAGER_SUCCESS, false); - // uid_0, pkg_1, app_0, version_0, author_0, not hybrid -> fail (app_name + uid must be unique) - install(users[0], pkgId[1], appId[0], version[0], author[0], hybrid[0], SECURITY_MANAGER_ERROR_INPUT_PARAM); - // uid_0, pkg_0, app_0, version_0, author_1, not hybrid -> fail (app_name + uid must be unique) - install(users[0], pkgId[0], appId[0], version[0], author[1], hybrid[0], SECURITY_MANAGER_ERROR_INPUT_PARAM); + auto& app001001 = make_helper(0, 0, 1, 0, 0, 1); + auto i3 = install(app001001, true); + + // uid_1, pkg_0, app_0, version_0, author_0, hybrid -> ok (hybrid, different uid) + auto& app100001 = make_helper(1, 0, 0, 0, 0, 1); + auto i4 = install(app100001, true); + + // uid_1, pkg_0, app_0, version_0, author_1, not hybrid -> author of app_0 must be the same + auto& app100010 = make_helper(1, 0, 0, 0, 1, 0); + install(app100010, false); + + // uid_1, pkg_0, app_0, version_1, author_0, not hybrid -> ok (app version and hybridity changed) + auto& app100100 = make_helper(1, 0, 0, 1, 0, 0); + update(app100100); + + // uid_1, pkg_1, app_0, version_1, author_0, not hybrid -> pkg of app_0 must be the same + auto& app110100 = make_helper(1, 1, 0, 1, 0, 0); + install(app110100, false); + + for (auto& gu : users) + gu.remove(); + + RUNNER_IGNORED_MSG("Disabled until hybridity update works properly for all users"); + for (auto& app : apps) + app.checkAfterUninstall(); } RUNNER_TEST(security_manager_09a_install_many_apps_in_single_request) { - const std::string pkgId = "sm_test_09a_pkg_id_0"; - const std::vector appIds = {"sm_test_09a_app_id_0", "sm_test_09a_app_id_1", "sm_test_09a_app_id_2"}; + constexpr char pkgIdPrefix[] = "sm_test_09a"; + const AppInstallHelperExt apps[] = {{"sm_test_09a_0", pkgIdPrefix}, + {"sm_test_09a_1", pkgIdPrefix}, + {"sm_test_09a_2", pkgIdPrefix}}; + static_assert(sizeof(apps) > 0); + + std::vector appIds; + for (auto &app : apps) + appIds.push_back(app.getAppId()); { - ScopedInstaller appsInstall(appIds, pkgId); + ScopedInstaller appsInstall(appIds, apps[0].getPkgId()); // Installing many applications in single request - for (const auto &appId : appIds) { - check_app_after_install(appId, pkgId); + for (auto &app : apps) { + app.checkAfterInstall(); } } - for (const auto &appId : appIds) { - check_app_after_uninstall(appId, pkgId); + for (auto &app : apps) { + app.checkAfterUninstall(); } } RUNNER_TEST(security_manager_09b_install_many_apps_in_single_request_duplicated_ids) { - const std::string pkgId = "sm_test_09b_pkg_id_0"; - const std::string appId = "sm_test_09b_app_id_0"; - + AppInstallHelperExt app("sm_test_09b"); { - ScopedInstaller appsInstall({appId, appId}, pkgId); - check_app_after_install(appId, pkgId); + ScopedInstaller appsInstall({app.getAppId(), app.getAppId()}, app.getPkgId()); + app.checkAfterInstall(); } - check_app_after_uninstall(appId, pkgId); + app.checkAfterUninstall(); } RUNNER_TEST(security_manager_09c_update_many_apps_in_single_request_hybrid_package) { - const std::vector appIds = {"sm_test_09c_app_id_0", "sm_test_09c_app_id_1", "sm_test_09c_app_id_2"}; - const std::string pkgId = "sm_test_09c_pkg_id_0"; + constexpr char pkgIdPrefix[] = "sm_test_09c"; + AppInstallHelperExt apps[] = {{"sm_test_09c_0", pkgIdPrefix}, + {"sm_test_09c_1", pkgIdPrefix}, + {"sm_test_09c_2", pkgIdPrefix}}; + static_assert(sizeof(apps) > 0); + + std::vector appIds; + for (const auto &app : apps) + appIds.push_back(app.getAppId()); { - ScopedInstaller appsInstall(appIds, pkgId); + ScopedInstaller appsInstall(appIds, apps[0].getPkgId()); // Package is not hybrid, every app has same policy. - for (const auto &appId : appIds) { - check_app_after_install(appId, pkgId); + for (const auto &app : apps) { + app.checkAfterInstall(); } // Updating package -- changing set of apps in package and setting hybrid mode InstallRequest updateRequest; - updateRequest.setPkgId(pkgId); + updateRequest.setPkgId(apps[0].getPkgId()); updateRequest.setAppId(appIds[0]); updateRequest.nextApp(); updateRequest.setAppId(appIds[1]); updateRequest.setHybrid(); Api::update(updateRequest); + // Package became hybrid, so every app has its own Smack label - check_app_after_install(appIds[0], pkgId, true); - check_app_after_install(appIds[1], pkgId, true); + for (auto &app : apps) { + app.setHybrid(); + } + apps[0].checkAfterInstall(); + apps[1].checkAfterInstall(); + // Package became hybrid properly, // so app not included in updated version of package was uninstalled. - check_app_after_uninstall(appIds[2], pkgId); + apps[2].checkAfterUninstall(false); } - for (const auto &appId : appIds) { - check_app_after_uninstall(appId, pkgId, true, true); + for (const auto &app : apps) { + app.checkAfterUninstall(); } } RUNNER_TEST(security_manager_09d_uninstall_app_from_hybrid_package) { - const std::vector appIds = {"sm_test_09d_app_id_0", "sm_test_09d_app_id_1", "sm_test_09d_app_id_2"}; - const std::string pkgId = "sm_test_09d_pkg_id_0"; + constexpr char pkgIdPrefix[] = "sm_test_09d"; + AppInstallHelperExt apps[] = {{"sm_test_09d_0", pkgIdPrefix}, + {"sm_test_09d_1", pkgIdPrefix}, + {"sm_test_09d_2", pkgIdPrefix}}; + static_assert(sizeof(apps) > 0); + + std::vector appIds; + for (const auto &app : apps) + appIds.push_back(app.getAppId()); + { - ScopedInstaller appsInstall(appIds, pkgId); + ScopedInstaller appsInstall(appIds, apps[0].getPkgId()); InstallRequest updateRequest; - updateRequest.setPkgId(pkgId); + updateRequest.setPkgId(apps[0].getPkgId()); for (unsigned int i = 0; i < appIds.size(); i++) { if (i > 0) { updateRequest.nextApp(); @@ -592,31 +630,32 @@ RUNNER_TEST(security_manager_09d_uninstall_app_from_hybrid_package) Api::update(updateRequest); InstallRequest uninstRequest; - uninstRequest.setPkgId(pkgId); + uninstRequest.setPkgId(apps[0].getPkgId()); uninstRequest.setAppId(appIds[0]); Api::uninstall(uninstRequest); - check_app_after_uninstall(appIds[0], pkgId, true); + for (auto &app : apps) { + app.setHybrid(); + } + apps[0].checkAfterUninstall(false); + } + for (const auto &app : apps) { + app.checkAfterUninstall(); } } RUNNER_CHILD_TEST(security_manager_10_app_has_privilege) { - const std::vector allowedPrivs = { - "http://tizen.org/privilege/wifidirect", - "http://tizen.org/privilege/telephony" - }; - const std::vector someDeniedPrivs = { - "http://tizen.org/privilege/vpnservice", - "http://tizen.org/privilege/notification" - }; - AppInstallHelper app("sm_test_10"); + const PrivilegeVector allowedPrivs = {PRIV_WIFIDIRECT, PRIV_TELEPHONY}; + const PrivilegeVector someDeniedPrivs = {PRIV_VPNSERVICE, PRIV_NOTIFICATION}; + + AppInstallHelperExt app("sm_test_10"); app.addPrivileges(allowedPrivs); ScopedInstaller appInstall(app); - sm_app_has_privileges(app, allowedPrivs, 1); + app.checkAfterInstall(); + app.checkDeniedPrivileges(someDeniedPrivs); // FIXME - all other existing privileges should be checked - sm_app_has_privileges(app, someDeniedPrivs, 0); } RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_POLICY) @@ -651,40 +690,31 @@ RUNNER_TEST(security_manager_20_user_cynara_policy) RUNNER_CHILD_TEST(security_manager_21_security_manager_admin_deny_user_priv) { - const privileges_t adminRequiredPrivs = { - "http://tizen.org/privilege/notexist", - "http://tizen.org/privilege/internal/usermanagement" - }; - const privileges_t manifestPrivs = { - "http://tizen.org/privilege/internet", - "http://tizen.org/privilege/datasharing" - }; - const privileges_t allowedPrivsAfterChange = {"http://tizen.org/privilege/datasharing"}; - const privileges_t deniedPrivsAfterChange = {"http://tizen.org/privilege/internet"}; + const PrivilegeVector adminRequiredPrivs = {PRIV_NOTEXIST, PRIV_INTERNAL_USERMANAGEMENT}; + const PrivilegeVector manifestPrivs = {PRIV_INTERNET, PRIV_DATASHARING}; + const PrivilegeVector allowedPrivsAfterChange = {PRIV_DATASHARING}; + const PrivilegeVector deniedPrivsAfterChange = {PRIV_INTERNET}; + TemporaryTestUser adminUser("sm_test_21_admin_user_name", GUM_USERTYPE_ADMIN, false); TemporaryTestUser normalUser("sm_test_21_normal_user_name", GUM_USERTYPE_NORMAL, false); adminUser.create(); normalUser.create(); - std::string childUidStr = normalUser.getUidString(); AppInstallHelper adminApp("sm_test_21_admin", adminUser.getUid()); adminApp.addPrivileges(adminRequiredPrivs); ScopedInstaller adminAppInstall(adminApp); - AppInstallHelper normalApp("sm_test_21_normal", normalUser.getUid()); + AppInstallHelperExt normalApp("sm_test_21_normal", normalUser.getUid()); normalApp.addPrivileges(manifestPrivs); ScopedInstaller normalAppInstall(normalApp); - - check_app_permissions(normalApp.getAppId(), normalApp.getPkgId(), childUidStr, - manifestPrivs, {}); + normalApp.checkAfterInstall(); pid_t pid = fork(); RUNNER_ASSERT_MSG(pid >= 0, "fork failed"); if (pid != 0) { //parent process waitPid(pid); - check_app_permissions(normalApp.getAppId(), normalApp.getPkgId(), childUidStr, - allowedPrivsAfterChange, deniedPrivsAfterChange); + normalApp.checkPrivileges(allowedPrivsAfterChange, deniedPrivsAfterChange); } else { Api::setProcessLabel(adminApp.getAppId()); RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(adminUser.getUid(),adminUser.getGid()) == 0, @@ -693,7 +723,7 @@ RUNNER_CHILD_TEST(security_manager_21_security_manager_admin_deny_user_priv) PolicyRequest addPolicyReq; for (auto &deniedPriv : deniedPrivsAfterChange) { PolicyEntry entry(SECURITY_MANAGER_ANY, normalUser.getUidString(), deniedPriv); - entry.setMaxLevel("Deny"); + entry.setMaxLevel(PolicyEntry::LEVEL_DENY); addPolicyReq.addEntry(entry); } Api::sendPolicy(addPolicyReq); @@ -721,8 +751,8 @@ RUNNER_TEST(security_manager_22_security_manager_cmd_install) const std::string appopt = " --app=" + app_id; const std::string uidopt = " --uid=" + user.getUidString(); - mktreeSafe(path1.c_str(), 0); - mktreeSafe(path2.c_str(), 0); + mktreeSafe(path1, 0); + mktreeSafe(path2, 0); const std::string installcmd = "security-manager-cmd --install " + appopt + pkgopt + uidopt; @@ -819,16 +849,16 @@ RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_INSTALL_TYPE) RUNNER_TEST(security_manager_25a_global_user_set_install_type_global) { - AppInstallHelper app("sm_test_25a"); + AppInstallHelperExt app("sm_test_25a"); app.setInstallType(SM_APP_INSTALL_GLOBAL); { ScopedInstaller appInstall(app); - check_app_after_install(app.getAppId(), app.getPkgId()); + app.checkAfterInstall(); } // Check records in the security-manager database - check_app_after_uninstall(app.getAppId(), app.getPkgId()); + app.checkAfterUninstall(); } RUNNER_TEST(security_manager_25b_global_user_set_install_type_local) @@ -845,13 +875,13 @@ RUNNER_TEST(security_manager_25b_global_user_set_install_type_local) RUNNER_TEST(security_manager_25c_global_user_set_install_type_preloaded) { - AppInstallHelper app("sm_test_25c"); + AppInstallHelperExt app("sm_test_25c"); app.setInstallType(SM_APP_INSTALL_PRELOADED); { ScopedInstaller appInstall(app); - check_app_after_install(app.getAppId(), app.getPkgId()); + app.checkAfterInstall(); } - check_app_after_uninstall(app.getAppId(), app.getPkgId()); + app.checkAfterUninstall(); } RUNNER_TEST(security_manager_25d_local_user_set_install_type_invalid) @@ -907,21 +937,13 @@ RUNNER_CHILD_TEST(security_manager_25f_unprivileged_install_type_preloaded) RUNNER_CHILD_TEST(security_manager_25g_local_user_set_install_type_local) { - std::vector allowedPrivs = { - "http://tizen.org/privilege/volume.set", - "http://tizen.org/privilege/systemmonitor", - "http://tizen.org/privilege/internet" - }; - std::vector someDeniedPrivs = { - "http://tizen.org/privilege/push", - "http://tizen.org/privilege/power", - "http://tizen.org/privilege/notification" - }; + const PrivilegeVector allowedPrivs = {PRIV_VOLUME_SET, PRIV_SYSTEMMONITOR, PRIV_INTERNET}; + const PrivilegeVector someDeniedPrivs = {PRIV_PUSH, PRIV_POWER, PRIV_NOTIFICATION}; TemporaryTestUser testUser("sm_test_25g_user_name", GUM_USERTYPE_NORMAL); testUser.create(); - AppInstallHelper app("sm_test_25g", testUser.getUid()); + AppInstallHelperExt app("sm_test_25g", testUser.getUid()); app.createPrivateDir(); app.setInstallType(SM_APP_INSTALL_LOCAL); app.addPrivileges(allowedPrivs); @@ -930,13 +952,10 @@ RUNNER_CHILD_TEST(security_manager_25g_local_user_set_install_type_local) "drop_root_privileges failed"); { ScopedInstaller appInstall(app); - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), - allowedPrivs, someDeniedPrivs); - + app.checkAfterInstall(); + app.checkDeniedPrivileges(someDeniedPrivs); } - check_app_permissions(app.getAppId(), app.getPkgId(), testUser.getUidString(), - {}, merge(allowedPrivs, someDeniedPrivs)); - // TODO - check if app is properly uninstalled + app.checkAfterUninstall(); } RUNNER_CHILD_TEST(security_manager_25h_local_path_global_install) @@ -998,30 +1017,23 @@ RUNNER_CHILD_TEST(security_manager_26_hybrid_pkg_uninstall_artifacts_check) TemporaryTestUser testUser("sm_test_26_user_name", GUM_USERTYPE_NORMAL); testUser.create(); - const std::vector allowedPrivs = { - "http://tizen.org/privilege/wifidirect", - "http://tizen.org/privilege/telephony" - }; + const PrivilegeVector allowedPrivs = {PRIV_WIFIDIRECT, PRIV_TELEPHONY}; - AppInstallHelper app1("sm_test_26_1", "sm_test_26", testUser.getUid()); + AppInstallHelperExt app1("sm_test_26_1", "sm_test_26", testUser.getUid()); app1.addPrivileges(allowedPrivs); app1.setHybrid(); - AppInstallHelper app2("sm_test_26_2", "sm_test_26", testUser.getUid()); + AppInstallHelperExt app2("sm_test_26_2", "sm_test_26", testUser.getUid()); app2.addPrivileges(allowedPrivs); app2.setHybrid(); { ScopedInstaller appInstall1(app1); ScopedInstaller appInstall2(app2); - check_app_permissions(app1.getAppId(), app1.getPkgId(), testUser.getUidString(), - allowedPrivs, {}, app1.getIsHybrid()); - check_app_permissions(app2.getAppId(), app2.getPkgId(), testUser.getUidString(), - allowedPrivs, {}, app2.getIsHybrid()); + app1.checkAfterInstall(); + app2.checkAfterInstall(); } - check_app_permissions(app1.getAppId(), app1.getPkgId(), testUser.getUidString(), - {}, allowedPrivs, app1.getIsHybrid()); - check_app_permissions(app2.getAppId(), app2.getPkgId(), testUser.getUidString(), - {}, allowedPrivs, app2.getIsHybrid()); + app1.checkAfterUninstall(false); + app2.checkAfterUninstall(); } diff --git a/src/security-manager-tests/test_cases_app_defined_privilege.cpp b/src/security-manager-tests/test_cases_app_defined_privilege.cpp index a72a7d6..2e8965c 100644 --- a/src/security-manager-tests/test_cases_app_defined_privilege.cpp +++ b/src/security-manager-tests/test_cases_app_defined_privilege.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2017 - 2020 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. @@ -29,10 +29,12 @@ #include #include #include +#include RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_APP_DEFINED_PRIVILEGE) using namespace SecurityManagerTest; +using namespace PrivilegeNames; RUNNER_CHILD_TEST(app_defined_01_global_install_untrusted) { @@ -544,7 +546,7 @@ RUNNER_CHILD_TEST(app_defined_09_add_get_client_license) RUNNER_CHILD_TEST(app_defined_10_check_system_privileges) { const std::string providerAppId = "app_def_09_provider"; - const Privilege privilege("http://tizen.org/privilege/internet", Privilege::UNTRUSTED); + const Privilege privilege(PRIV_INTERNET, Privilege::UNTRUSTED); InstallRequest requestInst; requestInst.setAppId(providerAppId); @@ -608,4 +610,4 @@ RUNNER_CHILD_TEST(app_defined_12_invalid_common_name) CynaraTestClient::Client cynara; cynara.check(clientLabel, session, ownerId, clientPrivilegeLicense, CYNARA_API_ACCESS_DENIED); -} \ No newline at end of file +} diff --git a/src/security-manager-tests/test_cases_app_policy.cpp b/src/security-manager-tests/test_cases_app_policy.cpp index bb3ab94..27267f8 100644 --- a/src/security-manager-tests/test_cases_app_policy.cpp +++ b/src/security-manager-tests/test_cases_app_policy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -27,11 +27,14 @@ #include #include +#include + +using namespace PrivilegeNames; const PrivilegeVector TEST_PRIVACY_PRIVILEGES = { - Privilege("http://tizen.org/privilege/callhistory.read", Privilege::PRIVACY), - Privilege("http://tizen.org/privilege/account.read", Privilege::PRIVACY), - Privilege("http://tizen.org/privilege/healthinfo", Privilege::PRIVACY) }; + Privilege(PRIV_CALLHISTORY_READ, Privilege::PRIVACY), + Privilege(PRIV_ACCOUNT_READ, Privilege::PRIVACY), + Privilege(PRIV_HEALTHINFO, Privilege::PRIVACY) }; using namespace SecurityManagerTest; diff --git a/src/security-manager-tests/test_cases_nss.cpp b/src/security-manager-tests/test_cases_nss.cpp index 90099e2..152f4b5 100644 --- a/src/security-manager-tests/test_cases_nss.cpp +++ b/src/security-manager-tests/test_cases_nss.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -28,48 +28,20 @@ #include #include #include +#include #include using namespace SecurityManagerTest; +using namespace PrivilegeNames; RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_NSS_PLUGIN) -RUNNER_CHILD_TEST(nss_01_unknown_user) { +RUNNER_CHILD_TEST(nss_01_normal_user_without_inter_daemon_groups) { const std::string newUserName = "nss_01_user"; - PolicyConfiguration pc; - TemporaryTestUser testUser(newUserName, GUM_USERTYPE_NORMAL, false); - testUser.create(); - - auto gidVector = pc.getGid(); - - RUNNER_ASSERT_MSG(0 == initgroups(newUserName.c_str(), 0), "Init groups failed"); - - gid_t list[64]; - int grsize = getgroups(64, list); - size_t counter = 0; - - for (size_t i=0; i(testUser.getUid())), - "http://tizen.org/privilege/camera"); - entry.setMaxLevel("Deny"); - policyRequest.addEntry(entry); - Api::sendPolicy(policyRequest); - RUNNER_ASSERT_MSG(0 == initgroups(newUserName.c_str(), 0), "Init groups failed"); - gid_t list[64]; - int grsize = getgroups(64, list); - size_t counter = 0; - - for (int i=0; i #include #include +#include using namespace SecurityManagerTest; +using namespace PrivilegeNames; namespace { bool finish = false; @@ -45,9 +47,6 @@ const size_t THREADS = 10; const std::string APP_TEST_USER = "app_test_user"; -const std::string EXTERNAL_STORAGE_PRIVILEGE = "http://tizen.org/privilege/externalstorage"; -const std::string MEDIA_STORAGE_PRIVILEGE = "http://tizen.org/privilege/mediastorage"; - const std::string ACCESS_DENIED_DIR_PATH = "/usr/share/security-manager/dummy"; const std::string EXTERNAL_STORAGE_DIR_PATH = "/opt/media"; const std::string MEDIA_STORAGE_RW_DIR_PATH = "/opt/usr/media"; @@ -132,7 +131,7 @@ ino_t getFileInode(const std::string &path) std::string getTextFileContents(const std::string &path) { - std::ifstream in(path.c_str()); + std::ifstream in(path); if (in.fail()) return std::string(); std::stringstream ss; @@ -173,13 +172,13 @@ RUNNER_CHILD_TEST(security_manager_100_synchronize_credentials_test) for (size_t i = 0; i < THREADS; i++) threads[i].run(i, expectedLabel); - Api::prepareApp(app.getAppId().c_str()); + Api::prepareApp(app.getAppId()); } RUNNER_ASSERT_MSG(thread_errors.empty(), std::endl << thread_errors); exit(0); } else { waitPid(pid); - Api::cleanupApp(app.getAppId().c_str(), tmpUser.getUid(), pid); + Api::cleanupApp(app.getAppId(), tmpUser.getUid(), pid); } } @@ -226,7 +225,7 @@ RUNNER_CHILD_TEST(security_manager_101_create_namespace_test) synchPipe.claimParentEp(); RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed"); Api::prepareAppCandidate(); - Api::prepareApp(app.getAppId().c_str()); + Api::prepareApp(app.getAppId()); synchPipe.post(); synchPipe.wait(); @@ -235,7 +234,7 @@ RUNNER_CHILD_TEST(security_manager_101_create_namespace_test) synchPipe.claimChildEp(); synchPipe.wait(); - std::string appBindPath = std::string("/var/run/user/") + std::to_string(tmpUser.getUid()) + std::string appBindPath = std::string("/var/run/user/") + tmpUser.getUidString() + "/apps/" + app.generateAppLabel() + "/" + std::to_string(pid); std::string appProcPath = std::string("/proc/") + std::to_string(pid) + "/ns/mnt"; std::string launcherProcPath = std::string("/proc/") + std::to_string(getpid()) + "/ns/mnt"; @@ -253,7 +252,7 @@ RUNNER_CHILD_TEST(security_manager_101_create_namespace_test) synchPipe.post(); waitPid(pid); - Api::cleanupApp(app.getAppId().c_str(), tmpUser.getUid(), pid); + Api::cleanupApp(app.getAppId(), tmpUser.getUid(), pid); } } @@ -272,7 +271,7 @@ RUNNER_CHILD_TEST(security_manager_102_check_propagation_test) synchPipe.claimParentEp(); RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed"); Api::prepareAppCandidate(); - Api::prepareApp(app.getAppId().c_str()); + Api::prepareApp(app.getAppId()); synchPipe.post(); synchPipe.wait(); @@ -297,7 +296,7 @@ RUNNER_CHILD_TEST(security_manager_102_check_propagation_test) synchPipe.post(); waitPid(pid); - Api::cleanupApp(app.getAppId().c_str(), tmpUser.getUid(), pid); + Api::cleanupApp(app.getAppId(), tmpUser.getUid(), pid); } } @@ -307,8 +306,7 @@ RUNNER_CHILD_TEST(security_manager_103_policy_change_test) tmpUser.create(); AppInstallHelper app("app103", tmpUser.getUid()); - app.addPrivilege(EXTERNAL_STORAGE_PRIVILEGE); - app.addPrivilege(MEDIA_STORAGE_PRIVILEGE); + app.addPrivileges({PRIV_EXTERNALSTORAGE, PRIV_MEDIASTORAGE}); ScopedInstaller appInstall(app); SynchronizationPipe synchPipe; @@ -318,7 +316,7 @@ RUNNER_CHILD_TEST(security_manager_103_policy_change_test) synchPipe.claimParentEp(); RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed"); Api::prepareAppCandidate(); - Api::prepareApp(app.getAppId().c_str()); + Api::prepareApp(app.getAppId()); synchPipe.post(); synchPipe.wait(); @@ -335,12 +333,12 @@ RUNNER_CHILD_TEST(security_manager_103_policy_change_test) RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); PolicyRequest policyRequest; - PolicyEntry policyEntry(app.getAppId(), std::to_string(tmpUser.getUid()), EXTERNAL_STORAGE_PRIVILEGE); - policyEntry.setLevel("Deny"); + PolicyEntry policyEntry(app.getAppId(), tmpUser.getUidString(), PRIV_EXTERNALSTORAGE); + policyEntry.setLevel(PolicyEntry::LEVEL_DENY); policyRequest.addEntry(policyEntry); - policyEntry = PolicyEntry(app.getAppId(), std::to_string(tmpUser.getUid()), MEDIA_STORAGE_PRIVILEGE); - policyEntry.setLevel("Deny"); + policyEntry = PolicyEntry(app.getAppId(), tmpUser.getUidString(), PRIV_MEDIASTORAGE); + policyEntry.setLevel(PolicyEntry::LEVEL_DENY); policyRequest.addEntry(policyEntry); Api::sendPolicy(policyRequest); @@ -351,12 +349,12 @@ RUNNER_CHILD_TEST(security_manager_103_policy_change_test) result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RO_DIR_PATH, pid); RUNNER_ASSERT_ERRNO_MSG(result == true, "path is not bound"); - policyEntry = PolicyEntry(app.getAppId(), std::to_string(tmpUser.getUid()), EXTERNAL_STORAGE_PRIVILEGE); - policyEntry.setLevel("Allow"); + policyEntry = PolicyEntry(app.getAppId(), tmpUser.getUidString(), PRIV_EXTERNALSTORAGE); + policyEntry.setLevel(PolicyEntry::LEVEL_ALLOW); policyRequest.addEntry(policyEntry); - policyEntry = PolicyEntry(app.getAppId(), std::to_string(tmpUser.getUid()), MEDIA_STORAGE_PRIVILEGE); - policyEntry.setLevel("Allow"); + policyEntry = PolicyEntry(app.getAppId(), tmpUser.getUidString(), PRIV_MEDIASTORAGE); + policyEntry.setLevel(PolicyEntry::LEVEL_ALLOW); policyRequest.addEntry(policyEntry); Api::sendPolicy(policyRequest); @@ -369,7 +367,46 @@ RUNNER_CHILD_TEST(security_manager_103_policy_change_test) synchPipe.post(); waitPid(pid); - Api::cleanupApp(app.getAppId().c_str(), tmpUser.getUid(), pid); + Api::cleanupApp(app.getAppId(), tmpUser.getUid(), pid); + } +} + +RUNNER_CHILD_TEST(security_manager_104_policy_change_kill_app_test) +{ + TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false); + tmpUser.create(); + + AppInstallHelper app("app104", tmpUser.getUid()); + app.addPrivileges({PRIV_EXTERNALSTORAGE, PRIV_MEDIASTORAGE}); + ScopedInstaller appInstall(app); + + SynchronizationPipe synchPipe; + pid_t pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed"); + if (pid == 0) { + synchPipe.claimParentEp(); + try { + RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed"); + Api::prepareAppCandidate(); + Api::prepareApp(app.getAppId()); + } catch (...) { + synchPipe.post(); + throw; + } + synchPipe.post(); + exit(0); + } else { + synchPipe.claimChildEp(); + synchPipe.wait(); + + PolicyRequest policyRequest; + PolicyEntry policyEntry(app.getAppId(), tmpUser.getUidString(), PRIV_EXTERNALSTORAGE); + policyEntry.setLevel(PolicyEntry::LEVEL_DENY); + policyRequest.addEntry(policyEntry); + Api::sendPolicy(policyRequest); + + waitPid(pid); + Api::cleanupApp(app.getAppId(), tmpUser.getUid(), pid); } } @@ -469,10 +506,7 @@ RUNNER_TEST(security_manager_200_prepare_app_perf) for (int i = 0; i < nAppsMax; i++) { apps.emplace_back(App{AppInstallHelper("app200_" + std::to_string(i), uid), 0}); auto &hlp = apps.back().hlp; - for (const auto &p : { EXTERNAL_STORAGE_PRIVILEGE, MEDIA_STORAGE_PRIVILEGE, - std::string("http://tizen.org/privilege/camera"), - std::string("http://tizen.org/privilege/internet") }) - hlp.addPrivilege(p); + hlp.addPrivileges({PRIV_EXTERNALSTORAGE, PRIV_MEDIASTORAGE, PRIV_CAMERA, PRIV_INTERNET}); hlp.createSharedRODir(); appInstalls.emplace_back(ScopedInstaller(hlp)); } diff --git a/src/security-manager-tests/test_cases_privacy_manager.cpp b/src/security-manager-tests/test_cases_privacy_manager.cpp index c354041..ac72b73 100644 --- a/src/security-manager-tests/test_cases_privacy_manager.cpp +++ b/src/security-manager-tests/test_cases_privacy_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -38,8 +38,11 @@ #include #include #include +#include +#include using namespace SecurityManagerTest; +using namespace PrivilegeNames; namespace { struct UserInfo { std::string userName; @@ -47,50 +50,29 @@ struct UserInfo { }; // Privileges required for having permission to self/admin get/set policies. -const std::string SELF_PRIVILEGE = "http://tizen.org/privilege/notexist"; -const std::string ADMIN_PRIVILEGE = "http://tizen.org/privilege/internal/usermanagement"; - -typedef std::vector Privileges; -const std::vector TEST_PRIVILEGES = { - { - "http://tizen.org/privilege/internet", - "http://tizen.org/privilege/display" - }, - { - "http://tizen.org/privilege/telephony", - "http://tizen.org/privilege/datasharing" - }, - { - "http://tizen.org/privilege/content.write", - "http://tizen.org/privilege/led", - "http://tizen.org/privilege/email" - }, - { - "http://tizen.org/privilege/led", - "http://tizen.org/privilege/email", - "http://tizen.org/privilege/telephony", - "http://tizen.org/privilege/datasharing" - }, - { - "http://tizen.org/privilege/internet", - "http://tizen.org/privilege/display", - "http://tizen.org/privilege/led", - "http://tizen.org/privilege/email" - } +const std::string& SELF_PRIVILEGE = PRIV_NOTEXIST; +const std::string& ADMIN_PRIVILEGE = PRIV_INTERNAL_USERMANAGEMENT; + +const std::vector TEST_PRIVILEGES = { + {PRIV_INTERNET, PRIV_DISPLAY}, + {PRIV_TELEPHONY, PRIV_DATASHARING}, + {PRIV_CONTENT_WRITE, PRIV_LED, PRIV_EMAIL}, + {PRIV_LED, PRIV_EMAIL, PRIV_TELEPHONY, PRIV_DATASHARING}, + {PRIV_INTERNET, PRIV_DISPLAY, PRIV_LED, PRIV_EMAIL} }; const PrivilegeVector TEST_PRIVACY_PRIVILEGES[] = { { - Privilege("http://tizen.org/privilege/telephony"), - Privilege("http://tizen.org/privilege/led"), - Privilege("http://tizen.org/privilege/callhistory.read", Privilege::PRIVACY), - Privilege("http://tizen.org/privilege/account.read", Privilege::PRIVACY), - Privilege("http://tizen.org/privilege/healthinfo", Privilege::PRIVACY), + Privilege(PRIV_TELEPHONY), + Privilege(PRIV_LED), + Privilege(PRIV_CALLHISTORY_READ, Privilege::PRIVACY), + Privilege(PRIV_ACCOUNT_READ, Privilege::PRIVACY), + Privilege(PRIV_HEALTHINFO, Privilege::PRIVACY), }, { - Privilege("http://tizen.org/privilege/telephony"), - Privilege("http://tizen.org/privilege/led"), - Privilege("http://tizen.org/privilege/callhistory.read", Privilege::PRIVACY), + Privilege(PRIV_TELEPHONY), + Privilege(PRIV_LED), + Privilege(PRIV_CALLHISTORY_READ, Privilege::PRIVACY), } }; @@ -151,7 +133,7 @@ RUNNER_CHILD_TEST(security_manager_10_privacy_manager_fetch_whole_policy_for_sel RUNNER_ASSERT_MSG(appIt != appIdToAIH.end(), "Policy returned unexpected app: " << app); AppInstallHelper &aih = appIt->second; - auto appPrivileges = aih.getPrivilegesNames(); + auto& appPrivileges = aih.getPrivileges(); auto privIt = std::find(appPrivileges.begin(), appPrivileges.end(), privilege); RUNNER_ASSERT_MSG(privIt != appPrivileges.end(), "Unexpected privilege " << privilege << " for app " << app); @@ -232,7 +214,7 @@ RUNNER_CHILD_TEST(security_manager_11_privacy_manager_fetch_whole_policy_for_adm AppInstallHelper &aih = userAppIdToAIHIt->second; auto privs = aih.getPrivileges(); - auto appPrivileges = aih.getPrivilegesNames(); + auto& appPrivileges = aih.getPrivileges(); auto privIt = std::find(appPrivileges.begin(), appPrivileges.end(), privilege); RUNNER_ASSERT_MSG(privIt != appPrivileges.end(), "Unexpected privilege " << privilege << " for app " << app); @@ -324,7 +306,7 @@ RUNNER_CHILD_TEST(security_manager_12_privacy_manager_fetch_whole_policy_for_adm AppInstallHelper &aih = userAppIdToAIHIt->second; auto privs = aih.getPrivileges(); - auto appPrivileges = aih.getPrivilegesNames(); + auto& appPrivileges = aih.getPrivileges(); auto privIt = std::find(appPrivileges.begin(), appPrivileges.end(), privilege); RUNNER_ASSERT_MSG(privIt != appPrivileges.end(), "Unexpected privilege " << privilege << " for app " << app); @@ -389,7 +371,7 @@ RUNNER_CHILD_TEST(security_manager_13_privacy_manager_fetch_policy_after_update_ normalUser.getUidString(), app1.getPrivileges()[0] ); - policyEntry.setLevel("Deny"); + policyEntry.setLevel(PolicyEntry::LEVEL_DENY); policyRequest.addEntry(policyEntry); policyEntry = PolicyEntry( @@ -397,7 +379,7 @@ RUNNER_CHILD_TEST(security_manager_13_privacy_manager_fetch_policy_after_update_ normalUser.getUidString(), app1.getPrivileges()[1] ); - policyEntry.setLevel("Deny"); + policyEntry.setLevel(PolicyEntry::LEVEL_DENY); policyRequest.addEntry(policyEntry); Api::sendPolicy(policyRequest); @@ -464,15 +446,12 @@ RUNNER_CHILD_TEST(security_manager_14_privacy_manager_fetch_and_update_policy_fo PolicyRequest setPolicyRequest; std::vector policyEntries; - const std::string internetPriv = "http://tizen.org/privilege/internet"; - const std::string displayPriv = "http://tizen.org/privilege/display"; - - PolicyEntry internetPolicyEntry(SECURITY_MANAGER_ANY, SECURITY_MANAGER_ANY, internetPriv); - internetPolicyEntry.setMaxLevel("Deny"); + PolicyEntry internetPolicyEntry(SECURITY_MANAGER_ANY, SECURITY_MANAGER_ANY, PRIV_INTERNET); + internetPolicyEntry.setMaxLevel(PolicyEntry::LEVEL_DENY); setPolicyRequest.addEntry(internetPolicyEntry); - PolicyEntry displayPolicyEntry(SECURITY_MANAGER_ANY, SECURITY_MANAGER_ANY, displayPriv); - displayPolicyEntry.setMaxLevel("Deny"); + PolicyEntry displayPolicyEntry(SECURITY_MANAGER_ANY, SECURITY_MANAGER_ANY, PRIV_DISPLAY); + displayPolicyEntry.setMaxLevel(PolicyEntry::LEVEL_DENY); setPolicyRequest.addEntry(displayPolicyEntry); Api::sendPolicy(setPolicyRequest); @@ -501,7 +480,7 @@ RUNNER_CHILD_TEST(security_manager_14_privacy_manager_fetch_and_update_policy_fo RUNNER_CHILD_TEST(security_manager_15_privacy_manager_send_policy_update_for_admin) { - const std::string updatePriv = "http://tizen.org/privilege/led"; + const std::string& updatePriv = PRIV_LED; TemporaryTestUser adminUser("sm_test_15_username", GUM_USERTYPE_ADMIN); adminUser.create(); @@ -528,7 +507,7 @@ RUNNER_CHILD_TEST(security_manager_15_privacy_manager_send_policy_update_for_adm "drop_root_privileges failed"); PolicyEntry entry(updatedApp.getAppId(), adminUser.getUidString(), updatePriv); - entry.setMaxLevel("Allow"); + entry.setMaxLevel(PolicyEntry::LEVEL_ALLOW); PolicyRequest addPolicyRequest; addPolicyRequest.addEntry(entry); Api::sendPolicy(addPolicyRequest); @@ -538,7 +517,7 @@ RUNNER_CHILD_TEST(security_manager_15_privacy_manager_send_policy_update_for_adm RUNNER_CHILD_TEST(security_manager_15_privacy_manager_send_policy_update_for_admin_wildcard) { - const std::string updatePriv = "http://tizen.org/privilege/led"; + const std::string& updatePriv = PRIV_LED; TemporaryTestUser adminUser("sm_test_15_username", GUM_USERTYPE_ADMIN); adminUser.create(); @@ -564,7 +543,7 @@ RUNNER_CHILD_TEST(security_manager_15_privacy_manager_send_policy_update_for_adm "drop_root_privileges failed"); PolicyEntry entry(SECURITY_MANAGER_ANY, adminUser.getUidString(), updatePriv); - entry.setMaxLevel("Allow"); + entry.setMaxLevel(PolicyEntry::LEVEL_ALLOW); PolicyRequest addPolicyRequest; addPolicyRequest.addEntry(entry); @@ -575,7 +554,7 @@ RUNNER_CHILD_TEST(security_manager_15_privacy_manager_send_policy_update_for_adm RUNNER_CHILD_TEST(security_manager_15_privacy_manager_send_policy_update_for_self) { - const std::string updatePriv = "http://tizen.org/privilege/led"; + const std::string& updatePriv = PRIV_LED; TemporaryTestUser user("sm_test_15_username", GUM_USERTYPE_NORMAL); user.create(); @@ -600,7 +579,7 @@ RUNNER_CHILD_TEST(security_manager_15_privacy_manager_send_policy_update_for_sel "drop_root_privileges failed"); PolicyEntry entry(app.getAppId(), user.getUidString(), updatePriv); - entry.setLevel("Allow"); + entry.setLevel(PolicyEntry::LEVEL_ALLOW); PolicyRequest addPolicyRequest; addPolicyRequest.addEntry(entry); @@ -637,11 +616,11 @@ RUNNER_CHILD_TEST(security_manager_16_policy_levels_get) std::string allowPolicy = std::string(levels[count-1]); // first should always be Deny - RUNNER_ASSERT_MSG(denyPolicy.compare("Deny") == 0, + RUNNER_ASSERT_MSG(denyPolicy.compare(PolicyEntry::LEVEL_DENY) == 0, "Invalid first policy level. Should be Deny, instead there is: " << levels[0]); // last should always be Allow - RUNNER_ASSERT_MSG(allowPolicy.compare("Allow") == 0, + RUNNER_ASSERT_MSG(allowPolicy.compare(PolicyEntry::LEVEL_ALLOW) == 0, "Invalid last policy level. Should be Allow, instead there is: " << levels[count-1]); exit(0); } @@ -649,7 +628,7 @@ RUNNER_CHILD_TEST(security_manager_16_policy_levels_get) RUNNER_CHILD_TEST(security_manager_17a_privacy_manager_delete_policy_for_self) { - const std::string updatePriv = "http://tizen.org/privilege/led"; + const std::string& updatePriv = PRIV_LED; TemporaryTestUser user("sm_test_17a_username", GUM_USERTYPE_NORMAL); user.create(); @@ -679,7 +658,7 @@ RUNNER_CHILD_TEST(security_manager_17a_privacy_manager_delete_policy_for_self) "drop_root_privileges failed"); PolicyEntry entry(app.getAppId(), user.getUidString(), updatePriv); - entry.setLevel("Allow"); + entry.setLevel(PolicyEntry::LEVEL_ALLOW); PolicyRequest addPolicyRequest; addPolicyRequest.addEntry(entry); Api::sendPolicy(addPolicyRequest); @@ -699,7 +678,7 @@ RUNNER_CHILD_TEST(security_manager_17a_privacy_manager_delete_policy_for_self) RUNNER_CHILD_TEST(security_manager_17b_privacy_manager_delete_policy_for_self) { - const std::string updatePriv = "http://tizen.org/privilege/led"; + const std::string& updatePriv = PRIV_LED; TemporaryTestUser user("sm_test_17b_username", GUM_USERTYPE_NORMAL); user.create(); @@ -734,7 +713,7 @@ RUNNER_CHILD_TEST(security_manager_17b_privacy_manager_delete_policy_for_self) "drop_root_privileges failed"); PolicyEntry entry(app.getAppId(), user.getUidString(), updatePriv); - entry.setLevel("Allow"); + entry.setLevel(PolicyEntry::LEVEL_ALLOW); PolicyRequest addPolicyRequest; addPolicyRequest.addEntry(entry); Api::sendPolicy(addPolicyRequest); @@ -827,7 +806,6 @@ RUNNER_CHILD_TEST(security_manager_17_privacy_manager_fetch_whole_policy_for_sel RUNNER_CHILD_TEST(security_manager_18_privacy_manager_privacy_related_privileges_policy_install_remove) { - const std::string askUserDescription = "Ask user"; TemporaryTestUser user("sm_test_18_username", GUM_USERTYPE_NORMAL); user.create(); @@ -851,7 +829,7 @@ RUNNER_CHILD_TEST(security_manager_18_privacy_manager_privacy_related_privileges unsigned int privacyActNum = 0; for (auto &entry : policyEntries) if (isPrivilegePrivacy(entry.getPrivilege())) { - RUNNER_ASSERT_MSG(entry.getCurrentLevel() == askUserDescription, + RUNNER_ASSERT_MSG(entry.getCurrentLevel() == PolicyEntry::LEVEL_ASK_USER, "Invalid policy setup; policy should be \"Ask user\" but is " << entry.getCurrentLevel()); ++privacyActNum; @@ -870,7 +848,6 @@ RUNNER_CHILD_TEST(security_manager_18_privacy_manager_privacy_related_privileges } void test_privacy_related_privileges(bool isHybrid) { - const std::string askUserDescription = "Ask user"; TemporaryTestUser user("sm_test_19_username", GUM_USERTYPE_NORMAL); user.create(); @@ -911,7 +888,7 @@ void test_privacy_related_privileges(bool isHybrid) { "Invalid appId: should be either " << app1.getAppId() << " or " << app2.getAppId() << " but is " << entry.getAppId()); if (PolicyConfiguration::getIsAskuserEnabled() && isPrivilegePrivacy(entry.getPrivilege())) { - RUNNER_ASSERT_MSG(entry.getCurrentLevel() == askUserDescription, + RUNNER_ASSERT_MSG(entry.getCurrentLevel() == PolicyEntry::LEVEL_ASK_USER, "Invalid policy setup; policy should be \"Ask user\" but is " << entry.getCurrentLevel()); if (entry.getAppId() == app1.getAppId()) @@ -938,7 +915,6 @@ RUNNER_CHILD_TEST(security_manager_19b_privacy_manager_privacy_related_privilege RUNNER_CHILD_TEST(security_manager_20_privacy_manager_privacy_related_privileges_policy_admin_check) { - const std::string askUserDescription = "Ask user"; TemporaryTestUser user("sm_test_20_username", GUM_USERTYPE_NORMAL); user.create(); @@ -952,7 +928,7 @@ RUNNER_CHILD_TEST(security_manager_20_privacy_manager_privacy_related_privileges int policyType = CYNARA_ADMIN_ALLOW; int privacyPolicyType = -1; if (PolicyConfiguration::getIsAskuserEnabled()) - admin.getPolicyTypeForDescription(askUserDescription, privacyPolicyType); + admin.getPolicyTypeForDescription(PolicyEntry::LEVEL_ASK_USER, privacyPolicyType); for (auto &priv : app.getPrivileges()) { if (PolicyConfiguration::getIsAskuserEnabled() && isPrivilegePrivacy(priv)) { @@ -1001,7 +977,7 @@ RUNNER_CHILD_TEST(security_manager_23_fetch_app_manifest_invalid_user) static void check_privileges_from_manifest(const AppInstallHelper &aih, char **privileges, size_t nPrivs) { - std::vector aihPrivs = aih.getPrivilegesNames(); + auto& aihPrivs = aih.getPrivileges(); RUNNER_ASSERT_MSG(nPrivs == aihPrivs.size(), "Expected privileges number: " << aihPrivs.size() << ", got " << nPrivs); for (size_t i = 0; i < nPrivs; ++i) { RUNNER_ASSERT_MSG(std::find(aihPrivs.begin(), aihPrivs.end(), std::string(privileges[i])) != aihPrivs.end(), @@ -1016,8 +992,7 @@ RUNNER_CHILD_TEST(security_manager_24_fetch_app_manifest_global_app) AppInstallHelper app("security_manager_24_fetch"); app.setInstallType(SM_APP_INSTALL_GLOBAL); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); + app.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE}); ScopedInstaller appInstall(app); char **privileges; @@ -1043,8 +1018,7 @@ RUNNER_CHILD_TEST(security_manager_25_fetch_app_manifest_local_app) AppInstallHelper app("security_manager_25_fetch", user.getUid()); app.setInstallType(SM_APP_INSTALL_LOCAL); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); + app.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE}); ScopedInstaller appInstall(app); char **privileges; @@ -1069,15 +1043,12 @@ RUNNER_CHILD_TEST(security_manager_26_fetch_app_manifest_both_apps) AppInstallHelper appGlobal("security_manager_26_fetch"); appGlobal.setInstallType(SM_APP_INSTALL_GLOBAL); - appGlobal.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - appGlobal.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); - appGlobal.addPrivilege(std::string("http://tizen.org/privielge/contacts.read")); + appGlobal.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE, PRIV_CONTACTS_READ}); ScopedInstaller appGlobalInstall(appGlobal); AppInstallHelper appLocal("security_manager_26_fetch", user.getUid()); appLocal.setInstallType(SM_APP_INSTALL_LOCAL); - appLocal.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - appLocal.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); + appLocal.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE}); ScopedInstaller appLocalInstall(appLocal); @@ -1103,8 +1074,7 @@ RUNNER_CHILD_TEST(security_manager_27_fetch_app_manifest_app_context_local_posit AppInstallHelper app("security_manager_27_fetch", user.getUid()); app.setInstallType(SM_APP_INSTALL_LOCAL); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); + app.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE}); ScopedInstaller appInstall(app); pid_t pid = fork(); @@ -1133,8 +1103,7 @@ RUNNER_CHILD_TEST(security_manager_28_fetch_app_manifest_app_context_global_posi AppInstallHelper app("security_manager_28_fetch"); app.setInstallType(SM_APP_INSTALL_GLOBAL); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); + app.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE}); ScopedInstaller appInstall(app); pid_t pid = fork(); @@ -1166,15 +1135,12 @@ RUNNER_CHILD_TEST(security_manager_29_fetch_app_manifest_app_context_local_diffe AppInstallHelper app("security_manager_29_fetch", user.getUid()); app.setInstallType(SM_APP_INSTALL_LOCAL); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); + app.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE}); ScopedInstaller appInstall(app); AppInstallHelper app1("security_manager_29_fetch", user1.getUid()); app1.setInstallType(SM_APP_INSTALL_LOCAL); - app1.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app1.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); - app1.addPrivilege(std::string("http://tizen.org/privilege/contacts.read")); + app1.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE, PRIV_CONTACTS_READ}); ScopedInstaller appInstall1(app1); @@ -1208,15 +1174,12 @@ RUNNER_CHILD_TEST(security_manager_30_fetch_app_manifest_app_context_local_diffe AppInstallHelper app("security_manager_30_fetch", user.getUid()); app.setInstallType(SM_APP_INSTALL_LOCAL); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); + app.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE}); ScopedInstaller appInstall(app); AppInstallHelper app1("security_manager_30_fetch_1", user.getUid()); app1.setInstallType(SM_APP_INSTALL_LOCAL); - app1.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app1.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); - app1.addPrivilege(std::string("http://tizen.org/privilege/contacts.read")); + app1.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE, PRIV_CONTACTS_READ}); ScopedInstaller appInstall1(app1); @@ -1250,16 +1213,15 @@ RUNNER_CHILD_TEST(security_manager_31_fetch_app_manifest_app_context_local_diffe AppInstallHelper app("security_manager_31_fetch", user.getUid()); app.setInstallType(SM_APP_INSTALL_LOCAL); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); + app.addPrivileges({PRIV_CALENDAR_READ, PRIV_CALENDAR_WRITE}); ScopedInstaller appInstall(app); AppInstallHelper app1("security_manager_31_fetch_1", user.getUid()); app1.setInstallType(SM_APP_INSTALL_LOCAL); - app1.addPrivilege(std::string("http://tizen.org/privilege/calendar.read")); - app1.addPrivilege(std::string("http://tizen.org/privilege/calendar.write")); - app1.addPrivilege(std::string("http://tizen.org/privilege/contacts.read")); - app1.addPrivilege(std::string("http://tizen.org/privilege/internal/usermanagement")); + app1.addPrivileges({PRIV_CALENDAR_READ, + PRIV_CALENDAR_WRITE, + PRIV_CONTACTS_READ, + PRIV_INTERNAL_USERMANAGEMENT}); ScopedInstaller appInstall1(app1); diff --git a/src/security-manager-tests/test_cases_public_sharing.cpp b/src/security-manager-tests/test_cases_public_sharing.cpp index b71ad04..c4f0078 100644 --- a/src/security-manager-tests/test_cases_public_sharing.cpp +++ b/src/security-manager-tests/test_cases_public_sharing.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2020 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. @@ -65,13 +65,13 @@ static void runAccessTest(uid_t uid, gid_t gid, const std::string &appId, if (pid == 0) { setLauncherSecurityAttributes(uid, gid); Api::prepareAppCandidate(); - Api::prepareApp(appId.c_str()); + Api::prepareApp(appId); f(); exit(0); } else { waitPid(pid); - Api::cleanupApp(appId.c_str(), uid, pid); + Api::cleanupApp(appId, uid, pid); } } diff --git a/src/security-manager-tests/test_cases_smack_privileges.cpp b/src/security-manager-tests/test_cases_smack_privileges.cpp new file mode 100644 index 0000000..0aba4f7 --- /dev/null +++ b/src/security-manager-tests/test_cases_smack_privileges.cpp @@ -0,0 +1,961 @@ +/* + * Copyright (c) 2020 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 +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace SecurityManagerTest; +using namespace PrivilegeNames; + +namespace { + +namespace fs = boost::filesystem; + +const uid_t OWNER_ID = tzplatform_getuid(TZ_SYS_DEFAULT_USER); + +const fs::path TEST_SETUP_PATH = SM_TEST_DIR "/smack-privileges"; +const fs::path BACKUP_SETUP_PATH = TEST_SETUP_PATH / "backup"; + +constexpr char SM_POLICY_PATH[] = "/usr/share/security-manager/policy"; +constexpr char SM_SMACK_PRIV_MAPPING_SUBDIR[] = "/privilege-mapping"; +constexpr char SM_SMACK_PRIV_CONFIG[] = "privilege-smack.list"; + +void changePolicy(const AppInstallHelper& app, const std::string& priv, const std::string &level) { + PolicyRequest policyRequest; + PolicyEntry entry(app.getAppId(), std::to_string(app.getUID()), priv); + entry.setLevel(level); + policyRequest.addEntry(entry); + Api::sendPolicy(policyRequest); +} + +const std::vector INTERNET_RULES = { + {"~PROCESS~", "System::Privilege::Internet", "w"}, + {"System::Privilege::Internet", "~PROCESS~", "w"} +}; +const std::vector CAMERA_RULES = { + {"~PROCESS~", "System::Privilege::Camera", "w"}, + {"System::Privilege::Camera", "~PROCESS~", "w"} +}; +const std::vector CAMERA_IGNORED_RULES = { + {"~PROCESS~", "System::TEF", "r"} +}; + +enum class SmackPrivSetup { + ORIGINAL, + EMPTY, + INTERNET_ONLY, + MULTIPLE_PRIVS, + MALFORMED +}; + +// This is to ensure that original security-manager policy is restored after the group is finished +class SmackPrivGroupEnv final : public DPL::Test::TestGroup { +private: + class SmackPrivSetupMgr final { + public: + SmackPrivSetupMgr() : + m_currentSetup(SmackPrivSetup::ORIGINAL), + m_serviceManager("security-manager.service"), + m_setupMap({{ SmackPrivSetup::EMPTY, "empty" }, + { SmackPrivSetup::INTERNET_ONLY, "internet-only" }, + { SmackPrivSetup::MULTIPLE_PRIVS, "multiple-privs" }, + { SmackPrivSetup::MALFORMED, "malformed" }}) + { + } + SmackPrivSetupMgr(const SmackPrivSetupMgr&) = delete; + SmackPrivSetupMgr& operator=(const SmackPrivSetupMgr&) = delete; + ~SmackPrivSetupMgr() + { + // restore setup + if (m_currentSetup != SmackPrivSetup::ORIGINAL) { + try { + copySetup(BACKUP_SETUP_PATH, SM_POLICY_PATH); + + m_serviceManager.restartService(); + } catch (...) { + RUNNER_ERROR_MSG("Unknown exception occurred during backup restore."); + } + } + } + + void install(SmackPrivSetup setup) + { + if (setup == m_currentSetup) + return; + + // backup setup + if (m_currentSetup == SmackPrivSetup::ORIGINAL) + copySetup(SM_POLICY_PATH, BACKUP_SETUP_PATH); + + copySetup(TEST_SETUP_PATH / m_setupMap.at(setup), SM_POLICY_PATH); + m_currentSetup = setup; + + // restart SM + m_serviceManager.restartService(); + } + + private: + void copySetup(const boost::filesystem::path& src, const boost::filesystem::path& dst) + { + const auto srcConfig = src / SM_SMACK_PRIV_CONFIG; + const auto dstConfig = dst / SM_SMACK_PRIV_CONFIG; + const auto srcMappingSubdir = src / SM_SMACK_PRIV_MAPPING_SUBDIR; + const auto dstMappingSubdir = dst / SM_SMACK_PRIV_MAPPING_SUBDIR; + + // remove dst + fs::remove(dstConfig); + fs::remove_all(dstMappingSubdir); + + // copy + if (fs::exists(srcConfig)) + fs::copy_file(srcConfig, dstConfig); + + if (fs::exists(srcMappingSubdir)) { + fs::create_directory(dstMappingSubdir); + for (const auto& e: fs::recursive_directory_iterator(srcMappingSubdir)) + fs::copy(e.path(), dstMappingSubdir / fs::relative(e.path(), srcMappingSubdir)); + } + } + + SmackPrivSetup m_currentSetup; + ServiceManager m_serviceManager; + const std::map m_setupMap; + }; + + static SmackPrivSetupMgr* m_setupMgr; + +public: + void Init() override { + assert(!m_setupMgr); + + m_setupMgr = new SmackPrivSetupMgr(); + } + + static void Install(SmackPrivSetup setup) + { + assert(m_setupMgr); + + m_setupMgr->install(setup); + } + + void Finish() override { + assert(m_setupMgr); + + delete(m_setupMgr); + m_setupMgr = nullptr; + } +}; + +SmackPrivGroupEnv::SmackPrivSetupMgr* SmackPrivGroupEnv::m_setupMgr = nullptr; + +template +class TestSetup +{ +public: + void init(const std::string &) { + SmackPrivGroupEnv::Install(T); + } + void finish() {} +}; + +typedef TestSetup EmptySetup; +typedef TestSetup InternetOnlySetup; +typedef TestSetup MultiplePrivsSetup; +typedef TestSetup MalformedSetup; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(SECURITY_MANAGER_SMACK_PRIVILEGES, SmackPrivGroupEnv) + +RUNNER_CHILD_TEST(smack_privileges_10_no_privileges, InternetOnlySetup) +{ + AppInstallHelperExt app("sm_test_sp_10_app"); + { + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + app.checkDeniedPrivileges({PRIV_INTERNET}); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + app.checkSmackAccesses(CAMERA_RULES, false); + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + app.checkSmackAccesses(CAMERA_RULES, false); + } + } + app.checkAfterUninstall(); +} + +RUNNER_CHILD_TEST(smack_privileges_20_internet_privilege, InternetOnlySetup) +{ + AppInstallHelperExt app("sm_test_sp_20_app"); + app.addPrivileges({PRIV_INTERNET, PRIV_CAMERA}); + { + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + // rules absent before app is launched + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + app.checkSmackAccesses(CAMERA_RULES, false); + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + app.checkSmackAccesses(CAMERA_RULES, false); + } + // rules present after app is terminated + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + // rules removed after app uninstallation + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_30_one_after_another, InternetOnlySetup) +{ + AppInstallHelperExt app("sm_test_sp_30_app"); + app.addPrivileges({PRIV_INTERNET}); + { + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + // rules absent before app is launched + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + // rules present after app is terminated + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + // rules present after app is terminated + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + // rules removed after app uninstallation + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_40_different_users_one_after_another, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_40_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + AppInstallHelperExt app("sm_test_sp_40_app"); + app.addPrivileges({PRIV_INTERNET}); + { + // global install + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // owner launch + { + app.setUidGid(OWNER_ID); + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // test user launch + { + app.setUidGid(testUser.getUid()); + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_50_same_user_simultaneously, InternetOnlySetup) +{ + AppInstallHelperExt app("sm_test_sp_50_app", OWNER_ID); + app.addPrivileges({PRIV_INTERNET}); + { + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + { + ScopedAppLauncher appLaunch1(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + { + ScopedAppLauncher appLaunch2(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_60_same_user_interchangeably, InternetOnlySetup) +{ + AppInstallHelperExt app("sm_test_sp_60_app", OWNER_ID); + app.addPrivileges({PRIV_INTERNET}); + { + // local install + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // owner launch 1 + auto appLaunch1 = std::make_unique(app); + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // owner launch 2 + auto appLaunch2 = std::make_unique(app); + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // owner terminate 1 + appLaunch1.reset(); + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // owner terminate 2 + appLaunch2.reset(); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_70_different_users_simultaneously, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_70_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + AppInstallHelperExt app("sm_test_sp_70_app"); + app.addPrivileges({PRIV_INTERNET}); + { + // global install + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // owner launch + { + app.setUidGid(OWNER_ID); + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // test user launch + { + app.setUidGid(testUser.getUid()); + ScopedAppLauncher appLaunch(app); + + // multiuser detected -> rules removed + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + } + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + } + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // owner launch + { + app.setUidGid(OWNER_ID); + ScopedAppLauncher appLaunch(app); + + // rules restored + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_80_uninstall_local_while_running, InternetOnlySetup) +{ + AppInstallHelperExt app("sm_test_sp_80_app"); + app.addPrivileges({PRIV_INTERNET}); + { + // global install + ScopedInstaller appInstall1(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // local install + AppInstallHelperExt app2("sm_test_sp_80_app", OWNER_ID); + auto appInstall2 = std::make_unique(app2); + app2.checkAfterInstall(); + + // global launch + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // local uninstall + appInstall2.reset(); + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_90_user_removal, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_90_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + AppInstallHelperExt app("sm_test_sp_90_app", testUser.getUid()); + app.addPrivileges({PRIV_INTERNET}); + { + // local install + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // local launch + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // user removal + testUser.remove(); + + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + } +} + +RUNNER_CHILD_TEST(smack_privileges_100_hybrid_app, InternetOnlySetup) +{ + AppInstallHelperExt app("sm_test_sp_100_app"); + app.addPrivileges({PRIV_INTERNET}); + app.setHybrid(); + { + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // launch + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_110_hybridity_change, InternetOnlySetup) +{ + AppInstallHelperExt app("sm_test_sp_110_app"); + app.addPrivileges({PRIV_INTERNET}); + { + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // launch + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + app.setHybrid(); + + // make it hybrid + InstallRequest request; + request.setAppId(app.getAppId()); + request.setPkgId(app.getPkgId()); + request.setUid(app.getUID()); + request.setHybrid(); + for (const auto &priv: app.getPrivileges()) { + request.addPrivilege(priv); + } + Api::update(request); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // launch + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_120_policy_change_while_running, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_120_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + AppInstallHelperExt app("sm_test_sp_120_app", testUser.getUid()); + app.addPrivileges({PRIV_INTERNET}); + { + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // launch + { + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // change policy + changePolicy(app, PRIV_INTERNET, PolicyEntry::LEVEL_DENY); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // change policy + changePolicy(app, PRIV_INTERNET, PolicyEntry::LEVEL_ALLOW); + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_130_different_users_and_policies, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_130_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + AppInstallHelperExt app("sm_test_sp_130_app"); + app.addPrivileges({PRIV_INTERNET}); + { + // global install + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // test user launch with denied policy + { + app.setUidGid(testUser.getUid()); + changePolicy(app, PRIV_INTERNET, PolicyEntry::LEVEL_DENY); + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + } + + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // owner launch + { + app.setUidGid(OWNER_ID); + ScopedAppLauncher appLaunch(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_140_two_users_sequence, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_140_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + AppInstallHelperExt app("sm_test_sp_140_app"); + app.addPrivileges({PRIV_INTERNET}); + { + // global install + ScopedInstaller appInstall(app); + app.checkAfterInstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + { + // owner launch -> allowed + app.setUidGid(OWNER_ID); + ScopedAppLauncher appLaunch1(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + { + // test user launch -> denied + app.setUidGid(testUser.getUid()); + ScopedAppLauncher appLaunch2(app); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // owner launch -> denied + app.setUidGid(OWNER_ID); + ScopedAppLauncher appLaunch3(app); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + } + // test user launch -> still denied + app.setUidGid(testUser.getUid()); + ScopedAppLauncher appLaunch4(app); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); + } + + // test user launch -> allowed + app.setUidGid(testUser.getUid()); + ScopedAppLauncher appLaunch5(app); + app.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_150_independent_apps, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_150_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + AppInstallHelperExt app1("sm_test_sp_150_app1", testUser.getUid()); + AppInstallHelperExt app2("sm_test_sp_150_app2", testUser.getUid()); + app1.addPrivileges({PRIV_INTERNET}); + { + ScopedInstaller appInstall1(app1); + ScopedInstaller appInstall2(app2); + + app1.checkAfterInstall(); + app2.checkAfterInstall(); + + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // launch + { + ScopedAppLauncher appLaunch1(app1); + ScopedAppLauncher appLaunch2(app2); + + app1.checkSmackPrivileges({PRIV_INTERNET}, {}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + } + } + app1.checkAfterUninstall(); + app2.checkAfterUninstall(); + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_160_nonhybrid_package, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_160_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + constexpr char pkgPrefix[] = "sm_test_sp_160_pkg"; + + AppInstallHelperExt app1("sm_test_sp_160_app1", pkgPrefix, testUser.getUid()); + app1.addPrivileges({PRIV_INTERNET}); + + AppInstallHelperExt app2("sm_test_sp_160_app2", pkgPrefix, testUser.getUid()); + app2.addPrivileges({PRIV_INTERNET}); + { + ScopedInstaller appInstall1(app1); + ScopedInstaller appInstall2(app2); + + app1.checkAfterInstall(); + app2.checkAfterInstall(); + + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // launch + { + ScopedAppLauncher appLaunch1(app1); + ScopedAppLauncher appLaunch2(app2); + + // both have access in non-hybrid package + app1.checkSmackPrivileges({PRIV_INTERNET}, {}); + app2.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // change policy of single app + changePolicy(app1, PRIV_INTERNET, PolicyEntry::LEVEL_DENY); + + // both should lose the access + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + + changePolicy(app1, PRIV_INTERNET, PolicyEntry::LEVEL_ALLOW); + + app1.checkSmackPrivileges({PRIV_INTERNET}, {}); + app2.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + } + app1.checkAfterUninstall(); + app2.checkAfterUninstall(); + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + + +RUNNER_CHILD_TEST(smack_privileges_170_hybrid_package, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_170_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + constexpr char pkgPrefix[] = "sm_test_sp_170_pkg"; + + AppInstallHelperExt app1("sm_test_sp_170_app1", pkgPrefix, testUser.getUid()); + app1.addPrivileges({PRIV_INTERNET}); + app1.setHybrid(); + + AppInstallHelperExt app2("sm_test_sp_170_app2", pkgPrefix, testUser.getUid()); + app2.setHybrid(); + { + ScopedInstaller appInstall1(app1); + ScopedInstaller appInstall2(app2); + + app1.checkAfterInstall(); + app2.checkAfterInstall(); + + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // launch + { + ScopedAppLauncher appLaunch1(app1); + ScopedAppLauncher appLaunch2(app2); + + // only one have access in a hybrid package + app1.checkSmackPrivileges({PRIV_INTERNET}, {}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // change policy of single app + changePolicy(app1, PRIV_INTERNET, PolicyEntry::LEVEL_DENY); + + // both should have no access + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + + changePolicy(app1, PRIV_INTERNET, PolicyEntry::LEVEL_ALLOW); + + app1.checkSmackPrivileges({PRIV_INTERNET}, {}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + } + } + app1.checkAfterUninstall(); + app2.checkAfterUninstall(); + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_180_hybrid_package_both_apps_privileged, InternetOnlySetup) +{ + TemporaryTestUser testUser("sm_test_180_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + constexpr char pkgPrefix[] = "sm_test_sp_180_pkg"; + + AppInstallHelperExt app1("sm_test_sp_180_app1", pkgPrefix, testUser.getUid()); + app1.addPrivileges({PRIV_INTERNET}); + app1.setHybrid(); + + AppInstallHelperExt app2("sm_test_sp_180_app2", pkgPrefix, testUser.getUid()); + app2.addPrivileges({PRIV_INTERNET}); + app2.setHybrid(); + { + ScopedInstaller appInstall1(app1); + ScopedInstaller appInstall2(app2); + + app1.checkAfterInstall(); + app2.checkAfterInstall(); + + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); + + // launch + { + ScopedAppLauncher appLaunch1(app1); + ScopedAppLauncher appLaunch2(app2); + + // only one have access in a hybrid package + app1.checkSmackPrivileges({PRIV_INTERNET}, {}); + app2.checkSmackPrivileges({PRIV_INTERNET}, {}); + + // change policy of single app + changePolicy(app1, PRIV_INTERNET, PolicyEntry::LEVEL_DENY); + + // both should have no access + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({PRIV_INTERNET}, {}); + + changePolicy(app1, PRIV_INTERNET, PolicyEntry::LEVEL_ALLOW); + + app1.checkSmackPrivileges({PRIV_INTERNET}, {}); + app2.checkSmackPrivileges({PRIV_INTERNET}, {}); + } + } + app1.checkAfterUninstall(); + app2.checkAfterUninstall(); + app1.checkSmackPrivileges({}, {PRIV_INTERNET}); + app2.checkSmackPrivileges({}, {PRIV_INTERNET}); +} + +RUNNER_CHILD_TEST(smack_privileges_200_empty_policy, EmptySetup) +{ + AppInstallHelperExt app("sm_test_sp_200_app"); + app.addPrivileges({PRIV_INTERNET, PRIV_CAMERA}); + { + ScopedInstaller appInstall(app); + + app.checkAfterInstall(); + + app.checkSmackAccesses(INTERNET_RULES, false); + app.checkSmackAccesses(CAMERA_RULES, false); + { + ScopedAppLauncher appLaunch(app); + + // no config -> no access + app.checkSmackAccesses(INTERNET_RULES, false); + app.checkSmackAccesses(CAMERA_RULES, false); + } + } + app.checkAfterUninstall(); + app.checkSmackAccesses(INTERNET_RULES, false); + app.checkSmackAccesses(CAMERA_RULES, false); +} + +RUNNER_CHILD_TEST(smack_privileges_300_multi_policy_no_privs, MultiplePrivsSetup) +{ + AppInstallHelperExt app("sm_test_sp_300_app"); + { + ScopedInstaller appInstall(app); + + app.checkAfterInstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET, PRIV_CAMERA}); + app.checkSmackAccesses(CAMERA_IGNORED_RULES, false); + { + ScopedAppLauncher appLaunch(app); + + app.checkSmackPrivileges({}, {PRIV_INTERNET, PRIV_CAMERA}); + app.checkSmackAccesses(CAMERA_IGNORED_RULES, false); + } + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET, PRIV_CAMERA}); +} + +RUNNER_CHILD_TEST(smack_privileges_310_multi_policy_single_priv, MultiplePrivsSetup) +{ + AppInstallHelperExt app("sm_test_sp_310_app"); + app.addPrivilege(PRIV_CAMERA); + { + ScopedInstaller appInstall(app); + + app.checkAfterInstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET, PRIV_CAMERA}); + app.checkSmackAccesses(CAMERA_IGNORED_RULES, false); + { + ScopedAppLauncher appLaunch(app); + + app.checkSmackPrivileges({PRIV_CAMERA}, {PRIV_INTERNET}); + app.checkSmackAccesses(CAMERA_IGNORED_RULES, false); + } + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET, PRIV_CAMERA}); +} + +RUNNER_CHILD_TEST(smack_privileges_320_multi_policy_all_privs, MultiplePrivsSetup) +{ + TemporaryTestUser testUser("sm_test_320_user_name", GUM_USERTYPE_NORMAL, true); + testUser.create(); + + AppInstallHelperExt app("sm_test_sp_320_app", testUser.getUid()); + app.addPrivileges({PRIV_CAMERA, PRIV_INTERNET}); + { + ScopedInstaller appInstall(app); + + app.checkAfterInstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET, PRIV_CAMERA}); + app.checkSmackAccesses(CAMERA_IGNORED_RULES, false); + { + ScopedAppLauncher appLaunch(app); + + app.checkSmackPrivileges({PRIV_CAMERA, PRIV_INTERNET}, {}); + app.checkSmackAccesses(CAMERA_IGNORED_RULES, false); + + // change policy + changePolicy(app, PRIV_INTERNET, PolicyEntry::LEVEL_DENY); + + app.checkSmackPrivileges({PRIV_CAMERA}, {PRIV_INTERNET}); + app.checkSmackAccesses(CAMERA_IGNORED_RULES, false); + + // change policy + changePolicy(app, PRIV_INTERNET, PolicyEntry::LEVEL_ALLOW); + changePolicy(app, PRIV_CAMERA, PolicyEntry::LEVEL_DENY); + + app.checkSmackPrivileges({PRIV_INTERNET}, {PRIV_CAMERA}); + app.checkSmackAccesses(CAMERA_IGNORED_RULES, false); + } + } + app.checkAfterUninstall(); + app.checkSmackPrivileges({}, {PRIV_INTERNET, PRIV_CAMERA}); +} + +RUNNER_CHILD_TEST(smack_privileges_400_malformed, MalformedSetup) +{ + AppInstallHelperExt app("sm_test_sp_400_app"); + app.addPrivileges({PRIV_INTERNET, PRIV_CAMERA}); + { + ScopedInstaller appInstall(app); + + app.checkAfterInstall(); + + app.checkSmackAccesses(INTERNET_RULES, false); + app.checkSmackAccesses(CAMERA_RULES, false); + { + ScopedAppLauncher appLaunch(app); + + // malformed config -> no access + app.checkSmackAccesses(INTERNET_RULES, false); + app.checkSmackAccesses(CAMERA_RULES, false); + } + } + app.checkAfterUninstall(); + app.checkSmackAccesses(INTERNET_RULES, false); + app.checkSmackAccesses(CAMERA_RULES, false); +}