Apply tizen coding rule
[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 G_LOCK_DEFINE_STATIC(cynara_mutex);
59
60 static void ms_cynara_dbg_err(const char *prefix, int error_code)
61 {
62         char error_buffer[256];
63         int err;
64         error_buffer[0] = '\0';
65
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);
69         } else {
70                 MSAPI_DBG_ERR("%s: error code %i", prefix, error_code);
71         }
72 }
73
74 int ms_cynara_initialize(void)
75 {
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;
80         }
81
82         return MS_MEDIA_ERR_NONE;
83 }
84
85 void ms_cynara_finish(void)
86 {
87         cynara_finish(_cynara);
88         _cynara = NULL;
89 }
90
91 int ms_cynara_receive_untrusted_message(int sockfd, ms_comm_msg_s *recv_msg, ms_peer_credentials *credentials)
92 {
93         int ret = 0;
94         int recv_msg_size = 0;
95
96         if (!recv_msg || !credentials)
97                 return MS_MEDIA_ERR_INVALID_PARAMETER;
98
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;
103                 } else {
104                         MSAPI_DBG_ERR("recv failed");
105                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
106                 }
107         }
108
109         MSAPI_DBG_SLOG("receive msg from [%d] %d, %s", recv_msg->pid, recv_msg->msg_type, recv_msg->msg);
110
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;
114         }
115
116         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
117         if (ret < 0) {
118                 MSAPI_DBG_ERR("cynara_creds_socket_get_pid failed");
119                 return MS_MEDIA_ERR_INTERNAL;
120         }
121
122         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
123         if (ret < 0) {
124                 MSAPI_DBG_ERR("cynara_creds_socket_get_user failed");
125                 return MS_MEDIA_ERR_INTERNAL;
126         }
127
128         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
129         if (ret < 0) {
130                 MSAPI_DBG_ERR("cynara_creds_socket_get_client failed");
131                 return MS_MEDIA_ERR_INTERNAL;
132         }
133
134 //      MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
135
136         return MS_MEDIA_ERR_NONE;
137 }
138
139 int ms_cynara_receive_untrusted_message_thumb(int sockfd, thumbMsg *recv_msg, ms_peer_credentials *credentials)
140 {
141         int ret = 0;
142         int header_size = 0;
143         int recv_msg_size = 0;
144         unsigned char *buf = NULL;
145
146         if (!recv_msg || !credentials)
147                 return MS_MEDIA_ERR_INVALID_PARAMETER;
148
149         header_size = sizeof(thumbMsg) -(MAX_FILEPATH_LEN * 2) - sizeof(unsigned char *);
150         MS_MALLOC(buf, header_size);
151
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;
156                 } else {
157                         MSAPI_DBG_ERR("recv failed");
158                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
159                 }
160         }
161
162         memcpy(recv_msg, buf, header_size);
163
164         MS_SAFE_FREE(buf);
165
166         if (recv_msg->origin_path_size <= 0) {
167                 MS_SAFE_FREE(buf);
168                 MSAPI_DBG_ERR("msg->origin_path_size is invalid %d", recv_msg->origin_path_size);
169                 return MS_MEDIA_ERR_INVALID_PARAMETER;
170         }
171
172         MS_MALLOC(buf, (unsigned int)(recv_msg->origin_path_size));
173         if (buf == NULL) {
174                 MSAPI_DBG_STRERROR("malloc failed");
175                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
176         }
177
178         if ((recv_msg_size = recv(sockfd, buf, recv_msg->origin_path_size, 0)) < 0) {
179                 MS_SAFE_FREE(buf);
180                 if (errno == EWOULDBLOCK) {
181                         MSAPI_DBG_ERR("Timeout. Can't try any more");
182                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
183                 } else {
184                         MSAPI_DBG_ERR("recv failed");
185                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
186                 }
187
188         }
189
190         strncpy(recv_msg->org_path, (char*)buf, recv_msg->origin_path_size);
191         MS_SAFE_FREE(buf);
192
193         if (recv_msg->dest_path_size <= 0) {
194                 MS_SAFE_FREE(buf);
195                 MSAPI_DBG_ERR("msg->origin_path_size is invalid %d", recv_msg->dest_path_size);
196                 return MS_MEDIA_ERR_INVALID_PARAMETER;
197         }
198
199         MS_MALLOC(buf, (unsigned int)(recv_msg->dest_path_size));
200         if (buf == NULL) {
201                 MSAPI_DBG_STRERROR("malloc failed");
202                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
203         }
204
205         if ((recv_msg_size = recv(sockfd, buf, recv_msg->dest_path_size, 0)) < 0) {
206                 MS_SAFE_FREE(buf);
207                 if (errno == EWOULDBLOCK) {
208                         MSAPI_DBG_ERR("Timeout. Can't try any more");
209                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
210                 } else {
211                         MSAPI_DBG_ERR("recv failed");
212                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
213                 }
214
215         }
216
217         strncpy(recv_msg->dst_path, (char*)buf, recv_msg->dest_path_size);
218         MS_SAFE_FREE(buf);
219
220
221         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
222         if (ret < 0) {
223                 MSAPI_DBG_ERR("cynara_creds_socket_get_pid failed");
224                 return MS_MEDIA_ERR_INTERNAL;
225         }
226
227         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
228         if (ret < 0) {
229                 MSAPI_DBG_ERR("cynara_creds_socket_get_user failed");
230                 return MS_MEDIA_ERR_INTERNAL;
231         }
232
233         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
234         if (ret < 0) {
235                 MSAPI_DBG_ERR("cynara_creds_socket_get_client failed");
236                 return MS_MEDIA_ERR_INTERNAL;
237         }
238
239 //      MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
240
241         return MS_MEDIA_ERR_NONE;
242 }
243
244 int ms_cynara_check(const ms_peer_credentials *creds, const char *privilege)
245 {
246         int result;
247         char *session;
248
249         if (!creds || !privilege)
250                 return MS_MEDIA_ERR_INVALID_PARAMETER;
251
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;
256         }
257
258         G_LOCK(cynara_mutex);
259         result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege);
260         G_UNLOCK(cynara_mutex);
261
262         if (result != CYNARA_API_ACCESS_ALLOWED)
263                 ms_cynara_dbg_err("cynara_check", result);
264
265         MS_SAFE_FREE(session);
266         return result == CYNARA_API_ACCESS_ALLOWED ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_PERMISSION_DENIED;
267 }
268
269 int ms_cynara_enable_credentials_passing(int fd)
270 {
271         const int optval = 1;
272         int err;
273
274         err = setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval));
275         if (err != 0) {
276                 MSAPI_DBG_ERR("Failed to set SO_PASSSEC socket option");
277                 return MS_MEDIA_ERR_SOCKET_INTERNAL;
278         }
279
280         err = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
281         if (err != 0) {
282                 MSAPI_DBG_ERR("Failed to set SO_PASSCRED socket option");
283                 return MS_MEDIA_ERR_SOCKET_INTERNAL;
284         }
285
286         return MS_MEDIA_ERR_NONE;
287 }
288
289