[Common] Added macros useful for reporting errors.
[platform/core/api/webapi-plugins.git] / src / common / tools.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "common/tools.h"
18
19 #ifdef PRIVILEGE_USE_DB
20 #include <sqlite3.h>
21 #include "common/current_application.h"
22 #elif PRIVILEGE_USE_ACE
23 //#include <privilege_checker.h>
24 #elif PRIVILEGE_USE_CYNARA
25 #include <unistd.h>
26
27 #include <cynara/cynara-client.h>
28 #include <sys/smack.h>
29 #endif
30
31 #include "common/logger.h"
32 #include "common/scope_exit.h"
33
34 namespace common {
35 namespace tools {
36
37 void ReportSuccess(picojson::object& out) {
38   LoggerD("Enter");
39   out.insert(std::make_pair("status", picojson::value("success")));
40 }
41
42 void ReportSuccess(const picojson::value& result, picojson::object& out) {
43   LoggerD("Enter");
44   out.insert(std::make_pair("status", picojson::value("success")));
45   out.insert(std::make_pair("result", result));
46 }
47
48 void ReportError(picojson::object& out) {
49   LoggerE("Error without error code");
50   out.insert(std::make_pair("status", picojson::value("error")));
51 }
52
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()));
57 }
58
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()));
63 }
64
65 namespace {
66
67 #ifdef PRIVILEGE_USE_DB
68
69 class AccessControlImpl {
70  public:
71   AccessControlImpl()
72       : initialized_(false) {
73     LoggerD("Privilege access checked using DB.");
74
75     const char* kWrtDBPath = "/opt/dbspace/.wrt.db";
76     sqlite3* db = nullptr;
77
78     int ret = sqlite3_open(kWrtDBPath, &db);
79     if (SQLITE_OK != ret) {
80       LoggerE("Failed to access WRT database");
81       return;
82     }
83
84     const char* kQuery = "select name from WidgetFeature where app_id = "
85                          "(select app_id from WidgetInfo where tizen_appid = ?)"
86                          " and rejected = 0";
87     const std::string app_id = common::CurrentApplication::GetInstance().GetApplicationId();
88     sqlite3_stmt* stmt = nullptr;
89
90     ret = sqlite3_prepare_v2(db, kQuery, -1, &stmt, nullptr);
91     ret |= sqlite3_bind_text(stmt, 1, app_id.c_str(), -1, SQLITE_TRANSIENT);
92
93     SCOPE_EXIT {
94       sqlite3_finalize(stmt);
95       sqlite3_close(db);
96     };
97
98     if (SQLITE_OK != ret) {
99       LoggerE("Failed to query WRT database");
100       return;
101     }
102
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);
107     }
108
109     initialized_ = true;
110   }
111
112   ~AccessControlImpl() {}
113
114   bool CheckAccess(const std::vector<std::string>& privileges) {
115     LoggerD("Enter");
116     if (!initialized_) {
117       return false;
118     }
119
120     for (const auto& privilege : privileges) {
121       if (std::find(granted_privileges_.begin(), granted_privileges_.end(), privilege) == granted_privileges_.end()) {
122         return false;
123       }
124     }
125
126     return true;
127   }
128
129  private:
130   bool initialized_;
131   std::vector<std::string> granted_privileges_;
132 };
133
134 #elif PRIVILEGE_USE_ACE
135
136 class AccessControlImpl {
137  public:
138   AccessControlImpl() {
139     LoggerD("Privilege access checked using ACE.");
140   }
141
142   ~AccessControlImpl() {
143   }
144
145   bool CheckAccess(const std::vector<std::string>& privileges) {
146     LoggerD("Enter");
147
148     return true;
149 };
150
151 #elif PRIVILEGE_USE_CYNARA
152
153 class AccessControlImpl {
154  public:
155   AccessControlImpl() : cynara_(nullptr) {
156     LoggerD("Privilege access checked using Cynara.");
157
158     char* smack_label = nullptr;
159     int len= smack_new_label_from_self(&smack_label);
160
161     if (0 < len && nullptr != smack_label) {
162       auto uid = getuid();
163
164       SLoggerD("uid: [%u]", uid);
165       SLoggerD("smack label: [%s]", smack_label);
166
167       uid_ = std::to_string(uid);
168       smack_label_ = smack_label;
169
170       free(smack_label);
171     } else {
172       LoggerE("Failed to get smack label");
173       return;
174     }
175
176     int ret = cynara_initialize(&cynara_, nullptr);
177     if (CYNARA_API_SUCCESS != ret) {
178       LoggerE("Failed to initialize Cynara");
179       cynara_ = nullptr;
180     }
181   }
182
183   ~AccessControlImpl() {
184     if (cynara_) {
185       auto ret = cynara_finish(cynara_);
186       if (CYNARA_API_SUCCESS != ret) {
187         LoggerE("Failed to finalize Cynara");
188       }
189       cynara_ = nullptr;
190     }
191   }
192
193   bool CheckAccess(const std::vector<std::string>& privileges) {
194
195     if (cynara_) {
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
202                                                              )) {
203           return false;
204         }
205       }
206       return true;
207     } else {
208       return false;
209     }
210   }
211
212  private:
213   cynara* cynara_;
214   std::string uid_;
215   std::string smack_label_;
216 };
217
218 #else
219
220 class AccessControlImpl {
221  public:
222   AccessControlImpl() {
223     LoggerD("Privilege access - deny all.");
224   }
225
226   bool CheckAccess(const std::vector<std::string>& privileges) {
227     return false;
228   }
229 };
230
231 #endif
232
233 class AccessControl {
234  public:
235   static AccessControl& GetInstance() {
236     static AccessControl instance;
237     return instance;
238   }
239
240   bool CheckAccess(const std::string& privilege) {
241     return CheckAccess(std::vector<std::string>{privilege});
242   }
243
244   bool CheckAccess(const std::vector<std::string>& privileges) {
245     return impl_.CheckAccess(privileges);
246   }
247
248  private:
249   AccessControl() {}
250   ~AccessControl() {}
251   AccessControlImpl impl_;
252 };
253
254 } // namespace
255
256 PlatformResult CheckAccess(const std::string& privilege) {
257   return CheckAccess(std::vector<std::string>{privilege});
258 }
259
260 PlatformResult CheckAccess(const std::vector<std::string>& privileges) {
261   LoggerD("Enter");
262   if (AccessControl::GetInstance().CheckAccess(privileges)) {
263     return PlatformResult(ErrorCode::NO_ERROR);
264   } else {
265     for (const auto& privilege : privileges) {
266       LoggerD("Access to privilege: %s has been denied.", privilege.c_str());
267     }
268     return PlatformResult(ErrorCode::SECURITY_ERR, "Permission denied");
269   }
270 }
271
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);
276   return msg;
277 }
278
279
280 int HexToInt(char c) {
281   if (c >= '0' && c <= '9') {
282     return c - '0';
283   } else if (c >= 'A' && c <= 'Z') {
284     return c - 'A';
285   } else {
286     return c - 'a';
287   }
288 }
289
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]);
294   }
295   return bin;
296 }
297
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];
303   }
304   return hex;
305 }
306
307 }  // namespace tools
308 }  // namespace common