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