Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / step / security / step_privilege_compatibility.cc
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.
4
5 #include "common/step/security/step_privilege_compatibility.h"
6
7 #include <pkgmgrinfo_basic.h>
8 #include <privilege_manager.h>
9
10 #include <cassert>
11 #include <cstdlib>
12 #include <cstring>
13 #include <memory>
14 #include <string>
15
16 #include "common/privileges.h"
17 #include "common/utils/glist_range.h"
18
19 namespace ci = common_installer;
20
21 namespace {
22
23 const char kAppDebuggingPrivilegeStr[] =
24     "http://tizen.org/privilege/internal/appdebugging";
25
26 std::string GetInternalPrivilegeForLevel(ci::PrivilegeLevel level) {
27   switch (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;
34     default:
35       assert(false && "This shouldn't be reached");
36   }
37 }
38
39 bool MapPrivileges(GList* priv, GList** out, bool is_web,
40                    const char* api_version) {
41   if (!priv)
42     return true;
43
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");
49     return false;
50   }
51
52   return true;
53 }
54
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))
60       continue;
61     api_version = app->api_version;
62     break;
63   }
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;
68   return api_version;
69 }
70
71 void FreePrivilegeList(GList* priv) {
72   g_list_free_full(priv, free);
73 }
74
75 void FreePrivilegeXList(GList* priv) {
76   g_list_free_full(priv, &ci::FreePrivilegeX);
77 }
78
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";
83     return true;
84   }
85
86   // No privileges to map
87   if (!m->privileges) {
88     return true;
89   }
90
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);
111
112   if (!MapPrivileges(native_privileges, &mapped_native_privileges, false,
113                      GetAPIVersion(m, false).c_str()))
114     return false;
115   if (!MapPrivileges(web_privileges, &mapped_web_privileges, true,
116                      GetAPIVersion(m, true).c_str()))
117     return false;
118
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);
125
126   converted_native_privileges =
127       g_list_concat(converted_native_privileges, converted_web_privileges);
128   converted_web_privileges = nullptr;
129
130   g_list_free_full(m->privileges, &ci::FreePrivilegeX);
131   m->privileges = converted_native_privileges;
132   converted_native_privileges = nullptr;
133
134   return true;
135 }
136
137 bool AppendPrivilegeToList(const char* type, const char* privilege_str,
138     GList** list) {
139   privilege_x* privilege =
140       reinterpret_cast<privilege_x*>(calloc(1, sizeof(privilege_x)));
141   if (!privilege) {
142     LOG(ERROR) << "Out of memory";
143     return false;
144   }
145   privilege->type = strdup(type);
146   privilege->value = strdup(privilege_str);
147   *list = g_list_append(*list, privilege);
148
149   return true;
150 }
151
152 }  // namespace
153
154 namespace common_installer {
155 namespace security {
156
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;
161   }
162   return Status::OK;
163 }
164
165 Step::Status StepPrivilegeCompatibility::process() {
166   // Add default privileges for each certificates level.
167   auto internal_priv =
168       GetInternalPrivilegeForLevel(context_->partial_rw.get()?
169           ci::PrivilegeLevel::PLATFORM : context_->privilege_level.get());
170
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;
181     }
182   }
183
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;
194     }
195   }
196
197   return TranslatePrivilegesForCompatibility(context_->manifest_data.get()) ?
198       Status::OK : Status::PRIVILEGE_ERROR;
199 }
200
201 }  // namespace security
202 }  // namespace common_installer