Fix bug : wrong received message size
[platform/core/multimedia/media-server.git] / lib / media-util-cynara.c
1 /*
2  * Media Server
3  *
4  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Yong Yeon Kim <yy9875.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 /**
23  * This file contains Cynara integration code
24  *
25  * @file                media-util-cynara.c
26  * @author      Jacek Bukarewicz (j.bukarewicz@samsung.com)
27  * @version     1.0
28  * @brief
29  */
30
31 #define _GNU_SOURCE
32
33 #include <errno.h>
34 #include <glib.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <sys/socket.h>
38 #include <unistd.h>
39
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>
45
46 #include <cynara-client.h>
47 #include <cynara-session.h>
48 #include <cynara-error.h>
49 #include <cynara-creds-socket.h>
50
51
52 /* this definition is missing in glibc headers (version 2.21). It was introduced in kernel version 2.6.17 */
53 #ifndef SCM_SECURITY
54 #define SCM_SECURITY 0x03
55 #endif
56
57 static cynara *_cynara = NULL;
58 static cynara_configuration *_p_conf = NULL;
59 G_LOCK_DEFINE_STATIC(cynara_mutex);
60
61 static void ms_cynara_dbg_err(const char *prefix, int error_code)
62 {
63         char error_buffer[256];
64         int err;
65         error_buffer[0] = '\0';
66
67         err = cynara_strerror(error_code, error_buffer, sizeof(error_buffer));
68         if (err == CYNARA_API_SUCCESS) {
69                 MSAPI_DBG_ERR("%s: %s", prefix, error_buffer);
70         } else {
71                 MSAPI_DBG_ERR("%s: error code %i", prefix, error_code);
72         }
73 }
74
75 int ms_cynara_initialize(void)
76 {
77         int ret = 0;
78
79         ret = cynara_configuration_create(&_p_conf);
80         if (ret != CYNARA_API_SUCCESS)  {
81                 ms_cynara_dbg_err("cynara_configuration_create", ret);
82                 return MS_MEDIA_ERR_INTERNAL;
83         }
84         ret = cynara_configuration_set_cache_size(_p_conf, 100);
85         if (ret != CYNARA_API_SUCCESS)  {
86                 ms_cynara_dbg_err("cynara_configuration_set_cache_size", ret);
87                 return MS_MEDIA_ERR_INTERNAL;
88         }
89         ret = cynara_initialize(&_cynara, _p_conf);
90         if (ret  != CYNARA_API_SUCCESS) {
91                 ms_cynara_dbg_err("cynara_initialize", ret);
92                 return MS_MEDIA_ERR_INTERNAL;
93         }
94
95         cynara_configuration_destroy(_p_conf);
96
97         return MS_MEDIA_ERR_NONE;
98 }
99
100 void ms_cynara_finish(void)
101 {
102         cynara_finish(_cynara);
103         _cynara = NULL;
104 }
105
106 int ms_cynara_receive_untrusted_message(int sockfd, ms_comm_msg_s *recv_msg, ms_peer_credentials *credentials)
107 {
108         int ret = 0;
109         int recv_msg_size = 0;
110
111         if (!recv_msg || !credentials)
112                 return MS_MEDIA_ERR_INVALID_PARAMETER;
113
114         if ((recv_msg_size = read(sockfd, recv_msg, sizeof(ms_comm_msg_s))) < 0) {
115                 if (errno == EWOULDBLOCK) {
116                         MSAPI_DBG_ERR("Timeout. Can't try any more");
117                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
118                 } else {
119                         MSAPI_DBG_ERR("recv failed");
120                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
121                 }
122         }
123
124         MSAPI_DBG_SLOG("receive msg from [%d] %d, %s", recv_msg->pid, recv_msg->msg_type, recv_msg->msg);
125
126         if (!(recv_msg->msg_size > 0 && recv_msg->msg_size < MAX_MSG_SIZE)) {
127                 MSAPI_DBG_ERR("IPC message is wrong. message size is %d", recv_msg->msg_size);
128                 return MS_MEDIA_ERR_INVALID_IPC_MESSAGE;
129         }
130
131         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
132         if (ret < 0) {
133                 MSAPI_DBG_ERR("cynara_creds_socket_get_pid failed");
134                 return MS_MEDIA_ERR_INTERNAL;
135         }
136
137         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
138         if (ret < 0) {
139                 MSAPI_DBG_ERR("cynara_creds_socket_get_user failed");
140                 return MS_MEDIA_ERR_INTERNAL;
141         }
142
143         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
144         if (ret < 0) {
145                 MSAPI_DBG_ERR("cynara_creds_socket_get_client failed");
146                 return MS_MEDIA_ERR_INTERNAL;
147         }
148
149 //      MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
150
151         return MS_MEDIA_ERR_NONE;
152 }
153
154 int ms_cynara_receive_untrusted_message_thumb(int sockfd, thumbMsg *recv_msg, ms_peer_credentials *credentials)
155 {
156         int ret = 0;
157         int header_size = 0;
158         int recv_msg_size = 0;
159         unsigned char *buf = NULL;
160
161         if (!recv_msg || !credentials)
162                 return MS_MEDIA_ERR_INVALID_PARAMETER;
163
164         header_size = sizeof(thumbMsg) -(MAX_FILEPATH_LEN * 2) - sizeof(unsigned char *);
165         MS_MALLOC(buf, header_size);
166
167         if ((recv_msg_size = recv(sockfd, buf, header_size, 0)) < 0) {
168                 if (errno == EWOULDBLOCK) {
169                         MSAPI_DBG_ERR("Timeout. Can't try any more");
170                         MS_SAFE_FREE(buf);
171                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
172                 } else {
173                         MSAPI_DBG_ERR("recv failed");
174                         MS_SAFE_FREE(buf);
175                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
176                 }
177         }
178
179         memcpy(recv_msg, buf, header_size);
180
181         MS_SAFE_FREE(buf);
182
183         if (recv_msg->origin_path_size <= 0) {
184                 MS_SAFE_FREE(buf);
185                 MSAPI_DBG_ERR("msg->origin_path_size is invalid %d", recv_msg->origin_path_size);
186                 return MS_MEDIA_ERR_INVALID_PARAMETER;
187         }
188
189         MS_MALLOC(buf, (unsigned int)(recv_msg->origin_path_size));
190         if (buf == NULL) {
191                 MSAPI_DBG_STRERROR("malloc failed");
192                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
193         }
194
195         if ((recv_msg_size = recv(sockfd, buf, recv_msg->origin_path_size, 0)) < 0) {
196                 MS_SAFE_FREE(buf);
197                 if (errno == EWOULDBLOCK) {
198                         MSAPI_DBG_ERR("Timeout. Can't try any more");
199                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
200                 } else {
201                         MSAPI_DBG_ERR("recv failed");
202                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
203                 }
204
205         }
206
207         strncpy(recv_msg->org_path, (char*)buf, recv_msg->origin_path_size);
208         MS_SAFE_FREE(buf);
209
210         if (recv_msg->dest_path_size <= 0) {
211                 MS_SAFE_FREE(buf);
212                 MSAPI_DBG_ERR("msg->origin_path_size is invalid %d", recv_msg->dest_path_size);
213                 return MS_MEDIA_ERR_INVALID_PARAMETER;
214         }
215
216         MS_MALLOC(buf, (unsigned int)(recv_msg->dest_path_size));
217         if (buf == NULL) {
218                 MSAPI_DBG_STRERROR("malloc failed");
219                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
220         }
221
222         if ((recv_msg_size = recv(sockfd, buf, recv_msg->dest_path_size, 0)) < 0) {
223                 MS_SAFE_FREE(buf);
224                 if (errno == EWOULDBLOCK) {
225                         MSAPI_DBG_ERR("Timeout. Can't try any more");
226                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
227                 } else {
228                         MSAPI_DBG_ERR("recv failed");
229                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
230                 }
231
232         }
233
234         strncpy(recv_msg->dst_path, (char*)buf, recv_msg->dest_path_size);
235         MS_SAFE_FREE(buf);
236
237
238         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
239         if (ret < 0) {
240                 MSAPI_DBG_ERR("cynara_creds_socket_get_pid failed");
241                 return MS_MEDIA_ERR_INTERNAL;
242         }
243
244         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
245         if (ret < 0) {
246                 MSAPI_DBG_ERR("cynara_creds_socket_get_user failed");
247                 return MS_MEDIA_ERR_INTERNAL;
248         }
249
250         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
251         if (ret < 0) {
252                 MSAPI_DBG_ERR("cynara_creds_socket_get_client failed");
253                 return MS_MEDIA_ERR_INTERNAL;
254         }
255
256 //      MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
257
258         return MS_MEDIA_ERR_NONE;
259 }
260
261 int ms_cynara_check(const ms_peer_credentials *creds, const char *privilege)
262 {
263         int result;
264         char *session;
265
266         if (!creds || !privilege)
267                 return MS_MEDIA_ERR_INVALID_PARAMETER;
268
269         session = cynara_session_from_pid(creds->pid);
270         if (session == NULL) {
271                 MSAPI_DBG_ERR("cynara_session_from_pid failed");
272                 return MS_MEDIA_ERR_INTERNAL;
273         }
274
275         G_LOCK(cynara_mutex);
276         result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege);
277         G_UNLOCK(cynara_mutex);
278
279         if (result != CYNARA_API_ACCESS_ALLOWED)
280                 ms_cynara_dbg_err("cynara_check", result);
281
282         MS_SAFE_FREE(session);
283         return result == CYNARA_API_ACCESS_ALLOWED ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_PERMISSION_DENIED;
284 }
285
286 int ms_cynara_enable_credentials_passing(int fd)
287 {
288         const int optval = 1;
289         int err;
290
291         err = setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval));
292         if (err != 0) {
293                 MSAPI_DBG_ERR("Failed to set SO_PASSSEC socket option");
294                 return MS_MEDIA_ERR_SOCKET_INTERNAL;
295         }
296
297         err = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
298         if (err != 0) {
299                 MSAPI_DBG_ERR("Failed to set SO_PASSCRED socket option");
300                 return MS_MEDIA_ERR_SOCKET_INTERNAL;
301         }
302
303         return MS_MEDIA_ERR_NONE;
304 }
305
306