From e3fb8faa3aef9b2616a98743383ca5959d77c2dc Mon Sep 17 00:00:00 2001 From: Rafal Krypa Date: Tue, 28 Nov 2017 08:49:46 +0100 Subject: [PATCH] Add ConfigFile class for run-time reading and parsing of config files New code reads config file and splits it into lines to vector, with one element per file line. Each line is represented as vector itself, with one element per white space separated token. Lines that are empty or start with '#' are ignored. New code is now used for parsing Smack policy templates and privilege to group mapping. Change-Id: I009cf2a33f0233a170666cfe27fd7604fb7f4340 Signed-off-by: Rafal Krypa --- CMakeLists.txt | 9 ------ policy/security-manager-policy-reload.in | 2 +- src/client/client-security-manager.cpp | 30 ++++++++---------- src/common/CMakeLists.txt | 1 + src/common/config-file.cpp | 52 ++++++++++++++++++++++++++++++++ src/common/config.cpp | 2 ++ src/common/include/config-file.h | 41 +++++++++++++++++++++++++ src/common/include/config.h | 5 ++- src/common/include/smack-rules.h | 2 +- src/common/smack-rules.cpp | 39 ++++++++---------------- test/CMakeLists.txt | 1 + test/test_smack-rules.cpp | 21 +++++++------ 12 files changed, 140 insertions(+), 65 deletions(-) create mode 100644 src/common/config-file.cpp create mode 100644 src/common/include/config-file.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f539418..dd6649c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,15 +47,6 @@ ADD_DEFINITIONS("-DLOCAL_STATE_DIR=\"${LOCAL_STATE_DIR}\"") ADD_DEFINITIONS("-DDATA_ROOT_DIR=\"${DATA_ROOT_DIR}\"") ADD_DEFINITIONS("-DPOLICY_DIR=\"${POLICY_DIR}\"") -############################## file names ##################################### - -SET(PRIVILEGE_GROUP_LIST_FILE - "privilege-group.list" - CACHE PATH - "File with mapping from privileges into groups") - -ADD_DEFINITIONS("-DPRIVILEGE_GROUP_LIST_FILE=\"${PRIVILEGE_GROUP_LIST_FILE}\"") - ############################# compiler flags ################################## SET(CMAKE_CXX_FLAGS_PROFILING "-g -std=c++0x -O0 -pg -Wp,-U_FORTIFY_SOURCE") diff --git a/policy/security-manager-policy-reload.in b/policy/security-manager-policy-reload.in index 366303e..2611327 100755 --- a/policy/security-manager-policy-reload.in +++ b/policy/security-manager-policy-reload.in @@ -2,7 +2,7 @@ PATH=/bin:/usr/bin:/sbin:/usr/sbin POLICY_PATH=@POLICY_DIR@ -PRIVILEGE_GROUP_MAPPING=$POLICY_PATH/@PRIVILEGE_GROUP_LIST_FILE@ +PRIVILEGE_GROUP_MAPPING=$POLICY_PATH/privilege-group.list DB_FILE=`tzplatform-get TZ_SYS_DB | cut -d= -f2`/.security-manager.db diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index 654fb0a..dd2abf3 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -61,6 +60,8 @@ #include #include #include +#include +#include #include #include @@ -1250,25 +1251,20 @@ void security_manager_policy_levels_free(char **levels, size_t levels_count) delete[] levels; } -static void loadGroups(std::vector &vgroups) { - static const int LINEMAX = 256; - char line[LINEMAX]; - std::ifstream input(POLICY_DIR "/" PRIVILEGE_GROUP_LIST_FILE); - - std::vector buf(1024); - group *result = NULL; - group grp; - - while (input.getline(line, LINEMAX)) { - if (line[0] == '#') - continue; - char *pos = strchr(line, ' '); - if (pos == NULL) +static void loadGroups(std::vector &vgroups) +{ + auto groupsMapData = ConfigFile(Config::PRIVILEGE_GROUP_LIST_FILE).read(); + for (const auto &groupsMapEntry : groupsMapData) { + if (groupsMapEntry.size() != 2) continue; - pos++; + + const std::string &groupName = groupsMapEntry[1]; + std::vector buf(1024); + group *result = nullptr; + group grp; for (;;) { - int ret = TEMP_FAILURE_RETRY(getgrnam_r(pos, &grp, buf.data(), buf.size(), &result)); + int ret = TEMP_FAILURE_RETRY(getgrnam_r(groupName.c_str(), &grp, buf.data(), buf.size(), &result)); if (ret == ERANGE) { buf.resize(buf.size() * 2); continue; diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 1526aa6..145cb82 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -49,6 +49,7 @@ SET(COMMON_SOURCES ${DPL_PATH}/db/src/sql_connection.cpp ${COMMON_PATH}/channel.cpp ${COMMON_PATH}/config.cpp + ${COMMON_PATH}/config-file.cpp ${COMMON_PATH}/connection.cpp ${COMMON_PATH}/credentials.cpp ${COMMON_PATH}/cynara.cpp diff --git a/src/common/config-file.cpp b/src/common/config-file.cpp new file mode 100644 index 0000000..9999e32 --- /dev/null +++ b/src/common/config-file.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa + * + * 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 config-file.cpp + * @author Rafal Krypa (r.krypa@samsung.com) + * @version 1.0 + * @brief + */ + +#include +#include +#include +#include + +#include +#include + +namespace SecurityManager { + +std::vector> ConfigFile::read() +{ + std::vector> ret; + std::istringstream stream(FS::getTextFileContents(m_path)); + + std::string line; + while (getline(stream, line)) { + if (line.empty() || line[0] == '#') + continue; + + std::istringstream stream(line); + ret.emplace_back(std::istream_iterator(stream), std::istream_iterator()); + } + + return ret; +} + +} // namespace SecurityManager diff --git a/src/common/config.cpp b/src/common/config.cpp index a9bd113..4a58718 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -42,6 +42,8 @@ const std::string PRIVILEGE_APP_BIND = "http://tizen.org/privilege/notex const std::string APPS_LABELS_FILE = "apps-labels"; const std::string SKEL_DIR = "/etc/skel"; +const std::string PRIVILEGE_GROUP_LIST_FILE = POLICY_DIR "/privilege-group.list"; + const std::string PRIVACY_POLICY_DESC = "Ask user"; #ifdef ASKUSER_ENABLED const bool IS_ASKUSER_ENABLED = true; diff --git a/src/common/include/config-file.h b/src/common/include/config-file.h new file mode 100644 index 0000000..309c93a --- /dev/null +++ b/src/common/include/config-file.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Rafal Krypa + * + * 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 config-file.h + * @author Rafal Krypa (r.krypa@samsung.com) + * @version 1.0 + * @brief + */ + +#pragma once + +#include +#include + +namespace SecurityManager { + +class ConfigFile { +public: + ConfigFile(const std::string &path) : m_path(path) {} + std::vector> read(); + +private: + const std::string m_path; +}; + +} // namespace SecurityManager diff --git a/src/common/include/config.h b/src/common/include/config.h index bd5aa38..61a7747 100644 --- a/src/common/include/config.h +++ b/src/common/include/config.h @@ -29,8 +29,8 @@ namespace SecurityManager { namespace Config { -/* Service name */ +/* Service name */ extern const std::string SERVICE_NAME; /* Privileges required from users of our API */ @@ -46,6 +46,9 @@ extern const std::string PRIVILEGE_APP_BIND; /* Files used in permitted label managment */ extern const std::string APPS_LABELS_FILE; +/* Policy files */ +extern const std::string PRIVILEGE_GROUP_LIST_FILE; + extern const std::string SKEL_DIR; /* Ask-user policy description */ diff --git a/src/common/include/smack-rules.h b/src/common/include/smack-rules.h index 65c40db..736df18 100644 --- a/src/common/include/smack-rules.h +++ b/src/common/include/smack-rules.h @@ -36,7 +36,7 @@ namespace SecurityManager { class SmackRules { public: - typedef std::string Rule; + typedef std::vector Rule; typedef std::vector RuleVector; typedef std::vector Pkgs; typedef std::vector Labels; diff --git a/src/common/smack-rules.cpp b/src/common/smack-rules.cpp index 244bb9d..c7684ca 100644 --- a/src/common/smack-rules.cpp +++ b/src/common/smack-rules.cpp @@ -35,6 +35,7 @@ #include #include +#include "config-file.h" #include "dpl/log/log.h" #include "dpl/errno_string.h" #include "dpl/fstream_accessors.h" @@ -212,25 +213,12 @@ void SmackRules::addFromTemplateFile( const std::string &pkgName, const int authorId) { - RuleVector templateRules; - std::string line; - std::ifstream templateRulesFile(templatePath); - - if (!templateRulesFile.is_open()) { - LogError("Cannot open rules template file: " << templatePath); - ThrowMsg(SmackException::FileError, "Cannot open rules template file: " << templatePath); - } - - while (std::getline(templateRulesFile, line)) - if (!line.empty()) - templateRules.push_back(line); - - if (templateRulesFile.bad()) { + try { + addFromTemplate(ConfigFile(templatePath).read(), appProcessLabel, pkgName, authorId); + } catch (FS::Exception::Base) { LogError("Error reading template file: " << templatePath); ThrowMsg(SmackException::FileError, "Error reading template file: " << templatePath); } - - addFromTemplate(templateRules, appProcessLabel, pkgName, authorId); } void SmackRules::addFromTemplate( @@ -251,19 +239,16 @@ void SmackRules::addFromTemplate( if (authorId >= 0) pathTrustedLabel = SmackLabels::generatePathTrustedLabel(authorId); - for (auto rule : templateRules) { - if (rule.empty()) - continue; - - std::stringstream stream(rule); - std::string subject, object, permissions; - stream >> subject >> object >> permissions; - - if (stream.fail() || !stream.eof()) { - LogError("Invalid rule template: " << rule); - ThrowMsg(SmackException::FileError, "Invalid rule template: " << rule); + for (auto &rule : templateRules) { + if (rule.size() != 3) { + LogError("Invalid rule template: " << rule.size() << " tokens"); + ThrowMsg(SmackException::FileError, "Invalid rule template: " << rule.size() << " tokens"); } + std::string subject = rule[0]; + std::string object = rule[1]; + std::string permissions = rule[2]; + strReplace(subject, SMACK_PROCESS_LABEL_TEMPLATE, appProcessLabel); strReplace(object, SMACK_PROCESS_LABEL_TEMPLATE, appProcessLabel); strReplace(object, SMACK_PATH_RW_LABEL_TEMPLATE, pathRWLabel); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 14b04fe..8edb441 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -63,6 +63,7 @@ SET(SM_TESTS_SOURCES ${DPL_PATH}/log/src/abstract_log_provider.cpp ${DPL_PATH}/log/src/log.cpp ${DPL_PATH}/log/src/old_style_log_provider.cpp + ${PROJECT_SOURCE_DIR}/src/common/config-file.cpp ${PROJECT_SOURCE_DIR}/src/common/file-lock.cpp ${PROJECT_SOURCE_DIR}/src/common/privilege_db.cpp ${PROJECT_SOURCE_DIR}/src/common/smack-check.cpp diff --git a/test/test_smack-rules.cpp b/test/test_smack-rules.cpp index e981591..4503acf 100644 --- a/test/test_smack-rules.cpp +++ b/test/test_smack-rules.cpp @@ -163,20 +163,23 @@ BOOST_AUTO_TEST_CASE(T1120_smack_rules_exception) BOOST_FIXTURE_TEST_CASE(T1130_smack_rules_templates, RulesFixture) { - SmackRules::RuleVector templateRules = { "System ~PROCESS~ rwxat", - "~PROCESS~ System wx", - "~PROCESS~ ~PATH_RW~ rwxat", - "~PROCESS~ ~PATH_RO~ rxl", - "~PROCESS~ ~PATH_SHARED_RO~ rwxat", - "~PROCESS~ ~PATH_TRUSTED~ rwxat" }; + SmackRules::RuleVector templateRules = {{"System", "~PROCESS~", "rwxat"}, + {"~PROCESS~", "System", "wx"}, + {"~PROCESS~", "~PATH_RW~", "rwxat"}, + {"~PROCESS~", "~PATH_RO~", "rxl"}, + {"~PROCESS~", "~PATH_SHARED_RO~", "rwxat"}, + {"~PROCESS~", "~PATH_TRUSTED~", "rwxat"}}; std::ofstream templateRulesFile; templateRulesFile.open(templateRulesFilePath); - for (auto templateRule : templateRules) - templateRulesFile << templateRule << std::endl; + for (auto &templateRule : templateRules) { + for (auto &templateRuleToken : templateRule) + templateRulesFile << templateRuleToken << ' '; + templateRulesFile << std::endl; + } templateRulesFile.close(); - SmackRules::RuleVector expectedRules = { "System User::Pkg::pkgNameT1130 rwxat-", + std::vector expectedRules = { "System User::Pkg::pkgNameT1130 rwxat-", "User::Pkg::pkgNameT1130 System -wx---", "User::Pkg::pkgNameT1130 User::Pkg::pkgNameT1130 rwxat-", "User::Pkg::pkgNameT1130 User::Pkg::pkgNameT1130::RO r-x--l", -- 2.7.4