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