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