/* * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * @file task_certify.cpp * @author Pawel Sikorski (p.sikorski@samgsung.com) * @version * @brief */ //SYSTEM INCLUDES #include #include #include #include //TODO is it necessary here? #include //WRT INCLUDES #include #include #include #include #include #include #include #include "wac_widget_id.h" #include #include #include #include #include #include #include #include using namespace ValidationCore; using namespace WrtDB; namespace { const std::string LABEL_NEW_LINE = "
"; const std::string LABEL_NEW_LINE_2 = "

"; const std::string UNTRUSTED_WIDGET ="It is an Untrusted Widget"; const char *QUESTION ="Do you wanto to install?"; WidgetCertificateData toWidgetCertificateData(const SignatureData &data, bool root) { WidgetCertificateData result; result.chainId = data.getSignatureNumber(); result.owner = data.isAuthorSignature() ? WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR; result.type = root ? WidgetCertificateData::ROOT : WidgetCertificateData::ENDENTITY; CertificatePtr certificate; if (root) { certificate = data.getRootCaCertificatePtr(); } else { certificate = data.getEndEntityCertificatePtr(); } Assert(certificate && !certificate->getCommonName().IsNull() && "CommonName is Null"); result.strCommonName = *certificate->getCommonName(); result.strMD5Fingerprint = std::string("md5 ") + SignatureValidator::FingerprintToColonHex( certificate->getFingerprint(Certificate::FINGERPRINT_MD5)); result.strSHA1Fingerprint = std::string("sha-1 ") + SignatureValidator::FingerprintToColonHex( certificate->getFingerprint(Certificate::FINGERPRINT_SHA1)); return result; } } // namespace anonymous namespace Jobs { namespace WidgetInstall { TaskCertify::TaskCertify(InstallerContext &inCont) : DPL::TaskDecl(this), m_contextData(inCont), WidgetInstallPopup(inCont) { AddStep(&TaskCertify::stepSignature); // Block until fixed popup issues if (!GlobalSettings::TestModeEnabled() && !m_installContext.m_quiet && !isTizenWebApp()) { AddStep(&TaskCertify::stepWarningPopup); AddStep(&TaskCertify::stepWarningPopupAnswer); AddStep(&TaskCertify::stepAuthorInfoPopup); AddStep(&TaskCertify::stepAuthorInfoPopupAnswer); AddStep(&TaskCertify::StepDeletePopupWin); } AddStep(&TaskCertify::stepFinalize); } void TaskCertify::processDistributorSignature(const SignatureData &data, bool first) { // this signature is verified - // no point in check domain WAC_ROOT and WAC_RECOGNIZED m_contextData.wacSecurity.setDistributorSigned(true); if (data.getStorageType().contains(CertStoreId::WAC_ROOT)) { m_contextData.wacSecurity.setWacSigned(true); } CertificateCollection collection; collection.load(data.getCertList()); collection.sort(); Assert(collection.isChain() && "Certificate collection is not able to create chain. " "It is not possible to verify this signature."); m_contextData.wacSecurity.getCertificateChainListRef().push_back( collection); if (first) { m_contextData.wacSecurity.getCertificateListRef().push_back( toWidgetCertificateData(data, true)); m_contextData.wacSecurity.getCertificateListRef().push_back( toWidgetCertificateData(data, false)); } } void TaskCertify::processAuthorSignature(const SignatureData &data) { using namespace ValidationCore; LogInfo("DNS Identity match!"); // this signature is verified or widget is distributor signed m_contextData.wacSecurity.getAuthorCertificatePtr() = data.getEndEntityCertificatePtr(); m_contextData.wacSecurity.getCertificateListRef().push_back( toWidgetCertificateData(data, true)); m_contextData.wacSecurity.getCertificateListRef().push_back( toWidgetCertificateData(data, false)); // match widget_id with one from dns identity set WacWidgetId widgetId(m_contextData.widgetConfig.configInfo.widget_id); CertificatePtr cert = data.getEndEntityCertificatePtr(); Assert(cert); Certificate::AltNameSet dnsIdentity = cert->getAlternativeNameDNS(); FOREACH(it, dnsIdentity){ if (widgetId.matchHost(*it)) { m_contextData.wacSecurity.setRecognized(true); return; } } } void TaskCertify::stepSignature() { LogInfo("enter"); std::string widgetPath = m_contextData.locations->getTemporaryRootDir() + "/"; SignatureFileInfoSet signatureFiles; SignatureFinder signatureFinder(widgetPath); if (SignatureFinder::NO_ERROR != signatureFinder.find(signatureFiles)) { LogError("Error in Signature Finder"); ThrowMsg(Exceptions::InvalidPackage, "Error openig temporary widget directory"); } SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin(); LogInfo("No of signatures: " << signatureFiles.size()); bool firstDistributorSignature = true; bool testCertificate = false; bool complianceMode = GlobalDAOReadOnly::getComplianceMode(); for (; iter != signatureFiles.rend(); ++iter) { LogInfo("Checking signature with id=" << iter->getFileNumber()); SignatureData data(widgetPath + iter->getFileName(), iter->getFileNumber()); Try { SignatureReader xml; xml.initialize(data, GlobalConfig::GetSignatureXmlSchema()); xml.read(data); SignatureValidator validator(!GlobalSettings::TestModeEnabled(), !GlobalSettings::TestModeEnabled(), complianceMode); SignatureValidator::Result result = validator.check(data, widgetPath); if (result == SignatureValidator::SIGNATURE_REVOKED) { LogWarning("Certificate is REVOKED"); ThrowMsg(Exceptions::InvalidPackage, "Certificate is REVOKED"); } if (result == SignatureValidator::SIGNATURE_INVALID) { LogWarning("Signature is INVALID"); // TODO change exception name ThrowMsg(Exceptions::InvalidPackage, "Invalid Package"); } if (data.isAuthorSignature()) { if (result == SignatureValidator::SIGNATURE_VERIFIED || m_contextData.wacSecurity.isDistributorSigned()) { processAuthorSignature(data); } else if (result == SignatureValidator::SIGNATURE_DISREGARD) { continue; } } else { if (result == SignatureValidator::SIGNATURE_DISREGARD) { continue; } // now signature _must_ be verified processDistributorSignature(data, firstDistributorSignature); firstDistributorSignature = false; } bool developerMode = GlobalDAOReadOnly::GetDeveloperMode(); std::string realMEID; TapiHandle *tapiHandle = tel_init(NULL); char *meid = tel_get_misc_me_sn_sync(tapiHandle); if (meid) { realMEID = meid; free(meid); } tel_deinit(tapiHandle); DeveloperModeValidator developerModeValidator( complianceMode, developerMode, GlobalDAOReadOnly::getComplianceFakeImei(), GlobalDAOReadOnly::getComplianceFakeMeid(), realMEID); developerModeValidator.check(data); testCertificate |= data.getStorageType().contains(CertStoreId::DEVELOPER); if (testCertificate && !developerMode) { LogDebug("Widget signed by test certificate, " "but developer mode is off."); ThrowMsg(Exceptions::InvalidPackage, "Widget signed by test certificate, " "but developer mode is off."); } m_contextData.widgetConfig.isTestWidget = testCertificate; } Catch(ParserSchemaException::Base) { LogDebug("Error occured in ParserSchema."); ReThrowMsg(Exceptions::InvalidPackage, "Error occured in ParserSchema."); } Catch(DeveloperModeValidator::Exception::Base) { LogDebug("Cannot validate developer certificate."); ReThrowMsg(Exceptions::InvalidPackage, "Cannot validate developer certificate."); } } if (signatureFiles.empty()) { LogInfo("No signature files has been found."); } LogInfo("================ Step: <> DONE ================"); m_contextData.job->UpdateProgress( InstallerContext::INSTALL_DIGSIG_CHECK, "Widget Signature checked"); } void TaskCertify::createInstallPopup(PopupType type, const std::string &label) { m_contextData.job->Pause(); if(m_popup) destroyPopup(); bool ret = createPopup(); if(ret) { loadPopup(type, label); showPopup(); } } void TaskCertify::StepDeletePopupWin() { destroyPopup(); } void TaskCertify::stepWarningPopup() { LogInfo("Step:: <>"); // SP-2151: If widget is not recognized (OCSP status of any of certificates // it is signed with is not recognized) WRT must notify user that // widget cannot be installed as a trusted application, and let the // user decide whether it should be installed as an untrusted // application. if (!m_contextData.wacSecurity.isDistributorSigned()) { std::string label = UNTRUSTED_WIDGET + LABEL_NEW_LINE_2 + QUESTION; createInstallPopup(PopupType::WIDGET_UNRECOGNIZED, label); } } std::string TaskCertify::createAuthorWidgetInfo() const { std::string authorInfo; if (m_contextData.wacSecurity.isRecognized()) { //authorInfo += _("IDS_IM_WIDGET_RECOGNISED"); authorInfo += _("WIDGET RECOGNISED"); } else { //authorInfo += _("IDS_IM_WIDGET_UNRECOGNISED"); authorInfo += _("WIDGET UNRECOGNISED"); } authorInfo += LABEL_NEW_LINE_2; ValidationCore::CertificatePtr authorCert = m_contextData.wacSecurity.getAuthorCertificatePtr(); if (!!authorCert) { DPL::Optional < DPL::String > organizationName = authorCert->getOrganizationName(); //authorInfo += _("IDS_IM_WIDGET_AUTHOR_ORGANIZATION_NAME"); authorInfo += _("AUTHOR ORGANIZATION NAME"); authorInfo += LABEL_NEW_LINE; if (!organizationName.IsNull()) { authorInfo += DPL::ToUTF8String(*organizationName); } else { //authorInfo += _("IDS_IM_WIDGET_ORGANIZATION_UNKNOWN"); authorInfo += _("WIDGET ORGANIZATION UNKNOWN"); } authorInfo += LABEL_NEW_LINE_2; DPL::Optional < DPL::String > countryName = authorCert->getCountryName(); //authorInfo += _("IDS_IM_WIDGET_COUNTRY_NAME"); authorInfo += _("WIDGET COUNTRY NAME"); authorInfo += LABEL_NEW_LINE; if (!countryName.IsNull()) { authorInfo += DPL::ToUTF8String(*countryName); } else { //authorInfo += _("IDS_IM_WIDGET_COUNTRY_UNKNOWN"); authorInfo += _("WIDGET COUNTRY UNKNOWN"); } } else { authorInfo += //_("IDS_IM_WIDGET_DOES_NOT_CONTAIN_RECOGNIZED_AUTHOR_SIGNATURE"); _("Widget does not contain recognized author signature"); } return authorInfo; } void TaskCertify::stepAuthorInfoPopup() { LogInfo("Step:: <>"); std::string label = createAuthorWidgetInfo() + LABEL_NEW_LINE_2 + QUESTION; createInstallPopup(PopupType::WIDGET_AUTHOR_INFO, label); } void TaskCertify::stepFinalize() { LogInfo("Step: <>"); m_contextData.job->UpdateProgress( InstallerContext::INSTALL_CERT_CHECK, "Widget Certification Check Finished"); } void TaskCertify::stepWarningPopupAnswer() { LogInfo("Step: <>"); if (false == m_contextData.wacSecurity.isDistributorSigned() && WRT_POPUP_BUTTON_CANCEL == m_installCancel) { LogWarning("User does not agreed to install unsigned widgets!"); m_installCancel = WRT_POPUP_BUTTON; destroyPopup(); ThrowMsg(Exceptions::NotAllowed, "Widget not allowed"); } } void TaskCertify::stepAuthorInfoPopupAnswer() { LogInfo("Step: <>"); if ( WRT_POPUP_BUTTON_CANCEL == m_installCancel) { LogWarning("User does not agreed to install widget!"); m_installCancel = WRT_POPUP_BUTTON; destroyPopup(); ThrowMsg(Exceptions::NotAllowed, "Widget not allowed"); } } bool TaskCertify::isTizenWebApp() const { bool ret = FALSE; if (m_installContext.widgetConfig.type.appType == WrtDB::AppType::APP_TYPE_TIZENWEBAPP) ret = TRUE; return ret; } } //namespace WidgetInstall } //namespace Jobs