Fix unwanted differences between SLP and RSA repositories.
[platform/core/security/libprivilege-control.git] / src / access-db.c
1 /*
2  * libprivilege control
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Janusz Kozerski <j.kozerski@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #define _GNU_SOURCE
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <sys/smack.h>
28 #include <dlog.h>
29 #include <ctype.h>
30
31 #include "access-db.h"
32 #include "privilege-control.h"
33 #include "common.h"
34
35 typedef enum {
36         DB_APP_TYPE_APPLICATION,
37         DB_APP_TYPE_ANTIVIRUS,
38         DB_APP_TYPE_GROUPS,
39         DB_APP_TYPE_PUBLIC_DIRS,
40         DB_APP_TYPE_APPSETTING,
41         DB_APP_TYPE_SETTING_DIR,
42         DB_APP_TYPE_COUNT /* Dummy enum element to get number of elements */
43 } db_app_type_t;
44
45 const char* db_file_names[DB_APP_TYPE_COUNT] = {
46                 "/opt/dbspace/.privilege_control_all_apps_id.db",
47                 "/opt/dbspace/.privilege_control_all_avs_id.db",
48                 "/opt/dbspace/.privilege_control_app_gids.db",
49                 "/opt/dbspace/.privilege_control_public_dirs.db",
50                 "/opt/dbspace/.privilege_control_app_setting.db",
51                 "/opt/dbspace/.privilege_control_setting_dir.db",
52 };
53
54 typedef struct element_s {
55         struct element_s* next;
56         char* value;
57 } element_t;
58
59 static element_t* add_element (element_t* elem, const char* value)
60 {
61         SECURE_C_LOGD("Entering function: %s. Params: value=%s",
62                                 __func__, value);
63
64         if (NULL == elem)
65                 return NULL;
66
67         element_t* new_element = malloc(sizeof(element_t));
68         if (NULL == new_element)
69                 return NULL;
70
71         new_element->value = malloc(sizeof(char) * (SMACK_LABEL_LEN + 1) );
72         if (NULL == new_element->value) {
73                 free(new_element);
74                 return NULL;
75         }
76
77         strncpy(new_element->value, value, SMACK_LABEL_LEN);
78         new_element->value[SMACK_LABEL_LEN] = '\0';
79         new_element->next = NULL;
80         elem->next = new_element;
81
82         return new_element;
83 }
84
85 static int remove_list(element_t* first_elem)
86 {
87         SECURE_C_LOGD("Entering function: %s.", __func__);
88
89         element_t* current = NULL;
90
91         while (NULL != first_elem) {
92                 current = first_elem;
93                 first_elem = first_elem->next;
94                 if (current->value)
95                         free(current->value);
96                 free(current);
97         }
98         return 0;
99 }
100
101 static int add_id_to_database_internal(const char * id, db_app_type_t app_type)
102 {
103         SECURE_C_LOGD("Entering function: %s. Params: id=%s",
104                                 __func__, id);
105
106         FILE* file_db AUTO_FCLOSE;
107         const char* db_file_name = db_file_names[app_type];
108
109         SECURE_C_LOGD("Opening database file %s.", db_file_name);
110         file_db = fopen(db_file_name, "a");
111         if (NULL == file_db) {
112                 SECURE_C_LOGE("Error while opening database file: %s", db_file_name);
113                 return PC_ERR_FILE_OPERATION;
114         }
115
116         if (0 > fprintf(file_db, "%s\n", id)) {
117                 SECURE_C_LOGE("Write label %s to database failed (error: %s)", id, strerror(errno));
118                 return PC_ERR_FILE_OPERATION;
119         }
120
121         return PC_OPERATION_SUCCESS;
122 }
123
124 static int get_all_ids_internal (char *** ids, int * len, db_app_type_t app_type)
125 {
126         SECURE_C_LOGD("Entering function: %s.", __func__);
127
128         int ret;
129         FILE* file_db AUTO_FCLOSE;
130         const char* db_file_name = db_file_names[app_type];
131         char smack_label[SMACK_LABEL_LEN + 1];
132         element_t* begin_of_list = NULL;
133
134         SECURE_C_LOGD("Opening database file %s.", db_file_name);
135         file_db = fopen(db_file_name, "r");
136         if (NULL == file_db) {
137                 SECURE_C_LOGE("Error while opening database file: %s", db_file_name);
138                 ret = PC_ERR_FILE_OPERATION;
139                 goto out;
140         }
141
142         // intialization of list of smack labels
143         *len = 0;
144         begin_of_list = malloc(sizeof(element_t));
145         if (begin_of_list == NULL ) {
146                 C_LOGE("Error while allocating memory");
147                 ret = PC_ERR_MEM_OPERATION;
148                 goto out;
149         }
150         begin_of_list->next  = NULL;
151         begin_of_list->value = NULL;
152         element_t* current = begin_of_list;
153
154         // reading from file ("database")
155         // notice that first element always stays with empty "value"
156         while (fscanf(file_db, "%" TOSTRING(SMACK_LABEL_LEN) "s\n", smack_label) == 1) {
157                 smack_label[SMACK_LABEL_LEN] = '\0';
158                 if (!smack_label_is_valid(smack_label)) {
159                         SECURE_C_LOGD("Found entry in database, but it's not correct SMACK label: \"%s\"", smack_label);
160                         continue;
161                 }
162                 SECURE_C_LOGD("Found installed label: \"%s\"", smack_label);
163                 ++(*len);
164                 current = add_element(current, smack_label);
165                 if (NULL == current) {
166                         *len = 0;
167                         C_LOGE("Error while adding smack label to the list.");
168                         ret = PC_ERR_MEM_OPERATION;
169                         goto out;
170                 }
171         }
172
173         if (*len > 0) {
174                 C_LOGD("Allocating memory for list of %d labels", *len);
175                 *ids = malloc((*len) * sizeof(char*));
176                 if (NULL == *ids) {
177                         *len = 0;
178                         C_LOGE("Error while allocating memory for list of labels.");
179                         ret = PC_ERR_MEM_OPERATION;
180                         goto out;
181                 }
182                 current = begin_of_list->next;
183                 int i;
184                 for (i=0; i < *len; ++i) {
185                         C_LOGD("Allocating memory for \"%s\" label", current->value);
186                         (*ids)[i] = malloc((SMACK_LABEL_LEN + 1) * sizeof(char));
187                         if (NULL == (*ids)[i]) {
188                                 ret = PC_ERR_MEM_OPERATION;
189                                 int j;
190                                 for (j = 0; j < i; ++j)
191                                         free((*ids)[j]);
192                                 free(*ids);
193                                 *ids = NULL;
194                                 *len = 0;
195                                 C_LOGE("Error while allocating memory for \"%s\" label", current->value);
196                                 goto out;
197                         }
198                         strncpy((*ids)[i], current->value, SMACK_LABEL_LEN);
199                         (*ids)[i][SMACK_LABEL_LEN] = '\0';
200                         current = current->next;
201                 }
202         }
203         else {
204                 C_LOGD("No labels found!");
205                 *ids = NULL;
206         }
207
208         ret =  PC_OPERATION_SUCCESS;
209
210
211 out:
212         remove_list(begin_of_list);
213
214         return ret;
215 }
216
217 int get_all_apps_ids (char *** apps_ids, int * len)
218 {
219         SECURE_C_LOGD("Entering function: %s.", __func__);
220
221         if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_APPLICATION))
222                 return PC_ERR_DB_OPERATION;
223
224         return PC_OPERATION_SUCCESS;
225 }
226
227 int get_all_settings_dir_ids(char ***apps_ids, int *len)
228 {
229         SECURE_C_LOGD("Entering function: %s.", __func__);
230
231         if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_SETTING_DIR))
232                 return PC_ERR_DB_OPERATION;
233
234         return PC_OPERATION_SUCCESS;
235 }
236
237 int get_all_appsetting_ids(char ***apps_ids, int *len)
238 {
239         SECURE_C_LOGD("Entering function: %s.", __func__);
240
241         if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_APPSETTING))
242                 return PC_ERR_DB_OPERATION;
243
244         return PC_OPERATION_SUCCESS;
245 }
246
247 int get_all_avs_ids (char *** av_ids, int * len)
248 {
249         SECURE_C_LOGD("Entering function: %s.", __func__);
250
251         if (get_all_ids_internal(av_ids, len, DB_APP_TYPE_ANTIVIRUS))
252                 return PC_ERR_DB_OPERATION;
253
254         return PC_OPERATION_SUCCESS;
255 }
256
257 int add_app_id_to_databse(const char * app_id)
258 {
259         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
260                                 __func__, app_id);
261
262         if (add_id_to_database_internal(app_id, DB_APP_TYPE_APPLICATION))
263                 return PC_ERR_DB_OPERATION;
264
265         return PC_OPERATION_SUCCESS;
266 }
267
268 int add_av_id_to_databse (const char * av_id)
269 {
270         SECURE_C_LOGD("Entering function: %s. Params: av_id=%s",
271                                 __func__, av_id);
272
273         if (add_id_to_database_internal(av_id, DB_APP_TYPE_ANTIVIRUS))
274                 return PC_ERR_DB_OPERATION;
275
276         return PC_OPERATION_SUCCESS;
277 }
278
279 int add_appsetting_id_to_databse(const char *appsetting_id)
280 {
281         SECURE_C_LOGD("Entering function: %s. Params: appsetting_id=%s",
282                                 __func__, appsetting_id);
283
284         if (add_id_to_database_internal(appsetting_id, DB_APP_TYPE_APPSETTING))
285                 return PC_ERR_DB_OPERATION;
286
287         return PC_OPERATION_SUCCESS;
288 }
289
290 int add_setting_dir_id_to_databse(const char *setting_dir_id)
291 {
292         SECURE_C_LOGD("Entering function: %s. Params: setting_dir_id=%s",
293                                 __func__, setting_dir_id);
294
295         if (add_id_to_database_internal(
296                         setting_dir_id, DB_APP_TYPE_SETTING_DIR))
297                 return PC_ERR_DB_OPERATION;
298
299         return PC_OPERATION_SUCCESS;
300 }
301
302 int add_app_gid(const char *app_id, unsigned gid)
303 {
304         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, gid=%u",
305                                 __func__, app_id, gid);
306
307         char *field = NULL;
308         int ret;
309
310         ret = asprintf(&field, "%u:%s", gid, app_id);
311         if (ret == -1)
312         {
313                 C_LOGE("asprintf failed.");
314                 return PC_ERR_MEM_OPERATION;
315         }
316
317         ret = add_id_to_database_internal(field, DB_APP_TYPE_GROUPS);
318         free(field);
319
320         return ret;
321 }
322
323 int get_app_gids(const char *app_id, unsigned **gids, int *len)
324 {
325         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
326                                 __func__, app_id);
327
328         char** fields AUTO_FREE;
329         int len_tmp, ret, i;
330
331         ret = get_all_ids_internal(&fields, &len_tmp, DB_APP_TYPE_GROUPS);
332         if (ret != PC_OPERATION_SUCCESS)
333         {
334                 C_LOGE("get_all_ids_internal failed.");
335                 return ret;
336         }
337
338         *len = 0;
339         *gids = NULL;
340         for (i = 0; i < len_tmp; ++i) {
341                 const char *field = fields[i];
342                 const char *app_id_tmp = NULL;
343                 unsigned gid = 0;
344
345                 for (; *field; ++field) {
346                         if (*field == ':') {
347                                 app_id_tmp = field + 1;
348                                 break;
349                         }
350                         if (isdigit(*field)) {
351                                 gid = gid * 10 + *field - '0';
352                         } else {
353                                 C_LOGE("Invalid format of group id read from groups database: %s", fields[i]);
354                                 ret = PC_ERR_FILE_OPERATION;
355                                 goto out;
356                         }
357                 }
358
359                 if (!app_id_tmp) {
360                         C_LOGE("No group id found.");
361                         ret = PC_ERR_FILE_OPERATION;
362                         goto out;
363                 }
364
365                 if (NULL == app_id) {
366                         *len = 0;
367                         return PC_OPERATION_SUCCESS;
368                 }
369
370                 if (!strcmp(app_id, app_id_tmp)) {
371                         unsigned *gids_realloc = realloc(*gids, sizeof(unsigned) * (*len + 1));
372                         if (gids_realloc == NULL) {
373                                 C_LOGE("Memory allocation failed.");
374                                 ret = PC_ERR_MEM_OPERATION;
375                                 goto out;
376                         }
377                         *gids = gids_realloc;
378                         (*gids)[(*len)++] = gid;
379                 }
380         }
381
382         ret = PC_OPERATION_SUCCESS;
383 out:
384         for (i = 0; i < len_tmp; ++i)
385                 free(fields[i]);
386
387         if (ret != PC_OPERATION_SUCCESS) {
388                 free(*gids);
389                 *len = 0;
390         }
391
392         return ret;
393 }
394
395 int db_add_public_dir(const char *dir_label)
396 {
397         SECURE_C_LOGD("Entering function: %s. Params: dir_label=%s",
398                                 __func__, dir_label);
399
400         if (add_id_to_database_internal(dir_label, DB_APP_TYPE_PUBLIC_DIRS))
401         {
402                 C_LOGE("add_id_to_database_internal failed.");
403                 return PC_ERR_DB_OPERATION;
404         }
405
406         return PC_OPERATION_SUCCESS;
407 }
408
409 int db_get_public_dirs(char ***dir_labels, int *len)
410 {
411         SECURE_C_LOGD("Entering function: %s.", __func__);
412
413         if (get_all_ids_internal(dir_labels, len, DB_APP_TYPE_PUBLIC_DIRS))
414         {
415                 C_LOGE("get_all_ids_internal failed.");
416                 return PC_ERR_DB_OPERATION;
417         }
418
419         return PC_OPERATION_SUCCESS;
420 }