[Release] wrt-installer_0.1.58
[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 {
59     AddStep(&TaskSmack::SmackFolderLabelingStep);
60     AddStep(&TaskSmack::SmackPrivilegeStep);
61     AddStep(&TaskSmack::SetEndofInstallation);
62
63     AddAbortStep(&TaskSmack::StepAbortSmack);
64 }
65
66 void TaskSmack::SmackFolderLabelingStep()
67 {
68     LogInfo("----------------> SMACK:\
69             Jobs::WidgetInstall::TaskSmack::SmackFolderLabelingStep()");
70 #ifdef WRT_SMACK_ENABLED
71     std::string pkg = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
72     char* pkgId = NULL;
73     pkgId = (char*)calloc(1, pkg.length() + 1);
74     snprintf(pkgId, pkg.length() + 1, "%s", pkg.c_str());
75
76     if (m_context.widgetConfig.packagingType !=
77             WrtDB::PkgType::PKG_TYPE_HYBRID_WEB_APP)
78     {
79             if (PC_OPERATION_SUCCESS != app_install(pkgId)) {
80             free(pkgId);
81             ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
82                     "failure in creating smack rules file.");
83         }
84     }
85
86     /* /opt/usr/apps/[pkgid] directory's label is "_" */
87     if (PC_OPERATION_SUCCESS != app_label_dir("_",
88                 m_context.locations->getPackageInstallationDir().c_str())) {
89         free(pkgId);
90         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
91                 "Add Label failure");
92     }
93
94     /* res directory */
95     std::string resDir = m_context.locations->getPackageInstallationDir() +
96         "/res";
97     if (PC_OPERATION_SUCCESS != app_label_dir(pkgId,
98                 resDir.c_str())) {
99         free(pkgId);
100         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
101                 "Add Label failure");
102     }
103
104     /* for prealod */
105     if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD)
106     {
107         if (PC_OPERATION_SUCCESS != app_label_dir("_",
108                     m_context.locations->getUserDataRootDir().c_str())) {
109             free(pkgId);
110             ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
111                     "Add Label failure");
112         }
113     }
114
115     /* data directory */
116     if (PC_OPERATION_SUCCESS != app_label_dir(pkgId,
117                 m_context.locations->getPrivateStorageDir().c_str())) {
118         free(pkgId);
119         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
120                 "Add Label failure");
121     }
122
123     /* bin directory */
124     if (PC_OPERATION_SUCCESS != app_label_dir(pkgId,
125                 m_context.locations->getBinaryDir().c_str())) {
126         free(pkgId);
127         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
128                 "Add Label failure");
129     }
130
131     if(!setLabelForSharedDir(pkgId)) {
132         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
133                 "Add Label failure");
134     }
135
136     free(pkgId);
137
138     /* TODO : set label at wrt-client 
139
140     std::string app = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
141     char* appId = NULL;
142     appId = (char*)calloc(1, app.length() + 1);
143     snprintf(appId, app.length() + 1, "%s", app.c_str());
144
145     if (0 != smack_lsetlabel(m_context.locations->getExecFile().c_str(),
146                 appId, SMACK_LABEL_ACCESS)) {
147         free(pkgId);
148         free(appId);
149         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
150                 "Add ACESS Label for binary failure");
151     }
152
153     if (0 != smack_lsetlabel(m_context.locations->getExecFile().c_str(),
154                 appId, SMACK_LABEL_EXEC)) {
155         free(pkgId);
156         free(appId);
157         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
158                 "Add EXEC Label for binary failure");
159     }
160
161    if (PC_OPERATION_SUCCESS != app_add_friend(pkgId, appId)) {
162         free(pkgId);
163         free(appId);
164         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
165                 "Add friend failure");
166    }
167
168     if (PC_OPERATION_SUCCESS != app_label_shared_dir(appId, pkgId,
169                 m_context.locations->getBinaryDir().c_str())) {
170         free(pkgId);
171         free(appId);
172         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
173                 "Add Label failure");
174     }
175     */
176 #endif
177 }
178
179 void TaskSmack::SmackPrivilegeStep()
180 {
181     LogInfo("----------------> SMACK:\
182             Jobs::WidgetInstall::TaskSmack::SmackPrivilegeStep()");
183 #ifdef WRT_SMACK_ENABLED
184     /* TODO : 
185     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
186     */
187     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
188     char* appId = NULL;
189     appId = (char*)calloc(1, id.length() + 1);
190     snprintf(appId, id.length() + 1, "%s", id.c_str());
191
192     WrtDB::ConfigParserData::PrivilegeList privileges =
193         m_context.widgetConfig.configInfo.privilegeList;
194
195     const char** perm_list = new const char*[privileges.size() + 1];
196     int index = 0;
197     FOREACH(it, privileges) {
198         LogInfo("Permission : " << it->name);
199         int length = DPL::ToUTF8String(it->name).length();
200         char *priv = (char*) calloc(1, (sizeof(char) * length) + 1);
201         snprintf(priv, length + 1, "%s",
202                 DPL::ToUTF8String(it->name).c_str());
203         perm_list[index++] = priv;
204     }
205     perm_list[index] = NULL;
206
207     if (PC_OPERATION_SUCCESS != app_enable_permissions(appId, APP_TYPE_WGT,
208                 perm_list, true)) {
209         LogError("failure in contructing smack rules based on perm_list");
210     }
211
212     free(appId);
213
214     m_context.job->UpdateProgress(
215         InstallerContext::INSTALL_SMACK_ENABLE,
216         "Widget SMACK Enabled");
217 #endif
218 }
219
220 void TaskSmack::StepAbortSmack()
221 {
222     LogInfo("----------------> SMACK:\
223             Jobs::WidgetInstall::TaskSmack::StepAbortSmack()");
224 #ifdef WRT_SMACK_ENABLED
225     /* TODO :
226     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzAppid);
227     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
228     char* appId = NULL;
229     appId = (char*)calloc(1, id.length() + 1);
230     snprintf(appId, id.length() + 1, "%s", id.c_str());
231     */
232
233     std::string pkg = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
234     char* pkgId = NULL;
235     pkgId = (char*)calloc(1, pkg.length() + 1);
236     snprintf(pkgId, pkg.length() + 1, "%s", pkg.c_str());
237
238     if (PC_OPERATION_SUCCESS != app_revoke_permissions(pkgId)) {
239         LogError("failure in revoking smack permissions");
240     }
241
242     if (PC_OPERATION_SUCCESS != app_uninstall(pkgId)) {
243         LogError("failure in removing smack rules file");
244     }
245     free(pkgId);
246 #endif
247 }
248
249 void TaskSmack::SetEndofInstallation()
250 {
251     m_context.job->UpdateProgress(
252         InstallerContext::INSTALL_END,
253         "End installation");
254 }
255
256 bool TaskSmack::setLabelForSharedDir(const char* pkgId)
257 {
258     /* shared directory */
259     if (PC_OPERATION_SUCCESS != app_label_dir("*",
260                 m_context.locations->getSharedRootDir().c_str())) {
261         return false;
262     }
263
264     /* shared/res directory */
265     if (PC_OPERATION_SUCCESS != app_label_dir("_",
266                 m_context.locations->getSharedResourceDir().c_str())) {
267         return false;
268     }
269
270     /* shared/trusted directory */
271     CertificatePtr rootCert = m_context.wacSecurity.getAuthorCertificatePtr();
272     if (rootCert.Get() != NULL) {
273         ValidationCore::Crypto::Hash::SHA1 sha1;
274         sha1.Append(rootCert->getDER());
275         sha1.Finish();
276         std::string sha1String = sha1.ToBase64String();
277         size_t iPos = sha1String.find("/");
278         while(iPos < std::string::npos) {
279             sha1String.replace(iPos, 1, "#");
280             iPos = sha1String.find("/");
281         }
282
283         LogDebug("sha1 label string : " << sha1String);
284
285         if (PC_OPERATION_SUCCESS != app_label_shared_dir(pkgId,
286                     sha1String.c_str(),
287                     m_context.locations->getSharedTrustedDir().c_str())) {
288             return false;
289         }
290     }
291
292     /* shared/data directory */
293     std::string dataLabel = std::string(pkgId) + "_shareddata";
294     TizenPkgIdList pkgList = WidgetDAOReadOnly::getTizenPkgidList();
295     const char** pList = new (std::nothrow) const char*[pkgList.size() + 1];
296
297     int index = 0;
298     FOREACH(app, pkgList) {
299         std::string id = DPL::ToUTF8String(*app);
300         char *pId = new char[id.size() + 1];
301         snprintf(pId, id.length() + 1, "%s", id.c_str());
302         pList[index++] = pId;
303     }
304
305     pList[index] = NULL;
306     if (PC_OPERATION_SUCCESS != app_label_shared_dir(pkgId,
307                 dataLabel.c_str(),
308                 m_context.locations->getSharedDataDir().c_str())) {
309         freeList(pList);
310         return false;
311     }
312     if (PC_OPERATION_SUCCESS != add_shared_dir_readers(dataLabel.c_str(), pList)) {
313         freeList(pList);
314         return false;
315     }
316     if (PC_OPERATION_SUCCESS != app_label_shared_dir(pkgId,
317                 "*",
318                 m_context.locations->getSharedDataDir().c_str())) {
319         freeList(pList);
320         return false;
321     }
322     freeList(pList);
323     return true;
324 }
325 } //namespace WidgetInstall
326 } //namespace Jobs