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 <dpl/event/nested_loop.h>
28 #include <appcore-common.h> //TODO is it necessary here?
32 #include <widget_install/task_certify.h>
33 #include <widget_install/job_widget_install.h>
34 #include <widget_install/widget_install_errors.h>
35 #include <widget_install/widget_install_context.h>
36 #include <dpl/log/log.h>
37 #include <wrt_error.h>
38 #include <dpl/wrt-dao-ro/global_config.h>
39 #include "wac_widget_id.h"
41 #include <vcore/SignatureReader.h>
42 #include <vcore/SignatureFinder.h>
43 #include <vcore/SignatureValidator.h>
44 #include <vcore/DeveloperModeValidator.h>
45 #include <dpl/utils/wrt_global_settings.h>
46 #include <dpl/wrt-dao-ro/global_dao_read_only.h>
48 using namespace ValidationCore;
49 using namespace WrtDB;
58 const std::string LABEL_NEW_LINE = "<br>";
59 const std::string LABEL_NEW_LINE_2 = "<br><br>";
61 WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
64 WidgetCertificateData result;
66 result.chainId = data.getSignatureNumber();
68 result.owner = data.isAuthorSignature() ?
69 WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR;
72 WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY;
74 CertificatePtr certificate;
77 certificate = data.getRootCaCertificatePtr();
79 certificate = data.getEndEntityCertificatePtr();
82 Assert(!certificate->getCommonName().IsNull() && "CommonName is Null");
84 result.strCommonName = *certificate->getCommonName();
86 result.strMD5Fingerprint = std::string("md5 ") +
87 SignatureValidator::FingerprintToColonHex(
88 certificate->getFingerprint(Certificate::FINGERPRINT_MD5));
90 result.strSHA1Fingerprint = std::string("sha-1 ") +
91 SignatureValidator::FingerprintToColonHex(
92 certificate->getFingerprint(Certificate::FINGERPRINT_SHA1));
96 } // namespace anonymous
99 namespace WidgetInstall {
100 TaskCertify::TaskCertify(InstallerContext &inCont) :
101 DPL::TaskDecl<TaskCertify>(this),
102 m_contextData(inCont),
103 m_cancelInstallation(false),
104 m_userAgreedToInstallUntrustedWidget(false)
106 AddStep(&TaskCertify::stepSignature);
107 AddStep(&TaskCertify::stepWarningPopup);
108 AddStep(&TaskCertify::stepWarningPopupAnswer);
109 AddStep(&TaskCertify::stepAuthorInfoPopup);
110 AddStep(&TaskCertify::stepAuthorInfoPopupAnswer);
111 AddStep(&TaskCertify::stepFinalize);
114 TaskCertify::~TaskCertify()
118 void TaskCertify::processDistributorSignature(const SignatureData &data,
121 // this signature is verified -
122 // no point in check domain WAC_ROOT and WAC_RECOGNIZED
123 m_contextData.wacSecurity.setDistributorSigned(true);
125 if (data.getStorageType().contains(CertStoreId::WAC_ROOT)) {
126 m_contextData.wacSecurity.setWacSigned(true);
129 CertificateCollection collection;
130 collection.load(data.getCertList());
132 Assert(collection.isChain() &&
133 "Certificate collection is not able to create chain. "
134 "It is not possible to verify this signature.");
136 m_contextData.wacSecurity.getCertificateChainListRef().push_back(
140 m_contextData.wacSecurity.getCertificateListRef().push_back(
141 toWidgetCertificateData(data, true));
142 m_contextData.wacSecurity.getCertificateListRef().push_back(
143 toWidgetCertificateData(data, false));
147 void TaskCertify::processAuthorSignature(const SignatureData &data)
149 using namespace ValidationCore;
150 LogInfo("DNS Identity match!");
151 // this signature is verified or widget is distributor signed
152 m_contextData.wacSecurity.getAuthorCertificatePtr() =
153 data.getEndEntityCertificatePtr();
154 m_contextData.wacSecurity.getCertificateListRef().push_back(
155 toWidgetCertificateData(data, true));
156 m_contextData.wacSecurity.getCertificateListRef().push_back(
157 toWidgetCertificateData(data, false));
159 // match widget_id with one from dns identity set
160 WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id);
162 Certificate::AltNameSet dnsIdentity =
163 data.getEndEntityCertificatePtr()->getAlternativeNameDNS();
165 FOREACH(it, dnsIdentity){
166 if (widgetId.matchHost(*it)) {
167 m_contextData.wacSecurity.setRecognized(true);
173 void TaskCertify::stepSignature()
175 Assert(!m_contextData.tempWidgetPath.empty());
177 std::string widgetPath = m_contextData.tempWidgetPath + "/";
179 SignatureFileInfoSet signatureFiles;
180 SignatureFinder signatureFinder(widgetPath);
181 if (SignatureFinder::NO_ERROR != signatureFinder.find(signatureFiles)) {
182 LogError("Error in Signature Finder");
183 ThrowMsg(Exceptions::InvalidPackage,
184 "Error openig temporary widget directory");
187 SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
188 LogInfo("No of signatures: " << signatureFiles.size());
190 bool firstDistributorSignature = true;
191 bool testCertificate = false;
193 bool complianceMode = GlobalDAOReadOnly::getComplianceMode();
195 for (; iter != signatureFiles.rend(); ++iter) {
196 LogInfo("Checking signature with id=" << iter->getFileNumber());
197 SignatureData data(widgetPath + iter->getFileName(),
198 iter->getFileNumber());
202 xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
204 SignatureValidator validator(GlobalConfig::IsOCSPEnabled(),
205 GlobalConfig::IsCRLEnabled(),
207 SignatureValidator::Result result =
208 validator.check(data, widgetPath);
210 if (result == SignatureValidator::SIGNATURE_REVOKED) {
211 LogWarning("Certificate is REVOKED");
212 ThrowMsg(Exceptions::InvalidPackage,
213 "Certificate is REVOKED");
216 if (result == SignatureValidator::SIGNATURE_INVALID) {
217 LogWarning("Signature is INVALID");
218 // TODO change exception name
219 ThrowMsg(Exceptions::InvalidPackage,
223 if (data.isAuthorSignature()) {
224 if (result == SignatureValidator::SIGNATURE_VERIFIED ||
225 m_contextData.wacSecurity.isDistributorSigned())
227 processAuthorSignature(data);
228 } else if (result == SignatureValidator::SIGNATURE_DISREGARD) {
232 if (result == SignatureValidator::SIGNATURE_DISREGARD) {
235 // now signature _must_ be verified
236 processDistributorSignature(data, firstDistributorSignature);
237 firstDistributorSignature = false;
240 DeveloperModeValidator developerModeValidator(
242 GlobalDAOReadOnly::getComplianceFakeImei(),
243 GlobalDAOReadOnly::getComplianceFakeMeid());
245 developerModeValidator.check(data);
248 data.getStorageType().contains(CertStoreId::DEVELOPER);
250 bool developerMode = GlobalDAOReadOnly::GetDeveloperMode();
252 if (testCertificate && !developerMode) {
253 LogDebug("Widget signed by test certificate, "
254 "but developer mode is off.");
255 ThrowMsg(Exceptions::InvalidPackage,
256 "Widget signed by test certificate, "
257 "but developer mode is off.");
259 m_contextData.widgetConfig.isTestWidget = testCertificate;
260 } Catch(ParserSchemaException::Base) {
261 LogDebug("Error occured in ParserSchema.");
262 ReThrowMsg(Exceptions::InvalidPackage,
263 "Error occured in ParserSchema.");
265 Catch(DeveloperModeValidator::Exception::Base) {
266 LogDebug("Cannot validate developer certificate.");
267 ReThrowMsg(Exceptions::InvalidPackage,
268 "Cannot validate developer certificate.");
272 if (signatureFiles.empty()) {
273 LogInfo("No signature files has been found.");
276 LogInfo("================ Step: <<CSignature>> DONE ================");
279 void TaskCertify::stepWarningPopup()
281 LogInfo("Step:: <<Warning Popup>>");
282 // SP-2151: If widget is not recognized (OCSP status of any of certificates
283 // it is signed with is not recognized) WRT must notify user that
284 // widget cannot be installed as a trusted application, and let the
285 // user decide whether it should be installed as an untrusted
287 if (!m_contextData.wacSecurity.isDistributorSigned()) {
288 if (GlobalSettings::GetPopupsEnabledFlag()) {
289 m_contextData.job->Pause();
290 std::string label = _("IDS_IM_POP_WIDGET_UNTRUSTED_WARNING") +
292 _("IDS_IM_WIDGET_WANT_TO_INSTALL");
293 using namespace DPL::Popup;
295 PopupControllerSingleton::Instance().CreatePopup();
296 popup->SetTitle(_("IDS_IM_POP_WIDGET_UNTRUSTED_TITLE"));
297 popup->Append(new PopupObject::Label(label));
298 popup->Append(new PopupObject::Button(_("IDS_IM_BUTTON_INSTALL"),
300 popup->Append(new PopupObject::Button(_("IDS_IM_BUTTON_RESIGN"),
303 ListenForAnswer(popup);
305 PopupAnswerCallback cb = MakeAnswerCallback(this,
306 &TaskCertify::onWarningPopupAnswer);
308 ShowPopupEvent event(popup, cb, DPL::Event::UNDEFINED_LOOP_HANDLE);
309 CONTROLLER_POST_EVENT(PopupController, event);
311 m_userAgreedToInstallUntrustedWidget = true;
316 void TaskCertify::stepWarningPopupAnswer()
318 LogInfo("Step: <<Warning Popup Answer>>");
319 if (false == m_contextData.wacSecurity.isDistributorSigned() &&
320 false == m_userAgreedToInstallUntrustedWidget)
322 LogWarning("User does not agreed to install unsigned widgets!");
323 ThrowMsg(Exceptions::NotAllowed, "Widget not allowed");
327 void TaskCertify::stepAuthorInfoPopupAnswer()
329 LogInfo("Step: <<Author Info Popup Answer>>");
330 if (m_cancelInstallation) {
331 LogWarning("User does not agreed to install widget!");
332 ThrowMsg(Exceptions::NotAllowed, "Widget not allowed");
336 std::string TaskCertify::createAuthorWidgetInfo() const
338 std::string authorInfo;
339 if (m_contextData.wacSecurity.isRecognized()) {
340 authorInfo += _("IDS_IM_WIDGET_RECOGNISED");
342 authorInfo += _("IDS_IM_WIDGET_UNRECOGNISED");
345 authorInfo += LABEL_NEW_LINE_2;
346 ValidationCore::CertificatePtr authorCert =
347 m_contextData.wacSecurity.getAuthorCertificatePtr();
349 DPL::Optional < DPL::String > organizationName =
350 authorCert->getOrganizationName();
352 authorInfo += _("IDS_IM_WIDGET_AUTHOR_ORGANIZATION_NAME");
353 authorInfo += LABEL_NEW_LINE;
355 if (!organizationName.IsNull()) {
356 authorInfo += DPL::ToUTF8String(*organizationName);
358 authorInfo += _("IDS_IM_WIDGET_ORGANIZATION_UNKNOWN");
361 authorInfo += LABEL_NEW_LINE_2;
363 DPL::Optional < DPL::String > countryName =
364 authorCert->getCountryName();
366 authorInfo += _("IDS_IM_WIDGET_COUNTRY_NAME");
367 authorInfo += LABEL_NEW_LINE;
369 if (!countryName.IsNull()) {
370 authorInfo += DPL::ToUTF8String(*countryName);
372 authorInfo += _("IDS_IM_WIDGET_COUNTRY_UNKNOWN");
376 _("IDS_IM_WIDGET_DOES_NOT_CONTAIN_RECOGNIZED_AUTHOR_SIGNATURE");
381 void TaskCertify::stepAuthorInfoPopup()
383 LogInfo("Step:: <<Author Popup Information>>");
385 if (!GlobalSettings::GetPopupsEnabledFlag()) {
386 LogDebug("Popups are not enabled! Author information wont be shown.");
390 using namespace DPL::Popup;
391 m_contextData.job->Pause();
392 std::string label = createAuthorWidgetInfo() + LABEL_NEW_LINE + _("IDS_IM_WIDGET_WANT_TO_INSTALL");
394 CtrlPopupPtr popup = PopupControllerSingleton::Instance().CreatePopup();
395 popup->SetTitle(_("IDS_IM_WIDGET_HEAD"));
396 popup->Append(new PopupObject::Label(label));
397 popup->Append(new PopupObject::Button(_("IDS_IM_BUTTON_INSTALL"),
399 popup->Append(new PopupObject::Button(_("IDS_IM_BUTTON_RESIGN"),
401 ListenForAnswer(popup);
402 ShowPopupEvent event(popup,
405 &TaskCertify::onAuthorInfoPopupAnswer),
406 DPL::Event::UNDEFINED_LOOP_HANDLE);
407 CONTROLLER_POST_EVENT(PopupController, event);
410 void TaskCertify::stepFinalize()
412 LogInfo("Step: <<CERTYFYING DONE>>");
415 void TaskCertify::onWarningPopupAnswer(const DPL::Popup::AnswerCallbackData& answer)
417 m_contextData.job->Resume();
418 if (BUTTON_ID_RESIGN == answer.buttonAnswer) {
419 m_userAgreedToInstallUntrustedWidget = false;
420 } else if (BUTTON_ID_INSTALL == answer.buttonAnswer) {
421 m_userAgreedToInstallUntrustedWidget = true;
423 Assert(false && "Unpredicted answer received.");
427 void TaskCertify::onAuthorInfoPopupAnswer(
428 const DPL::Popup::AnswerCallbackData& answer)
430 m_contextData.job->Resume();
431 if (BUTTON_ID_RESIGN == answer.buttonAnswer) {
432 m_cancelInstallation = true;
435 } //namespace WidgetInstall