[Install Location: Part 2] WGT file unzip to package directory (/opt/usr/apps/[pkgid...
[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 = m_contextData.locations->getPackageInstallationDir() + "/";
84     SignatureFileInfoSet signatureFiles;
85
86     Try {
87         getSignatureFiles(widgetPath, signatureFiles);
88
89         if (signatureFiles.size() <= 0) {
90             widgetPath += std::string(WrtDB::GlobalConfig::GetWidgetSrcPath())
91                 + "/";
92             if (0 == access(widgetPath.c_str(), F_OK)) {
93                 getSignatureFiles(widgetPath, signatureFiles);
94             }
95         }
96     } Catch(Exceptions::SignatureNotFound) {
97         ReThrowMsg(Exceptions::SignatureNotFound, widgetPath);
98     }
99
100     SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
101     _D("Number of signatures: %d", signatureFiles.size());
102
103     Level level = Level::UNKNOWN;
104     for (; iter != signatureFiles.rend(); ++iter) {
105         _D("Checking signature with id=%d", iter->getFileNumber());
106         SignatureData data(widgetPath + iter->getFileName(),
107                            iter->getFileNumber());
108
109         Try {
110             SignatureReader xml;
111             xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
112             xml.read(data);
113
114             WrtSignatureValidator validator(
115                     WrtSignatureValidator::TIZEN,
116                     !GlobalSettings::
117                     OCSPTestModeEnabled(),
118                     !GlobalSettings::
119                     CrlTestModeEnabled(),
120                     false);
121
122             WrtSignatureValidator::Result result =
123                 validator.check(data, widgetPath);
124
125             if (m_contextData.mode.installTime
126                 ==  InstallMode::InstallTime::PRELOAD)
127             {
128                 result = WrtSignatureValidator::SIGNATURE_VERIFIED;
129             }
130
131             if (result == WrtSignatureValidator::SIGNATURE_REVOKED) {
132                 ThrowMsg(Exceptions::CertificateExpired,
133                          "Certificate is REVOKED");
134             }
135
136             if (result == WrtSignatureValidator::SIGNATURE_INVALID &&
137                     iter->getFileNumber() <= 1)
138             {
139                 ThrowMsg(Exceptions::SignatureInvalid, "Invalid Package");
140             }
141
142             if (data.isAuthorSignature()) {
143                 _D("Skip author signature");
144             } else {
145                 Level currentCertLevel =
146                     certTypeToLevel(data.getVisibilityLevel());
147                 if (currentCertLevel == Level::UNKNOWN) {
148                     continue;
149                 }
150                 if (currentCertLevel > level) {
151                     level = currentCertLevel;
152                     _D("level %s", enumToString(level).c_str());
153                 }
154             }
155         } Catch(ParserSchemaException::Base) {
156             _E("Error occured in ParserSchema.");
157             ReThrowMsg(Exceptions::SignatureInvalid,
158                        "Error occured in ParserSchema.");
159         }
160     }
161
162     m_contextData.certLevel = level;
163     return level;
164 }
165
166 bool TaskCertifyLevel::checkConfigurationLevel(
167     TaskCertifyLevel::Level level)
168 {
169     if (!checkSettingLevel(level)) {
170         return false;
171     }
172     if (!checkAppcontrolHasDisposition(level)) {
173         return false;
174     }
175     return true;
176 }
177
178 bool TaskCertifyLevel::checkSettingLevel(
179     TaskCertifyLevel::Level level)
180 {
181     secureSettingMap data = {
182         {"sound-mode", Level::PARTNER},
183         {"nodisplay", Level::PARTNER}
184     };
185     FOREACH(it, m_contextData.widgetConfig.configInfo.settingsList) {
186         secureSettingIter ret = data.find(DPL::ToUTF8String(it->m_name));
187         if (ret != data.end()) {
188             if (level < ret->second) {
189                 _E("\"%ls\" needs \"%s\" level", it->m_name.c_str(), enumToString(ret->second).c_str());
190                 return false;
191             }
192         }
193     }
194     return true;
195 }
196
197 bool TaskCertifyLevel::checkAppcontrolHasDisposition(
198     TaskCertifyLevel::Level level)
199 {
200     // tizen:disposition -> platform
201     FOREACH(it, m_contextData.widgetConfig.configInfo.appControlList) {
202         if (ConfigParserData::AppControlInfo::Disposition::UNDEFINE !=
203             it->m_disposition)
204         {
205             if (level < Level::PLATFORM) {
206                 _E("\"tizen:disposition\" needs \"%s \" level", enumToString(Level::PLATFORM).c_str());
207                 return false;
208             }
209         }
210     }
211     return true;
212 }
213
214 std::string TaskCertifyLevel::enumToString(
215     TaskCertifyLevel::Level level)
216 {
217     switch (level) {
218 #define X(x, y) case x: return #y;
219         X(Level::UNKNOWN, UNKNOWN)
220         X(Level::PUBLIC, PUBLIC)
221         X(Level::PARTNER, PARTNER)
222         X(Level::PLATFORM, PLATFORM)
223 #undef X
224     default:
225         return "UNKNOWN";
226     }
227 }
228
229 TaskCertifyLevel::Level TaskCertifyLevel::certTypeToLevel(
230     CertStoreId::Type type)
231 {
232     // CertStoreType.h (framework/security/cert-svc)
233     // RootCA's visibility level : public
234     // const Type VIS_PUBLIC = 1 << 6;
235     // RootCA's visibility level : partner
236     // const Type VIS_PARTNER = 1 << 7;
237     // RootCA's visibility level : platform
238     // const Type VIS_PLATFORM = 1 << 10;
239     if (type == CertStoreId::VIS_PUBLIC) {
240         return Level::PUBLIC;
241     } else if (type == CertStoreId::VIS_PARTNER) {
242         return Level::PARTNER;
243     } else if (type == CertStoreId::VIS_PLATFORM) {
244         return Level::PLATFORM;
245     }
246     return Level::UNKNOWN;
247 }
248
249 void TaskCertifyLevel::StartStep()
250 {
251     _D("--------- <TaskCertifyLevel> : START ----------");
252 }
253
254 void TaskCertifyLevel::EndStep()
255 {
256     _D("--------- <TaskCertifyLevel> : END ----------");
257
258     m_contextData.job->UpdateProgress(
259         InstallerContext::INSTALL_CERTIFY_LEVEL_CHECK,
260         "Application Certificate level check Finished");
261 }
262 } //namespace WidgetInstall
263 } //namespace Jobs
264