2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file task_certify.cpp
18 * @author Pawel Sikorski (p.sikorski@samgsung.com)
26 #include <dpl/assert.h>
27 #include <appcore-common.h> //TODO is it necessary here?
31 #include <widget_install/task_certify.h>
32 #include <widget_install/job_widget_install.h>
33 #include <widget_install/widget_install_errors.h>
34 #include <widget_install/widget_install_context.h>
35 #include <dpl/log/log.h>
36 #include <dpl/wrt-dao-ro/global_config.h>
37 #include "wac_widget_id.h"
39 #include <vcore/Certificate.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 #include <dpl/wrt-dao-ro/global_dao_read_only.h>
46 #include <ITapiModem.h>
47 #include <tapi_common.h>
49 using namespace ValidationCore;
50 using namespace WrtDB;
53 const std::string LABEL_NEW_LINE = "<br>";
54 const std::string LABEL_NEW_LINE_2 = "<br><br>";
55 const std::string UNTRUSTED_WIDGET = "It is an Untrusted Widget";
56 const char *QUESTION = "Do you wanto to install?";
58 WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
61 WidgetCertificateData result;
63 result.chainId = data.getSignatureNumber();
64 LogDebug("result.chainId : " << result.chainId);
66 result.owner = data.isAuthorSignature() ?
67 WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR;
70 WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY;
72 CertificatePtr certificate;
75 certificate = data.getRootCaCertificatePtr();
77 certificate = data.getEndEntityCertificatePtr();
80 Assert(certificate && !certificate->getCommonName().IsNull() &&
81 "CommonName is Null");
83 result.strCommonName = *certificate->getCommonName();
85 result.strMD5Fingerprint = std::string("md5 ") +
86 Certificate::FingerprintToColonHex(
87 certificate->getFingerprint(Certificate::FINGERPRINT_MD5));
89 result.strSHA1Fingerprint = std::string("sha-1 ") +
90 Certificate::FingerprintToColonHex(
91 certificate->getFingerprint(Certificate::FINGERPRINT_SHA1));
96 CertificatePtr getOldAuthorSignerCertificate(DPL::String appid)
98 WidgetDAOReadOnly dao(appid);
99 CertificateChainList chainList = dao.getWidgetCertificate(SIGNATURE_AUTHOR);
101 FOREACH(it, chainList)
103 ValidationCore::CertificateCollection chain;
104 if (false == chain.load(*it)) {
105 LogError("Chain is broken");
109 LogError("Chain failed at sorting");
112 ValidationCore::CertificateList list = chain.getCertificateList();
116 if (!(*cert)->isRootCert() && !(*cert)->isCA()) {
121 return CertificatePtr(NULL);
123 } // namespace anonymous
126 namespace WidgetInstall {
127 TaskCertify::TaskCertify(InstallerContext &inCont) :
128 DPL::TaskDecl<TaskCertify>(this),
129 WidgetInstallPopup(inCont),
130 m_contextData(inCont)
132 AddStep(&TaskCertify::stepSignature);
133 // certi comparison determines whether the update.
134 if (true == m_contextData.isUpdateMode) {
135 AddStep(&TaskCertify::stepVerifyUpdate);
138 // Block until fixed popup issues
139 if (!GlobalSettings::PopupsTestModeEnabled()
140 && !m_installContext.m_quiet && !isTizenWebApp())
142 AddStep(&TaskCertify::stepWarningPopup);
143 AddStep(&TaskCertify::stepWarningPopupAnswer);
144 AddStep(&TaskCertify::stepAuthorInfoPopup);
145 AddStep(&TaskCertify::stepAuthorInfoPopupAnswer);
146 AddStep(&TaskCertify::StepDeletePopupWin);
148 AddStep(&TaskCertify::stepFinalize);
151 void TaskCertify::processDistributorSignature(const SignatureData &data)
153 // this signature is verified -
154 // no point in check domain WAC_ROOT and WAC_RECOGNIZED
155 m_contextData.wacSecurity.setDistributorSigned(true);
157 CertificateCollection collection;
158 collection.load(data.getCertList());
159 Assert(collection.sort() &&
160 "Certificate collection can't sort");
162 Assert(collection.isChain() &&
163 "Certificate collection is not able to create chain. "
164 "It is not possible to verify this signature.");
166 m_contextData.wacSecurity.getCertificateChainListRef().push_back(
169 if (data.getSignatureNumber() == 1) {
170 m_contextData.wacSecurity.getCertificateListRef().push_back(
171 toWidgetCertificateData(data, true));
172 m_contextData.wacSecurity.getCertificateListRef().push_back(
173 toWidgetCertificateData(data, false));
177 void TaskCertify::processAuthorSignature(const SignatureData &data)
179 using namespace ValidationCore;
180 LogInfo("DNS Identity match!");
181 // this signature is verified or widget is distributor signed
182 m_contextData.wacSecurity.setAuthorCertificatePtr(data.getEndEntityCertificatePtr());
183 CertificatePtr test = m_contextData.wacSecurity.getAuthorCertificatePtr();
185 m_contextData.wacSecurity.getCertificateListRef().push_back(
186 toWidgetCertificateData(data, true));
187 m_contextData.wacSecurity.getCertificateListRef().push_back(
188 toWidgetCertificateData(data, false));
190 // match widget_id with one from dns identity set
191 WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id);
193 CertificatePtr cert = data.getEndEntityCertificatePtr();
195 Certificate::AltNameSet dnsIdentity = cert->getAlternativeNameDNS();
197 CertificateCollection collection;
198 collection.load(data.getCertList());
200 Assert(collection.isChain() &&
201 "Certificate collection is not able to create chain. "
202 "It is not possible to verify this signature.");
204 m_contextData.wacSecurity.getAuthorsCertificateChainListRef().push_back(
207 FOREACH(it, dnsIdentity){
208 if (widgetId.matchHost(*it)) {
209 m_contextData.wacSecurity.setRecognized(true);
215 void TaskCertify::stepSignature()
217 LogInfo("================ Step: <<Signature>> ENTER ===============");
219 std::string widgetPath;
220 if (m_contextData.widgetConfig.packagingType ==
221 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
223 widgetPath = m_contextData.locations->getSourceDir() + "/";
225 widgetPath = m_contextData.locations->getTemporaryPackageDir() + "/";
228 SignatureFileInfoSet signatureFiles;
229 SignatureFinder signatureFinder(widgetPath);
230 if (SignatureFinder::NO_ERROR != signatureFinder.find(signatureFiles)) {
231 LogError("Error in Signature Finder");
232 ThrowMsg(Exceptions::SignatureNotFound,
233 "Error openig temporary widget directory");
236 SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
237 LogInfo("Number of signatures: " << signatureFiles.size());
239 bool complianceMode = GlobalDAOReadOnly::getComplianceMode();
241 for (; iter != signatureFiles.rend(); ++iter) {
242 LogInfo("Checking signature with id=" << iter->getFileNumber());
243 SignatureData data(widgetPath + iter->getFileName(),
244 iter->getFileNumber());
248 xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
251 WrtSignatureValidator::AppType appType =
252 WrtSignatureValidator::WAC20;
254 if (m_installContext.widgetConfig.webAppType ==
255 APP_TYPE_TIZENWEBAPP)
257 appType = WrtSignatureValidator::TIZEN;
260 WrtSignatureValidator::Result result;
262 WrtSignatureValidator validator(
265 OCSPTestModeEnabled(),
267 CrlTestModeEnabled(),
270 result = validator.check(data, widgetPath);
272 if (m_contextData.widgetConfig.packagingType
273 == WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
275 // In directory installation mode, the validation is skipped.
277 result = WrtSignatureValidator::SIGNATURE_VERIFIED;
280 if (result == WrtSignatureValidator::SIGNATURE_REVOKED) {
281 LogWarning("Certificate is REVOKED");
282 ThrowMsg(Exceptions::CertificateExpired,
283 "Certificate is REVOKED");
286 if (result == WrtSignatureValidator::SIGNATURE_INVALID) {
287 LogWarning("Signature is INVALID");
288 // TODO change exception name
289 ThrowMsg(Exceptions::SignatureInvalid,
293 if (data.isAuthorSignature()) {
294 if (result == WrtSignatureValidator::SIGNATURE_VERIFIED ||
295 m_contextData.wacSecurity.isDistributorSigned())
297 processAuthorSignature(data);
299 WrtSignatureValidator::SIGNATURE_DISREGARD)
304 if (result == WrtSignatureValidator::SIGNATURE_DISREGARD) {
307 // now signature _must_ be verified
308 processDistributorSignature(data);
310 } Catch(ParserSchemaException::Base) {
311 LogError("Error occured in ParserSchema.");
312 ReThrowMsg(Exceptions::SignatureInvalid,
313 "Error occured in ParserSchema.");
317 if (signatureFiles.empty()) {
318 LogInfo("No signature files has been found.");
321 LogInfo("================ Step: <<Signature>> DONE ================");
323 m_contextData.job->UpdateProgress(
324 InstallerContext::INSTALL_DIGSIG_CHECK,
325 "Widget Signature checked");
328 void TaskCertify::createInstallPopup(PopupType type, const std::string &label)
330 m_contextData.job->Pause();
334 bool ret = createPopup();
336 loadPopup(type, label);
340 void TaskCertify::StepDeletePopupWin()
345 void TaskCertify::stepWarningPopup()
347 LogInfo("Step:: <<Warning Popup>>");
348 // SP-2151: If widget is not recognized (OCSP status of any of certificates
349 // it is signed with is not recognized) WRT must notify user that
350 // widget cannot be installed as a trusted application, and let the
351 // user decide whether it should be installed as an untrusted
353 if (!m_contextData.wacSecurity.isDistributorSigned()) {
354 std::string label = UNTRUSTED_WIDGET +
357 createInstallPopup(PopupType::WIDGET_UNRECOGNIZED, label);
361 std::string TaskCertify::createAuthorWidgetInfo() const
363 std::string authorInfo;
364 if (m_contextData.wacSecurity.isRecognized()) {
365 //authorInfo += _("IDS_IM_WIDGET_RECOGNISED");
366 authorInfo += _("WIDGET RECOGNISED");
368 //authorInfo += _("IDS_IM_WIDGET_UNRECOGNISED");
369 authorInfo += _("WIDGET UNRECOGNISED");
372 authorInfo += LABEL_NEW_LINE_2;
373 ValidationCore::CertificatePtr authorCert =
374 m_contextData.wacSecurity.getAuthorCertificatePtr();
376 DPL::Optional < DPL::String > organizationName =
377 authorCert->getOrganizationName();
379 //authorInfo += _("IDS_IM_WIDGET_AUTHOR_ORGANIZATION_NAME");
380 authorInfo += _("AUTHOR ORGANIZATION NAME");
381 authorInfo += LABEL_NEW_LINE;
383 if (!organizationName.IsNull()) {
384 authorInfo += DPL::ToUTF8String(*organizationName);
386 //authorInfo += _("IDS_IM_WIDGET_ORGANIZATION_UNKNOWN");
387 authorInfo += _("WIDGET ORGANIZATION UNKNOWN");
390 authorInfo += LABEL_NEW_LINE_2;
392 DPL::Optional < DPL::String > countryName =
393 authorCert->getCountryName();
395 //authorInfo += _("IDS_IM_WIDGET_COUNTRY_NAME");
396 authorInfo += _("WIDGET COUNTRY NAME");
397 authorInfo += LABEL_NEW_LINE;
399 if (!countryName.IsNull()) {
400 authorInfo += DPL::ToUTF8String(*countryName);
402 //authorInfo += _("IDS_IM_WIDGET_COUNTRY_UNKNOWN");
403 authorInfo += _("WIDGET COUNTRY UNKNOWN");
407 //_("IDS_IM_WIDGET_DOES_NOT_CONTAIN_RECOGNIZED_AUTHOR_SIGNATURE");
408 _("Widget does not contain recognized author signature");
413 void TaskCertify::stepAuthorInfoPopup()
415 LogInfo("Step:: <<Author Popup Information>>");
417 = createAuthorWidgetInfo() + LABEL_NEW_LINE_2 + QUESTION;
418 createInstallPopup(PopupType::WIDGET_AUTHOR_INFO, label);
421 void TaskCertify::stepFinalize()
423 LogInfo("Step: <<CERTYFYING DONE>>");
425 m_contextData.job->UpdateProgress(
426 InstallerContext::INSTALL_CERT_CHECK,
427 "Widget Certification Check Finished");
430 void TaskCertify::stepWarningPopupAnswer()
432 LogInfo("Step: <<Warning Popup Answer>>");
433 if (false == m_contextData.wacSecurity.isDistributorSigned() &&
434 WRT_POPUP_BUTTON_CANCEL == m_installCancel)
436 LogWarning("User does not agreed to install unsigned widgets!");
437 m_installCancel = WRT_POPUP_BUTTON;
439 ThrowMsg(Exceptions::NotAllowed, "Widget not allowed");
443 void TaskCertify::stepAuthorInfoPopupAnswer()
445 LogInfo("Step: <<Author Info Popup Answer>>");
446 if (WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
447 LogWarning("User does not agreed to install widget!");
448 m_installCancel = WRT_POPUP_BUTTON;
450 ThrowMsg(Exceptions::NotAllowed, "Widget not allowed");
454 bool TaskCertify::isTizenWebApp() const
457 if (m_installContext.widgetConfig.webAppType.appType
458 == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
466 void TaskCertify::stepVerifyUpdate()
468 LogInfo("Step: <<Check Update>>");
469 CertificatePtr newCertificate =
470 m_contextData.wacSecurity.getAuthorCertificatePtr();
471 CertificatePtr oldCertificate =
472 getOldAuthorSignerCertificate(m_installContext.widgetConfig.tzAppid);
474 if (!!newCertificate && !!oldCertificate) {
475 if (0 != newCertificate->getBase64().compare(oldCertificate->getBase64())) {
476 LogDebug("old widget's author signer certificate : " <<
477 oldCertificate->getBase64());
478 LogDebug("new widget's author signer certificate : " <<
479 newCertificate->getBase64());
480 ThrowMsg(Exceptions::NotMatchedCertification,
481 "Author signer certificates doesn't match \
482 between old widget and installing widget");
485 if (!(NULL == newCertificate.Get() && NULL == oldCertificate.Get())) {
486 ThrowMsg(Exceptions::NotMatchedCertification,
487 "Author signer certificates doesn't match \
488 between old widget and installing widget");
492 } //namespace WidgetInstall