perm_app_enable_permissions() always set persistent rules
[platform/core/security/libprivilege-control.git] / api_feature_loader / api_feature_loader.c
1 /*
2  * libprivilege control, rules database
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Jan Olszak <j.olszak@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 /**
23 * @file        api_feature_loader.c
24 * @author      Jan Olszak (j.olszak@samsung.com)
25 * @version     1.0
26 * @brief       Binary file for loading predefined API features to the database.
27 */
28
29 #define _GNU_SOURCE
30 #include <dirent.h>             // For iterating directories
31 #include <getopt.h>             // For getopt
32 #include <glob.h>               // For glob
33 #include <obstack.h>            // For obstack implementation
34 #include <privilege-control.h>  // For app_type
35 #include <stdio.h>              // For file manipulation
36 #include <stdlib.h>             // For malloc and free
37 #include <sys/smack.h>          // For SMACK_LABEL_LEN
38 #include <unistd.h>             // For basename
39
40
41 #define API_FEATURE_LOADER_VERSION "1.0"
42 #define API_FEATURES_DIR "/usr/share/privilege-control/"
43 #define API_FEATURE_LOADER_LOG(format, ...) if(i_verbose_flag__) printf(format, ##__VA_ARGS__)
44
45 // Obstack configuration
46 #define obstack_chunk_alloc malloc
47 #define obstack_chunk_free  free
48 #define vector_init(V)              obstack_init(&(V))
49 #define vector_push_back_ptr(V, I)  obstack_ptr_grow(&(V), (I))
50 #define vector_finish(V)            obstack_finish(&(V))
51 #define vector_free(V)              obstack_free(&(V), NULL)
52 typedef struct obstack vector_t;
53
54 static int i_verbose_flag__ = 0;
55 static const size_t ui_smack_ext_len__ = 6; // = strlen(".smack");
56
57 bool has_prefix(const char *const s_str, const char *const s_prefix)
58 {
59         return !strncmp(s_str, s_prefix, strlen(s_prefix));
60 }
61
62 bool has_smack_ext(const char *const s_str)
63 {
64         return strlen(s_str) > ui_smack_ext_len__ &&
65                !strncmp(&s_str[strlen(s_str) - ui_smack_ext_len__], ".smack", ui_smack_ext_len__);
66 }
67
68 int wrt_filter(const struct dirent *entry)
69 {
70         return !strcmp(entry->d_name, "WRT.smack");
71 }
72
73 int wrt_family_filter(const struct dirent *entry)
74 {
75         return has_prefix(entry->d_name, "WRT_") &&
76                has_smack_ext(entry->d_name);
77 }
78
79 int osp_filter(const struct dirent *entry)
80 {
81         return !strcmp(entry->d_name, "OSP.smack");
82 }
83
84
85 int osp_family_filter(const struct dirent *entry)
86 {
87         return has_prefix(entry->d_name, "OSP_") &&
88                has_smack_ext(entry->d_name);
89 }
90
91 int efl_filter(const struct dirent *entry)
92 {
93         return !strcmp(entry->d_name, "EFL.smack");
94 }
95
96 int efl_family_filter(const struct dirent *entry)
97 {
98         return has_prefix(entry->d_name, "EFL_") &&
99                has_smack_ext(entry->d_name);
100 }
101
102 void load_rules_from_file(const char *s_rules_file_path,
103                           const char *s_permission_name,
104                           const app_type_t app_type)
105 {
106         FILE *p_file       = NULL;
107         char *s_rule       = NULL;
108         char **rules_array = NULL;
109         size_t i_num_rules = 0;
110         size_t i           = 0;
111         int ret;
112         vector_t rules_vector;
113
114         p_file = fopen(s_rules_file_path, "r");
115         if(!p_file) goto finish;
116
117         API_FEATURE_LOADER_LOG("Loading permission: %s  \n", s_permission_name);
118
119         vector_init(rules_vector);
120         while(getline(&s_rule, &i, p_file) > 0) {
121                 vector_push_back_ptr(rules_vector, s_rule);
122                 ++i_num_rules;
123                 s_rule = NULL;
124         }
125         vector_push_back_ptr(rules_vector, NULL);
126
127         rules_array = vector_finish(rules_vector);
128
129         ret = perm_add_api_feature(app_type,
130                                    s_permission_name,
131                                    (const char **)rules_array,
132                                    NULL,
133                                    i_num_rules);
134         if(ret != PC_OPERATION_SUCCESS)
135                 API_FEATURE_LOADER_LOG("Error %d\n", ret);
136
137 finish:
138         if(p_file != NULL) fclose(p_file);
139         if(rules_array != NULL) {
140                 for(i = 0; i < i_num_rules; ++i) {
141                         free(rules_array[i]);
142                 }
143                 vector_free(rules_vector);
144         }
145 }
146
147
148 char *get_permission_name(const char *s_file_name, const char *s_prefix)
149 {
150         int i_prefix_len = strlen(s_prefix);
151
152         // Allocate memory
153         int i_perm_name_len = strlen(s_file_name);
154         char *s_permission_name = (char *) malloc(i_perm_name_len);
155         if(!s_permission_name) {
156                 API_FEATURE_LOADER_LOG("Error during allocating memory.\n");
157                 return NULL;
158         }
159
160         strncpy(s_permission_name,
161                 &(s_file_name[i_prefix_len]),
162                 i_perm_name_len - i_prefix_len - ui_smack_ext_len__);
163
164         s_permission_name[i_perm_name_len - i_prefix_len - ui_smack_ext_len__ ] = '\0';
165
166         return s_permission_name;
167 }
168
169 void load_permission_family(int (*filter)(const struct dirent *),
170                             const char const *s_prefix,
171                             const app_type_t app_type,
172                             const char const *s_dir)
173 {
174         int i, num_files          = 0;
175         struct dirent **file_list = NULL;
176         char *s_path              = NULL;
177         char *s_permission_name   = NULL;
178
179
180         num_files = scandir(s_dir, &file_list, filter, alphasort);
181         for(i = 0; i < num_files; ++i) {
182                 if(asprintf(&s_path, "%s%s", s_dir, file_list[i]->d_name) <= 0) continue;
183
184                 s_permission_name = get_permission_name(file_list[i]->d_name, s_prefix);
185                 load_rules_from_file(s_path, s_permission_name, app_type);
186
187                 free(file_list[i]);
188                 free(s_path);
189                 free(s_permission_name);
190                 s_path = NULL;
191                 s_permission_name = NULL;
192         }
193         free(file_list);
194 }
195
196 void load_pemission_type_rules(int (*filter)(const struct dirent *),
197                                const char const *s_permission_name,
198                                const app_type_t app_type,
199                                const char const *s_dir)
200 {
201         char *s_path              = NULL;
202         struct dirent **file_list = NULL;
203         int i, num_files;
204
205         num_files = scandir(s_dir, &file_list, filter, alphasort);
206         for(i = 0; i < num_files; ++i) {
207                 if(asprintf(&s_path, "%s%s", API_FEATURES_DIR, file_list[i]->d_name) <= 0) continue;
208
209                 load_rules_from_file(s_path, s_permission_name, app_type);
210
211                 free(file_list[i]);
212                 free(s_path);
213                 s_path = NULL;
214         }
215         free(file_list);
216 }
217
218
219 void load_from_dir(const char  *const s_dir)
220 {
221
222         API_FEATURE_LOADER_LOG("Loading rules from directory...\n");
223         if(perm_begin()) return;
224
225         // Load rules specific to permission's types:
226         load_pemission_type_rules(wrt_filter,          "WRT",          APP_TYPE_WGT,          s_dir);
227         load_pemission_type_rules(osp_filter,          "OSP",          APP_TYPE_OSP,          s_dir);
228         load_pemission_type_rules(efl_filter,          "EFL",          APP_TYPE_EFL,          s_dir);
229
230         // Load rules for each permission type:
231         load_permission_family(wrt_family_filter, "WRT_", APP_TYPE_WGT, s_dir);
232         load_permission_family(osp_family_filter, "OSP_", APP_TYPE_OSP, s_dir);
233         load_permission_family(efl_family_filter, "EFL_", APP_TYPE_EFL, s_dir);
234
235
236         perm_end();
237         API_FEATURE_LOADER_LOG("Done.\n");
238 }
239
240 void load_single_file(const char *const s_file_path)
241 {
242         API_FEATURE_LOADER_LOG("Loading rules from file...\n");
243         if(perm_begin()) return;
244
245         char *s_permission_name = NULL;
246         char *s_file_name;
247         struct dirent file;
248
249         if(!has_smack_ext(s_file_path)) {
250                 API_FEATURE_LOADER_LOG("File doesn't have smack extension: %s\n", s_file_path);
251                 perm_end();
252                 return;
253         }
254
255         s_file_name = basename(s_file_path);
256         strncpy(file.d_name, s_file_name, sizeof(file.d_name));
257
258         // Load as the right type of permission
259         if(wrt_family_filter(&file)) {
260                 s_permission_name = get_permission_name(s_file_name, "WRT_");
261                 load_rules_from_file(s_file_path, s_permission_name, APP_TYPE_WGT);
262
263         } else if(osp_family_filter(&file)) {
264                 s_permission_name = get_permission_name(s_file_name, "OSP_");
265                 load_rules_from_file(s_file_path, s_permission_name, APP_TYPE_OSP);
266
267         } else if(efl_family_filter(&file)) {
268                 s_permission_name = get_permission_name(s_file_name, "EFL_");
269                 load_rules_from_file(s_file_path, s_permission_name, APP_TYPE_EFL);
270
271         } else {
272                 API_FEATURE_LOADER_LOG("Unknown api-feature type: %s\n", s_file_path);
273         }
274
275         free(s_permission_name);
276
277         perm_end();
278         API_FEATURE_LOADER_LOG("Done.\n");
279 }
280
281 void load_from_file(const char *const s_name_pattern)
282 {
283         API_FEATURE_LOADER_LOG("Loading rules from file(s) matching pattern: %s\n",
284                                s_name_pattern);
285         int ret;
286         glob_t g;
287         ret = glob(s_name_pattern, 0, NULL, &g);
288
289         if(ret == GLOB_ABORTED) {
290                 API_FEATURE_LOADER_LOG("Cannot open given directory\n");
291                 goto finish;
292         }
293         if(ret == GLOB_NOMATCH) {
294                 API_FEATURE_LOADER_LOG("No match found for given pattern\n");
295                 goto finish;
296         }
297         if(ret == GLOB_NOSPACE) {
298                 API_FEATURE_LOADER_LOG("Not enough memory\n");
299                 goto finish;
300         }
301         if(ret != 0) {
302                 API_FEATURE_LOADER_LOG("Error during file(s) loading\n");
303                 goto finish;
304         }
305
306         size_t i;
307         for(i = 0; i < g.gl_pathc; ++i)
308                 load_single_file(g.gl_pathv[i]);
309
310 finish:
311         globfree(&g);
312
313         API_FEATURE_LOADER_LOG("Loading rules from file(s) matching pattern: %s done.\n",
314                                s_name_pattern);
315 }
316
317 int main(int argc, char *argv[])
318 {
319         int c;
320         int i_option_index = 0;
321
322         bool b_load_from_file = false;
323         const char *s_file_name = NULL;
324
325         bool b_load_from_dir = false;
326         const char *s_dir_name = NULL;
327
328         static struct option long_options[] = {
329                 {"verbose", no_argument,       &i_verbose_flag__,  1},
330                 {"file",    required_argument, 0, 'f'},
331                 {"dir",     required_argument, 0, 'd'},
332                 {"help",    no_argument,       0, 'h'},
333                 {"version", no_argument,       0, 'v'},
334                 {0, 0, 0, 0}
335         };
336
337         while((c = getopt_long(argc, argv,
338                                "f:d:hv",
339                                long_options,
340                                &i_option_index)) != -1) {
341                 switch(c) {
342                 case 0:
343                         // If this option set a flag, do nothing.
344                         break;
345                 case '?':
346                         // No such command.
347                         // getopt_long already printed an error message.
348                         return 0;
349                 case 'f':
350                         b_load_from_file = true;
351                         s_file_name = optarg;
352                         break;
353
354                 case 'd':
355                         b_load_from_dir = true;
356                         s_dir_name = optarg;
357                         break;
358
359                 case 'h':
360                         printf("Api feature loader v." API_FEATURE_LOADER_VERSION "\n\n");
361                         printf("    Options:\n");
362                         printf("        -d,--dir=path        load api-features from the directory\n");
363                         printf("        -f,--file=file_name  load api-feature from the file\n");
364                         printf("        -h,--help            print this help\n");
365                         printf("        --verbose            verbose output\n");
366                         printf("        -v,--version         show applcation version\n");
367
368                         return 0;
369
370                 case 'v':
371                         printf("Api feature loader v." API_FEATURE_LOADER_VERSION "\n");
372                         return 0;
373
374                 default:
375                         break;
376                 }
377         }
378
379         // Print unknown remaining command line arguments
380         if(optind < argc) {
381                 printf("Unknown options: ");
382                 while(optind < argc)
383                         printf("%s ", argv[optind++]);
384                 putchar('\n');
385                 return 0;
386         }
387
388         // Run task
389         if(b_load_from_dir)
390                 load_from_dir(s_dir_name);
391         if(b_load_from_file)
392                 load_from_file(s_file_name);
393         if(!b_load_from_dir &&
394             !b_load_from_file)
395                 load_from_dir(API_FEATURES_DIR);
396
397         return 0;
398 }