2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
18 * @file PermissionManager.cpp
19 * @brief This is the implementation file for %PermissionManager class.
24 #include <sys/capability.h>
26 #include <unique_ptr.h>
28 #include <FBaseUtilStringUtil.h>
30 #include <FIoDirectory.h>
31 #include <FBase_StringConverter.h>
32 #include <FIo_FileImpl.h>
34 #include "PermissionManager.h"
35 #include "InstallerUtil.h"
36 #include "SmackManager.h"
37 #include "CompatibilityManager.h"
39 using namespace Tizen::Base;
40 using namespace Tizen::Base::Collection;
41 using namespace Tizen::Base::Utility;
42 using namespace Tizen::Io;
43 using namespace Tizen::App;
45 PermissionManager::PermissionManager(void)
49 PermissionManager::~PermissionManager(void)
54 PermissionManager::SetDirectory(InstallationContext* pContext)
61 SmackManager smackManager;
62 smackManager.Construct(pContext);
64 CompatibilityManager compatibilityManager;
65 compatibilityManager.Construct(pContext);
67 appRootPath = pContext->__rootPath;
68 PackageId packageId = pContext->__packageId;
71 // InstallerUtil::ChangeOwner(appRootPath);
72 InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
73 smackManager.SetupPath(packageId, appRootPath, APP_PATH_ANY_LABEL, L"_");
75 if (pContext->__isPreloaded == true)
77 String preloadedAppPath(PATH_USR_APPS);
78 preloadedAppPath += L"/";
79 preloadedAppPath += packageId;
81 smackManager.SetupPath(packageId, preloadedAppPath, APP_PATH_ANY_LABEL, L"_");
85 destPath = appRootPath + DIR_BIN;
86 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
87 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
90 destPath = appRootPath + DIR_INFO;
91 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
92 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
95 destPath = appRootPath + DIR_RES;
96 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
97 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
100 destPath = appRootPath + DIR_LIB;
101 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
102 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
105 destPath = appRootPath + DIR_SHARED;
106 if (File::IsFileExist(destPath) == false)
108 r = Directory::Create(destPath, false);
109 TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "Directory::Create() failed");
111 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
113 // appRoot/shared/res
114 destPath = appRootPath + DIR_SHARED_RES;
115 if (File::IsFileExist(destPath) == false)
117 String iconPath = appRootPath + DIR_ICONS;
118 InstallerUtil::CreateSymlink(iconPath, destPath);
120 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
122 // appRoot/shared/data
123 destPath = appRootPath + DIR_SHARED_DATA;
124 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
125 smackManager.SetupPath(packageId, destPath, APP_PATH_PUBLIC_RO);
127 // appRoot/shared/trusted
128 destPath = appRootPath + DIR_SHARED_TRUSTED;
129 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
130 smackManager.SetupPath(packageId, destPath, APP_PATH_GROUP_RW);
133 destPath = appRootPath + DIR_CONTENTS;
134 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
135 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
138 destPath = appRootPath + DIR_SETTING;
139 if (File::IsFileExist(destPath) == true)
141 String appVersion = pContext->__version;
143 String settingXmlPath;
144 srcPath = destPath + L"/setting." + appVersion + L".xml";
145 settingXmlPath = destPath + L"/setting.xml";
147 InstallerUtil::Remove(settingXmlPath);
148 InstallerUtil::CreateSymlink(srcPath, settingXmlPath);
150 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
151 smackManager.SetupPath(packageId, destPath, APP_PATH_SETTINGS_RW);
155 destPath = appRootPath + DIR_DATA;
156 if (File::IsFileExist(destPath) == false)
158 r = Directory::Create(destPath, false);
159 TryReturn(!IsFailed(r), false, "Directory::Create() failed");
161 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
163 // appRoot/data/[virtualRoot]
164 if (pContext->__virtualRootPath.IsEmpty() == false)
166 res = compatibilityManager.PrepareVirtualRoot(appRootPath, packageId);
167 TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.PrepareVirtualRoot(%ls) failed.", appRootPath.GetPointer());
169 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
171 String apiVersion = pContext->__apiVersion;
173 AppLog("------------------------------------------");
174 AppLog("[Tizen::Io] # path = [%ls]", appRootPath.GetPointer());
175 AppLog("[Tizen::Io] # package = [%ls]", packageId.GetPointer());
176 AppLog("[Tizen::Io] # apiVersion = [%ls]", apiVersion.GetPointer());
178 if (pContext->__isOspCompat == true)
180 AppLog("[Tizen::Io] OSP 2.0 application");
182 res = compatibilityManager.PrepareDataCaging(appRootPath, packageId);
183 TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.PrepareDataCaging() failed.");
185 SetSymLink(pContext);
189 AppLog("[Tizen::Io] apiVersion is equal to or greater than Tizen 2.0");
191 res = compatibilityManager.CleanDirectories(appRootPath, packageId);
192 TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.CleanDirectories() failed.");
194 res = compatibilityManager.LinkOspSharePath(appRootPath, packageId);
195 TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.LinkOspSharePath() failed.");
198 AppLog("------------------------------------------");
204 PermissionManager::SetFile(InstallationContext* pContext)
207 String appRootPath = pContext->__rootPath;
209 IListT<AppData*>* pAppDataList = pContext->__pAppDataList;
210 TryReturn(pAppDataList, false, "pAppDataList is null.");
212 for (int i = 0 ; i < pAppDataList->GetCount(); i++)
214 AppData* pAppData = null;
215 pAppDataList->GetAt(i, pAppData);
216 TryReturn(pAppData, false, "pAppData is null.");
218 String loader = appRootPath + DIR_BIN + L"/" + pAppData->__name;
219 if (File::IsFileExist(loader) == true)
221 SetFileCapability(loader, pContext);
224 // set permission(755) to bin file.
225 destPath = appRootPath + DIR_BIN + L"/" + pAppData->__name + L".exe";
226 if (File::IsFileExist(destPath) == true)
228 SetFileCapability(destPath, pContext);
229 InstallerUtil::ChangeMode(destPath, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
237 PermissionManager::SetSymLink(InstallationContext* pContext)
244 String appRootPath = pContext->__rootPath;
246 std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
247 TryCatch(pRootPath != null, res = false, "The memory is insufficient.");
249 pCwd = get_current_dir_name();
250 TryCatch(pCwd != null, res = false, "get_current_dir_name() failed.");
252 result = chdir(pRootPath.get());
253 TryCatch(result == 0, res = false, "chdir(%s) failed.", pRootPath.get());
255 newPath = appRootPath + L"/Res";
256 InstallerUtil::CreateSymlink(L"./res", newPath, false);
258 newPath = appRootPath + L"/Home";
259 InstallerUtil::CreateSymlink(L"./data", newPath, false);
261 result = chdir(pCwd);
262 TryCatch(result == 0, res = false, "chdir(%s) failed.", pCwd);
264 oldPath = appRootPath + DIR_RES + L"/screen-size-normal";
265 newPath = appRootPath + L"/Res/ScreenSize-Normal";
266 InstallerUtil::CreateSymlink(oldPath, newPath, false);
268 oldPath = appRootPath + DIR_RES + L"/screen-density-high";
269 newPath = appRootPath + L"/Res/ScreenDensity-High";
270 InstallerUtil::CreateSymlink(oldPath, newPath, false);
272 oldPath = appRootPath + DIR_RES + L"/screen-density-middle";
273 newPath = appRootPath + L"/Res/ScreenDensity-Middle";
274 InstallerUtil::CreateSymlink(oldPath, newPath, false);
276 oldPath = appRootPath + DIR_RES + L"/screen-density-low";
277 newPath = appRootPath + L"/Res/ScreenDensity-Low";
278 InstallerUtil::CreateSymlink(oldPath, newPath, false);
290 PermissionManager::CopyForRds(InstallationContext* pContext, IList* pFileList, bool& isInstallRequired)
292 TryReturn(pFileList, false, "pFileList is null.");
294 for (int idx = 0; idx < pFileList->GetCount(); idx++)
296 String* pFilePath = static_cast<String *>(pFileList->GetAt(idx));
297 TryReturn(pFilePath, false, "pFilePath is null.");
299 String srcFile = DIR_APPLICATIONS_TMP;
300 srcFile += L"/" + pContext->__packageId + L"/" + *pFilePath;
301 String destFile = pContext->__rootPath + L"/" + *pFilePath;
304 result r = E_SUCCESS;
307 AppLog("copy file from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
309 if (destFile.EndsWith(L"/") == true)
312 if (File::IsFileExist(destDir) == false)
314 Directory::Create(destDir, true);
320 r = destFile.LastIndexOf(L'/', destFile.GetLength() -1, pos);
321 if (IsFailed(r) == true)
323 AppLog("destFile is invalid[%ls]", destFile.GetPointer());
326 destFile.SubString(0, pos, destDir);
329 if (File::IsFileExist(destDir) == false)
331 Directory::Create(destDir, true);
333 InstallerUtil::Remove(destFile);
335 r = File::Copy(srcFile, destFile, true);
336 TryReturn(!IsFailed(r), false, "File::Copy() failed, [%ls] -> [%ls]", srcFile.GetPointer(), destFile.GetPointer());
338 AppLog("copy file from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
340 if ((destFile.Contains(pContext->__packageId + DIR_BIN) == true) && (destFile.EndsWith(L".exe") == true))
342 SetFileCapability(destFile, pContext);
345 if (*pFilePath == L"info/manifest.xml")
347 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
348 isInstallRequired = true;
350 else if (pFilePath->StartsWith("setting/setting", 0) == true)
352 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
353 isInstallRequired = true;
361 PermissionManager::ApplyPermissionForRds(InstallationContext* pContext)
365 SmackManager smackManager;
366 smackManager.Construct(pContext);
368 appRootPath = pContext->__rootPath;
369 PackageId packageId = pContext->__packageId;
372 InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
373 smackManager.SetupPath(packageId, appRootPath, APP_PATH_ANY_LABEL, L"_");
376 destPath = appRootPath + DIR_BIN;
377 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
378 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
381 destPath = appRootPath + DIR_INFO;
382 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
383 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
386 destPath = appRootPath + DIR_RES;
387 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
388 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
391 destPath = appRootPath + DIR_LIB;
392 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
393 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
396 destPath = appRootPath + DIR_SHARED;
397 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
399 // appRoot/shared/res
400 destPath = appRootPath + DIR_SHARED_RES;
401 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
403 // appRoot/shared/data
404 destPath = appRootPath + DIR_SHARED_DATA;
405 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
406 smackManager.SetupPath(packageId, destPath, APP_PATH_PUBLIC_RO);
408 // appRoot/shared/trusted
409 destPath = appRootPath + DIR_SHARED_TRUSTED;
410 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
411 smackManager.SetupPath(packageId, destPath, APP_PATH_GROUP_RW);
414 destPath = appRootPath + DIR_SETTING;
415 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
416 smackManager.SetupPath(packageId, destPath, APP_PATH_SETTINGS_RW);
419 destPath = appRootPath + DIR_DATA;
420 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
421 smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
427 PermissionManager::SetFileCapability(const String& path, InstallationContext* pContext)
429 TryReturn(path.IsEmpty() == false, false, "path is empty.");
430 TryReturn(pContext, false, "pContext is null.");
432 if (pContext->__isPreloaded == true)
434 AppLog("cap_set_file() is skipped.");
438 std::unique_ptr<char[]> pPath(_StringConverter::CopyToCharArrayN(path));
439 TryReturn(pPath != null, false, "The memory is insufficient.");
441 int res = cap_set_file(pPath.get(), cap_from_text("CAP_NET_RAW,CAP_SYS_CHROOT+i"));
442 TryReturn(res == 0, false, "cap_set_file() failed. [res = %d]", res);
444 AppLog("cap_set_file(%s, cap_from_text(CAP_NET_RAW,CAP_SYS_CHROOT+i)) called.", pPath.get());
451 PermissionManager::ApplyPermission(InstallationContext* pContext, const IList* pFileList)
453 TryReturn(pContext, false, "pContext is null");
454 TryReturn(pFileList, false, "pFileList is null");
456 // dir | type | owner | mode | smack
457 static RdsPermssions perms[] =
459 {"res", PERM_DIR_RES, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
460 {"data", PERM_DIR_DATA, PERM_OWNER_APP, PERM_BASE, PERM_SMACK_0},
461 {"bin", PERM_DIR_BIN, PERM_OWNER_ROOT, (PERM_BASE | PERM_EXECUTE), PERM_SMACK_0},
462 {"info", PERM_DIR_INFO, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
463 {"lib", PERM_DIR_LIB, PERM_OWNER_ROOT, (PERM_BASE | PERM_EXECUTE), PERM_SMACK_0},
464 {"setting", PERM_DIR_SETTING, PERM_OWNER_ROOT, (PERM_BASE | PERM_WRITE), PERM_SMACK_0},
465 {"shared/res", PERM_DIR_SHARED_RES, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
466 {"shared/data", PERM_DIR_SHARED_DATA, PERM_OWNER_APP, PERM_BASE, PERM_SMACK_0},
467 {"shared/trusted", PERM_DIR_SHARED_TRUSTED, PERM_OWNER_APP, PERM_BASE, PERM_SMACK_0},
468 {"shared", PERM_DIR_SHARED, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
469 {"author", PERM_DIR_ROOT, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
470 {"signature", PERM_DIR_ROOT, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
473 static int permCount = sizeof(perms) / sizeof(RdsPermssions);
474 bool isInstallRequired = false;
475 SmackManager smackManager;
476 smackManager.Construct(pContext);
478 for (int i = 0; i < pFileList->GetCount(); i++)
480 const String *pFilePath = static_cast<const String *>(pFileList->GetAt(i));
481 TryReturn(pFilePath, false, "pFilePath is null");
483 AppLog("pFilePath=(%ls)", pFilePath->GetPointer());
486 for (permIdx = 0; permIdx < permCount; permIdx++)
488 if (pFilePath->StartsWith(perms[permIdx].pDir, 0) == true)
490 if (perms[permIdx].dirType == PERM_DIR_INFO)
492 if (*pFilePath == L"info/manifest.xml")
494 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
495 isInstallRequired = true;
498 else if (perms[permIdx].dirType == PERM_DIR_SETTING)
500 if (pFilePath->StartsWith("setting/setting", 0) == true)
502 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
503 isInstallRequired = true;
507 AppLog("dirType=(%d), owner=(%d), mode=(%d), smack=(%d)",
508 perms[permIdx].dirType, perms[permIdx].ownerIndex, perms[permIdx].modeIndex, perms[permIdx].smackIndex);
510 String srcFile = DIR_APPLICATIONS_TMP;
511 srcFile += L"/" + pContext->__packageId + L"/" + *pFilePath;
512 String destFile = pContext->__rootPath + L"/" + *pFilePath;
514 AppLog("copy file: from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
515 File::Copy(srcFile, destFile, false);
517 bool isAppOwner = false;
518 if (perms[permIdx].ownerIndex == PERM_OWNER_APP)
524 if (perms[permIdx].dirType != PERM_DIR_ROOT)
526 destPath = pContext->__rootPath + L"/" + perms[permIdx].pDir;
527 InstallerUtil::ChangeDirectoryPermission(destPath, perms[permIdx].modeIndex, isAppOwner);
531 destPath = pContext->__rootPath + L"/" + *pFilePath;
532 InstallerUtil::ChangeMode(*pFilePath, perms[permIdx].modeIndex);
534 smackManager.AddLabelSharedDir(pContext->__packageId, destPath);