Add unit tests for template manager class 79/228679/35
authorZofia Abramowska <z.abramowska@samsung.com>
Tue, 24 Mar 2020 17:21:29 +0000 (18:21 +0100)
committerTomasz Swierczek <t.swierczek@samsung.com>
Wed, 24 Jun 2020 12:05:51 +0000 (14:05 +0200)
Change-Id: I2781dcd3b87ddbeea9578ff15d073c909cf4deb3

src/common/include/smack-common.h
test/CMakeLists.txt
test/test_template-manager.cpp [new file with mode: 0644]

index 254e8631da7ecf2bb820911100a00180d796d97c..86ca454366b11ee538de40cfd020b20ccfb714c9 100644 (file)
@@ -38,6 +38,12 @@ struct Rule {
     Label subject;
     Label object;
     Permission permissions;
+
+    bool operator==(const SecurityManager::Smack::Rule &other) const {
+        return subject == other.subject && object == other.object
+            && permissions == other.permissions;
+}
+
 };
 
 typedef std::vector<Rule> Rules;
index b316d462331959bd0ca432fda3812f4a258811ce..5f98a91b22395cf96f285241dfd112bc2f831feb 100644 (file)
@@ -68,6 +68,7 @@ SET(SM_TESTS_SOURCES
     ${SM_TEST_SRC}/test_smack-rules.cpp
     ${SM_TEST_SRC}/test_check_proper_drop.cpp
     ${SM_TEST_SRC}/test_misc.cpp
+    ${SM_TEST_SRC}/test_template-manager.cpp
     ${DPL_PATH}/core/src/assert.cpp
     ${DPL_PATH}/core/src/colors.cpp
     ${DPL_PATH}/core/src/errno_string.cpp
diff --git a/test/test_template-manager.cpp b/test/test_template-manager.cpp
new file mode 100644 (file)
index 0000000..b94647b
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ *  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()