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 <vcore/DeveloperModeValidator.h>
44 #include <dpl/utils/wrt_global_settings.h>
45 #include <dpl/wrt-dao-ro/global_dao_read_only.h>
47 #include <ITapiModem.h>
48 #include <tapi_common.h>
50 using namespace ValidationCore;
51 using namespace WrtDB;
54 const std::string LABEL_NEW_LINE = "<br>";
55 const std::string LABEL_NEW_LINE_2 = "<br><br>";
56 const std::string UNTRUSTED_WIDGET = "It is an Untrusted Widget";
57 const char *QUESTION = "Do you wanto to install?";
59 WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
62 WidgetCertificateData result;
64 result.chainId = data.getSignatureNumber();
65 LogDebug("result.chainId : " << result.chainId);
67 result.owner = data.isAuthorSignature() ?
68 WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR;
71 WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY;
73 CertificatePtr certificate;
76 certificate = data.getRootCaCertificatePtr();
78 certificate = data.getEndEntityCertificatePtr();
81 Assert(certificate && !certificate->getCommonName().IsNull() &&
82 "CommonName is Null");
84 result.strCommonName = *certificate->getCommonName();
86 result.strMD5Fingerprint = std::string("md5 ") +
87 Certificate::FingerprintToColonHex(
88 certificate->getFingerprint(Certificate::FINGERPRINT_MD5));
90 result.strSHA1Fingerprint = std::string("sha-1 ") +
91 Certificate::FingerprintToColonHex(
92 certificate->getFingerprint(Certificate::FINGERPRINT_SHA1));
97 CertificatePtr getOldAuthorSignerCertificate(DPL::String appid)
99 WidgetDAOReadOnly dao(appid);
100 CertificateChainList chainList = dao.getWidgetCertificate(SIGNATURE_AUTHOR);
102 FOREACH(it, chainList)
104 ValidationCore::CertificateCollection chain;
105 if (false == chain.load(*it)) {
106 LogError("Chain is broken");
110 LogError("Chain failed at sorting");
113 ValidationCore::CertificateList list = chain.getCertificateList();
117 if (!(*cert)->isRootCert() && !(*cert)->isCA()) {
122 return CertificatePtr(NULL);
124 } // namespace anonymous
127 namespace WidgetInstall {
128 TaskCertify::TaskCertify(InstallerContext &inCont) :
129 DPL::TaskDecl<TaskCertify>(this),
130 WidgetInstallPopup(inCont),
131 m_contextData(inCont)
133 AddStep(&TaskCertify::stepSignature);
134 // certi comparison determines whether the update.
135 if (true == m_contextData.existingWidgetInfo.isExist) {
136 AddStep(&TaskCertify::stepVerifyUpdate);
139 // Block until fixed popup issues
140 if (!GlobalSettings::PopupsTestModeEnabled()
141 && !m_installContext.m_quiet && !isTizenWebApp())
143 AddStep(&TaskCertify::stepWarningPopup);
144 AddStep(&TaskCertify::stepWarningPopupAnswer);
145 AddStep(&TaskCertify::stepAuthorInfoPopup);
146 AddStep(&TaskCertify::stepAuthorInfoPopupAnswer);
147 AddStep(&TaskCertify::StepDeletePopupWin);
149 AddStep(&TaskCertify::stepFinalize);
152 void TaskCertify::processDistributorSignature(const SignatureData &data)
154 // this signature is verified -
155 // no point in check domain WAC_ROOT and WAC_RECOGNIZED
156 m_contextData.wacSecurity.setDistributorSigned(true);
158 if (data.getStorageType().contains(CertStoreId::WAC_ROOT)) {
159 m_contextData.wacSecurity.setWacSigned(true);
162 CertificateCollection collection;
163 collection.load(data.getCertList());
164 Assert(collection.sort() &&
165 "Certificate collection can't sort");
167 Assert(collection.isChain() &&
168 "Certificate collection is not able to create chain. "
169 "It is not possible to verify this signature.");
171 m_contextData.wacSecurity.getCertificateChainListRef().push_back(
174 if (data.getSignatureNumber() == 1) {
175 m_contextData.wacSecurity.getCertificateListRef().push_back(
176 toWidgetCertificateData(data, true));
177 m_contextData.wacSecurity.getCertificateListRef().push_back(
178 toWidgetCertificateData(data, false));
182 void TaskCertify::processAuthorSignature(const SignatureData &data)
184 using namespace ValidationCore;
185 LogInfo("DNS Identity match!");
186 // this signature is verified or widget is distributor signed
187 m_contextData.wacSecurity.setAuthorCertificatePtr(data.getEndEntityCertificatePtr());
188 CertificatePtr test = m_contextData.wacSecurity.getAuthorCertificatePtr();
190 m_contextData.wacSecurity.getCertificateListRef().push_back(
191 toWidgetCertificateData(data, true));
192 m_contextData.wacSecurity.getCertificateListRef().push_back(
193 toWidgetCertificateData(data, false));
195 // match widget_id with one from dns identity set
196 WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id);
198 CertificatePtr cert = data.getEndEntityCertificatePtr();
200 Certificate::AltNameSet dnsIdentity = cert->getAlternativeNameDNS();
202 CertificateCollection collection;
203 collection.load(data.getCertList());
205 Assert(collection.isChain() &&
206 "Certificate collection is not able to create chain. "
207 "It is not possible to verify this signature.");
209 m_contextData.wacSecurity.getAuthorsCertificateChainListRef().push_back(
212 FOREACH(it, dnsIdentity){
213 if (widgetId.matchHost(*it)) {
214 m_contextData.wacSecurity.setRecognized(true);
220 void TaskCertify::stepSignature()
222 LogInfo("================ Step: <<Signature>> ENTER ===============");
224 std::string widgetPath;
225 if (m_contextData.widgetConfig.packagingType ==
226 WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
228 widgetPath = m_contextData.locations->getSourceDir() + "/";
230 widgetPath = m_contextData.locations->getTemporaryPackageDir() + "/";
233 SignatureFileInfoSet signatureFiles;
234 SignatureFinder signatureFinder(widgetPath);
235 if (SignatureFinder::NO_ERROR != signatureFinder.find(signatureFiles)) {
236 LogError("Error in Signature Finder");
237 ThrowMsg(Exceptions::InvalidPackage,
238 "Error openig temporary widget directory");
241 SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
242 LogInfo("Number of signatures: " << signatureFiles.size());
244 bool testCertificate = false;
246 bool complianceMode = GlobalDAOReadOnly::getComplianceMode();
248 for (; iter != signatureFiles.rend(); ++iter) {
249 LogInfo("Checking signature with id=" << iter->getFileNumber());
250 SignatureData data(widgetPath + iter->getFileName(),
251 iter->getFileNumber());
255 xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
258 WrtSignatureValidator::AppType appType =
259 WrtSignatureValidator::WAC20;
261 if (m_installContext.widgetConfig.webAppType ==
262 APP_TYPE_TIZENWEBAPP)
264 appType = WrtSignatureValidator::TIZEN;
267 WrtSignatureValidator::Result result;
269 WrtSignatureValidator validator(
272 OCSPTestModeEnabled(),
274 CrlTestModeEnabled(),
277 result = validator.check(data, widgetPath);
279 if (m_contextData.widgetConfig.packagingType
280 == WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
282 // In directory installation mode, the validation is skipped.
284 result = WrtSignatureValidator::SIGNATURE_VERIFIED;
287 if (result == WrtSignatureValidator::SIGNATURE_REVOKED) {
288 LogWarning("Certificate is REVOKED");
289 ThrowMsg(Exceptions::InvalidPackage,
290 "Certificate is REVOKED");
293 if (result == WrtSignatureValidator::SIGNATURE_INVALID) {
294 LogWarning("Signature is INVALID");
295 // TODO change exception name
296 ThrowMsg(Exceptions::InvalidPackage,
300 if (data.isAuthorSignature()) {
301 if (result == WrtSignatureValidator::SIGNATURE_VERIFIED ||
302 m_contextData.wacSecurity.isDistributorSigned())
304 processAuthorSignature(data);
306 WrtSignatureValidator::SIGNATURE_DISREGARD)
311 if (result == WrtSignatureValidator::SIGNATURE_DISREGARD) {
314 // now signature _must_ be verified
315 processDistributorSignature(data);
318 bool developerMode = GlobalDAOReadOnly::GetDeveloperMode();
320 std::string realMEID;
321 TapiHandle *tapiHandle = tel_init(NULL);
322 char *meid = tel_get_misc_me_sn_sync(tapiHandle);
327 tel_deinit(tapiHandle);
329 DeveloperModeValidator developerModeValidator(
332 GlobalDAOReadOnly::getComplianceFakeImei(),
333 GlobalDAOReadOnly::getComplianceFakeMeid(),
336 developerModeValidator.check(data);
339 data.getStorageType().contains(CertStoreId::DEVELOPER);
341 if (testCertificate && !developerMode) {
342 LogError("Widget signed by test certificate, "
343 "but developer mode is off.");
344 ThrowMsg(Exceptions::InvalidPackage,
345 "Widget signed by test certificate, "
346 "but developer mode is off.");
348 m_contextData.widgetConfig.isTestWidget = testCertificate;
349 } Catch(ParserSchemaException::Base) {
350 LogError("Error occured in ParserSchema.");
351 ReThrowMsg(Exceptions::InvalidPackage,
352 "Error occured in ParserSchema.");
354 Catch(DeveloperModeValidator::Exception::Base) {
355 LogError("Cannot validate developer certificate.");
356 ReThrowMsg(Exceptions::InvalidPackage,
357 "Cannot validate developer certificate.");
361 if (signatureFiles.empty()) {
362 LogInfo("No signature files has been found.");
365 LogInfo("================ Step: <<Signature>> DONE ================");
367 m_contextData.job->UpdateProgress(
368 InstallerContext::INSTALL_DIGSIG_CHECK,
369 "Widget Signature checked");
372 void TaskCertify::createInstallPopup(PopupType type, const std::string &label)
374 m_contextData.job->Pause();
378 bool ret = createPopup();
380 loadPopup(type, label);
384 void TaskCertify::StepDeletePopupWin()
389 void TaskCertify::stepWarningPopup()
391 LogInfo("Step:: <<Warning Popup>>");
392 // SP-2151: If widget is not recognized (OCSP status of any of certificates
393 // it is signed with is not recognized) WRT must notify user that
394 // widget cannot be installed as a trusted application, and let the
395 // user decide whether it should be installed as an untrusted
397 if (!m_contextData.wacSecurity.isDistributorSigned()) {
398 std::string label = UNTRUSTED_WIDGET +
401 createInstallPopup(PopupType::WIDGET_UNRECOGNIZED, label);
405 std::string TaskCertify::createAuthorWidgetInfo() const
407 std::string authorInfo;
408 if (m_contextData.wacSecurity.isRecognized()) {
409 //authorInfo += _("IDS_IM_WIDGET_RECOGNISED");
410 authorInfo += _("WIDGET RECOGNISED");
412 //authorInfo += _("IDS_IM_WIDGET_UNRECOGNISED");
413 authorInfo += _("WIDGET UNRECOGNISED");
416 authorInfo += LABEL_NEW_LINE_2;
417 ValidationCore::CertificatePtr authorCert =
418 m_contextData.wacSecurity.getAuthorCertificatePtr();
420 DPL::Optional < DPL::String > organizationName =
421 authorCert->getOrganizationName();
423 //authorInfo += _("IDS_IM_WIDGET_AUTHOR_ORGANIZATION_NAME");
424 authorInfo += _("AUTHOR ORGANIZATION NAME");
425 authorInfo += LABEL_NEW_LINE;
427 if (!organizationName.IsNull()) {
428 authorInfo += DPL::ToUTF8String(*organizationName);
430 //authorInfo += _("IDS_IM_WIDGET_ORGANIZATION_UNKNOWN");
431 authorInfo += _("WIDGET ORGANIZATION UNKNOWN");
434 authorInfo += LABEL_NEW_LINE_2;
436 DPL::Optional < DPL::String > countryName =
437 authorCert->getCountryName();
439 //authorInfo += _("IDS_IM_WIDGET_COUNTRY_NAME");
440 authorInfo += _("WIDGET COUNTRY NAME");
441 authorInfo += LABEL_NEW_LINE;
443 if (!countryName.IsNull()) {
444 authorInfo += DPL::ToUTF8String(*countryName);
446 //authorInfo += _("IDS_IM_WIDGET_COUNTRY_UNKNOWN");
447 authorInfo += _("WIDGET COUNTRY UNKNOWN");
451 //_("IDS_IM_WIDGET_DOES_NOT_CONTAIN_RECOGNIZED_AUTHOR_SIGNATURE");
452 _("Widget does not contain recognized author signature");
457 void TaskCertify::stepAuthorInfoPopup()
459 LogInfo("Step:: <<Author Popup Information>>");
461 = createAuthorWidgetInfo() + LABEL_NEW_LINE_2 + QUESTION;
462 createInstallPopup(PopupType::WIDGET_AUTHOR_INFO, label);
465 void TaskCertify::stepFinalize()
467 LogInfo("Step: <<CERTYFYING DONE>>");
469 m_contextData.job->UpdateProgress(
470 InstallerContext::INSTALL_CERT_CHECK,
471 "Widget Certification Check Finished");
474 void TaskCertify::stepWarningPopupAnswer()
476 LogInfo("Step: <<Warning Popup Answer>>");
477 if (false == m_contextData.wacSecurity.isDistributorSigned() &&
478 WRT_POPUP_BUTTON_CANCEL == m_installCancel)
480 LogWarning("User does not agreed to install unsigned widgets!");
481 m_installCancel = WRT_POPUP_BUTTON;
483 ThrowMsg(Exceptions::NotAllowed, "Widget not allowed");
487 void TaskCertify::stepAuthorInfoPopupAnswer()
489 LogInfo("Step: <<Author Info Popup Answer>>");
490 if (WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
491 LogWarning("User does not agreed to install widget!");
492 m_installCancel = WRT_POPUP_BUTTON;
494 ThrowMsg(Exceptions::NotAllowed, "Widget not allowed");
498 bool TaskCertify::isTizenWebApp() const
501 if (m_installContext.widgetConfig.webAppType.appType
502 == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
510 void TaskCertify::stepVerifyUpdate()
512 LogInfo("Step: <<Check Update>>");
513 CertificatePtr newCertificate =
514 m_contextData.wacSecurity.getAuthorCertificatePtr();
515 CertificatePtr oldCertificate =
516 getOldAuthorSignerCertificate(m_installContext.widgetConfig.tzAppid);
518 if (!!newCertificate && !!oldCertificate) {
519 if (0 != newCertificate->getBase64().compare(oldCertificate->getBase64())) {
520 LogDebug("old widget's author signer certificate : " <<
521 oldCertificate->getBase64());
522 LogDebug("new widget's author signer certificate : " <<
523 newCertificate->getBase64());
524 ThrowMsg(Exceptions::InvalidPackage,
525 "Author signer certificates doesn't match \
526 between old widget and installing widget");
529 if (!(NULL == newCertificate.Get() && NULL == oldCertificate.Get())) {
530 ThrowMsg(Exceptions::InvalidPackage,
531 "Author signer certificates doesn't match \
532 between old widget and installing widget");
536 } //namespace WidgetInstall