From: Inhwan Lee Date: Thu, 16 Jun 2016 10:14:55 +0000 (+0900) Subject: implement step for use user extension X-Git-Tag: accepted/tizen/common/20160707.171532^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3014326fcc25ea087930aa64b855dbfb9eabf785;p=platform%2Fcore%2Fappfw%2Fwgt-backend.git implement step for use user extension Change-Id: Ie5442f543f6e4dc3dbf78685716db2b113c021d0 --- diff --git a/src/wgt/CMakeLists.txt b/src/wgt/CMakeLists.txt old mode 100644 new mode 100755 index f45acc5..2e70267 --- a/src/wgt/CMakeLists.txt +++ b/src/wgt/CMakeLists.txt @@ -18,8 +18,10 @@ SET(SRCS step/security/step_check_wgt_notification_category.cc step/security/step_check_wgt_ime_privilege.cc step/security/step_direct_manifest_check_signature.cc + step/security/step_check_extension_privileges.cc wgt_app_query_interface.cc wgt_installer.cc + extension_config_parser.cc ) IF(WRT_LAUNCHER) diff --git a/src/wgt/extension_config_parser.cc b/src/wgt/extension_config_parser.cc new file mode 100755 index 0000000..4813d72 --- /dev/null +++ b/src/wgt/extension_config_parser.cc @@ -0,0 +1,190 @@ +// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a apache 2.0 license that can be +// found in the LICENSE file. + +#include "wgt/extension_config_parser.h" +#include +#include + +#include +#include + +namespace wgt { + +namespace { +const xmlChar kExtensionNodeKey[] = "extension"; +const xmlChar kNamePrivilegeKey[] = "privilege"; +const xmlChar kPrivigeNameAttributeKey[] = "name"; +const char kAttributePrefix[] = "@"; +const xmlChar kDirAttributeKey[] = "dir"; +const char kXmlTextKey[] = "#text"; +const char kNamespaceKey[] = "@namespace"; +const char kExtensionPath[] = "extension.privilege"; +const char kExtensionNameKey[] = "@name"; +} // namespace + +ExtensionConfigParser::ExtensionConfigParser(std::string config_xml) { + config_xml_ = config_xml; +} + +std::unique_ptr + ExtensionConfigParser::LoadExtensionConfig(const std::string& config_xml) { + xmlDoc *doc = nullptr; + xmlNode* root_node = nullptr; + doc = xmlReadFile(config_xml.c_str(), nullptr, XML_PARSE_NOENT); + if (!doc) { + LOG(ERROR) << "Failed to read xml document model from" << config_xml; + return nullptr; + } + root_node = xmlDocGetRootElement(doc); + std::unique_ptr dv = LoadXMLNode(root_node); + std::unique_ptr result(new parser::DictionaryValue); + if (dv) + result->Set(reinterpret_cast(root_node->name), dv.release()); + return result; +} + +std::string ExtensionConfigParser::GetNodeDir( + xmlNode* node, const std::string& inherit_dir) { + std::string dir(inherit_dir); + for (xmlAttr* prop = node->properties; prop; prop = prop->next) { + if (xmlStrEqual(prop->name, kDirAttributeKey)) { + char* prop_value = reinterpret_cast(xmlNodeListGetString( + node->doc, prop->children, 1)); + dir = prop_value; + xmlFree(prop_value); + break; + } + } + return dir; +} +std::string ExtensionConfigParser::GetNodeText( + xmlNode* root, const std::string& inherit_dir) { + if (root->type != XML_ELEMENT_NODE) + return std::string(); + std::string current_dir(GetNodeDir(root, inherit_dir)); + std::string text; + if (!current_dir.empty()) + text += parser::utils::GetDirUTF8Start(current_dir); + for (xmlNode* node = root->children; node; node = node->next) { + if (node->type == XML_TEXT_NODE || node->type == XML_CDATA_SECTION_NODE) + text = text + std::string(reinterpret_cast(node->content)); + else + text += GetNodeText(node, current_dir); + } + if (!current_dir.empty()) + text += parser::utils::GetDirUTF8End(); + return text; +} +bool ExtensionConfigParser::IsPropSupportDir(xmlNode* root, xmlAttr* prop) { + if (xmlStrEqual(root->name, kNamePrivilegeKey) + && xmlStrEqual(prop->name, kPrivigeNameAttributeKey)) { + return true; + } + return false; +} +bool ExtensionConfigParser::IsTrimRequiredForElement(xmlNode* root) { + if (xmlStrEqual(root->name, kNamePrivilegeKey)) { + return true; + } + return false; +} +bool ExtensionConfigParser::IsTrimRequiredForProp( + xmlNode* root, xmlAttr* prop) { + if (xmlStrEqual(root->name, kNamePrivilegeKey) && + xmlStrEqual(prop->name, kPrivigeNameAttributeKey)) { + return true; + } + return false; +} +std::unique_ptr + ExtensionConfigParser::LoadXMLNode( + xmlNode* root, const std::string& inherit_dir) { + std::unique_ptr value(new parser::DictionaryValue()); + if (root->type != XML_ELEMENT_NODE) + return nullptr; + + std::string current_dir(GetNodeDir(root, inherit_dir)); + + xmlAttr* prop = nullptr; + for (prop = root->properties; prop; prop = prop->next) { + xmlChar* value_ptr = xmlNodeListGetString(root->doc, prop->children, 1); + std::string prop_value(reinterpret_cast(value_ptr)); + xmlFree(value_ptr); + if (IsPropSupportDir(root, prop)) + prop_value = parser::utils::GetDirTextUTF8(prop_value, current_dir); + + if (IsTrimRequiredForProp(root, prop)) + prop_value = parser::utils::CollapseWhitespaceUTF8(prop_value); + + value->SetString( + std::string(kAttributePrefix) + + reinterpret_cast(prop->name), + prop_value); + } + + if (root->ns) + value->SetString(kNamespaceKey, + reinterpret_cast(root->ns->href)); + + for (xmlNode* node = root->children; node; node = node->next) { + std::string sub_node_name(reinterpret_cast(node->name)); + std::unique_ptr sub_value = + LoadXMLNode(node, current_dir); + + if (!sub_value) { + continue; + } + if (!value->HasKey(sub_node_name)) { + value->Set(sub_node_name, sub_value.release()); + continue; + } + + parser::Value* temp; + value->Get(sub_node_name, &temp); + + if (temp->IsType(parser::Value::TYPE_LIST)) { + parser::ListValue* list; + temp->GetAsList(&list); + list->Append(sub_value.release()); + } else { + assert(temp->IsType(parser::Value::TYPE_DICTIONARY)); + parser::DictionaryValue* dict; + temp->GetAsDictionary(&dict); + parser::DictionaryValue* prev_value = dict->DeepCopy(); + + parser::ListValue* list = new parser::ListValue(); + list->Append(prev_value); + list->Append(sub_value.release()); + value->Set(sub_node_name, list); + } + } + + std::string text; + xmlChar* text_ptr = xmlNodeListGetString(root->doc, root->children, 1); + if (text_ptr) { + text = reinterpret_cast(text_ptr); + xmlFree(text_ptr); + } + if (IsTrimRequiredForElement(root)) + text = parser::utils::CollapseWhitespaceUTF8(text); + if (!text.empty()) + value->SetString(kXmlTextKey, text); + + return value; +} +std::vector ExtensionConfigParser::GetExtensionPrivilegeList() { + std::unique_ptr dic + = LoadExtensionConfig(config_xml_); + std::vector privilege_list; + + for (auto& item : parser::GetOneOrMany(dic.get(), kExtensionPath, "")) { + std::string privilege; + if (item->GetString(kExtensionNameKey, &privilege)) { + LOG(DEBUG) << "User defined extra privilege: " << privilege; + privilege_list.push_back(privilege); + } + } + return privilege_list; +} +} // namespace wgt diff --git a/src/wgt/extension_config_parser.h b/src/wgt/extension_config_parser.h new file mode 100755 index 0000000..c5cd454 --- /dev/null +++ b/src/wgt/extension_config_parser.h @@ -0,0 +1,36 @@ +// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a apache 2.0 license that can be +// found in the LICENSE file. + +#ifndef WGT_EXTENSION_CONFIG_PARSER_H_ +#define WGT_EXTENSION_CONFIG_PARSER_H_ + +#include +#include +#include +#include + +#include +#include +#include + +namespace wgt { +class ExtensionConfigParser { + public: + explicit ExtensionConfigParser(std::string config_xml); + std::vector GetExtensionPrivilegeList(); + private: + std::unique_ptr LoadExtensionConfig( + const std::string& config_xml); + std::string GetNodeDir(xmlNode* node, const std::string& inherit_dir); + std::string GetNodeText(xmlNode* root, const std::string& inherit_dir); + bool IsPropSupportDir(xmlNode* root, xmlAttr* prop); + bool IsTrimRequiredForElement(xmlNode* root); + bool IsTrimRequiredForProp(xmlNode* root, xmlAttr* prop); + std::unique_ptr LoadXMLNode( + xmlNode* root, const std::string& inherit_dir = ""); + std::string config_xml_; +}; +} // namespace wgt + +#endif // WGT_EXTENSION_CONFIG_PARSER_H_ diff --git a/src/wgt/step/security/step_check_extension_privileges.cc b/src/wgt/step/security/step_check_extension_privileges.cc new file mode 100755 index 0000000..f75c832 --- /dev/null +++ b/src/wgt/step/security/step_check_extension_privileges.cc @@ -0,0 +1,132 @@ +// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a apache 2.0 license that can be +// found in the LICENSE file. + +#include "wgt/step/security/step_check_extension_privileges.h" +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "wgt/extension_config_parser.h" +#include "manifest_parser/values.h" +#include "common/certificate_validation.h" +#include "common/utils/glist_range.h" + +namespace { +const char kPluginsDirectory[] = "/res/wgt/plugin/"; +const char kArchArmv7l[] = "armv7l"; +const char kArchI586[] = "i586"; +const char kArchDefault[] = "default"; +} + +namespace wgt { +namespace security { + +common_installer::Step::Status StepCheckExtensionPrivileges::precheck() { + if (!context_->manifest_data.get()) { + LOG(ERROR) << "Manifest data is not set"; + return Status::ERROR; + } + return Status::OK; +} +common_installer::Step::Status StepCheckExtensionPrivileges::process() { + std::string app_ext_config_pattern(GetExtensionPath()); + + manifest_x* m = context_->manifest_data.get(); + std::set current_privileges; + for (const char* priv : GListRange(m->privileges)) { + current_privileges.insert(priv); + } + + std::set xmlFiles; + { + glob_t glob_result; + glob(app_ext_config_pattern.c_str(), GLOB_TILDE, NULL, &glob_result); + for (unsigned int i = 0; i < glob_result.gl_pathc; ++i) { + xmlFiles.insert(glob_result.gl_pathv[i]); + } + } + std::set privileges; + for (auto it = xmlFiles.begin(); it != xmlFiles.end(); ++it) { + LOG(DEBUG) << "start to parse extension xml : " << *it; + ExtensionConfigParser extensionParser(*it); + std::vector list = extensionParser.GetExtensionPrivilegeList(); + for (int i = 0 ; i < list.size() ; i++) { + if (current_privileges.find(list[i]) == current_privileges.end()) { + privileges.insert(list[i]); + } + } + } + + if (!privileges.empty()) { + if (!CheckPriviligeLevel(privileges)) { + LOG(DEBUG) << "Fail to validation of privilege"; + return Status::ERROR; + } + for (auto it = privileges.begin(); it != privileges.end(); ++it) { + LOG(DEBUG) << "set list privilege : " << *it; + m->privileges = g_list_append(m->privileges, strdup((*it).c_str())); + } + } + return Status::OK; +} + +std::string StepCheckExtensionPrivileges::GetExtensionPath() { + std::string app_ext_config_pattern(context_->pkg_path.get().string()); + app_ext_config_pattern.append(kPluginsDirectory); + struct utsname u; + if (0 == uname(&u)) { + std::string machine = u.machine; + LOG(DEBUG) << "Machine archicture for user defined plugins: " << machine; + if (!machine.empty()) { + if (machine == kArchArmv7l) { + app_ext_config_pattern.append(kArchArmv7l); + } else if (machine == kArchI586) { + app_ext_config_pattern.append(kArchI586); + } else { + app_ext_config_pattern.append(kArchDefault); + } + } else { + LOG(ERROR) << "cannot get machine info"; + app_ext_config_pattern.append(kArchDefault); + } + app_ext_config_pattern.append("/"); + } + app_ext_config_pattern.append("*"); + app_ext_config_pattern.append(".xml"); + return app_ext_config_pattern; +} + +bool StepCheckExtensionPrivileges::CheckPriviligeLevel( + std::set priv_set) { + GList* privileges = nullptr; + for (auto it = priv_set.begin(); it != priv_set.end(); ++it) { + privileges = g_list_append(privileges, strdup((*it).c_str())); + } + guint size = g_list_length(privileges); + if (size == 0) return true; + + std::string error_message; + if (!common_installer::ValidatePrivilegeLevel( + context_->privilege_level.get(), + false, + context_->manifest_data.get()->api_version, + privileges, + &error_message)) { + if (!error_message.empty()) { + LOG(ERROR) << "error_message: " << error_message; + return false; + } + return false; + } + return true; +} + +} // namespace security +} // namespace wgt diff --git a/src/wgt/step/security/step_check_extension_privileges.h b/src/wgt/step/security/step_check_extension_privileges.h new file mode 100755 index 0000000..0c27abc --- /dev/null +++ b/src/wgt/step/security/step_check_extension_privileges.h @@ -0,0 +1,55 @@ +// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a apache 2.0 license that can be +// found in the LICENSE file. +// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a apache 2.0 license that can be +// found in the LICENSE file. + +#ifndef WGT_STEP_SECURITY_STEP_CHECK_EXTENSION_PRIVILEGES_H_ +#define WGT_STEP_SECURITY_STEP_CHECK_EXTENSION_PRIVILEGES_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace wgt { +namespace security { + +/** + * \brief Step that add user extension privileges during installation + */ +class StepCheckExtensionPrivileges : public common_installer::Step { + public: + using Step::Step; + + /** + * \Adds extra package privileges defined by extension manifest. + * + * \return Status::OK + */ + Status process() override; + Status clean() override { return Status::OK; } + Status undo() override { return Status::OK; } + /** + * \brief Check requirements for this step + * + * \return Status::ERROR when rmanifest data are missing, + * Status::OK otherwise + */ + Status precheck() override; + private: + std::string GetExtensionPath(); + bool CheckPriviligeLevel(std::set priv_set); + STEP_NAME(CheckExtensionPrivileges) +}; + +} // namespace security +} // namespace wgt + +#endif // WGT_STEP_SECURITY_STEP_CHECK_EXTENSION_PRIVILEGES_H_ diff --git a/src/wgt/wgt_installer.cc b/src/wgt/wgt_installer.cc old mode 100644 new mode 100755 index 7abd4e2..ee5f62c --- a/src/wgt/wgt_installer.cc +++ b/src/wgt/wgt_installer.cc @@ -82,6 +82,7 @@ #include "wgt/step/security/step_check_wgt_notification_category.h" #include "wgt/step/security/step_check_wgt_ime_privilege.h" #include "wgt/step/security/step_direct_manifest_check_signature.h" +#include "wgt/step/security/step_check_extension_privileges.h" namespace ci = common_installer; @@ -118,6 +119,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep( @@ -157,6 +159,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep( @@ -202,6 +205,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); break; } @@ -241,6 +245,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep( @@ -301,6 +306,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep( ci::Plugin::ActionType::Install); AddStep(); + AddStep(); AddStep(); break; } @@ -332,6 +338,7 @@ WgtInstaller::WgtInstaller(ci::PkgMgrPtr pkgrmgr) AddStep(); AddStep(); AddStep(); + AddStep(); AddStep(); AddStep(); AddStep(