79b2ea7a73e0b83ecfeb867f3c2eb1bc8ff1e732
[platform/core/security/privilege-info.git] / src / privilege_info.c
1 /*
2  * Copyright (c) 2014-2018 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 <stdio.h>
18 #include <stdlib.h>
19 #include <libintl.h>
20 #include <dlog.h>
21 #include <privilege_db_manager.h>
22 #include <cynara-session.h>
23 #include <cynara-client.h>
24 #include <unistd.h>
25 #include <sys/smack.h>
26 #include <system_info.h>
27 #include "privilege_information.h"
28 #ifdef LOG_TAG
29 #undef LOG_TAG
30 #define LOG_TAG "PRIVILEGE_INFO"
31 #endif
32
33 #define PRIVACY_FEATURE "http://tizen.org/feature/security.privacy_privilege"
34 #define CHECK_FEATURE_SUPPORTED(feature_name) \
35         do { \
36                 bool is_supported = false; \
37                 int ret = system_info_get_platform_bool(feature_name, &is_supported); \
38                 if (ret != SYSTEM_INFO_ERROR_NONE) { \
39                         LOGE("system_info_get_platform_bool failed. ret = %d", ret); \
40                         return PRVINFO_ERROR_INTERNAL_ERROR; \
41                 } \
42                 if (!is_supported) { \
43                         LOGE("%s is disabled", feature_name); \
44                         return PRVINFO_ERROR_NOT_SUPPORTED; \
45                 } \
46         } while (0)
47
48 #define UIDMAXLEN 10
49
50 #define TryReturn(condition, expr, returnValue, ...)  \
51         if (!(condition)) { \
52                 expr; \
53                 LOGE(__VA_ARGS__); \
54                 return returnValue; \
55         }
56
57 #ifndef PI_API
58 #define PI_API __attribute__((visibility("default")))
59 #endif
60
61 typedef enum {
62         PRVINFO_ERROR_NO_MATCHING_PRIVILEGE             = TIZEN_ERROR_PRIVILEGE_INFORMATION | 0x01
63 } privilege_info_internal_error_e;
64
65 int privilege_info_get_string_id(const char *package_type_string, int display, const char *api_version, const char *privilege, char **string_id)
66 {
67         TryReturn(api_version != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] api_version is NULL");
68         TryReturn(privilege != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege is NULL");
69
70         char* temp = NULL;
71         int ret;
72         privilege_manager_package_type_e package_type;
73
74         if (package_type_string != NULL)
75                 goto get_string_id_with_package_type;
76
77         /* Check NATIVE */
78         if (display)
79                 ret = privilege_db_manager_get_privilege_display(PRVMGR_PACKAGE_TYPE_CORE, privilege, api_version, &temp);
80         else
81                 ret = privilege_db_manager_get_privilege_description(PRVMGR_PACKAGE_TYPE_CORE, privilege, api_version, &temp);
82
83         if (ret == PRIVILEGE_DB_MANAGER_ERR_NONE)
84                 goto err_none;
85         else if (ret != PRIVILEGE_DB_MANAGER_ERR_NO_EXIST_RESULT)
86                 goto err_internal_error;
87
88         /* Check WEB */
89
90 get_string_id_with_package_type:
91         if (package_type_string == NULL || strcmp(package_type_string, "PRVINFO_PACKAGE_TYPE_WEB") == 0)
92                 package_type = PRVMGR_PACKAGE_TYPE_WRT;
93         else if (strcmp(package_type_string, "PRVINFO_PACKAGE_TYPE_NATIVE") == 0)
94                 package_type = PRVMGR_PACKAGE_TYPE_CORE;
95         else
96                 return PRVINFO_ERROR_INVALID_PARAMETER;
97
98         if (display)
99                 ret = privilege_db_manager_get_privilege_display(package_type, privilege, api_version, &temp);
100         else
101                 ret = privilege_db_manager_get_privilege_description(package_type, privilege, api_version, &temp);
102
103
104         if (ret == PRIVILEGE_DB_MANAGER_ERR_NONE)
105                 goto err_none;
106         else if (ret == PRIVILEGE_DB_MANAGER_ERR_NO_EXIST_RESULT)
107                 goto err_no_matching_privilege;
108         else
109                 goto err_internal_error;
110
111 err_none:
112         *string_id = strdup(temp);
113         TryReturn(*string_id != NULL, free(temp), PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation is failed.");
114         free(temp);
115         return PRVINFO_ERROR_NONE;
116
117 err_no_matching_privilege:
118         *string_id = NULL;
119         free(temp);
120         return PRVINFO_ERROR_NO_MATCHING_PRIVILEGE;
121
122 err_internal_error:
123         free(temp);
124         return PRVINFO_ERROR_INTERNAL_ERROR;
125 }
126
127 int privilege_info_get_string_by_string_id(const char *string_id, char **string)
128 {
129         char *temp = NULL;
130         TryReturn(string_id != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] string_id is NULL");
131
132         temp = dgettext("privilege", string_id);
133
134         *string = strdup(temp);
135         TryReturn(*string != NULL, , PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] strdup of string failed.");
136
137         return PRVINFO_ERROR_NONE;
138 }
139
140 PI_API
141 int privilege_info_get_display_name(const char *api_version, const char *privilege, char **display_name)
142 {
143         int ret = 0;
144         char* string_id = NULL;
145
146         TryReturn(api_version != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] api_version is NULL");
147         TryReturn(privilege != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege is NULL");
148
149         ret = privilege_info_get_string_id(NULL, 1, api_version, privilege, &string_id);
150
151         if (ret == PRVINFO_ERROR_NO_MATCHING_PRIVILEGE) {
152                 char* tempPrivilege = NULL;
153                 char* token = NULL;
154                 char* temp = NULL;
155                 char* save = NULL;
156
157                 tempPrivilege = strdup(privilege);
158                 TryReturn(tempPrivilege != NULL, free(tempPrivilege), PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] tempPrivilege's strdup is failed.");
159
160                 token = strtok_r(tempPrivilege, "/", &save);
161                 while (token) {
162                         temp = token;
163                         token = strtok_r(NULL, "/", &save);
164                 }
165                 *display_name = strdup(temp);
166                 TryReturn(*display_name != NULL, free(tempPrivilege), PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
167                 free(tempPrivilege);
168         } else if (ret == PRVINFO_ERROR_NONE) {
169                 ret = privilege_info_get_string_by_string_id(string_id, display_name);
170                 free(string_id);
171                 TryReturn(ret == PRVINFO_ERROR_NONE, , PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
172         } else {
173                 return PRVINFO_ERROR_INTERNAL_ERROR;
174         }
175         return PRVINFO_ERROR_NONE;
176 }
177
178
179 PI_API
180 int privilege_info_get_description(const char *api_version, const char *privilege, char **description)
181 {
182         int ret = 0;
183         char* string_id = NULL;
184
185         TryReturn(api_version != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] api_version is NULL");
186         TryReturn(privilege != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege is NULL");
187
188         ret = privilege_info_get_string_id(NULL, 0, api_version, privilege, &string_id);
189
190         if (ret == PRVINFO_ERROR_NO_MATCHING_PRIVILEGE) {
191                 ret = privilege_info_get_string_by_string_id("IDS_TPLATFORM_BODY_THIS_PRIVILEGE_IS_NOT_DEFINED", description);
192                 TryReturn(ret == PRVINFO_ERROR_NONE, , PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
193         } else if (ret == PRVINFO_ERROR_NONE) {
194                 ret = privilege_info_get_string_by_string_id(string_id, description);
195                 free(string_id);
196                 TryReturn(ret == PRVINFO_ERROR_NONE, , PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
197         } else {
198                 return PRVINFO_ERROR_INTERNAL_ERROR;
199         }
200         return PRVINFO_ERROR_NONE;
201 }
202
203 PI_API
204 int privilege_info_get_display_name_by_pkgtype(const char *package_type, const char *api_version, const char *privilege, char **display_name)
205 {
206         int ret = 0;
207         char* string_id = NULL;
208
209         TryReturn(package_type != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] package_type is NULL");
210         TryReturn(api_version != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] api_version is NULL");
211         TryReturn(privilege != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege is NULL");
212
213         ret = privilege_info_get_string_id(package_type, 1, api_version, privilege, &string_id);
214         TryReturn(ret != PRVINFO_ERROR_INVALID_PARAMETER, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] invalid package_type : %s", package_type);
215
216         if (ret == PRVINFO_ERROR_NO_MATCHING_PRIVILEGE) {
217                 char* tempPrivilege = NULL;
218                 char* token = NULL;
219                 char* temp = NULL;
220                 char* save = NULL;
221                 tempPrivilege = strdup(privilege);
222                 TryReturn(tempPrivilege != NULL, free(tempPrivilege), PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] tempPrivilege's strdup is failed.");
223                 token = strtok_r(tempPrivilege, "/", &save);
224                 while (token) {
225                         temp = token;
226                         token = strtok_r(NULL, "/", &save);
227                 }
228                 *display_name = strdup(temp);
229                 TryReturn(*display_name != NULL, free(tempPrivilege), PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
230                 free(tempPrivilege);
231         } else if (ret == PRVINFO_ERROR_NONE) {
232                 ret = privilege_info_get_string_by_string_id(string_id, display_name);
233                 free(string_id);
234                 TryReturn(ret == PRVINFO_ERROR_NONE, , PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
235         } else {
236                 return PRVINFO_ERROR_INTERNAL_ERROR;
237         }
238         return PRVINFO_ERROR_NONE;
239 }
240
241 PI_API
242 int privilege_info_get_description_by_pkgtype(const char *package_type, const char *api_version, const char *privilege, char **description)
243 {
244         int ret = 0;
245         char* string_id = NULL;
246
247         TryReturn(package_type != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] package_type is NULL");
248         TryReturn(api_version != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] api_version is NULL");
249         TryReturn(privilege != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege is NULL");
250
251         ret = privilege_info_get_string_id(package_type, 0, api_version, privilege, &string_id);
252         TryReturn(ret != PRVINFO_ERROR_INVALID_PARAMETER, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] invalid package_type : %s", package_type);
253
254         if (ret == PRVINFO_ERROR_NO_MATCHING_PRIVILEGE) {
255                 ret = privilege_info_get_string_by_string_id("IDS_TPLATFORM_BODY_THIS_PRIVILEGE_IS_NOT_DEFINED", description);
256                 TryReturn(ret == PRVINFO_ERROR_NONE, , PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
257         } else if (ret == PRVINFO_ERROR_NONE) {
258                 ret = privilege_info_get_string_by_string_id(string_id, description);
259                 free(string_id);
260                 TryReturn(ret == PRVINFO_ERROR_NONE, , PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
261         } else {
262                 return PRVINFO_ERROR_INTERNAL_ERROR;
263         }
264         return PRVINFO_ERROR_NONE;
265 }
266
267 PI_API
268 int privilege_info_get_privacy_display_name(const char *privilege, char **privacy_display_name)
269 {
270         CHECK_FEATURE_SUPPORTED(PRIVACY_FEATURE);
271         TryReturn(privilege != NULL, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege is NULL");
272         TryReturn(privilege_db_manager_is('p', privilege) == 1, , PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege does not exist or is not a privacy related");
273
274         char* privacy_id = NULL;
275         char* privacy_display_string_id = NULL;
276
277         TryReturn(privilege_db_manager_get_privacy_by_privilege(privilege, &privacy_id) == PRIVILEGE_DB_MANAGER_ERR_NONE && privacy_id != NULL, , PRVINFO_ERROR_INTERNAL_ERROR, "[PRVINFO_ERROR_INTERNAL_ERROR] privilege_db_manager_get_privacy_by_privilege failed");
278
279         TryReturn(privilege_db_manager_get_privacy_display(privacy_id, &privacy_display_string_id) == PRIVILEGE_DB_MANAGER_ERR_NONE && privacy_display_string_id != NULL, free(privacy_id), PRVINFO_ERROR_INTERNAL_ERROR, "[PRVINFO_ERROR_INTERNAL_ERROR] privilege_db_manager_get_privacy_display failed");
280
281         TryReturn(privilege_info_get_string_by_string_id(privacy_display_string_id, privacy_display_name) == PRVINFO_ERROR_NONE && *privacy_display_name != NULL, free(privacy_id); free(privacy_display_string_id), PRVINFO_ERROR_OUT_OF_MEMORY, "[PRVINFO_ERROR_OUT_OF_MEMORY] Memory allocation failed.");
282
283         free(privacy_id);
284         free(privacy_display_string_id);
285         return PRVINFO_ERROR_NONE;
286 }
287
288 PI_API
289 int privilege_info_get_privacy_privilege_status(const char *privilege, bool *status)
290 {
291         CHECK_FEATURE_SUPPORTED(PRIVACY_FEATURE);
292         TryReturn(privilege != NULL, *status = true, PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege is NULL");
293         TryReturn(privilege_db_manager_is('p', privilege) == 1, *status = true, PRVINFO_ERROR_INVALID_PARAMETER, "[PRVINFO_ERROR_INVALID_PARAMETER] privilege does not exist or is not a privacy related");
294
295         char* smack_label = NULL;
296         TryReturn(smack_new_label_from_self(&smack_label) != -1, *status = true, PRVINFO_ERROR_INTERNAL_ERROR, "[PRVINFO_ERROR_INTERNAL_ERROR] smack_new_label_from_self() failed.");
297
298         cynara *cynara = NULL;
299         TryReturn(cynara_initialize(&cynara, NULL) == CYNARA_API_SUCCESS, *status = true; cynara = NULL; free(smack_label), PRVINFO_ERROR_INTERNAL_ERROR, "[PRVINFO_ERROR_INTERNAL_ERROR] cynara_initialize() failed.");
300
301         char *session = NULL;
302         session = cynara_session_from_pid(getpid());
303         TryReturn(session != NULL, *status = true; cynara_finish(cynara); free(smack_label), PRVINFO_ERROR_INTERNAL_ERROR, "[PRVINFO_ERROR_INTERNAL_ERROR] cynara_session_from_pid() failed");
304
305         char uid[UIDMAXLEN];
306         int result = snprintf(uid, UIDMAXLEN, "%d", getuid());
307         TryReturn(uid != NULL && result > 0, *status = true; free(session); cynara_finish(cynara); free(smack_label), PRVINFO_ERROR_INTERNAL_ERROR, "[PRVINFO_ERROR_INTERNAL_ERROR] snprintf() for uid failed.");
308
309         result = cynara_simple_check(cynara, smack_label, session, uid, privilege);
310         int ret = PRVINFO_ERROR_NONE;
311         free(session);
312         cynara_finish(cynara);
313
314         LOGD("result of cynara_check(cynara %s, session, %s, %s) result = %d", smack_label, uid, privilege, result);
315         free(smack_label);
316         if (result == CYNARA_API_ACCESS_DENIED) {
317                 *status = false;
318         } else if (result == CYNARA_API_ACCESS_ALLOWED) {
319                 *status = true;
320         } else {
321                 *status = true;
322                 LOGE("[PRVINFO_ERROR_INTERNAL_ERROR] cynara_check() failed. ret = %d", result);
323                 ret = PRVINFO_ERROR_INTERNAL_ERROR;
324         }
325
326         return ret;
327 }