Tizen 2.4.0 rev3 SDK Public Release
[framework/web/wearable/wrt-installer.git] / src / jobs / widget_install / task_ace_check.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_ace_check.cpp
18  * @author  Pawel Sikorski (p.sikorski@samsung.com)
19  * @version 1.0
20  * @brief   Implementation file for installer task ace check
21  */
22
23 #include <utility>
24 #include <vector>
25 #include <string>
26
27 #include <widget_install/task_ace_check.h>
28 #include <dpl/assert.h>
29 #include <dpl/foreach.h>
30
31 #include <widget_install/widget_install_context.h>
32 #include <widget_install/widget_install_errors.h>
33 #include <widget_install/job_widget_install.h>
34 #include <widget_install/task_certify.h>
35 #include <dpl/wrt-dao-rw/widget_dao.h>
36 #include <ace_api_install.h>
37 #include <privilege_manager.h>
38 #include <installer_log.h>
39 #include <glib.h>
40
41 namespace Jobs {
42 namespace WidgetInstall {
43 TaskAceCheck::TaskAceCheck(InstallerContext& context) :
44     DPL::TaskDecl<TaskAceCheck>(this),
45     m_context(context)
46 {
47     AddStep(&TaskAceCheck::StartStep);
48     AddStep(&TaskAceCheck::StepPrivilegeCheck);
49     AddStep(&TaskAceCheck::StepPrepareForAce);
50     AddStep(&TaskAceCheck::StepAceCheck);
51     AddStep(&TaskAceCheck::StepProcessAceResponse);
52     AddStep(&TaskAceCheck::StepCheckAceResponse);
53     AddStep(&TaskAceCheck::EndStep);
54 }
55
56 void TaskAceCheck::StepPrepareForAce()
57 {
58     m_context.featureLogic =
59         FeatureLogicPtr(new FeatureLogic(m_context.widgetConfig.tzAppid));
60     m_context.job->UpdateProgress(
61         InstallerContext::INSTALL_ACE_PREPARE,
62         "Widget Access Control Check Prepared");
63 }
64
65 void TaskAceCheck::StepAceCheck()
66 {
67     WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid);
68     _D("StepAceCheck!");
69     // This widget does not use any device cap
70     if (m_context.featureLogic->isDone()) {
71         return;
72     }
73
74     _D("StepAceCheck!");
75     DPL::String deviceCap = m_context.featureLogic->getDevice();
76
77     _D("StepAceCheck!");
78     _D("DevCap is : %ls", deviceCap.c_str());
79
80     std::string devCapStr = DPL::ToUTF8String(deviceCap);
81     ace_policy_result_t policyResult = ACE_DENY;
82
83     if (m_context.mode.installTime == InstallMode::InstallTime::PRELOAD ||
84         m_context.mode.installTime == InstallMode::InstallTime::FOTA) {
85         _D("This widget is preloaded. So ace check will be skiped");
86         policyResult = ACE_PERMIT;
87     } else {
88         ace_return_t ret = ace_get_policy_result(
89                 const_cast<const ace_resource_t>(devCapStr.c_str()),
90                 dao.getHandle(),
91                 &policyResult);
92         if (ACE_OK != ret) {
93             ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. "
94                     "ACE check failure");
95         }
96     }
97
98     _D("PolicyResult is : %d", static_cast<int>(policyResult));
99     m_context.staticPermittedDevCaps.insert(std::make_pair(deviceCap,
100                                                            policyResult ==
101                                                            ACE_PERMIT));
102
103     m_context.featureLogic->setAceResponse(policyResult != ACE_DENY);
104 }
105
106 void TaskAceCheck::StepProcessAceResponse()
107 {
108     if (m_context.widgetConfig.packagingType ==
109         WrtDB::PKG_TYPE_HOSTED_WEB_APP)
110     {
111         return;
112     }
113
114     _D("StepProcessAceResponse");
115     m_context.featureLogic->next();
116
117     // No device caps left to process
118     if (m_context.featureLogic->isDone()) {
119         WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid);
120 #ifdef SERVICE_ENABLED
121         std::list<WrtDB::DbWidgetHandle> serviceList;
122         FOREACH( it , m_context.widgetConfig.configInfo.serviceAppInfoList ){
123              WrtDB::WidgetDAO serviceDao(it->serviceId);
124              serviceList.push_back(serviceDao.getHandle());
125         }
126 #endif
127         _D("All responses has been received from ACE.");
128         // Data to convert to C API
129         std::vector<std::string> devCaps;
130         std::vector<bool> devCapsSmack;
131         // Saving static dev cap permissions
132         FOREACH(cap, m_context.staticPermittedDevCaps) {
133             _D("staticPermittedDevCaps : %ls smack: %d", cap->first.c_str(), cap->second);
134             std::string devCapStr = DPL::ToUTF8String(cap->first);
135             devCaps.push_back(devCapStr);
136             devCapsSmack.push_back(cap->second);
137         }
138         ace_requested_dev_cap_list_t list;
139         list.count = devCaps.size();
140         list.items = new ace_requested_dev_cap_t[list.count];
141
142         for (unsigned int i = 0; i < devCaps.size(); ++i) {
143             list.items[i].device_capability =
144                 const_cast<const ace_resource_t>(devCaps[i].c_str());
145             list.items[i].smack_granted =
146                 devCapsSmack[i] ? ACE_TRUE : ACE_FALSE;
147         }
148         //TODO: remove dao.getHandle()
149         int ret = ace_set_requested_dev_caps(dao.getHandle(),&list);
150 #ifdef SERVICE_ENABLED
151         FOREACH( it, serviceList){
152             ret |= ace_set_requested_dev_caps(*it,&list);
153         }
154 #endif
155         delete[] list.items;
156
157         if (ACE_OK != static_cast<ace_return_t>(ret)) {
158             ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. "
159                                              "ACE failure");
160         }
161
162         std::set<std::string> acceptedFeature;
163         auto it = m_context.featureLogic->resultBegin();
164         for (; it != m_context.featureLogic->resultEnd(); ++it) {
165             if (!(it->rejected)) {
166                 acceptedFeature.insert(DPL::ToUTF8String(it->name));
167             }
168         }
169         ace_feature_list_t featureList;
170         featureList.count = acceptedFeature.size();
171         featureList.items = new ace_string_t[featureList.count];
172
173         size_t i = 0;
174         for (std::set<std::string>::const_iterator iter = acceptedFeature.begin();
175              iter != acceptedFeature.end(); ++iter)
176         {
177             _D("Accepted feature item: %s", iter->c_str());
178             featureList.items[i] = const_cast<char *>(iter->c_str());
179             i++;
180         }
181
182         //TODO: remove dao.getHandle()
183         ret = ace_set_accepted_feature(dao.getHandle(), &featureList);
184 #ifdef SERVICE_ENABLED
185         FOREACH( it, serviceList){
186             ret |= ace_set_accepted_feature(*it, &featureList);
187         }
188 #endif
189         delete[] featureList.items;
190
191         if (ACE_OK != static_cast<ace_return_t>(ret)) {
192             _E("Error in ace_set_feature");
193             ThrowMsg(Exceptions::AceCheckFailed, "Instalation failure. "
194                                              "ace_set_feature failure.");
195         }
196         return;
197     }
198
199     _D("Next device cap.");
200     // Process next device cap
201     SwitchToStep(&TaskAceCheck::StepAceCheck);
202 }
203
204 void TaskAceCheck::StepCheckAceResponse()
205 {
206     _D("Checking ACE response");
207     if (m_context.featureLogic->isRejected()) {
208         _E("Installation failure. Some devCap was not accepted by ACE.");
209         ThrowMsg(
210             Exceptions::PrivilegeLevelViolation,
211             "Instalation failure. "
212             "Some deviceCap was not accepted by ACE.");
213     }
214     _D("Updating \"feature reject status\" in database!");
215     auto it = m_context.featureLogic->resultBegin();
216     auto end = m_context.featureLogic->resultEnd();
217     for (; it != end; ++it) {
218         _D("  |-  Feature: %ls has reject status: %d", it->name.c_str(), it->rejected);
219         if (it->rejected) {
220             WrtDB::WidgetDAO dao(m_context.widgetConfig.tzAppid);
221             dao.updateFeatureRejectStatus(*it);
222
223 #ifdef SERVICE_ENABLED
224             FOREACH( svcApp , m_context.widgetConfig.configInfo.serviceAppInfoList){
225                 WrtDB::WidgetDAO dao(svcApp->serviceId);
226                 dao.updateFeatureRejectStatus(*it);
227             }
228 #endif
229         }
230     }
231     _D("Installation continues...");
232 }
233
234 void TaskAceCheck::StepPrivilegeCheck()
235 {
236     _D("StepPrivilegeCheck!");
237
238     GList* privilege_list = NULL;
239     char* error_privilege_name = NULL;
240
241     WrtDB::WidgetDAOReadOnly widgetDao(m_context.widgetConfig.tzAppid);
242     WidgetFeatureSet featureSet = widgetDao.getFeaturesList();
243     std::list<std::string> privliege_std_list;
244     FOREACH(it, featureSet) {
245         _D("Privilege List : %ls", it->name.c_str());
246         privliege_std_list.push_back(DPL::ToUTF8String(it->name).c_str());
247         privilege_list = g_list_append(privilege_list, (gpointer)(privliege_std_list.back()).c_str());
248     }
249
250     if (privilege_list == NULL) {
251         _D("Skip privilege check. Privilege list is NULL");
252         return;
253     }
254
255     DPL::OptionalString minVersion = m_context.widgetConfig.minVersion;
256     std::string version = DPL::ToUTF8String(*minVersion);
257     privilege_manager_visibility_e cert_svc_visibility = static_cast<privilege_manager_visibility_e>(CERT_SVC_VISIBILITY_PUBLIC);
258
259     _D("Cert level : %d", m_context.certLevel);
260     switch(m_context.certLevel) {
261         case Jobs::WidgetInstall::TaskCertify::Level::PLATFORM:
262             cert_svc_visibility = static_cast<privilege_manager_visibility_e>(CERT_SVC_VISIBILITY_PLATFORM);
263             break;
264         case Jobs::WidgetInstall::TaskCertify::Level::PARTNER:
265             cert_svc_visibility = static_cast<privilege_manager_visibility_e>(CERT_SVC_VISIBILITY_PARTNER);
266             break;
267     }
268
269     int ret = privilege_manager_verify_privilege(
270             version.c_str(),
271             PRVMGR_PACKAGE_TYPE_WRT,
272             privilege_list,
273             cert_svc_visibility,
274             &error_privilege_name);
275
276     if (ret != PRVMGR_ERR_NONE) {
277         _E("privilege_manager_verify_privilege_list(PRVMGR_PACKAGE_TYPE_WRT) failed.\n%s", error_privilege_name);
278         if (privilege_list != NULL) {
279             g_list_free(privilege_list);
280             privilege_list = NULL;
281         }
282
283         if (error_privilege_name != NULL) {
284             std::string error_message = error_privilege_name;
285             free(error_privilege_name);
286             error_privilege_name = NULL;
287             if (strstr(error_message.c_str(), "[DEPRECATED_PRIVILEGE]") != NULL) {
288                 ThrowMsg(Exceptions::PrivilegeUsingLegacyFailed, error_message.c_str());
289             } else if (strstr(error_message.c_str(), "[NO_EXIST_PRIVILEGE]") != NULL) {
290                 ThrowMsg(Exceptions::PrivilegeUnknownkFailed, error_message.c_str());
291             } else if (strstr(error_message.c_str(), "[MISMATCHED_PRIVILEGE_LEVEL]") != NULL) {
292                 ThrowMsg(Exceptions::PrivilegeUnauthorizedFailed, error_message.c_str());
293             } else {
294                 ThrowMsg(Exceptions::SignatureVerificationFailed, error_message.c_str());
295             }
296         }
297     } else {
298         _D("privilege_manager_verify_privilege_list(PRVMGR_PACKAGE_TYPE_WRT) is ok.");
299     }
300
301     if (privilege_list != NULL) {
302         g_list_free(privilege_list);
303         privilege_list = NULL;
304     }
305
306     if (error_privilege_name != NULL) {
307         free(error_privilege_name);
308         error_privilege_name = NULL;
309     }
310 }
311
312 void TaskAceCheck::StartStep()
313 {
314     LOGI("--------- <TaskAceCheck> : START ----------");
315 }
316
317 void TaskAceCheck::EndStep()
318 {
319     m_context.job->UpdateProgress(
320         InstallerContext::INSTALL_ACE_CHECK,
321         "Widget Access Control Check Finished");
322
323     LOGI("--------- <TaskAceCheck> : END ----------");
324 }
325 } //namespace WidgetInstall
326 } //namespace Jobs