Code cleanup in media-util
[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 #include <errno.h>
32 #include <glib.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/socket.h>
36 #include <unistd.h>
37
38 #include <media-util-cynara.h>
39 #include <media-util-dbg.h>
40 #include <media-util-err.h>
41 #include <media-util-ipc.h>
42 #include <media-util-internal.h>
43
44 #include <cynara-client.h>
45 #include <cynara-session.h>
46 #include <cynara-error.h>
47 #include <cynara-creds-socket.h>
48
49 /* this definition is missing in glibc headers (version 2.21). It was introduced in kernel version 2.6.17 */
50 #ifndef SCM_SECURITY
51 #define SCM_SECURITY 0x03
52 #endif
53
54 static cynara *_cynara = NULL;
55 static cynara_configuration *_p_conf = NULL;
56 G_LOCK_DEFINE_STATIC(cynara_mutex);
57
58 static void ms_cynara_dbg_err(const char *prefix, int error_code)
59 {
60         char error_buffer[256];
61         int err;
62         error_buffer[0] = '\0';
63
64         err = cynara_strerror(error_code, error_buffer, sizeof(error_buffer));
65         if (err == CYNARA_API_SUCCESS)
66                 MSAPI_DBG_ERR("%s: %s", prefix, error_buffer);
67         else
68                 MSAPI_DBG_ERR("%s: error code %i", prefix, error_code);
69 }
70
71 int ms_cynara_initialize(void)
72 {
73         int ret = 0;
74
75         ret = cynara_configuration_create(&_p_conf);
76         if (ret != CYNARA_API_SUCCESS)  {
77                 ms_cynara_dbg_err("cynara_configuration_create", ret);
78                 return MS_MEDIA_ERR_INTERNAL;
79         }
80         ret = cynara_configuration_set_cache_size(_p_conf, 100);
81         if (ret != CYNARA_API_SUCCESS)  {
82                 ms_cynara_dbg_err("cynara_configuration_set_cache_size", ret);
83                 return MS_MEDIA_ERR_INTERNAL;
84         }
85         ret = cynara_initialize(&_cynara, _p_conf);
86         if (ret  != CYNARA_API_SUCCESS) {
87                 ms_cynara_dbg_err("cynara_initialize", ret);
88                 return MS_MEDIA_ERR_INTERNAL;
89         }
90
91         cynara_configuration_destroy(_p_conf);
92
93         return MS_MEDIA_ERR_NONE;
94 }
95
96 void ms_cynara_finish(void)
97 {
98         cynara_finish(_cynara);
99         _cynara = NULL;
100 }
101
102 int ms_cynara_receive_untrusted_message(int sockfd, ms_comm_msg_s *recv_msg, ms_peer_credentials *credentials)
103 {
104         int ret = 0;
105         int recv_msg_size = 0;
106
107         if (!recv_msg || !credentials)
108                 return MS_MEDIA_ERR_INVALID_PARAMETER;
109
110         if ((recv_msg_size = read(sockfd, recv_msg, sizeof(ms_comm_msg_s))) < 0) {
111                 if (errno == EWOULDBLOCK) {
112                         MSAPI_DBG_ERR("Timeout. Can't try any more");
113                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
114                 } else {
115                         MSAPI_DBG_ERR("recv failed");
116                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
117                 }
118         }
119
120         MSAPI_DBG_SLOG("receive msg from [%d] %d, %s", recv_msg->pid, recv_msg->msg_type, recv_msg->msg);
121
122         if (!(recv_msg->msg_size > 0 && recv_msg->msg_size < MAX_MSG_SIZE)) {
123                 MSAPI_DBG_ERR("IPC message is wrong. message size is %d", recv_msg->msg_size);
124                 return MS_MEDIA_ERR_INVALID_IPC_MESSAGE;
125         }
126
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");
129
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");
132
133         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
134         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get smack");
135
136 //      MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
137
138         return MS_MEDIA_ERR_NONE;
139 }
140
141 int ms_cynara_receive_untrusted_message_thumb(int sockfd, thumbMsg *recv_msg, ms_peer_credentials *credentials)
142 {
143         int ret = 0;
144         int header_size = 0;
145         int recv_msg_size = 0;
146         unsigned char *buf = NULL;
147
148         if (!recv_msg || !credentials)
149                 return MS_MEDIA_ERR_INVALID_PARAMETER;
150
151         header_size = sizeof(thumbMsg) -(MAX_FILEPATH_LEN * 2) - sizeof(unsigned char *);
152         MS_MALLOC(buf, header_size);
153
154         if ((recv_msg_size = recv(sockfd, buf, header_size, 0)) < 0) {
155                 if (errno == EWOULDBLOCK) {
156                         MSAPI_DBG_ERR("Timeout. Can't try any more");
157                         MS_SAFE_FREE(buf);
158                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
159                 } else {
160                         MSAPI_DBG_ERR("recv failed");
161                         MS_SAFE_FREE(buf);
162                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
163                 }
164         }
165
166         memcpy(recv_msg, buf, header_size);
167         MS_SAFE_FREE(buf);
168
169         if (recv_msg->origin_path_size <= 0) {
170                 MSAPI_DBG_ERR("msg->origin_path_size is invalid %d", recv_msg->origin_path_size);
171                 return MS_MEDIA_ERR_INVALID_PARAMETER;
172         }
173
174         MS_MALLOC(buf, (unsigned int)(recv_msg->origin_path_size));
175         if (buf == NULL) {
176                 MSAPI_DBG_STRERROR("malloc failed");
177                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
178         }
179
180         if ((recv_msg_size = recv(sockfd, buf, recv_msg->origin_path_size, 0)) < 0) {
181                 MS_SAFE_FREE(buf);
182                 if (errno == EWOULDBLOCK) {
183                         MSAPI_DBG_ERR("Timeout. Can't try any more");
184                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
185                 } else {
186                         MSAPI_DBG_ERR("recv failed");
187                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
188                 }
189
190         }
191
192         SAFE_STRLCPY(recv_msg->org_path, (char*)buf, sizeof(recv_msg->org_path));
193         MS_SAFE_FREE(buf);
194
195         if (recv_msg->dest_path_size <= 0) {
196                 MSAPI_DBG_ERR("msg->origin_path_size is invalid %d", recv_msg->dest_path_size);
197                 return MS_MEDIA_ERR_INVALID_PARAMETER;
198         }
199
200         MS_MALLOC(buf, (unsigned int)(recv_msg->dest_path_size));
201         if (buf == NULL) {
202                 MSAPI_DBG_STRERROR("malloc failed");
203                 return MS_MEDIA_ERR_OUT_OF_MEMORY;
204         }
205
206         if ((recv_msg_size = recv(sockfd, buf, recv_msg->dest_path_size, 0)) < 0) {
207                 MS_SAFE_FREE(buf);
208                 if (errno == EWOULDBLOCK) {
209                         MSAPI_DBG_ERR("Timeout. Can't try any more");
210                         return MS_MEDIA_ERR_SOCKET_RECEIVE_TIMEOUT;
211                 } else {
212                         MSAPI_DBG_ERR("recv failed");
213                         return MS_MEDIA_ERR_SOCKET_RECEIVE;
214                 }
215
216         }
217
218         SAFE_STRLCPY(recv_msg->dst_path, (char*)buf, sizeof(recv_msg->dst_path));
219         MS_SAFE_FREE(buf);
220
221         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
222         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get pid");
223
224         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
225         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get uid");
226
227         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
228         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get smack");
229
230 //      MSAPI_DBG_ERR("cynara_creds_info : P[%d]U[%s]S[%s]", credentials->pid, credentials->uid, credentials->smack);
231
232         return MS_MEDIA_ERR_NONE;
233 }
234
235 int ms_cynara_check(const ms_peer_credentials *creds, const char *privilege)
236 {
237         int result;
238         char *session;
239
240         if (!creds || !privilege)
241                 return MS_MEDIA_ERR_INVALID_PARAMETER;
242
243         session = cynara_session_from_pid(creds->pid);
244         MSAPI_RETVM_IF(session == NULL, MS_MEDIA_ERR_INTERNAL, "cynara_session_from_pid failed");
245
246         G_LOCK(cynara_mutex);
247         result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege);
248         G_UNLOCK(cynara_mutex);
249
250         if (result != CYNARA_API_ACCESS_ALLOWED)
251                 ms_cynara_dbg_err("cynara_check", result);
252
253         MS_SAFE_FREE(session);
254         return result == CYNARA_API_ACCESS_ALLOWED ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_PERMISSION_DENIED;
255 }
256
257 int ms_cynara_enable_credentials_passing(int fd)
258 {
259         const int optval = 1;
260         int err;
261
262         err = setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval));
263         MSAPI_RETVM_IF(err != 0, MS_MEDIA_ERR_SOCKET_INTERNAL, "Failed to set SO_PASSSEC socket option");
264
265         err = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
266         MSAPI_RETVM_IF(err != 0, MS_MEDIA_ERR_SOCKET_INTERNAL, "Failed to set SO_PASSCRED socket option");
267
268         return MS_MEDIA_ERR_NONE;
269 }
270