Integrate IPC related errors
[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 <glib.h>
32 #include <unistd.h>
33
34 #include <media-util-cynara.h>
35 #include <media-util-dbg.h>
36 #include <media-util-err.h>
37 #include <media-util-internal.h>
38
39 #include <cynara-client.h>
40 #include <cynara-session.h>
41 #include <cynara-error.h>
42 #include <cynara-creds-socket.h>
43
44 static cynara *_cynara = NULL;
45 static cynara_configuration *_p_conf = NULL;
46 G_LOCK_DEFINE_STATIC(cynara_mutex);
47
48 static void ms_cynara_dbg_err(const char *prefix, int error_code)
49 {
50         char error_buffer[256];
51         int err;
52         error_buffer[0] = '\0';
53
54         err = cynara_strerror(error_code, error_buffer, sizeof(error_buffer));
55         if (err == CYNARA_API_SUCCESS)
56                 MSAPI_DBG_ERR("%s: %s", prefix, error_buffer);
57         else
58                 MSAPI_DBG_ERR("%s: error code %i", prefix, error_code);
59 }
60
61 int ms_cynara_initialize(void)
62 {
63         int ret = 0;
64
65         ret = cynara_configuration_create(&_p_conf);
66         if (ret != CYNARA_API_SUCCESS)  {
67                 ms_cynara_dbg_err("cynara_configuration_create", ret);
68                 return MS_MEDIA_ERR_INTERNAL;
69         }
70         ret = cynara_configuration_set_cache_size(_p_conf, 100);
71         if (ret != CYNARA_API_SUCCESS)  {
72                 ms_cynara_dbg_err("cynara_configuration_set_cache_size", ret);
73                 return MS_MEDIA_ERR_INTERNAL;
74         }
75         ret = cynara_initialize(&_cynara, _p_conf);
76         if (ret  != CYNARA_API_SUCCESS) {
77                 ms_cynara_dbg_err("cynara_initialize", ret);
78                 return MS_MEDIA_ERR_INTERNAL;
79         }
80
81         cynara_configuration_destroy(_p_conf);
82
83         return MS_MEDIA_ERR_NONE;
84 }
85
86 void ms_cynara_finish(void)
87 {
88         cynara_finish(_cynara);
89         _cynara = NULL;
90 }
91
92 int ms_cynara_receive_untrusted_message(int sockfd, ms_comm_msg_s *recv_msg, ms_peer_credentials *credentials)
93 {
94         int ret = 0;
95         int recv_msg_size = 0;
96
97         if (!recv_msg || !credentials)
98                 return MS_MEDIA_ERR_INVALID_PARAMETER;
99
100         if ((recv_msg_size = read(sockfd, recv_msg, sizeof(ms_comm_msg_s))) < 0) {
101                 MSAPI_DBG_STRERROR("recv failed");
102                 return MS_MEDIA_ERR_IPC;
103         }
104
105         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);
106
107         if (strlen(recv_msg->msg) == 0 || strlen(recv_msg->msg) >= MAX_MSG_SIZE) {
108                 MSAPI_DBG_ERR("IPC message is wrong. message size is over MAX_MSG_SIZE");
109                 return MS_MEDIA_ERR_IPC;
110         }
111
112         if (strlen(recv_msg->storage_id) >= MS_UUID_SIZE) {
113                 MSAPI_DBG_ERR("IPC message is wrong. storage_id size is over MS_UUID_SIZE");
114                 return MS_MEDIA_ERR_IPC;
115         }
116
117         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
118         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get pid");
119
120         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
121         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get uid");
122
123         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
124         if (ret != 0) {
125                 MSAPI_DBG_ERR("[CYNARA]Failed to get smack");
126                 MS_SAFE_FREE(credentials->uid);
127
128                 return MS_MEDIA_ERR_INTERNAL;
129         }
130
131         return MS_MEDIA_ERR_NONE;
132 }
133
134 int ms_cynara_receive_untrusted_message_thumb(int sockfd, thumbMsg *recv_msg, ms_peer_credentials *credentials)
135 {
136         int ret = 0;
137         unsigned int header_size = 0;
138         int recv_msg_size = 0;
139         unsigned char *buf = NULL;
140
141         if (!recv_msg || !credentials)
142                 return MS_MEDIA_ERR_INVALID_PARAMETER;
143
144         header_size = sizeof(thumbMsg) - sizeof(unsigned char *);
145         MS_MALLOC(buf, header_size);
146
147         if ((recv_msg_size = recv(sockfd, buf, header_size, 0)) < 0) {
148                 MSAPI_DBG_STRERROR("recv failed");
149                 MS_SAFE_FREE(buf);
150                 return MS_MEDIA_ERR_IPC;
151         }
152
153         memcpy(recv_msg, buf, header_size);
154         MS_SAFE_FREE(buf);
155
156         /* Can be null (kill server msg) */
157         if (strlen(recv_msg->org_path) >= MAX_FILEPATH_LEN) {
158                 MSAPI_DBG_ERR("org_path size is invlid[%zu]", strlen(recv_msg->org_path));
159                 return MS_MEDIA_ERR_IPC;
160         }
161
162         /* Can be null (raw request case) */
163         if (strlen(recv_msg->dst_path) >= MAX_FILEPATH_LEN) {
164                 MSAPI_DBG_ERR("dst_path size is invlid[%zu]", strlen(recv_msg->dst_path));
165                 return MS_MEDIA_ERR_IPC;
166         }
167
168         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
169         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get pid");
170
171         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
172         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get uid");
173
174         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
175         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get smack");
176
177         return MS_MEDIA_ERR_NONE;
178 }
179
180 int ms_cynara_check(const ms_peer_credentials *creds, const char *privilege)
181 {
182         int result;
183         char *session;
184
185         if (!creds || !privilege)
186                 return MS_MEDIA_ERR_INVALID_PARAMETER;
187
188         session = cynara_session_from_pid(creds->pid);
189         MSAPI_RETVM_IF(session == NULL, MS_MEDIA_ERR_INTERNAL, "cynara_session_from_pid failed");
190
191         G_LOCK(cynara_mutex);
192         result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege);
193         G_UNLOCK(cynara_mutex);
194
195         if (result != CYNARA_API_ACCESS_ALLOWED)
196                 ms_cynara_dbg_err("cynara_check", result);
197
198         MS_SAFE_FREE(session);
199         return result == CYNARA_API_ACCESS_ALLOWED ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_PERMISSION_DENIED;
200 }
201
202 int ms_cynara_enable_credentials_passing(int fd)
203 {
204         const int optval = 1;
205         int err;
206
207         err = setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval));
208         MSAPI_RETVM_IF(err != 0, MS_MEDIA_ERR_IPC, "Failed to set SO_PASSSEC socket option");
209
210         err = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
211         MSAPI_RETVM_IF(err != 0, MS_MEDIA_ERR_IPC, "Failed to set SO_PASSCRED socket option");
212
213         return MS_MEDIA_ERR_NONE;
214 }
215