Initialize Tizen 2.3
[framework/web/wrt-installer.git] / src_wearable / 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/global_config.h>
30 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
31 #include <dpl/utils/bash_utils.h>
32 #include <dpl/utils/path.h>
33 #include <vcore/Certificate.h>
34 #include <vcore/CryptoHash.h>
35 #include <vcore/SignatureFinder.h>
36 #include <privilege-control.h>
37 #include <sys/smack.h>
38 #include <sstream>
39 #include <installer_log.h>
40 #include <privilege-control.h>
41
42 using namespace WrtDB;
43 using namespace ValidationCore;
44
45 namespace {
46 const int MAX_BUF_SIZE = 128;
47 void freeList(const char** list) {
48     for (int i = 0; list[i] != NULL; i++)
49     {
50         delete(list[i]);
51     }
52     delete[] list;
53 }
54 }
55
56 namespace Jobs {
57 namespace WidgetInstall {
58 TaskSmack::TaskSmack(InstallerContext& context) :
59     DPL::TaskDecl<TaskSmack>(this),
60     m_context(context)
61 {
62     AddStep(&TaskSmack::StartStep);
63     AddStep(&TaskSmack::StepSetInstall);
64     AddStep(&TaskSmack::StepSmackFolderLabeling);
65     AddStep(&TaskSmack::StepSmackPrivilege);
66     AddStep(&TaskSmack::StepAddLabelNPRuntime);
67     AddStep(&TaskSmack::StepLabelSignatureFiles);
68     AddStep(&TaskSmack::EndStep);
69
70     AddAbortStep(&TaskSmack::StepAbortSmack);
71 }
72
73 void TaskSmack::StepSetInstall()
74 {
75     _D("----------------> SMACK: StepStartSetSmack()");
76
77     m_pkgId = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
78
79     if (PC_OPERATION_SUCCESS != perm_app_install(m_pkgId.c_str())) {
80         ThrowMsg(Exceptions::NotAllowed, "Instalation failure. "
81                 "failure in creating smack rules file.");
82     }
83 }
84
85 void TaskSmack::StepSmackFolderLabeling()
86 {
87     _D("----------------> SMACK:\
88             Jobs::WidgetInstall::TaskSmack::SmackFolderLabelingStep()");
89
90     /* /opt/usr/apps/[pkgid] directory's label is "_" */
91     if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(),
92                 m_context.locations->getPackageInstallationDir().c_str(),
93                 APP_PATH_ANY_LABEL, "_")) {
94         _W("Add label to %s", m_context.locations->getPackageInstallationDir().c_str());
95     }
96
97     /* for prelaod */
98     if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD) {
99         if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(),
100                     m_context.locations->getUserDataRootDir().c_str(),
101                     APP_PATH_ANY_LABEL, "_")) {
102         }
103     }
104
105     /* res directory */
106     std::string resDir = m_context.locations->getPackageInstallationDir() +
107         "/res";
108
109     if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(), resDir.c_str(),
110                 APP_PATH_PRIVATE)) {
111         _W("Add label to %s", resDir.c_str());
112     }
113
114     /* data directory */
115     if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(),
116                 m_context.locations->getPrivateStorageDir().c_str(),
117                 APP_PATH_PRIVATE)) {
118         _W("Add label to %s", m_context.locations->getPrivateStorageDir().c_str());
119     }
120
121     /* tmp directory */
122     if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(),
123                 m_context.locations->getPrivateTempStorageDir().c_str(),
124                 APP_PATH_PRIVATE))
125     {
126         _W("Add label to %s", m_context.locations->getPrivateTempStorageDir().c_str());
127     }
128
129     /* bin directory */
130     if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(),
131                 m_context.locations->getBinaryDir().c_str(),
132                 APP_PATH_PRIVATE)) {
133         _W("Add label to %s", m_context.locations->getBinaryDir().c_str());
134     }
135
136     if(!setLabelForSharedDir(m_pkgId.c_str())) {
137         _W("Add label to shared directory");
138     }
139
140     /* TODO : set label at wrt-client */
141 }
142
143 void TaskSmack::StepSmackPrivilege()
144 {
145     _D("----------------> SMACK:\
146         Jobs::WidgetInstall::TaskSmack::SmackPrivilegeStep()");
147
148     std::string id = DPL::ToUTF8String(m_context.widgetConfig.tzPkgid);
149     char* appId = NULL;
150     appId = (char*)calloc(1, id.length() + 1);
151     snprintf(appId, id.length() + 1, "%s", id.c_str());
152
153     WrtDB::ConfigParserData::PrivilegeList privileges =
154         m_context.widgetConfig.configInfo.privilegeList;
155
156     char** perm_list = new char*[privileges.size() + 1];
157     int index = 0;
158     FOREACH(it, privileges) {
159         _D("Permission : %ls", it->name.c_str());
160         int length = DPL::ToUTF8String(it->name).length();
161         char *priv = new char[length + 1];
162         snprintf(priv, length + 1, "%s",
163                  DPL::ToUTF8String(it->name).c_str());
164         perm_list[index++] = priv;
165     }
166     perm_list[index] = NULL;
167
168     if (PC_OPERATION_SUCCESS != perm_app_enable_permissions(appId, APP_TYPE_WGT,
169                 const_cast<const char **>(perm_list), true)) {
170         _W("failure in contructing smack rules based on perm_list");
171     }
172
173     free(appId);
174     index = 0;
175     while (NULL != perm_list[index]) {
176         delete [] perm_list[index++];
177     }
178     delete [] perm_list;
179
180     m_context.job->UpdateProgress(
181         InstallerContext::INSTALL_SMACK_ENABLE,
182         "Widget SMACK Enabled");
183 }
184
185 void TaskSmack::StepAddLabelNPRuntime()
186 {
187     _D("----------------> SMACK:\
188             Jobs::WidgetInstall::TaskSmack::StepAddLabelNPRuntime()");
189
190     if (0 == access(m_context.locations->getNPPluginsDir().c_str(), F_OK)) {
191         if (PC_OPERATION_SUCCESS !=
192                 perm_app_setup_path(DPL::ToUTF8String(m_context.widgetConfig.tzPkgid).c_str(),
193                     m_context.locations->getNPPluginsExecFile().c_str(),
194                     PERM_APP_PATH_NPRUNTIME)) {
195             _E("failed to set smack execute label to %s",
196                     m_context.locations->getNPPluginsExecFile().c_str());
197         }
198     }
199 }
200
201
202 void TaskSmack::StepLabelSignatureFiles()
203 {
204     _D("----------------> SMACK:\
205             Jobs::WidgetInstall::TaskSmack::StepLabelSignatureFiles()");
206
207     DPL::Utils::Path widgetPath{
208             m_context.locations->getPackageInstallationDir()};
209     widgetPath /= WrtDB::GlobalConfig::GetWidgetSrcPath();
210
211     SignatureFileInfoSet signatureFiles;
212     SignatureFinder signatureFinder(widgetPath.Fullpath());
213     if (SignatureFinder::NO_ERROR != signatureFinder.find(signatureFiles)) {
214         ThrowMsg(Exceptions::SignatureNotFound,
215                  "Error while discovering signature files.");
216     }
217
218     for (auto it = signatureFiles.cbegin(); it != signatureFiles.cend(); ++it) {
219         auto sigPath = widgetPath / it->getFileName();
220
221         _D("Setting label to %s", sigPath.Fullpath().c_str());
222         if (PC_OPERATION_SUCCESS != perm_app_setup_path(m_pkgId.c_str(),
223                     sigPath.Fullpath().c_str(),
224                     APP_PATH_ANY_LABEL, "_")) {
225             _W("Failed to set label to %s", sigPath.Fullpath().c_str());
226         }
227     }
228 }
229
230 void TaskSmack::StepRevokeForUpdate()
231 {
232     _D("----------------> SMACK:\
233         Jobs::WidgetInstall::TaskSmack::StepRevokePrivilegeForUpdate()");
234
235     if (PC_OPERATION_SUCCESS != perm_app_revoke_permissions(m_pkgId.c_str())) {
236         _W("failure in revoking smack permissions");
237     }
238 }
239
240 void TaskSmack::StepAbortSmack()
241 {
242     _D("----------------> SMACK:\
243             Jobs::WidgetInstall::TaskSmack::StepAbortSmack()");
244
245     if (PC_OPERATION_SUCCESS != perm_app_revoke_permissions(m_pkgId.c_str())) {
246         _W("failure in revoking smack permissions");
247     }
248
249     if (PC_OPERATION_SUCCESS != perm_app_uninstall(m_pkgId.c_str())) {
250         _W("failure in removing smack rules file");
251     }
252 }
253
254 bool TaskSmack::setLabelForSharedDir(const char* pkgId)
255 {
256     /* /shared directory */
257     if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId,
258                 m_context.locations->getSharedRootDir().c_str(),
259                 APP_PATH_ANY_LABEL, "_")) {
260         _W("Add label to %s", m_context.locations->getUserDataRootDir().c_str());
261     }
262
263     /* /shared/res directory */
264     if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId,
265                 m_context.locations->getSharedResourceDir().c_str(),
266                 APP_PATH_ANY_LABEL, "_")) {
267         _W("Add label to %s", m_context.locations->getSharedResourceDir().c_str());
268     }
269
270     /* /shared/trusted directory */
271     CertificatePtr rootCert = m_context.widgetSecurity.getAuthorCertificatePtr();
272     if (!!rootCert) {
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         _D("sha1 label string : %s", sha1String.c_str());
284
285         if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId,
286                     m_context.locations->getSharedTrustedDir().c_str(),
287                     APP_PATH_GROUP_RW, sha1String.c_str())) {
288             _W("Add label to %s", m_context.locations->getBinaryDir().c_str());
289         }
290     }
291
292     /* /shared/data directory */
293     if (PC_OPERATION_SUCCESS != perm_app_setup_path(pkgId,
294                 m_context.locations->getSharedDataDir().c_str(),
295                 APP_PATH_PUBLIC_RO)) {
296         _W("Add label to %s", m_context.locations->getSharedDataDir().c_str());
297     }
298
299     return true;
300 }
301
302 void TaskSmack::StartStep()
303 {
304     LOGD("--------- <TaskSmack> : START ----------");
305     if (PC_OPERATION_SUCCESS != perm_begin()) {
306         LOGE("Failed to smack transaction begin.");
307         ThrowMsg(Exceptions::SmackTransactionFailed, "Failed to smack transaction begin");
308     }
309 }
310
311 void TaskSmack::EndStep()
312 {
313     LOGD("--------- <TaskSmack> : END ----------");
314     if (PC_OPERATION_SUCCESS != perm_end()) {
315         LOGE("Failed to smack transaction end.");
316         ThrowMsg(Exceptions::SmackTransactionFailed, "Failed to smack transaction end");
317     }
318 }
319 } //namespace WidgetInstall
320 } //namespace Jobs