From 59eed4211859fc7393543d59be0149a6952db3f5 Mon Sep 17 00:00:00 2001 From: Jihoon Chung Date: Sun, 14 Jul 2013 20:15:14 +0900 Subject: [PATCH] Implement task to check "tizen:setting" [Issue#] N/A [Problem] Current wrt-installer only checks "tizen:privilege" level, even manifest received many requirement of sensitive "tizen:setting" [Cause] N/A [Solution] Implement task "task_certify_level" To avoid sensitive manifest setting is used by untrust application, installer needs to check privilege level of application. This commit doesn't use global, static and member value intentionally to reduce attack. [SCMRequest] N/A Change-Id: Icb63c2ad3b02a57c90d39f729db159a84576f348 --- configuration/widgets.tizen.xsd | 8 + src/CMakeLists.txt | 1 + src/jobs/widget_install/job_widget_install.cpp | 5 +- src/jobs/widget_install/task_certify_level.cpp | 234 +++++++++++++++++++++++ src/jobs/widget_install/task_certify_level.h | 73 +++++++ src/jobs/widget_install/widget_install_context.h | 1 + 6 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 src/jobs/widget_install/task_certify_level.cpp create mode 100644 src/jobs/widget_install/task_certify_level.h diff --git a/configuration/widgets.tizen.xsd b/configuration/widgets.tizen.xsd index 0d8233a..5a99dc3 100644 --- a/configuration/widgets.tizen.xsd +++ b/configuration/widgets.tizen.xsd @@ -40,6 +40,13 @@ + + + + + + + @@ -78,6 +85,7 @@ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d842af9..93a2431 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,6 +70,7 @@ SET(INSTALLER_SOURCES ${INSTALLER_JOBS}/widget_install/task_ace_check.cpp ${INSTALLER_JOBS}/widget_install/task_manifest_file.cpp ${INSTALLER_JOBS}/widget_install/task_certify.cpp + ${INSTALLER_JOBS}/widget_install/task_certify_level.cpp ${INSTALLER_JOBS}/widget_install/task_prepare_files.cpp ${INSTALLER_JOBS}/widget_install/task_recovery.cpp ${INSTALLER_JOBS}/widget_install/task_install_ospsvc.cpp diff --git a/src/jobs/widget_install/job_widget_install.cpp b/src/jobs/widget_install/job_widget_install.cpp index 3b45ff2..12a7d7a 100644 --- a/src/jobs/widget_install/job_widget_install.cpp +++ b/src/jobs/widget_install/job_widget_install.cpp @@ -55,6 +55,7 @@ #include "parser_runner.h" #include #include +#include #include #include #include @@ -190,7 +191,7 @@ JobWidgetInstall::JobWidgetInstall( if (m_needEncryption) { AddTask(new TaskEncryptResource(m_installerContext)); } - + AddTask(new TaskCertifyLevel(m_installerContext)); AddTask(new TaskFileManipulation(m_installerContext)); AddTask(new TaskManifestFile(m_installerContext)); if (m_installerContext.widgetConfig.packagingType == @@ -225,7 +226,7 @@ JobWidgetInstall::JobWidgetInstall( if (m_needEncryption) { AddTask(new TaskEncryptResource(m_installerContext)); } - + AddTask(new TaskCertifyLevel(m_installerContext)); if (m_installerContext.mode.extension != InstallMode::ExtensionType::DIR) { AddTask(new TaskUpdateFiles(m_installerContext)); diff --git a/src/jobs/widget_install/task_certify_level.cpp b/src/jobs/widget_install/task_certify_level.cpp new file mode 100644 index 0000000..6c77ccf --- /dev/null +++ b/src/jobs/widget_install/task_certify_level.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2013 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 Jihoon Chung (jihoon.chung@samgsung.com) + * @version + * @brief + */ + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace ValidationCore; +using namespace WrtDB; + +namespace Jobs { +namespace WidgetInstall { +TaskCertifyLevel::TaskCertifyLevel(InstallerContext &inCont) : + DPL::TaskDecl(this), + m_contextData(inCont) +{ + AddStep(&TaskCertifyLevel::stepCertifyLevel); +} + +void TaskCertifyLevel::stepCertifyLevel() +{ + LogDebug("================ Step: <> ENTER ==============="); + if (!checkSettingLevel(getCertifyLevel())) { + ThrowMsg(Exceptions::PrivilegeLevelViolation, "setting level violate"); + } + LogDebug("================ Step: <> DONE ================"); + + m_contextData.job->UpdateProgress( + InstallerContext::INSTALL_CERTIFY_LEVEL_CHECK, + "Application Certificate level check Finished"); +} + +void TaskCertifyLevel::getSignatureFiles(const std::string& path, + SignatureFileInfoSet& file) +{ + SignatureFileInfoSet signatureFiles; + SignatureFinder signatureFinder(path); + if (SignatureFinder::NO_ERROR != signatureFinder.find(file)) { + LogError("Error in Signature Finder : " << path); + ThrowMsg(Exceptions::SignatureNotFound, "Signature not found"); + } +} + +TaskCertifyLevel::Level TaskCertifyLevel::getCertifyLevel() +{ + std::string widgetPath; + widgetPath = m_contextData.locations->getTemporaryPackageDir() + "/"; + + if (m_contextData.mode.command == InstallMode::Command::REINSTALL) { + widgetPath = + m_contextData.locations->getPackageInstallationDir() + "/"; + } + + SignatureFileInfoSet signatureFiles; + + Try { + getSignatureFiles(widgetPath, signatureFiles); + + if (signatureFiles.size() <= 0) { + widgetPath += std::string(WrtDB::GlobalConfig::GetWidgetSrcPath()) + + "/"; + if (0 == access(widgetPath.c_str(), F_OK)) { + getSignatureFiles(widgetPath, signatureFiles); + } + } + } Catch(Exceptions::SignatureNotFound) { + ReThrowMsg(Exceptions::SignatureNotFound, widgetPath); + } + + SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin(); + LogDebug("Number of signatures: " << signatureFiles.size()); + + Level level = Level::UNKNOWN; + for (; iter != signatureFiles.rend(); ++iter) { + LogDebug("Checking signature with id=" << iter->getFileNumber()); + SignatureData data(widgetPath + iter->getFileName(), + iter->getFileNumber()); + + Try { + SignatureReader xml; + xml.initialize(data, GlobalConfig::GetSignatureXmlSchema()); + xml.read(data); + + WrtSignatureValidator validator( + WrtSignatureValidator::TIZEN, + !GlobalSettings:: + OCSPTestModeEnabled(), + !GlobalSettings:: + CrlTestModeEnabled(), + false); + + WrtSignatureValidator::Result result = + validator.check(data, widgetPath); + + if (m_contextData.mode.installTime + == InstallMode::InstallTime::PRELOAD) + { + result = WrtSignatureValidator::SIGNATURE_VERIFIED; + } + + if (result == WrtSignatureValidator::SIGNATURE_REVOKED) { + ThrowMsg(Exceptions::CertificateExpired, + "Certificate is REVOKED"); + } + + if (result == WrtSignatureValidator::SIGNATURE_INVALID && + iter->getFileNumber() <= 1) + { + ThrowMsg(Exceptions::SignatureInvalid, "Invalid Package"); + } + + if (data.isAuthorSignature()) { + LogDebug("Skip author signature"); + } else { + Level currentCertLevel = + certTypeToLevel(data.getVisibilityLevel()); + if (currentCertLevel == Level::UNKNOWN) { + continue; + } + if (currentCertLevel > level) { + level = currentCertLevel; + LogDebug("level " << enumToString(level)); + } + } + } Catch(ParserSchemaException::Base) { + LogError("Error occured in ParserSchema."); + ReThrowMsg(Exceptions::SignatureInvalid, + "Error occured in ParserSchema."); + } + } + + return level; +} + +bool TaskCertifyLevel::checkSettingLevel( + TaskCertifyLevel::Level level) +{ + secureSettingMap data = { + {"sound-mode", Level::PARTNER} + }; + + FOREACH(it, m_contextData.widgetConfig.configInfo.settingsList) { + secureSettingIter ret = data.find(DPL::ToUTF8String(it->m_name)); + if (ret != data.end()) { + if (level < ret->second) { + LogError("\"" << + it->m_name << + "\" needs \"" << + enumToString(ret->second) << + "\" level"); + return false; + } + } + } + return true; +} + +std::string TaskCertifyLevel::enumToString( + TaskCertifyLevel::Level level) +{ + switch (level) { +#define X(x, y) case x: return #y; + X(Level::UNKNOWN, UNKNOWN) + X(Level::PUBLIC, PUBLIC) + X(Level::PARTNER, PARTNER) + X(Level::PLATFORM, PLATFORM) +#undef X + default: + return "UNKNOWN"; + } +} + +TaskCertifyLevel::Level TaskCertifyLevel::certTypeToLevel( + CertStoreId::Type type) +{ + // CertStoreType.h (framework/security/cert-svc) + // RootCA's visibility level : public + // const Type VIS_PUBLIC = 1 << 6; + // RootCA's visibility level : partner + // const Type VIS_PARTNER = 1 << 7; + // RootCA's visibility level : platform + // const Type VIS_PLATFORM = 1 << 10; + if (type == CertStoreId::VIS_PUBLIC) { + return Level::PUBLIC; + } else if (type == CertStoreId::VIS_PARTNER) { + return Level::PARTNER; + } else if (type == CertStoreId::VIS_PLATFORM) { + return Level::PLATFORM; + } + return Level::UNKNOWN; +} + +} //namespace WidgetInstall +} //namespace Jobs + diff --git a/src/jobs/widget_install/task_certify_level.h b/src/jobs/widget_install/task_certify_level.h new file mode 100644 index 0000000..ae8ce40 --- /dev/null +++ b/src/jobs/widget_install/task_certify_level.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 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_level.h + * @author Jihoon Chung (jihoon.chung@samgsung.com) + * @version + * @brief + */ +#ifndef INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H +#define INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H + +//SYSTEM INCLUDES +#include +#include +#include + +//WRT INCLUDES +#include +#include +#include + +class InstallerContext; + +namespace Jobs { +namespace WidgetInstall { +class TaskCertifyLevel : + public DPL::TaskDecl +{ + public: + TaskCertifyLevel(InstallerContext &inCont); + + private: + //data + InstallerContext& m_contextData; + + enum class Level : std::int8_t { + UNKNOWN = 0, + PUBLIC = 1, + PARTNER = 2, + PLATFORM = 3 + }; + typedef std::map secureSettingMap; + typedef std::map::iterator secureSettingIter; + + //steps + void stepCertifyLevel(); + + //util + void getSignatureFiles(const std::string& path, + ValidationCore::SignatureFileInfoSet& file); + Level getCertifyLevel(); + bool checkSettingLevel(Level level); + std::string enumToString(Level level); + Level certTypeToLevel(ValidationCore::CertStoreId::Type type); + +}; +} //namespace WidgetInstall +} //namespace Jobs + +#endif // INSTALLER_CORE_JOS_WIDGET_INSTALL_TASK_CERTIFY_LEVEL_H diff --git a/src/jobs/widget_install/widget_install_context.h b/src/jobs/widget_install/widget_install_context.h index 0317c0d..649de9b 100644 --- a/src/jobs/widget_install/widget_install_context.h +++ b/src/jobs/widget_install/widget_install_context.h @@ -56,6 +56,7 @@ struct InstallerContext INSTALL_WIDGET_CONFIG2, INSTALL_DIGSIG_CHECK, INSTALL_CERT_CHECK, + INSTALL_CERTIFY_LEVEL_CHECK, INSTALL_ECRYPTION_FILES, INSTALL_CREATE_BACKUP_DIR, /* For Update */ INSTALL_DIR_CREATE, -- 2.7.4