Apply tizen coding rule
[platform/framework/web/download-provider.git] / provider / download-provider-smack.c
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18 #include <errno.h>
19 #include <sys/statfs.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23
24 #include <sys/smack.h>
25
26 #include <download-provider.h>
27 #include <download-provider-log.h>
28 #include <download-provider-utils.h>
29
30 #define SMACKFS_MAGIC 0x43415d53
31 #define SMACKFS_MNT "/smack"
32
33 static int __dp_smack_is_transmute(char *path)
34 {
35         char *dir_label = NULL;
36         int ret = -1;
37         if (smack_getlabel(path, &dir_label, SMACK_LABEL_TRANSMUTE) == 0 && dir_label != NULL) {
38                 if (strncmp(dir_label, "TRUE", strlen(dir_label)) == 0)
39                         ret = 0;
40         }
41
42         if (smack_getlabel(path, &dir_label, SMACK_LABEL_ACCESS) == 0 && dir_label != NULL) {
43                 if (strncmp(dir_label, "*", strlen(dir_label)) == 0)
44                         ret = 0;
45         }
46
47         free(dir_label);
48         return ret;
49 }
50
51 int dp_smack_is_mounted()
52 {
53         struct statfs sfs;
54         int ret;
55         do {
56                 ret = statfs(SMACKFS_MNT, &sfs);
57         } while (ret < 0 && errno == EINTR);
58         if (ret) {
59                 TRACE_ERROR("[SMACK ERROR]");
60                 return -1;
61         }
62         if (sfs.f_type == SMACKFS_MAGIC)
63                 return 1;
64         TRACE_ERROR("[SMACK DISABLE]");
65         return 0;
66 }
67
68 int dp_smack_set_label(char *label, char *source, char *target)
69 {
70         if (label == NULL || source == NULL || target == NULL)
71                 return DP_ERROR_PERMISSION_DENIED;
72
73         int is_setted_dir_label = 0;
74         int errorcode = DP_ERROR_NONE;
75
76         if (__dp_smack_is_transmute(source) < 0) {
77                 TRACE_SECURE_ERROR("[SMACK] no transmute:%s", source);
78         } else {
79                 char *dir_label = NULL;
80                 if (smack_getlabel(source, &dir_label, SMACK_LABEL_ACCESS) == 0) {
81                         if (smack_have_access(label, dir_label, "t") > 0) {
82                                 if (smack_setlabel(target, dir_label, SMACK_LABEL_ACCESS) != 0) {
83                                         TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", dir_label);
84                                         errorcode = DP_ERROR_PERMISSION_DENIED;
85                                 } else {
86                                         is_setted_dir_label = 1;
87                                 }
88                         } else {
89                                 TRACE_SECURE_ERROR("[SMACK ERROR] access:%s/%s", label, dir_label);
90                                 errorcode = DP_ERROR_PERMISSION_DENIED;
91                         }
92                 } else {
93                         TRACE_SECURE_ERROR("[SMACK ERROR] no label:%s", source);
94                         errorcode = DP_ERROR_PERMISSION_DENIED;
95                 }
96                 free(dir_label);
97         }
98         if (is_setted_dir_label == 0 &&
99                         smack_setlabel(target, label, SMACK_LABEL_ACCESS) != 0) {
100                 TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", label);
101                 errorcode = DP_ERROR_PERMISSION_DENIED;
102                 // remove file.
103                 if (dp_is_file_exist(target) == 0)
104                         unlink(target);
105         }
106         return errorcode;
107 }
108
109 char *dp_smack_get_label_from_socket(int sock)
110 {
111         char *label = NULL;
112         if (smack_new_label_from_socket(sock, &label) != 0) {
113                 free(label);
114                 return NULL;
115         }
116         return label;
117 }
118
119 int dp_smack_is_valid_dir(int uid, int gid, char *smack_label, char *dir)
120 {
121         if (smack_label == NULL || dir == NULL) {
122                 TRACE_ERROR("check parameter %s/%s", smack_label, dir);
123                 return -1;
124         }
125         int ret = -1;
126         struct stat dstate;
127         if (stat(dir, &dstate) == 0) {
128                 if ((dstate.st_uid == uid && (dstate.st_mode & (S_IRUSR | S_IWUSR)) == (S_IRUSR | S_IWUSR)) ||
129                                 (dstate.st_gid == gid && (dstate.st_mode & (S_IRGRP | S_IWGRP)) == (S_IRGRP | S_IWGRP)) ||
130                                 ((dstate.st_mode & (S_IROTH | S_IWOTH)) == (S_IROTH | S_IWOTH))) {
131                         char *dir_label = NULL;
132                         if (smack_getlabel(dir, &dir_label, SMACK_LABEL_ACCESS) == 0 &&
133                                         smack_have_access(smack_label, dir_label, "rw") > 0) {
134                                 ret = 0;
135                         }
136                         free(dir_label);
137                 }
138         }
139         return ret;
140 }
141
142 int dp_is_valid_dir(const char *dirpath)
143 {
144         struct stat dir_state;
145         int stat_ret;
146         if (dirpath == NULL) {
147                 TRACE_ERROR("check path");
148                 return -1;
149         }
150         stat_ret = stat(dirpath, &dir_state);
151         if (stat_ret == 0 && S_ISDIR(dir_state.st_mode))
152                 return 0;
153         return -1;
154 }
155
156 void dp_rebuild_dir(const char *dirpath, mode_t mode)
157 {
158         if (dp_is_valid_dir(dirpath) < 0) {
159                 if (mkdir(dirpath, mode) == 0) {
160                         TRACE_INFO("check directory:%s", dirpath);
161                         if (smack_setlabel(dirpath, "_", SMACK_LABEL_ACCESS) != 0)
162                                 TRACE_SECURE_ERROR("failed to set smack label:%s", dirpath);
163                 } else {
164                         TRACE_ERROR("failed to create directory:%s", dirpath);
165                 }
166         }
167 }