Correction in enabling permissions.
[platform/core/security/libprivilege-control.git] / src / privilege-control.c
1 /*
2  * libprivilege control
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact: Kidong Kim <kd0228.kim@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 <string.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <grp.h>
30 #include <fts.h>
31 #include <errno.h>
32 #include <math.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35 #include <sys/time.h>
36 #include <sys/stat.h>
37 #include <sys/file.h>
38 #include <sys/smack.h>
39 #include <linux/capability.h>
40 #include <sys/capability.h>
41 #include <sys/mman.h>
42 #include <stdbool.h>
43 #include <search.h>
44
45 #include "privilege-control.h"
46 #include "access-db.h"
47 #include "common.h"
48 #include "rules-db.h"
49
50 #define APP_GID 5000
51 #define APP_UID 5000
52 #define DEVELOPER_GID   5100
53 #define DEVELOPER_UID   5100
54
55 #define APP_USER_NAME   "app"
56 #define DEV_USER_NAME   "developer"
57
58 #define APP_HOME_DIR    TOSTRING(HOMEDIR) "/app"
59 #define DEV_HOME_DIR    TOSTRING(HOMEDIR) "/developer"
60
61 #define APP_GROUP_PATH  TOSTRING(SHAREDIR) "/app_group_list"
62 #define DEV_GROUP_PATH  TOSTRING(SHAREDIR) "/dev_group_list"
63
64 #define SMACK_SRC_FILE_SUFFIX   "_src_file"
65 #define SMACK_SRC_DIR_SUFFIX    "_src_dir"
66 #define SMACK_DATA_SUFFIX       "_data"
67 #define WRT_BASE_DEVCAP         "WRT"
68 #define WRT_CLIENT_PATH         "/usr/bin/wrt-client"
69 #define ACC_LEN                 6
70 #define TIZEN_PRIVILEGE_ANTIVIRUS  "http://tizen.org/privilege/antivirus"
71 #define TIZEN_PRIVILEGE_APPSETTING "http://tizen.org/privilege/appsetting"
72 #define PATH_RULES_PUBLIC_RO       "PATH_RULES_PUBLIC_RO.smack"
73 #define PATH_RULES_GROUP_RW        "PATH_RULES_GROUP_RW.smack"
74
75 typedef struct {
76         char user_name[10];
77         int uid;
78         int gid;
79         char home_dir[64];
80         char group_list[64];
81 } new_user;
82
83 /**
84  * Return values
85  * <0 - error
86  * 0 - skip
87  * 1 - label
88  */
89 typedef int (*label_decision_fn)(const FTSENT*);
90 enum {
91         DECISION_SKIP = 0,
92         DECISION_LABEL = 1
93 };
94
95 __attribute__ ((destructor))
96 static void libprivilege_destructor()
97 {
98         SECURE_C_LOGD("Entering function: %s.", __func__);
99         perm_end();
100 }
101
102 API int perm_begin(void)
103 {
104         SECURE_C_LOGD("Entering function: %s.", __func__);
105         return rdb_modification_start();
106 }
107
108 API int perm_end(void)
109 {
110         SECURE_C_LOGD("Entering function: %s.", __func__);
111
112         rdb_modification_finish();
113         sync();
114         return PC_OPERATION_SUCCESS;
115 }
116
117 API int control_privilege(void)//deprecated
118 {
119         SECURE_C_LOGD("Entering function: %s.", __func__);
120
121         if(getuid() == APP_UID) // current user is 'app'
122                 return PC_OPERATION_SUCCESS;
123
124         if(perm_app_set_privilege("org.tizen.", NULL, NULL) == PC_OPERATION_SUCCESS)
125                 return PC_OPERATION_SUCCESS;
126         else {
127                 C_LOGE("perm_app_set_privilege failed (not permitted).");
128                 return PC_ERR_NOT_PERMITTED;
129         }
130 }
131
132 /**
133  * TODO: this function should be moved to libsmack in open-source.
134  */
135 API int get_smack_label_from_process(pid_t pid, char *smack_label)
136 {
137         SECURE_C_LOGD("Entering function: %s. Params: pid=%i", __func__, pid);
138
139         int ret;
140         int fd AUTO_CLOSE;
141         int PATH_MAX_LEN = 64;
142         char path[PATH_MAX_LEN + 1];
143
144         if (pid < 0) {
145                 C_LOGE("invalid param pid.");
146                 ret = PC_ERR_INVALID_PARAM;
147                 goto out;
148         }
149
150         if(smack_label == NULL) {
151                 C_LOGE("Invalid param smack_label (NULL).");
152                 ret = PC_ERR_INVALID_PARAM;
153                 goto out;
154         }
155
156         bzero(smack_label, SMACK_LABEL_LEN + 1);
157         if (!have_smack()) { // If no smack just return success with empty label
158                 C_LOGD("No SMACK. Returning empty label");
159                 ret = PC_OPERATION_SUCCESS;
160                 goto out;
161         }
162
163         bzero(path, PATH_MAX_LEN + 1);
164         snprintf(path, PATH_MAX_LEN, "/proc/%d/attr/current", pid);
165         fd = open(path, O_RDONLY);
166         if (fd < 0) {
167                 SECURE_C_LOGE("Cannot open file %s (errno: %s)", path, strerror(errno));
168                 ret = PC_ERR_FILE_OPERATION;
169                 goto out;
170         }
171
172         ret = read(fd, smack_label, SMACK_LABEL_LEN);
173         if (ret < 0) {
174                 SECURE_C_LOGE("Cannot read from file %s", path);
175                 ret = PC_ERR_FILE_OPERATION;
176                 goto out;
177         }
178
179         SECURE_C_LOGD("smack_label=%s", smack_label);
180
181         ret = PC_OPERATION_SUCCESS;
182
183 out:
184         return ret;
185 }
186
187 API int smack_pid_have_access(pid_t pid,
188                                                                 const char* object,
189                                                                 const char *access_type)
190 {
191         SECURE_C_LOGD("Entering function: %s. Params: pid=%i, object=%s, access_type=%s",
192                                 __func__, pid, object, access_type);
193
194         int ret;
195         char pid_subject_label[SMACK_LABEL_LEN + 1];
196         cap_t cap;
197         cap_flag_value_t cap_v;
198
199         if (!have_smack()) {
200                 C_LOGD("No SMACK. Return access granted");
201                 return 1;
202         }
203
204         if (pid < 0) {
205                 C_LOGE("Invalid pid.");
206                 return -1;
207         }
208
209         if(object == NULL) {
210                 C_LOGE("Invalid object param.");
211                 return -1;
212         }
213
214         if(access_type == NULL) {
215                 C_LOGE("Invalid access_type param");
216                 return -1;
217         }
218
219         //get SMACK label of process
220         ret = get_smack_label_from_process(pid, pid_subject_label);
221         if (PC_OPERATION_SUCCESS != ret) {
222                 SECURE_C_LOGE("get_smack_label_from_process %d failed: %d", pid, ret);
223                 return -1;
224         }
225         SECURE_C_LOGD("pid %d has label: %s", pid, pid_subject_label);
226
227         // do not call smack_have_access() if label is empty
228         if (pid_subject_label[0] != '\0') {
229                 ret = smack_have_access(pid_subject_label, object, access_type);
230                 if ( -1 == ret) {
231                         C_LOGE("smack_have_access failed.");
232                         return -1;
233                 }
234                 if ( 1 == ret ) { // smack_have_access return 1 (access granted)
235                         C_LOGD("smack_have_access returned 1 (access granted)");
236                         return 1;
237                 }
238         }
239
240         // smack_have_access returned 0 (access denied). Now CAP_MAC_OVERRIDE should be checked
241         C_LOGD("smack_have_access returned 0 (access denied)");
242         cap = cap_get_pid(pid);
243         if (cap == NULL) {
244                 C_LOGE("cap_get_pid failed");
245                 return -1;
246         }
247         ret = cap_get_flag(cap, CAP_MAC_OVERRIDE, CAP_EFFECTIVE, &cap_v);
248         if (0 != ret) {
249                 C_LOGE("cap_get_flag failed");
250                 return -1;
251         }
252
253         if (cap_v == CAP_SET) {
254                 C_LOGD("pid %d has CAP_MAC_OVERRIDE", pid);
255                 return 1;
256
257         } else {
258                 C_LOGD("pid %d doesn't have CAP_MAC_OVERRIDE", pid);
259                 return 0;
260         }
261 }
262
263 static int set_dac(const char *smack_label, const char *pkg_name)
264 {
265         SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s, pkg_name=%s",
266                                 __func__, smack_label, pkg_name);
267
268         FILE* fp_group = NULL;  // /etc/group
269         uid_t t_uid = -1;               // uid of current process
270         gid_t *glist = NULL;    // group list
271         gid_t temp_gid = -1;    // for group list
272         char buf[10] = {0, };           // contents in group_list file
273         int glist_cnt = 0;              // for group list
274         int result;
275         int i;
276         new_user usr;
277         unsigned *additional_gids = NULL;
278
279         /*
280          * initialize user structure
281          */
282         C_LOGD("Initialize user structure");
283         memset(usr.user_name, 0x00, 10);
284         memset(usr.home_dir, 0x00, 64);
285         memset(usr.group_list, 0x00, 64);
286         usr.uid = -1;
287         usr.gid = -1;
288
289         t_uid = getuid();
290         C_LOGD("Current uid is %d", t_uid);
291
292         if(t_uid == 0)  // current user is 'root'
293         {
294                 if(!strncmp(pkg_name, "developer", 9))
295                 {
296                         strncpy(usr.user_name, DEV_USER_NAME, sizeof(usr.user_name));
297                         usr.uid = DEVELOPER_UID;
298                         usr.gid = DEVELOPER_GID;
299                         strncpy(usr.home_dir, DEV_HOME_DIR, sizeof(usr.home_dir));
300                         strncpy(usr.group_list, DEV_GROUP_PATH, sizeof(usr.group_list));
301                 }
302                 else
303                 {
304                         strncpy(usr.user_name, APP_USER_NAME, sizeof(usr.user_name));
305                         usr.uid = APP_UID;
306                         usr.gid = APP_GID;
307                         strncpy(usr.home_dir, APP_HOME_DIR, sizeof(usr.home_dir));
308                         strncpy(usr.group_list, APP_GROUP_PATH, sizeof(usr.group_list));
309                 }
310
311                 /*
312                  * get group information
313                  */
314                 C_LOGD("Get group information");
315                 SECURE_C_LOGD("Opening file %s.", usr.group_list);
316                 if(!(fp_group = fopen(usr.group_list, "r")))
317                 {
318                         C_LOGE("fopen failed.");
319                         result = PC_ERR_FILE_OPERATION; // return -1
320                         goto error;
321                 }
322
323                 while(fgets(buf, 10, fp_group) != NULL)
324                 {
325                         errno = 0;
326                         temp_gid = strtoul(buf, 0, 10);
327                         if(errno != 0)  // error occured during strtoul()
328                         {
329                                 C_LOGE("Cannot change string to integer: %s", buf);
330                                 result = PC_ERR_INVALID_OPERATION;
331                                 goto error;
332                         }
333
334                         glist = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + 1));
335                         if(!glist)
336                         {
337                                 result = PC_ERR_MEM_OPERATION;  // return -2
338                                 C_LOGE("Cannot allocate memory");
339                                 goto error;
340                         }
341                         glist[glist_cnt] = temp_gid;
342                         glist_cnt++;
343                 }
344                 fclose(fp_group);
345                 fp_group = NULL;
346
347                 if(NULL != smack_label)
348                 {
349                         gid_t *glist_new;
350                         int i, cnt;
351
352                         result = get_app_gids(smack_label, &additional_gids, &cnt);
353                         if (result != PC_OPERATION_SUCCESS)
354                                 goto error;
355
356                         if (cnt > 0) {
357                                 glist_new = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + cnt));
358                                 if (glist_new == NULL) {
359                                         result = PC_ERR_MEM_OPERATION;  // return -2
360                                         C_LOGE("Memory allocation failed");
361                                         goto error;
362                                 }
363                                 glist = glist_new;
364                                 for (i = 0; i < cnt; ++i) {
365                                         C_LOGD("Additional GID based on enabled permissions: %u", additional_gids[i]);
366                                         glist[glist_cnt++] = additional_gids[i];
367                                 }
368                         }
369                 }
370
371                 /*
372                  * setgroups()
373                  */
374                 C_LOGD("Adding process to the following groups:");
375                 for(i=0; i<glist_cnt; ++i) {
376                         SECURE_C_LOGD("glist [ %d ] = %d", i, glist[i]);
377                 }
378                 C_LOGD("Calling setgroups()");
379                 if(setgroups(glist_cnt, glist) != 0)
380                 {
381                         C_LOGE("setgroups failed");
382                         result = PC_ERR_NOT_PERMITTED;  // return -3
383                         goto error;
384                 }
385                 if(glist != NULL)
386                 {
387                         free(glist);
388                         glist = NULL;
389                 }
390
391                 /*
392                  * setuid() & setgid()
393                  */
394                 C_LOGD("setgid( %d ) & setuid( %d )", usr.gid, usr.uid);
395                 if(setgid(usr.gid) != 0)        // fail
396                 {
397                         C_LOGE("Failed to execute setgid().");
398                         result = PC_ERR_INVALID_OPERATION;
399                         goto error;
400                 }
401                 if(setuid(usr.uid) != 0)        // fail
402                 {
403                         C_LOGE("Failed to execute setuid().");
404                         result = PC_ERR_INVALID_OPERATION;
405                         goto error;
406                 }
407
408                 SECURE_C_LOGD("setenv(): USER = %s, HOME = %s", usr.user_name, usr.home_dir);
409                 if(setenv("USER", usr.user_name, 1) != 0)       //fail
410                 {
411                         C_LOGE("Failed to execute setenv() [USER].");
412                         result = PC_ERR_INVALID_OPERATION;
413                         goto error;
414                 }
415                 if(setenv("HOME", usr.home_dir, 1) != 0)        // fail
416                 {
417                         C_LOGE("Failed to execute setenv() [HOME].");
418                         result = PC_ERR_INVALID_OPERATION;
419                         goto error;
420                 }
421         }
422         else    // current user is not only 'root' but 'app'
423         {
424                 C_LOGE("Current user is NOT root");
425                 result = PC_ERR_NOT_PERMITTED;  // return -3
426                 goto error;
427         }
428
429         result = PC_OPERATION_SUCCESS;
430
431 error:
432         if(fp_group != NULL)
433                 fclose(fp_group);
434         if(glist != NULL)
435                 free(glist);
436         free(additional_gids);
437
438         return result;
439 }
440
441 /**
442  * Get SMACK label from EXEC label of a file.
443  * SMACK label should be freed by caller
444  *
445  * @param path file path to take label from
446  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
447  */
448 static int get_smack_from_binary(char **smack_label, const char* path, app_type_t type)
449 {
450         SECURE_C_LOGD("Entering function: %s. Params: path=%s, type=%d",
451                                 __func__, path, type);
452         int ret;
453
454         *smack_label = NULL;
455         if (type == PERM_APP_TYPE_WGT
456         || type == PERM_APP_TYPE_WGT_PARTNER
457         || type == PERM_APP_TYPE_WGT_PLATFORM) {
458                 ret = smack_lgetlabel(path, smack_label, SMACK_LABEL_EXEC);
459         } else {
460                 ret = smack_getlabel(path, smack_label, SMACK_LABEL_EXEC);
461         }
462         if (ret != 0) {
463                 C_LOGE("Getting exec label from file %s failed", path);
464                 return PC_ERR_INVALID_OPERATION;
465         }
466
467         return PC_OPERATION_SUCCESS;
468 }
469
470 /**
471  * Set process SMACK label.
472  * This function is emulating EXEC label behavior of SMACK for programs
473  * run by dlopen/dlsym instead of execv.
474  *
475  * @param smack label
476  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
477  */
478 static int set_smack_for_self (char *smack_label)
479 {
480         SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s",
481                                 __func__, smack_label);
482         int ret;
483
484         if (smack_label == NULL) {
485                 /* No label to set, just return with success */
486                 C_LOGD("No label to set, just return with success.");
487                 ret = PC_OPERATION_SUCCESS;
488         }
489         else {
490                 SECURE_C_LOGD("smack_label=%s", smack_label);
491                 if (have_smack()) {
492                         ret = smack_set_label_for_self(smack_label);
493                         C_LOGD("smack_set_label_for_self returned %d", ret);
494                 } else
495                         ret = PC_OPERATION_SUCCESS;
496         }
497
498         return ret;
499 }
500
501 static int is_widget(const char* path)
502 {
503         SECURE_C_LOGD("Entering function: %s. Params: path=%s",
504                                 __func__, path);
505         char buf[sizeof(WRT_CLIENT_PATH)];
506         int ret;
507
508         ret = readlink(path, buf, sizeof(WRT_CLIENT_PATH));
509         if (ret == -1)
510                 C_LOGD("readlink(%s) returned error: %s. Assuming that app is not a widget", path, strerror(errno));
511         else if (ret == sizeof(WRT_CLIENT_PATH))
512                 C_LOGD("%s is not a widget", path);
513         if (ret == -1 || ret == sizeof(WRT_CLIENT_PATH))
514                 return 0;
515         buf[ret] = '\0';
516         C_LOGD("buf=%s", buf);
517
518         ret = !strcmp(WRT_CLIENT_PATH, buf);
519         C_LOGD("%s is %s widget", path, ret ? "a" : "not a");
520         return (ret);
521 }
522
523 /**
524  * Partially verify, that the type given for app is correct.
525  * This function will use some heuristics to check whether the app type is right.
526  * It is intended for security hardening to catch privilege setting for the
527  * app type not corresponding to the actual binary.
528  * Beware - when it detects an anomaly, the whole process will be terminated.
529  *
530  * @param type claimed application type
531  * @param path file path to executable
532  * @return return void on success, terminate the process on error
533  */
534 static app_type_t verify_app_type(const char* type, const char* path)
535 {
536         SECURE_C_LOGD("Entering function: %s. Params: type=%s, path=%s",
537                                 __func__, type, path);
538
539         /* TODO: this should actually be treated as error, but until the old
540          * set_privilege API is removed, it must be ignored */
541         if (path == NULL) {
542                 C_LOGD("PKG_TYPE_OTHER");
543                 return APP_TYPE_OTHER; /* good */
544         }
545
546         if (is_widget(path)) {
547                 if (!strcmp(type, "wgt")) {
548                         C_LOGD("PKG_TYPE_WGT");
549                         return PERM_APP_TYPE_WGT; /* good */
550                 } else if (!strcmp(type, "wgt_partner")) {
551                         C_LOGD("PKG_TYPE_WGT_PARTNER");
552                         return PERM_APP_TYPE_WGT_PARTNER; /* good */
553                 } else if (!strcmp(type, "wgt_platform")) {
554                         C_LOGD("PKG_TYPE_WGT_PLATFORM");
555                         return PERM_APP_TYPE_WGT_PLATFORM; /* good */
556                 }
557
558         } else {
559                 if (type == NULL || (strcmp(type, "wgt")
560                                 && strcmp(type, "wgt_partner")
561                                 && strcmp(type, "wgt_platform"))){
562                         C_LOGD("PKG_TYPE_OTHER");
563                         return PERM_APP_TYPE_OTHER; /* good */
564                 }
565         }
566
567         /* bad */
568         C_LOGE("EXIT_FAILURE");
569         exit(EXIT_FAILURE);
570 }
571
572 API int set_app_privilege(const char* name, const char* type, const char* path)//deprecated
573 {
574         SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
575                                 __func__, name, type, path);
576
577         return perm_app_set_privilege(name, type, path);
578 }
579
580 API int perm_app_set_privilege(const char* name, const char* type, const char* path)
581 {
582         SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
583                                 __func__, name, type, path);
584
585         //SECURE_C_LOGD("Function params: name = %s, type = %s, path = %s", name, type, path);
586         int ret = PC_OPERATION_SUCCESS;
587         char *smack_label AUTO_FREE;
588
589         if (name == NULL) {
590                 C_LOGE("Error invalid parameter");
591                 return PC_ERR_INVALID_PARAM;
592         }
593
594         if (path != NULL && have_smack()) {
595                 ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
596                 if (ret != PC_OPERATION_SUCCESS)
597                         return ret;
598
599                 ret = set_smack_for_self(smack_label);
600                 if (ret != PC_OPERATION_SUCCESS)
601                         return ret;
602         }
603
604         if (path != NULL && !have_smack()) {
605                 ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
606                 if (ret != PC_OPERATION_SUCCESS)
607                         return ret;
608         }
609
610         return set_dac(smack_label, name);
611 }
612
613 API int set_privilege(const char* pkg_name)//deprecated
614 {
615         SECURE_C_LOGD("Entering function: %s. Params: pkg_name=%s",
616                                 __func__, pkg_name);
617
618         return perm_app_set_privilege(pkg_name, NULL, NULL);
619 }
620
621 static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix, bool is_early)
622 {
623         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, perm=%s, suffix=%s, is_early=%d",
624                                 __func__, app_type, perm, suffix, is_early);
625
626         const char* app_type_prefix = NULL;
627         char* perm_basename = NULL;
628         int ret = 0;
629
630         if (perm == NULL || strlen(perm) == 0) {
631                 C_LOGE("Empty permission name.");
632                 return PC_ERR_INVALID_PARAM;
633         }
634
635         app_type_prefix = app_type_group_name(app_type);
636
637         ret = base_name_from_perm(perm, &perm_basename);
638         if (ret != PC_OPERATION_SUCCESS) {
639                 C_LOGE("Couldn't get permission basename.");
640                 return ret;
641         }
642
643         if (is_early) {
644                 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s%s",
645                 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
646                 perm_basename, "_early", suffix);
647         }
648         else {
649                 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
650                 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
651                 perm_basename, suffix);
652         }
653         if (ret == -1) {
654                 C_LOGE("asprintf failed.");
655                 return PC_ERR_MEM_OPERATION;
656         }
657
658         C_LOGD("Path=%s", *path);
659
660         return PC_OPERATION_SUCCESS;
661 }
662
663 static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
664 {
665         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
666                                 __func__, app_label, app_type, perm);
667
668         int ret;
669         char* path AUTO_FREE;
670         FILE* file AUTO_FCLOSE;
671         int gid;
672
673         ret = perm_file_path(&path, app_type, perm, ".dac", 0);
674         if (ret != PC_OPERATION_SUCCESS) {
675                 C_LOGD("No dac config file for permission %s", perm);
676                 return ret;
677         }
678
679         SECURE_C_LOGD("Opening file %s.", path);
680         file = fopen(path, "r");
681         if (file == NULL) {
682                 C_LOGW("fopen failed.");
683                 return PC_OPERATION_SUCCESS;
684         }
685
686         while (fscanf(file, "%d\n", &gid) == 1) {
687                 SECURE_C_LOGD("Adding app_id %s to group %d", app_label, gid);
688                 ret = add_app_gid(app_label, gid);
689                 if (ret != PC_OPERATION_SUCCESS) {
690                         C_LOGE("add_app_gid failed");
691                         return ret;
692                 }
693         }
694
695         return PC_OPERATION_SUCCESS;
696 }
697
698 static int label_all(const FTSENT* ftsent UNUSED)
699 {
700         SECURE_C_LOGD("Entering function: %s.", __func__);
701
702         return DECISION_LABEL;
703 }
704
705 static int label_execs(const FTSENT* ftsent)
706 {
707         SECURE_C_LOGD("Entering function: %s.", __func__);
708
709         C_LOGD("Mode = %d", ftsent->fts_statp->st_mode);
710         // label only regular executable files
711         if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
712                 return DECISION_LABEL;
713         return DECISION_SKIP;
714 }
715
716 static int label_dirs(const FTSENT* ftsent)
717 {
718         SECURE_C_LOGD("Entering function: %s.", __func__);
719
720         // label only directories
721         if (S_ISDIR(ftsent->fts_statp->st_mode))
722                 return DECISION_LABEL;
723         return DECISION_SKIP;
724 }
725
726 static int label_links_to_execs(const FTSENT* ftsent)
727 {
728         SECURE_C_LOGD("Entering function: %s.", __func__);
729
730         struct stat buf;
731         char* target AUTO_FREE;
732
733         // check if it's a link
734         if ( !S_ISLNK(ftsent->fts_statp->st_mode))
735                 return DECISION_SKIP;
736
737         target = realpath(ftsent->fts_path, NULL);
738         if (!target) {
739                 SECURE_C_LOGE("Getting link target for %s failed (Error = %s)", ftsent->fts_path, strerror(errno));
740                 return PC_ERR_FILE_OPERATION;
741         }
742         if (-1 == stat(target, &buf)) {
743                 SECURE_C_LOGE("stat failed for %s (Error = %s", target, strerror(errno));
744                 return PC_ERR_FILE_OPERATION;
745         }
746         // skip if link target is not a regular executable file
747         if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
748                 SECURE_C_LOGD("%s is not a regular executable file. Skipping.", target);
749                 return DECISION_SKIP;
750         }
751
752         return DECISION_LABEL;
753 }
754
755 static int dir_set_smack_r(const char *path, const char* label,
756                 enum smack_label_type type, label_decision_fn fn)
757 {
758         SECURE_C_LOGD("Entering function: %s. Params: path=%s, label=%s, type=%d",
759                                 __func__, path, label, type);
760
761         const char* path_argv[] = {path, NULL};
762         FTS *fts AUTO_FTS_CLOSE;
763         FTSENT *ftsent;
764         int ret;
765
766         fts = fts_open((char * const *) path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
767         if (fts == NULL) {
768                 C_LOGE("fts_open failed.");
769                 return PC_ERR_FILE_OPERATION;
770         }
771
772         while ((ftsent = fts_read(fts)) != NULL) {
773                 /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
774                 if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
775                         C_LOGE("FTS_ERR error or failed stat(2) (FTS_NS)");
776                         return PC_ERR_FILE_OPERATION;
777                 }
778
779                 ret = fn(ftsent);
780                 if (ret < 0) {
781                         C_LOGE("fn(ftsent) failed.");
782                         return ret;
783                 }
784
785                 if (ret == DECISION_LABEL) {
786                         C_LOGD("smack_lsetlabel (label: %s (type: %d), path: %s)", label, type, ftsent->fts_path);
787                         if (smack_lsetlabel(ftsent->fts_path, label, type) != 0) {
788                                 C_LOGE("smack_lsetlabel failed.");
789                                 return PC_ERR_FILE_OPERATION;
790                         }
791                 }
792         }
793
794         /* If last call to fts_read() set errno, we need to return error. */
795         if (errno != 0) {
796                 C_LOGE("Last errno from fts_read: %s", strerror(errno));
797                 return PC_ERR_FILE_OPERATION;
798         }
799         return PC_OPERATION_SUCCESS;
800 }
801 API char* app_id_from_socket(int sockfd)//deprecated
802 {
803         SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
804                                 __func__, sockfd);
805
806     return perm_app_id_from_socket(sockfd);
807 }
808
809 API char* perm_app_id_from_socket(int sockfd)
810 {
811         SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
812                                 __func__, sockfd);
813
814         if (!have_smack()) {
815                 C_LOGD("No SMACK. Returning NULL.");
816                 return NULL;
817         }
818
819         char* app_id;
820         int ret;
821
822         ret = smack_new_label_from_socket(sockfd, &app_id);
823         if (ret < 0) {
824                 C_LOGE("smack_new_label_from_socket failed");
825                 return NULL;
826         }
827
828         SECURE_C_LOGD("app_id = %s", app_id);
829
830         return app_id;
831 }
832
833
834 static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
835 {
836         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
837                                 __func__, app_id, app_type, permanent);
838
839         int i, ret;
840         char* smack_path AUTO_FREE;
841         char* smack_path_early AUTO_FREE;
842         int fd AUTO_CLOSE;
843         int fd_early AUTO_CLOSE;
844         struct smack_accesses *smack AUTO_SMACK_FREE;
845         struct smack_accesses *smack_early AUTO_SMACK_FREE;
846
847         if (!smack_label_is_valid(app_id)) {
848                 C_LOGE("Invalid param app_id.");
849                 return PC_ERR_INVALID_PARAM;
850         }
851
852         if(perm_list == NULL) {
853                 C_LOGE("Invalid perm_list (NULL).");
854                 return PC_ERR_INVALID_PARAM;
855         }
856
857         if (app_type_group_name(app_type) == NULL) {
858                 C_LOGE("Unknown app type.");
859                 return PC_ERR_INVALID_PARAM;
860         }
861
862         // Add permission to DAC
863         for (i = 0; perm_list[i] != NULL; ++i) {
864                 ret = perm_to_dac(app_id, app_type, perm_list[i]);
865                 if (ret != PC_OPERATION_SUCCESS){
866                         C_LOGE("perm_to_dac failed");
867                         return ret;
868                 }
869         }
870
871         // Enable the permissions:
872         ret = rdb_enable_app_permissions(app_id,
873                                          app_type,
874                                          perm_list,
875                                          !((bool)permanent));
876         if (ret != PC_OPERATION_SUCCESS) {
877                 C_LOGE("RDB rdb_enable_app_permissions failed with: %d", ret);
878                 return ret;
879         }
880
881
882         SECURE_C_LOGD("Leaving function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
883                                 __func__, app_id, app_type, permanent);
884
885         return PC_OPERATION_SUCCESS;
886 }
887
888 API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
889 {
890         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
891                                 __func__, app_id);
892
893         return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
894 }
895
896 API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
897 {
898         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
899                                 __func__, app_id);
900
901         return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
902 }
903
904 API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
905 {
906         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
907                                 __func__, pkg_id, app_type, persistent);
908
909         return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
910 }
911
912 API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)
913 {
914         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
915                                 __func__, pkg_id, app_type, persistent);
916
917         return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
918 }
919
920 API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
921 {
922         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
923                                 __func__, pkg_id, app_type);
924
925         return perm_app_disable_permissions(pkg_id, app_type, perm_list);
926 }
927
928 /* FIXME: this function is only a stub */
929 API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
930 {
931         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
932                                 __func__, pkg_id, app_type);
933
934         int ret;
935         if (!smack_label_is_valid(pkg_id)) {
936                 C_LOGE("Invalid param app_id.");
937                 return PC_ERR_INVALID_PARAM;
938         }
939
940         if (perm_list == NULL) {
941                 C_LOGE("Invalid perm_list (NULL).");
942                 return PC_ERR_INVALID_PARAM;
943         }
944
945         if (app_type_group_name(app_type) == NULL) {
946                 C_LOGE("Unknown app type.");
947                 return PC_ERR_INVALID_PARAM;
948         }
949
950         ret = rdb_disable_app_permissions(pkg_id, app_type, perm_list);
951         if (ret != PC_OPERATION_SUCCESS) {
952                 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
953                 return ret;
954         }
955
956         return PC_OPERATION_SUCCESS;
957 }
958
959 API int app_revoke_permissions(const char* pkg_id)//deprecated
960 {
961         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
962         return perm_app_revoke_permissions(pkg_id);
963 }
964
965 API int perm_app_revoke_permissions(const char* pkg_id)
966 {
967         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
968         int ret;
969
970         if (!smack_label_is_valid(pkg_id)) {
971                 C_LOGE("Invalid param app_id.");
972                 return PC_ERR_INVALID_PARAM;
973         }
974
975         ret = rdb_revoke_app_permissions(pkg_id);
976         if (ret != PC_OPERATION_SUCCESS) {
977                 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
978                 return ret;
979         }
980
981         return PC_OPERATION_SUCCESS;
982 }
983
984 API int app_reset_permissions(const char* pkg_id)//deprecated
985 {
986         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
987                                 __func__, pkg_id);
988
989         return perm_app_reset_permissions(pkg_id);
990 }
991
992 API int perm_app_reset_permissions(const char* pkg_id)
993 {
994         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
995                                 __func__, pkg_id);
996         int ret;
997
998         if (!smack_label_is_valid(pkg_id)) {
999                 C_LOGE("Invalid param pkg_id.");
1000                 return PC_ERR_INVALID_PARAM;
1001         }
1002
1003         ret = rdb_reset_app_permissions(pkg_id);
1004         if (ret != PC_OPERATION_SUCCESS) {
1005                 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
1006                 return ret;
1007         }
1008
1009         return PC_OPERATION_SUCCESS;
1010 }
1011
1012 API int app_label_dir(const char* label, const char* path)//deprecated
1013 {
1014         SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
1015                                 __func__, label, path);
1016
1017         int ret = PC_OPERATION_SUCCESS;
1018
1019         if(path == NULL) {
1020                 C_LOGE("Invalid argument path (NULL).");
1021                 return PC_ERR_INVALID_PARAM;
1022         }
1023
1024         if (!smack_label_is_valid(label)) {
1025                 C_LOGE("Invalid param label.");
1026                 return PC_ERR_INVALID_PARAM;
1027         }
1028
1029         //setting access label on everything in given directory and below
1030         ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
1031         if (PC_OPERATION_SUCCESS != ret)
1032         {
1033                 C_LOGE("dir_set_smack_r failed.");
1034                 return ret;
1035         }
1036
1037         //setting execute label for everything with permission to execute
1038         ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
1039         if (PC_OPERATION_SUCCESS != ret)
1040         {
1041                 C_LOGE("dir_set_smack_r failed.");
1042                 return ret;
1043         }
1044
1045         //setting execute label for everything with permission to execute
1046         ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
1047         return ret;
1048 }
1049
1050
1051 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
1052 {
1053         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
1054                                 __func__, app_label, shared_label, path);
1055         int ret;
1056
1057         if(path == NULL) {
1058                 C_LOGE("Invalid param path.");
1059                 return PC_ERR_INVALID_PARAM;
1060         }
1061
1062         if(!smack_label_is_valid(app_label)) {
1063                 C_LOGE("Invalid param app_label");
1064                 return PC_ERR_INVALID_PARAM;
1065         }
1066
1067         if(!smack_label_is_valid(shared_label)) {
1068                 C_LOGE("Invalid param shared_label");
1069                 return PC_ERR_INVALID_PARAM;
1070         }
1071
1072         if (strcmp(app_label, shared_label) == 0) {
1073                 C_LOGE("app_label equals shared_label");
1074                 return PC_ERR_INVALID_PARAM;
1075         }
1076
1077         //setting label on everything in given directory and below
1078         ret = dir_set_smack_r(path, shared_label, SMACK_LABEL_ACCESS, label_all);
1079         if(ret != PC_OPERATION_SUCCESS){
1080                 C_LOGE("dir_set_smack_r failed.");
1081                 return ret;
1082         }
1083
1084         //setting transmute on dir
1085         ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, label_dirs);
1086         if (ret != PC_OPERATION_SUCCESS) {
1087                 C_LOGE("dir_set_smack_r failed");
1088                 return ret;
1089         }
1090
1091         return PC_OPERATION_SUCCESS;
1092 }
1093
1094 API int add_shared_dir_readers(const char* shared_label UNUSED, const char** app_list UNUSED)//deprecated
1095 {
1096         SECURE_C_LOGD("Entering function: %s. Params: shared_label=%s",
1097                                 __func__, shared_label);
1098
1099         C_LOGE("add_shared_dir_readers is deprecated and unimplemented!");
1100
1101         // TODO: This function is not implemented with RDB.
1102         return PC_ERR_INVALID_OPERATION;
1103 }
1104
1105 static char* smack_label_for_path(const char *app_id, const char *path)
1106 {
1107         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, path=%s",
1108                                 __func__, app_id, path);
1109
1110         char *salt AUTO_FREE;
1111         char *label;
1112         char *x;
1113
1114         /* Prefix $1$ causes crypt() to use MD5 function */
1115         if (-1 == asprintf(&salt, "$1$%s", app_id)) {
1116                 C_LOGE("asprintf failed");
1117                 return NULL;
1118         }
1119
1120         label = crypt(path, salt);
1121         if (label == NULL) {
1122                 C_LOGE("crypt failed");
1123                 return NULL;
1124         }
1125
1126         /* crypt() output may contain slash character,
1127          * which is not legal in Smack labels */
1128         for (x = label; *x; ++x) {
1129                 if (*x == '/')
1130                         *x = '%';
1131         }
1132
1133         return label;
1134 }
1135
1136 /* FIXME: remove this pragma once deprecated API is deleted */
1137 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1138 static int perm_app_setup_path_internal(const char* pkg_id, const char* path, app_path_type_t app_path_type, va_list ap)
1139 {
1140         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1141                                 __func__, pkg_id, path, app_path_type);
1142
1143         if(path == NULL) {
1144                 C_LOGE("Invalid argument path.");
1145                 return PC_ERR_INVALID_PARAM;
1146         }
1147
1148         if (!smack_label_is_valid(pkg_id)) {
1149                 C_LOGE("Invalid pkg_id.");
1150                 SECURE_C_LOGE("Invalid pkg_id %s", pkg_id);
1151                 return PC_ERR_INVALID_PARAM;
1152         }
1153
1154         switch (app_path_type) {
1155         case APP_PATH_PRIVATE:
1156                 C_LOGD("app_path_type is APP_PATH_PRIVATE.");
1157                 return app_label_dir(pkg_id, path);
1158
1159         case APP_PATH_GROUP: {
1160                 C_LOGD("app_path_type is APP_PATH_GROUP.");
1161                 int ret;
1162                 const char *shared_label;
1163
1164                 shared_label = va_arg(ap, const char *);
1165
1166                 if (!smack_label_is_valid(shared_label)) {
1167                         C_LOGE("Invalid shared_label.");
1168                         return PC_ERR_INVALID_PARAM;
1169                 }
1170
1171                 if (strcmp(pkg_id, shared_label) == 0) {
1172                         C_LOGE("pkg_id equals shared_label.");
1173                         return PC_ERR_INVALID_PARAM;
1174                 }
1175
1176                 ret = app_label_shared_dir(pkg_id, shared_label, path);
1177                 if (ret != PC_OPERATION_SUCCESS) {
1178                         C_LOGE("app_label_shared_dir failed: %d", ret);
1179                         return ret;
1180                 }
1181
1182                 // Add the path to the database:
1183                 ret = rdb_add_path(pkg_id, shared_label, path, "rwxatl", "GROUP_PATH");
1184                 if (ret != PC_OPERATION_SUCCESS) {
1185                         C_LOGE("RDB rdb_add_path failed with: %d", ret);
1186                         return ret;
1187                 }
1188
1189                 return PC_OPERATION_SUCCESS;
1190         }
1191
1192         case APP_PATH_PUBLIC: {
1193                 C_LOGD("app_path_type is APP_PATH_PUBLIC.");
1194                 char **app_ids AUTO_FREE;
1195                 const char *label;
1196                 int ret;
1197
1198                 C_LOGD("New public RO path %s", path);
1199
1200                 // Generate label:
1201                 label = smack_label_for_path(pkg_id, path);
1202                 if (label == NULL) {
1203                         C_LOGE("smack_label_for_path failed.");
1204                         return PC_ERR_INVALID_OPERATION;
1205                 }
1206                 C_LOGD("Generated label '%s' for public RO path %s", label, path);
1207
1208                 ret = app_label_shared_dir(pkg_id, label, path);
1209                 if (ret != PC_OPERATION_SUCCESS) {
1210                         C_LOGE("app_label_shared_dir failed.");
1211                         return ret;
1212                 }
1213
1214                 // Add the path to the database:
1215                 ret = rdb_add_path(pkg_id, label, path, "rwxatl", "PUBLIC_PATH");
1216                 if (ret != PC_OPERATION_SUCCESS) {
1217                         C_LOGE("RDB rdb_add_path failed with: %d", ret);
1218                         return ret;
1219                 }
1220
1221                 return PC_OPERATION_SUCCESS;
1222         }
1223
1224         case APP_PATH_SETTINGS: {
1225                 C_LOGD("app_path_type is APP_PATH_SETTINGS.");
1226                 char **app_ids AUTO_FREE;
1227                 const char *label;
1228                 int ret;
1229
1230                 // Generate label:
1231                 label = smack_label_for_path(pkg_id, path);
1232                 if (label == NULL) {
1233                         C_LOGE("smack_label_for_path failed.");
1234                         return PC_ERR_INVALID_OPERATION;
1235                 }
1236                 C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
1237
1238                 /*set id for path and all subfolders*/
1239                 ret = app_label_shared_dir(pkg_id, label, path);
1240                 if (ret != PC_OPERATION_SUCCESS) {
1241                         C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
1242                         return ret;
1243                 }
1244
1245                 // Add the path to the database:
1246                 ret = rdb_add_path(pkg_id, label, path, "rwxatl", "SETTINGS_PATH");
1247                 if (ret != PC_OPERATION_SUCCESS) {
1248                         C_LOGE("RDB rdb_add_path failed with: %d", ret);
1249                         return ret;
1250                 }
1251
1252                 return PC_OPERATION_SUCCESS;
1253         }
1254
1255         case APP_PATH_ANY_LABEL: {
1256                 C_LOGD("app_path_type is APP_PATH_ANY_LABEL.");
1257                 const char *label = NULL;
1258                 label = va_arg(ap, const char *);
1259                 return app_label_dir(label, path);
1260         }
1261
1262         default:
1263                 C_LOGE("app_path_type is invalid.");
1264                 return PC_ERR_INVALID_PARAM;
1265         }
1266
1267         return PC_OPERATION_SUCCESS;
1268 }
1269 /* FIXME: remove this pragma once deprecated API is deleted */
1270 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
1271
1272 API int app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)//deprecated
1273 {
1274         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1275                                 __func__, pkg_id, path, app_path_type);
1276
1277         va_list ap;
1278         int ret;
1279         va_start( ap, app_path_type );
1280         ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
1281         va_end( ap );
1282         return ret;
1283 }
1284
1285
1286 API int perm_app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)
1287 {
1288         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1289                                 __func__, pkg_id, path, app_path_type);
1290
1291         va_list ap;
1292         int ret;
1293         va_start( ap, app_path_type );
1294         ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
1295         va_end( ap );
1296         return ret;
1297 }
1298
1299 API int app_add_friend(const char* pkg_id1, const char* pkg_id2)//deprecated
1300 {
1301         SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
1302                                 __func__, pkg_id1, pkg_id2);
1303
1304         return perm_app_add_friend(pkg_id1, pkg_id2);
1305 }
1306
1307 API int perm_app_add_friend(const char* pkg_id1 UNUSED, const char* pkg_id2 UNUSED)
1308 {
1309         SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
1310                                 __func__, pkg_id1, pkg_id2);
1311
1312         C_LOGE("app_register_av is deprecated and unimplemented!");
1313
1314         // TODO: This function is not implemented with RDB.
1315         return PC_ERR_INVALID_OPERATION;
1316 }
1317
1318 API int app_install(const char* pkg_id)//deprecated
1319 {
1320         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1321                                 __func__, pkg_id);
1322
1323         return perm_app_install(pkg_id);
1324 }
1325
1326 API int perm_app_install(const char* pkg_id)
1327 {
1328         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1329                                 __func__, pkg_id);
1330         int ret;
1331         int fd AUTO_CLOSE;
1332         char* smack_path AUTO_FREE;
1333         struct smack_accesses *smack AUTO_SMACK_FREE;
1334
1335         ret = perm_begin();
1336         if(ret != PC_OPERATION_SUCCESS) {
1337                 C_LOGE("RDB perm_begin failed with: %d", ret);
1338                 return ret;
1339         }
1340
1341         if (!smack_label_is_valid(pkg_id)) {
1342                 C_LOGE("Invalid param pkg_id.");
1343                 return PC_ERR_INVALID_PARAM;
1344         }
1345
1346         // Add application to the database:
1347         ret = rdb_add_application(pkg_id);
1348         if (ret != PC_OPERATION_SUCCESS) {
1349                 C_LOGE("RDB rdb_add_application failed with: %d", ret);
1350                 return ret;
1351         }
1352
1353         return PC_OPERATION_SUCCESS;
1354 }
1355
1356 API int app_uninstall(const char* pkg_id)//deprecated
1357 {
1358         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1359                                 __func__, pkg_id);
1360
1361         return perm_app_uninstall(pkg_id);
1362 }
1363
1364 API int perm_app_uninstall(const char* pkg_id)
1365 {
1366         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
1367         char* smack_path AUTO_FREE;
1368         int ret;
1369
1370         if (!smack_label_is_valid(pkg_id)) {
1371                 C_LOGE("Invalid param pkg_id.");
1372                 return PC_ERR_INVALID_PARAM;
1373         }
1374
1375         // Remove application from the database
1376         ret = rdb_remove_application(pkg_id);
1377         if (ret != PC_OPERATION_SUCCESS) {
1378                 C_LOGE("RDB rdb_remove_application failed with: %d", ret);
1379                 return ret;
1380         }
1381
1382         return PC_OPERATION_SUCCESS;
1383 }
1384
1385 static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
1386
1387         SECURE_C_LOGD("Entering function: %s.", __func__);
1388         int ret = PC_OPERATION_SUCCESS;
1389         int written = 0;
1390         size_t i = 0;
1391
1392         if (file == NULL) {
1393                 C_LOGE("Unable to create file. Error: %s", strerror(errno));
1394                 return PC_ERR_FILE_OPERATION;   // TODO remove smack accesses?
1395         }
1396
1397         if(-1 == fchmod(fileno(file), 0644)) {
1398                 C_LOGE("Unable to chmod file. Error: %s", strerror(errno));
1399                 return PC_ERR_FILE_OPERATION;
1400         }
1401
1402         for (i = 0; i < list_size ; ++i) {
1403                 written = fprintf(file, "%u\n", list_of_db_gids[i]);
1404                 if (written <= 0) {
1405                         C_LOGE("fprintf failed for file. Error: %s", strerror(errno));
1406                         ret = PC_ERR_FILE_OPERATION;
1407                         break;
1408                 }
1409         }
1410         return ret;
1411 }
1412
1413 API int add_api_feature(app_type_t app_type,
1414                         const char* api_feature_name,
1415                         const char** smack_rules,
1416                         const gid_t* list_of_db_gids,
1417                         size_t list_size)//deprecated
1418 {
1419         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
1420                                 __func__, app_type, api_feature_name);
1421
1422     return perm_add_api_feature(app_type, api_feature_name, smack_rules, list_of_db_gids, list_size);
1423 }
1424
1425 API int perm_add_api_feature(app_type_t app_type,
1426                                                 const char* api_feature_name,
1427                                                 const char** smack_rules,
1428                                                 const gid_t* list_of_db_gids,
1429                                                 size_t list_size) {
1430         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
1431                                 __func__, app_type, api_feature_name);
1432
1433         int ret = PC_OPERATION_SUCCESS;
1434         char* smack_file AUTO_FREE;
1435         char* dac_file AUTO_FREE;
1436         char * base_api_feature_name AUTO_FREE;
1437         FILE* file = NULL;
1438         // struct smack_accesses* accesses = NULL;
1439         const char *s_type_name = app_type_name(app_type);
1440
1441         // Check input values
1442         if (s_type_name == NULL || !strcmp(s_type_name, "")) {
1443                 C_LOGE("Unknown api type");
1444                 return PC_ERR_INVALID_PARAM;
1445         }
1446
1447         if (api_feature_name == NULL || strlen(api_feature_name) == 0) {
1448                 C_LOGE("Api feature name is empty.");
1449                 return PC_ERR_INVALID_PARAM;
1450         }
1451
1452         if (smack_rules && ((ret = validate_all_rules(smack_rules) ) != PC_OPERATION_SUCCESS) ) {
1453                 C_LOGE("Error in rules list.");
1454                 return ret;
1455         }
1456
1457         // check .dac existence only if gids are supported
1458         if (list_of_db_gids && list_size > 0) {
1459                 // get feature DAC file name
1460                 ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac", 0);
1461                 if (ret != PC_OPERATION_SUCCESS || !dac_file ) {
1462                         C_LOGE("perm_file_path failed.");
1463                         return ret;
1464                 }
1465
1466                 unlink(dac_file);
1467         }
1468
1469         // go through gid list
1470         if (ret == PC_OPERATION_SUCCESS && list_of_db_gids && list_size > 0) {
1471                 // save to file
1472                 SECURE_C_LOGD("Opening file %s.", dac_file);
1473                 file = fopen(dac_file, "w+");
1474                 ret = save_gids(file, list_of_db_gids, list_size);
1475                 if(file) fclose(file);
1476         }
1477
1478         // remove file in case of failure
1479         if (ret != PC_OPERATION_SUCCESS && dac_file) {
1480                 unlink(dac_file);
1481         }
1482
1483         ret = base_name_from_perm(api_feature_name, &base_api_feature_name);
1484         if (ret != PC_OPERATION_SUCCESS){
1485                 C_LOGE("Error during creating base name: ", ret);
1486                 return ret;
1487         }
1488
1489         // Save api feature to the database.
1490         ret = rdb_add_permission_rules(base_api_feature_name, s_type_name, smack_rules);
1491         if (ret != PC_OPERATION_SUCCESS) {
1492                 C_LOGE("RDB rdb_add_permission_rules failed with: %d", ret);
1493                 return ret;
1494         }
1495
1496         return ret;
1497 }
1498
1499 /**
1500  * This function is marked as deprecated and will be removed
1501  */
1502 API int app_register_av(const char* app_av_id UNUSED)//deprecated
1503 {
1504         SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s",
1505                                 __func__, app_av_id);
1506
1507         C_LOGE("app_register_av is deprecated and unimplemented!");
1508
1509         // TODO: This function is not implemented with RDB.
1510         return PC_ERR_INVALID_OPERATION;
1511 }
1512
1513 API int perm_add_additional_rules(const char** smack_rules){
1514         SECURE_C_LOGD("Entering function: %s.", __func__);
1515         int ret;
1516         if (!smack_rules){
1517                 C_LOGE("smack_rules is NULL");
1518                 return PC_ERR_INVALID_PARAM;
1519         }
1520
1521         ret = rdb_add_additional_rules(smack_rules);
1522         if (ret != PC_OPERATION_SUCCESS) {
1523                 C_LOGE("RDB rdb_add_additional_rules failed with: %d", ret);
1524                 return ret;
1525         }
1526
1527         return PC_OPERATION_SUCCESS;
1528 }