1 // Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
5 #include "common/step/security/step_privilege_compatibility.h"
7 #include <pkgmgrinfo_basic.h>
8 #include <privilege_manager.h>
16 #include "common/privileges.h"
17 #include "common/utils/glist_range.h"
19 namespace ci = common_installer;
23 const char kAppDebuggingPrivilegeStr[] =
24 "http://tizen.org/privilege/internal/appdebugging";
26 std::string GetInternalPrivilegeForLevel(ci::PrivilegeLevel level) {
28 case ci::PrivilegeLevel::PUBLIC:
29 return ci::privileges::kPrivForPublic;
30 case ci::PrivilegeLevel::PARTNER:
31 return ci::privileges::kPrivForPartner;
32 case ci::PrivilegeLevel::PLATFORM:
33 return ci::privileges::kPrivForPlatform;
35 assert(false && "This shouldn't be reached");
39 bool MapPrivileges(GList* priv, GList** out, bool is_web,
40 const char* api_version) {
44 if (privilege_manager_get_mapped_privilege_list(api_version,
45 is_web ? PRVMGR_PACKAGE_TYPE_WRT : PRVMGR_PACKAGE_TYPE_CORE,
46 priv, out) != PRVMGR_ERR_NONE) {
47 LOG(ERROR) << "privilege_manager_get_mapped_privilege_list failed for "
48 << (is_web ? "web privileges" : "native privileges");
55 std::string GetAPIVersion(manifest_x* m, bool is_web) {
56 std::string api_version;
57 for (auto& app : GListRange<application_x*>(m->application)) {
58 if ((is_web && strcmp(app->type, "webapp") != 0) ||
59 (!is_web && strcmp(app->type, "webapp") == 0))
61 api_version = app->api_version;
64 if (api_version.empty())
65 // fallback if api-version not found. In case of addon package,
66 // application does not included in package.
67 api_version = m->api_version;
71 void FreePrivilegeList(GList* priv) {
72 g_list_free_full(priv, free);
75 void FreePrivilegeXList(GList* priv) {
76 g_list_free_full(priv, &ci::FreePrivilegeX);
79 bool TranslatePrivilegesForCompatibility(manifest_x* m) {
80 if (!m->api_version) {
81 LOG(WARNING) << "Skipping privileges mapping because api-version "
82 << "is not specified by package";
86 // No privileges to map
91 GList* native_privileges =
92 ci::PrivilegeXToPrivilege(m->privileges, ci::kNativePrivilegeType);
93 GList* web_privileges =
94 ci::PrivilegeXToPrivilege(m->privileges, ci::kWebPrivilegeType);
95 GList* mapped_native_privileges = nullptr;
96 GList* mapped_web_privileges = nullptr;
97 GList* converted_native_privileges = nullptr;
98 GList* converted_web_privileges = nullptr;
99 std::unique_ptr<GList, decltype(::FreePrivilegeList)*> deleter1(
100 native_privileges, &::FreePrivilegeList);
101 std::unique_ptr<GList, decltype(::FreePrivilegeList)*> deleter2(
102 web_privileges, &::FreePrivilegeList);
103 std::unique_ptr<GList, decltype(::FreePrivilegeList)*> deleter3(
104 mapped_native_privileges, &::FreePrivilegeList);
105 std::unique_ptr<GList, decltype(::FreePrivilegeList)*> deleter4(
106 mapped_web_privileges, &::FreePrivilegeList);
107 std::unique_ptr<GList, decltype(::FreePrivilegeXList)*> deleter5(
108 converted_native_privileges, &::FreePrivilegeXList);
109 std::unique_ptr<GList, decltype(::FreePrivilegeXList)*> deleter6(
110 converted_web_privileges, &::FreePrivilegeXList);
112 if (!MapPrivileges(native_privileges, &mapped_native_privileges, false,
113 GetAPIVersion(m, false).c_str()))
115 if (!MapPrivileges(web_privileges, &mapped_web_privileges, true,
116 GetAPIVersion(m, true).c_str()))
119 converted_native_privileges =
120 ci::PrivilegeToPrivilegeX(mapped_native_privileges,
121 ci::kNativePrivilegeType);
122 converted_web_privileges =
123 ci::PrivilegeToPrivilegeX(mapped_web_privileges,
124 ci::kWebPrivilegeType);
126 converted_native_privileges =
127 g_list_concat(converted_native_privileges, converted_web_privileges);
128 converted_web_privileges = nullptr;
130 g_list_free_full(m->privileges, &ci::FreePrivilegeX);
131 m->privileges = converted_native_privileges;
132 converted_native_privileges = nullptr;
137 bool AppendPrivilegeToList(const char* type, const char* privilege_str,
139 privilege_x* privilege =
140 reinterpret_cast<privilege_x*>(calloc(1, sizeof(privilege_x)));
142 LOG(ERROR) << "Out of memory";
145 privilege->type = strdup(type);
146 privilege->value = strdup(privilege_str);
147 *list = g_list_append(*list, privilege);
154 namespace common_installer {
157 Step::Status StepPrivilegeCompatibility::precheck() {
158 if (!context_->manifest_data.get()) {
159 LOG(ERROR) << "Manifest data is not set";
160 return Status::MANIFEST_NOT_FOUND;
165 Step::Status StepPrivilegeCompatibility::process() {
166 // Add default privileges for each certificates level.
168 GetInternalPrivilegeForLevel(context_->partial_rw.get()?
169 ci::PrivilegeLevel::PLATFORM : context_->privilege_level.get());
171 if (internal_priv_type_ == InternalPrivType::TPK ||
172 internal_priv_type_ == InternalPrivType::BOTH) {
173 if (!AppendPrivilegeToList(kNativePrivilegeType, internal_priv.c_str(),
174 &context_->manifest_data.get()->privileges))
175 return Step::Status::ERROR;
176 if (context_->debug_mode.get()) {
177 if (!AppendPrivilegeToList(kNativePrivilegeType,
178 kAppDebuggingPrivilegeStr,
179 &context_->manifest_data.get()->privileges))
180 return Step::Status::ERROR;
184 if (internal_priv_type_ == InternalPrivType::WGT ||
185 internal_priv_type_ == InternalPrivType::BOTH) {
186 if (!AppendPrivilegeToList(kWebPrivilegeType, internal_priv.c_str(),
187 &context_->manifest_data.get()->privileges))
188 return Step::Status::ERROR;
189 if (context_->debug_mode.get()) {
190 if (!AppendPrivilegeToList(kWebPrivilegeType,
191 kAppDebuggingPrivilegeStr,
192 &context_->manifest_data.get()->privileges))
193 return Step::Status::ERROR;
197 return TranslatePrivilegesForCompatibility(context_->manifest_data.get()) ?
198 Status::OK : Status::PRIVILEGE_ERROR;
201 } // namespace security
202 } // namespace common_installer