Add better debug logs to 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 #include <iri.h>
45
46 #include "privilege-control.h"
47 #include "access-db.h"
48 #include "common.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_APP_LABEL_TEMPLATE        "~APP~"
65 #define SMACK_SHARED_DIR_LABEL_TEMPLATE "~APP_SHARED_DIR~"
66
67 #define SMACK_SRC_FILE_SUFFIX   "_src_file"
68 #define SMACK_SRC_DIR_SUFFIX    "_src_dir"
69 #define SMACK_DATA_SUFFIX       "_data"
70 #define WRT_BASE_DEVCAP         "WRT"
71 #define WRT_CLIENT_PATH         "/usr/bin/wrt-client"
72 #define ACC_LEN                 6
73 #define TIZEN_PRIVILEGE_ANTIVIRUS  "http://tizen.org/privilege/antivirus"
74 #define TIZEN_PRIVILEGE_APPSETTING "http://tizen.org/privilege/appsetting"
75 #define PATH_RULES_PUBLIC_RO       "PATH_RULES_PUBLIC_RO.smack"
76 #define PATH_RULES_GROUP_RW        "PATH_RULES_GROUP_RW.smack"
77
78 typedef struct {
79         char user_name[10];
80         int uid;
81         int gid;
82         char home_dir[64];
83         char group_list[64];
84 } new_user;
85
86 /**
87  * Return values
88  * <0 - error
89  * 0 - skip
90  * 1 - label
91  */
92 typedef int (*label_decision_fn)(const FTSENT*);
93 enum {
94         DECISION_SKIP = 0,
95         DECISION_LABEL = 1
96 };
97
98 API int control_privilege(void)//deprecated
99 {
100         SECURE_C_LOGD("Entering function: %s.", __func__);
101
102         if(getuid() == APP_UID) // current user is 'app'
103                 return PC_OPERATION_SUCCESS;
104
105         if(perm_app_set_privilege("org.tizen.", NULL, NULL) == PC_OPERATION_SUCCESS)
106                 return PC_OPERATION_SUCCESS;
107         else {
108                 C_LOGE("perm_app_set_privilege failed (not permitted).");
109                 return PC_ERR_NOT_PERMITTED;
110         }
111 }
112
113 /**
114  * TODO: this function should be moved to libsmack in open-source.
115  */
116 API int get_smack_label_from_process(pid_t pid, char smack_label[SMACK_LABEL_LEN + 1])
117 {
118         SECURE_C_LOGD("Entering function: %s. Params: pid=%i", __func__, pid);
119
120         int ret;
121         int fd AUTO_CLOSE;
122         int PATH_MAX_LEN = 64;
123         char path[PATH_MAX_LEN + 1];
124
125         if (pid < 0) {
126                 C_LOGE("invalid param pid.");
127                 ret = PC_ERR_INVALID_PARAM;
128                 goto out;
129         }
130
131         if(smack_label == NULL) {
132                 C_LOGE("Invalid param smack_label (NULL).");
133                 ret = PC_ERR_INVALID_PARAM;
134                 goto out;
135         }
136
137         bzero(smack_label, SMACK_LABEL_LEN + 1);
138         if (!have_smack()) { // If no smack just return success with empty label
139                 C_LOGD("No SMACK. Returning empty label");
140                 ret = PC_OPERATION_SUCCESS;
141                 goto out;
142         }
143
144         bzero(path, PATH_MAX_LEN + 1);
145         snprintf(path, PATH_MAX_LEN, "/proc/%d/attr/current", pid);
146         fd = open(path, O_RDONLY);
147         if (fd < 0) {
148                 SECURE_C_LOGE("Cannot open file %s (errno: %s)", path, strerror(errno));
149                 ret = PC_ERR_FILE_OPERATION;
150                 goto out;
151         }
152
153         ret = read(fd, smack_label, SMACK_LABEL_LEN);
154         if (ret < 0) {
155                 SECURE_C_LOGE("Cannot read from file %s", path);
156                 ret = PC_ERR_FILE_OPERATION;
157                 goto out;
158         }
159
160         SECURE_C_LOGD("smack_label=%s", smack_label);
161
162         ret = PC_OPERATION_SUCCESS;
163
164 out:
165         return ret;
166 }
167
168 API int smack_pid_have_access(pid_t pid,
169                                                                 const char* object,
170                                                                 const char *access_type)
171 {
172         SECURE_C_LOGD("Entering function: %s. Params: pid=%i, object=%s, access_type=%s",
173                                 __func__, pid, object, access_type);
174
175         int ret;
176         char pid_subject_label[SMACK_LABEL_LEN + 1];
177         cap_t cap;
178         cap_flag_value_t cap_v;
179
180         if (!have_smack()) {
181                 C_LOGD("No SMACK. Return access granted");
182                 return 1;
183         }
184
185         if (pid < 0) {
186                 C_LOGE("Invalid pid.");
187                 return -1;
188         }
189
190         if(object == NULL) {
191                 C_LOGE("Invalid object param.");
192                 return -1;
193         }
194
195         if(access_type == NULL) {
196                 C_LOGE("Invalid access_type param");
197                 return -1;
198         }
199
200         //get SMACK label of process
201         ret = get_smack_label_from_process(pid, pid_subject_label);
202         if (PC_OPERATION_SUCCESS != ret) {
203                 SECURE_C_LOGE("get_smack_label_from_process %d failed: %d", pid, ret);
204                 return -1;
205         }
206         SECURE_C_LOGD("pid %d has label: %s", pid, pid_subject_label);
207
208         // do not call smack_have_access() if label is empty
209         if (pid_subject_label[0] != '\0') {
210                 ret = smack_have_access(pid_subject_label, object, access_type);
211                 if ( -1 == ret) {
212                         C_LOGE("smack_have_access failed.");
213                         return -1;
214                 }
215                 if ( 1 == ret ) { // smack_have_access return 1 (access granted)
216                         C_LOGD("smack_have_access returned 1 (access granted)");
217                         return 1;
218                 }
219         }
220
221         // smack_have_access returned 0 (access denied). Now CAP_MAC_OVERRIDE should be checked
222         C_LOGD("smack_have_access returned 0 (access denied)");
223         cap = cap_get_pid(pid);
224         if (cap == NULL) {
225                 C_LOGE("cap_get_pid failed");
226                 return -1;
227         }
228         ret = cap_get_flag(cap, CAP_MAC_OVERRIDE, CAP_EFFECTIVE, &cap_v);
229         if (0 != ret) {
230                 C_LOGE("cap_get_flag failed");
231                 return -1;
232         }
233
234         if (cap_v == CAP_SET) {
235                 C_LOGD("pid %d has CAP_MAC_OVERRIDE", pid);
236                 return 1;
237
238         } else {
239                 C_LOGD("pid %d doesn't have CAP_MAC_OVERRIDE", pid);
240                 return 0;
241         }
242 }
243
244 static int set_dac(const char *smack_label, const char *pkg_name)
245 {
246         SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s, pkg_name=%s",
247                                 __func__, smack_label, pkg_name);
248
249         FILE* fp_group = NULL;  // /etc/group
250         uid_t t_uid = -1;               // uid of current process
251         gid_t *glist = NULL;    // group list
252         gid_t temp_gid = -1;    // for group list
253         char buf[10] = {0, };           // contents in group_list file
254         int glist_cnt = 0;              // for group list
255         int result;
256         int i;
257         new_user usr;
258         unsigned *additional_gids = NULL;
259
260         /*
261          * initialize user structure
262          */
263         C_LOGD("Initialize user structure");
264         memset(usr.user_name, 0x00, 10);
265         memset(usr.home_dir, 0x00, 64);
266         memset(usr.group_list, 0x00, 64);
267         usr.uid = -1;
268         usr.gid = -1;
269
270         t_uid = getuid();
271         C_LOGD("Current uid is %d", t_uid);
272
273         if(t_uid == 0)  // current user is 'root'
274         {
275                 if(!strncmp(pkg_name, "developer", 9))
276                 {
277                         strncpy(usr.user_name, DEV_USER_NAME, sizeof(usr.user_name));
278                         usr.uid = DEVELOPER_UID;
279                         usr.gid = DEVELOPER_GID;
280                         strncpy(usr.home_dir, DEV_HOME_DIR, sizeof(usr.home_dir));
281                         strncpy(usr.group_list, DEV_GROUP_PATH, sizeof(usr.group_list));
282                 }
283                 else
284                 {
285                         strncpy(usr.user_name, APP_USER_NAME, sizeof(usr.user_name));
286                         usr.uid = APP_UID;
287                         usr.gid = APP_GID;
288                         strncpy(usr.home_dir, APP_HOME_DIR, sizeof(usr.home_dir));
289                         strncpy(usr.group_list, APP_GROUP_PATH, sizeof(usr.group_list));
290                 }
291
292                 /*
293                  * get group information
294                  */
295                 C_LOGD("Get group information");
296                 SECURE_C_LOGD("Opening file %s.", usr.group_list);
297                 if(!(fp_group = fopen(usr.group_list, "r")))
298                 {
299                         C_LOGE("fopen failed.");
300                         result = PC_ERR_FILE_OPERATION; // return -1
301                         goto error;
302                 }
303
304                 while(fgets(buf, 10, fp_group) != NULL)
305                 {
306                         errno = 0;
307                         temp_gid = strtoul(buf, 0, 10);
308                         if(errno != 0)  // error occured during strtoul()
309                         {
310                                 C_LOGE("Cannot change string to integer: %s", buf);
311                                 result = PC_ERR_INVALID_OPERATION;
312                                 goto error;
313                         }
314
315                         glist = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + 1));
316                         if(!glist)
317                         {
318                                 result = PC_ERR_MEM_OPERATION;  // return -2
319                                 C_LOGE("Cannot allocate memory");
320                                 goto error;
321                         }
322                         glist[glist_cnt] = temp_gid;
323                         glist_cnt++;
324                 }
325                 fclose(fp_group);
326                 fp_group = NULL;
327
328                 if(NULL != smack_label)
329                 {
330                         gid_t *glist_new;
331                         int i, cnt;
332
333                         result = get_app_gids(smack_label, &additional_gids, &cnt);
334                         if (result != PC_OPERATION_SUCCESS)
335                                 goto error;
336
337                         if (cnt > 0) {
338                                 glist_new = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + cnt));
339                                 if (glist_new == NULL) {
340                                         result = PC_ERR_MEM_OPERATION;  // return -2
341                                         C_LOGE("Memory allocation failed");
342                                         goto error;
343                                 }
344                                 glist = glist_new;
345                                 for (i = 0; i < cnt; ++i) {
346                                         C_LOGD("Additional GID based on enabled permissions: %u", additional_gids[i]);
347                                         glist[glist_cnt++] = additional_gids[i];
348                                 }
349                         }
350                 }
351
352                 /*
353                  * setgroups()
354                  */
355                 C_LOGD("Adding process to the following groups:");
356                 for(i=0; i<glist_cnt; ++i) {
357                         SECURE_C_LOGD("glist [ %d ] = %d", i, glist[i]);
358                 }
359                 C_LOGD("Calling setgroups()");
360                 if(setgroups(glist_cnt, glist) != 0)
361                 {
362                         C_LOGE("setgroups failed");
363                         result = PC_ERR_NOT_PERMITTED;  // return -3
364                         goto error;
365                 }
366                 if(glist != NULL)
367                 {
368                         free(glist);
369                         glist = NULL;
370                 }
371
372                 /*
373                  * setuid() & setgid()
374                  */
375                 C_LOGD("setgid( %d ) & setuid( %d )", usr.gid, usr.uid);
376                 if(setgid(usr.gid) != 0)        // fail
377                 {
378                         C_LOGE("Failed to execute setgid().");
379                         result = PC_ERR_INVALID_OPERATION;
380                         goto error;
381                 }
382                 if(setuid(usr.uid) != 0)        // fail
383                 {
384                         C_LOGE("Failed to execute setuid().");
385                         result = PC_ERR_INVALID_OPERATION;
386                         goto error;
387                 }
388
389                 SECURE_C_LOGD("setenv(): USER = %s, HOME = %s", usr.user_name, usr.home_dir);
390                 if(setenv("USER", usr.user_name, 1) != 0)       //fail
391                 {
392                         C_LOGE("Failed to execute setenv() [USER].");
393                         result = PC_ERR_INVALID_OPERATION;
394                         goto error;
395                 }
396                 if(setenv("HOME", usr.home_dir, 1) != 0)        // fail
397                 {
398                         C_LOGE("Failed to execute setenv() [HOME].");
399                         result = PC_ERR_INVALID_OPERATION;
400                         goto error;
401                 }
402         }
403         else    // current user is not only 'root' but 'app'
404         {
405                 C_LOGE("Current user is NOT root");
406                 result = PC_ERR_NOT_PERMITTED;  // return -3
407                 goto error;
408         }
409
410         result = PC_OPERATION_SUCCESS;
411
412 error:
413         if(fp_group != NULL)
414                 fclose(fp_group);
415         if(glist != NULL)
416                 free(glist);
417         free(additional_gids);
418
419         return result;
420 }
421
422 /**
423  * Get SMACK label from EXEC label of a file.
424  * SMACK label should be freed by caller
425  *
426  * @param path file path to take label from
427  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
428  */
429 static int get_smack_from_binary(char **smack_label, const char* path, app_type_t type)
430 {
431         SECURE_C_LOGD("Entering function: %s. Params: path=%s, type=%d",
432                                 __func__, path, type);
433         int ret;
434
435         *smack_label = NULL;
436         if (type == APP_TYPE_WGT
437         || type == APP_TYPE_WGT_PARTNER
438         || type == APP_TYPE_WGT_PLATFORM) {
439                 ret = smack_lgetlabel(path, smack_label, SMACK_LABEL_EXEC);
440         } else {
441                 ret = smack_getlabel(path, smack_label, SMACK_LABEL_EXEC);
442         }
443         if (ret != 0) {
444                 C_LOGE("Getting exec label from file %s failed", path);
445                 return PC_ERR_INVALID_OPERATION;
446         }
447
448         return PC_OPERATION_SUCCESS;
449 }
450
451 /**
452  * Set process SMACK label.
453  * This function is emulating EXEC label behavior of SMACK for programs
454  * run by dlopen/dlsym instead of execv.
455  *
456  * @param smack label
457  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
458  */
459 static int set_smack_for_self (char *smack_label)
460 {
461         SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s",
462                                 __func__, smack_label);
463         int ret;
464
465         if (smack_label == NULL) {
466                 /* No label to set, just return with success */
467                 C_LOGD("No label to set, just return with success.");
468                 ret = PC_OPERATION_SUCCESS;
469         }
470         else {
471                 SECURE_C_LOGD("smack_label=%s", smack_label);
472                 if (have_smack()) {
473                         ret = smack_set_label_for_self(smack_label);
474                         C_LOGD("smack_set_label_for_self returned %d", ret);
475                 } else
476                         ret = PC_OPERATION_SUCCESS;
477         }
478
479         return ret;
480 }
481
482 static int is_widget(const char* path)
483 {
484         SECURE_C_LOGD("Entering function: %s. Params: path=%s",
485                                 __func__, path);
486         char buf[sizeof(WRT_CLIENT_PATH)];
487         int ret;
488
489         ret = readlink(path, buf, sizeof(WRT_CLIENT_PATH));
490         if (ret == -1)
491                 C_LOGD("readlink(%s) returned error: %s. Assuming that app is not a widget", path, strerror(errno));
492         else if (ret == sizeof(WRT_CLIENT_PATH))
493                 C_LOGD("%s is not a widget", path);
494         if (ret == -1 || ret == sizeof(WRT_CLIENT_PATH))
495                 return 0;
496         buf[ret] = '\0';
497         C_LOGD("buf=%s", buf);
498
499         ret = !strcmp(WRT_CLIENT_PATH, buf);
500         C_LOGD("%s is %s widget", path, ret ? "a" : "not a");
501         return (ret);
502 }
503
504 /**
505  * Partially verify, that the type given for app is correct.
506  * This function will use some heuristics to check whether the app type is right.
507  * It is intended for security hardening to catch privilege setting for the
508  * app type not corresponding to the actual binary.
509  * Beware - when it detects an anomaly, the whole process will be terminated.
510  *
511  * @param type claimed application type
512  * @param path file path to executable
513  * @return return void on success, terminate the process on error
514  */
515 static app_type_t verify_app_type(const char* type, const char* path)
516 {
517         SECURE_C_LOGD("Entering function: %s. Params: type=%s, path=%s",
518                                 __func__, type, path);
519
520         /* TODO: this should actually be treated as error, but until the old
521          * set_privilege API is removed, it must be ignored */
522         if (path == NULL) {
523                 C_LOGD("PKG_TYPE_OTHER");
524                 return APP_TYPE_OTHER; /* good */
525         }
526
527         if (is_widget(path)) {
528                 if (!strcmp(type, "wgt")) {
529                         C_LOGD("PKG_TYPE_WGT");
530                         return APP_TYPE_WGT; /* good */
531                 } else if (!strcmp(type, "wgt_partner")) {
532                         C_LOGD("PKG_TYPE_WGT_PARTNER");
533                         return APP_TYPE_WGT_PARTNER; /* good */
534                 } else if (!strcmp(type, "wgt_platform")) {
535                         C_LOGD("PKG_TYPE_WGT_PLATFORM");
536                         return APP_TYPE_WGT_PLATFORM; /* good */
537                 }
538
539         } else {
540                 if (type == NULL || (strcmp(type, "wgt")
541                                 && strcmp(type, "wgt_partner")
542                                 && strcmp(type, "wgt_platform"))){
543                         C_LOGD("PKG_TYPE_OTHER");
544                         return APP_TYPE_OTHER; /* good */
545                 }
546         }
547
548         /* bad */
549         C_LOGE("EXIT_FAILURE");
550         exit(EXIT_FAILURE);
551 }
552
553 API int set_app_privilege(const char* name, const char* type, const char* path)//deprecated
554 {
555         SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
556                                 __func__, name, type, path);
557
558         return perm_app_set_privilege(name, type, path);
559 }
560
561 API int perm_app_set_privilege(const char* name, const char* type, const char* path)
562 {
563         SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
564                                 __func__, name, type, path);
565
566         //SECURE_C_LOGD("Function params: name = %s, type = %s, path = %s", name, type, path);
567         int ret = PC_OPERATION_SUCCESS;
568         int were_rules_loaded = 0;
569         char *smack_label AUTO_FREE;
570
571         if (name == NULL) {
572                 C_LOGE("Error invalid parameter");
573                 return PC_ERR_INVALID_PARAM;
574         }
575
576         if (path != NULL && have_smack()) {
577                 ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
578                 if (ret != PC_OPERATION_SUCCESS)
579                         return ret;
580
581                 were_rules_loaded = check_if_rules_were_loaded(smack_label);
582                 if (were_rules_loaded < 0) {
583                         C_LOGE("check_if_rules_was_loaded failed.");
584                         return PC_ERR_INVALID_OPERATION;
585                 }
586                 if (!were_rules_loaded) { // first run of application
587                         C_LOGD("This is first run of this application. Adding SMACK rules.");
588                         ret = add_app_first_run_rules(smack_label);
589                         if (ret != PC_OPERATION_SUCCESS ) {
590                                 C_LOGW("add_app_first_run_rules failed");
591                                 // should we return here with error code?
592                         }
593                         mark_rules_as_loaded(smack_label);
594                 }
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 inline const char* app_type_name(app_type_t app_type)
619 {
620         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
621                                 __func__, app_type);
622
623         switch (app_type) {
624         case APP_TYPE_WGT:
625                 C_LOGD("App type = APP_TYPE_WGT");
626                 return "WRT";
627         case APP_TYPE_OSP:
628                 C_LOGD("App type = APP_TYPE_OSP");
629                 return "OSP";
630         case APP_TYPE_WGT_PARTNER:
631                 C_LOGD("App type = APP_TYPE_WGT_PARTNER");
632                 return "WRT_partner";
633         case APP_TYPE_WGT_PLATFORM:
634                 C_LOGD("App type = APP_TYPE_WGT_PLATFORM");
635                 return "WRT_platform";
636         case APP_TYPE_OSP_PARTNER:
637                 C_LOGD("App type = APP_TYPE_OSP_PARTNER");
638                 return "OSP_partner";
639         case APP_TYPE_OSP_PLATFORM:
640                 C_LOGD("App type = APP_TYPE_OSP_PLATFORM");
641                 return "OSP_platform";
642         case APP_TYPE_EFL:
643                 return "EFL";
644         default:
645                 C_LOGD("App type = other");
646                 return NULL;
647         }
648 }
649
650 static inline const char* app_type_group_name(app_type_t app_type)
651 {
652         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
653                                 __func__, app_type);
654
655         switch (app_type) {
656         case APP_TYPE_WGT:
657         case APP_TYPE_WGT_PARTNER:
658         case APP_TYPE_WGT_PLATFORM:
659                 C_LOGD("App type group name = WRT");
660                 return "WRT";
661         case APP_TYPE_OSP:
662         case APP_TYPE_OSP_PARTNER:
663         case APP_TYPE_OSP_PLATFORM:
664                 C_LOGD("App type group name = OST");
665                 return "OSP";
666         case APP_TYPE_EFL:
667                 return "EFL";
668         default:
669                 return NULL;
670         }
671 }
672
673 /**
674  * This function changes permission URI to basename for file name.
675  * For e.g. from http://tizen.org/privilege/contact.read will be
676  * created basename : org.tizen.privilege.contact.read
677  */
678
679 static int base_name_from_perm(const char *perm, char **name)
680 {
681         SECURE_C_LOGD("Entering function: %s. Params: perm=%s",
682                                 __func__, perm);
683
684         iri_t *ip = NULL;
685         char *host_dot = NULL;
686         char *rest_slash = NULL;
687         int ret;
688
689         ip = iri_parse(perm);
690         if (ip == NULL || ip->host == NULL) {
691                 SECURE_C_LOGE("Bad permission format : %s", perm);
692                 iri_destroy(ip);
693                 return PC_ERR_INVALID_PARAM;
694         }
695
696         if (ip->path == NULL) {
697                 ip->path = ip->host;
698                 ip->host = NULL;
699         }
700
701         if (ip->host) {
702                 host_dot = strrchr(ip->host, '.');
703                 if (host_dot) {
704                         *host_dot = '\0';
705                         ++host_dot;
706                 }
707         }
708
709         while ((rest_slash = strchr(ip->path, '/'))) {
710                 *rest_slash = '.';
711         }
712
713         ret = asprintf(name, "%s%s%s%s",
714                         host_dot ? host_dot : "", host_dot ? "." : "",
715                         ip->host ? ip->host : "", ip->path);
716         if (ret == -1) {
717                 C_LOGE("asprintf failed");
718                 iri_destroy(ip);
719                 return PC_ERR_MEM_OPERATION;
720         }
721
722         iri_destroy(ip);
723         return PC_OPERATION_SUCCESS;
724 }
725
726 static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix, bool is_early)
727 {
728         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, perm=%s, suffix=%s, is_early=%d",
729                                 __func__, app_type, perm, suffix, is_early);
730
731         const char* app_type_prefix = NULL;
732         char* perm_basename = NULL;
733         int ret = 0;
734
735         if (perm == NULL || strlen(perm) == 0) {
736                 C_LOGE("Empty permission name.");
737                 return PC_ERR_INVALID_PARAM;
738         }
739
740         app_type_prefix = app_type_group_name(app_type);
741
742         ret = base_name_from_perm(perm, &perm_basename);
743         if (ret != PC_OPERATION_SUCCESS) {
744                 C_LOGE("Couldn't get permission basename.");
745                 return ret;
746         }
747
748         if (is_early) {
749                 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s%s",
750                 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
751                 perm_basename, "_early", suffix);
752         }
753         else {
754                 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
755                 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
756                 perm_basename, suffix);
757         }
758         if (ret == -1) {
759                 C_LOGE("asprintf failed.");
760                 return PC_ERR_MEM_OPERATION;
761         }
762
763         C_LOGD("Path=%s", *path);
764
765         return PC_OPERATION_SUCCESS;
766 }
767
768 static int perm_to_smack_from_file(struct smack_accesses* smack,
769                                            const char* app_label,
770                                            const char* app_label_template,
771                                            const char* rules_file_path)
772 {
773         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_label_template=%s, rules_file_path=%s",
774                                 __func__, app_label, app_label_template, rules_file_path);
775
776         char smack_subject[SMACK_LABEL_LEN + 1];
777         char smack_object[SMACK_LABEL_LEN + 1];
778         char smack_accesses[ACC_LEN + 1];
779         FILE* file AUTO_FCLOSE;
780
781         SECURE_C_LOGD("Opening file %s.", rules_file_path);
782         file = fopen(rules_file_path, "r");
783         if (file == NULL) {
784                 SECURE_C_LOGW("fopen failed [%s] %s", rules_file_path, strerror(errno));
785                 return PC_OPERATION_SUCCESS;
786         }
787
788         while (fscanf(file,
789                         "%" TOSTRING(SMACK_LABEL_LEN) "s "
790                         "%" TOSTRING(SMACK_LABEL_LEN) "s "
791                         "%" TOSTRING(ACC_LEN) "s\n",
792                         smack_subject, smack_object, smack_accesses) == 3) {
793                 if (!strcmp(smack_subject, app_label_template))
794                         strcpy(smack_subject, app_label);
795
796                 if (!strcmp(smack_object, app_label_template))
797                         strcpy(smack_object, app_label);
798
799                 C_LOGD("smack_accesses_add_modify (subject: %s, object: %s, access: %s)", smack_subject, smack_object, smack_accesses);
800                 if (smack_accesses_add_modify(smack, smack_subject, smack_object, smack_accesses, "") != 0) {
801                         C_LOGE("smack_accesses_add_modify failed.");
802                         return PC_ERR_INVALID_OPERATION;
803                 }
804         }
805
806         return PC_OPERATION_SUCCESS;
807 }
808
809 static int perm_to_smack_generic(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm, bool is_early)
810 {
811         C_LOGD("Enter function: %s", __func__);
812
813         int ret;
814         char* path AUTO_FREE;
815
816         // get file name for permission (devcap)
817         ret = perm_file_path(&path, app_type, perm, ".smack", is_early);
818         if (ret != PC_OPERATION_SUCCESS) {
819                 C_LOGD("No smack config file for permission %s", perm);
820                 return ret;
821         }
822
823         ret = perm_to_smack_from_file(smack, app_label, SMACK_APP_LABEL_TEMPLATE, path);
824         if (ret != PC_OPERATION_SUCCESS) {
825                 return ret;
826         }
827
828         return PC_OPERATION_SUCCESS;
829 }
830
831 static int perm_to_smack_early(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
832 {
833         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
834                                 __func__, app_label, app_type, perm);
835
836         return perm_to_smack_generic(smack, app_label, app_type, perm, 1);
837 }
838
839 static int perm_to_smack(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
840 {
841         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
842                                 __func__, app_label, app_type, perm);
843
844         return perm_to_smack_generic(smack, app_label, app_type, perm, 0);
845 }
846
847 static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
848 {
849         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
850                                 __func__, app_label, app_type, perm);
851
852         int ret;
853         char* path AUTO_FREE;
854         FILE* file AUTO_FCLOSE;
855         int gid;
856
857         ret = perm_file_path(&path, app_type, perm, ".dac", 0);
858         if (ret != PC_OPERATION_SUCCESS) {
859                 C_LOGD("No dac config file for permission %s", perm);
860                 return ret;
861         }
862
863         SECURE_C_LOGD("Opening file %s.", path);
864         file = fopen(path, "r");
865         if (file == NULL) {
866                 C_LOGW("fopen failed.");
867                 return PC_OPERATION_SUCCESS;
868         }
869
870         while (fscanf(file, "%d\n", &gid) == 1) {
871                 SECURE_C_LOGD("Adding app_id %s to group %d", app_label, gid);
872                 ret = add_app_gid(app_label, gid);
873                 if (ret != PC_OPERATION_SUCCESS) {
874                         C_LOGE("add_app_gid failed");
875                         return ret;
876                 }
877         }
878
879         return PC_OPERATION_SUCCESS;
880 }
881
882 static int label_all(const FTSENT* ftsent)
883 {
884         SECURE_C_LOGD("Entering function: %s.", __func__);
885
886         return DECISION_LABEL;
887 }
888
889 static int label_execs(const FTSENT* ftsent)
890 {
891         SECURE_C_LOGD("Entering function: %s.", __func__);
892
893         C_LOGD("Mode = %d", ftsent->fts_statp->st_mode);
894         // label only regular executable files
895         if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
896                 return DECISION_LABEL;
897         return DECISION_SKIP;
898 }
899
900 static int label_dirs(const FTSENT* ftsent)
901 {
902         SECURE_C_LOGD("Entering function: %s.", __func__);
903
904         // label only directories
905         if (S_ISDIR(ftsent->fts_statp->st_mode))
906                 return DECISION_LABEL;
907         return DECISION_SKIP;
908 }
909
910 static int label_links_to_execs(const FTSENT* ftsent)
911 {
912         SECURE_C_LOGD("Entering function: %s.", __func__);
913
914         struct stat buf;
915         char* target AUTO_FREE;
916
917         // check if it's a link
918         if ( !S_ISLNK(ftsent->fts_statp->st_mode))
919                 return DECISION_SKIP;
920
921         target = realpath(ftsent->fts_path, NULL);
922         if (!target) {
923                 SECURE_C_LOGE("Getting link target for %s failed (Error = %s)", ftsent->fts_path, strerror(errno));
924                 return PC_ERR_FILE_OPERATION;
925         }
926         if (-1 == stat(target, &buf)) {
927                 SECURE_C_LOGE("stat failed for %s (Error = %s", target, strerror(errno));
928                 return PC_ERR_FILE_OPERATION;
929         }
930         // skip if link target is not a regular executable file
931         if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
932                 SECURE_C_LOGD("%s is not a regular executable file. Skipping.", target);
933                 return DECISION_SKIP;
934         }
935
936         return DECISION_LABEL;
937 }
938
939 static int dir_set_smack_r(const char *path, const char* label,
940                 enum smack_label_type type, label_decision_fn fn)
941 {
942         SECURE_C_LOGD("Entering function: %s. Params: path=%s, label=%s, type=%d",
943                                 __func__, path, label, type);
944
945         const char* path_argv[] = {path, NULL};
946         FTS *fts AUTO_FTS_CLOSE;
947         FTSENT *ftsent;
948         int ret;
949
950         fts = fts_open((char * const *) path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
951         if (fts == NULL) {
952                 C_LOGE("fts_open failed.");
953                 return PC_ERR_FILE_OPERATION;
954         }
955
956         while ((ftsent = fts_read(fts)) != NULL) {
957                 /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
958                 if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
959                         C_LOGE("FTS_ERR error or failed stat(2) (FTS_NS)");
960                         return PC_ERR_FILE_OPERATION;
961                 }
962
963                 ret = fn(ftsent);
964                 if (ret < 0) {
965                         C_LOGE("fn(ftsent) failed.");
966                         return ret;
967                 }
968
969                 if (ret == DECISION_LABEL) {
970                         C_LOGD("smack_lsetlabel (label: %s (type: %d), path: %s)", label, type, ftsent->fts_path);
971                         if (smack_lsetlabel(ftsent->fts_path, label, type) != 0) {
972                                 C_LOGE("smack_lsetlabel failed.");
973                                 return PC_ERR_FILE_OPERATION;
974                         }
975                 }
976         }
977
978         /* If last call to fts_read() set errno, we need to return error. */
979         if (errno != 0) {
980                 C_LOGE("Last errno from fts_read: %s", strerror(errno));
981                 return PC_ERR_FILE_OPERATION;
982         }
983         return PC_OPERATION_SUCCESS;
984 }
985
986 API char* app_id_from_socket(int sockfd)//deprecated
987 {
988         SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
989                                 __func__, sockfd);
990
991     return perm_app_id_from_socket(sockfd);
992 }
993
994 API char* perm_app_id_from_socket(int sockfd)
995 {
996         SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
997                                 __func__, sockfd);
998
999         if (!have_smack()) {
1000                 C_LOGD("No SMACK. Returning NULL.");
1001                 return NULL;
1002         }
1003
1004         char* app_id;
1005         int ret;
1006
1007         ret = smack_new_label_from_socket(sockfd, &app_id);
1008         if (ret < 0) {
1009                 C_LOGE("smack_new_label_from_socket failed");
1010                 return NULL;
1011         }
1012
1013         SECURE_C_LOGD("app_id = %s", app_id);
1014
1015         return app_id;
1016 }
1017
1018 static int app_add_rule(const char *app_id, const char *object, const char *perm)
1019 {
1020         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, object=%s, perm=%s",
1021                                 __func__, app_id, object, perm);
1022
1023         int ret;
1024         int fd AUTO_CLOSE;
1025         char *smack_path AUTO_FREE;
1026         struct smack_accesses* smack AUTO_SMACK_FREE;
1027
1028         ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
1029         if (ret != PC_OPERATION_SUCCESS) {
1030                 C_LOGE("load_smack_from_file failed.");
1031                 return ret;
1032         }
1033
1034         ret = smack_accesses_add_modify(smack, app_id, object, perm, "");
1035         if (ret == -1) {
1036                 C_LOGE("smack_accesses_add_modify failed.");
1037                 return PC_ERR_INVALID_OPERATION;
1038         }
1039
1040         if (have_smack() && smack_accesses_apply(smack)) {
1041                 C_LOGE("smack_accesses_apply failed.");
1042                 return PC_ERR_INVALID_OPERATION;
1043         }
1044
1045         if (smack_accesses_save(smack, fd)) {
1046                 C_LOGE("smack_accesses_save failed.");
1047                 return PC_ERR_INVALID_OPERATION;
1048         }
1049
1050         return PC_OPERATION_SUCCESS;
1051 }
1052
1053
1054 static int
1055 app_register_appsetting(const char *app_id, struct smack_accesses *smack)
1056 {
1057         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1058                                 __func__, app_id);
1059
1060         int ret;
1061         int i;
1062
1063         char **label_app_list AUTO_FREE;
1064         char **label_dir_list AUTO_FREE;
1065         int app_list_len = 0;
1066         int dir_list_len = 0;
1067
1068         if (!smack_label_is_valid(app_id)) {
1069                 C_LOGE("Invalid param app_id.");
1070                 return PC_ERR_INVALID_PARAM;
1071         }
1072
1073         /* writing appsetting_id (app_id) to "database"*/
1074         ret = add_appsetting_id_to_databse(app_id);
1075         if (ret != PC_OPERATION_SUCCESS)
1076                 goto out;
1077
1078
1079         /* Reading labels of all installed apps from "database"*/
1080         ret = get_all_apps_ids(&label_app_list, &app_list_len);
1081         if (ret != PC_OPERATION_SUCCESS) {
1082                 C_LOGE("Error while getting data from database");
1083                 goto out;
1084         }
1085
1086         /*Add smack rules with rx access to each app*/
1087         for (i = 0; i < app_list_len; ++i) {
1088                 C_LOGD("Appsetting: applying rx rule for %s", label_app_list[i]);
1089                 if (smack_accesses_add_modify(smack, app_id,
1090                                 label_app_list[i], "rx", "") == -1) {
1091                         C_LOGE("smack_accesses_add_modify failed.");
1092                         ret = PC_ERR_INVALID_OPERATION;
1093                         goto out;
1094                 }
1095         }
1096
1097         /* Reading labels of all registered settings dirs from "database"*/
1098         ret = get_all_settings_dir_ids(
1099                         &label_dir_list, &dir_list_len);
1100         if (ret != PC_OPERATION_SUCCESS) {
1101                 C_LOGE("Error while getting data from database");
1102                 goto out;
1103         }
1104         /*Add smack rules with rwx access to each app*/
1105         for (i = 0; i < dir_list_len; ++i) {
1106                 C_LOGD("Appsetting: applying rwx rule for %s", label_dir_list[i]);
1107                 if (smack_accesses_add_modify(smack, app_id,
1108                                 label_dir_list[i], "rwx", "") == -1) {
1109                         C_LOGE("smack_accesses_add_modify failed.");
1110                         ret = PC_ERR_INVALID_OPERATION;
1111                         goto out;
1112                         /* Should we abort adding rules if
1113                          * smack_accesses_add_modify fails once?*/
1114                 }
1115         }
1116
1117         out:
1118         for (i = 0; i < app_list_len; ++i) {
1119                 free(label_app_list[i]);
1120         }
1121         for (i = 0; i < dir_list_len; ++i) {
1122                 free(label_dir_list[i]);
1123         }
1124
1125         return ret;
1126 }
1127
1128 static int app_register_av_internal(const char *app_av_id, struct smack_accesses* smack)
1129 {
1130         SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s.",
1131                                 __func__, app_av_id);
1132
1133         int ret;
1134         int i;
1135
1136         char** smack_label_app_list AUTO_FREE;
1137         int smack_label_app_list_len = 0;
1138
1139         if (!smack_label_is_valid(app_av_id)) {
1140                 C_LOGE("Invalid param app_av_id.");
1141                 return PC_ERR_INVALID_PARAM;
1142         }
1143
1144         if(smack == NULL) {
1145                 C_LOGE("Invalid param smack (NULL).");
1146                 return PC_ERR_INVALID_PARAM;
1147         }
1148
1149         // writing anti_virus_id (app_av_id) to "database"
1150         ret = add_av_id_to_databse(app_av_id);
1151         if (ret != PC_OPERATION_SUCCESS )
1152                 goto out;
1153
1154         // Reading labels of all installed apps from "database"
1155         ret = get_all_apps_ids(&smack_label_app_list, &smack_label_app_list_len);
1156         if (ret != PC_OPERATION_SUCCESS ) {
1157                 C_LOGE("Error while geting data from database.");
1158                 goto out;
1159         }
1160         for (i = 0; i < smack_label_app_list_len; ++i) {
1161                 SECURE_C_LOGD("Applying rwx rule for %s", smack_label_app_list[i]);
1162                 if (smack_accesses_add_modify(smack, app_av_id, smack_label_app_list[i], "wrx", "") == -1) {
1163                         C_LOGE("smack_accesses_add_modify failed.");
1164                         ret = PC_ERR_INVALID_OPERATION;
1165                         goto out;
1166                         // Should we abort adding rules once smack_accesses_add_modify will fail?
1167                 }
1168         }
1169
1170 out:
1171         for (i = 0; i < smack_label_app_list_len; ++i) {
1172                 free(smack_label_app_list[i]);
1173         }
1174
1175         return ret;
1176 }
1177
1178 /**
1179  *  This function will find labels of all anti viruses in database
1180  *  and for all of them will add a rule "anti_virus_label app_id rwx".
1181  *  This should be called in app_install function.
1182  */
1183 static int register_app_for_av(const char * app_id)
1184 {
1185         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s.",
1186                                 __func__, app_id);
1187
1188         int ret, i;
1189         char** smack_label_av_list AUTO_FREE;
1190         int smack_label_av_list_len = 0;
1191
1192         // Reading labels of all installed anti viruses from "database"
1193         ret = get_all_avs_ids(&smack_label_av_list, &smack_label_av_list_len);
1194         if (ret != PC_OPERATION_SUCCESS) {
1195                 C_LOGE("Error while geting data from database.");
1196                 return ret;
1197         }
1198
1199         // for each anti-virus label put rule: "anti_virus_label app_id rwx"
1200         for (i = 0; i < smack_label_av_list_len; ++i) {
1201                 SECURE_C_LOGD("Antivirus: app_add_rule (%s, %s rx)", smack_label_av_list[i], app_id);
1202                 if (strcmp(app_id, smack_label_av_list[i])==0) {
1203                         SECURE_C_LOGW("Trying to add antivirus rule for self. Skipping");
1204                         continue;
1205                 }
1206                 ret = app_add_rule(smack_label_av_list[i], app_id, "wrx");
1207                 if (ret != PC_OPERATION_SUCCESS) {
1208                         C_LOGE("app_add_rule failed.");
1209                         goto out;
1210                 }
1211
1212                 free(smack_label_av_list[i]);
1213         }
1214
1215         ret = PC_OPERATION_SUCCESS;
1216
1217 out:
1218         // If something failed, then no entry of smack_label_av_list[i]
1219         // was deallocated. They all must be freed.
1220         for(; i<smack_label_av_list_len; ++i) {
1221                 free(smack_label_av_list[i]);
1222         }
1223
1224         return ret;
1225 }
1226
1227 /**
1228  *  This function will find labels of all setting applications in database
1229  *  and for all of them will add a rule "appsetting_id app_id rwx".
1230  *  This should be called in app_install function.
1231  */
1232 static int register_app_for_appsetting(const char *app_id)
1233 {
1234         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1235                                 __func__, app_id);
1236
1237         int ret, i;
1238         char **smack_label_list AUTO_FREE;
1239         int smack_label_list_len = 0;
1240
1241         /* Reading labels of all installed setting managers from "database"*/
1242         ret = get_all_appsetting_ids(&smack_label_list, &smack_label_list_len);
1243         if (ret != PC_OPERATION_SUCCESS) {
1244                 C_LOGE("Error while geting data from database.");
1245                 return ret;
1246         }
1247
1248         /* for each appsetting put rule: "appsetting_id app_id rx"*/
1249         for (i = 0; i < smack_label_list_len; ++i) {
1250
1251                 SECURE_C_LOGD("Appsetting: app_add_rule (%s, %s rx)", smack_label_list[i], app_id);
1252                 if (strcmp(app_id, smack_label_list[i])==0) {
1253                         SECURE_C_LOGW("Trying to add setting rule for self. Skipping");
1254                         continue;
1255                 }
1256                 ret = app_add_rule(smack_label_list[i], app_id, "rx");
1257                 if (ret != PC_OPERATION_SUCCESS) {
1258                         C_LOGE("app_add_rule failed");
1259                         goto out;
1260                 }
1261
1262                 free(smack_label_list[i]);
1263         }
1264
1265         ret = PC_OPERATION_SUCCESS;
1266
1267 out:
1268         /* If something failed, then no entry of smack_label_list[i]
1269          was deallocated. They all must be freed.*/
1270         for (; i < smack_label_list_len; ++i) {
1271                 free(smack_label_list[i]);
1272         }
1273
1274         return ret;
1275 }
1276
1277
1278 /**
1279  *  This function will grant app_id rx access to all public directories and
1280  *  files previously designated by app_setup_path(APP_PATH_PUBLIC_RO)
1281  *  This should be called in app_install function.
1282  */
1283 static int register_app_for_public_dirs(const char *app_id, struct smack_accesses *smack)
1284 {
1285         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1286                                 __func__, app_id);
1287         int ret, i;
1288         char **public_dirs AUTO_FREE;
1289         int public_dirs_cnt = 0;
1290
1291         ret = db_get_public_dirs(&public_dirs, &public_dirs_cnt);
1292         if (ret != PC_OPERATION_SUCCESS) {
1293                 C_LOGE("Error while getting data from database");
1294                 return ret;
1295         }
1296
1297         for (i = 0; i < public_dirs_cnt; ++i) {
1298                 SECURE_C_LOGD("Allowing app %s to access public path %s", app_id, public_dirs[i]);
1299                 if (smack_accesses_add_modify(smack, app_id, public_dirs[i], "rx", "")) {
1300                         C_LOGE("app_add_rule_modify failed");
1301                         while (i < public_dirs_cnt)
1302                                 free(public_dirs[i++]);
1303                         return PC_ERR_INVALID_OPERATION;
1304                 }
1305                 free(public_dirs[i]);
1306         }
1307
1308         return PC_OPERATION_SUCCESS;
1309 }
1310
1311 static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
1312 {
1313         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
1314                                 __func__, app_id, app_type, permanent);
1315
1316         int i, ret;
1317         char* smack_path AUTO_FREE;
1318         char* smack_path_early AUTO_FREE;
1319         int fd AUTO_CLOSE;
1320         int fd_early AUTO_CLOSE;
1321         struct smack_accesses *smack AUTO_SMACK_FREE;
1322         struct smack_accesses *smack_early AUTO_SMACK_FREE;
1323         const char* base_perm = NULL;
1324
1325         if (!smack_label_is_valid(app_id)) {
1326                 C_LOGE("Invalid param app_id.");
1327                 return PC_ERR_INVALID_PARAM;
1328         }
1329
1330         if(perm_list == NULL) {
1331                 C_LOGE("Invalid perm_list (NULL).");
1332                 return PC_ERR_INVALID_PARAM;
1333         }
1334
1335         ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
1336         if (ret != PC_OPERATION_SUCCESS) {
1337                 C_LOGE("load_smack_from_file failed");
1338                 return ret;
1339         }
1340
1341         ret = load_smack_from_file_early(app_id, &smack_early, &fd_early, &smack_path_early);
1342         if (ret != PC_OPERATION_SUCCESS) {
1343                 C_LOGE("load_smack_from_file failed");
1344                 return ret;
1345         }
1346
1347         /* Implicitly enable base permission for an app_type */
1348         base_perm = app_type_name(app_type);
1349         if (base_perm) {
1350                 SECURE_C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
1351                 ret = perm_to_smack(smack, app_id, APP_TYPE_OTHER, base_perm);
1352                 if (ret != PC_OPERATION_SUCCESS){
1353                         C_LOGE("perm_to_smack failed");
1354                         return ret;
1355                 }
1356
1357                 // Add early permission - such permissions should be enabled right after system boot
1358                 SECURE_C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
1359                 ret = perm_to_smack_early(smack_early, app_id, APP_TYPE_OTHER, base_perm);
1360                 if (ret != PC_OPERATION_SUCCESS){
1361                         C_LOGE("perm_to_smack failed");
1362                         return ret;
1363                 }
1364
1365         }
1366         for (i = 0; perm_list[i] != NULL; ++i) {
1367                 SECURE_C_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]);
1368                 if (strcmp(perm_list[i], TIZEN_PRIVILEGE_ANTIVIRUS) == 0) {
1369                         ret = app_register_av_internal(app_id, smack);
1370                         if (ret != PC_OPERATION_SUCCESS) {
1371                                 C_LOGE("app_register_av_internal failed");
1372                                 return ret;
1373                         }
1374                 }
1375                 if (strcmp(perm_list[i], TIZEN_PRIVILEGE_APPSETTING) == 0) {
1376                         ret = app_register_appsetting(app_id, smack);
1377                         if (ret != PC_OPERATION_SUCCESS) {
1378                                 C_LOGE("app_register_appsetting failed");
1379                                 return ret;
1380                         }
1381                 }
1382
1383                 ret = perm_to_smack(smack, app_id, app_type, perm_list[i]);
1384                 if (ret != PC_OPERATION_SUCCESS){
1385                         C_LOGE("perm_to_smack failed");
1386                         return ret;
1387                 }
1388
1389                 ret = perm_to_smack_early(smack_early, app_id, app_type, perm_list[i]);
1390                 if (ret != PC_OPERATION_SUCCESS){
1391                         C_LOGE("perm_to_smack_early failed");
1392                         return ret;
1393                 }
1394
1395                 ret = perm_to_dac(app_id, app_type, perm_list[i]);
1396                 if (ret != PC_OPERATION_SUCCESS){
1397                         C_LOGE("perm_to_dac failed");
1398                         return ret;
1399                 }
1400         }
1401
1402         if (have_smack() && smack_accesses_apply(smack)) {
1403                 C_LOGE("smack_accesses_apply failed");
1404                 return PC_ERR_INVALID_OPERATION;
1405         }
1406
1407         if (have_smack() && smack_accesses_apply(smack_early)) {
1408                 C_LOGE("smack_accesses_apply (early) failed");
1409                 return PC_ERR_INVALID_OPERATION;
1410         }
1411
1412         if (permanent && smack_accesses_save(smack, fd)) {
1413                 C_LOGE("smack_accesses_save failed");
1414                 return PC_ERR_INVALID_OPERATION;
1415         }
1416
1417         if (permanent && smack_accesses_save(smack_early, fd_early)) {
1418                 C_LOGE("smack_accesses_save (early) failed");
1419                 return PC_ERR_INVALID_OPERATION;
1420         }
1421
1422         return PC_OPERATION_SUCCESS;
1423 }
1424
1425 API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
1426 {
1427         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1428                                 __func__, app_id);
1429
1430         return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
1431 }
1432
1433 API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
1434 {
1435         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1436                                 __func__, app_id);
1437
1438         return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
1439 }
1440
1441 API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
1442 {
1443         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
1444                                 __func__, pkg_id, app_type, persistent);
1445
1446         return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
1447 }
1448
1449 API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)
1450 {
1451         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
1452                                 __func__, pkg_id, app_type, persistent);
1453
1454         return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
1455 }
1456
1457 API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
1458 {
1459         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
1460                                 __func__, pkg_id, app_type);
1461
1462         return perm_app_disable_permissions(pkg_id, app_type, perm_list);
1463 }
1464
1465 /* FIXME: this function is only a stub */
1466 API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
1467 {
1468         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
1469                                 __func__, pkg_id, app_type);
1470
1471         return PC_OPERATION_SUCCESS;
1472 }
1473
1474 static int app_revoke_permissions_internal(const char* app_id, bool persistent)
1475 {
1476         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, persistent=%d",
1477                                 __func__, app_id, persistent);
1478
1479         char* smack_path AUTO_FREE;
1480         int ret;
1481         int fd AUTO_CLOSE;
1482         struct smack_accesses *smack AUTO_SMACK_FREE;
1483
1484         if (!smack_label_is_valid(app_id)) {
1485                 C_LOGE("Invalid param app_id.");
1486                 return PC_ERR_INVALID_PARAM;
1487         }
1488
1489         ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
1490         if (ret != PC_OPERATION_SUCCESS) {
1491                 C_LOGE("load_smack_from_file failed.");
1492                 return ret;
1493         }
1494
1495         if (have_smack() && smack_accesses_clear(smack)) {
1496                 ret = PC_ERR_INVALID_OPERATION;
1497                 C_LOGE("smack_accesses_clear failed.");
1498                 return ret;
1499         }
1500
1501         if (have_smack() && smack_revoke_subject(app_id)) {
1502                 ret = PC_ERR_INVALID_OPERATION;
1503                 C_LOGE("smack_revoke_subject failed.");
1504                 return ret;
1505         }
1506
1507         if (persistent && ftruncate(fd, 0) == -1)
1508                 C_LOGW("file truncation failed");
1509
1510         return PC_OPERATION_SUCCESS;
1511 }
1512
1513 API int app_revoke_permissions(const char* pkg_id)//deprecated
1514 {
1515         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
1516         return perm_app_revoke_permissions(pkg_id);
1517 }
1518
1519 API int perm_app_revoke_permissions(const char* pkg_id)
1520 {
1521         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
1522         int ret;
1523
1524         if (!smack_label_is_valid(pkg_id)) {
1525                 C_LOGE("Invalid param app_id.");
1526                 return PC_ERR_INVALID_PARAM;
1527         }
1528
1529         ret = app_revoke_permissions_internal(pkg_id, true);
1530         if (ret) {
1531                 C_LOGE("Revoking permissions failed.");
1532                 return ret;
1533         }
1534
1535         return PC_OPERATION_SUCCESS;
1536 }
1537
1538 API int app_reset_permissions(const char* pkg_id)//deprecated
1539 {
1540         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1541                                 __func__, pkg_id);
1542
1543         return perm_app_reset_permissions(pkg_id);
1544 }
1545
1546 API int perm_app_reset_permissions(const char* pkg_id)
1547 {
1548         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1549                                 __func__, pkg_id);
1550
1551         int ret;
1552
1553         if (!smack_label_is_valid(pkg_id)) {
1554                 C_LOGE("Invalid param pkg_id.");
1555                 return PC_ERR_INVALID_PARAM;
1556         }
1557
1558         ret = app_revoke_permissions_internal(pkg_id, false);
1559         if (ret) {
1560                 C_LOGE("Revoking permissions failed.");
1561                 return ret;
1562         }
1563
1564         /* Add empty permissions set to trigger re-read of rules */
1565         return perm_app_enable_permissions(pkg_id, APP_TYPE_OTHER, (const char*[]){NULL}, 0);
1566 }
1567
1568 API int app_label_dir(const char* label, const char* path)//deprecated
1569 {
1570         SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
1571                                 __func__, label, path);
1572
1573         int ret = PC_OPERATION_SUCCESS;
1574
1575         if(path == NULL) {
1576                 C_LOGE("Invalid argument path (NULL).");
1577                 return PC_ERR_INVALID_PARAM;
1578         }
1579
1580         if (!smack_label_is_valid(label)) {
1581                 C_LOGE("Invalid param label.");
1582                 return PC_ERR_INVALID_PARAM;
1583         }
1584
1585         //setting access label on everything in given directory and below
1586         ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
1587         if (PC_OPERATION_SUCCESS != ret)
1588         {
1589                 C_LOGE("dir_set_smack_r failed.");
1590                 return ret;
1591         }
1592
1593         //setting execute label for everything with permission to execute
1594         ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
1595         if (PC_OPERATION_SUCCESS != ret)
1596         {
1597                 C_LOGE("dir_set_smack_r failed.");
1598                 return ret;
1599         }
1600
1601         //setting execute label for everything with permission to execute
1602         ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
1603         return ret;
1604 }
1605
1606 int smack_get_access_new(const char* subject, const char* object, char** label)
1607 {
1608         SECURE_C_LOGD("Entering function: %s. Params: subject=%s, object=%s",
1609                                 __func__, subject, object);
1610         
1611         char buff[ACC_LEN] = {'r', 'w', 'x', 'a', 't', 'l'};
1612         char perm[2] = {'-'};
1613         int i;
1614
1615         if(!smack_label_is_valid(subject)) {
1616                 C_LOGE("Invalid param subject.");
1617                 return PC_ERR_INVALID_PARAM;
1618         }
1619
1620         if(!smack_label_is_valid(object)) {
1621                 C_LOGE("Invalid param object.");
1622                 return PC_ERR_INVALID_PARAM;
1623         }
1624
1625         if(!label) {
1626                 C_LOGE("Invalid param label (NULL).");
1627                 return PC_ERR_INVALID_PARAM;
1628         }
1629
1630         for (i=0; i<ACC_LEN; ++i) {
1631                 perm[0] = buff[i];
1632                 int ret = smack_have_access(subject, object, perm);
1633                 if (-1 == ret) {
1634                         C_LOGE("smack_have_access failed during %c check.", perm[0]);
1635                         return PC_ERR_INVALID_OPERATION;
1636                 }
1637                 if (0 == ret)
1638                         buff[i] = '-';
1639         }
1640
1641         *label = malloc(ACC_LEN+1);
1642         if (NULL == *label)
1643                 return PC_ERR_MEM_OPERATION;
1644
1645         memcpy(*label, buff, ACC_LEN);
1646         (*label)[ACC_LEN] = 0;
1647         return PC_OPERATION_SUCCESS;
1648 }
1649
1650 static int app_uninstall_remove_early_rules(const char *app_id)
1651 {
1652         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1653                                 __func__, app_id);
1654
1655         int ret;
1656         int fd AUTO_CLOSE;
1657         int size;
1658         char tmp;
1659         char *data, *data_end;
1660         char *line_begin, *line_end, *write_pos;
1661         char subject[SMACK_LABEL_LEN + 1];
1662         char object[SMACK_LABEL_LEN + 1];
1663
1664         SECURE_C_LOGD("Opening file %s.", SMACK_STARTUP_RULES_FILE);
1665         fd = open(SMACK_STARTUP_RULES_FILE, O_RDWR);
1666         if (fd < 0) {
1667                 SECURE_C_LOGE("Unable to open file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
1668                 return PC_ERR_FILE_OPERATION;
1669         }
1670
1671         if (flock(fd, LOCK_EX)) {
1672                 SECURE_C_LOGE("flock failed, error %s", strerror(errno));
1673                 return PC_ERR_FILE_OPERATION;
1674         }
1675
1676         size = lseek(fd, 0, SEEK_END);
1677         if (size < 0) {
1678                 SECURE_C_LOGE("Unable to read file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
1679                 return PC_ERR_FILE_OPERATION;
1680         }
1681
1682         if (size == 0)
1683                 return PC_OPERATION_SUCCESS;
1684
1685         data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1686         if (data == MAP_FAILED) {
1687                 SECURE_C_LOGE("Unable to read file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
1688                 return PC_ERR_FILE_OPERATION;
1689         }
1690         data_end = data + size;
1691
1692         line_begin = write_pos = data;
1693         while (line_begin < data_end) {
1694                 line_end = memchr(line_begin, '\n', data_end - line_begin);
1695                 if (line_end == NULL)
1696                         line_end = data_end - 1;
1697
1698                 tmp = *line_end;
1699                 *line_end = '\0';
1700                 SECURE_C_LOGD("Considering early rule: %s", line_begin);
1701
1702                 ret = sscanf(line_begin, "%" TOSTRING(SMACK_LABEL_LEN) "s %" TOSTRING(SMACK_LABEL_LEN) "s", subject, object);
1703                 if (ret != 2) {
1704                         C_LOGD("Rule format is invalid, skipping it.");
1705                         goto loop_next;
1706                 }
1707
1708                 if (!strcmp(subject, app_id) || !strcmp(object, app_id)) {
1709                         C_LOGD("Rule belongs to an app being removed, skipping it.");
1710                         goto loop_next;
1711                 }
1712
1713                 C_LOGD("Rule still needed, keeping it.");
1714                 *line_end = tmp;
1715                 if (write_pos != line_begin)
1716                         memcpy(write_pos, line_begin, line_end - line_begin + 1);
1717                 write_pos += (line_end - line_begin + 1);
1718
1719         loop_next:
1720                 *line_end = tmp;
1721                 line_begin = line_end + 1;
1722         }
1723
1724         munmap(data, size);
1725         ret = ftruncate(fd, write_pos - data);
1726         if (ret < 0) {
1727                 SECURE_C_LOGE("Unable to truncate file %s to %d bytes: %s", SMACK_STARTUP_RULES_FILE, write_pos, strerror(errno));
1728
1729                 return PC_ERR_FILE_OPERATION;
1730         }
1731
1732         return PC_OPERATION_SUCCESS;
1733 }
1734
1735 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
1736 {
1737         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
1738                                 __func__, app_label, shared_label, path);
1739         int ret;
1740
1741         if(path == NULL) {
1742                 C_LOGE("Invalid param path.");
1743                 return PC_ERR_INVALID_PARAM;
1744         }
1745
1746         if(!smack_label_is_valid(app_label)) {
1747                 C_LOGE("Invalid param app_label");
1748                 return PC_ERR_INVALID_PARAM;
1749         }
1750
1751         if(!smack_label_is_valid(shared_label)) {
1752                 C_LOGE("Invalid param shared_label");
1753                 return PC_ERR_INVALID_PARAM;
1754         }
1755
1756         if (strcmp(app_label, shared_label) == 0) {
1757                 C_LOGE("app_label equals shared_label");
1758                 return PC_ERR_INVALID_PARAM;
1759         }
1760
1761         //setting label on everything in given directory and below
1762         ret = dir_set_smack_r(path, shared_label, SMACK_LABEL_ACCESS, label_all);
1763         if(ret != PC_OPERATION_SUCCESS){
1764                 C_LOGE("dir_set_smack_r failed.");
1765                 return ret;
1766         }
1767
1768         //setting transmute on dir
1769         ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, label_dirs);
1770         if (ret != PC_OPERATION_SUCCESS) {
1771                 C_LOGE("dir_set_smack_r failed");
1772                 return ret;
1773         }
1774
1775         ret = app_add_rule(app_label, shared_label, "rwxat");
1776         if (ret != PC_OPERATION_SUCCESS) {
1777                 C_LOGE("app_add_rule failed");
1778                 return ret;
1779         }
1780
1781         return PC_OPERATION_SUCCESS;
1782 }
1783
1784 API int add_shared_dir_readers(const char* shared_label, const char** app_list)//deprecated
1785 {
1786         SECURE_C_LOGD("Entering function: %s. Params: shared_label=%s",
1787                                 __func__, shared_label);
1788         int ret;
1789         int i;
1790
1791         if(app_list == NULL) {
1792                 C_LOGE("Invalid param app_list.");
1793                 return PC_ERR_INVALID_PARAM;
1794         }
1795
1796         if (!smack_label_is_valid(shared_label)) {
1797                 C_LOGE("Invalid param shared_label.");
1798                 return PC_ERR_INVALID_PARAM;
1799         }
1800
1801         for (i = 0; app_list[i] != NULL; i++) {
1802                 if (!smack_label_is_valid(app_list[i])) {
1803                         C_LOGE("Invalid %d element from param app_list.", i);
1804                         return PC_ERR_INVALID_PARAM;
1805                 }
1806
1807                 ret = app_add_rule(app_list[i], shared_label, "rx");
1808                 if (ret != PC_OPERATION_SUCCESS) {
1809                         C_LOGE("app_add_rule failed.");
1810                         return ret;
1811                 }
1812         }
1813
1814         return PC_OPERATION_SUCCESS;
1815 }
1816
1817 static char* smack_label_for_path(const char *app_id, const char *path)
1818 {
1819         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, path=%s",
1820                                 __func__, app_id, path);
1821
1822         char *salt AUTO_FREE;
1823         char *label;
1824         char *x;
1825
1826         /* Prefix $1$ causes crypt() to use MD5 function */
1827         if (-1 == asprintf(&salt, "$1$%s", app_id)) {
1828                 C_LOGE("asprintf failed");
1829                 return NULL;
1830         }
1831
1832         label = crypt(path, salt);
1833         if (label == NULL) {
1834                 C_LOGE("crypt failed");
1835                 return NULL;
1836         }
1837
1838         /* crypt() output may contain slash character,
1839          * which is not legal in Smack labels */
1840         for (x = label; *x; ++x) {
1841                 if (*x == '/')
1842                         *x = '%';
1843         }
1844
1845         return label;
1846 }
1847 /*
1848  * This function should be called in perm_app_setup_path_internal().
1849  * After installation of new application (pkg_id) and labeling its shared directory (RW or RO),
1850  * all others apps installed in system should get rules to this shared directory.
1851  * This function will add and store those rules in rule-file of new installed app (pkg_id)
1852  */
1853 static int add_other_apps_rules_for_shared_dir(const char *pkg_id, const char *type_of_shared_dir, const char *shared_dir_label)
1854 {
1855         C_LOGD("Enter function: %s", __func__);
1856
1857         int ret;
1858         int fd AUTO_CLOSE;
1859         char *smack_path AUTO_FREE;
1860         char *smack_rules_file_path AUTO_FREE;
1861         struct smack_accesses* smack AUTO_SMACK_FREE;
1862
1863         ret = load_smack_from_file(pkg_id, &smack, &fd, &smack_path);
1864         if (ret != PC_OPERATION_SUCCESS ) {
1865                 C_LOGE("load_smack_from_file failed: %d", ret);
1866                 return ret;
1867         }
1868
1869         ret = asprintf(&smack_rules_file_path, TOSTRING(SHAREDIR)"/%s", type_of_shared_dir);
1870         if (ret < 0) {
1871                 C_LOGE("asprintf failed");
1872                 return PC_ERR_MEM_OPERATION;
1873         }
1874
1875         ret = perm_to_smack_from_file(smack, shared_dir_label, SMACK_SHARED_DIR_LABEL_TEMPLATE, smack_rules_file_path);
1876         if (ret != PC_OPERATION_SUCCESS ) {
1877                 C_LOGE("perm_to_smack_from_file failed: %d", ret);
1878         }
1879
1880         if (have_smack() && smack_accesses_apply(smack)) {
1881                 C_LOGE("smack_accesses_apply failed");
1882                 return PC_ERR_INVALID_OPERATION;
1883         }
1884
1885         if (smack_accesses_save(smack, fd)) {
1886                 C_LOGE("smack_accesses_save failed");
1887                 return PC_ERR_INVALID_OPERATION;
1888         }
1889
1890         return PC_OPERATION_SUCCESS;
1891 }
1892
1893 /* FIXME: remove this pragma once deprecated API is deleted */
1894 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1895 static int perm_app_setup_path_internal(const char* pkg_id, const char* path, app_path_type_t app_path_type, va_list ap)
1896 {
1897         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1898                                 __func__, pkg_id, path, app_path_type);
1899
1900         if(path == NULL) {
1901                 C_LOGE("Invalid argument path.");
1902                 return PC_ERR_INVALID_PARAM;
1903         }
1904
1905         if (!smack_label_is_valid(pkg_id)) {
1906                 C_LOGE("Invalid pkg_id.");
1907                 SECURE_C_LOGE("Invalid pkg_id %s", pkg_id);
1908                 return PC_ERR_INVALID_PARAM;
1909         }
1910
1911         switch (app_path_type) {
1912         case APP_PATH_PRIVATE:
1913                 C_LOGD("app_path_type is APP_PATH_PRIVATE.");
1914                 return app_label_dir(pkg_id, path);
1915
1916         case APP_PATH_GROUP_RW: {
1917                 C_LOGD("app_path_type is APP_PATH_GROUP_RW.");
1918                 int ret;
1919                 const char *shared_label;
1920
1921                 shared_label = va_arg(ap, const char *);
1922
1923                 if (!smack_label_is_valid(shared_label)) {
1924                         C_LOGE("Invalid shared_label.");
1925                         return PC_ERR_INVALID_PARAM;
1926                 }
1927
1928                 if (strcmp(pkg_id, shared_label) == 0) {
1929                         C_LOGE("pkg_id equals shared_label.");
1930                         return PC_ERR_INVALID_PARAM;
1931                 }
1932
1933                 ret = app_label_shared_dir(pkg_id, shared_label, path);
1934                 if (ret != PC_OPERATION_SUCCESS) {
1935                         C_LOGE("app_label_shared_dir failed: %d", ret);
1936                         return ret;
1937                 }
1938
1939                 return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_GROUP_RW, shared_label);
1940         }
1941
1942         case APP_PATH_PUBLIC_RO: {
1943                 C_LOGD("app_path_type is APP_PATH_PUBLIC_RO.");
1944                 char **app_ids AUTO_FREE;
1945                 int app_ids_cnt = 0;
1946                 const char *label;
1947                 int i, ret;
1948
1949                 C_LOGD("New public RO path %s", path);
1950                 label = smack_label_for_path(pkg_id, path);
1951                 if (label == NULL) {
1952                         C_LOGE("smack_label_for_path failed.");
1953                         return PC_ERR_INVALID_OPERATION;
1954                 }
1955
1956                 C_LOGD("Generated label '%s' for public RO path %s", label, path);
1957                 ret = app_label_shared_dir(pkg_id, label, path);
1958                 if (ret != PC_OPERATION_SUCCESS) {
1959                         C_LOGE("app_label_shared_dir failed.");
1960                         return ret;
1961                 }
1962
1963                 /* FIXME: This should be in some kind of transaction/lock */
1964                 ret = db_add_public_dir(label);
1965                 if (ret != PC_OPERATION_SUCCESS) {
1966                         C_LOGE("db_add_public_dir failed.");
1967                         return ret;
1968                 }
1969
1970                 ret = get_all_apps_ids(&app_ids, &app_ids_cnt);
1971                 if (ret != PC_OPERATION_SUCCESS) {
1972                         C_LOGE("get_all_aps_ids failed.");
1973                         return ret;
1974                 }
1975
1976                 for (i = 0; i < app_ids_cnt; ++i) {
1977                         SECURE_C_LOGD("Allowing app %s to access public path %s", app_ids[i], path);
1978                         ret = app_add_rule(app_ids[i], label, "rx");
1979                         if (ret != PC_OPERATION_SUCCESS) {
1980                                 C_LOGE("smack_accesses_new failed");
1981                                 while (i < app_ids_cnt)
1982                                         free(app_ids[i++]);
1983                                 return ret;
1984                         }
1985                         free(app_ids[i]);
1986                 }
1987
1988                 return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_PUBLIC_RO, label);
1989         }
1990
1991         case APP_PATH_SETTINGS_RW:
1992         {
1993                 C_LOGD("app_path_type is APP_PATH_SETTINGS_RW.");
1994                 char **app_ids AUTO_FREE;
1995                 int app_ids_cnt = 0;
1996                 const char *label;
1997                 int i;
1998                 int ret;
1999
2000                 /*get path id*/
2001                 label = smack_label_for_path(pkg_id, path);
2002                 if (label == NULL) {
2003                         C_LOGE("smack_label_for_path failed.");
2004                         return PC_ERR_INVALID_OPERATION;
2005                 }
2006
2007                 /*set id for path and all subfolders*/
2008                 C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
2009                 ret = app_label_shared_dir(pkg_id, label, path);
2010                 if (ret != PC_OPERATION_SUCCESS) {
2011                         C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
2012                         return ret;
2013                 }
2014
2015                 /* add path to database */
2016                 /* FIXME: This should be in some kind of transaction/lock */
2017                 ret = add_setting_dir_id_to_databse(label);
2018                 if (ret != PC_OPERATION_SUCCESS) {
2019                         C_LOGE("Appsetting: add_setting_dir_id_to_databse failed");
2020                         return ret;
2021                 }
2022
2023                 /*read all apps with appsetting privilege*/
2024                 ret = get_all_appsetting_ids(&app_ids, &app_ids_cnt);
2025                 if (ret != PC_OPERATION_SUCCESS) {
2026                         C_LOGE("Appsetting: get_all_appsetting_ids failed");
2027                         return ret;
2028                 }
2029                 C_LOGD("Appsetting: %d appsetting privileged apps registered",
2030                                 app_ids_cnt);
2031
2032                 /*give RWX rights to all apps that have appsetting privilege*/
2033                 for (i = 0; i < app_ids_cnt; ++i) {
2034                         C_LOGD("Appsetting: allowing app %s to access setting path %s",
2035                                         app_ids[i], label);
2036                         ret = app_add_rule(app_ids[i], label, "rwx");
2037                         if (ret != PC_OPERATION_SUCCESS) {
2038                                 C_LOGE("app_add_rule failed");
2039                                 while (i < app_ids_cnt)
2040                                         free(app_ids[i++]);
2041                                 return ret;
2042                         }
2043                         free(app_ids[i]);
2044                 }
2045
2046                 return PC_OPERATION_SUCCESS;
2047         }
2048
2049         case APP_PATH_ANY_LABEL: {
2050                 C_LOGD("app_path_type is APP_PATH_ANY_LABEL.");
2051                 const char *label = NULL;
2052                 label = va_arg(ap, const char *);
2053                 return app_label_dir(label, path);
2054         }
2055
2056         default:
2057                 C_LOGE("app_path_type is invalid.");
2058                 return PC_ERR_INVALID_PARAM;
2059         }
2060
2061         return PC_OPERATION_SUCCESS;
2062 }
2063 /* FIXME: remove this pragma once deprecated API is deleted */
2064 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
2065
2066 API int app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)//deprecated
2067 {
2068         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
2069                                 __func__, pkg_id, path, app_path_type);
2070
2071         va_list ap;
2072         int ret;
2073         va_start( ap, app_path_type );
2074         ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
2075         va_end( ap );
2076         return ret;
2077 }
2078
2079
2080 API int perm_app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)
2081 {
2082         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
2083                                 __func__, pkg_id, path, app_path_type);
2084
2085         va_list ap;
2086         int ret;
2087         va_start( ap, app_path_type );
2088         ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
2089         va_end( ap );
2090         return ret;
2091 }
2092
2093 API int app_add_friend(const char* pkg_id1, const char* pkg_id2)//deprecated
2094 {
2095         SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
2096                                 __func__, pkg_id1, pkg_id2);
2097
2098         return perm_app_add_friend(pkg_id1, pkg_id2);
2099 }
2100
2101 API int perm_app_add_friend(const char* pkg_id1, const char* pkg_id2)
2102 {
2103         SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
2104                                 __func__, pkg_id1, pkg_id2);
2105
2106         int ret;
2107
2108         if (!smack_label_is_valid(pkg_id1) || !smack_label_is_valid(pkg_id2)) {
2109                 C_LOGE("Invalid pkg_id1 or pkg_id2.");
2110                 return PC_ERR_INVALID_PARAM;
2111         }
2112
2113         ret = app_add_rule(pkg_id1, pkg_id2, "rwxat");
2114         if (ret != PC_OPERATION_SUCCESS) {
2115                 C_LOGE("app_add_rule failed");
2116                 return ret;
2117         }
2118
2119         ret = app_add_rule(pkg_id2, pkg_id1, "rwxat");
2120         if (ret != PC_OPERATION_SUCCESS) {
2121                 C_LOGE("app_add_rule failed");
2122                 return ret;
2123         }
2124
2125         return PC_OPERATION_SUCCESS;
2126 }
2127
2128 API int app_install(const char* pkg_id)//deprecated
2129 {
2130         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
2131                                 __func__, pkg_id);
2132
2133         return perm_app_install(pkg_id);
2134 }
2135
2136 API int perm_app_install(const char* pkg_id)
2137 {
2138         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
2139                                 __func__, pkg_id);
2140
2141         int ret;
2142         int fd AUTO_CLOSE;
2143         char* smack_path AUTO_FREE;
2144         struct smack_accesses *smack AUTO_SMACK_FREE;
2145
2146         if (!smack_label_is_valid(pkg_id)) {
2147                 C_LOGE("Invalid param pkg_id.");
2148                 return PC_ERR_INVALID_PARAM;
2149         }
2150
2151         ret = smack_file_name(pkg_id, &smack_path);
2152         if (ret != PC_OPERATION_SUCCESS) {
2153                 C_LOGE("smack_file_name failed.");
2154                 return ret;
2155         }
2156
2157         ret = load_smack_from_file(pkg_id, &smack, &fd, &smack_path);
2158         if (ret != PC_OPERATION_SUCCESS) {
2159                 C_LOGE("load_smack_from_file failed");
2160                 return ret;
2161         }
2162
2163         ret = add_app_id_to_databse(pkg_id);
2164         if (ret != PC_OPERATION_SUCCESS ) {
2165                 SECURE_C_LOGE("Error while adding app %s to database: %s ", pkg_id, strerror(errno));
2166                 return ret;
2167         }
2168
2169         ret = register_app_for_av(pkg_id);
2170         if (ret != PC_OPERATION_SUCCESS) {
2171                 SECURE_C_LOGE("Error while adding rules for anti viruses to app %s: %s ", pkg_id, strerror(errno));
2172                 return ret;
2173         }
2174
2175         ret = register_app_for_appsetting(pkg_id);
2176         if (ret != PC_OPERATION_SUCCESS) {
2177                 SECURE_C_LOGE("Error while adding rules for setting managers to app %s: %s ", pkg_id, strerror(errno));
2178                 return ret;
2179         }
2180
2181         ret = register_app_for_public_dirs(pkg_id, smack);
2182         if (ret != PC_OPERATION_SUCCESS) {
2183                 SECURE_C_LOGE("Error while adding rules for access to public dirs for app %s: %s ", pkg_id, strerror(errno));
2184                 return ret;
2185         }
2186
2187         if (have_smack() && smack_accesses_apply(smack)) {
2188                 C_LOGE("smack_accesses_apply failed");
2189                 return PC_ERR_INVALID_OPERATION;
2190         }
2191
2192         if (smack_accesses_save(smack, fd)) {
2193                 C_LOGE("smack_accesses_save failed");
2194                 return PC_ERR_INVALID_OPERATION;
2195         }
2196
2197         return PC_OPERATION_SUCCESS;
2198 }
2199
2200 API int app_uninstall(const char* pkg_id)//deprecated
2201 {
2202         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
2203                                 __func__, pkg_id);
2204
2205         return perm_app_uninstall(pkg_id);
2206 }
2207
2208 API int perm_app_uninstall(const char* pkg_id)
2209 {
2210         // TODO: When real database will be used, then this function should remove app_id
2211         //       from database.
2212         //       It also should remove rules like: "anti_virus_label app_id rwx".
2213         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
2214         char* smack_path AUTO_FREE;
2215         int ret;
2216
2217         if (!smack_label_is_valid(pkg_id)) {
2218                 C_LOGE("Invalid param pkg_id.");
2219                 return PC_ERR_INVALID_PARAM;
2220         }
2221
2222         ret = smack_file_name(pkg_id, &smack_path);
2223         if (ret != PC_OPERATION_SUCCESS) {
2224                 C_LOGE("smack_file_name failed.");
2225                 return ret;
2226         }
2227
2228         if (unlink(smack_path)) {
2229                 C_LOGE("unlink failed (error: %s)", strerror(errno));
2230                 return PC_OPERATION_SUCCESS;
2231         }
2232
2233         ret = app_uninstall_remove_early_rules(pkg_id);
2234         if (ret != PC_OPERATION_SUCCESS) {
2235                 C_LOGE("app_uninstall_remove_early_rules failed.");
2236                 return ret;
2237         }
2238
2239         return PC_OPERATION_SUCCESS;
2240 }
2241
2242 static int save_rules(int fd, struct smack_accesses* accesses) {
2243         SECURE_C_LOGD("Entering function: %s. Params: fd=%d", __func__, fd);
2244
2245         if (flock(fd, LOCK_EX)) {
2246                 C_LOGE("flock failed (error: %s)", strerror(errno));
2247                 return PC_ERR_FILE_OPERATION;
2248         }
2249
2250         if (smack_accesses_save(accesses, fd)) {
2251                 C_LOGE("smack_accesses_save failed");
2252                 return PC_ERR_FILE_OPERATION;
2253         }
2254         return PC_OPERATION_SUCCESS ;
2255 }
2256
2257 static int validate_and_add_rule(char* rule, struct smack_accesses* accesses) {
2258         SECURE_C_LOGD("Entering function: %s. Params: rule=%s",
2259                                 __func__, rule);
2260
2261         const char* subject = NULL;
2262         const char* object = NULL;
2263         const char* access = NULL;
2264         char* saveptr = NULL;
2265
2266         subject = strtok_r(rule, " \t\n", &saveptr);
2267         object = strtok_r(NULL, " \t\n", &saveptr);
2268         access = strtok_r(NULL, " \t\n", &saveptr);
2269
2270         // check rule validity
2271         if (subject == NULL ||
2272                 object == NULL ||
2273                 access == NULL ||
2274                 strtok_r(NULL, " \t\n", &saveptr) != NULL ||
2275                 !smack_label_is_valid(subject) ||
2276                 !smack_label_is_valid(object))
2277         {
2278                 C_LOGE("Incorrect rule format: %s", rule);
2279                 return PC_ERR_INVALID_PARAM;
2280         }
2281
2282         if (smack_accesses_add_modify(accesses, subject, object, access, "")) {
2283                 C_LOGE("smack_accesses_add_modify failed");
2284                 return PC_ERR_INVALID_OPERATION;
2285         }
2286         return PC_OPERATION_SUCCESS ;
2287 }
2288
2289 static int parse_and_save_rules(const char** smack_rules,
2290                 struct smack_accesses* accesses, const char* feature_file) {
2291         SECURE_C_LOGD("Entering function: %s. Params: feature_file=%s",
2292                                 __func__, feature_file);
2293
2294         size_t i = 0;
2295         int fd = 0;
2296         int ret = PC_OPERATION_SUCCESS;
2297         char* tmp = NULL;
2298
2299         for (i = 0; smack_rules[i] != NULL ; i++) {
2300                 // ignore empty lines
2301                 if (strspn(smack_rules[i], " \t\n") == strlen(smack_rules[i]))
2302                         continue;
2303
2304                 tmp = strdup(smack_rules[i]);
2305                 ret = validate_and_add_rule(tmp, accesses);
2306                 free(tmp);
2307                 if (ret != PC_OPERATION_SUCCESS )
2308                         return ret;
2309         }
2310
2311         // save to file
2312         fd = open(feature_file, O_CREAT | O_WRONLY, 0644);
2313         if (fd == -1) {
2314                 SECURE_C_LOGE("Unable to create file %s. (error: %s)", feature_file, strerror(errno));
2315                 return PC_ERR_FILE_OPERATION;
2316         }
2317
2318         ret = save_rules(fd, accesses);
2319         close(fd);
2320         return ret;
2321 }
2322
2323 static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
2324         SECURE_C_LOGD("Entering function: %s.", __func__);
2325         int ret = PC_OPERATION_SUCCESS;
2326         int written = 0;
2327         size_t i = 0;
2328
2329         if (file == NULL) {
2330                 C_LOGE("Unable to create file. Error: %s", strerror(errno));
2331                 return PC_ERR_FILE_OPERATION;   // TODO remove smack accesses?
2332         }
2333
2334         if(-1 == fchmod(fileno(file), 0644)) {
2335                 C_LOGE("Unable to chmod file. Error: %s", strerror(errno));
2336                 return PC_ERR_FILE_OPERATION;
2337         }
2338
2339         for (i = 0; i < list_size ; ++i) {
2340                 written = fprintf(file, "%u\n", list_of_db_gids[i]);
2341                 if (written <= 0) {
2342                         C_LOGE("fprintf failed for file. Error: %s", strerror(errno));
2343                         ret = PC_ERR_FILE_OPERATION;
2344                         break;
2345                 }
2346         }
2347         return ret;
2348 }
2349
2350 API int add_api_feature(app_type_t app_type,
2351                         const char* api_feature_name,
2352                         const char** smack_rules,
2353                         const gid_t* list_of_db_gids,
2354                         size_t list_size)//deprecated
2355 {
2356         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
2357                                 __func__, app_type, api_feature_name);
2358
2359     return perm_add_api_feature(app_type, api_feature_name, smack_rules, list_of_db_gids, list_size);
2360 }
2361
2362 API int perm_add_api_feature(app_type_t app_type,
2363                                                 const char* api_feature_name,
2364                                                 const char** smack_rules,
2365                                                 const gid_t* list_of_db_gids,
2366                                                 size_t list_size) {
2367         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
2368                                 __func__, app_type, api_feature_name);
2369
2370         int ret = PC_OPERATION_SUCCESS;
2371         char* smack_file AUTO_FREE;
2372         char* dac_file AUTO_FREE;
2373         struct smack_accesses* accesses = NULL;
2374         FILE* file = NULL;
2375
2376         // TODO check process capabilities
2377
2378         // get feature SMACK file name
2379         ret = perm_file_path(&smack_file, app_type, api_feature_name, ".smack", 0);
2380         if (ret != PC_OPERATION_SUCCESS || !smack_file ) {
2381                 C_LOGE("perm_file_path failed.");
2382                 return ret;
2383         }
2384
2385         // check if feature exists
2386         if (file_exists(smack_file)) {
2387                 C_LOGE("Feature file %s already exists", smack_file);
2388                 return PC_ERR_INVALID_PARAM;
2389         }
2390
2391         // check .dac existence only if gids are supported
2392         if (list_of_db_gids && list_size > 0) {
2393                 // get feature DAC file name
2394                 ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac", 0);
2395                 if (ret != PC_OPERATION_SUCCESS || !dac_file ) {
2396                         C_LOGE("perm_file_path failed.");
2397                         return ret;
2398                 }
2399
2400                 // check if feature exists
2401                 if (file_exists(dac_file)) {
2402                         C_LOGE("Feature file %s already exists", dac_file);
2403                         return PC_ERR_INVALID_PARAM;
2404                 }
2405         }
2406
2407         // parse & save rules
2408         if (smack_rules) {
2409                 if (smack_accesses_new(&accesses)) {
2410                         C_LOGE("smack_acceses_new failed");
2411                         return PC_ERR_MEM_OPERATION;
2412                 }
2413
2414                 ret = parse_and_save_rules(smack_rules, accesses, smack_file);
2415                 smack_accesses_free(accesses);
2416         }
2417
2418         // go through gid list
2419         if (ret == PC_OPERATION_SUCCESS && list_of_db_gids && list_size > 0) {
2420                 // save to file
2421                 SECURE_C_LOGD("Opening file %s.", dac_file);
2422                 file = fopen(dac_file, "w+");
2423                 ret = save_gids(file, list_of_db_gids, list_size);
2424                 fclose(file);
2425         }
2426
2427         // remove both files in case of failure
2428         if (ret != PC_OPERATION_SUCCESS) {
2429                 unlink(smack_file);
2430                 if (dac_file) {
2431                         unlink(dac_file);
2432                 }
2433         }
2434
2435         return ret;
2436 }
2437
2438 /**
2439  * This function is marked as deprecated and will be removed
2440  */
2441 API int app_register_av(const char* app_av_id)//deprecated
2442 {
2443         SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s",
2444                                 __func__, app_av_id);
2445
2446         int ret;
2447         int fd AUTO_CLOSE;
2448         char* smack_path AUTO_FREE;
2449         struct smack_accesses* smack AUTO_SMACK_FREE;
2450
2451         if(app_av_id == NULL) {
2452                 C_LOGE("Invalid param app_av_id.");
2453                 return PC_ERR_INVALID_PARAM;
2454         }
2455
2456         ret = load_smack_from_file(app_av_id, &smack, &fd, &smack_path);
2457         if (ret != PC_OPERATION_SUCCESS ) {
2458                 C_LOGE("load_smack_from_file failed");
2459                 return ret;
2460         }
2461
2462         ret = app_register_av_internal(app_av_id, smack);
2463         if (PC_OPERATION_SUCCESS != ret) {
2464                 C_LOGE("app_register_av_internal failed");
2465                 return ret;
2466         }
2467
2468         // Add permisions from OSP_antivirus.smack file
2469         ret = perm_to_smack(smack, app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
2470         if (PC_OPERATION_SUCCESS != ret) {
2471                 C_LOGE("perm_to_smack failed");
2472                 return ret;
2473         }
2474
2475         // Add permisions from OSP_antivirus.dac file
2476         ret = perm_to_dac(app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
2477         if (ret != PC_OPERATION_SUCCESS) {
2478                 C_LOGE("perm_to_dac failed");
2479                 return ret;
2480         }
2481
2482         if (have_smack() && smack_accesses_apply(smack)) {
2483                 C_LOGE("smack_accesses_apply failed");
2484                 ret = PC_ERR_INVALID_OPERATION;
2485                 return ret;
2486         }
2487
2488         if (smack_accesses_save(smack, fd)) {
2489                 C_LOGE("smack_accesses_save failed");
2490                 ret = PC_ERR_INVALID_OPERATION;
2491                 return ret;
2492         }
2493
2494         return ret;
2495 }