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