Unify dulicated code regarding checking msg validity
[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_RETVM_IF(!ms_ipc_is_valid_msg(recv_msg->msg), MS_MEDIA_ERR_IPC, "Invalid msg");
106
107         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);
108
109         if (strlen(recv_msg->storage_id) >= MS_UUID_SIZE) {
110                 MSAPI_DBG_ERR("IPC message is wrong. storage_id size is over MS_UUID_SIZE");
111                 return MS_MEDIA_ERR_IPC;
112         }
113
114         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
115         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get pid");
116
117         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
118         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get uid");
119
120         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
121         if (ret != 0) {
122                 MSAPI_DBG_ERR("[CYNARA]Failed to get smack");
123                 MS_SAFE_FREE(credentials->uid);
124
125                 return MS_MEDIA_ERR_INTERNAL;
126         }
127
128         return MS_MEDIA_ERR_NONE;
129 }
130
131 int ms_cynara_receive_untrusted_message_thumb(int sockfd, thumbMsg *recv_msg, ms_peer_credentials *credentials)
132 {
133         int ret = 0;
134         unsigned int header_size = 0;
135         int recv_msg_size = 0;
136         unsigned char *buf = NULL;
137
138         if (!recv_msg || !credentials)
139                 return MS_MEDIA_ERR_INVALID_PARAMETER;
140
141         header_size = sizeof(thumbMsg) - sizeof(unsigned char *);
142         MS_MALLOC(buf, header_size);
143
144         if ((recv_msg_size = recv(sockfd, buf, header_size, 0)) < 0) {
145                 MSAPI_DBG_STRERROR("recv failed");
146                 MS_SAFE_FREE(buf);
147                 return MS_MEDIA_ERR_IPC;
148         }
149
150         memcpy(recv_msg, buf, header_size);
151         MS_SAFE_FREE(buf);
152
153         /* Can be null (kill server msg) */
154         if (strlen(recv_msg->org_path) >= MAX_FILEPATH_LEN) {
155                 MSAPI_DBG_ERR("org_path size is invlid[%zu]", strlen(recv_msg->org_path));
156                 return MS_MEDIA_ERR_IPC;
157         }
158
159         /* Can be null (raw request case) */
160         if (strlen(recv_msg->dst_path) >= MAX_FILEPATH_LEN) {
161                 MSAPI_DBG_ERR("dst_path size is invlid[%zu]", strlen(recv_msg->dst_path));
162                 return MS_MEDIA_ERR_IPC;
163         }
164
165         ret = cynara_creds_socket_get_pid(sockfd, &(credentials->pid));
166         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get pid");
167
168         ret = cynara_creds_socket_get_user(sockfd, USER_METHOD_UID, &(credentials->uid));
169         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get uid");
170
171         ret = cynara_creds_socket_get_client(sockfd, CLIENT_METHOD_SMACK, &(credentials->smack));
172         MSAPI_RETVM_IF(ret != 0, MS_MEDIA_ERR_INTERNAL, "[CYNARA]Failed to get smack");
173
174         return MS_MEDIA_ERR_NONE;
175 }
176
177 int ms_cynara_check(const ms_peer_credentials *creds, const char *privilege)
178 {
179         int result;
180         char *session;
181
182         if (!creds || !privilege)
183                 return MS_MEDIA_ERR_INVALID_PARAMETER;
184
185         session = cynara_session_from_pid(creds->pid);
186         MSAPI_RETVM_IF(session == NULL, MS_MEDIA_ERR_INTERNAL, "cynara_session_from_pid failed");
187
188         G_LOCK(cynara_mutex);
189         result = cynara_check(_cynara, creds->smack, session, creds->uid, privilege);
190         G_UNLOCK(cynara_mutex);
191
192         if (result != CYNARA_API_ACCESS_ALLOWED)
193                 ms_cynara_dbg_err("cynara_check", result);
194
195         MS_SAFE_FREE(session);
196         return result == CYNARA_API_ACCESS_ALLOWED ? MS_MEDIA_ERR_NONE : MS_MEDIA_ERR_PERMISSION_DENIED;
197 }
198
199 int ms_cynara_enable_credentials_passing(int fd)
200 {
201         const int optval = 1;
202         int err;
203
204         err = setsockopt(fd, SOL_SOCKET, SO_PASSSEC, &optval, sizeof(optval));
205         MSAPI_RETVM_IF(err != 0, MS_MEDIA_ERR_IPC, "Failed to set SO_PASSSEC socket option");
206
207         err = setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
208         MSAPI_RETVM_IF(err != 0, MS_MEDIA_ERR_IPC, "Failed to set SO_PASSCRED socket option");
209
210         return MS_MEDIA_ERR_NONE;
211 }
212