2 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <sys/statfs.h>
21 #include <sys/types.h>
26 #include <download-provider.h>
27 #include <download-provider-log.h>
28 #include <download-provider-utils.h>
30 #include <cynara-client.h>
31 #include <cynara-client-async.h>
32 #include <cynara-creds-socket.h>
33 #include <cynara-creds-dbus.h>
35 #include <app_manager.h>
36 #include <tzplatform_config.h>
38 #include "download-provider-security.h"
40 #define MAX_ARRAY_LEN 1024
41 #define SECURITY_ATTRIBUTES_PATH "/proc/%d/attr/current"
42 #define TEMP_DIR "/tmp/"
43 #define LEGACY_USER_APP "/opt/usr/apps/"
45 static int dp_is_exist_dir(const char *dirpath)
47 struct stat dir_state;
49 if (dirpath == NULL) {
50 TRACE_ERROR("check path");
53 stat_ret = stat(dirpath, &dir_state);
54 if (stat_ret == 0 && S_ISDIR(dir_state.st_mode))
59 static char *_dp_get_pkg_id(dp_credential cred)
63 app_info_h app_info = NULL;
65 if (app_manager_get_app_id(cred.pid, &app_id) != APP_MANAGER_ERROR_NONE) {
66 TRACE_ERROR("Failed to get application ID");
70 if (app_info_create(app_id, &app_info) != APP_MANAGER_ERROR_NONE) {
71 TRACE_ERROR("Failed to create app_info");
76 if (app_info_get_package(app_info, &pkg_id) != APP_MANAGER_ERROR_NONE) {
77 TRACE_ERROR("Failed to get package ID");
78 app_info_destroy(app_info);
84 app_info_destroy(app_info);
90 static int _dp_check_dir_permission(dp_credential cred, const char *privilege)
94 char client_smack[MAX_ARRAY_LEN + 1] = {0, };
95 char client_smack_path[MAX_ARRAY_LEN + 1] = {0, };
97 char *client_session = "";
98 cynara *p_cynara = NULL;
100 if (CYNARA_API_SUCCESS != cynara_initialize(&p_cynara, NULL)) {
101 TRACE_ERROR("Failed to initialize cynara structure\n");
105 snprintf(client_smack_path, MAX_ARRAY_LEN, SECURITY_ATTRIBUTES_PATH, cred.pid);
106 fd = fopen(client_smack_path, "r");
108 TRACE_ERROR("Failed to open %s", client_smack_path);
109 cynara_finish(p_cynara);
112 ret = fread(client_smack, 1, MAX_ARRAY_LEN, fd);
114 TRACE_ERROR("Failed to read %s", client_smack_path);
116 cynara_finish(p_cynara);
120 client_smack[ret] = '\0';
122 snprintf(uid, sizeof(uid), "%d", cred.uid);
124 TRACE_DEBUG("pid: %d, uid: %s, checked privilege:%s", cred.pid, uid, privilege);
125 ret = cynara_check(p_cynara, client_smack, client_session, uid, privilege);
126 cynara_finish(p_cynara);
128 return (ret == CYNARA_API_ACCESS_ALLOWED) ? 0 : -1;
131 int dp_is_valid_dir(dp_credential cred, const char *dirpath)
133 char default_storage[PATH_MAX + 1] = {0, };
134 char media_storage[PATH_MAX + 1] = {0, };
135 char external_storage[PATH_MAX + 1] = {0, };
136 char apps_storage[PATH_MAX + 1] = {0, };
137 char resolved_path[PATH_MAX + 1] = {0 , };
140 const char *temp = NULL;
143 res = realpath(dirpath, NULL);
145 TRACE_ERROR("Failed to get absolute path");
146 return DP_ERROR_INVALID_DESTINATION;
149 strncpy(resolved_path, res, PATH_MAX - 1);
152 end = strlen(resolved_path) - 1;
153 if (resolved_path[end] != '/')
154 resolved_path[end + 1] = '/';
156 TRACE_INFO("%s -> %s", dirpath, resolved_path);
158 // Check whether directory is exist or not.
159 if (dp_is_exist_dir(resolved_path) < 0) {
160 TRACE_ERROR("%s is not exist.", resolved_path);
161 return DP_ERROR_INVALID_DESTINATION;
164 // Check whether directory is temporary directory or not.
165 if (strncmp(resolved_path, TEMP_DIR, strlen(TEMP_DIR)) == 0)
166 return DP_ERROR_NONE;
168 tzplatform_set_user(cred.uid);
170 // Check whether directory is default directory or not.
171 temp = tzplatform_getenv(TZ_USER_DOWNLOADS);
173 snprintf(default_storage, PATH_MAX - 1, "%s/", temp);
174 if (strncmp(resolved_path, default_storage,
175 strlen(default_storage)) == 0)
176 return DP_ERROR_NONE;
180 // Check permission: media storage
181 temp = tzplatform_getenv(TZ_USER_CONTENT);
183 snprintf(media_storage, PATH_MAX - 1, "%s/", temp);
184 if (strncmp(resolved_path, media_storage,
185 strlen(media_storage)) == 0) {
186 if (_dp_check_dir_permission(cred, MEDIA_STORAGE_PRIVILEGE) < 0) {
187 TRACE_ERROR("Permission denied: %s needs %s privilege",
188 resolved_path, MEDIA_STORAGE_PRIVILEGE);
189 return DP_ERROR_INVALID_DESTINATION;
191 return DP_ERROR_NONE;
196 // Check permission: external storage
197 temp = tzplatform_getenv(TZ_SYS_STORAGE);
199 snprintf(external_storage, PATH_MAX - 1, "%s/", temp);
200 if (strncmp(resolved_path, external_storage,
201 strlen(external_storage)) == 0) {
202 if (_dp_check_dir_permission(cred, EXTERNAL_STORAGE_PRIVILEGE) < 0) {
203 TRACE_ERROR("Permission denied: %s needs %s privilege",
204 resolved_path, EXTERNAL_STORAGE_PRIVILEGE);
205 return DP_ERROR_INVALID_DESTINATION;
207 return DP_ERROR_NONE;
212 // Check permission: private storage
213 if (strncmp(resolved_path, LEGACY_USER_APP, strlen(LEGACY_USER_APP)) == 0) {
214 // Some applications use a legacy app path.
215 snprintf(apps_storage, PATH_MAX - 1, "%s", LEGACY_USER_APP);
217 temp = tzplatform_getenv(TZ_USER_APP);
218 snprintf(apps_storage, PATH_MAX - 1, "%s/", temp);
222 if (strlen(apps_storage) > 0) {
223 if (strncmp(resolved_path, apps_storage,
224 strlen(apps_storage)) == 0) {
225 pkg_id = _dp_get_pkg_id(cred);
227 return DP_ERROR_INVALID_DESTINATION;
229 TRACE_INFO("pkg_id: %s", pkg_id);
230 if (strncmp(resolved_path + strlen(apps_storage),
231 pkg_id, strlen(pkg_id)) != 0) {
232 TRACE_ERROR("Permission denied");
234 return DP_ERROR_INVALID_DESTINATION;
237 return DP_ERROR_NONE;
241 // Check whether directory is shared directory or not.
242 temp = tzplatform_getenv(TZ_USER_SHARE);
244 if (strncmp(resolved_path, temp,
246 return DP_ERROR_NONE;
250 return DP_ERROR_INVALID_DESTINATION;
253 void dp_rebuild_dir(const char *dirpath, mode_t mode)
255 if (dp_is_exist_dir(dirpath) < 0) {
256 if (mkdir(dirpath, mode) == 0)
257 TRACE_INFO("check directory:%s", dirpath);
259 TRACE_ERROR("failed to create directory:%s", dirpath);
263 int dp_check_permission(int clientfd, const char *pkgname)
266 int result = DP_ERROR_NONE;
267 cynara *p_cynara = NULL;
268 cynara_configuration *p_conf = NULL;
269 size_t cache_size = 100;
270 const char *client_session = "";
271 char *client_smack = NULL;
274 TRACE_DEBUG("clientfd[%d] pkgname[%s]", clientfd, pkgname);
275 if (CYNARA_API_SUCCESS != cynara_configuration_create(&p_conf)) {
276 TRACE_DEBUG("failed to create cynara configuration");
277 result = DP_ERROR_PERMISSION_DENIED;
281 if (CYNARA_API_SUCCESS != cynara_configuration_set_cache_size(p_conf, cache_size)) {
282 TRACE_DEBUG("failed to set cache size");
283 result = DP_ERROR_PERMISSION_DENIED;
287 ret = cynara_initialize(&p_cynara, NULL);
288 if (ret != CYNARA_API_SUCCESS) {
289 TRACE_DEBUG("failed to initialize cynara");
290 result = DP_ERROR_PERMISSION_DENIED;
294 // Get client peer credential
295 ret = cynara_creds_socket_get_client(clientfd, CLIENT_METHOD_SMACK, &client_smack);
296 if (ret != CYNARA_API_SUCCESS) {
297 TRACE_DEBUG("failed to createsa client identification string");
298 result = DP_ERROR_PERMISSION_DENIED;
302 ret = cynara_creds_socket_get_user(clientfd, USER_METHOD_UID, &uid);
303 if (ret != CYNARA_API_SUCCESS) {
304 TRACE_DEBUG("failed to create a user identification string");
305 result = DP_ERROR_PERMISSION_DENIED;
310 ret = cynara_check(p_cynara, client_smack, client_session, uid, DOWNLOAD_PRIVILEGE);
311 if (ret == CYNARA_API_ACCESS_ALLOWED) {
312 TRACE_DEBUG("CYNARA_API_ACCESS_ALLOWED");
314 TRACE_DEBUG("DP_ERROR_PERMISSION_DENIED");
315 result = DP_ERROR_PERMISSION_DENIED;
320 cynara_configuration_destroy(p_conf);
322 cynara_finish(p_cynara);