Add implementation for appsetting privilege
[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         C_LOGD("Enter function: %s", __func__);
62
63         if (NULL == elem)
64                 return NULL;
65
66         element_t* new_element = malloc(sizeof(element_t));
67         if (NULL == new_element)
68                 return NULL;
69
70         new_element->value = malloc(sizeof(char) * (SMACK_LABEL_LEN + 1) );
71         if (NULL == new_element->value) {
72                 free(new_element);
73                 return NULL;
74         }
75
76         strncpy(new_element->value, value, SMACK_LABEL_LEN);
77         new_element->value[SMACK_LABEL_LEN] = '\0';
78         new_element->next = NULL;
79         elem->next = new_element;
80
81         return new_element;
82 }
83
84 static int remove_list(element_t* first_elem)
85 {
86         C_LOGD("Enter function: %s", __func__);
87
88         element_t* current = NULL;
89
90         while (NULL != first_elem) {
91                 current = first_elem;
92                 first_elem = first_elem->next;
93                 free(current);
94         }
95         return 0;
96 }
97
98 static int add_id_to_database_internal(const char * id, db_app_type_t app_type)
99 {
100         C_LOGD("Enter function: %s", __func__);
101         FILE* file_db AUTO_FCLOSE;
102         const char* db_file_name = db_file_names[app_type];
103
104         file_db = fopen(db_file_name, "a");
105         if (NULL == file_db) {
106                 C_LOGE("Error while opening database file: %s", db_file_name);
107                 return PC_ERR_FILE_OPERATION;
108         }
109
110         if (0 > fprintf(file_db, "%s\n", id)) {
111                 C_LOGE("Write label %s to database failed: %s", id, strerror(errno));
112                 return PC_ERR_FILE_OPERATION;
113         }
114
115         return PC_OPERATION_SUCCESS;
116 }
117
118 static int get_all_ids_internal (char *** ids, int * len, db_app_type_t app_type)
119 {
120         int ret;
121         char* scanf_label_format AUTO_FREE;
122         FILE* file_db AUTO_FCLOSE;
123         const char* db_file_name = db_file_names[app_type];
124         char smack_label[SMACK_LABEL_LEN + 1];
125         element_t* begin_of_list = NULL;
126
127         if (asprintf(&scanf_label_format, "%%%ds\\n", SMACK_LABEL_LEN) < 0) {
128                 C_LOGE("Error while creating scanf input label format");
129                 ret = PC_ERR_MEM_OPERATION;
130                 goto out;
131         }
132
133         file_db = fopen(db_file_name, "r");
134         if (NULL == file_db) {
135                 C_LOGE("Error while opening antivirus_ids database file: %s", db_file_name);
136                 ret = PC_ERR_FILE_OPERATION;
137                 goto out;
138         }
139
140         // intialization of list of smack labels
141         *len = 0;
142         begin_of_list = malloc(sizeof(element_t));
143         if (begin_of_list == NULL ) {
144                 C_LOGE("Error while allocating memory");
145                 ret = PC_ERR_MEM_OPERATION;
146                 goto out;
147         }
148         begin_of_list->next  = NULL;
149         begin_of_list->value = NULL;
150         element_t* current = begin_of_list;
151
152         // reading from file ("database")
153         // notice that first element always stays with empty "value"
154         while (fscanf(file_db, scanf_label_format, smack_label) == 1) {
155                 smack_label[SMACK_LABEL_LEN] = '\0';
156                 if (!smack_label_is_valid(smack_label)) {
157                         C_LOGD("Found entry in database, but it's not correct SMACK label: \"%s\"", smack_label);
158                         continue;
159                 }
160                 C_LOGD("Found installed anti virus label: \"%s\"", smack_label);
161                 ++(*len);
162                 current = add_element(current, smack_label);
163                 if (NULL == current) {
164                         C_LOGE("Error while adding smack label to the list");
165                         ret = PC_ERR_MEM_OPERATION;
166                         goto out;
167                 }
168         }
169
170         if (*len > 0) {
171                 C_LOGD("Allocating memory for list of %d labels", *len);
172                 *ids = malloc((*len) * sizeof(char*));
173                 if (NULL == *ids) {
174                         C_LOGE("Error while allocating memory for list of labels");
175                         ret = PC_ERR_MEM_OPERATION;
176                         goto out;
177                 }
178                 current = begin_of_list->next;
179                 int i;
180                 for (i=0; i < *len; ++i) {
181                         C_LOGD("Allocating memory for \"%s\" label", current->value);
182                         (*ids)[i] = malloc((SMACK_LABEL_LEN + 1) * sizeof(char));
183                         if (NULL == (*ids)[i]) {
184                                 ret = PC_ERR_MEM_OPERATION;
185                                 C_LOGE("Error while allocating memory for \"%s\" label", current->value);
186                                 goto out;
187                         }
188                         strncpy((*ids)[i], current->value, SMACK_LABEL_LEN);
189                         (*ids)[i][SMACK_LABEL_LEN] = '\0';
190                         current = current->next;
191                 }
192         }
193         else {
194                 C_LOGD("Not found any labels!");
195                 *ids = NULL;
196         }
197
198         ret =  PC_OPERATION_SUCCESS;
199
200
201 out:
202         remove_list(begin_of_list);
203
204         return ret;
205 }
206
207 int get_all_apps_ids (char *** apps_ids, int * len)
208 {
209         if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_APPLICATION))
210                 return PC_ERR_DB_OPERATION;
211
212         return PC_OPERATION_SUCCESS;
213 }
214
215 int get_all_settings_dir_ids(char ***apps_ids, int *len)
216 {
217         if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_SETTING_DIR))
218                 return PC_ERR_DB_OPERATION;
219
220         return PC_OPERATION_SUCCESS;
221 }
222
223 int get_all_appsetting_ids(char ***apps_ids, int *len)
224 {
225         if (get_all_ids_internal(apps_ids, len, DB_APP_TYPE_APPSETTING))
226                 return PC_ERR_DB_OPERATION;
227
228         return PC_OPERATION_SUCCESS;
229 }
230
231 int get_all_avs_ids (char *** av_ids, int * len)
232 {
233         if (get_all_ids_internal(av_ids, len, DB_APP_TYPE_ANTIVIRUS))
234                 return PC_ERR_DB_OPERATION;
235
236         return PC_OPERATION_SUCCESS;
237 }
238
239 int add_app_id_to_databse(const char * app_id)
240 {
241         C_LOGD("Enter function: %s", __func__);
242
243         if (add_id_to_database_internal(app_id, DB_APP_TYPE_APPLICATION))
244                 return PC_ERR_DB_OPERATION;
245
246         return PC_OPERATION_SUCCESS;
247 }
248
249 int add_av_id_to_databse (const char * av_id)
250 {
251         C_LOGD("Enter function: %s", __func__);
252
253         if (add_id_to_database_internal(av_id, DB_APP_TYPE_ANTIVIRUS))
254                 return PC_ERR_DB_OPERATION;
255
256         return PC_OPERATION_SUCCESS;
257 }
258
259 int add_appsetting_id_to_databse(const char *appsetting_id)
260 {
261         C_LOGD("Enter function: %s", __func__);
262
263         if (add_id_to_database_internal(appsetting_id, DB_APP_TYPE_APPSETTING))
264                 return PC_ERR_DB_OPERATION;
265
266         return PC_OPERATION_SUCCESS;
267 }
268
269 int add_setting_dir_id_to_databse(const char *setting_dir_id)
270 {
271         C_LOGD("Enter function: %s", __func__);
272
273         if (add_id_to_database_internal(
274                         setting_dir_id, DB_APP_TYPE_SETTING_DIR))
275                 return PC_ERR_DB_OPERATION;
276
277         return PC_OPERATION_SUCCESS;
278 }
279
280 int add_app_gid(const char *app_id, unsigned gid)
281 {
282         C_LOGD("Enter function: %s", __func__);
283         char *field = NULL;
284         int ret;
285
286         ret = asprintf(&field, "%u:%s", gid, app_id);
287         if (ret == -1)
288                 return PC_ERR_MEM_OPERATION;
289
290         ret = add_id_to_database_internal(field, DB_APP_TYPE_GROUPS);
291         free(field);
292
293         return ret;
294 }
295
296 int get_app_gids(const char *app_id, unsigned **gids, int *len)
297 {
298         char** fields AUTO_FREE;
299         int len_tmp, ret, i;
300
301         ret = get_all_ids_internal(&fields, &len_tmp, DB_APP_TYPE_GROUPS);
302         if (ret != PC_OPERATION_SUCCESS)
303                 return ret;
304
305         *len = 0;
306         *gids = NULL;
307         for (i = 0; i < len_tmp; ++i) {
308                 const char *field = fields[i];
309                 const char *app_id_tmp = NULL;
310                 unsigned gid = 0;
311
312                 for (; *field; ++field) {
313                         if (*field == ':') {
314                                 app_id_tmp = field + 1;
315                                 break;
316                         }
317                         if (isdigit(*field)) {
318                                 gid = gid * 10 + *field - '0';
319                         } else {
320                                 C_LOGE("Invalid line read: %s", fields[i]);
321                                 ret = PC_ERR_FILE_OPERATION;
322                                 goto out;
323                         }
324                 }
325
326                 if (!app_id_tmp) {
327                         C_LOGE("No group id found");
328                         ret = PC_ERR_FILE_OPERATION;
329                         goto out;
330                 }
331
332                 if (!strcmp(app_id, app_id_tmp)) {
333                         unsigned *gids_realloc = realloc(*gids, sizeof(unsigned) * (*len + 1));
334                         if (gids_realloc == NULL) {
335                                 C_LOGE("Memory allocation failed");
336                                 ret = PC_ERR_MEM_OPERATION;
337                                 goto out;
338                         }
339                         *gids = gids_realloc;
340                         (*gids)[(*len)++] = gid;
341                 }
342         }
343
344         ret = PC_OPERATION_SUCCESS;
345 out:
346         for (i = 0; i < len_tmp; ++i)
347                 free(fields[i]);
348
349         if (ret != PC_OPERATION_SUCCESS) {
350                 free(*gids);
351                 *len = 0;
352         }
353
354         return ret;
355 }
356
357 int db_add_public_dir(const char *dir_label)
358 {
359         C_LOGD("Enter function: %s", __func__);
360
361         if (add_id_to_database_internal(dir_label, DB_APP_TYPE_PUBLIC_DIRS))
362                 return PC_ERR_DB_OPERATION;
363
364         return PC_OPERATION_SUCCESS;
365 }
366
367 int db_get_public_dirs(char ***dir_labels, int *len)
368 {
369         C_LOGD("Enter function: %s", __func__);
370
371         if (get_all_ids_internal(dir_labels, len, DB_APP_TYPE_PUBLIC_DIRS))
372                 return PC_ERR_DB_OPERATION;
373
374         return PC_OPERATION_SUCCESS;
375 }