2 * Copyright (c) 2016-2020 Samsung Electronics Co., Ltd. All rights reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include <sys/types.h>
27 #include <dpl/test/test_runner.h>
28 #include <dpl/test/test_runner_child.h>
29 #include <policy_configuration.h>
31 #define CONF_DIR "/usr/share/security-manager/policy/"
32 #define CONF_GROUP_FILE "privilege-group.list"
33 #define CONF_SYSTEMD_PRIVS_FILE "privilege-managed-by-systemd-for-daemons.list"
34 #define CONF_USER_TEMPLATE_FILE "usertype-%s.profile"
36 namespace SecurityManagerTest {
40 PolicyConfiguration::SmackPrivRulesMap parsePrivilegeSmackList() {
41 constexpr char PRIVILEGE[] = "~PRIVILEGE~";
42 PolicyConfiguration::SmackPrivRulesMap privilegeRules;
44 std::ifstream templateFile(CONF_DIR "privilege-smack.list");
46 if (templateFile.fail())
47 return privilegeRules;
51 while (getline(templateFile, line)) {
52 if (line.empty() || line[0] == '#')
55 std::string privilege, label, rulesFileName;
56 std::istringstream stream(line);
57 stream >> privilege >> label >> rulesFileName;
59 if (rulesFileName == "default")
60 rulesFileName = "priv-rules-default-template.smack";
62 std::ifstream rulesFile(std::string(CONF_DIR) + "privilege-mapping/" + rulesFileName);
63 std::string object, subject, access;
64 while (rulesFile >> subject >> object >> access) {
65 if (object.empty() || subject.empty())
66 throw std::runtime_error("Malformed rule");
69 if (object.front() != '~' || subject.front() != '~')
72 if (object == PRIVILEGE)
74 if (subject == PRIVILEGE)
76 privilegeRules[privilege].emplace_back(std::move(subject),
81 } catch (const std::exception&) {
82 privilegeRules.clear();
84 return privilegeRules;
87 } // namespace anonymous
89 gid_t nameToGid(const char *name) {
90 struct group entry, *gresult;
93 0 == getgrnam_r(name, &entry, buffer, 1024, &gresult) && (gresult != NULL),
94 "Error in getgrnam. Group name: " << name);
99 std::string PolicyConfiguration::getConfigFilePath(UserType userType) {
100 const char *user = NULL;
102 case GUEST: user = "guest"; break;
103 case NORMAL: user = "normal"; break;
104 case ADMIN: user = "admin"; break;
105 case SYSTEM: user = "system"; break;
108 snprintf(buffer, 1024, CONF_DIR CONF_USER_TEMPLATE_FILE, user);
109 return std::string(buffer);
112 PolicyConfiguration::PrivVector PolicyConfiguration::getUserPriv(PolicyConfiguration::UserType userType) {
113 return getUserDescription(userType).privVector;
116 PolicyConfiguration::GroupVector PolicyConfiguration::getUserGroup(PolicyConfiguration::UserType userType) {
117 return getUserDescription(userType).groupVector;
120 PolicyConfiguration::GidVector PolicyConfiguration::getUserGid(PolicyConfiguration::UserType userType) {
121 return getUserDescription(userType).gidVector;
124 PolicyConfiguration::GidVector PolicyConfiguration::getGid() {
125 return groupToGid(getGroup());
128 PolicyConfiguration::GroupVector PolicyConfiguration::getGroup() {
130 if (m_privGroupMap.empty())
132 for (auto &e : m_privGroupMap)
133 result.push_back(e.second);
137 PolicyConfiguration::UserDescription& PolicyConfiguration::getUserDescription(PolicyConfiguration::UserType userType) {
138 auto it = m_userDescriptionMap.find(userType);
139 if (it == m_userDescriptionMap.end())
140 m_userDescriptionMap[userType] = loadUserDescription(userType);
141 return m_userDescriptionMap[userType];
144 gid_t PolicyConfiguration::groupToGid(const std::string &gname) {
145 auto it = m_groupGidMap.find(gname);
146 if (it == m_groupGidMap.end())
147 m_groupGidMap[gname] = nameToGid(gname.c_str());
148 return m_groupGidMap[gname];
151 PolicyConfiguration::GidVector PolicyConfiguration::groupToGid(const PolicyConfiguration::GroupVector &groupVector) {
153 for (auto &e : groupVector)
154 result.push_back(groupToGid(e));
158 PolicyConfiguration::PrivGroupMap PolicyConfiguration::getPrivGroupMap()
160 if (m_privGroupMap.empty())
162 return m_privGroupMap;
165 bool PolicyConfiguration::getIsAskuserEnabled() {
166 #ifdef ASKUSER_ENABLED
173 PolicyConfiguration::UserDescription PolicyConfiguration::loadUserDescription(PolicyConfiguration::UserType userType) {
174 UserDescription result;
175 std::string path = getConfigFilePath(userType);
176 result.privVector = loadPrivFile(path);
177 result.groupVector = privToGroup(result.privVector);
178 result.gidVector = groupToGid(result.groupVector);
182 PolicyConfiguration::PrivVector PolicyConfiguration::loadPrivFile(const std::string &path) {
184 std::ifstream file(path);
186 std::regex r("^\\*[ \t]+(.*)");
187 while (std::getline(file, line)) {
189 if (std::regex_search(line, m, r))
190 result.push_back(m[1]);
195 PolicyConfiguration::PrivVector PolicyConfiguration::getSystemdManagedPrivs()
197 PolicyConfiguration::PrivVector result;
198 std::ifstream file(CONF_DIR CONF_SYSTEMD_PRIVS_FILE);
199 if (!file.is_open()) {
200 RUNNER_ASSERT_MSG(file.is_open(),
201 "Unable to read config file " << CONF_DIR CONF_SYSTEMD_PRIVS_FILE);
204 std::regex r("^(http(.*))");
205 while (std::getline(file, line)) {
207 if (std::regex_search(line, m, r))
208 result.emplace_back(m[1]);
213 void PolicyConfiguration::loadPrivGroupMap(void) {
214 std::string pgPath(CONF_DIR CONF_GROUP_FILE);
215 std::ifstream file(pgPath);
217 RUNNER_ASSERT_MSG(file.is_open(),
218 "Unable to read group mapping file " << pgPath);
221 std::regex r("^(http(.*)) +(.*)");
222 while (std::getline(file, line)) {
224 if (std::regex_search(line, m, r))
225 m_privGroupMap[m[1]] = m[3];
229 std::string PolicyConfiguration::getPkgRulesFilePath() {
230 return CONF_DIR "pkg-rules-template.smack";
232 std::string PolicyConfiguration::getAppRulesFilePath() {
233 return CONF_DIR "app-rules-template.smack";
236 const PolicyConfiguration::SmackPrivRulesMap& PolicyConfiguration::getSmackPrivRulesMap() {
237 const static auto smackPrivRulesMap = parsePrivilegeSmackList();
238 return smackPrivRulesMap;
241 } // namespace SecurityManagerTest