Update doxygen
[platform/core/appfw/message-port.git] / src / message_port_common.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18
19 #include <bundle.h>
20 #include <bundle_internal.h>
21 #include <pkgmgr-info.h>
22 #include <aul.h>
23
24 #include <sys/socket.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <openssl/md5.h>
30 #include <gio/gio.h>
31 #include <pthread.h>
32 #include <glib-unix.h>
33 #include <poll.h>
34
35 #include "message_port_log.h"
36 #include "message_port.h"
37 #include "message_port_common.h"
38
39 #define MAX_PACKAGE_STR_SIZE 512
40 #define MAX_RETRY_CNT 10
41
42 bool initialized_common;
43 GDBusConnection *gdbus_conn;
44 char *app_id;
45
46 static const int MAX_MESSAGE_SIZE = 16 * 1024;
47 static pthread_mutex_t _message_port_mutex = PTHREAD_MUTEX_INITIALIZER;
48
49 int write_socket(int fd,
50                 const char *buffer,
51                 unsigned int nbytes,
52                 unsigned int *bytes_write,
53                 int *sequence)
54 {
55 #define SEND_TIMEOUT 5 /* milliseconds */
56
57         unsigned int left = nbytes;
58         ssize_t nb;
59         int retry_cnt = 0;
60         struct pollfd fds[1];
61         int ret;
62
63         *sequence += 1;
64         *bytes_write = 0;
65
66         fds[0].fd = fd;
67         fds[0].events = POLLOUT;
68         fds[0].revents = 0;
69
70         ret = poll(fds, 1, SEND_TIMEOUT);
71         if (ret == 0) {
72                 LOGE("write_socket: : fd %d poll timeout", fd);
73                 return MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
74         }
75
76         while (left && (retry_cnt < MAX_RETRY_CNT)) {
77                 nb = write(fd, buffer, left);
78                 if (nb == -1) {
79                         if (errno == EINTR) {
80                                 LOGW("write_socket: EINTR continue ...");
81                                 retry_cnt++;
82                                 continue;
83                         }
84                         LOGE("write_socket: ...error fd %d: errno %d\n", fd, errno);
85
86                         if (errno == EWOULDBLOCK || errno == EAGAIN)
87                                 return MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
88
89                         return MESSAGE_PORT_ERROR_IO_ERROR;
90                 }
91
92                 left -= nb;
93                 buffer += nb;
94                 *bytes_write += nb;
95                 retry_cnt = 0;
96         }
97
98         if (left != 0) {
99                 _LOGE("error fd %d: retry_cnt %d", fd, retry_cnt);
100                 return MESSAGE_PORT_ERROR_IO_ERROR;
101         }
102
103         return MESSAGE_PORT_ERROR_NONE;
104 }
105
106 int write_string_to_socket(int fd,
107                 const char *buffer,
108                 int string_len,
109                 unsigned int *bytes_write,
110                 int *sequence)
111 {
112         int ret;
113
114         ret = write_socket(fd, (char *)&string_len, sizeof(string_len),
115                         bytes_write, sequence);
116         if (ret != MESSAGE_PORT_ERROR_NONE) {
117                 _LOGE("write string_len fail");
118                 return ret;
119         }
120
121         if (string_len > 0) {
122                 ret = write_socket(fd, buffer, string_len, bytes_write, sequence);
123                 if (ret != MESSAGE_PORT_ERROR_NONE) {
124                         _LOGE("wirte buffer fail");
125                         return ret;
126                 }
127         } else {
128                 *sequence += 1;
129         }
130
131         return MESSAGE_PORT_ERROR_NONE;
132 }
133
134 int read_socket(int fd,
135                 char *buffer,
136                 unsigned int nbytes,
137                 unsigned int *bytes_read)
138 {
139         unsigned int left = nbytes;
140         ssize_t nb;
141         int retry_cnt = 0;
142         struct timespec TRY_SLEEP_TIME = { 0, 5 * 1000 * 1000 };
143
144         *bytes_read = 0;
145         while (left && (retry_cnt < MAX_RETRY_CNT)) {
146                 nb = read(fd, buffer, left);
147                 if (nb == 0) {
148                         LOGE("read_socket: ...read EOF, socket closed %d: nb %zd\n", fd, nb);
149                         return MESSAGE_PORT_ERROR_IO_ERROR;
150                 } else if (nb == -1) {
151                         /*  wrt(nodejs) could change socket to none-blocking socket :-( */
152                         if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
153                                 LOGW("read_socket: %d , sleep and retry ...", errno);
154                                 retry_cnt++;
155                                 nanosleep(&TRY_SLEEP_TIME, 0);
156                                 TRY_SLEEP_TIME.tv_nsec *= 2;
157                                 continue;
158                         }
159                         LOGE("read_socket: ...error fd %d: errno %d\n", fd, errno);
160                         return MESSAGE_PORT_ERROR_IO_ERROR;
161                 }
162
163                 left -= nb;
164                 buffer += nb;
165                 *bytes_read += nb;
166                 retry_cnt = 0;
167         }
168
169         if (left != 0) {
170                 _LOGE("error fd %d: retry_cnt %d", fd, retry_cnt);
171                 return MESSAGE_PORT_ERROR_IO_ERROR;
172         }
173
174         return MESSAGE_PORT_ERROR_NONE;
175 }
176
177 int read_string_from_socket(int fd, char **buffer, int *string_len)
178 {
179         unsigned int nb;
180         if (read_socket(fd, (char *)string_len, sizeof(*string_len), &nb) != MESSAGE_PORT_ERROR_NONE) {
181                 LOGE("read socket fail");
182                 return MESSAGE_PORT_ERROR_IO_ERROR;
183         }
184         if (*string_len > 0 && *string_len < MAX_MESSAGE_SIZE) {
185                 *buffer = (char *)calloc(*string_len, sizeof(char));
186                 if (*buffer == NULL) {
187                         LOGE("Out of memory.");
188                         return MESSAGE_PORT_ERROR_IO_ERROR;
189                 }
190                 if (read_socket(fd, *buffer, *string_len, &nb) != MESSAGE_PORT_ERROR_NONE) {
191                         LOGE("read socket fail");
192                         return MESSAGE_PORT_ERROR_IO_ERROR;
193                 }
194         } else {
195                 LOGE("Invalid string len %d", *string_len);
196                 return MESSAGE_PORT_ERROR_IO_ERROR;
197         }
198         return MESSAGE_PORT_ERROR_NONE;
199 }
200
201 static int __dbus_init(void)
202 {
203         bool ret = true;
204         GError *error = NULL;
205
206         gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
207         if (gdbus_conn == NULL) {
208                 if (error != NULL) {
209                         _LOGE("Failed to get dbus [%s]", error->message);
210                         g_error_free(error);
211                 }
212                 ret = false;
213         }
214
215         return ret;
216 }
217
218 bool initialize_common(void)
219 {
220
221 #if !GLIB_CHECK_VERSION(2, 35, 0)
222         g_type_init();
223 #endif
224
225         int pid = getpid();
226         int ret = 0;
227         char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
228
229         ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
230         retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
231
232         app_id = strdup(buffer);
233         retvm_if(!app_id, false, "Malloc failed");
234         _LOGI("init : %s", app_id);
235
236         if (!__dbus_init())
237                 return false;
238         initialized_common = true;
239
240         return true;
241 }
242
243 bool is_preloaded(const char *local_appid, const char *remote_appid)
244 {
245         _LOGD("IsPreloaded");
246
247         bool preload_local = false;
248         bool preload_remote = false;
249
250         pkgmgrinfo_appinfo_h handle = NULL;
251         int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
252         if (ret != PMINFO_R_OK) {
253                 _LOGE("Failed to get the appinfo. %d", ret);
254                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
255                 return false;
256         }
257         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
258         if (ret != PMINFO_R_OK) {
259                 _LOGE("Failed to check the preloaded application. %d", ret);
260                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
261                 return false;
262         }
263         pkgmgrinfo_appinfo_destroy_appinfo(handle);
264
265         ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
266         if (ret != PMINFO_R_OK) {
267                 _LOGE("Failed to get the appinfo. %d", ret);
268                 return false;
269         }
270         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
271         if (ret != PMINFO_R_OK) {
272                 _LOGE("Failed to check the preloaded application. %d", ret);
273                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
274                 return false;
275         }
276
277         if (preload_local && preload_remote) {
278                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
279                 return true;
280         }
281         pkgmgrinfo_appinfo_destroy_appinfo(handle);
282         return false;
283 }
284
285 int check_certificate(const char *local_appid, const char *remote_appid)
286 {
287         _LOGD("CheckCertificate");
288
289         pkgmgrinfo_cert_compare_result_type_e res;
290         int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid, remote_appid, getuid(), &res);
291         if (ret < 0) {
292                 _LOGE(":CheckCertificate() Failed");
293                 return MESSAGE_PORT_ERROR_IO_ERROR;
294         }
295         if (res != PMINFO_CERT_COMPARE_MATCH) {
296                 _LOGE("CheckCertificate() Failed : MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH");
297                 return MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH;
298         }
299
300         return MESSAGE_PORT_ERROR_NONE;
301 }
302
303 char *get_encoded_name(const char *remote_app_id, const char *port_name, bool is_trusted)
304 {
305
306         int prefix_len = strlen(MESSAGEPORT_BUS_NAME_PREFIX);
307         int postfix_len = 1;
308         char *postfix = is_trusted ? "1" : "0";
309
310         unsigned char c[MD5_DIGEST_LENGTH] = {0};
311         char *md5_interface = NULL;
312         char *temp;
313         int index = 0;
314         MD5_CTX mdContext;
315         int encoded_bus_name_len = prefix_len + postfix_len + (MD5_DIGEST_LENGTH * 2) + 2;
316         int bus_name_len = strlen(remote_app_id) + strlen(port_name) + 2;
317         char *bus_name = (char *)calloc(bus_name_len, sizeof(char));
318         if (bus_name == NULL) {
319                 _LOGE("bus_name calloc failed");
320                 return 0;
321         }
322
323         snprintf(bus_name, bus_name_len, "%s_%s", remote_app_id, port_name);
324
325         MD5_Init(&mdContext);
326         MD5_Update(&mdContext, bus_name, bus_name_len);
327         MD5_Final(c, &mdContext);
328
329         md5_interface = (char *)calloc(encoded_bus_name_len , sizeof(char));
330         if (md5_interface == NULL) {
331                 if (bus_name)
332                         free(bus_name);
333
334                 _LOGE("md5_interface calloc failed!!");
335                 return 0;
336         }
337
338         snprintf(md5_interface, encoded_bus_name_len, "%s", MESSAGEPORT_BUS_NAME_PREFIX);
339         temp = md5_interface;
340         temp += prefix_len;
341
342         for (index = 0; index < MD5_DIGEST_LENGTH; index++) {
343                 snprintf(temp, 3, "%02x", c[index]);
344                 temp += 2;
345         }
346
347         if (postfix && postfix_len > 0)
348                 snprintf(temp, encoded_bus_name_len - (temp - md5_interface), "%s", postfix);
349         if (bus_name)
350                 free(bus_name);
351
352         _LOGD("encoded_bus_name : %s ", md5_interface);
353
354         return md5_interface;
355 }
356
357 void message_port_lock_mutex()
358 {
359         pthread_mutex_lock(&_message_port_mutex);
360 }
361
362 void message_port_unlock_mutex()
363 {
364         pthread_mutex_unlock(&_message_port_mutex);
365 }