2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "common/tools.h"
19 #ifdef PRIVILEGE_USE_DB
21 #include "common/current_application.h"
22 #elif PRIVILEGE_USE_ACE
23 //#include <privilege_checker.h>
24 #elif PRIVILEGE_USE_CYNARA
27 #include <cynara/cynara-client.h>
28 #include <sys/smack.h>
31 #include "common/logger.h"
32 #include "common/scope_exit.h"
37 void ReportSuccess(picojson::object& out) {
39 out.insert(std::make_pair("status", picojson::value("success")));
42 void ReportSuccess(const picojson::value& result, picojson::object& out) {
44 out.insert(std::make_pair("status", picojson::value("success")));
45 out.insert(std::make_pair("result", result));
48 void ReportError(picojson::object& out) {
49 LoggerE("Error without error code");
50 out.insert(std::make_pair("status", picojson::value("error")));
53 void ReportError(const PlatformException& ex, picojson::object& out) {
54 LoggerE("PlatformException: %s, message: %s", ex.name().c_str(), ex.message().c_str());
55 out.insert(std::make_pair("status", picojson::value("error")));
56 out.insert(std::make_pair("error", ex.ToJSON()));
59 void ReportError(const PlatformResult& error, picojson::object* out) {
60 LoggerE("PlatformResult: %d, message: %s", error.error_code(), error.message().c_str());
61 out->insert(std::make_pair("status", picojson::value("error")));
62 out->insert(std::make_pair("error", error.ToJSON()));
67 #ifdef PRIVILEGE_USE_DB
69 class AccessControlImpl {
72 : initialized_(false) {
73 LoggerD("Privilege access checked using DB.");
75 const char* kWrtDBPath = "/opt/dbspace/.wrt.db";
76 sqlite3* db = nullptr;
78 int ret = sqlite3_open(kWrtDBPath, &db);
79 if (SQLITE_OK != ret) {
80 LoggerE("Failed to access WRT database");
84 const char* kQuery = "select name from WidgetFeature where app_id = "
85 "(select app_id from WidgetInfo where tizen_appid = ?)"
87 const std::string app_id = common::CurrentApplication::GetInstance().GetApplicationId();
88 sqlite3_stmt* stmt = nullptr;
90 ret = sqlite3_prepare_v2(db, kQuery, -1, &stmt, nullptr);
91 ret |= sqlite3_bind_text(stmt, 1, app_id.c_str(), -1, SQLITE_TRANSIENT);
94 sqlite3_finalize(stmt);
98 if (SQLITE_OK != ret) {
99 LoggerE("Failed to query WRT database");
103 while (sqlite3_step(stmt) == SQLITE_ROW) {
104 const char* privilege = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
105 SLoggerD("Granted: %s", privilege);
106 granted_privileges_.push_back(privilege);
112 ~AccessControlImpl() {}
114 bool CheckAccess(const std::vector<std::string>& privileges) {
120 for (const auto& privilege : privileges) {
121 if (std::find(granted_privileges_.begin(), granted_privileges_.end(), privilege) == granted_privileges_.end()) {
131 std::vector<std::string> granted_privileges_;
134 #elif PRIVILEGE_USE_ACE
136 class AccessControlImpl {
138 AccessControlImpl() {
139 LoggerD("Privilege access checked using ACE.");
142 ~AccessControlImpl() {
145 bool CheckAccess(const std::vector<std::string>& privileges) {
151 #elif PRIVILEGE_USE_CYNARA
153 class AccessControlImpl {
155 AccessControlImpl() : cynara_(nullptr) {
156 LoggerD("Privilege access checked using Cynara.");
158 char* smack_label = nullptr;
159 int len= smack_new_label_from_self(&smack_label);
161 if (0 < len && nullptr != smack_label) {
164 SLoggerD("uid: [%u]", uid);
165 SLoggerD("smack label: [%s]", smack_label);
167 uid_ = std::to_string(uid);
168 smack_label_ = smack_label;
172 LoggerE("Failed to get smack label");
176 int ret = cynara_initialize(&cynara_, nullptr);
177 if (CYNARA_API_SUCCESS != ret) {
178 LoggerE("Failed to initialize Cynara");
183 ~AccessControlImpl() {
185 auto ret = cynara_finish(cynara_);
186 if (CYNARA_API_SUCCESS != ret) {
187 LoggerE("Failed to finalize Cynara");
193 bool CheckAccess(const std::vector<std::string>& privileges) {
196 for (const auto& privilege : privileges) {
197 if (CYNARA_API_ACCESS_ALLOWED != cynara_simple_check(cynara_, // p_cynara
198 smack_label_.c_str(), // client
199 "", // client_session
200 uid_.c_str(), // user
201 privilege.c_str() // privilege
215 std::string smack_label_;
220 class AccessControlImpl {
222 AccessControlImpl() {
223 LoggerD("Privilege access - deny all.");
226 bool CheckAccess(const std::vector<std::string>& privileges) {
233 class AccessControl {
235 static AccessControl& GetInstance() {
236 static AccessControl instance;
240 bool CheckAccess(const std::string& privilege) {
241 return CheckAccess(std::vector<std::string>{privilege});
244 bool CheckAccess(const std::vector<std::string>& privileges) {
245 return impl_.CheckAccess(privileges);
251 AccessControlImpl impl_;
256 PlatformResult CheckAccess(const std::string& privilege) {
257 return CheckAccess(std::vector<std::string>{privilege});
260 PlatformResult CheckAccess(const std::vector<std::string>& privileges) {
262 if (AccessControl::GetInstance().CheckAccess(privileges)) {
263 return PlatformResult(ErrorCode::NO_ERROR);
265 for (const auto& privilege : privileges) {
266 LoggerD("Access to privilege: %s has been denied.", privilege.c_str());
268 return PlatformResult(ErrorCode::SECURITY_ERR, "Permission denied");
272 std::string GetErrorString(int error_code) {
273 static const size_t kSize = 1024;
274 char msg[kSize] = {0};
275 strerror_r(error_code, msg, kSize);
280 int HexToInt(char c) {
281 if (c >= '0' && c <= '9') {
283 } else if (c >= 'A' && c <= 'Z') {
290 unsigned char* HexToBin(const char* hex, int size, unsigned char* bin, int bin_size) {
291 for (int i = 0; i < size - 1 && i / 2 < bin_size; i += 2) {
292 bin[i * 2] = HexToInt(hex[i]) << 4;
293 bin[i * 2] += HexToInt(hex[i + 1]);
298 char* BinToHex(const unsigned char* bin, int size, char* hex, int hex_size) {
299 static const char * const digits = "0123456789ABCDEF";
300 for (int i = 0; i < size && i < hex_size / 2; i++) {
301 hex[i * 2] = digits[bin[i] >> 4];
302 hex[i * 2 + 1] = digits[bin[i] & 15];
308 } // namespace common