update source from tizen 2.4
[platform/core/appfw/message-port.git] / src / message-port.c
1
2 // Message Port
3 // Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        message-port.cpp
20  * @brief       This is the implementation file for the MessagePort.
21  */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <glib.h>
26 #include <gio/gio.h>
27 #include <aul/aul.h>
28 #include <openssl/md5.h>
29 #include <bundle.h>
30 #include <pkgmgr-info.h>
31
32 #include "message-port.h"
33 #include "message-port-log.h"
34
35
36 #define MAX_PACKAGE_STR_SIZE 512
37 #define MESSAGEPORT_BUS_NAME_PREFIX "org.tizen.messageport._"
38 #define MESSAGEPORT_OBJECT_PATH "/org/tizen/messageport"
39 #define MESSAGEPORT_INTERFACE "org.tizen.messageport"
40
41
42
43 #define retvm_if(expr, val, fmt, arg...) do { \
44         if (expr) { \
45                 _LOGE(fmt, ##arg); \
46                 _LOGE("(%s) -> %s() return", #expr, __func__); \
47                 return val; \
48         } \
49 } while (0)
50
51 #define retv_if(expr, val) do { \
52         if (expr) { \
53                 _LOGE("(%s) -> %s() return", #expr, __func__); \
54                 return val; \
55         } \
56 } while (0)
57
58 #define FREE_AND_NULL(ptr) do { \
59         if (ptr) { \
60                 free((void *)ptr); \
61                 ptr = NULL; \
62         } \
63 } while (0)
64
65 static bool _initialized = false;
66 static GDBusConnection *__gdbus_conn = NULL;
67 static char *__app_id;
68 static GHashTable *__local_port_info = NULL;
69 static GHashTable *__remote_port_info = NULL;;
70 static GHashTable *__sender_appid_hash = NULL;;
71 static GHashTable *__checked_app_list_hash = NULL;
72 static GHashTable *__trusted_app_list_hash = NULL;
73 static const int MAX_MESSAGE_SIZE = 16 * 1024;
74
75
76
77 enum __certificate_info_type {
78         UNKNOWN = 0,
79         CERTIFICATE_MATCH,
80         CERTIFICATE_NOT_MATCH,
81 };
82
83 typedef struct message_port_local_port_info {
84         messageport_message_cb callback;
85         bool is_trusted;
86         char *port_name;
87         int local_id;
88 } message_port_local_port_info_s;
89
90 typedef struct message_port_remote_port_info {
91         char *encoded_bus_name;
92         char *sender_id;
93         char *remote_app_id;
94         int certificate_info;
95         int watcher_id;
96         GList *port_list;
97 } message_port_remote_app_info_s;
98
99 typedef struct port_list_info {
100         char *port_name;
101         bool is_trusted;
102         bool exist;
103 } port_list_info_s;
104
105 static char *__get_encoded_bus_name(const char *bus_name, const char *prefix, int len)
106 {
107         unsigned char c[MD5_DIGEST_LENGTH] = {0};
108         char *md5_interface = NULL;
109         char *temp;
110         int index = 0;
111         MD5_CTX mdContext;
112         int interface_len = len + (MD5_DIGEST_LENGTH * 2) + 1;
113
114         MD5_Init(&mdContext);
115         MD5_Update(&mdContext, bus_name, strlen(bus_name));
116         MD5_Final(c, &mdContext);
117
118         md5_interface = (char *)calloc(interface_len , sizeof(char));
119         if (md5_interface == NULL) {
120                 _LOGI("Malloc failed!!");
121                 return 0;
122         }
123
124         snprintf(md5_interface, interface_len, "%s", prefix);
125         temp = md5_interface;
126         temp += len;
127
128         for (index = 0; index < MD5_DIGEST_LENGTH; index++) {
129                 snprintf(temp, 3, "%02x", c[index]);
130                 temp += 2;
131         }
132
133         return md5_interface;
134 }
135
136 static char *__get_bus_name(const char *remote_app_id)
137 {
138         char *bus_name = NULL;
139
140         bus_name = __get_encoded_bus_name(remote_app_id, MESSAGEPORT_BUS_NAME_PREFIX, strlen(MESSAGEPORT_BUS_NAME_PREFIX));
141         if (!bus_name) {
142                 _LOGE("fail to get bus name");
143         }
144         return bus_name;
145 }
146
147 int __get_next_id(void)
148 {
149         static int count = 0;
150
151         ++count;
152         return count;
153 }
154
155 static int __remote_port_compare_cb(gconstpointer a, gconstpointer b)
156 {
157         port_list_info_s *key1 = (port_list_info_s *)a;
158         port_list_info_s *key2 = (port_list_info_s *)b;
159
160         if (key1->is_trusted == key2->is_trusted) {
161                 return strcmp(key1->port_name, key2->port_name);
162         }
163
164         return 1;
165 }
166
167
168 static bool __is_preloaded(const char *local_appid, const char *remote_appid)
169 {
170         _LOGI("IsPreloaded");
171
172         bool preload_local = false;
173         bool preload_remote = false;
174
175         pkgmgrinfo_appinfo_h handle = NULL;
176         int ret = pkgmgrinfo_appinfo_get_usr_appinfo(local_appid, getuid(), &handle);
177         if (ret != PMINFO_R_OK) {
178                 _LOGE("Failed to get the appinfo. %d", ret);
179                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
180                 return false;
181         }
182         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_local);
183         if (ret != PMINFO_R_OK) {
184                 _LOGE("Failed to check the preloaded application. %d", ret);
185                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
186                 return false;
187         }
188         ret = pkgmgrinfo_appinfo_get_usr_appinfo(remote_appid, getuid(), &handle);
189         if (ret != PMINFO_R_OK) {
190                 _LOGE("Failed to get the appinfo. %d", ret);
191                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
192                 return false;
193         }
194         ret = pkgmgrinfo_appinfo_is_preload(handle, &preload_remote);
195         if (ret != PMINFO_R_OK) {
196                 _LOGE("Failed to check the preloaded application. %d", ret);
197                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
198                 return false;
199         }
200
201         if (preload_local && preload_remote) {
202                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
203                 return true;
204         }
205         pkgmgrinfo_appinfo_destroy_appinfo(handle);
206         return false;
207 }
208
209 static int __check_certificate(const char *local_appid, const char *remote_appid)
210 {
211         _LOGI("CheckCertificate");
212
213         pkgmgrinfo_cert_compare_result_type_e res;
214         int ret = pkgmgrinfo_pkginfo_compare_usr_app_cert_info(local_appid,
215                         remote_appid, getuid(), &res);
216         if (ret < 0) {
217                 _LOGE(":CheckCertificate() Failed");
218                 return MESSAGEPORT_ERROR_IO_ERROR;
219         }
220         if (res != PMINFO_CERT_COMPARE_MATCH) {
221                 _LOGE("CheckCertificate() Failed : MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH");
222                 return MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
223         }
224
225         return MESSAGEPORT_ERROR_NONE;
226 }
227
228 static void on_name_appeared (GDBusConnection *connection,
229                 const gchar     *name,
230                 const gchar     *name_owner,
231                 gpointer         user_data)
232 {
233         _LOGI("name appeared : %s %s", __app_id, name);
234 }
235
236 static void on_name_vanished (GDBusConnection *connection,
237                 const gchar     *name,
238                 gpointer         user_data)
239 {
240         _LOGI("name vanished : %s", name);
241         message_port_remote_app_info_s *remote_app_info = (message_port_remote_app_info_s *)user_data;
242         g_bus_unwatch_name(remote_app_info->watcher_id);
243         g_hash_table_remove(__remote_port_info, remote_app_info->remote_app_id);
244 }
245
246 static void __hash_destory_list_value(gpointer data)
247 {
248         GList *list = (GList *)data;
249         g_list_foreach(list, (GFunc)g_free, NULL);
250         g_list_free(list);
251         list = NULL;
252 }
253
254 static void __set_checked_app_list(message_port_local_port_info_s *mi, char *remote_appid) {
255
256         GList *app_list = (GList *)g_hash_table_lookup(__checked_app_list_hash, mi->port_name);
257         if (app_list == NULL) {
258                 app_list = g_list_append(app_list, strdup(remote_appid));
259                 _LOGI("set checked_app_list appid: %s", remote_appid);
260                 g_hash_table_insert(__checked_app_list_hash, mi->port_name, app_list);
261         } else {
262                 GList *app = g_list_find(app_list, (gpointer)remote_appid);
263                 if (app == NULL) {
264                         app_list = g_list_append(app_list, strdup(remote_appid));
265                         _LOGI("set checked_app_list appid: %s", remote_appid);
266                 }
267         }
268 }
269
270 static int __get_local_port_info(int id, message_port_local_port_info_s **info)
271 {
272         message_port_local_port_info_s *mi = (message_port_local_port_info_s *)g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(id));
273
274         if (mi == NULL) {
275                 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
276         }
277         *info = mi;
278
279         return MESSAGEPORT_ERROR_NONE;
280 }
281
282 static port_list_info_s *__set_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
283 {
284         int ret_val = MESSAGEPORT_ERROR_NONE;
285         port_list_info_s *port_info = (port_list_info_s *)calloc(1, sizeof(port_list_info_s));
286
287         if (!port_info) {
288                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
289                 goto out;
290         }
291         port_info->port_name = strdup(remote_port);
292         if (!port_info->port_name) {
293                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
294                 goto out;
295         }
296         port_info->is_trusted = is_trusted;
297
298         out:
299         if (ret_val != MESSAGEPORT_ERROR_NONE) {
300                 if (port_info) {
301                         FREE_AND_NULL(port_info->port_name);
302                         free(port_info);
303                 }
304                 return NULL;
305         }
306         return port_info;
307 }
308
309 static message_port_remote_app_info_s *__set_remote_app_info(const char *remote_app_id, const char *remote_port, bool is_trusted)
310 {
311         port_list_info_s *port_info = NULL;
312         message_port_remote_app_info_s *remote_app_info = NULL;
313         int ret_val = MESSAGEPORT_ERROR_NONE;
314
315         remote_app_info = (message_port_remote_app_info_s *)calloc(1, sizeof(message_port_remote_app_info_s));
316         if (!remote_app_info) {
317                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
318                 goto out;
319         }
320
321         remote_app_info->encoded_bus_name = __get_bus_name(remote_app_id);
322         if (remote_app_info->encoded_bus_name == NULL) {
323                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
324                 goto out;
325         }
326
327         remote_app_info->remote_app_id = strdup(remote_app_id);
328         if (remote_app_info->remote_app_id == NULL) {
329                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;;
330                 goto out;
331         }
332
333         remote_app_info->watcher_id = g_bus_watch_name(G_BUS_TYPE_SESSION,
334                 remote_app_info->encoded_bus_name,
335                 G_BUS_NAME_WATCHER_FLAGS_NONE,
336                 on_name_appeared,
337                 on_name_vanished,
338                 remote_app_info,
339                 NULL);
340
341         port_info = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
342         if (port_info == NULL) {
343                 ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
344                 goto out;
345         }
346
347         remote_app_info->port_list = g_list_append(remote_app_info->port_list, port_info);
348
349         out:
350         if (ret_val != MESSAGEPORT_ERROR_NONE) {
351                 if (remote_app_info) {
352                         FREE_AND_NULL(remote_app_info->encoded_bus_name);
353                         FREE_AND_NULL(remote_app_info->remote_app_id);
354                         FREE_AND_NULL(remote_app_info);
355                 }
356                 return NULL;
357         }
358         return remote_app_info;
359 }
360
361 static int __get_remote_port_info(const char *remote_app_id, const char *remote_port, bool is_trusted,
362                 message_port_remote_app_info_s **mri, port_list_info_s **pli)
363 {
364         message_port_remote_app_info_s *remote_app_info = NULL;
365         port_list_info_s port_info;
366         GList *cb_list = NULL;
367
368         remote_app_info = (message_port_remote_app_info_s *)g_hash_table_lookup(__remote_port_info, remote_app_id);
369
370         if (remote_app_info == NULL) {
371                 remote_app_info = __set_remote_app_info(remote_app_id, remote_port, is_trusted);
372                 retvm_if(!remote_app_info, MESSAGEPORT_ERROR_OUT_OF_MEMORY, "fail to create message_port_remote_app_info_s");
373                 g_hash_table_insert(__remote_port_info, remote_app_info->remote_app_id, remote_app_info);
374
375         }
376         *mri = remote_app_info;
377
378         port_info.port_name = strdup(remote_port);
379         port_info.is_trusted = is_trusted;
380         cb_list = g_list_find_custom(remote_app_info->port_list, &port_info,
381                                         (GCompareFunc)__remote_port_compare_cb);
382         if (port_info.port_name)
383                 free(port_info.port_name);
384         if (cb_list == NULL) {
385                 port_list_info_s *tmp = __set_remote_port_info(remote_app_id, remote_port, is_trusted);
386                 retvm_if(!tmp, MESSAGEPORT_ERROR_OUT_OF_MEMORY, "fail to create port_list_info_s");
387                 remote_app_info->port_list = g_list_append(remote_app_info->port_list, tmp);
388                 *pli = tmp;
389         } else {
390                 *pli = (port_list_info_s *)cb_list->data;
391         }
392         return MESSAGEPORT_ERROR_NONE;
393 }
394
395 static bool __is_local_port_registed(const char *local_port, bool trusted, int *local_id, message_port_local_port_info_s **lpi)
396 {
397         GHashTableIter iter;
398         gpointer key, value;
399
400         g_hash_table_iter_init(&iter, __local_port_info);
401
402         while (g_hash_table_iter_next(&iter, &key, &value)) {
403                 message_port_local_port_info_s *mi = (message_port_local_port_info_s *)value;
404
405                 if ((mi->is_trusted == trusted) && strcmp(mi->port_name, local_port) == 0) {
406                         *local_id = mi->local_id;
407                         if (lpi != NULL) {
408                                 *lpi = mi;
409                         }
410                         return true;
411                 }
412         }
413         return false;
414 }
415
416 static int __get_sender_pid(GDBusConnection *conn, const char *sender_name)
417 {
418         GDBusMessage *msg = NULL;
419         GDBusMessage *reply = NULL;
420         GError *err = NULL;
421         GVariant *body;
422         int pid = 0;
423
424         msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
425                         "org.freedesktop.DBus", "GetConnectionUnixProcessID");
426         if (!msg) {
427                 _LOGE("Can't allocate new method call");
428                 goto out;
429         }
430
431         g_dbus_message_set_body (msg, g_variant_new ("(s)", sender_name));
432         reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
433                                                         G_DBUS_SEND_MESSAGE_FLAGS_NONE, 500, NULL, NULL, &err);
434
435         if (!reply) {
436                 if (err != NULL) {
437                         _LOGE("Failed to get pid [%s]", err->message);
438                         g_error_free(err);
439                 }
440                 goto out;
441         }
442
443         body = g_dbus_message_get_body(reply);
444         g_variant_get(body, "(u)", &pid);
445
446 out:
447         if (msg)
448                 g_object_unref(msg);
449         if (reply)
450                 g_object_unref(reply);
451
452         return pid;
453 }
454
455
456 static bool send_message(GVariant *parameters)
457 {
458         char *local_port = NULL;
459         char *local_appid = NULL;
460         char *remote_appid = NULL;
461         char *remote_port = NULL;
462         gboolean local_trusted = false;
463         gboolean remote_trusted = false;
464         gboolean bi_dir = false;
465         int len = 0;
466
467         bundle *data = NULL;
468         bundle_raw *raw = NULL;
469         message_port_local_port_info_s *mi;
470         int local_reg_id = 0;
471
472         g_variant_get(parameters, "(ssbbssbus)", &local_appid, &local_port, &local_trusted, &bi_dir,
473                         &remote_appid, &remote_port, &remote_trusted, &len, &raw);
474
475         if (!remote_port) {
476                 _LOGE("Invalid argument : remote_port is NULL");
477                 goto out;
478         }
479         if (!remote_appid) {
480                 _LOGE("Invalid argument : remote_appid is NULL");
481                 goto out;
482         }
483         if (!__is_local_port_registed(remote_port, remote_trusted, &local_reg_id, &mi)) {
484                 _LOGE("Invalid argument : remote_port:(%s) trusted(%d)", remote_port, remote_trusted);
485                 goto out;
486         }
487         if (!local_appid) {
488                 _LOGE("Invalid argument : local_appid");
489                 goto out;
490         }
491         if (!local_port) {
492                 _LOGE("Invalid argument : local_port");
493                 goto out;
494         }
495         if (strcmp(remote_appid, __app_id) != 0) {
496                 _LOGE("Invalid argument : remote_appid (%s)", remote_appid);
497                 goto out;
498         }
499         if (strcmp(remote_port, mi->port_name) != 0) {
500                 _LOGE("Invalid argument : remote_port (%s)", remote_port);
501                 goto out;
502         }
503         if (!len) {
504                 _LOGE("Invalid argument : data_len");
505                 goto out;
506         }
507         if (remote_trusted) {
508                 if (g_hash_table_lookup(__trusted_app_list_hash, (gpointer)local_appid) == NULL) {
509                         if (!__is_preloaded(local_appid, remote_appid)) {
510                                 // Check the certificate
511                                 int ret = __check_certificate(local_appid, remote_appid);
512                                 if (ret == MESSAGEPORT_ERROR_NONE) {
513                                         g_hash_table_insert(__trusted_app_list_hash, local_appid, "TRUE");
514                                 } else {
515                                         _LOGE("The application (%s) is not signed with the same certificate",
516                                                         local_appid);
517                                         goto out;
518                                 }
519                         }
520                 }
521         }
522
523         data = bundle_decode(raw, len);
524         bundle_free_encoded_rawdata(&raw);
525
526         if (!data) {
527                 _LOGE("Invalid argument : message");
528                 goto out;
529         }
530
531         if (bi_dir) {
532                 mi->callback(mi->local_id, local_appid, local_port, local_trusted, data);
533         } else {
534                 mi->callback(mi->local_id, local_appid, NULL, false, data);
535         }
536 out:
537
538         return true;
539 }
540
541 static int unregister_port(GVariant *parameters)
542 {
543         int ret = MESSAGEPORT_ERROR_NONE;
544         char *remote_appid = NULL;
545         char *remote_port = NULL;
546         bool is_trusted;
547         port_list_info_s *port_info = NULL;
548         message_port_remote_app_info_s *remote_app_info = NULL;
549
550         g_variant_get(parameters, "(sbs)", &remote_appid, &is_trusted, &remote_port);
551
552         if (!remote_appid) {
553                 _LOGE("Invalid argument : remote_appid");
554                 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
555                 goto out;
556         }
557         if (!remote_port) {
558                 _LOGE("Invalid argument : remote_port");
559                 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
560                 goto out;
561         }
562
563         ret = __get_remote_port_info(remote_appid, remote_port, is_trusted, &remote_app_info, &port_info);
564         if (ret != MESSAGEPORT_ERROR_NONE) {
565                 goto out;
566         }
567         port_info->exist = false;
568
569
570         out:
571         if (remote_appid)
572                 g_free(remote_appid);
573         if (remote_port)
574                 g_free(remote_port);
575
576         return ret;
577 }
578 static int __check_remote_port(const char *remote_app_id, const char *remote_port, bool is_trusted, bool *exist)
579 {
580         _LOGI("Check a remote port : [%s:%s]", remote_app_id, remote_port);
581
582         GDBusMessage *msg = NULL;
583         GDBusMessage *reply = NULL;
584         GError *err = NULL;
585         GVariant *body;
586         int ret_val = MESSAGEPORT_ERROR_NONE;
587         char *bus_name = NULL;
588         message_port_remote_app_info_s *remote_app_info = NULL;
589         port_list_info_s *port_info = NULL;
590         int local_reg_id = 0;
591         message_port_local_port_info_s *mi = NULL;
592
593         _LOGI("remote_app_id, app_id :[%s : %s] ", remote_app_id, __app_id);
594
595         ret_val = __get_remote_port_info(remote_app_id, remote_port, is_trusted, &remote_app_info, &port_info);
596         if (ret_val != MESSAGEPORT_ERROR_NONE) {
597                 return ret_val;
598         }
599
600         if (strcmp(remote_app_id, __app_id) == 0) {
601
602                 _LOGI("__is_local_port_registed ");
603                 if (!__is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi)) {
604                         *exist = false;
605                 } else {
606                         *exist = true;
607                 }
608                 _LOGI("__is_local_port_registed : %d ", *exist);
609                 return MESSAGEPORT_ERROR_NONE;
610         }
611
612         *exist = false;
613         port_info->exist = false;
614         bus_name = remote_app_info->encoded_bus_name;
615
616         msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH,
617                         MESSAGEPORT_INTERFACE, "check_remote_port");
618         _LOGI("bus_name, remote app id:[%s : %s] ", bus_name, remote_app_id);
619         if (!msg) {
620                 _LOGI("Can't allocate new method call");
621                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
622         }
623
624         g_dbus_message_set_body(msg, g_variant_new("(sbss)", __app_id, is_trusted, remote_app_id, remote_port));
625         reply = g_dbus_connection_send_message_with_reply_sync(
626                         __gdbus_conn,
627                         msg,
628                         G_DBUS_SEND_MESSAGE_FLAGS_NONE,
629                         500,
630                         NULL,
631                         NULL,
632                         &err);
633
634         if (err || (reply == NULL)) {
635                 if (err) {
636                         _LOGE("No reply. error = %s", err->message);
637                         g_error_free(err);
638                 }
639                 ret_val = MESSAGEPORT_ERROR_IO_ERROR;
640         } else {
641                 if (g_dbus_message_to_gerror(reply, &err)) {
642                         _LOGE("error = %s", err->message);
643                         g_error_free(err);
644                         ret_val = MESSAGEPORT_ERROR_NONE;
645                         *exist = false;
646                 } else {
647                         body = g_dbus_message_get_body(reply);
648                         g_variant_get(body, "(i)", &ret_val);
649
650                         if (ret_val == MESSAGEPORT_ERROR_NONE) {
651                                 *exist = true;
652                                 port_info->exist = true;
653                         } else if (ret_val == MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH) {
654                                 _SECURE_LOGI("The remote application (%s) is not signed with the same certificate", remote_app_id);
655                         }
656                 }
657         }
658
659         if (msg)
660                 g_object_unref(msg);
661         if (reply)
662                 g_object_unref(reply);
663
664         return ret_val;
665 }
666
667 static int check_remote_port(GVariant *parameters)
668 {
669         int ret = MESSAGEPORT_ERROR_NONE;
670         char *remote_appid = NULL;
671         char *remote_port = NULL;
672         char *local_appid = NULL;
673         bool is_trusted;
674         int local_reg_id = 0;
675         message_port_local_port_info_s *mi = NULL;
676
677         g_variant_get(parameters, "(sbss)", &local_appid, &is_trusted, &remote_appid, &remote_port);
678
679         if (!local_appid) {
680                 _LOGE("Invalid argument : local_appid");
681                 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
682                 goto out;
683         }
684         if (!remote_appid) {
685                 _LOGE("Invalid argument : remote_appid");
686                 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
687                 goto out;
688         }
689         if (!remote_port) {
690                 _LOGE("Invalid argument : remote_port");
691                 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
692                 goto out;
693         }
694         if (strcmp(remote_appid, __app_id) != 0) {
695                 _LOGE("Invalid argument : remote_appid (%s)", remote_appid);
696                 ret =  MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
697                 goto out;
698         }
699         if (!__is_local_port_registed(remote_port, is_trusted, &local_reg_id, &mi)) {
700                 _LOGE("Invalid argument : remote_port:(%s) trusted(%d)", remote_port, is_trusted);
701                 ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
702                 goto out;
703         }
704         if (is_trusted) {
705                 // Check the preloaded
706                 if (!__is_preloaded(local_appid, remote_appid)) {
707                         // Check the certificate
708                         ret = __check_certificate(local_appid, remote_appid);
709                         if (ret == MESSAGEPORT_ERROR_NONE) {
710                                 g_hash_table_insert(__trusted_app_list_hash, local_appid, "TRUE");
711                         }
712                 }
713         }
714
715         __set_checked_app_list(mi, local_appid);
716
717 out :
718
719         return ret;
720 }
721
722 static bool __check_sender_validation(GVariant *parameters, const char *sender, GDBusConnection *conn)
723 {
724         int ret = 0;
725         char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
726         char *local_appid = NULL;
727         int pid = __get_sender_pid(conn, sender);
728
729         ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
730         retvm_if(ret != AUL_R_OK, false, "Failed to get the sender ID: (%s) (%d)", sender, pid);
731
732         g_variant_get_child(parameters, 0, "s", &local_appid);
733         retvm_if(!local_appid, false, "remote_appid is NULL (%s) (%d)", sender, pid);
734
735         if (strncmp(buffer, local_appid, MAX_PACKAGE_STR_SIZE) == 0) {
736                 g_hash_table_insert(__sender_appid_hash, strdup(sender), GINT_TO_POINTER(pid));
737                 g_free(local_appid);
738         } else {
739                 g_free(local_appid);
740                 return false;
741         }
742         return true;
743 }
744
745 static void __dbus_method_call_handler(GDBusConnection *conn,
746                                 const gchar *sender, const gchar *object_path,
747                                 const gchar *iface_name, const gchar *method_name,
748                                 GVariant *parameters, GDBusMethodInvocation *invocation,
749                                 gpointer user_data)
750 {
751         _LOGI("method_name: %s", method_name);
752          gpointer sender_pid = g_hash_table_lookup(__sender_appid_hash, sender);
753         int ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
754         if (sender_pid == NULL) {
755                 if (!__check_sender_validation(parameters, sender, conn))
756                         return;
757         }
758         if (g_strcmp0(method_name, "send_message") == 0) {
759                 ret =send_message(parameters);
760         } else if (g_strcmp0(method_name, "check_remote_port") == 0) {
761                 ret = check_remote_port(parameters);
762                         g_dbus_method_invocation_return_value(invocation,
763                                 g_variant_new("(i)", ret));
764         } else if (g_strcmp0(method_name, "unregister_port") == 0) {
765                 ret = unregister_port(parameters);
766                         g_dbus_method_invocation_return_value(invocation,
767                                 g_variant_new("(i)", ret));
768         }
769
770
771 }
772
773 static const GDBusInterfaceVTable interface_vtable = {
774         __dbus_method_call_handler,
775         NULL,
776         NULL
777 };
778
779 static int __dbus_init(void)
780 {
781         static gchar introspection[] =
782                 "<node>"
783                 "  <interface name='"
784                 MESSAGEPORT_INTERFACE
785                 "'>"
786                 "        <method name='send_message'>"
787                 "          <arg type='s' name='local_appid' direction='in'/>"
788                 "          <arg type='s' name='local_port' direction='in'/>"
789                 "          <arg type='b' name='local_trusted' direction='in'/>"
790                 "          <arg type='b' name='bi_dir' direction='in'/>"
791                 "          <arg type='s' name='remote_appid' direction='in'/>"
792                 "          <arg type='s' name='remote_port' direction='in'/>"
793                 "          <arg type='b' name='remote_trusted' direction='in'/>"
794                 "          <arg type='u' name='data_len' direction='in'/>"
795                 "          <arg type='s' name='data' direction='in'/>"
796                 "        </method>"
797                 "        <method name='check_remote_port'>"
798                 "          <arg type='s' name='local_appid' direction='in'/>"
799                 "          <arg type='b' name='is_trusted' direction='in'/>"
800                 "          <arg type='s' name='remote_appid' direction='in'/>"
801                 "          <arg type='s' name='remote_port' direction='in'/>"
802                 "          <arg type='i' name='response' direction='out'/>"
803                 "        </method>"
804                 "        <method name='unregister_port'>"
805                 "          <arg type='s' name='local_appid' direction='in'/>"
806                 "          <arg type='b' name='is_trusted' direction='in'/>"
807                 "          <arg type='s' name='remote_port' direction='in'/>"
808                 "          <arg type='i' name='response' direction='out'/>"
809                 "        </method>"
810                 "  </interface>"
811                 "</node>";
812
813         int owner_id = 0;
814         int registration_id = 0;
815         char *bus_name = NULL;
816         bool ret = false;
817         GError *error = NULL;
818         GDBusNodeInfo *introspection_data = NULL;
819
820         bus_name = __get_bus_name(__app_id);
821         retvm_if(!bus_name, false, "bus_name is NULL");
822
823         __gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
824         if (__gdbus_conn == NULL) {
825                 if (error != NULL) {
826                         _LOGE("Failed to get dbus [%s]", error->message);
827                         g_error_free(error);
828                 }
829                 goto out;
830         }
831
832         owner_id = g_bus_own_name_on_connection(__gdbus_conn, bus_name,
833                         G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL);
834
835         if (owner_id == 0) {
836                 _LOGE("Acquiring the own name is failed");
837                 goto out;
838         }
839
840         introspection_data = g_dbus_node_info_new_for_xml(introspection, NULL);
841         if (!introspection_data) {
842                 _LOGE("g_dbus_node_info_new_for_xml() is failed.");
843                 goto out;
844         }
845
846         registration_id = g_dbus_connection_register_object(__gdbus_conn,
847                                                 MESSAGEPORT_OBJECT_PATH, introspection_data->interfaces[0],
848                                                 &interface_vtable, NULL, NULL, NULL);
849
850         _LOGE("registration_id %d", registration_id);
851
852         if (registration_id == 0) {
853                 _LOGE("Failed to g_dbus_connection_register_object");
854                 goto out;
855         }
856         ret = true;
857
858 out:
859         FREE_AND_NULL(bus_name);
860         if (!__gdbus_conn)
861                 g_object_unref(__gdbus_conn);
862         if (introspection_data)
863                 g_dbus_node_info_unref(introspection_data);
864
865         return ret;
866
867 }
868
869 void __list_free_port_list(gpointer data)
870 {
871         port_list_info_s *n = (port_list_info_s *)data;
872
873         FREE_AND_NULL(n->port_name);
874         FREE_AND_NULL(n);
875 }
876
877 static void __hash_destory_local_value(gpointer data)
878 {
879         message_port_local_port_info_s *mli = (message_port_local_port_info_s *)data;
880         if (mli->port_name)
881                 free(mli->port_name);
882 }
883 static void __hash_destory_remote_value(gpointer data)
884 {
885         message_port_remote_app_info_s *mri = (message_port_remote_app_info_s *)data;
886
887         if (mri) {
888                 FREE_AND_NULL(mri->encoded_bus_name);
889                 FREE_AND_NULL(mri->sender_id);
890                 FREE_AND_NULL(mri->remote_app_id);
891                 if (mri->port_list) {
892                         g_list_free_full(mri->port_list, __list_free_port_list);
893                 }
894         }
895 }
896
897 static bool __initialize(void)
898 {
899
900         int pid = getpid();
901         int ret = 0;
902         char buffer[MAX_PACKAGE_STR_SIZE] = {0, };
903
904         _LOGI("initialize");
905         ret = aul_app_get_appid_bypid(pid, buffer, sizeof(buffer));
906         retvm_if(ret != AUL_R_OK, false, "Failed to get the application ID: %d", ret);
907
908         __app_id = strdup(buffer);
909         retvm_if(!__app_id, false, "Malloc failed");
910         _LOGI("init : %s", __app_id);
911
912         if (__local_port_info == NULL) {
913                 __local_port_info = g_hash_table_new_full(g_direct_hash,  g_direct_equal, NULL, __hash_destory_local_value);
914                 retvm_if(!__local_port_info, false, "fail to create __local_port_info");
915         }
916
917         if (__remote_port_info == NULL) {
918                 __remote_port_info = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_remote_value);
919                 retvm_if(!__remote_port_info, false, "fail to create __remote_port_info");
920         }
921
922         if (__sender_appid_hash == NULL) {
923                 __sender_appid_hash = g_hash_table_new(g_str_hash, g_str_equal);
924                 retvm_if(!__sender_appid_hash, false, "fail to create __sender_appid_hash");
925         }
926
927         if (__trusted_app_list_hash == NULL)
928                 __trusted_app_list_hash = g_hash_table_new(g_str_hash, g_str_equal);
929
930         if (__checked_app_list_hash == NULL)
931                 __checked_app_list_hash =
932                         g_hash_table_new_full(g_str_hash, g_str_equal, NULL, __hash_destory_list_value);
933
934
935         if (!__dbus_init()) {
936                 return false;
937         }
938         _initialized = true;
939
940         return true;
941 }
942
943
944 static bool __message_port_register_port(const int local_id, const char *local_port, bool is_trusted, messageport_message_cb callback)
945 {
946         message_port_local_port_info_s *mi = (message_port_local_port_info_s *)calloc(1, sizeof(message_port_local_port_info_s));
947         retvm_if(!mi, false, "Malloc failed");
948
949         mi->callback = callback;
950         mi->is_trusted = is_trusted;
951         mi->port_name = strdup(local_port);
952         if (mi->port_name == NULL) {
953                 _LOGE("Malloc failed (%s)", local_port);
954                 free(mi);
955                 return false;
956         }
957         mi->local_id = local_id;
958
959         g_hash_table_insert(__local_port_info, GINT_TO_POINTER(mi->local_id), mi);
960         return true;
961 }
962
963 static int __register_message_port(const char *local_port, bool is_trusted, messageport_message_cb callback)
964 {
965         _SECURE_LOGI("Register a message port : [%s:%s]", __app_id, local_port);
966
967         int local_id = 0;
968
969         // Check the message port is already registed
970         if (__is_local_port_registed(local_port, is_trusted, &local_id, NULL)) {
971                 return local_id;
972         }
973
974         local_id = __get_next_id();
975
976         if (!__message_port_register_port(local_id, local_port, is_trusted, callback)) {
977                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
978         }
979
980         return local_id;
981 }
982
983 static int __message_port_send_message(const char *remote_appid, const char *remote_port,
984                 const char *local_port, bool trusted_message, bool local_trusted, bool bi_dir, bundle *message)
985 {
986         int ret = MESSAGEPORT_ERROR_NONE;
987         int len = 0;
988         bundle_raw *raw = NULL;
989         char *bus_name = NULL;
990
991         message_port_remote_app_info_s *remote_app_info = NULL;
992         port_list_info_s *port_info = NULL;
993         GDBusMessage *msg = NULL;
994         GError *err = NULL;
995         GVariant *body = NULL;
996
997         ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
998         if (ret != MESSAGEPORT_ERROR_NONE) {
999                 return ret;
1000         }
1001
1002         if (trusted_message) {
1003                 if (remote_app_info->certificate_info != CERTIFICATE_MATCH) {
1004                         if (!__is_preloaded(__app_id, remote_appid)) {
1005                                 if (__check_certificate(__app_id, remote_appid) != MESSAGEPORT_ERROR_NONE) {
1006                                         ret = MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH;
1007                                         goto out;
1008                                 }
1009                         }
1010                         remote_app_info->certificate_info = CERTIFICATE_MATCH;
1011                 }
1012         }
1013
1014         if (port_info->exist == false) {
1015                 bool exist = false;
1016                 _LOGI("port exist check !!");
1017                 ret =  __check_remote_port(remote_appid, remote_port, trusted_message, &exist);
1018                 if (ret != MESSAGEPORT_ERROR_NONE) {
1019                         goto out;
1020                 } else if (!exist) {
1021                         ret = MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1022                         goto out;
1023                 }
1024         }
1025
1026         bus_name = remote_app_info->encoded_bus_name;
1027
1028         if (bundle_encode(message, &raw, &len) != BUNDLE_ERROR_NONE) {
1029                 ret = MESSAGEPORT_ERROR_INVALID_PARAMETER;
1030                 goto out;
1031         }
1032
1033         if (MAX_MESSAGE_SIZE < len) {
1034                 _LOGE("The size of message (%d) has exceeded the maximum limit.", len);
1035                 ret = MESSAGEPORT_ERROR_MAX_EXCEEDED;
1036         }
1037
1038         body = g_variant_new("(ssbbssbus)", __app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
1039                           remote_appid, remote_port, trusted_message, len, raw);
1040
1041         msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, MESSAGEPORT_INTERFACE, "send_message");
1042         if (!msg) {
1043                 _LOGE("Can't allocate new method call");
1044                 ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1045                 goto out;
1046         }
1047
1048         g_dbus_message_set_body(msg, body);
1049         g_dbus_message_set_flags(msg, G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED);
1050         g_dbus_connection_send_message(__gdbus_conn, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &err);
1051         if (err != NULL) {
1052                 _LOGE("No reply. error = %s", err->message);
1053                 g_error_free(err);
1054                 ret = MESSAGEPORT_ERROR_IO_ERROR;
1055                 goto out;
1056         }
1057
1058         out:
1059         if (msg)
1060                 g_object_unref(msg);
1061         if (raw)
1062                 bundle_free_encoded_rawdata(&raw);
1063         return ret;
1064 }
1065
1066 int __message_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,  bool trusted_message, bundle *message)
1067 {
1068         message_port_local_port_info_s *local_info;
1069         int ret = __get_local_port_info(id, &local_info);
1070         if (ret != MESSAGEPORT_ERROR_NONE) {
1071                 return ret;
1072         }
1073
1074         _LOGE("bidirectional_message %s", local_info->port_name);
1075         return __message_port_send_message(remote_app_id, remote_port,
1076                         local_info->port_name, trusted_message, local_info->is_trusted, true, message);
1077 }
1078
1079 int messageport_unregister_local_port(int local_port_id, bool trusted_port)
1080 {
1081
1082         GDBusMessage *msg = NULL;
1083         GDBusMessage *reply = NULL;
1084         GError *err = NULL;
1085         GVariant *body;
1086         char *bus_name = NULL;
1087         GList *checked_app_list = NULL;
1088         GList *checked_app = NULL;
1089
1090         _LOGE("unregister : %d", local_port_id);
1091
1092         message_port_local_port_info_s *mi =
1093                 (message_port_local_port_info_s *)
1094                 g_hash_table_lookup(__local_port_info, GINT_TO_POINTER(local_port_id));
1095         if (mi == NULL)
1096                 return MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND;
1097
1098         if (mi->is_trusted != trusted_port)
1099                 return MESSAGEPORT_ERROR_INVALID_PARAMETER;
1100
1101         checked_app_list = (GList *)g_hash_table_lookup(__checked_app_list_hash, mi->port_name);
1102         checked_app = NULL;
1103         for (checked_app = checked_app_list; checked_app != NULL;
1104                         checked_app = checked_app->next) {
1105
1106                 char *checked_app_id = (char *)checked_app->data;
1107
1108                 _LOGI("unregister appid: %s", checked_app_id);
1109                 bus_name = __get_bus_name(checked_app_id);
1110                 msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH,
1111                                 MESSAGEPORT_INTERFACE, "unregister_port");
1112                 if (!msg) {
1113                         _LOGI("Can't allocate new method call");
1114                         return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1115                 }
1116
1117                 g_dbus_message_set_body(msg,
1118                                 g_variant_new("(sbs)", __app_id, mi->is_trusted, mi->port_name));
1119                 reply = g_dbus_connection_send_message_with_reply_sync(
1120                                 __gdbus_conn,
1121                                 msg,
1122                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
1123                                 500,
1124                                 NULL,
1125                                 NULL,
1126                                 &err);
1127
1128                 if (err || (reply == NULL)) {
1129                         if (err) {
1130                                 _LOGE("No reply. error = %s", err->message);
1131                                 g_error_free(err);
1132                         }
1133                 } else {
1134                         if (g_dbus_message_to_gerror(reply, &err)) {
1135                                 if (err) {
1136                                         _LOGE("error = %s", err->message);
1137                                         g_error_free(err);
1138                                 }
1139                         } else {
1140                                 int ret_val = MESSAGEPORT_ERROR_NONE;
1141
1142                                 body = g_dbus_message_get_body(reply);
1143                                 g_variant_get(body, "(u)", &ret_val);
1144
1145                                 if (ret_val == MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH) {
1146                                         _SECURE_LOGI("The remote application (%s) is not signed with the same certificate"
1147                                                         , checked_app_id);
1148                                 }
1149                         }
1150                 }
1151                 if (msg)
1152                         g_object_unref(msg);
1153                 if (reply)
1154                         g_object_unref(reply);
1155
1156
1157         }
1158         g_hash_table_remove(__checked_app_list_hash, mi->port_name);
1159         g_hash_table_remove(__local_port_info, GINT_TO_POINTER(local_port_id));
1160
1161         if (msg)
1162                 g_object_unref(msg);
1163         if (reply)
1164                 g_object_unref(reply);
1165
1166         return MESSAGEPORT_ERROR_NONE;
1167 }
1168
1169 int messageport_register_local_port(const char *local_port, messageport_message_cb callback)
1170 {
1171         if (!_initialized) {
1172                 if (!__initialize())
1173                         return MESSAGEPORT_ERROR_IO_ERROR;
1174         }
1175
1176         return __register_message_port(local_port, false, callback);
1177 }
1178
1179 int messageport_register_trusted_local_port(const char *local_port, messageport_message_cb callback)
1180 {
1181         if (!_initialized) {
1182                 if (!__initialize())
1183                         return MESSAGEPORT_ERROR_IO_ERROR;
1184         }
1185
1186         return __register_message_port(local_port, true, callback);
1187
1188 }
1189
1190 int messageport_check_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1191 {
1192         if (!_initialized) {
1193                 if (!__initialize())
1194                         return MESSAGEPORT_ERROR_IO_ERROR;
1195         }
1196
1197         return __check_remote_port(remote_app_id, remote_port, false, exist);
1198 }
1199
1200 int messageport_check_trusted_remote_port(const char *remote_app_id, const char *remote_port, bool *exist)
1201 {
1202         if (!_initialized) {
1203                 if (!__initialize())
1204                         return MESSAGEPORT_ERROR_IO_ERROR;
1205         }
1206
1207         return __check_remote_port(remote_app_id, remote_port, true, exist);
1208 }
1209
1210 int messageport_send_message(const char *remote_app_id, const char *remote_port, bundle *message)
1211 {
1212         if (!_initialized) {
1213                 if (!__initialize())
1214                         return MESSAGEPORT_ERROR_IO_ERROR;
1215         }
1216
1217         return __message_port_send_message(remote_app_id, remote_port, NULL, false, false, false, message);
1218 }
1219
1220 int messageport_send_trusted_message(const char *remote_app_id, const char *remote_port, bundle *message)
1221 {
1222         if (!_initialized) {
1223                 if (!__initialize())
1224                         return MESSAGEPORT_ERROR_IO_ERROR;
1225         }
1226
1227         return __message_port_send_message(remote_app_id, remote_port, NULL, true, false, false, message);
1228 }
1229
1230 int messageport_send_bidirectional_message(int id, const char *remote_app_id, const char *remote_port,
1231                 bundle *message)
1232 {
1233         if (!_initialized) {
1234                 if (!__initialize())
1235                         return MESSAGEPORT_ERROR_IO_ERROR;
1236         }
1237
1238         return __message_send_bidirectional_message(id, remote_app_id, remote_port, false, message);
1239 }
1240
1241 int messageport_send_bidirectional_trusted_message(int id, const char *remote_app_id, const char *remote_port,
1242                 bundle *message)
1243 {
1244         if (!_initialized) {
1245                 if (!__initialize())
1246                         return MESSAGEPORT_ERROR_IO_ERROR;
1247         }
1248         return __message_send_bidirectional_message(id, remote_app_id, remote_port, true, message);
1249 }
1250
1251 int messageport_get_local_port_name(int id, char **name)
1252 {
1253         message_port_local_port_info_s *local_info;
1254         int ret = __get_local_port_info(id, &local_info);
1255
1256         if (ret != MESSAGEPORT_ERROR_NONE) {
1257                 return ret;
1258         }
1259
1260         *name = strdup(local_info->port_name);
1261
1262         if (*name == NULL) {
1263                 return MESSAGEPORT_ERROR_OUT_OF_MEMORY;
1264         }
1265
1266         return MESSAGEPORT_ERROR_NONE;
1267 }
1268
1269 int messageport_check_trusted_local_port(int id, bool *trusted)
1270 {
1271         message_port_local_port_info_s *local_info;
1272         int ret = __get_local_port_info(id, &local_info);
1273
1274         if (ret != MESSAGEPORT_ERROR_NONE) {
1275                 return ret;
1276         }
1277
1278         *trusted = local_info->is_trusted;
1279
1280         return MESSAGEPORT_ERROR_NONE;;
1281 }
1282