fixed failed update preload web app
[platform/framework/web/wrt-installer.git] / src / jobs / widget_install / task_smack.cpp
1 /*
2  * Copyright (c) 2011 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  * @file    task_smack.cpp
18  * @author  Piotr Kozbial (p.kozbial@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for installer task smack
21  */
22
23 #include <widget_install/task_smack.h>
24 #include <widget_install/widget_install_context.h>
25 #include <widget_install/widget_install_errors.h>
26 #include <widget_install/job_widget_install.h>
27 #include <dpl/wrt-dao-ro/common_dao_types.h>
28 #include <dpl/foreach.h>
29 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
30 #include <dpl/utils/bash_utils.h>
31 #include <vcore/Certificate.h>
32 #include <vcore/CryptoHash.h>
33 #ifdef WRT_SMACK_ENABLED
34 #include <privilege-control.h>
35 #include <sys/smack.h>
36 #endif
37 #include <sstream>
38
39 using namespace WrtDB;
40 using namespace ValidationCore;
41
42 namespace {
43 const int MAX_BUF_SIZE = 128;
44 void freeList(const char** list) {
45     for (int i = 0; list[i] != NULL; i++)
46     {
47         delete(list[i]);
48     }
49     delete[] list;
50 }
51 }
52
53 namespace Jobs {
54 namespace WidgetInstall {
55 TaskSmack::TaskSmack(InstallerContext& context) :
56     DPL::TaskDecl<TaskSmack>(this),
57     m_context(context),
58     m_pkgId(NULL)
59 {
60     if (!m_context.isUpdateMode) {
61         AddStep(&TaskSmack::StepSetInstall);
62         AddStep(&TaskSmack::StepSmackFolderLabeling);
63         AddStep(&TaskSmack::StepSmackPrivilege);
64     } else {
65         AddStep(&TaskSmack::StepSmackPrivilege);
66     }
67     AddStep(&TaskSmack::StepSetEndofInstallation);
68
69     AddAbortStep(&TaskSmack::StepAbortSmack);
70 }
71
72 void TaskSmack::StepSetInstall()
73 {
74     LogInfo("----------------> SMACK: StepStartSetSmack()");
75 #ifdef WRT_SMACK_ENABLED
76     std::string pkg = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
77     m_pkgId = (char*)calloc(1, pkg.length() + 1);
78     snprintf(m_pkgId, pkg.length() + 1, "%s", pkg.c_str());
79
80     if (m_context.widgetConfig.packagingType !=
81             WrtDB::PkgType::PKG_TYPE_HYBRID_WEB_APP)
82     {
83             if (PC_OPERATION_SUCCESS != app_install(m_pkgId)) {
84             free(m_pkgId);
85             ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
86                     "failure in creating smack rules file.");
87         }
88     }
89 #endif
90 }
91
92 void TaskSmack::StepSmackFolderLabeling()
93 {
94     LogInfo("----------------> SMACK:\
95             Jobs::WidgetInstall::TaskSmack::SmackFolderLabelingStep()");
96 #ifdef WRT_SMACK_ENABLED
97     /* /opt/usr/apps/[pkgid] directory's label is "_" */
98     if (PC_OPERATION_SUCCESS != app_label_dir("_",
99                 m_context.locations->getPackageInstallationDir().c_str())) {
100         free(m_pkgId);
101         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
102                 "Add Label failure");
103     }
104
105     /* res directory */
106     std::string resDir = m_context.locations->getPackageInstallationDir() +
107         "/res";
108     if (PC_OPERATION_SUCCESS != app_label_dir(m_pkgId,
109                 resDir.c_str())) {
110         free(m_pkgId);
111         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
112                 "Add Label failure");
113     }
114
115     /* for prealod */
116     if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD)
117     {
118         if (PC_OPERATION_SUCCESS != app_label_dir("_",
119                     m_context.locations->getUserDataRootDir().c_str())) {
120             free(m_pkgId);
121             ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
122                     "Add Label failure");
123         }
124     }
125
126     /* data directory */
127     if (PC_OPERATION_SUCCESS != app_label_dir(m_pkgId,
128                 m_context.locations->getPrivateStorageDir().c_str())) {
129         free(m_pkgId);
130         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
131                 "Add Label failure");
132     }
133
134     /* bin directory */
135     if (PC_OPERATION_SUCCESS != app_label_dir(m_pkgId,
136                 m_context.locations->getBinaryDir().c_str())) {
137         free(m_pkgId);
138         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
139                 "Add Label failure");
140     }
141
142     if(!setLabelForSharedDir(m_pkgId)) {
143         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
144                 "Add Label failure");
145     }
146
147     free(m_pkgId);
148
149     /* TODO : set label at wrt-client 
150
151     std::string app = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
152     char* appId = NULL;
153     appId = (char*)calloc(1, app.length() + 1);
154     snprintf(appId, app.length() + 1, "%s", app.c_str());
155
156     if (0 != smack_lsetlabel(m_context.locations->getExecFile().c_str(),
157                 appId, SMACK_LABEL_ACCESS)) {
158         free(m_pkgId);
159         free(appId);
160         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
161                 "Add ACESS Label for binary failure");
162     }
163
164     if (0 != smack_lsetlabel(m_context.locations->getExecFile().c_str(),
165                 appId, SMACK_LABEL_EXEC)) {
166         free(m_pkgId);
167         free(appId);
168         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
169                 "Add EXEC Label for binary failure");
170     }
171
172    if (PC_OPERATION_SUCCESS != app_add_friend(m_pkgId, appId)) {
173         free(m_pkgId);
174         free(appId);
175         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
176                 "Add friend failure");
177    }
178
179     if (PC_OPERATION_SUCCESS != app_label_shared_dir(appId, m_pkgId,
180                 m_context.locations->getBinaryDir().c_str())) {
181         free(m_pkgId);
182         free(appId);
183         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
184                 "Add Label failure");
185     }
186     */
187 #endif
188 }
189
190 void TaskSmack::StepSmackPrivilege()
191 {
192     LogInfo("----------------> SMACK:\
193             Jobs::WidgetInstall::TaskSmack::SmackPrivilegeStep()");
194 #ifdef WRT_SMACK_ENABLED
195     /* TODO : 
196     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
197     */
198     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
199     char* appId = NULL;
200     appId = (char*)calloc(1, id.length() + 1);
201     snprintf(appId, id.length() + 1, "%s", id.c_str());
202
203     WrtDB::ConfigParserData::PrivilegeList privileges =
204         m_context.widgetConfig.configInfo.privilegeList;
205
206     const char** perm_list = new const char*[privileges.size() + 1];
207     int index = 0;
208     FOREACH(it, privileges) {
209         LogInfo("Permission : " << it->name);
210         int length = DPL::ToUTF8String(it->name).length();
211         char *priv = (char*) calloc(1, (sizeof(char) * length) + 1);
212         snprintf(priv, length + 1, "%s",
213                 DPL::ToUTF8String(it->name).c_str());
214         perm_list[index++] = priv;
215     }
216     perm_list[index] = NULL;
217
218     if (PC_OPERATION_SUCCESS != app_enable_permissions(appId, APP_TYPE_WGT,
219                 perm_list, true)) {
220         LogError("failure in contructing smack rules based on perm_list");
221     }
222
223     free(appId);
224
225     m_context.job->UpdateProgress(
226         InstallerContext::INSTALL_SMACK_ENABLE,
227         "Widget SMACK Enabled");
228 #endif
229 }
230
231 void TaskSmack::StepRevokeForUpdate()
232 {
233     LogInfo("----------------> SMACK:\
234             Jobs::WidgetInstall::TaskSmack::StepRevokePrivilegeForUpdate()");
235 #ifdef WRT_SMACK_ENABLED
236     if (PC_OPERATION_SUCCESS != app_revoke_permissions(m_pkgId)) {
237         LogError("failure in revoking smack permissions");
238     }
239 #endif
240 }
241
242 void TaskSmack::StepAbortSmack()
243 {
244     LogInfo("----------------> SMACK:\
245             Jobs::WidgetInstall::TaskSmack::StepAbortSmack()");
246 #ifdef WRT_SMACK_ENABLED
247     /* TODO :
248     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
249     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
250     char* appId = NULL;
251     appId = (char*)calloc(1, id.length() + 1);
252     snprintf(appId, id.length() + 1, "%s", id.c_str());
253     */
254
255     if (PC_OPERATION_SUCCESS != app_revoke_permissions(m_pkgId)) {
256         LogError("failure in revoking smack permissions");
257     }
258
259     if (PC_OPERATION_SUCCESS != app_uninstall(m_pkgId)) {
260         LogError("failure in removing smack rules file");
261     }
262     free(m_pkgId);
263 #endif
264 }
265
266 void TaskSmack::StepSetEndofInstallation()
267 {
268     m_context.job->UpdateProgress(
269         InstallerContext::INSTALL_END,
270         "End installation");
271 }
272
273 bool TaskSmack::setLabelForSharedDir(const char* pkgId)
274 {
275     /* shared directory */
276     if (PC_OPERATION_SUCCESS != app_label_dir("*",
277                 m_context.locations->getSharedRootDir().c_str())) {
278         return false;
279     }
280
281     /* shared/res directory */
282     if (PC_OPERATION_SUCCESS != app_label_dir("_",
283                 m_context.locations->getSharedResourceDir().c_str())) {
284         return false;
285     }
286
287     /* shared/trusted directory */
288     CertificatePtr rootCert = m_context.wacSecurity.getAuthorCertificatePtr();
289     if (rootCert.Get() != NULL) {
290         ValidationCore::Crypto::Hash::SHA1 sha1;
291         sha1.Append(rootCert->getDER());
292         sha1.Finish();
293         std::string sha1String = sha1.ToBase64String();
294         size_t iPos = sha1String.find("/");
295         while(iPos < std::string::npos) {
296             sha1String.replace(iPos, 1, "#");
297             iPos = sha1String.find("/");
298         }
299
300         LogDebug("sha1 label string : " << sha1String);
301
302         if (PC_OPERATION_SUCCESS != app_label_shared_dir(pkgId,
303                     sha1String.c_str(),
304                     m_context.locations->getSharedTrustedDir().c_str())) {
305             return false;
306         }
307     }
308
309     /* shared/data directory */
310     std::string dataLabel = std::string(pkgId) + "_shareddata";
311     TizenPkgIdList pkgList = WidgetDAOReadOnly::getTizenPkgidList();
312     const char** pList = new (std::nothrow) const char*[pkgList.size() + 1];
313
314     int index = 0;
315     FOREACH(app, pkgList) {
316         std::string id = DPL::ToUTF8String(*app);
317         char *pId = new char[id.size() + 1];
318         snprintf(pId, id.length() + 1, "%s", id.c_str());
319         pList[index++] = pId;
320     }
321
322     pList[index] = NULL;
323     if (PC_OPERATION_SUCCESS != app_label_shared_dir(pkgId,
324                 dataLabel.c_str(),
325                 m_context.locations->getSharedDataDir().c_str())) {
326         freeList(pList);
327         return false;
328     }
329     if (PC_OPERATION_SUCCESS != add_shared_dir_readers(dataLabel.c_str(), pList)) {
330         freeList(pList);
331         return false;
332     }
333     if (PC_OPERATION_SUCCESS != app_label_shared_dir(pkgId,
334                 "*",
335                 m_context.locations->getSharedDataDir().c_str())) {
336         freeList(pList);
337         return false;
338     }
339     freeList(pList);
340     return true;
341 }
342 } //namespace WidgetInstall
343 } //namespace Jobs