--- /dev/null
+/*
+ * 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
+ */
+
+/**
+ * @file test_template-manager.cpp
+ * @author Zofia Abramowska <z.abramowska@samsung.com>
+ * @version 1.0
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/filesystem.hpp>
+#include <fstream>
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <smack-common.h>
+#include <template-manager.h>
+#include <testmacros.h>
+
+using namespace SecurityManager;
+
+struct TemplateFixture
+{
+ struct PrivilegeSmackMapping {
+ std::string privName;
+ std::string privLabel;
+ std::string privFile;
+ };
+
+ TemplateFixture()
+ {
+ // Remove leftover files
+ removeAll();
+
+ // Create them again
+ boost::filesystem::path rootDir(rootPolicyDir);
+ boost::filesystem::create_directories(rootDir / PRIV_MAPPING_INSTALL_SUBDIR);
+ for (auto &ruleFile : templateRulesFiles) {
+ boost::filesystem::path file(rootDir / ruleFile);
+ }
+ }
+
+ void generateAppTemplates(
+ const Smack::TemplateRules &appRules = appTemplateRules,
+ const Smack::TemplateRules &pkgRules = pkgTemplateRules,
+ const Smack::TemplateRules &authorRules = authorTemplateRules)
+ {
+ // NOTE: These elements have to be in the same order as files in templateRulesFiles
+ std::vector<std::reference_wrapper<const Smack::TemplateRules>> rules
+ {appRules, pkgRules, authorRules};
+
+ for (std::size_t i = 0; i < rules.size(); i++) {
+ std::string path = rootPolicyDir + templateRulesFiles[i];
+ std::ofstream ruleFile(path);
+ for (auto &rule : rules[i].get()) {
+ ruleFile << rule.subject << " " << rule.object << " " << rule.permissions
+ << std::endl;
+ }
+ BOOST_REQUIRE_MESSAGE(ruleFile, "Failed to generate template file " << path);
+ }
+ }
+
+ void generatePrivDefaultTemplate(
+ const Smack::TemplateRules &privRules = privilegeTemplateRules)
+ {
+ std::string path = rootPolicyDir + privDefTemplFile;
+ std::ofstream ruleFile(path);
+ for (auto &rule : privRules) {
+ ruleFile << rule.subject << " " << rule.object << " " << rule.permissions << std::endl;
+ }
+ BOOST_REQUIRE_MESSAGE(ruleFile, "Failed to generate template file " << path);
+ }
+
+ void generatePrivSmackMapping(const std::vector<PrivilegeSmackMapping> &privSmackMapping =
+ privilegeSmackMappings)
+ {
+ std::ofstream mappingFile(rootPolicyDir + privilegeSmackMappingFile);
+ for (auto &mapping : privSmackMapping) {
+ mappingFile << mapping.privName << " " << mapping.privLabel << " "
+ << mapping.privFile << std::endl;
+ }
+ BOOST_REQUIRE_MESSAGE(mappingFile, "Failed to generate privilege Smack mapping file "
+ << privilegeSmackMappingFile);
+ }
+
+ void generateAllTemplates() {
+ generateAppTemplates();
+ generatePrivDefaultTemplate();
+ }
+
+ void generateAll() {
+ generateAllTemplates();
+ generatePrivSmackMapping();
+ }
+
+ void generateAdditional(const std::string &fileName, const Smack::TemplateRules &rules)
+ {
+ std::ofstream additionalFile(rootPolicyDir + fileName);
+ for (auto &rule : rules) {
+ additionalFile << rule.subject << " " << rule.object << " " << rule.permissions
+ << std::endl;
+ }
+ }
+
+ void removeAll() {
+ boost::filesystem::path rootDir(rootPolicyDir);
+ boost::filesystem::remove_all(rootDir);
+ }
+
+ ~TemplateFixture()
+ {
+ removeAll();
+ }
+
+ // DEFAULT FILES
+ const static inline std::string rootPolicyDir = "/tmp/sm-test-policy/";
+ const static inline std::vector<const char *> templateRulesFiles = {
+ "app-rules-template.smack",
+ "pkg-rules-template.smack",
+ "author-rules-template.smack",
+ };
+
+ const static inline char *privDefTemplFile =
+ PRIV_MAPPING_INSTALL_SUBDIR "/priv-rules-default-template.smack";
+ const static inline char *privilegeSmackMappingFile = "privilege-smack.list";
+
+ //DEFAULT RULES
+ const static inline Smack::TemplateRules appTemplateRules =
+ {{"System", "~PROCESS~", "rwxat"},
+ {"~PROCESS~", "System", "wx"},
+ {"~PROCESS~", "~PATH_RW~", "rwxat"},
+ {"~PROCESS~", "~PATH_RO~", "rxl"},
+ {"~PROCESS~", "~PATH_TRUSTED~", "rwxat"}
+ };
+ const static inline Smack::TemplateRules pkgTemplateRules =
+ {{"System", "~PATH_RW~", "rwxat"},
+ {"System", "~PATH_RO~", "rwxat"},
+ };
+ const static inline Smack::TemplateRules authorTemplateRules =
+ {{"User", "~PATH_TRUSTED~", "rwxat"},
+ {"System", "~PATH_TRUSTED~", "rwxat"},
+ {"System::Privileged", "~PATH_TRUSTED~", "rwxat"}
+ };
+ const static inline Smack::TemplateRules privilegeTemplateRules =
+ {{"~PRIVILEGE~", "~PROCESS~", "w"},
+ {"~PROCESS~", "~PRIVILEGE~", "w"},
+ };
+
+ // DEFAULT MAPPING
+ const static inline std::vector<PrivilegeSmackMapping> privilegeSmackMappings =
+ {{"http://tizen.org/privilege/internet", "System::Privilege::Internet", "default"}};
+};
+
+BOOST_AUTO_TEST_SUITE(SMACK_TEMPLATE_FILES_TEST)
+
+POSITIVE_FIXTURE_TEST_CASE(T1130_template_init, TemplateFixture)
+{
+ generateAll();
+
+ TemplateManager mgr(rootPolicyDir);
+
+ BOOST_REQUIRE_NO_THROW(mgr.init());
+ BOOST_REQUIRE(mgr.isPrivilegeMappingEnabled());
+
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::APP_RULES_TEMPLATE) == appTemplateRules);
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::PKG_RULES_TEMPLATE) == pkgTemplateRules);
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::AUTHOR_RULES_TEMPLATE) == authorTemplateRules);
+
+ for (auto &mapping : privilegeSmackMappings) {
+ BOOST_TEST(mgr.getPrivilegeLabel(mapping.privName) == mapping.privLabel);
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::PRIV_RULES_TEMPLATE, mapping.privName) == privilegeTemplateRules);
+ }
+}
+
+POSITIVE_FIXTURE_TEST_CASE(T1131_template_init_additional_mappings, TemplateFixture)
+{
+ generateAllTemplates();
+
+ const Smack::TemplateRules someRules =
+ {{"~PRIVILEGE~", "~PATH_RW", "rw"},
+ {"~PROCESS~", "~PRIVILEGE~", "w"},
+ {"~PRIVILEGE~", "~PATH_RO~", "rx"}};
+
+ PrivilegeSmackMapping mapping = {"somePrivilege", "somePrivilegeLabel", "/someRulesFile.smack"};
+
+ generateAdditional(PRIV_MAPPING_INSTALL_SUBDIR "/" + mapping.privFile, someRules);
+
+ auto additionalMapping = privilegeSmackMappings;
+
+ additionalMapping.push_back(mapping);
+ generatePrivSmackMapping(additionalMapping);
+
+ TemplateManager mgr(rootPolicyDir);
+ BOOST_REQUIRE_NO_THROW(mgr.init());
+ BOOST_REQUIRE(mgr.isPrivilegeMappingEnabled());
+
+ BOOST_TEST(mgr.getPrivilegeLabel(mapping.privName) == mapping.privLabel);
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::PRIV_RULES_TEMPLATE, mapping.privName) == someRules);
+}
+
+POSITIVE_FIXTURE_TEST_CASE(T1132_template_no_privilege_mappings, TemplateFixture)
+{
+ generateAppTemplates();
+ generatePrivSmackMapping({});
+
+ TemplateManager mgr(rootPolicyDir);
+ BOOST_REQUIRE_NO_THROW(mgr.init());
+ BOOST_REQUIRE(!mgr.isPrivilegeMappingEnabled());
+
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::APP_RULES_TEMPLATE) == appTemplateRules);
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::PKG_RULES_TEMPLATE) == pkgTemplateRules);
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::AUTHOR_RULES_TEMPLATE) == authorTemplateRules);
+}
+
+POSITIVE_FIXTURE_TEST_CASE(T1133_template_no_privilege_mappings_priv_rules, TemplateFixture)
+{
+ generateAppTemplates();
+ generatePrivSmackMapping({});
+ generatePrivDefaultTemplate();
+
+ TemplateManager mgr(rootPolicyDir);
+ BOOST_REQUIRE_NO_THROW(mgr.init());
+ BOOST_REQUIRE(!mgr.isPrivilegeMappingEnabled());
+
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::APP_RULES_TEMPLATE) == appTemplateRules);
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::PKG_RULES_TEMPLATE) == pkgTemplateRules);
+ BOOST_TEST(mgr.getRules(TemplateManager::Type::AUTHOR_RULES_TEMPLATE) == authorTemplateRules);
+}
+
+POSITIVE_FIXTURE_TEST_CASE(T1138_all_mapped_privileges, TemplateFixture)
+{
+ generateAppTemplates();
+ const std::vector<TemplateFixture::PrivilegeSmackMapping> mappings =
+ {{"privilege1", "label1", "file1"},
+ {"privilege2", "label2", "file2"},
+ };
+ std::vector<std::string> privileges;
+ for (auto &mapping : mappings) {
+ privileges.push_back(mapping.privName);
+ }
+ generatePrivSmackMapping(mappings);
+ const Smack::TemplateRules rules = {{"~PROCESS~", "~PRIVILEGE~", "rx"}};
+
+ for (auto &mapping : mappings)
+ generateAdditional(PRIV_MAPPING_INSTALL_SUBDIR "/" + mapping.privFile, rules);
+
+ TemplateManager mgr(rootPolicyDir);
+ BOOST_REQUIRE_NO_THROW(mgr.init());
+ BOOST_REQUIRE(mgr.isPrivilegeMappingEnabled());
+
+ BOOST_REQUIRE(mgr.getAllMappedPrivs() == privileges);
+
+ for (auto &mapping : mappings) {
+ BOOST_REQUIRE(mgr.getPrivilegeLabel(mapping.privName) == mapping.privLabel);
+ BOOST_REQUIRE(mgr.getRules(TemplateManager::PRIV_RULES_TEMPLATE, mapping.privName) == rules);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()