4 * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * This file contains Cynara integration code
25 * @file media-util-cynara.c
26 * @author Jacek Bukarewicz (j.bukarewicz@samsung.com)
37 #include <sys/socket.h>
40 #include <media-util-cynara.h>
41 #include <media-util-dbg.h>
42 #include <media-util-err.h>
43 #include <media-util-ipc.h>
44 #include <media-util-internal.h>
46 #include <cynara-client.h>
47 #include <cynara-session.h>
48 #include <cynara-error.h>
49 #include <cynara-creds-socket.h>
52 /* this definition is missing in glibc headers (version 2.21). It was introduced in kernel version 2.6.17 */
54 #define SCM_SECURITY 0x03
57 static cynara *_cynara = NULL;
58 G_LOCK_DEFINE_STATIC(cynara_mutex);
60 static void ms_cynara_dbg_err(const char *prefix, int error_code)
62 char error_buffer[256];
64 error_buffer[0] = '\0';
66 err = cynara_strerror(error_code, error_buffer, sizeof(error_buffer));
67 if (err == CYNARA_API_SUCCESS) {
68 MSAPI_DBG_ERR("%s: %s", prefix, error_buffer);
70 MSAPI_DBG_ERR("%s: error code %i", prefix, error_code);
74 int ms_cynara_initialize(void)
76 int ret = cynara_initialize(&_cynara, NULL);
77 if (ret != CYNARA_API_SUCCESS) {
78 ms_cynara_dbg_err("cynara_initialize", ret);
79 return MS_MEDIA_ERR_INTERNAL;
82 return MS_MEDIA_ERR_NONE;
85 void ms_cynara_finish(void)
87 cynara_finish(_cynara);
91 int ms_cynara_receive_untrusted_message(int sockfd, ms_comm_msg_s *recv_msg, ms_peer_credentials *credentials)
94 int recv_msg_size = 0;
96 if (!recv_msg ||!credentials)
97 return MS_MEDIA_ERR_INVALID_PARAMETER;
99 if ((recv_msg_size = read(sockfd, recv_msg, sizeof(ms_comm_msg_s))) < 0) {
100 if (errno == EWOULDBLOCK) {
101 MSAPI_DBG_ERR("Timeout. Can't try any more");
102 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
104 MSAPI_DBG_ERR("recv failed");
105 return MS_MEDIA_ERR_SOCKET_RECEIVE;
109 MSAPI_DBG_SLOG("receive msg from [%d] %d, %s", recv_msg->pid, recv_msg->msg_type, recv_msg->msg);
111 if (!(recv_msg->msg_size > 0 && recv_msg->msg_size < MAX_FILEPATH_LEN)) {
112 MSAPI_DBG_ERR("IPC message is wrong. message size is %d", recv_msg->msg_size);
113 return MS_MEDIA_ERR_INVALID_IPC_MESSAGE;
116 ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
118 MSAPI_DBG_ERR("cynara_creds_socket_get_pid failed");
119 return MS_MEDIA_ERR_INTERNAL;
122 ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
124 MSAPI_DBG_ERR("cynara_creds_socket_get_user failed");
125 return MS_MEDIA_ERR_INTERNAL;
128 ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
130 MSAPI_DBG_ERR("cynara_creds_socket_get_client failed");
131 return MS_MEDIA_ERR_INTERNAL;
134 // MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
136 return MS_MEDIA_ERR_NONE;
139 int ms_cynara_receive_untrusted_message_thumb(int sockfd, thumbMsg *recv_msg, ms_peer_credentials *credentials)
143 int recv_msg_size = 0;
144 unsigned char *buf = NULL;
146 if (!recv_msg ||!credentials)
147 return MS_MEDIA_ERR_INVALID_PARAMETER;
149 header_size = sizeof(thumbMsg) -(MAX_FILEPATH_LEN * 2) - sizeof(unsigned char *);
150 MS_MALLOC(buf,header_size);
152 if ((recv_msg_size = recv(sockfd, buf, header_size, 0)) < 0) {
153 if (errno == EWOULDBLOCK) {
154 MSAPI_DBG_ERR("Timeout. Can't try any more");
155 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
157 MSAPI_DBG_ERR("recv failed");
158 return MS_MEDIA_ERR_SOCKET_RECEIVE;
162 memcpy(recv_msg, buf, header_size);
166 if (recv_msg->origin_path_size <= 0) {
168 MSAPI_DBG_ERR("msg->origin_path_size is invalid %d", recv_msg->origin_path_size );
169 return MS_MEDIA_ERR_INVALID_PARAMETER;
172 MS_MALLOC(buf, (unsigned int)(recv_msg->origin_path_size));
174 MSAPI_DBG_STRERROR("malloc failed");
175 return MS_MEDIA_ERR_OUT_OF_MEMORY;
178 if ((recv_msg_size = recv(sockfd, buf, recv_msg->origin_path_size, 0)) < 0) {
180 if (errno == EWOULDBLOCK) {
181 MSAPI_DBG_ERR("Timeout. Can't try any more");
182 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
184 MSAPI_DBG_ERR("recv failed");
185 return MS_MEDIA_ERR_SOCKET_RECEIVE;
190 strncpy(recv_msg->org_path, (char*)buf, recv_msg->origin_path_size);
193 if (recv_msg->dest_path_size <= 0) {
195 MSAPI_DBG_ERR("msg->origin_path_size is invalid %d", recv_msg->dest_path_size );
196 return MS_MEDIA_ERR_INVALID_PARAMETER;
199 MS_MALLOC(buf, (unsigned int)(recv_msg->dest_path_size));
201 MSAPI_DBG_STRERROR("malloc failed");
202 return MS_MEDIA_ERR_OUT_OF_MEMORY;
205 if ((recv_msg_size = recv(sockfd, buf, recv_msg->dest_path_size, 0)) < 0) {
207 if (errno == EWOULDBLOCK) {
208 MSAPI_DBG_ERR("Timeout. Can't try any more");
209 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
211 MSAPI_DBG_ERR("recv failed");
212 return MS_MEDIA_ERR_SOCKET_RECEIVE;
217 strncpy(recv_msg->dst_path, (char*)buf, recv_msg->dest_path_size);
221 ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
223 MSAPI_DBG_ERR("cynara_creds_socket_get_pid failed");
224 return MS_MEDIA_ERR_INTERNAL;
227 ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
229 MSAPI_DBG_ERR("cynara_creds_socket_get_user failed");
230 return MS_MEDIA_ERR_INTERNAL;
233 ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
235 MSAPI_DBG_ERR("cynara_creds_socket_get_client failed");
236 return MS_MEDIA_ERR_INTERNAL;
239 // MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
241 return MS_MEDIA_ERR_NONE;
244 int ms_cynara_check(const ms_peer_credentials *creds, const char *privilege)
249 if (!creds || !privilege)
250 return MS_MEDIA_ERR_INVALID_PARAMETER;
252 session = cynara_session_from_pid(creds->pid);
253 if (session == NULL) {
254 MSAPI_DBG_ERR("cynara_session_from_pid failed");
255 return MS_MEDIA_ERR_INTERNAL;
258 G_LOCK(cynara_mutex);
259 result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege);
260 G_UNLOCK(cynara_mutex);
263 ms_cynara_dbg_err("cynara_check", result);
265 MS_SAFE_FREE(session);
266 return result == CYNARA_API_ACCESS_ALLOWED ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_PERMISSION_DENIED;
269 int ms_cynara_enable_credentials_passing(int fd)
271 const int optval = 1;
274 r = setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval));
276 MSAPI_DBG_ERR("Failed to set SO_PASSSEC socket option");
277 return MS_MEDIA_ERR_SOCKET_INTERNAL;
280 r = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
282 MSAPI_DBG_ERR("Failed to set SO_PASSCRED socket option");
283 return MS_MEDIA_ERR_SOCKET_INTERNAL;
286 return MS_MEDIA_ERR_NONE;