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, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_ANY_LABEL, L"_");
85 destPath = appRootPath + DIR_BIN;
86 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
87 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
90 destPath = appRootPath + DIR_INFO;
91 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
92 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
95 destPath = appRootPath + DIR_RES;
96 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
97 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
100 destPath = appRootPath + DIR_LIB;
101 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
102 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_PUBLIC_RO);
127 // appRoot/shared/trusted
128 destPath = appRootPath + DIR_SHARED_TRUSTED;
129 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
130 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_GROUP_RW);
133 destPath = appRootPath + DIR_CONTENTS;
134 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
135 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_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;
303 AppLog("copy file from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
306 result r = E_SUCCESS;
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);
334 r = File::Copy(srcFile, destFile, true);
335 if (IsFailed(r) == true)
337 AppLog("File::Copy() failed. [%ls] -> [%ls]", srcFile.GetPointer(), destFile.GetPointer());
341 if ((destFile.Contains(pContext->__packageId + DIR_BIN) == true) && (destFile.EndsWith(L".exe") == true))
343 SetFileCapability(destFile, pContext);
346 if (*pFilePath == L"info/manifest.xml")
348 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
349 isInstallRequired = true;
351 else if (pFilePath->StartsWith("setting/setting", 0) == true)
353 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
354 isInstallRequired = true;
362 PermissionManager::ApplyPermissionForRds(InstallationContext* pContext)
366 SmackManager smackManager;
367 smackManager.Construct(pContext);
369 appRootPath = pContext->__rootPath;
370 PackageId packageId = pContext->__packageId;
373 InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
374 smackManager.SetupPath(packageId, appRootPath, SMACK_DIR_TYPE_ANY_LABEL, L"_");
377 destPath = appRootPath + DIR_BIN;
378 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
379 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
382 destPath = appRootPath + DIR_INFO;
383 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
384 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
387 destPath = appRootPath + DIR_RES;
388 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
389 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
392 destPath = appRootPath + DIR_LIB;
393 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
394 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
397 destPath = appRootPath + DIR_SHARED;
398 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
400 // appRoot/shared/res
401 destPath = appRootPath + DIR_SHARED_RES;
402 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
404 // appRoot/shared/data
405 destPath = appRootPath + DIR_SHARED_DATA;
406 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
407 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PUBLIC_RO);
409 // appRoot/shared/trusted
410 destPath = appRootPath + DIR_SHARED_TRUSTED;
411 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
412 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_GROUP_RW);
415 destPath = appRootPath + DIR_SETTING;
416 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
417 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_SETTINGS_RW);
420 destPath = appRootPath + DIR_DATA;
421 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
422 smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
428 PermissionManager::SetFileCapability(const String& path, InstallationContext* pContext)
430 TryReturn(path.IsEmpty() == false, false, "path is empty.");
431 TryReturn(pContext, false, "pContext is null.");
433 if (pContext->__isPreloaded == true)
435 AppLog("cap_set_file() is skipped.");
439 std::unique_ptr<char[]> pPath(_StringConverter::CopyToCharArrayN(path));
440 TryReturn(pPath != null, false, "The memory is insufficient.");
442 int res = cap_set_file(pPath.get(), cap_from_text("CAP_NET_RAW,CAP_SYS_CHROOT+i"));
443 TryReturn(res == 0, false, "cap_set_file() failed. [res = %d]", res);
445 AppLog("cap_set_file(%s, cap_from_text(CAP_NET_RAW,CAP_SYS_CHROOT+i)) called.", pPath.get());
452 PermissionManager::ApplyPermission(InstallationContext* pContext, const IList* pFileList)
454 TryReturn(pContext, false, "pContext is null");
455 TryReturn(pFileList, false, "pFileList is null");
457 // dir | type | owner | mode | smack
458 static RdsPermssions perms[] =
460 {"res", PERM_DIR_RES, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
461 {"data", PERM_DIR_DATA, PERM_OWNER_APP, PERM_BASE, PERM_SMACK_0},
462 {"bin", PERM_DIR_BIN, PERM_OWNER_ROOT, (PERM_BASE | PERM_EXECUTE), PERM_SMACK_0},
463 {"info", PERM_DIR_INFO, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
464 {"lib", PERM_DIR_LIB, PERM_OWNER_ROOT, (PERM_BASE | PERM_EXECUTE), PERM_SMACK_0},
465 {"setting", PERM_DIR_SETTING, PERM_OWNER_ROOT, (PERM_BASE | PERM_WRITE), PERM_SMACK_0},
466 {"shared/res", PERM_DIR_SHARED_RES, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
467 {"shared/data", PERM_DIR_SHARED_DATA, PERM_OWNER_APP, PERM_BASE, PERM_SMACK_0},
468 {"shared/trusted", PERM_DIR_SHARED_TRUSTED, PERM_OWNER_APP, PERM_BASE, PERM_SMACK_0},
469 {"shared", PERM_DIR_SHARED, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
470 {"author", PERM_DIR_ROOT, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
471 {"signature", PERM_DIR_ROOT, PERM_OWNER_ROOT, PERM_BASE, PERM_SMACK_0},
474 static int permCount = sizeof(perms) / sizeof(RdsPermssions);
475 bool isInstallRequired = false;
476 SmackManager smackManager;
477 smackManager.Construct(pContext);
479 for (int i = 0; i < pFileList->GetCount(); i++)
481 const String *pFilePath = static_cast<const String *>(pFileList->GetAt(i));
482 TryReturn(pFilePath, false, "pFilePath is null");
484 AppLog("pFilePath=(%ls)", pFilePath->GetPointer());
487 for (permIdx = 0; permIdx < permCount; permIdx++)
489 if (pFilePath->StartsWith(perms[permIdx].pDir, 0) == true)
491 if (perms[permIdx].dirType == PERM_DIR_INFO)
493 if (*pFilePath == L"info/manifest.xml")
495 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
496 isInstallRequired = true;
499 else if (perms[permIdx].dirType == PERM_DIR_SETTING)
501 if (pFilePath->StartsWith("setting/setting", 0) == true)
503 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
504 isInstallRequired = true;
508 AppLog("dirType=(%d), owner=(%d), mode=(%d), smack=(%d)",
509 perms[permIdx].dirType, perms[permIdx].ownerIndex, perms[permIdx].modeIndex, perms[permIdx].smackIndex);
511 String srcFile = DIR_APPLICATIONS_TMP;
512 srcFile += L"/" + pContext->__packageId + L"/" + *pFilePath;
513 String destFile = pContext->__rootPath + L"/" + *pFilePath;
515 AppLog("copy file: from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
516 File::Copy(srcFile, destFile, false);
518 bool isAppOwner = false;
519 if (perms[permIdx].ownerIndex == PERM_OWNER_APP)
525 if (perms[permIdx].dirType != PERM_DIR_ROOT)
527 destPath = pContext->__rootPath + L"/" + perms[permIdx].pDir;
528 InstallerUtil::ChangeDirectoryPermission(destPath, perms[permIdx].modeIndex, isAppOwner);
532 destPath = pContext->__rootPath + L"/" + *pFilePath;
533 InstallerUtil::ChangeMode(*pFilePath, perms[permIdx].modeIndex);
535 smackManager.AddLabelSharedDir(pContext->__packageId, destPath);