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