Set Capability for RDS
[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, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_PRIVATE);
88
89         // appRoot/info
90         destPath = appRootPath + DIR_INFO;
91         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
92         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
93
94         // appRoot/res
95         destPath = appRootPath + DIR_RES;
96         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
97         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
98
99         // appRoot/lib
100         destPath = appRootPath + DIR_LIB;
101         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
102         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_GROUP_RW);
131
132         // appRoot/contents
133         destPath = appRootPath + DIR_CONTENTS;
134         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
135         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_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, SMACK_DIR_TYPE_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                 AppLog("copy file from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
304
305                 int pos = 0;
306                 result r = E_SUCCESS;
307                 String destDir;
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                 r = File::Copy(srcFile, destFile, true);
335                 if (IsFailed(r) == true)
336                 {
337                         AppLog("File::Copy() failed. [%ls] -> [%ls]", srcFile.GetPointer(), destFile.GetPointer());
338                         continue;
339                 }
340
341                 if ((destFile.Contains(pContext->__packageId + DIR_BIN) == true) && (destFile.EndsWith(L".exe") == true))
342                 {
343                         SetFileCapability(destFile, pContext);
344                 }
345
346                 if (*pFilePath == L"info/manifest.xml")
347                 {
348                         AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
349                         isInstallRequired = true;
350                 }
351                 else if (pFilePath->StartsWith("setting/setting", 0) == true)
352                 {
353                         AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
354                         isInstallRequired = true;
355                 }
356         }
357
358         return true;
359 }
360
361 bool
362 PermissionManager::ApplyPermissionForRds(InstallationContext* pContext)
363 {
364         String destPath;
365         String appRootPath;
366         SmackManager smackManager;
367         smackManager.Construct(pContext);
368
369         appRootPath = pContext->__rootPath;
370         PackageId packageId = pContext->__packageId;
371
372         // appRoot
373         InstallerUtil::ChangeMode(appRootPath, PERM_BASE | PERM_EXECUTE);
374         smackManager.SetupPath(packageId, appRootPath, SMACK_DIR_TYPE_ANY_LABEL, L"_");
375
376         // appRoot/bin
377         destPath = appRootPath + DIR_BIN;
378         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
379         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
380
381         // appRoot/info
382         destPath = appRootPath + DIR_INFO;
383         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
384         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
385
386         // appRoot/res
387         destPath = appRootPath + DIR_RES;
388         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
389         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
390
391         // appRoot/lib
392         destPath = appRootPath + DIR_LIB;
393         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_EXECUTE, false);
394         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
395
396         // appRoot/shared
397         destPath = appRootPath + DIR_SHARED;
398         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
399
400         // appRoot/shared/res
401         destPath = appRootPath + DIR_SHARED_RES;
402         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, false);
403
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);
408
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);
413
414         // appRoot/setting
415         destPath = appRootPath + DIR_SETTING;
416         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE | PERM_WRITE, false);
417         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_SETTINGS_RW);
418
419         // appRoot/data
420         destPath = appRootPath + DIR_DATA;
421         InstallerUtil::ChangeDirectoryPermission(destPath, PERM_BASE, true);
422         smackManager.SetupPath(packageId, destPath, SMACK_DIR_TYPE_PRIVATE);
423
424         return true;
425 }
426
427 bool
428 PermissionManager::SetFileCapability(const String& path, InstallationContext* pContext)
429 {
430         TryReturn(path.IsEmpty() == false, false, "path is empty.");
431         TryReturn(pContext, false, "pContext is null.");
432
433         if (pContext->__isPreloaded == true)
434         {
435                 AppLog("cap_set_file() is skipped.");
436                 return true;
437         }
438
439         std::unique_ptr<char[]> pPath(_StringConverter::CopyToCharArrayN(path));
440         TryReturn(pPath != null, false, "The memory is insufficient.");
441
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);
444
445         AppLog("cap_set_file(%s, cap_from_text(CAP_NET_RAW,CAP_SYS_CHROOT+i)) called.", pPath.get());
446
447         return true;
448 }
449
450 #if 0
451 bool
452 PermissionManager::ApplyPermission(InstallationContext* pContext, const IList* pFileList)
453 {
454         TryReturn(pContext, false, "pContext is null");
455         TryReturn(pFileList, false, "pFileList is null");
456
457         // dir | type | owner | mode | smack
458         static RdsPermssions perms[] =
459         {
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},
472         };
473
474         static int permCount = sizeof(perms) / sizeof(RdsPermssions);
475         bool isInstallRequired = false;
476         SmackManager smackManager;
477         smackManager.Construct(pContext);
478
479         for (int i = 0; i < pFileList->GetCount(); i++)
480         {
481                 const String *pFilePath = static_cast<const String *>(pFileList->GetAt(i));
482                 TryReturn(pFilePath, false, "pFilePath is null");
483
484                 AppLog("pFilePath=(%ls)", pFilePath->GetPointer());
485
486                 int permIdx = 0;
487                 for (permIdx = 0; permIdx < permCount; permIdx++)
488                 {
489                         if (pFilePath->StartsWith(perms[permIdx].pDir, 0) == true)
490                         {
491                                 if (perms[permIdx].dirType == PERM_DIR_INFO)
492                                 {
493                                         if (*pFilePath == L"info/manifest.xml")
494                                         {
495                                                 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
496                                                 isInstallRequired = true;
497                                         }
498                                 }
499                                 else if (perms[permIdx].dirType == PERM_DIR_SETTING)
500                                 {
501                                         if (pFilePath->StartsWith("setting/setting", 0) == true)
502                                         {
503                                                 AppLog("Install required, [%ls] is found", pFilePath->GetPointer());
504                                                 isInstallRequired = true;
505                                         }
506                                 }
507
508                                 AppLog("dirType=(%d), owner=(%d), mode=(%d), smack=(%d)",
509                                                 perms[permIdx].dirType, perms[permIdx].ownerIndex, perms[permIdx].modeIndex, perms[permIdx].smackIndex);
510
511                                 String srcFile = DIR_APPLICATIONS_TMP;
512                                 srcFile += L"/" + pContext->__packageId + L"/" + *pFilePath;
513                                 String destFile = pContext->__rootPath + L"/" + *pFilePath;
514
515                                 AppLog("copy file: from[%ls] to[%ls]", srcFile.GetPointer(), destFile.GetPointer());
516                                 File::Copy(srcFile, destFile, false);
517
518                                 bool isAppOwner = false;
519                                 if (perms[permIdx].ownerIndex == PERM_OWNER_APP)
520                                 {
521                                         isAppOwner = true;
522                                 }
523
524                                 String destPath;
525                                 if (perms[permIdx].dirType != PERM_DIR_ROOT)
526                                 {
527                                         destPath = pContext->__rootPath + L"/" + perms[permIdx].pDir;
528                                         InstallerUtil::ChangeDirectoryPermission(destPath, perms[permIdx].modeIndex, isAppOwner);
529                                 }
530                                 else
531                                 {
532                                         destPath = pContext->__rootPath + L"/" + *pFilePath;
533                                         InstallerUtil::ChangeMode(*pFilePath, perms[permIdx].modeIndex);
534                                 }
535                                 smackManager.AddLabelSharedDir(pContext->__packageId, destPath);
536
537                                 break;
538                         }
539                 }
540         }
541
542         return true;
543 }
544 #endif
545
546