Relase version 1.4.24
[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 <gio/gio.h>
30 #include <pthread.h>
31 #include <glib-unix.h>
32 #include <poll.h>
33
34 #include "message_port_log.h"
35 #include "message_port.h"
36 #include "message_port_common.h"
37
38 #define MAX_PACKAGE_STR_SIZE 512
39 #define MAX_RETRY_CNT 10
40
41 bool initialized_common;
42 GDBusConnection *gdbus_conn;
43 char *app_id;
44
45 static const int MAX_MESSAGE_SIZE = 16 * 1024;
46 static pthread_mutex_t _message_port_mutex = PTHREAD_MUTEX_INITIALIZER;
47
48 int write_socket(int fd,
49                 const char *buffer,
50                 unsigned int nbytes,
51                 unsigned int *bytes_write,
52                 int *sequence)
53 {
54         unsigned int left = nbytes;
55         ssize_t nb;
56         int retry_cnt = 0;
57         int tmp_errno;
58
59         *sequence += 1;
60         *bytes_write = 0;
61
62         while (left && (retry_cnt < MAX_RETRY_CNT)) {
63                 nb = write(fd, buffer, left);
64                 if (nb == -1) {
65 /* LCOV_EXCL_START */
66                         if (errno == EINTR) {
67                                 LOGW("write_socket: EINTR continue ...");
68                                 retry_cnt++;
69                                 continue;
70                         }
71                         tmp_errno = errno;
72                         LOGE("write_socket: ...error fd %d: errno %d\n", fd, tmp_errno);
73
74                         if (tmp_errno == EWOULDBLOCK || tmp_errno == EAGAIN)
75                                 return MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE;
76
77                         return MESSAGE_PORT_ERROR_IO_ERROR;
78                 }
79 /* LCOV_EXCL_STOP */
80                 left -= nb;
81                 buffer += nb;
82                 *bytes_write += nb;
83                 retry_cnt = 0;
84         }
85
86         if (left != 0) {
87                 _LOGE("error fd %d: retry_cnt %d", fd, retry_cnt);
88                 return MESSAGE_PORT_ERROR_IO_ERROR;
89         }
90
91         return MESSAGE_PORT_ERROR_NONE;
92 }
93
94 int write_string_to_socket(int fd,
95                 const char *buffer,
96                 int string_len,
97                 unsigned int *bytes_write,
98                 int *sequence)
99 {
100         int ret;
101
102         ret = write_socket(fd, (char *)&string_len, sizeof(string_len),
103                         bytes_write, sequence);
104         if (ret != MESSAGE_PORT_ERROR_NONE) {
105                 _LOGE("write string_len fail");
106                 return ret;
107         }
108
109         if (string_len > 0) {
110                 ret = write_socket(fd, buffer, string_len, bytes_write, sequence);
111                 if (ret != MESSAGE_PORT_ERROR_NONE) {
112                         _LOGE("wirte buffer fail");
113                         return ret;
114                 }
115         } else {
116                 *sequence += 1;
117         }
118
119         return MESSAGE_PORT_ERROR_NONE;
120 }
121
122 int read_socket(int fd,
123                 char *buffer,
124                 unsigned int nbytes,
125                 unsigned int *bytes_read)
126 {
127         unsigned int left = nbytes;
128         ssize_t nb;
129         int retry_cnt = 0;
130         struct timespec TRY_SLEEP_TIME = { 0, 5 * 1000 * 1000 };
131
132         *bytes_read = 0;
133         while (left && (retry_cnt < MAX_RETRY_CNT)) {
134                 nb = read(fd, buffer, left);
135                 if (nb == 0) {
136                         LOGE("read_socket: ...read EOF, socket closed %d: nb %zd\n", fd, nb);
137                         return MESSAGE_PORT_ERROR_IO_ERROR;
138                 } else if (nb == -1) {
139 /* LCOV_EXCL_START */
140                         /*  wrt(nodejs) could change socket to none-blocking socket :-( */
141                         if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
142                                 LOGW("read_socket: %d , sleep and retry ...", errno);
143                                 retry_cnt++;
144                                 nanosleep(&TRY_SLEEP_TIME, 0);
145                                 TRY_SLEEP_TIME.tv_nsec *= 2;
146                                 continue;
147                         }
148                         LOGE("read_socket: ...error fd %d: errno %d\n", fd, errno);
149                         return MESSAGE_PORT_ERROR_IO_ERROR;
150 /* LCOV_EXCL_STOP */
151                 }
152
153                 left -= nb;
154                 buffer += nb;
155                 *bytes_read += nb;
156                 retry_cnt = 0;
157         }
158
159         if (left != 0) {
160                 _LOGE("error fd %d: retry_cnt %d", fd, retry_cnt);
161                 return MESSAGE_PORT_ERROR_IO_ERROR;
162         }
163
164         return MESSAGE_PORT_ERROR_NONE;
165 }
166
167 int read_string_from_socket(int fd, char **buffer, int *string_len)
168 {
169         unsigned int nb;
170         if (read_socket(fd, (char *)string_len, sizeof(*string_len), &nb) != MESSAGE_PORT_ERROR_NONE) {
171                 LOGE("read socket fail");
172                 return MESSAGE_PORT_ERROR_IO_ERROR;
173         }
174         if (*string_len > 0 && *string_len < MAX_MESSAGE_SIZE) {
175                 *buffer = (char *)calloc(*string_len, sizeof(char));
176                 if (*buffer == NULL) {
177 /* LCOV_EXCL_START */
178                         LOGE("Out of memory.");
179                         return MESSAGE_PORT_ERROR_IO_ERROR;
180 /* LCOV_EXCL_STOP */
181                 }
182                 if (read_socket(fd, *buffer, *string_len, &nb) != MESSAGE_PORT_ERROR_NONE) {
183                         LOGE("read socket fail");
184                         return MESSAGE_PORT_ERROR_IO_ERROR;
185                 }
186         } else {
187                 LOGE("Invalid string len %d", *string_len);
188                 return MESSAGE_PORT_ERROR_IO_ERROR;
189         }
190         return MESSAGE_PORT_ERROR_NONE;
191 }
192
193 static int __dbus_init(void)
194 {
195         bool ret = true;
196         GError *error = NULL;
197
198         gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
199         if (gdbus_conn == NULL) {
200                 if (error != NULL) {
201                         _LOGE("Failed to get dbus [%s]", error->message);
202                         g_error_free(error);
203                 }
204                 ret = false;
205         }
206
207         return ret;
208 }
209
210 bool initialize_common(void)
211 {
212
213 #if !GLIB_CHECK_VERSION(2, 35, 0)
214         g_type_init();
215 #endif
216
217         int pid = getpid();
218         int ret = 0;
219         char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
220
221         ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
222         retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
223
224         app_id = strdup(buffer);
225         retvm_if(!app_id, false, "Malloc failed");
226         _LOGI("init : %s", app_id);
227
228         if (!__dbus_init())
229                 return false;
230         initialized_common = true;
231
232         return true;
233 }
234
235 bool is_preloaded(const char *local_appid, const char *remote_appid)
236 {
237         _LOGD("IsPreloaded");
238
239         bool preload_local = false;
240         bool preload_remote = false;
241
242         pkgmgrinfo_appinfo_h handle = NULL;
243         int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
244         if (ret != PMINFO_R_OK) {
245                 _LOGE("Failed to get the appinfo. %d", ret);
246                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
247                 return false;
248         }
249         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
250         if (ret != PMINFO_R_OK) {
251                 _LOGE("Failed to check the preloaded application. %d", ret);
252                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
253                 return false;
254         }
255         pkgmgrinfo_appinfo_destroy_appinfo(handle);
256
257         ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
258         if (ret != PMINFO_R_OK) {
259                 _LOGE("Failed to get the appinfo. %d", ret);
260                 return false;
261         }
262         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
263         if (ret != PMINFO_R_OK) {
264                 _LOGE("Failed to check the preloaded application. %d", ret);
265                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
266                 return false;
267         }
268
269         if (preload_local && preload_remote) {
270                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
271                 return true;
272         }
273         pkgmgrinfo_appinfo_destroy_appinfo(handle);
274         return false;
275 }
276
277 int check_certificate(const char *local_appid, const char *remote_appid)
278 {
279         _LOGD("CheckCertificate");
280
281         pkgmgrinfo_cert_compare_result_type_e res;
282         int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid, remote_appid, getuid(), &res);
283         if (ret < 0) {
284                 _LOGE(":CheckCertificate() Failed");
285                 return MESSAGE_PORT_ERROR_IO_ERROR;
286         }
287         if (res != PMINFO_CERT_COMPARE_MATCH) {
288                 _LOGE("CheckCertificate() Failed : MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH");
289                 return MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH;
290         }
291
292         return MESSAGE_PORT_ERROR_NONE;
293 }
294
295 char *get_encoded_name(const char *remote_app_id, const char *port_name, bool is_trusted)
296 {
297
298         size_t prefix_len = strlen(MESSAGEPORT_BUS_NAME_PREFIX);
299         int postfix_len = 1;
300         char *postfix = is_trusted ? "1" : "0";
301
302         gchar *encoded_bus_name;
303         size_t md5_digest_len = 0;
304         gssize bus_name_len = strlen(remote_app_id) + strlen(port_name) + 2;
305         char *bus_name = (char *)calloc(bus_name_len, sizeof(char));
306         if (bus_name == NULL) {
307 /* LCOV_EXCL_START */
308                 _LOGE("bus_name calloc failed");
309                 return NULL;
310 /* LCOV_EXCL_STOP */
311         }
312
313         snprintf(bus_name, bus_name_len, "%s_%s", remote_app_id, port_name);
314
315         encoded_bus_name = g_compute_checksum_for_string(G_CHECKSUM_MD5,
316                         bus_name, bus_name_len);
317
318         free(bus_name);
319
320         if (encoded_bus_name == NULL) {
321 /* LCOV_EXCL_START */
322                 _LOGE("g_compute_checksum_for_string failed");
323                 return NULL;
324 /* LCOV_EXCL_STOP */
325         }
326
327         // MD5_Final
328         md5_digest_len = prefix_len + postfix_len + strlen(encoded_bus_name) + 1;
329         char *md5_digest = (char *)calloc(md5_digest_len, sizeof(char));
330         if (md5_digest == NULL) {
331 /* LCOV_EXCL_START */
332                 g_free(encoded_bus_name);
333
334                 _LOGE("calloc failed!!");
335                 return NULL;
336 /* LCOV_EXCL_STOP */
337         }
338
339         snprintf(md5_digest, md5_digest_len, "%s%s%s",
340                         MESSAGEPORT_BUS_NAME_PREFIX, encoded_bus_name, postfix);
341
342         _LOGD("md5_encoded_bus_name : %s ", md5_digest);
343         g_free(encoded_bus_name);
344
345         return md5_digest;
346 }
347
348 void message_port_lock_mutex()
349 {
350         pthread_mutex_lock(&_message_port_mutex);
351 }
352
353 void message_port_unlock_mutex()
354 {
355         pthread_mutex_unlock(&_message_port_mutex);
356 }