Fix unwanted differences between SLP and RSA repositories.
[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                 were_rules_loaded = check_if_rules_were_loaded(smack_label);
581                 if (were_rules_loaded < 0) {
582                         C_LOGE("check_if_rules_was_loaded failed.");
583                         return PC_ERR_INVALID_OPERATION;
584                 }
585                 if (!were_rules_loaded) { // first run of application
586                         C_LOGD("This is first run of this application. Adding SMACK rules.");
587                         ret = add_app_first_run_rules(smack_label);
588                         if (ret != PC_OPERATION_SUCCESS ) {
589                                 C_LOGW("add_app_first_run_rules failed");
590                                 // should we return here with error code?
591                         }
592                         mark_rules_as_loaded(smack_label);
593                 }
594
595                 ret = set_smack_for_self(smack_label);
596                 if (ret != PC_OPERATION_SUCCESS)
597                         return ret;
598         }
599
600         if (path != NULL && !have_smack()) {
601                 ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
602                 if (ret != PC_OPERATION_SUCCESS)
603                         return ret;
604         }
605
606         return set_dac(smack_label, name);
607 }
608
609 API int set_privilege(const char* pkg_name)//deprecated
610 {
611         SECURE_C_LOGD("Entering function: %s. Params: pkg_name=%s",
612                                 __func__, pkg_name);
613
614         return perm_app_set_privilege(pkg_name, NULL, NULL);
615 }
616
617 static inline const char* app_type_name(app_type_t app_type)
618 {
619         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
620                                 __func__, app_type);
621
622         switch (app_type) {
623         case APP_TYPE_WGT:
624                 C_LOGD("App type = APP_TYPE_WGT");
625                 return "WRT";
626         case APP_TYPE_OSP:
627                 C_LOGD("App type = APP_TYPE_OSP");
628                 return "OSP";
629         case APP_TYPE_WGT_PARTNER:
630                 C_LOGD("App type = APP_TYPE_WGT_PARTNER");
631                 return "WRT_partner";
632         case APP_TYPE_WGT_PLATFORM:
633                 C_LOGD("App type = APP_TYPE_WGT_PLATFORM");
634                 return "WRT_platform";
635         case APP_TYPE_OSP_PARTNER:
636                 C_LOGD("App type = APP_TYPE_OSP_PARTNER");
637                 return "OSP_partner";
638         case APP_TYPE_OSP_PLATFORM:
639                 C_LOGD("App type = APP_TYPE_OSP_PLATFORM");
640                 return "OSP_platform";
641         case APP_TYPE_EFL:
642                 return "EFL";
643         default:
644                 C_LOGD("App type = other");
645                 return NULL;
646         }
647 }
648
649 static inline const char* app_type_group_name(app_type_t app_type)
650 {
651         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
652                                 __func__, app_type);
653
654         switch (app_type) {
655         case APP_TYPE_WGT:
656         case APP_TYPE_WGT_PARTNER:
657         case APP_TYPE_WGT_PLATFORM:
658                 C_LOGD("App type group name = WRT");
659                 return "WRT";
660         case APP_TYPE_OSP:
661         case APP_TYPE_OSP_PARTNER:
662         case APP_TYPE_OSP_PLATFORM:
663                 C_LOGD("App type group name = OST");
664                 return "OSP";
665         case APP_TYPE_EFL:
666                 return "EFL";
667         default:
668                 return NULL;
669         }
670 }
671
672 /**
673  * This function changes permission URI to basename for file name.
674  * For e.g. from http://tizen.org/privilege/contact.read will be
675  * created basename : org.tizen.privilege.contact.read
676  */
677
678 static int base_name_from_perm(const char *perm, char **name)
679 {
680         SECURE_C_LOGD("Entering function: %s. Params: perm=%s",
681                                 __func__, perm);
682
683         iri_t *ip = NULL;
684         char *host_dot = NULL;
685         char *rest_slash = NULL;
686         int ret;
687
688         ip = iri_parse(perm);
689         if (ip == NULL || ip->host == NULL) {
690                 SECURE_C_LOGE("Bad permission format : %s", perm);
691                 iri_destroy(ip);
692                 return PC_ERR_INVALID_PARAM;
693         }
694
695         if (ip->path == NULL) {
696                 ip->path = ip->host;
697                 ip->host = NULL;
698         }
699
700         if (ip->host) {
701                 host_dot = strrchr(ip->host, '.');
702                 if (host_dot) {
703                         *host_dot = '\0';
704                         ++host_dot;
705                 }
706         }
707
708         while ((rest_slash = strchr(ip->path, '/'))) {
709                 *rest_slash = '.';
710         }
711
712         ret = asprintf(name, "%s%s%s%s",
713                         host_dot ? host_dot : "", host_dot ? "." : "",
714                         ip->host ? ip->host : "", ip->path);
715         if (ret == -1) {
716                 C_LOGE("asprintf failed");
717                 iri_destroy(ip);
718                 return PC_ERR_MEM_OPERATION;
719         }
720
721         iri_destroy(ip);
722         return PC_OPERATION_SUCCESS;
723 }
724
725 static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix, bool is_early)
726 {
727         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, perm=%s, suffix=%s, is_early=%d",
728                                 __func__, app_type, perm, suffix, is_early);
729
730         const char* app_type_prefix = NULL;
731         char* perm_basename = NULL;
732         int ret = 0;
733
734         if (perm == NULL || strlen(perm) == 0) {
735                 C_LOGE("Empty permission name.");
736                 return PC_ERR_INVALID_PARAM;
737         }
738
739         app_type_prefix = app_type_group_name(app_type);
740
741         ret = base_name_from_perm(perm, &perm_basename);
742         if (ret != PC_OPERATION_SUCCESS) {
743                 C_LOGE("Couldn't get permission basename.");
744                 return ret;
745         }
746
747         if (is_early) {
748                 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s%s",
749                 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
750                 perm_basename, "_early", suffix);
751         }
752         else {
753                 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
754                 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
755                 perm_basename, suffix);
756         }
757         if (ret == -1) {
758                 C_LOGE("asprintf failed.");
759                 return PC_ERR_MEM_OPERATION;
760         }
761
762         C_LOGD("Path=%s", *path);
763
764         return PC_OPERATION_SUCCESS;
765 }
766
767 static int perm_to_smack_from_file(struct smack_accesses* smack,
768                                            const char* app_label,
769                                            const char* app_label_template,
770                                            const char* rules_file_path)
771 {
772         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_label_template=%s, rules_file_path=%s",
773                                 __func__, app_label, app_label_template, rules_file_path);
774
775         char smack_subject[SMACK_LABEL_LEN + 1];
776         char smack_object[SMACK_LABEL_LEN + 1];
777         char smack_accesses[ACC_LEN + 1];
778         FILE* file AUTO_FCLOSE;
779
780         SECURE_C_LOGD("Opening file %s.", rules_file_path);
781         file = fopen(rules_file_path, "r");
782         if (file == NULL) {
783                 SECURE_C_LOGW("fopen failed [%s] %s", rules_file_path, strerror(errno));
784                 return PC_OPERATION_SUCCESS;
785         }
786
787         while (fscanf(file,
788                         "%" TOSTRING(SMACK_LABEL_LEN) "s "
789                         "%" TOSTRING(SMACK_LABEL_LEN) "s "
790                         "%" TOSTRING(ACC_LEN) "s\n",
791                         smack_subject, smack_object, smack_accesses) == 3) {
792                 if (!strcmp(smack_subject, app_label_template))
793                         strcpy(smack_subject, app_label);
794
795                 if (!strcmp(smack_object, app_label_template))
796                         strcpy(smack_object, app_label);
797
798                 C_LOGD("smack_accesses_add_modify (subject: %s, object: %s, access: %s)", smack_subject, smack_object, smack_accesses);
799                 if (smack_accesses_add_modify(smack, smack_subject, smack_object, smack_accesses, "") != 0) {
800                         C_LOGE("smack_accesses_add_modify failed.");
801                         return PC_ERR_INVALID_OPERATION;
802                 }
803         }
804
805         return PC_OPERATION_SUCCESS;
806 }
807
808 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)
809 {
810         C_LOGD("Enter function: %s", __func__);
811
812         int ret;
813         char* path AUTO_FREE;
814
815         // get file name for permission (devcap)
816         ret = perm_file_path(&path, app_type, perm, ".smack", is_early);
817         if (ret != PC_OPERATION_SUCCESS) {
818                 C_LOGD("No smack config file for permission %s", perm);
819                 return ret;
820         }
821
822         ret = perm_to_smack_from_file(smack, app_label, SMACK_APP_LABEL_TEMPLATE, path);
823         if (ret != PC_OPERATION_SUCCESS) {
824                 return ret;
825         }
826
827         return PC_OPERATION_SUCCESS;
828 }
829
830 static int perm_to_smack_early(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
831 {
832         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
833                                 __func__, app_label, app_type, perm);
834
835         return perm_to_smack_generic(smack, app_label, app_type, perm, 1);
836 }
837
838 static int perm_to_smack(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
839 {
840         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
841                                 __func__, app_label, app_type, perm);
842
843         return perm_to_smack_generic(smack, app_label, app_type, perm, 0);
844 }
845
846 static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
847 {
848         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
849                                 __func__, app_label, app_type, perm);
850
851         int ret;
852         char* path AUTO_FREE;
853         FILE* file AUTO_FCLOSE;
854         int gid;
855
856         ret = perm_file_path(&path, app_type, perm, ".dac", 0);
857         if (ret != PC_OPERATION_SUCCESS) {
858                 C_LOGD("No dac config file for permission %s", perm);
859                 return ret;
860         }
861
862         SECURE_C_LOGD("Opening file %s.", path);
863         file = fopen(path, "r");
864         if (file == NULL) {
865                 C_LOGW("fopen failed.");
866                 return PC_OPERATION_SUCCESS;
867         }
868
869         while (fscanf(file, "%d\n", &gid) == 1) {
870                 SECURE_C_LOGD("Adding app_id %s to group %d", app_label, gid);
871                 ret = add_app_gid(app_label, gid);
872                 if (ret != PC_OPERATION_SUCCESS) {
873                         C_LOGE("add_app_gid failed");
874                         return ret;
875                 }
876         }
877
878         return PC_OPERATION_SUCCESS;
879 }
880
881 static int label_all(const FTSENT* ftsent)
882 {
883         SECURE_C_LOGD("Entering function: %s.", __func__);
884
885         return DECISION_LABEL;
886 }
887
888 static int label_execs(const FTSENT* ftsent)
889 {
890         SECURE_C_LOGD("Entering function: %s.", __func__);
891
892         C_LOGD("Mode = %d", ftsent->fts_statp->st_mode);
893         // label only regular executable files
894         if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
895                 return DECISION_LABEL;
896         return DECISION_SKIP;
897 }
898
899 static int label_dirs(const FTSENT* ftsent)
900 {
901         SECURE_C_LOGD("Entering function: %s.", __func__);
902
903         // label only directories
904         if (S_ISDIR(ftsent->fts_statp->st_mode))
905                 return DECISION_LABEL;
906         return DECISION_SKIP;
907 }
908
909 static int label_links_to_execs(const FTSENT* ftsent)
910 {
911         SECURE_C_LOGD("Entering function: %s.", __func__);
912
913         struct stat buf;
914         char* target AUTO_FREE;
915
916         // check if it's a link
917         if ( !S_ISLNK(ftsent->fts_statp->st_mode))
918                 return DECISION_SKIP;
919
920         target = realpath(ftsent->fts_path, NULL);
921         if (!target) {
922                 SECURE_C_LOGE("Getting link target for %s failed (Error = %s)", ftsent->fts_path, strerror(errno));
923                 return PC_ERR_FILE_OPERATION;
924         }
925         if (-1 == stat(target, &buf)) {
926                 SECURE_C_LOGE("stat failed for %s (Error = %s", target, strerror(errno));
927                 return PC_ERR_FILE_OPERATION;
928         }
929         // skip if link target is not a regular executable file
930         if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
931                 SECURE_C_LOGD("%s is not a regular executable file. Skipping.", target);
932                 return DECISION_SKIP;
933         }
934
935         return DECISION_LABEL;
936 }
937
938 static int dir_set_smack_r(const char *path, const char* label,
939                 enum smack_label_type type, label_decision_fn fn)
940 {
941         SECURE_C_LOGD("Entering function: %s. Params: path=%s, label=%s, type=%d",
942                                 __func__, path, label, type);
943
944         const char* path_argv[] = {path, NULL};
945         FTS *fts AUTO_FTS_CLOSE;
946         FTSENT *ftsent;
947         int ret;
948
949         fts = fts_open((char * const *) path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
950         if (fts == NULL) {
951                 C_LOGE("fts_open failed.");
952                 return PC_ERR_FILE_OPERATION;
953         }
954
955         while ((ftsent = fts_read(fts)) != NULL) {
956                 /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
957                 if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
958                         C_LOGE("FTS_ERR error or failed stat(2) (FTS_NS)");
959                         return PC_ERR_FILE_OPERATION;
960                 }
961
962                 ret = fn(ftsent);
963                 if (ret < 0) {
964                         C_LOGE("fn(ftsent) failed.");
965                         return ret;
966                 }
967
968                 if (ret == DECISION_LABEL) {
969                         C_LOGD("smack_lsetlabel (label: %s (type: %d), path: %s)", label, type, ftsent->fts_path);
970                         if (smack_lsetlabel(ftsent->fts_path, label, type) != 0) {
971                                 C_LOGE("smack_lsetlabel failed.");
972                                 return PC_ERR_FILE_OPERATION;
973                         }
974                 }
975         }
976
977         /* If last call to fts_read() set errno, we need to return error. */
978         if (errno != 0) {
979                 C_LOGE("Last errno from fts_read: %s", strerror(errno));
980                 return PC_ERR_FILE_OPERATION;
981         }
982         return PC_OPERATION_SUCCESS;
983 }
984
985 API char* app_id_from_socket(int sockfd)//deprecated
986 {
987         SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
988                                 __func__, sockfd);
989
990     return perm_app_id_from_socket(sockfd);
991 }
992
993 API char* perm_app_id_from_socket(int sockfd)
994 {
995         SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
996                                 __func__, sockfd);
997
998         if (!have_smack()) {
999                 C_LOGD("No SMACK. Returning NULL.");
1000                 return NULL;
1001         }
1002
1003         char* app_id;
1004         int ret;
1005
1006         ret = smack_new_label_from_socket(sockfd, &app_id);
1007         if (ret < 0) {
1008                 C_LOGE("smack_new_label_from_socket failed");
1009                 return NULL;
1010         }
1011
1012         SECURE_C_LOGD("app_id = %s", app_id);
1013
1014         return app_id;
1015 }
1016
1017 static int app_add_rule(const char *app_id, const char *object, const char *perm)
1018 {
1019         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, object=%s, perm=%s",
1020                                 __func__, app_id, object, perm);
1021
1022         int ret;
1023         int fd AUTO_CLOSE;
1024         char *smack_path AUTO_FREE;
1025         struct smack_accesses* smack AUTO_SMACK_FREE;
1026
1027         ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
1028         if (ret != PC_OPERATION_SUCCESS) {
1029                 C_LOGE("load_smack_from_file failed.");
1030                 return ret;
1031         }
1032
1033         ret = smack_accesses_add_modify(smack, app_id, object, perm, "");
1034         if (ret == -1) {
1035                 C_LOGE("smack_accesses_add_modify failed.");
1036                 return PC_ERR_INVALID_OPERATION;
1037         }
1038
1039         if (have_smack() && smack_accesses_apply(smack)) {
1040                 C_LOGE("smack_accesses_apply failed.");
1041                 return PC_ERR_INVALID_OPERATION;
1042         }
1043
1044         if (smack_accesses_save(smack, fd)) {
1045                 C_LOGE("smack_accesses_save failed.");
1046                 return PC_ERR_INVALID_OPERATION;
1047         }
1048
1049         return PC_OPERATION_SUCCESS;
1050 }
1051
1052
1053 static int
1054 app_register_appsetting(const char *app_id, struct smack_accesses *smack)
1055 {
1056         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1057                                 __func__, app_id);
1058
1059         int ret;
1060         int i;
1061
1062         char **label_app_list AUTO_FREE;
1063         char **label_dir_list AUTO_FREE;
1064         int app_list_len = 0;
1065         int dir_list_len = 0;
1066
1067         if (!smack_label_is_valid(app_id)) {
1068                 C_LOGE("Invalid param app_id.");
1069                 return PC_ERR_INVALID_PARAM;
1070         }
1071
1072         /* writing appsetting_id (app_id) to "database"*/
1073         ret = add_appsetting_id_to_databse(app_id);
1074         if (ret != PC_OPERATION_SUCCESS)
1075                 goto out;
1076
1077
1078         /* Reading labels of all installed apps from "database"*/
1079         ret = get_all_apps_ids(&label_app_list, &app_list_len);
1080         if (ret != PC_OPERATION_SUCCESS) {
1081                 C_LOGE("Error while getting data from database");
1082                 goto out;
1083         }
1084
1085         /*Add smack rules with rx access to each app*/
1086         for (i = 0; i < app_list_len; ++i) {
1087                 C_LOGD("Appsetting: applying rx rule for %s", label_app_list[i]);
1088                 if (smack_accesses_add_modify(smack, app_id,
1089                                 label_app_list[i], "rx", "") == -1) {
1090                         C_LOGE("smack_accesses_add_modify failed.");
1091                         ret = PC_ERR_INVALID_OPERATION;
1092                         goto out;
1093                 }
1094         }
1095
1096         /* Reading labels of all registered settings dirs from "database"*/
1097         ret = get_all_settings_dir_ids(
1098                         &label_dir_list, &dir_list_len);
1099         if (ret != PC_OPERATION_SUCCESS) {
1100                 C_LOGE("Error while getting data from database");
1101                 goto out;
1102         }
1103         /*Add smack rules with rwx access to each app*/
1104         for (i = 0; i < dir_list_len; ++i) {
1105                 C_LOGD("Appsetting: applying rwx rule for %s", label_dir_list[i]);
1106                 if (smack_accesses_add_modify(smack, app_id,
1107                                 label_dir_list[i], "rwx", "") == -1) {
1108                         C_LOGE("smack_accesses_add_modify failed.");
1109                         ret = PC_ERR_INVALID_OPERATION;
1110                         goto out;
1111                         /* Should we abort adding rules if
1112                          * smack_accesses_add_modify fails once?*/
1113                 }
1114         }
1115
1116         out:
1117         for (i = 0; i < app_list_len; ++i) {
1118                 free(label_app_list[i]);
1119         }
1120         for (i = 0; i < dir_list_len; ++i) {
1121                 free(label_dir_list[i]);
1122         }
1123
1124         return ret;
1125 }
1126
1127 static int app_register_av_internal(const char *app_av_id, struct smack_accesses* smack)
1128 {
1129         SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s.",
1130                                 __func__, app_av_id);
1131
1132         int ret;
1133         int i;
1134
1135         char** smack_label_app_list AUTO_FREE;
1136         int smack_label_app_list_len = 0;
1137
1138         if (!smack_label_is_valid(app_av_id)) {
1139                 C_LOGE("Invalid param app_av_id.");
1140                 return PC_ERR_INVALID_PARAM;
1141         }
1142
1143         if(smack == NULL) {
1144                 C_LOGE("Invalid param smack (NULL).");
1145                 return PC_ERR_INVALID_PARAM;
1146         }
1147
1148         // writing anti_virus_id (app_av_id) to "database"
1149         ret = add_av_id_to_databse(app_av_id);
1150         if (ret != PC_OPERATION_SUCCESS )
1151                 goto out;
1152
1153         // Reading labels of all installed apps from "database"
1154         ret = get_all_apps_ids(&smack_label_app_list, &smack_label_app_list_len);
1155         if (ret != PC_OPERATION_SUCCESS ) {
1156                 C_LOGE("Error while geting data from database.");
1157                 goto out;
1158         }
1159         for (i = 0; i < smack_label_app_list_len; ++i) {
1160                 SECURE_C_LOGD("Applying rwx rule for %s", smack_label_app_list[i]);
1161                 if (smack_accesses_add_modify(smack, app_av_id, smack_label_app_list[i], "wrx", "") == -1) {
1162                         C_LOGE("smack_accesses_add_modify failed.");
1163                         ret = PC_ERR_INVALID_OPERATION;
1164                         goto out;
1165                         // Should we abort adding rules once smack_accesses_add_modify will fail?
1166                 }
1167         }
1168
1169 out:
1170         for (i = 0; i < smack_label_app_list_len; ++i) {
1171                 free(smack_label_app_list[i]);
1172         }
1173
1174         return ret;
1175 }
1176
1177 /**
1178  *  This function will find labels of all anti viruses in database
1179  *  and for all of them will add a rule "anti_virus_label app_id rwx".
1180  *  This should be called in app_install function.
1181  */
1182 static int register_app_for_av(const char * app_id)
1183 {
1184         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s.",
1185                                 __func__, app_id);
1186
1187         int ret, i;
1188         char** smack_label_av_list AUTO_FREE;
1189         int smack_label_av_list_len = 0;
1190
1191         // Reading labels of all installed anti viruses from "database"
1192         ret = get_all_avs_ids(&smack_label_av_list, &smack_label_av_list_len);
1193         if (ret != PC_OPERATION_SUCCESS) {
1194                 C_LOGE("Error while geting data from database.");
1195                 return ret;
1196         }
1197
1198         // for each anti-virus label put rule: "anti_virus_label app_id rwx"
1199         for (i = 0; i < smack_label_av_list_len; ++i) {
1200                 SECURE_C_LOGD("Antivirus: app_add_rule (%s, %s rx)", smack_label_av_list[i], app_id);
1201                 if (strcmp(app_id, smack_label_av_list[i])==0) {
1202                         SECURE_C_LOGW("Trying to add antivirus rule for self. Skipping");
1203                         continue;
1204                 }
1205                 ret = app_add_rule(smack_label_av_list[i], app_id, "wrx");
1206                 if (ret != PC_OPERATION_SUCCESS) {
1207                         C_LOGE("app_add_rule failed.");
1208                         goto out;
1209                 }
1210
1211                 free(smack_label_av_list[i]);
1212         }
1213
1214         ret = PC_OPERATION_SUCCESS;
1215
1216 out:
1217         // If something failed, then no entry of smack_label_av_list[i]
1218         // was deallocated. They all must be freed.
1219         for(; i<smack_label_av_list_len; ++i) {
1220                 free(smack_label_av_list[i]);
1221         }
1222
1223         return ret;
1224 }
1225
1226 /**
1227  *  This function will find labels of all setting applications in database
1228  *  and for all of them will add a rule "appsetting_id app_id rwx".
1229  *  This should be called in app_install function.
1230  */
1231 static int register_app_for_appsetting(const char *app_id)
1232 {
1233         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1234                                 __func__, app_id);
1235
1236         int ret, i;
1237         char **smack_label_list AUTO_FREE;
1238         int smack_label_list_len = 0;
1239
1240         /* Reading labels of all installed setting managers from "database"*/
1241         ret = get_all_appsetting_ids(&smack_label_list, &smack_label_list_len);
1242         if (ret != PC_OPERATION_SUCCESS) {
1243                 C_LOGE("Error while geting data from database.");
1244                 return ret;
1245         }
1246
1247         /* for each appsetting put rule: "appsetting_id app_id rx"*/
1248         for (i = 0; i < smack_label_list_len; ++i) {
1249                 SECURE_C_LOGD("Appsetting: app_add_rule (%s, %s rx)", smack_label_list[i], app_id);
1250                 if (strcmp(app_id, smack_label_list[i])==0) {
1251                         SECURE_C_LOGW("Trying to add setting rule for self. Skipping");
1252                         continue;
1253                 }
1254
1255                 ret = app_add_rule(smack_label_list[i], app_id, "rx");
1256                 if (ret != PC_OPERATION_SUCCESS) {
1257                         C_LOGE("app_add_rule failed");
1258                         goto out;
1259                 }
1260
1261                 free(smack_label_list[i]);
1262         }
1263
1264         ret = PC_OPERATION_SUCCESS;
1265
1266 out:
1267         /* If something failed, then no entry of smack_label_list[i]
1268          was deallocated. They all must be freed.*/
1269         for (; i < smack_label_list_len; ++i) {
1270                 free(smack_label_list[i]);
1271         }
1272
1273         return ret;
1274 }
1275
1276
1277 /**
1278  *  This function will grant app_id rx access to all public directories and
1279  *  files previously designated by app_setup_path(APP_PATH_PUBLIC_RO)
1280  *  This should be called in app_install function.
1281  */
1282 static int register_app_for_public_dirs(const char *app_id, struct smack_accesses *smack)
1283 {
1284         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1285                                 __func__, app_id);
1286         int ret, i;
1287         char **public_dirs AUTO_FREE;
1288         int public_dirs_cnt = 0;
1289
1290         ret = db_get_public_dirs(&public_dirs, &public_dirs_cnt);
1291         if (ret != PC_OPERATION_SUCCESS) {
1292                 C_LOGE("Error while getting data from database");
1293                 return ret;
1294         }
1295
1296         for (i = 0; i < public_dirs_cnt; ++i) {
1297                 SECURE_C_LOGD("Allowing app %s to access public path %s", app_id, public_dirs[i]);
1298                 if (smack_accesses_add_modify(smack, app_id, public_dirs[i], "rx", "")) {
1299                         C_LOGE("app_add_rule_modify failed");
1300                         while (i < public_dirs_cnt)
1301                                 free(public_dirs[i++]);
1302                         return PC_ERR_INVALID_OPERATION;
1303                 }
1304                 free(public_dirs[i]);
1305         }
1306
1307         return PC_OPERATION_SUCCESS;
1308 }
1309
1310 static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
1311 {
1312         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
1313                                 __func__, app_id, app_type, permanent);
1314
1315         int i, ret;
1316         char* smack_path AUTO_FREE;
1317         char* smack_path_early AUTO_FREE;
1318         int fd AUTO_CLOSE;
1319         int fd_early AUTO_CLOSE;
1320         struct smack_accesses *smack AUTO_SMACK_FREE;
1321         struct smack_accesses *smack_early AUTO_SMACK_FREE;
1322         const char* base_perm = NULL;
1323
1324         if (!smack_label_is_valid(app_id)) {
1325                 C_LOGE("Invalid param app_id.");
1326                 return PC_ERR_INVALID_PARAM;
1327         }
1328
1329         if(perm_list == NULL) {
1330                 C_LOGE("Invalid perm_list (NULL).");
1331                 return PC_ERR_INVALID_PARAM;
1332         }
1333
1334         ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
1335         if (ret != PC_OPERATION_SUCCESS) {
1336                 C_LOGE("load_smack_from_file failed");
1337                 return ret;
1338         }
1339
1340         ret = load_smack_from_file_early(app_id, &smack_early, &fd_early, &smack_path_early);
1341         if (ret != PC_OPERATION_SUCCESS) {
1342                 C_LOGE("load_smack_from_file failed");
1343                 return ret;
1344         }
1345
1346         /* Implicitly enable base permission for an app_type */
1347         base_perm = app_type_name(app_type);
1348         if (base_perm) {
1349                 SECURE_C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
1350                 ret = perm_to_smack(smack, app_id, APP_TYPE_OTHER, base_perm);
1351                 if (ret != PC_OPERATION_SUCCESS){
1352                         C_LOGE("perm_to_smack failed");
1353                         return ret;
1354                 }
1355
1356                 // Add early permission - such permissions should be enabled right after system boot
1357                 SECURE_C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
1358                 ret = perm_to_smack_early(smack_early, app_id, APP_TYPE_OTHER, base_perm);
1359                 if (ret != PC_OPERATION_SUCCESS){
1360                         C_LOGE("perm_to_smack failed");
1361                         return ret;
1362                 }
1363
1364         }
1365         for (i = 0; perm_list[i] != NULL; ++i) {
1366                 SECURE_C_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]);
1367                 if (strcmp(perm_list[i], TIZEN_PRIVILEGE_ANTIVIRUS) == 0) {
1368                         ret = app_register_av_internal(app_id, smack);
1369                         if (ret != PC_OPERATION_SUCCESS) {
1370                                 C_LOGE("app_register_av_internal failed");
1371                                 return ret;
1372                         }
1373                 }
1374                 if (strcmp(perm_list[i], TIZEN_PRIVILEGE_APPSETTING) == 0) {
1375                         ret = app_register_appsetting(app_id, smack);
1376                         if (ret != PC_OPERATION_SUCCESS) {
1377                                 C_LOGE("app_register_appsetting failed");
1378                                 return ret;
1379                         }
1380                 }
1381
1382                 ret = perm_to_smack(smack, app_id, app_type, perm_list[i]);
1383                 if (ret != PC_OPERATION_SUCCESS){
1384                         C_LOGE("perm_to_smack failed");
1385                         return ret;
1386                 }
1387
1388                 ret = perm_to_smack_early(smack_early, app_id, app_type, perm_list[i]);
1389                 if (ret != PC_OPERATION_SUCCESS){
1390                         C_LOGE("perm_to_smack_early failed");
1391                         return ret;
1392                 }
1393
1394                 ret = perm_to_dac(app_id, app_type, perm_list[i]);
1395                 if (ret != PC_OPERATION_SUCCESS){
1396                         C_LOGE("perm_to_dac failed");
1397                         return ret;
1398                 }
1399         }
1400
1401         if (have_smack() && smack_accesses_apply(smack)) {
1402                 C_LOGE("smack_accesses_apply failed");
1403                 return PC_ERR_INVALID_OPERATION;
1404         }
1405
1406         if (have_smack() && smack_accesses_apply(smack_early)) {
1407                 C_LOGE("smack_accesses_apply (early) failed");
1408                 return PC_ERR_INVALID_OPERATION;
1409         }
1410
1411         if (permanent && smack_accesses_save(smack, fd)) {
1412                 C_LOGE("smack_accesses_save failed");
1413                 return PC_ERR_INVALID_OPERATION;
1414         }
1415
1416         if (permanent && smack_accesses_save(smack_early, fd_early)) {
1417                 C_LOGE("smack_accesses_save (early) failed");
1418                 return PC_ERR_INVALID_OPERATION;
1419         }
1420
1421         return PC_OPERATION_SUCCESS;
1422 }
1423
1424 API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
1425 {
1426         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1427                                 __func__, app_id);
1428
1429         return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
1430 }
1431
1432 API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
1433 {
1434         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1435                                 __func__, app_id);
1436
1437         return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
1438 }
1439
1440 API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
1441 {
1442         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
1443                                 __func__, pkg_id, app_type, persistent);
1444
1445         return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
1446 }
1447
1448 API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)
1449 {
1450         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
1451                                 __func__, pkg_id, app_type, persistent);
1452
1453         return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
1454 }
1455
1456 API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
1457 {
1458         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
1459                                 __func__, pkg_id, app_type);
1460
1461         return perm_app_disable_permissions(pkg_id, app_type, perm_list);
1462 }
1463
1464 /* FIXME: this function is only a stub */
1465 API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
1466 {
1467         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
1468                                 __func__, pkg_id, app_type);
1469
1470         return PC_OPERATION_SUCCESS;
1471 }
1472
1473 static int app_revoke_permissions_internal(const char* app_id, bool persistent)
1474 {
1475         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, persistent=%d",
1476                                 __func__, app_id, persistent);
1477
1478         char* smack_path AUTO_FREE;
1479         int ret;
1480         int fd AUTO_CLOSE;
1481         struct smack_accesses *smack AUTO_SMACK_FREE;
1482
1483         if (!smack_label_is_valid(app_id)) {
1484                 C_LOGE("Invalid param app_id.");
1485                 return PC_ERR_INVALID_PARAM;
1486         }
1487
1488         ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
1489         if (ret != PC_OPERATION_SUCCESS) {
1490                 C_LOGE("load_smack_from_file failed.");
1491                 return ret;
1492         }
1493
1494         if (have_smack() && smack_accesses_clear(smack)) {
1495                 ret = PC_ERR_INVALID_OPERATION;
1496                 C_LOGE("smack_accesses_clear failed.");
1497                 return ret;
1498         }
1499
1500         if (have_smack() && smack_revoke_subject(app_id)) {
1501                 ret = PC_ERR_INVALID_OPERATION;
1502                 C_LOGE("smack_revoke_subject failed.");
1503                 return ret;
1504         }
1505
1506         if (persistent && ftruncate(fd, 0) == -1)
1507                 C_LOGW("file truncation failed");
1508
1509         return PC_OPERATION_SUCCESS;
1510 }
1511
1512 API int app_revoke_permissions(const char* pkg_id)//deprecated
1513 {
1514         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
1515         return perm_app_revoke_permissions(pkg_id);
1516 }
1517
1518 API int perm_app_revoke_permissions(const char* pkg_id)
1519 {
1520         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
1521         int ret;
1522
1523         if (!smack_label_is_valid(pkg_id)) {
1524                 C_LOGE("Invalid param app_id.");
1525                 return PC_ERR_INVALID_PARAM;
1526         }
1527
1528         ret = app_revoke_permissions_internal(pkg_id, true);
1529         if (ret) {
1530                 C_LOGE("Revoking permissions failed.");
1531                 return ret;
1532         }
1533
1534         return PC_OPERATION_SUCCESS;
1535 }
1536
1537 API int app_reset_permissions(const char* pkg_id)//deprecated
1538 {
1539         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1540                                 __func__, pkg_id);
1541
1542         return perm_app_reset_permissions(pkg_id);
1543 }
1544
1545 API int perm_app_reset_permissions(const char* pkg_id)
1546 {
1547         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1548                                 __func__, pkg_id);
1549
1550         int ret;
1551
1552         if (!smack_label_is_valid(pkg_id)) {
1553                 C_LOGE("Invalid param pkg_id.");
1554                 return PC_ERR_INVALID_PARAM;
1555         }
1556
1557         ret = app_revoke_permissions_internal(pkg_id, false);
1558         if (ret) {
1559                 C_LOGE("Revoking permissions failed.");
1560                 return ret;
1561         }
1562
1563         /* Add empty permissions set to trigger re-read of rules */
1564         return perm_app_enable_permissions(pkg_id, APP_TYPE_OTHER, (const char*[]){NULL}, 0);
1565 }
1566
1567 API int app_label_dir(const char* label, const char* path)//deprecated
1568 {
1569         SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
1570                                 __func__, label, path);
1571
1572         int ret = PC_OPERATION_SUCCESS;
1573
1574         if(path == NULL) {
1575                 C_LOGE("Invalid argument path (NULL).");
1576                 return PC_ERR_INVALID_PARAM;
1577         }
1578
1579         if (!smack_label_is_valid(label)) {
1580                 C_LOGE("Invalid param label.");
1581                 return PC_ERR_INVALID_PARAM;
1582         }
1583
1584         //setting access label on everything in given directory and below
1585         ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
1586         if (PC_OPERATION_SUCCESS != ret)
1587         {
1588                 C_LOGE("dir_set_smack_r failed.");
1589                 return ret;
1590         }
1591
1592         //setting execute label for everything with permission to execute
1593         ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
1594         if (PC_OPERATION_SUCCESS != ret)
1595         {
1596                 C_LOGE("dir_set_smack_r failed.");
1597                 return ret;
1598         }
1599
1600         //setting execute label for everything with permission to execute
1601         ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
1602         return ret;
1603 }
1604
1605 int smack_get_access_new(const char* subject, const char* object, char** label)
1606 {
1607         SECURE_C_LOGD("Entering function: %s. Params: subject=%s, object=%s",
1608                                 __func__, subject, object);
1609         
1610         char buff[ACC_LEN] = {'r', 'w', 'x', 'a', 't', 'l'};
1611         char perm[2] = {'-'};
1612         int i;
1613
1614         if(!smack_label_is_valid(subject)) {
1615                 C_LOGE("Invalid param subject.");
1616                 return PC_ERR_INVALID_PARAM;
1617         }
1618
1619         if(!smack_label_is_valid(object)) {
1620                 C_LOGE("Invalid param object.");
1621                 return PC_ERR_INVALID_PARAM;
1622         }
1623
1624         if(!label) {
1625                 C_LOGE("Invalid param label (NULL).");
1626                 return PC_ERR_INVALID_PARAM;
1627         }
1628
1629         for (i=0; i<ACC_LEN; ++i) {
1630                 perm[0] = buff[i];
1631                 int ret = smack_have_access(subject, object, perm);
1632                 if (-1 == ret) {
1633                         C_LOGE("smack_have_access failed during %c check.", perm[0]);
1634                         return PC_ERR_INVALID_OPERATION;
1635                 }
1636                 if (0 == ret)
1637                         buff[i] = '-';
1638         }
1639
1640         *label = malloc(ACC_LEN+1);
1641         if (NULL == *label)
1642                 return PC_ERR_MEM_OPERATION;
1643
1644         memcpy(*label, buff, ACC_LEN);
1645         (*label)[ACC_LEN] = 0;
1646         return PC_OPERATION_SUCCESS;
1647 }
1648
1649 static int app_uninstall_remove_early_rules(const char *app_id)
1650 {
1651         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
1652                                 __func__, app_id);
1653
1654         int ret;
1655         int fd AUTO_CLOSE;
1656         int size;
1657         char tmp;
1658         char *data, *data_end;
1659         char *line_begin, *line_end, *write_pos;
1660         char subject[SMACK_LABEL_LEN + 1];
1661         char object[SMACK_LABEL_LEN + 1];
1662
1663         SECURE_C_LOGD("Opening file %s.", SMACK_STARTUP_RULES_FILE);
1664         fd = open(SMACK_STARTUP_RULES_FILE, O_RDWR);
1665         if (fd < 0) {
1666                 SECURE_C_LOGE("Unable to open file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
1667                 return PC_ERR_FILE_OPERATION;
1668         }
1669
1670         if (flock(fd, LOCK_EX)) {
1671                 SECURE_C_LOGE("flock failed, error %s", strerror(errno));
1672                 return PC_ERR_FILE_OPERATION;
1673         }
1674
1675         size = lseek(fd, 0, SEEK_END);
1676         if (size < 0) {
1677                 SECURE_C_LOGE("Unable to read file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
1678                 return PC_ERR_FILE_OPERATION;
1679         }
1680
1681         if (size == 0)
1682                 return PC_OPERATION_SUCCESS;
1683
1684         data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1685         if (data == MAP_FAILED) {
1686                 SECURE_C_LOGE("Unable to read file %s: %s", SMACK_STARTUP_RULES_FILE, strerror(errno));
1687                 return PC_ERR_FILE_OPERATION;
1688         }
1689         data_end = data + size;
1690
1691         line_begin = write_pos = data;
1692         while (line_begin < data_end) {
1693                 line_end = memchr(line_begin, '\n', data_end - line_begin);
1694                 if (line_end == NULL)
1695                         line_end = data_end - 1;
1696
1697                 tmp = *line_end;
1698                 *line_end = '\0';
1699                 SECURE_C_LOGD("Considering early rule: %s", line_begin);
1700
1701                 ret = sscanf(line_begin, "%" TOSTRING(SMACK_LABEL_LEN) "s %" TOSTRING(SMACK_LABEL_LEN) "s", subject, object);
1702                 if (ret != 2) {
1703                         C_LOGD("Rule format is invalid, skipping it.");
1704                         goto loop_next;
1705                 }
1706
1707                 if (!strcmp(subject, app_id) || !strcmp(object, app_id)) {
1708                         C_LOGD("Rule belongs to an app being removed, skipping it.");
1709                         goto loop_next;
1710                 }
1711
1712                 C_LOGD("Rule still needed, keeping it.");
1713                 *line_end = tmp;
1714                 if (write_pos != line_begin)
1715                         memcpy(write_pos, line_begin, line_end - line_begin + 1);
1716                 write_pos += (line_end - line_begin + 1);
1717
1718         loop_next:
1719                 *line_end = tmp;
1720                 line_begin = line_end + 1;
1721         }
1722
1723         munmap(data, size);
1724         ret = ftruncate(fd, write_pos - data);
1725         if (ret < 0) {
1726                 SECURE_C_LOGE("Unable to truncate file %s to %d bytes: %s", SMACK_STARTUP_RULES_FILE, write_pos, strerror(errno));
1727
1728                 return PC_ERR_FILE_OPERATION;
1729         }
1730
1731         return PC_OPERATION_SUCCESS;
1732 }
1733
1734 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
1735 {
1736         SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
1737                                 __func__, app_label, shared_label, path);
1738         int ret;
1739
1740         if(path == NULL) {
1741                 C_LOGE("Invalid param path.");
1742                 return PC_ERR_INVALID_PARAM;
1743         }
1744
1745         if(!smack_label_is_valid(app_label)) {
1746                 C_LOGE("Invalid param app_label");
1747                 return PC_ERR_INVALID_PARAM;
1748         }
1749
1750         if(!smack_label_is_valid(shared_label)) {
1751                 C_LOGE("Invalid param shared_label");
1752                 return PC_ERR_INVALID_PARAM;
1753         }
1754
1755         if (strcmp(app_label, shared_label) == 0) {
1756                 C_LOGE("app_label equals shared_label");
1757                 return PC_ERR_INVALID_PARAM;
1758         }
1759
1760         //setting label on everything in given directory and below
1761         ret = dir_set_smack_r(path, shared_label, SMACK_LABEL_ACCESS, label_all);
1762         if(ret != PC_OPERATION_SUCCESS){
1763                 C_LOGE("dir_set_smack_r failed.");
1764                 return ret;
1765         }
1766
1767         //setting transmute on dir
1768         ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, label_dirs);
1769         if (ret != PC_OPERATION_SUCCESS) {
1770                 C_LOGE("dir_set_smack_r failed");
1771                 return ret;
1772         }
1773
1774         ret = app_add_rule(app_label, shared_label, "rwxat");
1775         if (ret != PC_OPERATION_SUCCESS) {
1776                 C_LOGE("app_add_rule failed");
1777                 return ret;
1778         }
1779
1780         return PC_OPERATION_SUCCESS;
1781 }
1782
1783 API int add_shared_dir_readers(const char* shared_label, const char** app_list)//deprecated
1784 {
1785         SECURE_C_LOGD("Entering function: %s. Params: shared_label=%s",
1786                                 __func__, shared_label);
1787         int ret;
1788         int i;
1789
1790         if(app_list == NULL) {
1791                 C_LOGE("Invalid param app_list.");
1792                 return PC_ERR_INVALID_PARAM;
1793         }
1794
1795         if (!smack_label_is_valid(shared_label)) {
1796                 C_LOGE("Invalid param shared_label.");
1797                 return PC_ERR_INVALID_PARAM;
1798         }
1799
1800         for (i = 0; app_list[i] != NULL; i++) {
1801                 if (!smack_label_is_valid(app_list[i])) {
1802                         C_LOGE("Invalid %d element from param app_list.", i);
1803                         return PC_ERR_INVALID_PARAM;
1804                 }
1805
1806                 ret = app_add_rule(app_list[i], shared_label, "rx");
1807                 if (ret != PC_OPERATION_SUCCESS) {
1808                         C_LOGE("app_add_rule failed.");
1809                         return ret;
1810                 }
1811         }
1812
1813         return PC_OPERATION_SUCCESS;
1814 }
1815
1816 static char* smack_label_for_path(const char *app_id, const char *path)
1817 {
1818         SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, path=%s",
1819                                 __func__, app_id, path);
1820
1821         char *salt AUTO_FREE;
1822         char *label;
1823         char *x;
1824
1825         /* Prefix $1$ causes crypt() to use MD5 function */
1826         if (-1 == asprintf(&salt, "$1$%s", app_id)) {
1827                 C_LOGE("asprintf failed");
1828                 return NULL;
1829         }
1830
1831         label = crypt(path, salt);
1832         if (label == NULL) {
1833                 C_LOGE("crypt failed");
1834                 return NULL;
1835         }
1836
1837         /* crypt() output may contain slash character,
1838          * which is not legal in Smack labels */
1839         for (x = label; *x; ++x) {
1840                 if (*x == '/')
1841                         *x = '%';
1842         }
1843
1844         return label;
1845 }
1846 /*
1847  * This function should be called in perm_app_setup_path_internal().
1848  * After installation of new application (pkg_id) and labeling its shared directory (RW or RO),
1849  * all others apps installed on system should get rules to this shared directory.
1850  * This function will add and store those rules in rule-file of new installed app (pkg_id)
1851  */
1852 static int add_other_apps_rules_for_shared_dir(const char *pkg_id, const char *type_of_shared_dir, const char *shared_dir_label)
1853 {
1854         C_LOGD("Enter function: %s", __func__);
1855
1856         int ret;
1857         int fd AUTO_CLOSE;
1858         char *smack_path AUTO_FREE;
1859         char *smack_rules_file_path AUTO_FREE;
1860         struct smack_accesses* smack AUTO_SMACK_FREE;
1861
1862         ret = load_smack_from_file(pkg_id, &smack, &fd, &smack_path);
1863         if (ret != PC_OPERATION_SUCCESS ) {
1864                 C_LOGE("load_smack_from_file failed: %d", ret);
1865                 return ret;
1866         }
1867
1868         ret = asprintf(&smack_rules_file_path, TOSTRING(SHAREDIR)"/%s", type_of_shared_dir);
1869         if (ret < 0) {
1870                 C_LOGE("asprintf failed");
1871                 return PC_ERR_MEM_OPERATION;
1872         }
1873
1874         ret = perm_to_smack_from_file(smack, shared_dir_label, SMACK_SHARED_DIR_LABEL_TEMPLATE, smack_rules_file_path);
1875         if (ret != PC_OPERATION_SUCCESS ) {
1876                 C_LOGE("perm_to_smack_from_file failed: %d", ret);
1877         }
1878
1879         if (have_smack() && smack_accesses_apply(smack)) {
1880                 C_LOGE("smack_accesses_apply failed");
1881                 return PC_ERR_INVALID_OPERATION;
1882         }
1883
1884         if (smack_accesses_save(smack, fd)) {
1885                 C_LOGE("smack_accesses_save failed");
1886                 return PC_ERR_INVALID_OPERATION;
1887         }
1888
1889         return PC_OPERATION_SUCCESS;
1890 }
1891
1892 /* FIXME: remove this pragma once deprecated API is deleted */
1893 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1894 static int perm_app_setup_path_internal(const char* pkg_id, const char* path, app_path_type_t app_path_type, va_list ap)
1895 {
1896         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1897                                 __func__, pkg_id, path, app_path_type);
1898
1899         if(path == NULL) {
1900                 C_LOGE("Invalid argument path.");
1901                 return PC_ERR_INVALID_PARAM;
1902         }
1903
1904         if (!smack_label_is_valid(pkg_id)) {
1905                 C_LOGE("Invalid pkg_id.");
1906                 SECURE_C_LOGE("Invalid pkg_id %s", pkg_id);
1907                 return PC_ERR_INVALID_PARAM;
1908         }
1909
1910         switch (app_path_type) {
1911         case APP_PATH_PRIVATE:
1912                 C_LOGD("app_path_type is APP_PATH_PRIVATE.");
1913                 return app_label_dir(pkg_id, path);
1914
1915         case APP_PATH_GROUP_RW: {
1916                 C_LOGD("app_path_type is APP_PATH_GROUP_RW.");
1917                 int ret;
1918                 const char *shared_label;
1919
1920                 shared_label = va_arg(ap, const char *);
1921
1922                 if (!smack_label_is_valid(shared_label)) {
1923                         C_LOGE("Invalid shared_label.");
1924                         return PC_ERR_INVALID_PARAM;
1925                 }
1926
1927                 if (strcmp(pkg_id, shared_label) == 0) {
1928                         C_LOGE("pkg_id equals shared_label.");
1929                         return PC_ERR_INVALID_PARAM;
1930                 }
1931
1932                 ret = app_label_shared_dir(pkg_id, shared_label, path);
1933                 if (ret != PC_OPERATION_SUCCESS) {
1934                         C_LOGE("app_label_shared_dir failed: %d", ret);
1935                         return ret;
1936                 }
1937
1938                 return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_GROUP_RW, shared_label);
1939         }
1940
1941         case APP_PATH_PUBLIC_RO: {
1942                 C_LOGD("app_path_type is APP_PATH_PUBLIC_RO.");
1943                 char **app_ids AUTO_FREE;
1944                 int app_ids_cnt = 0;
1945                 const char *label;
1946                 int i, ret;
1947
1948                 C_LOGD("New public RO path %s", path);
1949                 label = smack_label_for_path(pkg_id, path);
1950                 if (label == NULL) {
1951                         C_LOGE("smack_label_for_path failed.");
1952                         return PC_ERR_INVALID_OPERATION;
1953                 }
1954
1955                 C_LOGD("Generated label '%s' for public RO path %s", label, path);
1956                 ret = app_label_shared_dir(pkg_id, label, path);
1957                 if (ret != PC_OPERATION_SUCCESS) {
1958                         C_LOGE("app_label_shared_dir failed.");
1959                         return ret;
1960                 }
1961
1962                 /* FIXME: This should be in some kind of transaction/lock */
1963                 ret = db_add_public_dir(label);
1964                 if (ret != PC_OPERATION_SUCCESS) {
1965                         C_LOGE("db_add_public_dir failed.");
1966                         return ret;
1967                 }
1968
1969                 ret = get_all_apps_ids(&app_ids, &app_ids_cnt);
1970                 if (ret != PC_OPERATION_SUCCESS) {
1971                         C_LOGE("get_all_aps_ids failed.");
1972                         return ret;
1973                 }
1974
1975                 for (i = 0; i < app_ids_cnt; ++i) {
1976                         SECURE_C_LOGD("Allowing app %s to access public path %s", app_ids[i], path);
1977                         ret = app_add_rule(app_ids[i], label, "rx");
1978                         if (ret != PC_OPERATION_SUCCESS) {
1979                                 C_LOGE("smack_accesses_new failed");
1980                                 while (i < app_ids_cnt)
1981                                         free(app_ids[i++]);
1982                                 return ret;
1983                         }
1984                         free(app_ids[i]);
1985                 }
1986
1987                 return add_other_apps_rules_for_shared_dir(pkg_id, PATH_RULES_PUBLIC_RO, label);
1988         }
1989
1990         case APP_PATH_SETTINGS_RW:
1991         {
1992                 C_LOGD("app_path_type is APP_PATH_SETTINGS_RW.");
1993                 char **app_ids AUTO_FREE;
1994                 int app_ids_cnt = 0;
1995                 const char *label;
1996                 int i;
1997                 int ret;
1998
1999                 /*get path id*/
2000                 label = smack_label_for_path(pkg_id, path);
2001                 if (label == NULL) {
2002                         C_LOGE("smack_label_for_path failed.");
2003                         return PC_ERR_INVALID_OPERATION;
2004                 }
2005
2006                 /*set id for path and all subfolders*/
2007                 C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
2008                 ret = app_label_shared_dir(pkg_id, label, path);
2009                 if (ret != PC_OPERATION_SUCCESS) {
2010                         C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
2011                         return ret;
2012                 }
2013
2014                 /* add path to database */
2015                 /* FIXME: This should be in some kind of transaction/lock */
2016                 ret = add_setting_dir_id_to_databse(label);
2017                 if (ret != PC_OPERATION_SUCCESS) {
2018                         C_LOGE("Appsetting: add_setting_dir_id_to_databse failed");
2019                         return ret;
2020                 }
2021
2022                 /*read all apps with appsetting privilege*/
2023                 ret = get_all_appsetting_ids(&app_ids, &app_ids_cnt);
2024                 if (ret != PC_OPERATION_SUCCESS) {
2025                         C_LOGE("Appsetting: get_all_appsetting_ids failed");
2026                         return ret;
2027                 }
2028                 C_LOGD("Appsetting: %d appsetting privileged apps registered",
2029                                 app_ids_cnt);
2030
2031                 /*give RWX rights to all apps that have appsetting privilege*/
2032                 for (i = 0; i < app_ids_cnt; ++i) {
2033                         C_LOGD("Appsetting: allowing app %s to access setting path %s",
2034                                         app_ids[i], label);
2035                         ret = app_add_rule(app_ids[i], label, "rwx");
2036                         if (ret != PC_OPERATION_SUCCESS) {
2037                                 C_LOGE("app_add_rule failed");
2038                                 while (i < app_ids_cnt)
2039                                         free(app_ids[i++]);
2040                                 return ret;
2041                         }
2042                         free(app_ids[i]);
2043                 }
2044
2045                 return PC_OPERATION_SUCCESS;
2046         }
2047
2048         case APP_PATH_ANY_LABEL: {
2049                 C_LOGD("app_path_type is APP_PATH_ANY_LABEL.");
2050                 const char *label = NULL;
2051                 label = va_arg(ap, const char *);
2052                 return app_label_dir(label, path);
2053         }
2054
2055         default:
2056                 C_LOGE("app_path_type is invalid.");
2057                 return PC_ERR_INVALID_PARAM;
2058         }
2059
2060         return PC_OPERATION_SUCCESS;
2061 }
2062 /* FIXME: remove this pragma once deprecated API is deleted */
2063 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
2064
2065 API int app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)//deprecated
2066 {
2067         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
2068                                 __func__, pkg_id, path, app_path_type);
2069
2070         va_list ap;
2071         int ret;
2072         va_start( ap, app_path_type );
2073         ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
2074         va_end( ap );
2075         return ret;
2076 }
2077
2078
2079 API int perm_app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)
2080 {
2081         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
2082                                 __func__, pkg_id, path, app_path_type);
2083
2084         va_list ap;
2085         int ret;
2086         va_start( ap, app_path_type );
2087         ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
2088         va_end( ap );
2089         return ret;
2090 }
2091
2092 API int app_add_friend(const char* pkg_id1, const char* pkg_id2)//deprecated
2093 {
2094         SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
2095                                 __func__, pkg_id1, pkg_id2);
2096
2097         return perm_app_add_friend(pkg_id1, pkg_id2);
2098 }
2099
2100 API int perm_app_add_friend(const char* pkg_id1, const char* pkg_id2)
2101 {
2102         SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
2103                                 __func__, pkg_id1, pkg_id2);
2104
2105         int ret;
2106
2107         if (!smack_label_is_valid(pkg_id1) || !smack_label_is_valid(pkg_id2)) {
2108                 C_LOGE("Invalid pkg_id1 or pkg_id2.");
2109                 return PC_ERR_INVALID_PARAM;
2110         }
2111
2112         ret = app_add_rule(pkg_id1, pkg_id2, "rwxat");
2113         if (ret != PC_OPERATION_SUCCESS) {
2114                 C_LOGE("app_add_rule failed");
2115                 return ret;
2116         }
2117
2118         ret = app_add_rule(pkg_id2, pkg_id1, "rwxat");
2119         if (ret != PC_OPERATION_SUCCESS) {
2120                 C_LOGE("app_add_rule failed");
2121                 return ret;
2122         }
2123
2124         return PC_OPERATION_SUCCESS;
2125 }
2126
2127 API int app_install(const char* pkg_id)//deprecated
2128 {
2129         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
2130                                 __func__, pkg_id);
2131
2132         return perm_app_install(pkg_id);
2133 }
2134
2135 API int perm_app_install(const char* pkg_id)
2136 {
2137         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
2138                                 __func__, pkg_id);
2139
2140         int ret;
2141         int fd AUTO_CLOSE;
2142         char* smack_path AUTO_FREE;
2143         struct smack_accesses *smack AUTO_SMACK_FREE;
2144
2145         if (!smack_label_is_valid(pkg_id)) {
2146                 C_LOGE("Invalid param pkg_id.");
2147                 return PC_ERR_INVALID_PARAM;
2148         }
2149
2150         ret = smack_file_name(pkg_id, &smack_path);
2151         if (ret != PC_OPERATION_SUCCESS) {
2152                 C_LOGE("smack_file_name failed.");
2153                 return ret;
2154         }
2155
2156         ret = load_smack_from_file(pkg_id, &smack, &fd, &smack_path);
2157         if (ret != PC_OPERATION_SUCCESS) {
2158                 C_LOGE("load_smack_from_file failed");
2159                 return ret;
2160         }
2161
2162         ret = add_app_id_to_databse(pkg_id);
2163         if (ret != PC_OPERATION_SUCCESS ) {
2164                 SECURE_C_LOGE("Error while adding app %s to database: %s ", pkg_id, strerror(errno));
2165                 return ret;
2166         }
2167
2168         ret = register_app_for_av(pkg_id);
2169         if (ret != PC_OPERATION_SUCCESS) {
2170                 SECURE_C_LOGE("Error while adding rules for anti viruses to app %s: %s ", pkg_id, strerror(errno));
2171                 return ret;
2172         }
2173
2174         ret = register_app_for_appsetting(pkg_id);
2175         if (ret != PC_OPERATION_SUCCESS) {
2176                 SECURE_C_LOGE("Error while adding rules for setting managers to app %s: %s ", pkg_id, strerror(errno));
2177                 return ret;
2178         }
2179
2180         ret = register_app_for_public_dirs(pkg_id, smack);
2181         if (ret != PC_OPERATION_SUCCESS) {
2182                 SECURE_C_LOGE("Error while adding rules for access to public dirs for app %s: %s ", pkg_id, strerror(errno));
2183                 return ret;
2184         }
2185
2186         if (have_smack() && smack_accesses_apply(smack)) {
2187                 C_LOGE("smack_accesses_apply failed");
2188                 return PC_ERR_INVALID_OPERATION;
2189         }
2190
2191         if (smack_accesses_save(smack, fd)) {
2192                 C_LOGE("smack_accesses_save failed");
2193                 return PC_ERR_INVALID_OPERATION;
2194         }
2195
2196         return PC_OPERATION_SUCCESS;
2197 }
2198
2199 API int app_uninstall(const char* pkg_id)//deprecated
2200 {
2201         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
2202                                 __func__, pkg_id);
2203
2204         return perm_app_uninstall(pkg_id);
2205 }
2206
2207 API int perm_app_uninstall(const char* pkg_id)
2208 {
2209         // TODO: When real database will be used, then this function should remove app_id
2210         //       from database.
2211         //       It also should remove rules like: "anti_virus_label app_id rwx".
2212         SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
2213         char* smack_path AUTO_FREE;
2214         int ret;
2215
2216         if (!smack_label_is_valid(pkg_id)) {
2217                 C_LOGE("Invalid param pkg_id.");
2218                 return PC_ERR_INVALID_PARAM;
2219         }
2220
2221         ret = smack_file_name(pkg_id, &smack_path);
2222         if (ret != PC_OPERATION_SUCCESS) {
2223                 C_LOGE("smack_file_name failed.");
2224                 return ret;
2225         }
2226
2227         if (unlink(smack_path)) {
2228                 C_LOGE("unlink failed (error: %s)", strerror(errno));
2229                 return PC_OPERATION_SUCCESS;
2230         }
2231
2232         ret = app_uninstall_remove_early_rules(pkg_id);
2233         if (ret != PC_OPERATION_SUCCESS) {
2234                 C_LOGE("app_uninstall_remove_early_rules failed.");
2235                 return ret;
2236         }
2237
2238         return PC_OPERATION_SUCCESS;
2239 }
2240
2241 static int save_rules(int fd, struct smack_accesses* accesses) {
2242         SECURE_C_LOGD("Entering function: %s. Params: fd=%d", __func__, fd);
2243
2244         if (flock(fd, LOCK_EX)) {
2245                 C_LOGE("flock failed (error: %s)", strerror(errno));
2246                 return PC_ERR_FILE_OPERATION;
2247         }
2248
2249         if (smack_accesses_save(accesses, fd)) {
2250                 C_LOGE("smack_accesses_save failed");
2251                 return PC_ERR_FILE_OPERATION;
2252         }
2253         return PC_OPERATION_SUCCESS ;
2254 }
2255
2256 static int validate_and_add_rule(char* rule, struct smack_accesses* accesses) {
2257         SECURE_C_LOGD("Entering function: %s. Params: rule=%s",
2258                                 __func__, rule);
2259
2260         const char* subject = NULL;
2261         const char* object = NULL;
2262         const char* access = NULL;
2263         char* saveptr = NULL;
2264
2265         subject = strtok_r(rule, " \t\n", &saveptr);
2266         object = strtok_r(NULL, " \t\n", &saveptr);
2267         access = strtok_r(NULL, " \t\n", &saveptr);
2268
2269         // check rule validity
2270         if (subject == NULL ||
2271                 object == NULL ||
2272                 access == NULL ||
2273                 strtok_r(NULL, " \t\n", &saveptr) != NULL ||
2274                 !smack_label_is_valid(subject) ||
2275                 !smack_label_is_valid(object))
2276         {
2277                 C_LOGE("Incorrect rule format: %s", rule);
2278                 return PC_ERR_INVALID_PARAM;
2279         }
2280
2281         if (smack_accesses_add_modify(accesses, subject, object, access, "")) {
2282                 C_LOGE("smack_accesses_add_modify failed");
2283                 return PC_ERR_INVALID_OPERATION;
2284         }
2285         return PC_OPERATION_SUCCESS ;
2286 }
2287
2288 static int parse_and_save_rules(const char** smack_rules,
2289                 struct smack_accesses* accesses, const char* feature_file) {
2290         SECURE_C_LOGD("Entering function: %s. Params: feature_file=%s",
2291                                 __func__, feature_file);
2292
2293         size_t i = 0;
2294         int fd = 0;
2295         int ret = PC_OPERATION_SUCCESS;
2296         char* tmp = NULL;
2297
2298         for (i = 0; smack_rules[i] != NULL ; i++) {
2299                 // ignore empty lines
2300                 if (strspn(smack_rules[i], " \t\n") == strlen(smack_rules[i]))
2301                         continue;
2302
2303                 tmp = strdup(smack_rules[i]);
2304                 ret = validate_and_add_rule(tmp, accesses);
2305                 free(tmp);
2306                 if (ret != PC_OPERATION_SUCCESS )
2307                         return ret;
2308         }
2309
2310         // save to file
2311         fd = open(feature_file, O_CREAT | O_WRONLY, 0644);
2312         if (fd == -1) {
2313                 SECURE_C_LOGE("Unable to create file %s. (error: %s)", feature_file, strerror(errno));
2314                 return PC_ERR_FILE_OPERATION;
2315         }
2316
2317         ret = save_rules(fd, accesses);
2318         close(fd);
2319         return ret;
2320 }
2321
2322 static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
2323         SECURE_C_LOGD("Entering function: %s.", __func__);
2324         int ret = PC_OPERATION_SUCCESS;
2325         int written = 0;
2326         size_t i = 0;
2327
2328         if (file == NULL) {
2329                 C_LOGE("Unable to create file. Error: %s", strerror(errno));
2330                 return PC_ERR_FILE_OPERATION;   // TODO remove smack accesses?
2331         }
2332
2333         if(-1 == fchmod(fileno(file), 0644)) {
2334                 C_LOGE("Unable to chmod file. Error: %s", strerror(errno));
2335                 return PC_ERR_FILE_OPERATION;
2336         }
2337
2338         for (i = 0; i < list_size ; ++i) {
2339                 written = fprintf(file, "%u\n", list_of_db_gids[i]);
2340                 if (written <= 0) {
2341                         C_LOGE("fprintf failed for file. Error: %s", strerror(errno));
2342                         ret = PC_ERR_FILE_OPERATION;
2343                         break;
2344                 }
2345         }
2346         return ret;
2347 }
2348
2349 API int add_api_feature(app_type_t app_type,
2350                         const char* api_feature_name,
2351                         const char** smack_rules,
2352                         const gid_t* list_of_db_gids,
2353                         size_t list_size)//deprecated
2354 {
2355         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
2356                                 __func__, app_type, api_feature_name);
2357
2358     return perm_add_api_feature(app_type, api_feature_name, smack_rules, list_of_db_gids, list_size);
2359 }
2360
2361 API int perm_add_api_feature(app_type_t app_type,
2362                                                 const char* api_feature_name,
2363                                                 const char** smack_rules,
2364                                                 const gid_t* list_of_db_gids,
2365                                                 size_t list_size) {
2366         SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
2367                                 __func__, app_type, api_feature_name);
2368
2369         int ret = PC_OPERATION_SUCCESS;
2370         char* smack_file AUTO_FREE;
2371         char* dac_file AUTO_FREE;
2372         struct smack_accesses* accesses = NULL;
2373         FILE* file = NULL;
2374
2375         // TODO check process capabilities
2376
2377         // get feature SMACK file name
2378         ret = perm_file_path(&smack_file, app_type, api_feature_name, ".smack", 0);
2379         if (ret != PC_OPERATION_SUCCESS || !smack_file ) {
2380                 C_LOGE("perm_file_path failed.");
2381                 return ret;
2382         }
2383
2384         // check if feature exists
2385         if (file_exists(smack_file)) {
2386                 C_LOGE("Feature file %s already exists", smack_file);
2387                 return PC_ERR_INVALID_PARAM;
2388         }
2389
2390         // check .dac existence only if gids are supported
2391         if (list_of_db_gids && list_size > 0) {
2392                 // get feature DAC file name
2393                 ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac", 0);
2394                 if (ret != PC_OPERATION_SUCCESS || !dac_file ) {
2395                         C_LOGE("perm_file_path failed.");
2396                         return ret;
2397                 }
2398
2399                 // check if feature exists
2400                 if (file_exists(dac_file)) {
2401                         C_LOGE("Feature file %s already exists", dac_file);
2402                         return PC_ERR_INVALID_PARAM;
2403                 }
2404         }
2405
2406         // parse & save rules
2407         if (smack_rules) {
2408                 if (smack_accesses_new(&accesses)) {
2409                         C_LOGE("smack_acceses_new failed");
2410                         return PC_ERR_MEM_OPERATION;
2411                 }
2412
2413                 ret = parse_and_save_rules(smack_rules, accesses, smack_file);
2414                 smack_accesses_free(accesses);
2415         }
2416
2417         // go through gid list
2418         if (ret == PC_OPERATION_SUCCESS && list_of_db_gids && list_size > 0) {
2419                 // save to file
2420                 SECURE_C_LOGD("Opening file %s.", dac_file);
2421                 file = fopen(dac_file, "w+");
2422                 ret = save_gids(file, list_of_db_gids, list_size);
2423                 fclose(file);
2424         }
2425
2426         // remove both files in case of failure
2427         if (ret != PC_OPERATION_SUCCESS) {
2428                 unlink(smack_file);
2429                 if (dac_file) {
2430                         unlink(dac_file);
2431                 }
2432         }
2433
2434         return ret;
2435 }
2436
2437 /**
2438  * This function is marked as deprecated and will be removed
2439  */
2440 API int app_register_av(const char* app_av_id)//deprecated
2441 {
2442         SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s",
2443                                 __func__, app_av_id);
2444
2445         int ret;
2446         int fd AUTO_CLOSE;
2447         char* smack_path AUTO_FREE;
2448         struct smack_accesses* smack AUTO_SMACK_FREE;
2449
2450         if(app_av_id == NULL) {
2451                 C_LOGE("Invalid param app_av_id.");
2452                 return PC_ERR_INVALID_PARAM;
2453         }
2454
2455         ret = load_smack_from_file(app_av_id, &smack, &fd, &smack_path);
2456         if (ret != PC_OPERATION_SUCCESS ) {
2457                 C_LOGE("load_smack_from_file failed");
2458                 return ret;
2459         }
2460
2461         ret = app_register_av_internal(app_av_id, smack);
2462         if (PC_OPERATION_SUCCESS != ret) {
2463                 C_LOGE("app_register_av_internal failed");
2464                 return ret;
2465         }
2466
2467         // Add permisions from OSP_antivirus.smack file
2468         ret = perm_to_smack(smack, app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
2469         if (PC_OPERATION_SUCCESS != ret) {
2470                 C_LOGE("perm_to_smack failed");
2471                 return ret;
2472         }
2473
2474         // Add permisions from OSP_antivirus.dac file
2475         ret = perm_to_dac(app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
2476         if (ret != PC_OPERATION_SUCCESS) {
2477                 C_LOGE("perm_to_dac failed");
2478                 return ret;
2479         }
2480
2481         if (have_smack() && smack_accesses_apply(smack)) {
2482                 C_LOGE("smack_accesses_apply failed");
2483                 ret = PC_ERR_INVALID_OPERATION;
2484                 return ret;
2485         }
2486
2487         if (smack_accesses_save(smack, fd)) {
2488                 C_LOGE("smack_accesses_save failed");
2489                 ret = PC_ERR_INVALID_OPERATION;
2490                 return ret;
2491         }
2492
2493         return ret;
2494 }