Osp-Installer merge changes from tizen_2.2
[platform/framework/native/installer.git] / src / Manager / PermissionManager.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
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
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
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.
16 //
17 /**
18  * @file        PermissionManager.cpp
19  * @brief       This is the implementation file for %PermissionManager class.
20  */
21
22 #include <stdio.h>
23 #include <sys/stat.h>
24 #include <sys/capability.h>
25 #include <unistd.h>
26 #include <unique_ptr.h>
27
28 #include <FBaseUtilStringUtil.h>
29 #include <FIoFile.h>
30 #include <FIoDirectory.h>
31 #include <FBase_StringConverter.h>
32 #include <FIo_FileImpl.h>
33
34 #include "PermissionManager.h"
35 #include "InstallerUtil.h"
36 #include "SmackManager.h"
37 #include "CompatibilityManager.h"
38
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;
44
45 PermissionManager::PermissionManager(void)
46 {
47 }
48
49 PermissionManager::~PermissionManager(void)
50 {
51 }
52
53 bool
54 PermissionManager::SetDirectory(InstallationContext* pContext)
55 {
56         result r = E_SUCCESS;
57         bool res = true;
58
59         String destPath;
60         String appRootPath;
61         SmackManager smackManager;
62         smackManager.Construct(pContext);
63
64         CompatibilityManager compatibilityManager;
65         compatibilityManager.Construct(pContext);
66
67         appRootPath = pContext->__rootPath;
68         PackageId packageId = pContext->__packageId;
69
70         // appRoot
71         // InstallerUtil::ChangeOwner(appRootPath);
72         InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
73         smackManager.SetupPath(packageId, appRootPath, APP_PATH_ANY_LABEL, L"_");
74
75         if (pContext->__isPreloaded == true)
76         {
77                 String preloadedAppPath(PATH_USR_APPS);
78                 preloadedAppPath += L"/";
79                 preloadedAppPath += packageId;
80
81                 smackManager.SetupPath(packageId, preloadedAppPath, APP_PATH_ANY_LABEL, L"_");
82         }
83
84         // appRoot/bin
85         destPath = appRootPath + DIR_BIN;
86         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
87         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
88
89         // appRoot/info
90         destPath = appRootPath + DIR_INFO;
91         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
92         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
93
94         // appRoot/res
95         destPath = appRootPath + DIR_RES;
96         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
97         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
98
99         // appRoot/lib
100         destPath = appRootPath + DIR_LIB;
101         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
102         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
103
104         // appRoot/shared
105         destPath = appRootPath + DIR_SHARED;
106         if (File::IsFileExist(destPath) == false)
107         {
108                 r = Directory::Create(destPath, false);
109                 TryReturn(!IsFailed(r), INSTALLER_ERROR_INTERNAL_STATE, "Directory::Create() failed");
110         }
111         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
112
113         // appRoot/shared/res
114         destPath = appRootPath + DIR_SHARED_RES;
115         if (File::IsFileExist(destPath) == false)
116         {
117                 String iconPath = appRootPath + DIR_ICONS;
118                 InstallerUtil::CreateSymlink(iconPath, destPath);
119         }
120         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
121
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);
126
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);
131
132         // appRoot/contents
133         destPath = appRootPath + DIR_CONTENTS;
134         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
135         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
136
137         // appRoot/setting
138         destPath = appRootPath + DIR_SETTING;
139         if (File::IsFileExist(destPath) == true)
140         {
141                 String appVersion = pContext->__version;
142                 String srcPath;
143                 String settingXmlPath;
144                 srcPath = destPath + L"/setting." + appVersion + L".xml";
145                 settingXmlPath = destPath + L"/setting.xml";
146
147                 InstallerUtil::Remove(settingXmlPath);
148                 InstallerUtil::CreateSymlink(srcPath, settingXmlPath);
149
150                 InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
151                 smackManager.SetupPath(packageId, destPath, APP_PATH_SETTINGS_RW);
152         }
153
154         // appRoot/data
155         destPath = appRootPath + DIR_DATA;
156         if (File::IsFileExist(destPath) == false)
157         {
158                 r = Directory::Create(destPath, false);
159                 TryReturn(!IsFailed(r), false, "Directory::Create() failed");
160         }
161         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
162
163         // appRoot/data/[virtualRoot]
164         if (pContext->__virtualRootPath.IsEmpty() == false)
165         {
166                 res = compatibilityManager.PrepareVirtualRoot(appRootPath, packageId);
167                 TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.PrepareVirtualRoot(%ls) failed.", appRootPath.GetPointer());
168         }
169         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
170
171         String apiVersion = pContext->__apiVersion;
172
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());
177
178         if (pContext->__isOspCompat == true)
179         {
180                 AppLog("[Tizen::Io] OSP 2.0 application");
181
182                 res = compatibilityManager.PrepareDataCaging(appRootPath, packageId);
183                 TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.PrepareDataCaging() failed.");
184
185                 SetSymLink(pContext);
186         }
187         else
188         {
189                 AppLog("[Tizen::Io] apiVersion is equal to or greater than Tizen 2.0");
190
191                 res = compatibilityManager.CleanDirectories(appRootPath, packageId);
192                 TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.CleanDirectories() failed.");
193
194                 res = compatibilityManager.LinkOspSharePath(appRootPath, packageId);
195                 TryReturn(res == true, false, "[Tizen::Io] compatibilityManager.LinkOspSharePath() failed.");
196         }
197
198         AppLog("------------------------------------------");
199
200         return true;
201 }
202
203 bool
204 PermissionManager::SetFile(InstallationContext* pContext)
205 {
206         String destPath;
207         String appRootPath = pContext->__rootPath;
208
209         IListT<AppData*>* pAppDataList = pContext->__pAppDataList;
210         TryReturn(pAppDataList, false, "pAppDataList is null.");
211
212         for (int i = 0 ; i < pAppDataList->GetCount(); i++)
213         {
214                 AppData* pAppData = null;
215                 pAppDataList->GetAt(i, pAppData);
216                 TryReturn(pAppData, false, "pAppData is null.");
217
218                 String loader = appRootPath + DIR_BIN + L"/" + pAppData->__name;
219                 if (File::IsFileExist(loader) == true)
220                 {
221                         SetFileCapability(loader, pContext);
222                 }
223
224                 // set permission(755) to bin file.
225                 destPath = appRootPath + DIR_BIN + L"/" + pAppData->__name + L".exe";
226                 if (File::IsFileExist(destPath) == true)
227                 {
228                         SetFileCapability(destPath, pContext);
229                         InstallerUtil::ChangeMode(destPath, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
230                 }
231         }
232
233         return true;
234 }
235
236 bool
237 PermissionManager::SetSymLink(InstallationContext* pContext)
238 {
239         bool res = true;
240         int result = 0;
241         char* pCwd = null;
242         String oldPath;
243         String newPath;
244         String appRootPath = pContext->__rootPath;
245
246         std::unique_ptr<char[]> pRootPath(_StringConverter::CopyToCharArrayN(appRootPath));
247         TryCatch(pRootPath != null, res = false, "The memory is insufficient.");
248
249         pCwd = get_current_dir_name();
250         TryCatch(pCwd != null, res = false, "get_current_dir_name() failed.");
251
252         result = chdir(pRootPath.get());
253         TryCatch(result == 0, res = false, "chdir(%s) failed.", pRootPath.get());
254
255         newPath = appRootPath + L"/Res";
256         InstallerUtil::CreateSymlink(L"./res", newPath, false);
257
258         newPath = appRootPath + L"/Home";
259         InstallerUtil::CreateSymlink(L"./data", newPath, false);
260
261         result = chdir(pCwd);
262         TryCatch(result == 0, res = false, "chdir(%s) failed.", pCwd);
263
264         oldPath = appRootPath + DIR_RES + L"/screen-size-normal";
265         newPath = appRootPath + L"/Res/ScreenSize-Normal";
266         InstallerUtil::CreateSymlink(oldPath, newPath, false);
267
268         oldPath = appRootPath + DIR_RES + L"/screen-density-high";
269         newPath = appRootPath + L"/Res/ScreenDensity-High";
270         InstallerUtil::CreateSymlink(oldPath, newPath, false);
271
272         oldPath = appRootPath + DIR_RES + L"/screen-density-middle";
273         newPath = appRootPath + L"/Res/ScreenDensity-Middle";
274         InstallerUtil::CreateSymlink(oldPath, newPath, false);
275
276         oldPath = appRootPath + DIR_RES + L"/screen-density-low";
277         newPath = appRootPath + L"/Res/ScreenDensity-Low";
278         InstallerUtil::CreateSymlink(oldPath, newPath, false);
279
280 CATCH:
281         if (pCwd)
282         {
283                 free(pCwd);
284         }
285
286         return res;
287 }
288
289 bool
290 PermissionManager::CopyForRds(InstallationContext* pContext, IList* pFileList, bool& isInstallRequired)
291 {
292         TryReturn(pFileList, false, "pFileList is null.");
293
294         for (int idx = 0; idx < pFileList->GetCount(); idx++)
295         {
296                 String* pFilePath = static_cast<String *>(pFileList->GetAt(idx));
297                 TryReturn(pFilePath, false, "pFilePath is null.");
298
299                 String srcFile = DIR_APPLICATIONS_TMP;
300                 srcFile += L"/" + pContext->__packageId + L"/" + *pFilePath;
301                 String destFile = pContext->__rootPath + L"/" + *pFilePath;
302
303                 int pos = 0;
304                 result r = E_SUCCESS;
305                 String destDir;
306
307                 AppLog("copy file from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
308
309                 if (destFile.EndsWith(L"/") == true)
310                 {
311                         destDir = destFile;
312                         if (File::IsFileExist(destDir) == false)
313                         {
314                                 Directory::Create(destDir, true);
315                         }
316                         continue;
317                 }
318                 else
319                 {
320                         r = destFile.LastIndexOf(L'/', destFile.GetLength() -1, pos);
321                         if (IsFailed(r) == true)
322                         {
323                                 AppLog("destFile is invalid[%ls]", destFile.GetPointer());
324                                 continue;
325                         }
326                         destFile.SubString(0, pos, destDir);
327                 }
328
329                 if (File::IsFileExist(destDir) == false)
330                 {
331                         Directory::Create(destDir, true);
332                 }
333                 InstallerUtil::Remove(destFile);
334
335                 r = File::Copy(srcFile, destFile, true);
336                 TryReturn(!IsFailed(r), false, "File::Copy() failed, [%ls] -> [%ls]", srcFile.GetPointer(), destFile.GetPointer());
337
338                 AppLog("copy file from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
339
340                 if ((destFile.Contains(pContext->__packageId + DIR_BIN) == true) && (destFile.EndsWith(L".exe") == true))
341                 {
342                         SetFileCapability(destFile, pContext);
343                 }
344
345                 if (*pFilePath == L"info/manifest.xml")
346                 {
347                         AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
348                         isInstallRequired = true;
349                 }
350                 else if (pFilePath->StartsWith("setting/setting", 0) == true)
351                 {
352                         AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
353                         isInstallRequired = true;
354                 }
355         }
356
357         return true;
358 }
359
360 bool
361 PermissionManager::ApplyPermissionForRds(InstallationContext* pContext)
362 {
363         String destPath;
364         String appRootPath;
365         SmackManager smackManager;
366         smackManager.Construct(pContext);
367
368         appRootPath = pContext->__rootPath;
369         PackageId packageId = pContext->__packageId;
370
371         // appRoot
372         InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
373         smackManager.SetupPath(packageId, appRootPath, APP_PATH_ANY_LABEL, L"_");
374
375         // appRoot/bin
376         destPath = appRootPath + DIR_BIN;
377         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
378         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
379
380         // appRoot/info
381         destPath = appRootPath + DIR_INFO;
382         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
383         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
384
385         // appRoot/res
386         destPath = appRootPath + DIR_RES;
387         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
388         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
389
390         // appRoot/lib
391         destPath = appRootPath + DIR_LIB;
392         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
393         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
394
395         // appRoot/shared
396         destPath = appRootPath + DIR_SHARED;
397         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
398
399         // appRoot/shared/res
400         destPath = appRootPath + DIR_SHARED_RES;
401         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
402
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);
407
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);
412
413         // appRoot/setting
414         destPath = appRootPath + DIR_SETTING;
415         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
416         smackManager.SetupPath(packageId, destPath, APP_PATH_SETTINGS_RW);
417
418         // appRoot/data
419         destPath = appRootPath + DIR_DATA;
420         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
421         smackManager.SetupPath(packageId, destPath, APP_PATH_PRIVATE);
422
423         return true;
424 }
425
426 bool
427 PermissionManager::SetFileCapability(const String& path, InstallationContext* pContext)
428 {
429         TryReturn(path.IsEmpty() == false, false, "path is empty.");
430         TryReturn(pContext, false, "pContext is null.");
431
432         if (pContext->__isPreloaded == true)
433         {
434                 AppLog("cap_set_file() is skipped.");
435                 return true;
436         }
437
438         std::unique_ptr<char[]> pPath(_StringConverter::CopyToCharArrayN(path));
439         TryReturn(pPath != null, false, "The memory is insufficient.");
440
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);
443
444         AppLog("cap_set_file(%s, cap_from_text(CAP_NET_RAW,CAP_SYS_CHROOT+i)) called.", pPath.get());
445
446         return true;
447 }
448
449 #if 0
450 bool
451 PermissionManager::ApplyPermission(InstallationContext* pContext, const IList* pFileList)
452 {
453         TryReturn(pContext, false, "pContext is null");
454         TryReturn(pFileList, false, "pFileList is null");
455
456         // dir | type | owner | mode | smack
457         static RdsPermssions perms[] =
458         {
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},
471         };
472
473         static int permCount = sizeof(perms) / sizeof(RdsPermssions);
474         bool isInstallRequired = false;
475         SmackManager smackManager;
476         smackManager.Construct(pContext);
477
478         for (int i = 0; i < pFileList->GetCount(); i++)
479         {
480                 const String *pFilePath = static_cast<const String *>(pFileList->GetAt(i));
481                 TryReturn(pFilePath, false, "pFilePath is null");
482
483                 AppLog("pFilePath=(%ls)", pFilePath->GetPointer());
484
485                 int permIdx = 0;
486                 for (permIdx = 0; permIdx < permCount; permIdx++)
487                 {
488                         if (pFilePath->StartsWith(perms[permIdx].pDir, 0) == true)
489                         {
490                                 if (perms[permIdx].dirType == PERM_DIR_INFO)
491                                 {
492                                         if (*pFilePath == L"info/manifest.xml")
493                                         {
494                                                 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
495                                                 isInstallRequired = true;
496                                         }
497                                 }
498                                 else if (perms[permIdx].dirType == PERM_DIR_SETTING)
499                                 {
500                                         if (pFilePath->StartsWith("setting/setting", 0) == true)
501                                         {
502                                                 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
503                                                 isInstallRequired = true;
504                                         }
505                                 }
506
507                                 AppLog("dirType=(%d), owner=(%d), mode=(%d), smack=(%d)",
508                                                 perms[permIdx].dirType, perms[permIdx].ownerIndex, perms[permIdx].modeIndex, perms[permIdx].smackIndex);
509
510                                 String srcFile = DIR_APPLICATIONS_TMP;
511                                 srcFile += L"/" + pContext->__packageId + L"/" + *pFilePath;
512                                 String destFile = pContext->__rootPath + L"/" + *pFilePath;
513
514                                 AppLog("copy file: from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
515                                 File::Copy(srcFile, destFile, false);
516
517                                 bool isAppOwner = false;
518                                 if (perms[permIdx].ownerIndex == PERM_OWNER_APP)
519                                 {
520                                         isAppOwner = true;
521                                 }
522
523                                 String destPath;
524                                 if (perms[permIdx].dirType != PERM_DIR_ROOT)
525                                 {
526                                         destPath = pContext->__rootPath + L"/" + perms[permIdx].pDir;
527                                         InstallerUtil::ChangeDirectoryPermission(destPath, perms[permIdx].modeIndex, isAppOwner);
528                                 }
529                                 else
530                                 {
531                                         destPath = pContext->__rootPath + L"/" + *pFilePath;
532                                         InstallerUtil::ChangeMode(*pFilePath, perms[permIdx].modeIndex);
533                                 }
534                                 smackManager.AddLabelSharedDir(pContext->__packageId, destPath);
535
536                                 break;
537                         }
538                 }
539         }
540
541         return true;
542 }
543 #endif
544
545