Add to pass rivilege level when installing service app.
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_certify_level.cpp
1 /*
2  * Copyright (c) 2013 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_certify_level.cpp
18  * @author  Jihoon Chung (jihoon.chung@samgsung.com)
19  * @version
20  * @brief
21  */
22
23 //SYSTEM INCLUDES
24 #include <string>
25 #include <map>
26 #include <unistd.h>
27
28 //WRT INCLUDES
29 #include <widget_install/task_certify_level.h>
30 #include <widget_install/job_widget_install.h>
31 #include <widget_install/widget_install_errors.h>
32 #include <widget_install/widget_install_context.h>
33 #include <dpl/assert.h>
34 #include <dpl/exception.h>
35 #include <dpl/string.h>
36 #include <dpl/foreach.h>
37 #include <dpl/wrt-dao-ro/global_config.h>
38
39 #include <vcore/CertStoreType.h>
40 #include <vcore/SignatureReader.h>
41 #include <vcore/SignatureFinder.h>
42 #include <vcore/WrtSignatureValidator.h>
43 #include <dpl/utils/wrt_global_settings.h>
44
45 #include <installer_log.h>
46
47 using namespace ValidationCore;
48 using namespace WrtDB;
49
50 namespace Jobs {
51 namespace WidgetInstall {
52 TaskCertifyLevel::TaskCertifyLevel(InstallerContext &inCont) :
53     DPL::TaskDecl<TaskCertifyLevel>(this),
54     m_contextData(inCont)
55 {
56     AddStep(&TaskCertifyLevel::StartStep);
57     AddStep(&TaskCertifyLevel::stepCertifyLevel);
58     AddStep(&TaskCertifyLevel::EndStep);
59 }
60
61 void TaskCertifyLevel::stepCertifyLevel()
62 {
63     _D("================ Step: <<Certify Level>> ENTER ===============");
64     if (!checkConfigurationLevel(getCertifyLevel())) {
65         ThrowMsg(Exceptions::PrivilegeLevelViolation, "setting level violate");
66     }
67     _D("================ Step: <<Certify Level>> DONE ================");
68 }
69
70 void TaskCertifyLevel::getSignatureFiles(const std::string& path,
71                                          SignatureFileInfoSet& file)
72 {
73     SignatureFileInfoSet signatureFiles;
74     SignatureFinder signatureFinder(path);
75     if (SignatureFinder::NO_ERROR != signatureFinder.find(file)) {
76         _E("Error in Signature Finder : %s", path.c_str());
77         ThrowMsg(Exceptions::SignatureNotFound, "Signature not found");
78     }
79 }
80
81 TaskCertifyLevel::Level TaskCertifyLevel::getCertifyLevel()
82 {
83     std::string widgetPath;
84     widgetPath = m_contextData.locations->getTemporaryPackageDir() + "/";
85
86     if (m_contextData.mode.command == InstallMode::Command::REINSTALL) {
87         widgetPath =
88             m_contextData.locations->getPackageInstallationDir() + "/";
89     }
90
91     SignatureFileInfoSet signatureFiles;
92
93     Try {
94         getSignatureFiles(widgetPath, signatureFiles);
95
96         if (signatureFiles.size() <= 0) {
97             widgetPath += std::string(WrtDB::GlobalConfig::GetWidgetSrcPath())
98                 + "/";
99             if (0 == access(widgetPath.c_str(), F_OK)) {
100                 getSignatureFiles(widgetPath, signatureFiles);
101             }
102         }
103     } Catch(Exceptions::SignatureNotFound) {
104         ReThrowMsg(Exceptions::SignatureNotFound, widgetPath);
105     }
106
107     SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
108     _D("Number of signatures: %d", signatureFiles.size());
109
110     Level level = Level::UNKNOWN;
111     for (; iter != signatureFiles.rend(); ++iter) {
112         _D("Checking signature with id=%d", iter->getFileNumber());
113         SignatureData data(widgetPath + iter->getFileName(),
114                            iter->getFileNumber());
115
116         Try {
117             SignatureReader xml;
118             xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
119             xml.read(data);
120
121             WrtSignatureValidator validator(
122                     WrtSignatureValidator::TIZEN,
123                     !GlobalSettings::
124                     OCSPTestModeEnabled(),
125                     !GlobalSettings::
126                     CrlTestModeEnabled(),
127                     false);
128
129             WrtSignatureValidator::Result result =
130                 validator.check(data, widgetPath);
131
132             if (m_contextData.mode.installTime
133                 ==  InstallMode::InstallTime::PRELOAD)
134             {
135                 result = WrtSignatureValidator::SIGNATURE_VERIFIED;
136             }
137
138             if (result == WrtSignatureValidator::SIGNATURE_REVOKED) {
139                 ThrowMsg(Exceptions::CertificateExpired,
140                          "Certificate is REVOKED");
141             }
142
143             if (result == WrtSignatureValidator::SIGNATURE_INVALID &&
144                     iter->getFileNumber() <= 1)
145             {
146                 ThrowMsg(Exceptions::SignatureInvalid, "Invalid Package");
147             }
148
149             if (data.isAuthorSignature()) {
150                 _D("Skip author signature");
151             } else {
152                 Level currentCertLevel =
153                     certTypeToLevel(data.getVisibilityLevel());
154                 if (currentCertLevel == Level::UNKNOWN) {
155                     continue;
156                 }
157                 if (currentCertLevel > level) {
158                     level = currentCertLevel;
159                     _D("level %s", enumToString(level).c_str());
160                 }
161             }
162         } Catch(ParserSchemaException::Base) {
163             _E("Error occured in ParserSchema.");
164             ReThrowMsg(Exceptions::SignatureInvalid,
165                        "Error occured in ParserSchema.");
166         }
167     }
168
169     m_contextData.certLevel = level;
170     return level;
171 }
172
173 bool TaskCertifyLevel::checkConfigurationLevel(
174     TaskCertifyLevel::Level level)
175 {
176     if (!checkSettingLevel(level)) {
177         return false;
178     }
179     if (!checkAppcontrolHasDisposition(level)) {
180         return false;
181     }
182     return true;
183 }
184
185 bool TaskCertifyLevel::checkSettingLevel(
186     TaskCertifyLevel::Level level)
187 {
188     secureSettingMap data = {
189         {"sound-mode", Level::PARTNER}
190     };
191
192     FOREACH(it, m_contextData.widgetConfig.configInfo.settingsList) {
193         secureSettingIter ret = data.find(DPL::ToUTF8String(it->m_name));
194         if (ret != data.end()) {
195             if (level < ret->second) {
196                 _E("\"%ls\" needs \"%s\" level", it->m_name.c_str(), enumToString(ret->second).c_str());
197                 return false;
198             }
199         }
200     }
201     return true;
202 }
203
204 bool TaskCertifyLevel::checkAppcontrolHasDisposition(
205     TaskCertifyLevel::Level level)
206 {
207     // tizen:disposition -> platform
208     FOREACH(it, m_contextData.widgetConfig.configInfo.appControlList) {
209         if (ConfigParserData::AppControlInfo::Disposition::UNDEFINE !=
210             it->m_disposition)
211         {
212             if (level < Level::PLATFORM) {
213                 _E("\"tizen:disposition\" needs \"%s \" level", enumToString(Level::PLATFORM).c_str());
214                 return false;
215             }
216         }
217     }
218     return true;
219 }
220
221 std::string TaskCertifyLevel::enumToString(
222     TaskCertifyLevel::Level level)
223 {
224     switch (level) {
225 #define X(x, y) case x: return #y;
226         X(Level::UNKNOWN, UNKNOWN)
227         X(Level::PUBLIC, PUBLIC)
228         X(Level::PARTNER, PARTNER)
229         X(Level::PLATFORM, PLATFORM)
230 #undef X
231     default:
232         return "UNKNOWN";
233     }
234 }
235
236 TaskCertifyLevel::Level TaskCertifyLevel::certTypeToLevel(
237     CertStoreId::Type type)
238 {
239     // CertStoreType.h (framework/security/cert-svc)
240     // RootCA's visibility level : public
241     // const Type VIS_PUBLIC = 1 << 6;
242     // RootCA's visibility level : partner
243     // const Type VIS_PARTNER = 1 << 7;
244     // RootCA's visibility level : platform
245     // const Type VIS_PLATFORM = 1 << 10;
246     if (type == CertStoreId::VIS_PUBLIC) {
247         return Level::PUBLIC;
248     } else if (type == CertStoreId::VIS_PARTNER) {
249         return Level::PARTNER;
250     } else if (type == CertStoreId::VIS_PLATFORM) {
251         return Level::PLATFORM;
252     }
253     return Level::UNKNOWN;
254 }
255
256 void TaskCertifyLevel::StartStep()
257 {
258     _D("--------- <TaskCertifyLevel> : START ----------");
259 }
260
261 void TaskCertifyLevel::EndStep()
262 {
263     _D("--------- <TaskCertifyLevel> : END ----------");
264
265     m_contextData.job->UpdateProgress(
266         InstallerContext::INSTALL_CERTIFY_LEVEL_CHECK,
267         "Application Certificate level check Finished");
268 }
269 } //namespace WidgetInstall
270 } //namespace Jobs
271