e863b1a234d0a8b3c35921cea6c2b1c1a2814df0
[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
43     if (smack_getlabel(path, &dir_label, SMACK_LABEL_ACCESS) == 0 && dir_label != NULL) {
44         if (strncmp(dir_label, "*", strlen(dir_label)) == 0) {
45             ret = 0;
46         }
47     }
48
49     free(dir_label);
50     return ret;
51 }
52
53 int dp_smack_is_mounted()
54 {
55         struct statfs sfs;
56         int ret;
57         do {
58                 ret = statfs(SMACKFS_MNT, &sfs);
59         } while (ret < 0 && errno == EINTR);
60         if (ret) {
61                 TRACE_ERROR("[SMACK ERROR]");
62                 return -1;
63         }
64         if (sfs.f_type == SMACKFS_MAGIC) {
65                 return 1;
66         }
67         TRACE_ERROR("[SMACK DISABLE]");
68         return 0;
69 }
70
71 int dp_smack_set_label(char *label, char *source, char *target)
72 {
73         if (label == NULL || source == NULL || target == NULL)
74                 return DP_ERROR_PERMISSION_DENIED;
75
76         int is_setted_dir_label = 0;
77         int errorcode = DP_ERROR_NONE;
78
79         if (__dp_smack_is_transmute(source) < 0) {
80                 TRACE_SECURE_ERROR("[SMACK] no transmute:%s", source);
81         } else {
82                 char *dir_label = NULL;
83                 if (smack_getlabel(source, &dir_label, SMACK_LABEL_ACCESS) == 0) {
84                         if (smack_have_access(label, dir_label, "t") > 0) {
85                                 if (smack_setlabel(target, dir_label, SMACK_LABEL_ACCESS) != 0) {
86                                         TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", dir_label);
87                                         errorcode = DP_ERROR_PERMISSION_DENIED;
88                                 } else {
89                                         is_setted_dir_label = 1;
90                                 }
91                         } else {
92                                 TRACE_SECURE_ERROR("[SMACK ERROR] access:%s/%s", label, dir_label);
93                                 errorcode = DP_ERROR_PERMISSION_DENIED;
94                         }
95                 } else {
96                         TRACE_SECURE_ERROR("[SMACK ERROR] no label:%s", source);
97                         errorcode = DP_ERROR_PERMISSION_DENIED;
98                 }
99                 free(dir_label);
100         }
101         if (is_setted_dir_label == 0 &&
102                         smack_setlabel(target, label, SMACK_LABEL_ACCESS) != 0) {
103                 TRACE_SECURE_ERROR("[SMACK ERROR] label:%s", label);
104                 errorcode = DP_ERROR_PERMISSION_DENIED;
105                 // remove file.
106                 if (dp_is_file_exist(target) == 0)
107                         unlink(target);
108         }
109         return errorcode;
110 }
111
112 char *dp_smack_get_label_from_socket(int sock)
113 {
114         char *label = NULL;
115         if (smack_new_label_from_socket(sock, &label) != 0) {
116                 free(label);
117                 return NULL;
118         }
119         return label;
120 }
121
122 int dp_smack_is_valid_dir(int uid, int gid, char *smack_label, char *dir)
123 {
124         if (smack_label == NULL || dir == NULL) {
125                 TRACE_ERROR("check parameter %s/%s", smack_label, dir);
126                 return -1;
127         }
128         int ret = -1;
129         struct stat dstate;
130         if (stat(dir, &dstate) == 0) {
131                 if ((dstate.st_uid == uid && (dstate.st_mode & (S_IRUSR | S_IWUSR)) == (S_IRUSR | S_IWUSR)) ||
132                                 (dstate.st_gid == gid && (dstate.st_mode & (S_IRGRP | S_IWGRP)) == (S_IRGRP | S_IWGRP)) ||
133                                 ((dstate.st_mode & (S_IROTH | S_IWOTH)) == (S_IROTH | S_IWOTH))) {
134                         char *dir_label = NULL;
135                         if (smack_getlabel(dir, &dir_label, SMACK_LABEL_ACCESS) == 0 &&
136                                         smack_have_access(smack_label, dir_label, "rw") > 0) {
137                                 ret = 0;
138                         }
139                         free(dir_label);
140                 }
141         }
142         return ret;
143 }
144
145 int dp_is_valid_dir(const char *dirpath)
146 {
147         struct stat dir_state;
148         int stat_ret;
149         if (dirpath == NULL) {
150                 TRACE_ERROR("check path");
151                 return -1;
152         }
153         stat_ret = stat(dirpath, &dir_state);
154         if (stat_ret == 0 && S_ISDIR(dir_state.st_mode)) {
155                 return 0;
156         }
157         return -1;
158 }
159
160 void dp_rebuild_dir(const char *dirpath, mode_t mode)
161 {
162         if (dp_is_valid_dir(dirpath) < 0) {
163                 if (mkdir(dirpath, mode) == 0) {
164                         TRACE_INFO("check directory:%s", dirpath);
165                         if (smack_setlabel(dirpath, "_", SMACK_LABEL_ACCESS) != 0) {
166                                 TRACE_SECURE_ERROR("failed to set smack label:%s", dirpath);
167                         }
168                 } else {
169                         TRACE_ERROR("failed to create directory:%s", dirpath);
170                 }
171         }
172 }