Allow uid change in AppInstallHelper
[platform/core/test/security-tests.git] / src / common / app_install_helper.cpp
1 /*
2  * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <fcntl.h>
18 #include <map>
19 #include <string>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <sys/smack.h>
23 #include <unistd.h>
24 #include <utility>
25
26 #include <security-manager-types.h>
27
28 #include <dpl/test/test_runner.h>
29 #include <tzplatform.h>
30 #include <label_generator.h>
31 #include <tests_common.h>
32 #include <tzplatform.h>
33
34 #include "app_install_helper.h"
35
36 namespace {
37
38 const gid_t FILE_GROUP = 100;
39
40     std::string genSkelPath() {
41         static std::string skelPkgDir;
42         if (!skelPkgDir.empty())
43             return skelPkgDir;
44         std::string app = TzPlatformConfig::getEnv(TZ_USER_APP);
45         std::string home = TzPlatformConfig::getEnv(TZ_USER_HOME);
46         std::string skelDir = "/etc/skel";
47
48         skelPkgDir.assign(app);
49         skelPkgDir.replace(0, home.length(), skelDir);
50
51         return skelPkgDir;
52     }
53
54     const AppInstallHelper::TypePathMap typeToPath = {
55             {SECURITY_MANAGER_PATH_RW, "app_rw"},
56             {SECURITY_MANAGER_PATH_RO, "app_ro"},
57             {SECURITY_MANAGER_PATH_PUBLIC_RO, "public_ro"},
58             {SECURITY_MANAGER_PATH_TRUSTED_RW, "trusted_rw"},
59             {SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, "shared_ro"}
60     };
61 }
62
63 AppInstallHelper::AppInstallHelper(AppInstallHelper &&other)
64     : m_appName(std::move(other.m_appName)), m_pkgName(std::move(other.m_pkgName)),
65       m_isLocal(other.m_isLocal), m_uidGid(other.m_uidGid),
66       m_version(std::move(other.m_version)), m_installType(other.m_installType),
67       m_isHybrid(other.m_isHybrid),
68       m_rootPaths(std::move(other.m_rootPaths)),
69       m_dirTypeMap(std::move(other.m_dirTypeMap)),
70       m_fileTypeMap(std::move(other.m_fileTypeMap)),
71       m_privileges(std::move(other.m_privileges)),
72       m_appDefinedPrivileges(std::move(other.m_appDefinedPrivileges)),
73       m_author(std::move(other.m_author)),
74       m_creatorPid(other.m_creatorPid)
75 {
76     other.m_creatorPid = -1;
77 }
78
79 void AppInstallHelper::setInstallPath(RootType type) const {
80     RootInfo &info = m_rootPaths[type];
81     if (!info.path.empty())
82         return;
83
84     switch (type) {
85     case RootType::BASE:
86         if (m_isLocal)
87             info.path = TzPlatformConfig::appDirPath(getUID()) + getPkgId();
88         else
89             info.path = TzPlatformConfig::globalAppDir() + "/" + getPkgId();
90         break;
91     case RootType::EXTENDED:
92         if (m_isLocal)
93             info.path = TzPlatformConfig::extendedSdUserDir(getUID()) + "/" + getPkgId();
94         else
95             info.path = TzPlatformConfig::extendedSdDir() + "/" + getPkgId();
96         break;
97     case RootType::SKEL:
98         info.path = genSkelPath() + "/" + getPkgId();
99         break;
100     case RootType::SHARED:
101         if (m_isLocal)
102             info.path = TzPlatformConfig::appDirPath(getUID()) + ".shared/" + getPkgId();
103         else
104             info.path = TzPlatformConfig::globalAppDir() + "/.shared/" + getPkgId();
105         break;
106     case RootType::SHARED_TMP:
107         if (m_isLocal)
108             info.path = TzPlatformConfig::appDirPath(getUID()) + ".shared_tmp/" + getPkgId();
109         else
110             info.path = TzPlatformConfig::globalAppDir() + "/.shared_tmp/" + getPkgId();
111         break;
112     }
113 }
114
115 std::string AppInstallHelper::getInstallDir(RootType type) const {
116     setInstallPath(type);
117     return m_rootPaths[type].path;
118 }
119
120 std::string AppInstallHelper::getPath(app_install_path_type smType, PathType pType, int i, RootType rType) const {
121     std::string path;
122     switch (pType) {
123     case PathType::DIR:
124         path = getInstallDir(rType) + "/" + typeToPath.at(smType) + "_dir" + std::to_string(i);
125         break;
126     case PathType::FILE:
127         // put files in the directory of the same type
128         path = getPath(smType, PathType::DIR, 0, rType) + "/" + typeToPath.at(smType) + std::to_string(i);
129         break;
130     }
131     return path;
132 }
133
134 std::string AppInstallHelper::getTrustedDir(int i, RootType type) const {
135     return getPath(SECURITY_MANAGER_PATH_TRUSTED_RW, PathType::DIR, i , type);
136 }
137
138 std::string AppInstallHelper::getPrivateDir(int i, RootType type) const {
139     return getPath(SECURITY_MANAGER_PATH_RW, PathType::DIR, i, type);
140 }
141
142 std::string AppInstallHelper::getPrivateRODir(int i, RootType type) const {
143     return getPath(SECURITY_MANAGER_PATH_RO, PathType::DIR, i, type);
144 }
145
146 std::string AppInstallHelper::getPublicDir(RootType type) const {
147     return getPath(SECURITY_MANAGER_PATH_PUBLIC_RO, PathType::DIR, 0, type);
148 }
149
150 std::string AppInstallHelper::getPrivatePath(int i, RootType type) const {
151     return getPath(SECURITY_MANAGER_PATH_RW, PathType::FILE, i, type);
152 }
153
154 std::string AppInstallHelper::getSharedRODir(int i, RootType type) const {
155 return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, type);
156 }
157
158 std::string AppInstallHelper::getSharedROPath(int i, RootType type) const {
159     return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::FILE, i, type);
160 }
161
162 const std::string& AppInstallHelper::getAppId() const {
163     return m_appName;
164 }
165
166 const std::string& AppInstallHelper::getPkgId() const {
167     return m_pkgName;
168 }
169
170 void AppInstallHelper::setVersion(const std::string &version) {
171     m_version = version;
172 }
173
174 std::string AppInstallHelper::getVersion() const {
175     return m_version;
176 }
177
178 void AppInstallHelper::setUidGid(int uidGid) {
179     m_uidGid = uidGid;
180 }
181
182 int AppInstallHelper::getUID() const {
183     return m_uidGid;
184 }
185
186 int AppInstallHelper::getGID() const {
187     return m_uidGid;
188 }
189
190 bool AppInstallHelper::createFile(app_install_path_type smType, const std::string &path) {
191     if (creat(path.c_str(), 0751) == 0) {
192         // Local paths need user change
193         m_fileTypeMap[smType].push_back(path);
194         if (!m_isLocal || chown(path.c_str(), m_uidGid, FILE_GROUP) == 0)
195             return true;
196     }
197     return false;
198 }
199
200 bool AppInstallHelper::createDir(app_install_path_type smType, const std::string &path, bool isBasePath) {
201     mktreeSafe(path, 0777);
202     // Dont pass base pkg dirs to SM, because transmute will be forced on RO subdirs
203     if (!isBasePath)
204         m_dirTypeMap[smType].push_back(path);
205     if (!m_isLocal || chown(path.c_str(), m_uidGid, FILE_GROUP) == 0)
206         return true;
207
208     return false;
209 }
210
211 void AppInstallHelper::createInstallDir(RootType type) {
212     setInstallPath(type);
213     RootInfo &info = m_rootPaths[type];
214     if (info.isCreated)
215         return;
216     createDir(SECURITY_MANAGER_PATH_PUBLIC_RO, info.path, true);
217     info.isCreated = true;
218 }
219
220 void AppInstallHelper::createPath(app_install_path_type smType, PathType pType, int i, RootType rType) {
221     createInstallDir(rType);
222     std::string path = getPath(smType, pType, i, rType);
223     switch (pType) {
224     case PathType::DIR:
225         createDir(smType, path);
226         break;
227     case PathType::FILE:
228         createPath(smType, PathType::DIR, 0, rType);
229         createFile(smType, path);
230         break;
231     }
232 }
233
234 void AppInstallHelper::createDirLink(app_install_path_type smType, const std::string &dest, int i,
235                                      RootType rType)
236 {
237     createInstallDir(rType);
238     std::string linkPath = getPath(smType, PathType::DIR, i, rType);
239     if (symlink(dest.c_str(), linkPath.c_str()) == 0) {
240         m_fileTypeMap[smType].push_back(linkPath);
241         if (m_isLocal) {
242             chown(linkPath.c_str(), m_uidGid, FILE_GROUP);
243         }
244     }
245 }
246
247 void AppInstallHelper::createTrustedDir(int i, RootType type) {
248     createPath(SECURITY_MANAGER_PATH_TRUSTED_RW, PathType::DIR, i, type);
249 }
250
251 void AppInstallHelper::createPrivateDir(int i, RootType type) {
252     createPath(SECURITY_MANAGER_PATH_RW, PathType::DIR, i, type);
253 }
254
255 void AppInstallHelper::createPublicDir(RootType type) {
256     createPath(SECURITY_MANAGER_PATH_PUBLIC_RO, PathType::DIR, 0, type);
257 }
258
259 void AppInstallHelper::createPrivateFile(int i, RootType type) {
260     createPath(SECURITY_MANAGER_PATH_RW, PathType::FILE, i, type);
261 }
262
263 void AppInstallHelper::createSharedRODir(int i, RootType type) {
264     createPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, RootType::SHARED);
265     createInstallDir(RootType::SHARED_TMP);
266     auto linkPath = getSharedRODir(i, RootType::SHARED);
267     createDirLink(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, linkPath, i, type);
268 }
269
270 void AppInstallHelper::createSharedROFile(int i, RootType type) {
271     createPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::FILE, i, type);
272 }
273
274 void AppInstallHelper::createPrivateRODir(int i, RootType type) {
275     createPath(SECURITY_MANAGER_PATH_RO, PathType::DIR, i, type);
276 }
277
278 void AppInstallHelper::setHybrid() {
279     m_isHybrid = true;
280 }
281
282 bool AppInstallHelper::getIsHybrid() const {
283     return m_isHybrid;
284 }
285
286 void AppInstallHelper::addPrivilege(Privilege privilege) {
287     m_privileges.push_back(std::move(privilege));
288 }
289
290 void AppInstallHelper::addPrivileges(const PrivilegeVector &privileges) {
291     std::copy(privileges.begin(), privileges.end(), std::back_inserter(m_privileges));
292 }
293
294 const PrivilegeVector& AppInstallHelper::getPrivileges() const {
295     return m_privileges;
296 }
297
298 void AppInstallHelper::addAppDefinedPrivilege(Privilege privilege) {
299     m_appDefinedPrivileges.push_back(std::move(privilege));
300 }
301
302 const PrivilegeVector& AppInstallHelper::getAppDefinedPrivileges() const {
303     return m_appDefinedPrivileges;
304 }
305
306 void AppInstallHelper::revokeRules() const {
307     RUNNER_ASSERT_MSG(
308         0 == smack_revoke_subject(generateAppLabel().c_str()),
309         "Revoking smack subject failed");
310 }
311
312 std::string AppInstallHelper::generateAppLabel() const {
313     return generateProcessLabel(getAppId(), getPkgId(), getIsHybrid());
314 }
315
316 std::string AppInstallHelper::generatePkgLabel() const {
317     return generatePathRWLabel(getPkgId());
318 }
319
320 const AppInstallHelper::TypePathsMap& AppInstallHelper::getDirsMap() const {
321     return m_dirTypeMap;
322 }
323
324 const AppInstallHelper::TypePathsMap& AppInstallHelper::getFilesMap() const {
325     return m_fileTypeMap;
326 }
327
328 void AppInstallHelper::removePaths() {
329     for (const auto &oneTypePaths : m_dirTypeMap)
330             for (const auto& path : oneTypePaths.second)
331                 rmdir(path.c_str());
332
333     m_dirTypeMap.clear();
334
335     for (const auto &oneTypePaths : m_fileTypeMap)
336             for (const auto& path : oneTypePaths.second)
337                 unlink(path.c_str());
338
339     m_fileTypeMap.clear();
340
341     for (auto& rootInfo : m_rootPaths) {
342         if (rootInfo.second.isCreated)
343             rmdir(rootInfo.second.path.c_str());
344         rootInfo.second.isCreated = false;
345     }
346 }
347
348 void AppInstallHelper::setAuthor(const std::string &author) {
349     m_author = author;
350 }
351 std::string AppInstallHelper::getAuthor() const {
352     return m_author;
353 }
354
355 void AppInstallHelper::setInstallType(app_install_type type) {
356     m_installType = type;
357 }
358 app_install_type AppInstallHelper::getInstallType() const {
359     return m_installType;
360 }