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)
34 #include <media-util-cynara.h>
35 #include <media-util-dbg.h>
36 #include <media-util-err.h>
37 #include <media-util-internal.h>
39 #include <cynara-client.h>
40 #include <cynara-session.h>
41 #include <cynara-error.h>
42 #include <cynara-creds-socket.h>
44 /* this definition is missing in glibc headers (version 2.21). It was introduced in kernel version 2.6.17 */
46 #define SCM_SECURITY 0x03
49 static cynara *_cynara = NULL;
50 static cynara_configuration *_p_conf = NULL;
51 G_LOCK_DEFINE_STATIC(cynara_mutex);
53 static void ms_cynara_dbg_err(const char *prefix, int error_code)
55 char error_buffer[256];
57 error_buffer[0] = '\0';
59 err = cynara_strerror(error_code, error_buffer, sizeof(error_buffer));
60 if (err == CYNARA_API_SUCCESS)
61 MSAPI_DBG_ERR("%s: %s", prefix, error_buffer);
63 MSAPI_DBG_ERR("%s: error code %i", prefix, error_code);
66 int ms_cynara_initialize(void)
70 ret = cynara_configuration_create(&_p_conf);
71 if (ret != CYNARA_API_SUCCESS) {
72 ms_cynara_dbg_err("cynara_configuration_create", ret);
73 return MS_MEDIA_ERR_INTERNAL;
75 ret = cynara_configuration_set_cache_size(_p_conf, 100);
76 if (ret != CYNARA_API_SUCCESS) {
77 ms_cynara_dbg_err("cynara_configuration_set_cache_size", ret);
78 return MS_MEDIA_ERR_INTERNAL;
80 ret = cynara_initialize(&_cynara, _p_conf);
81 if (ret != CYNARA_API_SUCCESS) {
82 ms_cynara_dbg_err("cynara_initialize", ret);
83 return MS_MEDIA_ERR_INTERNAL;
86 cynara_configuration_destroy(_p_conf);
88 return MS_MEDIA_ERR_NONE;
91 void ms_cynara_finish(void)
93 cynara_finish(_cynara);
97 int ms_cynara_receive_untrusted_message(int sockfd, ms_comm_msg_s *recv_msg, ms_peer_credentials *credentials)
100 int recv_msg_size = 0;
102 if (!recv_msg || !credentials)
103 return MS_MEDIA_ERR_INVALID_PARAMETER;
105 if ((recv_msg_size = read(sockfd, recv_msg, sizeof(ms_comm_msg_s))) < 0) {
106 if (errno == EWOULDBLOCK) {
107 MSAPI_DBG_ERR("Timeout. Can't try any more");
108 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
110 MSAPI_DBG_ERR("recv failed");
111 return MS_MEDIA_ERR_SOCKET_RECEIVE;
115 MSAPI_DBG_SLOG("receive msg from P[%d] T[%d] M[%.*s] S[%.*s]", recv_msg->pid, recv_msg->msg_type, MAX_MSG_SIZE, recv_msg->msg, MS_UUID_SIZE, recv_msg->storage_id);
117 if (strlen(recv_msg->msg) == 0 || strlen(recv_msg->msg) >= MAX_MSG_SIZE) {
118 MSAPI_DBG_ERR("IPC message is wrong. message size is %d", strlen(recv_msg->msg));
119 return MS_MEDIA_ERR_INVALID_IPC_MESSAGE;
122 if (strlen(recv_msg->storage_id) >= MS_UUID_SIZE) {
123 MSAPI_DBG_ERR("IPC message is wrong. storage_id size is %d", strlen(recv_msg->storage_id));
124 return MS_MEDIA_ERR_INVALID_IPC_MESSAGE;
127 ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
128 MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get pid");
130 ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
131 MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get uid");
133 ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
135 MSAPI_DBG_ERR("[CYNARA]Failed to get smack");
136 MS_SAFE_FREE(credentials->uid);
138 return MS_MEDIA_ERR_INTERNAL;
141 // MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
143 return MS_MEDIA_ERR_NONE;
146 int ms_cynara_receive_untrusted_message_thumb(int sockfd, thumbMsg *recv_msg, ms_peer_credentials *credentials)
150 int recv_msg_size = 0;
151 unsigned char *buf = NULL;
153 if (!recv_msg || !credentials)
154 return MS_MEDIA_ERR_INVALID_PARAMETER;
156 header_size = sizeof(thumbMsg) - sizeof(unsigned char *);
157 MS_MALLOC(buf, header_size);
159 if ((recv_msg_size = recv(sockfd, buf, header_size, 0)) < 0) {
160 if (errno == EWOULDBLOCK) {
161 MSAPI_DBG_ERR("Timeout. Can't try any more");
163 return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
165 MSAPI_DBG_ERR("recv failed");
167 return MS_MEDIA_ERR_SOCKET_RECEIVE;
171 memcpy(recv_msg, buf, header_size);
174 /* Can be null (kill server msg) */
175 if (strlen(recv_msg->org_path) >= MAX_FILEPATH_LEN) {
176 MSAPI_DBG_ERR("org_path size is invlid[%d]", strlen(recv_msg->org_path));
177 return MS_MEDIA_ERR_INVALID_IPC_MESSAGE;
180 /* Can be null (raw request case) */
181 if (strlen(recv_msg->dst_path) >= MAX_FILEPATH_LEN) {
182 MSAPI_DBG_ERR("dst_path size is invlid[%d]", strlen(recv_msg->dst_path));
183 return MS_MEDIA_ERR_INVALID_IPC_MESSAGE;
186 ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
187 MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get pid");
189 ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
190 MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get uid");
192 ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
193 MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get smack");
195 // MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
197 return MS_MEDIA_ERR_NONE;
200 int ms_cynara_check(const ms_peer_credentials *creds, const char *privilege)
205 if (!creds || !privilege)
206 return MS_MEDIA_ERR_INVALID_PARAMETER;
208 session = cynara_session_from_pid(creds->pid);
209 MSAPI_RETVM_IF(session == NULL, MS_MEDIA_ERR_INTERNAL, "cynara_session_from_pid failed");
211 G_LOCK(cynara_mutex);
212 result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege);
213 G_UNLOCK(cynara_mutex);
215 if (result != CYNARA_API_ACCESS_ALLOWED)
216 ms_cynara_dbg_err("cynara_check", result);
218 MS_SAFE_FREE(session);
219 return result == CYNARA_API_ACCESS_ALLOWED ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_PERMISSION_DENIED;
222 int ms_cynara_enable_credentials_passing(int fd)
224 const int optval = 1;
227 err = setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval));
228 MSAPI_RETVM_IF(err != 0, MS_MEDIA_ERR_SOCKET_INTERNAL, "Failed to set SO_PASSSEC socket option");
230 err = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
231 MSAPI_RETVM_IF(err != 0, MS_MEDIA_ERR_SOCKET_INTERNAL, "Failed to set SO_PASSCRED socket option");
233 return MS_MEDIA_ERR_NONE;