Remove privacy log
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-agent.c
1 /*
2  * BLUETOOTH HAL
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Anupam Roy <anupam.r@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 #include <unistd.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <malloc.h>
26
27 #include <vconf.h>
28 #include <bundle.h>
29 #include <bundle_internal.h>
30 #include <eventsystem.h>
31
32 #include <glib.h>
33 #include <gio/gio.h>
34 #include <dlog.h>
35 #include <vconf.h>
36
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <sys/mman.h>
41
42 /* BT HAL Headers */
43 #include "bt-hal.h"
44 #include "bt-hal-log.h"
45 #include "bt-hal-msg.h"
46 #include "bt-hal-internal.h"
47 #include "bt-hal-utils.h"
48 #include "bt-hal-event-receiver.h"
49 #include "bt-hal-dbus-common-utils.h"
50
51 #include "bt-hal-adapter-dbus-handler.h"
52 #include "bt-hal-rfcomm-dbus-handler.h"
53 #include "bt-hal-event-receiver.h"
54
55 #include <bt-hal-agent.h>
56 #include <bt-hal-gap-agent.h>
57 #include <bt-hal-dbus-common-utils.h>
58
59 /* TODO_40 : 4.0 merge  */
60 #include "bt-internal-types.h"
61
62 #define BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE (APP_SYSCONFDIR"/auto-pair-blacklist")
63 #define BT_HAL_AGENT_NEW_LINE "\r\n"
64 #define BUF_SIZE                256
65 #define PAGE_SIZE               (1 << 12)
66 #define _ALIGN_UP(addr, size)    (((addr)+((size)-1))&(~((size)-1)))
67 #define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
68 #define PAGE_ALIGN(addr)        _ALIGN_DOWN(addr, PAGE_SIZE)
69 #define BT_HAL_PIN_MAX_LENGTH 16
70 #define BT_HAL_PASSKEY_MAX_LENGTH 4
71 #define BT_HAL_LOWER_ADDRESS_LENGTH 9
72 #define BT_HAL_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
73 #define BT_HAL_AGENT_SYSPOPUP_MAX_ATTEMPT 3
74
75 #define G_VARIANT_UNREF(variant) \
76         g_variant_unref(variant); \
77         variant = NULL
78 #define BT_HAL_MAX_EVENT_STR_LENGTH 50
79
80 static void *adapter_agent = NULL;
81 static gboolean passkey_display_notification = FALSE;
82 static gboolean passkey_confirm_notification = FALSE;
83 static gboolean passkey_notification = FALSE;
84 static gboolean pincode_notification = FALSE;
85
86 /* Forward delcaration */
87 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
88                 uint32_t cod);
89 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device);
90 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
91                 guint passkey);
92 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device);
93 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
94                 guint passkey);
95 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
96                                                                 const char *uuid);
97 static gboolean __bt_hal_authorize_cancel_request(GapAgentPrivate *agent, const char *address);
98 static gboolean __bt_hal_pairing_cancel_request(GapAgentPrivate *agent, const char *address);
99 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface);
100 static void __bt_hal_agent_release_memory(void);
101 static inline void stack_trim(void);
102
103 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class);
104 static gboolean __bt_hal_is_hid_device_connectable(void);
105 static int __bt_hal_device_generate_passkey(char *passkey, int size);
106 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
107                 const gchar *address, const gchar *name);
108 static gboolean __bt_hal_device_is_device_blacklisted(const char *address, const char *name);
109 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
110                 const char *address);
111 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
112                 const char *partial_name);
113 static void __bt_hal_send_ssp_request_events(const gchar *address, const gchar *name,
114                 guint passkey, uint32_t cod, unsigned char variant);
115 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid);
116
117 void* _bt_hal_create_agent(const char *path, gboolean adapter)
118 {
119         GAP_AGENT_FUNC_CB func_cb;
120         GDBusProxy *adapter_proxy;
121         GapAgentPrivate *agent;
122
123         DBG("+");
124         adapter_proxy = _bt_hal_get_adapter_proxy();
125         if (!adapter_proxy)
126                 return NULL;
127
128         func_cb.pincode_func = __bt_hal_pincode_request;
129         func_cb.display_func = __bt_hal_display_request;
130         func_cb.passkey_func = __bt_hal_passkey_request;
131         func_cb.confirm_func = __bt_hal_confirm_request;
132         func_cb.authorize_func = __bt_hal_authorize_request;
133         func_cb.pairing_cancel_func = __bt_hal_pairing_cancel_request;
134         func_cb.authorization_cancel_func = __bt_hal_authorize_cancel_request;
135
136         /* Allocate memory*/
137         agent = g_new0(GapAgentPrivate, 1);
138
139         _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
140
141         if (adapter) {
142                 if (!_gap_agent_register(agent)) {
143                         ERR("gap agent registration failed!");
144                         _bt_hal_destroy_agent(agent);
145                         agent = NULL;
146                 }
147         }
148         DBG("-");
149         return agent;
150 }
151
152 void _bt_hal_destroy_agent(void *agent)
153 {
154         DBG("+");
155         if (!agent)
156                 return;
157
158         _gap_agent_reset_dbus((GapAgentPrivate *)agent);
159
160         g_free(agent);
161         DBG("-");
162 }
163
164 gboolean _bt_hal_agent_is_canceled(void)
165 {
166         void *agent = _bt_hal_get_adapter_agent();
167         if (!agent)
168                 return FALSE;
169
170         return _gap_agent_is_canceled(agent);
171 }
172
173 int _bt_hal_agent_reply_cancellation(void)
174 {
175         void *agent = _bt_hal_get_adapter_agent();
176         if (!agent)
177                 return BT_STATUS_FAIL;
178
179         if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
180                 ERR("Fail to reply agent");
181                 return BT_STATUS_FAIL;
182         }
183         DBG("gap agent cancellation done successfully!");
184         return BT_STATUS_SUCCESS;
185
186 }
187
188 void _bt_hal_agent_set_canceled(gboolean value)
189 {
190         void *agent = _bt_hal_get_adapter_agent();
191         if (!agent)
192                 return;
193
194         return _gap_agent_set_canceled(agent, value);
195 }
196
197 void _bt_hal_initialize_adapter_agent(void)
198 {
199         if (adapter_agent) {
200                 ERR("Adapter agent already exist!");
201                 return;
202         }
203
204         adapter_agent = _bt_hal_create_agent(BT_HAL_ADAPTER_AGENT_PATH, TRUE);
205         if (!adapter_agent) {
206                 ERR("Fail to register agent");
207                 return;
208         }
209 }
210
211 void _bt_hal_destroy_adapter_agent(void)
212 {
213         if (adapter_agent)
214                 _bt_hal_destroy_agent(adapter_agent);
215         adapter_agent = NULL;
216 }
217
218 void* _bt_hal_get_adapter_agent(void)
219 {
220         return adapter_agent;
221 }
222
223 void _bt_hal_enable_gap_auth_notifications(unsigned int type, gboolean enable)
224 {
225         INFO("type: %d, enable: %d", type, enable);
226
227         switch (type) {
228         case BT_PASSKEY_CONFIRMATION:
229                 /* Note: Currently not used for notification sending, should be used when required */
230                 passkey_confirm_notification = enable;
231                 break;
232         case BT_PASSKEY_DISPLAY:
233                 passkey_display_notification = enable;
234                 break;
235         case BT_PASSKEY_ENTRY:
236                 /* Note: Currently not used for notification sending, should be used when required */
237                 passkey_notification = enable;
238                 break;
239         case BT_PINCODE_ENTRY:
240                 pincode_notification = enable;
241                 break;
242         default:
243                 ERR("Unknown type: %d", type);
244         }
245 }
246
247 static void __bt_hal_send_authorize_request_event(const gchar *address, const char *uuid)
248 {
249         struct hal_ev_authorize_request ev;
250         memset(&ev, 0, sizeof(ev));
251
252         DBG("Remote Device address [%s]", address);
253
254         _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
255
256         /* UUID received in authorization request (In case of HFP unit, UUID received from Bluez
257            would be of that of Audio Gateway UUID (0x111f) */
258         ev.service_id = _bt_convert_uuid_string_to_service_id(uuid);
259
260         handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
261         if (event_cb) {
262                 event_cb(HAL_EV_AUTHORIZE_REQUEST, (void*)&ev, sizeof(ev));
263         }
264 }
265
266 #ifdef TIZEN_BT_HAL
267 static void __bt_hal_send_rfcomm_authorize_request_event(const gchar *address, const char *uuid, const char *name, char *path, int fd)
268 {
269         struct hal_ev_sock_conn_auth ev;
270
271         DBG("Remote Device address [%s], uuid: %s", address, uuid);
272
273         memset(&ev, 0, sizeof(ev));
274         _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
275         _bt_hal_convert_uuid_string_to_type(ev.uuid, uuid);
276
277         if (name)
278                 g_strlcpy((char *)ev.name, name, BT_HAL_DEVICE_NAME_LENGTH_MAX);
279
280         if (path)
281                 g_strlcpy((char *)ev.path, path, BT_HAL_PATH_NAME_LENGTH_MAX);
282
283         ev.fd = fd;
284
285         handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
286         if (event_cb) {
287                 event_cb(HAL_EV_SOCK_AUTHORIZE_REQUEST, (void*)&ev, sizeof(ev));
288         }
289 }
290 #endif
291
292 /* Legacy Pairing */
293 static void __bt_hal_send_pin_request_event(const gchar *address, const gchar *name,
294                 uint32_t cod)
295 {
296         struct hal_ev_pin_request ev;
297         memset(&ev, 0, sizeof(ev));
298
299         DBG("Remote Device address [%s]", address);
300         DBG("Remote Device Name [%s]", name);
301         DBG("Remote Device COD [%u]", cod);
302
303         _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
304
305         memcpy(ev.name, name, strlen(name)+1);
306         ev.class_of_dev = cod;
307
308         handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
309         if (event_cb) {
310                 DBG("Sending PIN REQUEST");
311                 event_cb(HAL_EV_PIN_REQUEST, (void*)&ev, sizeof(ev));
312         }
313
314         DBG("-");
315 }
316
317
318 void __bt_hal_get_auth_info(GVariant *reply, char *auth_info)
319 {
320         int cursor;
321         GVariant *tmp_value;
322         char *manufacturer_data = NULL;
323         int manufacturer_data_len;
324         gboolean is_alias_set;
325         GVariantIter *value_iter;
326         guint8 m_value;
327         int i = 0;
328
329         tmp_value = g_variant_lookup_value(reply, "IsAliasSet",
330                                                                 G_VARIANT_TYPE_BOOLEAN);
331         if (tmp_value) {
332                 is_alias_set = g_variant_get_boolean(tmp_value);
333                 g_variant_unref(tmp_value);
334         } else {
335                 is_alias_set = FALSE;
336         }
337         if (is_alias_set == FALSE) {
338                 tmp_value = g_variant_lookup_value(reply, "LagacyManufacturerDataLen",
339                                                                 G_VARIANT_TYPE_UINT16);
340                 if (tmp_value) {
341                         manufacturer_data_len = g_variant_get_uint16(tmp_value);
342                         if (manufacturer_data_len >
343                                         MAX_MANUFACTURE_LEN) {
344                                 ERR("manufacturer_data_len is too long");
345                                 manufacturer_data_len = MAX_MANUFACTURE_LEN;
346                         }
347                         g_variant_unref(tmp_value);
348                 } else
349                         manufacturer_data_len = 0;
350
351                 tmp_value = g_variant_lookup_value(reply, "LagacyManufacturerData",
352                                                                 G_VARIANT_TYPE_ARRAY);
353                 if (tmp_value) {
354                         if ((manufacturer_data_len == 0) ||
355                                         manufacturer_data_len != g_variant_get_size(tmp_value)) {
356                                 ERR("manufacturer data length doesn't match");
357                                 manufacturer_data_len = 0;
358                                 manufacturer_data = NULL;
359                         } else {
360                                 manufacturer_data = g_malloc0(manufacturer_data_len);
361                                 g_variant_get(tmp_value, "ay", &value_iter);
362                                 while (g_variant_iter_loop(value_iter, "y", &m_value))
363                                         manufacturer_data[i++] = m_value;
364
365                                 g_variant_iter_free(value_iter);
366                         }
367                         g_variant_unref(tmp_value);
368                 } else {
369                         INFO("manufacture data is not a G_VARIANT_TYPE_ARRAY ");
370                         manufacturer_data_len = 0;
371                         manufacturer_data = NULL;
372                 }
373                 /*minimum Size of the samsung specific manufacturer data is greater than 30 */
374                 if (manufacturer_data_len < 30) {
375                         g_free(manufacturer_data);
376                         return;
377                 }
378                 if (manufacturer_data[0] != 0x00 || manufacturer_data[1] != 0x75) {
379                         DBG("This is not a samsung specific manufaturer data");
380                         g_free(manufacturer_data);
381                         return;
382                 }
383
384                 /* 2  samsung (0x00 0x75) + 1 (control and version) + 1 (service ID) +
385                 1 (discovery version) + 1 (associated service ID)
386                 2 (Proxamity and locality) + 2 (Device type and icon) */
387
388                 cursor = 10;
389
390                 memcpy(auth_info, &(manufacturer_data[cursor]), 5);
391         }
392          g_free(manufacturer_data);
393 }
394
395 static gboolean __bt_hal_pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
396 {
397         uint32_t device_class;
398         const gchar *address;
399         unsigned char auth_info[5] = {0, };
400         const gchar *name;
401         GVariant *reply = NULL;
402         GVariant *reply_temp = NULL;
403         GVariant *tmp_value;
404         DBG("+");
405
406         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
407
408         if (reply_temp == NULL) {
409                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
410                                 NULL);
411                 goto done;
412         }
413
414         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
415
416         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
417         g_variant_get(tmp_value, "u", &device_class);
418         G_VARIANT_UNREF(tmp_value);
419
420         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
421         g_variant_get(tmp_value, "s", &address);
422         G_VARIANT_UNREF(tmp_value);
423
424         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
425         g_variant_get(tmp_value, "s", &name);
426         G_VARIANT_UNREF(tmp_value);
427
428         if (!name)
429                 name = address;
430
431         if (headed_plugin_info->plugin_headed_enabled) {
432                 __bt_hal_get_auth_info(reply, (char *)auth_info);
433                 if (__bt_hal_device_is_hid_keyboard(device_class)) {
434                         char str_passkey[BT_HAL_PASSKEY_MAX_LENGTH + 1] = { 0 };
435
436                         DBG("Device is HID Keyboard");
437                         if (__bt_hal_device_generate_passkey(str_passkey,
438                                                 BT_HAL_PASSKEY_MAX_LENGTH) != 0) {
439                                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
440                                                 "", NULL);
441                                 goto done;
442                         }
443
444                         gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
445                                         str_passkey, NULL);
446
447                         DBG("Launch BT Syspopup");
448                         headed_plugin_info->headed_plugin->bt_launch_system_popup(
449                                         BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
450                                         name, auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
451                 } else if (__bt_hal_device_is_auto_response(device_class, address, name)) {
452                         DBG("Device is of Type Auto response, send event to HAL");
453                         __bt_hal_send_pin_request_event(address, name, device_class);
454                 } else if (pincode_notification) {
455                         DBG("pincode_notification is enabled, send event to HAL");
456                         __bt_hal_send_pin_request_event(address, name, device_class);
457                 } else {
458                         DBG("Device is not of Auto response class, Show PIN Entry");
459                         headed_plugin_info->headed_plugin->bt_launch_system_popup(
460                                         BT_HAL_AGENT_EVENT_PIN_REQUEST, name, auth_info,
461                                         NULL, NULL, _gap_agent_get_path(agent));
462                 }
463         } else {
464                 INFO("Plugin Headed not Enabled");
465                 __bt_hal_send_pin_request_event(address, name, device_class);
466         }
467
468 done:
469         g_variant_unref(reply);
470         g_variant_unref(reply_temp);
471         __bt_hal_agent_release_memory();
472         DBG("-");
473
474         return TRUE;
475 }
476
477
478 /* BT_SSP_VARIANT_PASSKEY_CONFIRMATION */
479 /* BT_SSP_VARIANT_PASSKEY_NOTIFICATION */
480 /* BT_SSP_VARIANT_PASSKEY_ENTRY */
481 /* BT_SSP_VARIANT_CONSENT */
482
483 static void __bt_hal_send_ssp_request_events(const gchar *address,
484                 const gchar *name,
485                 guint passkey,
486                 uint32_t cod,
487                 unsigned char variant)
488 {
489         struct hal_ev_ssp_request ev;
490         memset(&ev, 0, sizeof(ev));
491         DBG("sizeof ev [%zu]", sizeof(ev));
492
493         DBG("Remote Device address [%s]", address);
494         DBG("Remote Device Name [%s]", name);
495         DBG("Remote Device passkey [%d]", passkey);
496         DBG("Remote Device pairing variant [0x%x]", variant);
497         DBG("Remote Device cod [%d]", cod);
498
499         _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
500
501         memcpy(ev.name, name, strlen(name)+1);
502         ev.class_of_dev = cod;
503         ev.pairing_variant = variant;
504         ev.passkey = passkey;
505
506         handle_stack_msg event_cb = _bt_hal_get_stack_message_handler();
507         if (event_cb) {
508                 DBG("Sending SSP type [%d]", variant);
509                 event_cb(HAL_EV_SSP_REQUEST, (void*)&ev, sizeof(ev));
510         }
511
512         DBG("-");
513 }
514
515 /* SSP */
516 static gboolean __bt_hal_display_request(GapAgentPrivate *agent, GDBusProxy *device,
517                 guint passkey)
518 {
519         const gchar *address;
520         const gchar *name;
521         unsigned char auth_info[5] = {0, };
522         char *str_passkey;
523         uint32_t device_class;
524         GVariant *reply = NULL;
525         GVariant *reply_temp = NULL;
526         GVariant *tmp_value = NULL;
527         DBG("+");
528
529         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
530         if (reply_temp == NULL) {
531                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
532                                 NULL);
533                 goto done;
534         }
535
536         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
537
538         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
539         g_variant_get(tmp_value, "s", &address);
540         G_VARIANT_UNREF(tmp_value);
541         if (!address) {
542                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
543                 goto done;
544         }
545
546         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
547         g_variant_get(tmp_value, "s", &name);
548         G_VARIANT_UNREF(tmp_value);
549
550         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
551         g_variant_get(tmp_value, "u", &device_class);
552         G_VARIANT_UNREF(tmp_value);
553
554         if (!name)
555                 name = address;
556
557         str_passkey = g_strdup_printf("%d", passkey);
558
559         __bt_hal_get_auth_info(reply, (char *)auth_info);
560
561         DBG("KEYBOARD_PASSKEY_REQUEST");
562
563         if (passkey_display_notification) {
564                 DBG("passkey_display_notification is enabled, send event to HAL");
565                 __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
566                                 BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
567         } else if (headed_plugin_info->plugin_headed_enabled) {
568                 INFO("Plugin Headed Enabled");
569                 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
570                                 auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
571         } else {
572                 INFO("Plugin Headed not Enabled");
573                 __bt_hal_send_ssp_request_events(address, name, passkey, device_class,
574                                 BT_SSP_VARIANT_PASSKEY_NOTIFICATION);
575         }
576
577         g_free(str_passkey);
578 done:
579         g_variant_unref(reply);
580         g_variant_unref(reply_temp);
581         __bt_hal_agent_release_memory();
582
583         DBG("-");
584         return TRUE;
585 }
586
587 /* SSP */
588 static gboolean __bt_hal_passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
589 {
590         const gchar *address;
591         const gchar *name;
592         unsigned char auth_info[5] = {0, };
593         uint32_t device_class;
594         GVariant *reply = NULL;
595         GVariant *reply_temp = NULL;
596         GVariant *tmp_value;
597         DBG("+");
598
599         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
600
601         if (reply_temp == NULL) {
602                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
603                                 NULL);
604                 goto done;
605         }
606
607         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
608
609         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
610         g_variant_get(tmp_value, "s", &address);
611         G_VARIANT_UNREF(tmp_value);
612         if (!address) {
613                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
614                 goto done;
615         }
616
617         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
618         g_variant_get(tmp_value, "s", &name);
619         G_VARIANT_UNREF(tmp_value);
620
621         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
622         g_variant_get(tmp_value, "u", &device_class);
623         G_VARIANT_UNREF(tmp_value);
624
625         if (!name)
626                 name = address;
627
628         DBG("PASSKEY_REQUEST");
629
630         __bt_hal_get_auth_info(reply, (char *)auth_info);
631
632         if (headed_plugin_info->plugin_headed_enabled) {
633                 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_REQUEST, name, auth_info,
634                                 NULL, NULL, _gap_agent_get_path(agent));
635         } else {
636                 __bt_hal_send_ssp_request_events(address, name, 0, device_class,
637                                 BT_SSP_VARIANT_PASSKEY_ENTRY);
638         }
639
640 done:
641         g_variant_unref(reply);
642         g_variant_unref(reply_temp);
643         __bt_hal_agent_release_memory();
644
645         DBG("-");
646         return TRUE;
647 }
648
649 /*ssp*/
650 static gboolean __bt_hal_confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
651                 guint passkey)
652 {
653         const gchar *address;
654         const gchar *name;
655         char str_passkey[7];
656         uint32_t device_class;
657         GVariant *reply_temp = NULL;
658         GVariant *reply = NULL;
659         GVariant *tmp_value;
660         DBG("+ passkey[%.6d]", passkey);
661         DBG("Agent Path [%s]", agent->path);
662
663         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
664
665         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
666
667         if (reply_temp == NULL) {
668                 ERR("####Device doesn't exist####");
669                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
670                                 NULL);
671                 goto done;
672         }
673         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
674
675         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
676         g_variant_get(tmp_value, "s", &address);
677         G_VARIANT_UNREF(tmp_value);
678
679         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
680         g_variant_get(tmp_value, "s", &name);
681         G_VARIANT_UNREF(tmp_value);
682
683         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
684         g_variant_get(tmp_value, "u", &device_class);
685         G_VARIANT_UNREF(tmp_value);
686
687         if (!name)
688                 name = address;
689
690         if (headed_plugin_info->plugin_headed_enabled) {
691                 unsigned char auth_info[5] = {0, };
692
693                 DBG("LAUNCH SYSPOPUP");
694                 DBG("Name [%s]", name);
695                 DBG("Passkey [%s]", str_passkey);
696
697                 __bt_hal_get_auth_info(reply, (char *)auth_info);
698                 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_HAL_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
699                                 auth_info, str_passkey, NULL,
700                                 _gap_agent_get_path(agent));
701         } else {
702                 DBG("Headless Confirmation");
703
704                 if (TIZEN_FEATURE_BLUEZ_SPEAKER_REFERENCE) {
705                         /* Reply the ssp confirmation automaticaly */
706                         gap_agent_reply_confirmation(agent, GAP_AGENT_ACCEPT, NULL);
707                 }
708
709                 __bt_hal_send_ssp_request_events(address, name, passkey,
710                                 device_class, BT_SSP_VARIANT_PASSKEY_CONFIRMATION);
711         }
712
713 done:
714         g_variant_unref(reply);
715         g_variant_unref(reply_temp);
716         __bt_hal_agent_release_memory();
717         DBG("-");
718         return TRUE;
719 }
720
721 static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
722                 const char *uuid)
723 {
724         const gchar *address;
725         const gchar *name;
726         gboolean trust;
727         gboolean paired;
728         GVariant *reply = NULL;
729         GVariant *reply_temp = NULL;
730         GVariant *tmp_value;
731 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
732         bt_hal_agent_osp_server_t *osp_server;
733 #endif
734
735         reply_temp = __bt_hal_service_getall(device, BT_HAL_DEVICE_INTERFACE);
736         if (reply_temp == NULL) {
737                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
738                 goto done;
739         }
740
741         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
742
743         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
744         g_variant_get(tmp_value, "s", &address);
745         G_VARIANT_UNREF(tmp_value);
746         if (!address) {
747                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
748                 goto done;
749         }
750
751         tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
752         g_variant_get(tmp_value, "s", &name);
753         G_VARIANT_UNREF(tmp_value);
754         if (!name)
755                 name = address;
756
757         tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
758         g_variant_get(tmp_value, "b", &trust);
759         G_VARIANT_UNREF(tmp_value);
760
761         tmp_value = g_variant_lookup_value(reply, "Paired", G_VARIANT_TYPE_BOOLEAN);
762         g_variant_get(tmp_value, "b", &paired);
763         G_VARIANT_UNREF(tmp_value);
764         if ((paired == FALSE) && (trust == FALSE)) {
765                 ERR("No paired & No trusted device");
766                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
767                 goto done;
768         }
769
770         INFO("Authorization request for device [%s] Service:[%s]\n", address + 12, uuid);
771
772         if (trust) {
773                 DBG("Trusted device, so authorize\n");
774                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
775                 goto done;
776         }
777
778         if (!strcasecmp(uuid, BT_HAL_HID_UUID)) {
779                 gboolean is_connectable = __bt_hal_is_hid_device_connectable();
780                 DBG("Automatically %s authorization for HID",
781                         is_connectable ? "accept" : "reject");
782                 if (is_connectable == TRUE)
783                         gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
784                 else
785                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
786                 goto done;
787         }
788
789         if (!strcasecmp(uuid, BT_HAL_HFP_AUDIO_GATEWAY_UUID) ||
790                         !strcasecmp(uuid, BT_HAL_HSP_AUDIO_GATEWAY_UUID) ||
791                         !strcasecmp(uuid, BT_HAL_HFP_HF_UUID) ||
792                         !strcasecmp(uuid, BT_HAL_HSP_HS_UUID) ||
793                         !strcasecmp(uuid, BT_HAL_A2DP_PROFILE_UUID) ||
794                         !strcasecmp(uuid, BT_HAL_HID_DEVICE_UUID) ||
795                         !strcasecmp(uuid, BT_HAL_SAP_UUID_OLD) ||
796                         !strcasecmp(uuid, BT_HAL_SAP_UUID_NEW) ||
797 #ifdef TIZEN_BT_HAL
798                         !strcasecmp(uuid, BT_HAL_IOTIVITY_UUID) ||
799 #endif
800                         !strcasecmp(uuid, BT_HAL_AVRCP_TARGET_UUID)) {
801                 __bt_hal_send_authorize_request_event(address, uuid);
802                 goto done;
803         }
804
805 #ifdef TIZEN_BT_HAL
806         if (!strcasecmp(uuid, BT_HAL_OPP_UUID)) {
807                 if (NULL != _bt_hal_gap_agent_find_osp_server_by_type(
808                                 agent->osp_servers, BT_OSP_SERVER_OBEX, NULL)) {
809                         INFO("OSP server for OPP found, send event");
810                         __bt_hal_send_authorize_request_event(address, uuid);
811                         goto done;
812                 } else {
813                         INFO("Native OPP server, auto accept");
814                         gap_agent_reply_authorize(agent,
815                                         GAP_AGENT_ACCEPT, NULL);
816                         goto done;
817                 }
818         }
819
820 #ifdef TIZEN_FEATURE_BT_RFCOMM_DIRECT
821         /* If user only listens(without accepts) to rfcomm server, occurs connection requested cb not popup */
822         osp_server = _bt_hal_gap_agent_find_osp_server_by_type(agent->osp_servers, BT_OSP_SERVER_RFCOMM, uuid);
823         if (osp_server) {
824                 INFO("Found rfcomm osp server. path: %s, fd: %d", osp_server->path, osp_server->fd);
825                 __bt_hal_send_rfcomm_authorize_request_event(address, uuid, name, osp_server->path, osp_server->fd);
826                 goto done;
827         }
828 #else
829         if (_is_rfcomm_server_uuid(uuid)) {
830                 __bt_hal_send_rfcomm_authorize_request_event(address, uuid, NULL, NULL, -1);
831                 goto done;
832         }
833 #endif
834 #endif
835
836         if (trust || !headed_plugin_info->plugin_headed_enabled) {
837                 INFO("Trusted or Headless device, so authorize\n");
838                 gap_agent_reply_authorize(agent,
839                                 GAP_AGENT_ACCEPT, NULL);
840
841                 goto done;
842         }
843
844         if (headed_plugin_info->plugin_headed_enabled) {
845                 unsigned char auth_info[5] = {0, };
846                 int request_type = BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST;
847
848                 __bt_hal_get_auth_info(reply, (char *)auth_info);
849
850                 if (!strcasecmp(uuid, BT_HAL_OPP_UUID))
851                         request_type = BT_HAL_AGENT_EVENT_EXCHANGE_REQUEST;
852                 else if (!strcasecmp(uuid, BT_HAL_PBAP_UUID))
853                         request_type = BT_HAL_AGENT_EVENT_PBAP_REQUEST;
854                 else if (!strcasecmp(uuid, BT_HAL_MAP_UUID))
855                         request_type = BT_HAL_AGENT_EVENT_MAP_REQUEST;
856
857                 headed_plugin_info->headed_plugin->bt_launch_system_popup(request_type, name, auth_info, NULL, NULL,
858                                         _gap_agent_get_path(agent));
859         }
860
861 done:
862         g_variant_unref(reply);
863         g_variant_unref(reply_temp);
864         __bt_hal_agent_release_memory();
865
866         return TRUE;
867 }
868
869 static gboolean __bt_hal_authorize_cancel_request(GapAgentPrivate *agent,
870                                                 const char *address)
871 {
872         DBG("On Going Authorization is cancelled by remote [%s]", address);
873         gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
874
875         if (headed_plugin_info->plugin_headed_enabled)
876                 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
877
878         __bt_hal_agent_release_memory();
879         return TRUE;
880 }
881
882 static gboolean __bt_hal_pairing_cancel_request(GapAgentPrivate *agent, const char *address)
883 {
884         DBG("On Going Pairing is cancelled by remote [%s]", address);
885
886         if (headed_plugin_info->plugin_headed_enabled)
887                 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
888
889         __bt_hal_agent_release_memory();
890         return TRUE;
891 }
892
893 static gboolean __bt_hal_device_is_hid_keyboard(unsigned int dev_class)
894 {
895         switch ((dev_class & 0x1f00) >> 8) {
896         case 0x05:
897                 switch ((dev_class & 0xc0) >> 6) {
898                 case 0x01:
899                         /* input-keyboard" */
900                         return TRUE;
901                 }
902                 break;
903         }
904
905         return FALSE;
906 }
907
908 static gboolean __bt_hal_is_hid_device_connectable(void)
909 {
910         GDBusProxy *proxy = NULL;
911         GVariant *reply = NULL;
912         GError *err = NULL;
913         gboolean connectable = FALSE;
914
915         proxy = _bt_hal_get_hid_agent_proxy();
916         if(proxy == NULL)
917                 return FALSE;
918
919         reply = g_dbus_proxy_call_sync(proxy, "IsHidConnectable", NULL,
920                                 G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &err);
921         if (reply == NULL) {
922                 ERR("Error returned in method call");
923                 if (err != NULL) {
924                         ERR("Error message = %s", err->message);
925                         g_error_free(err);
926                 }
927                 connectable = FALSE;
928         } else {
929                 g_variant_get(reply, "(b)", &connectable);
930                 g_variant_unref(reply);
931         }
932         g_object_unref(proxy);
933
934         INFO("HID Device is %s",
935                         connectable ? "Connectable" : "Non-connectable");
936
937         return connectable;
938 }
939
940 static int __bt_hal_device_generate_passkey(char *passkey, int size)
941 {
942         int i;
943         ssize_t len;
944         int random_fd;
945         unsigned int value = 0;
946
947         if (passkey == NULL)
948                 return -1;
949
950         if (size <= 0)
951                 return -1;
952
953         random_fd = open("/dev/urandom", O_RDONLY);
954
955         if (random_fd < 0)
956                 return -1;
957
958         for (i = 0; i < size; i++) {
959                 len = read(random_fd, &value, sizeof(value));
960                 if (len > 0)
961                         passkey[i] = '0' + (value % 10);
962         }
963
964         close(random_fd);
965
966         DBG("passkey: %s", passkey);
967
968         return 0;
969 }
970
971 static gboolean __bt_hal_find_device_by_address_exactname(char *buffer,
972                 const char *address)
973 {
974         char *pch;
975         char *last;
976
977         pch = strtok_r(buffer, "= ,", &last);
978
979         if (pch == NULL)
980                 return FALSE;
981
982         while ((pch = strtok_r(NULL, ",", &last))) {
983                 if (0 == g_strcmp0(pch, address)) {
984                         DBG("Match found\n");
985                         return TRUE;
986                 }
987         }
988         return FALSE;
989 }
990
991 static gboolean __bt_hal_find_device_by_partial_name(char *buffer,
992                 const char *partial_name)
993 {
994         char *pch;
995         char *last;
996
997         pch = strtok_r(buffer, "= ,", &last);
998
999         if (pch == NULL)
1000                 return FALSE;
1001
1002         while ((pch = strtok_r(NULL, ",", &last))) {
1003                 if (g_str_has_prefix(partial_name, pch)) {
1004                         DBG("Match found\n");
1005                         return TRUE;
1006                 }
1007         }
1008         return FALSE;
1009 }
1010
1011 static gboolean __bt_hal_device_is_device_blacklisted(const char *address,
1012                 const char *name)
1013 {
1014         char *buffer;
1015         char **lines;
1016         int i;
1017         FILE *fp;
1018         long size;
1019         size_t result;
1020
1021         DBG("+");
1022
1023         fp = fopen(BT_HAL_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
1024
1025         if (fp == NULL) {
1026                 ERR("Unable to open blacklist file");
1027                 return FALSE;
1028         }
1029
1030         fseek(fp, 0, SEEK_END);
1031         size = ftell(fp);
1032         if (size <= 0) {
1033                 DBG("size is not a positive number");
1034                 fclose(fp);
1035                 return FALSE;
1036         }
1037
1038         rewind(fp);
1039
1040         buffer = g_malloc0(sizeof(char) * size);
1041         /* Fix : NULL_RETURNS */
1042         if (buffer == NULL) {
1043                 ERR("Fail to allocate memory");
1044                 fclose(fp);
1045                 return FALSE;
1046         }
1047         result = fread((char *)buffer, 1, size, fp);
1048         fclose(fp);
1049         if (result != size) {
1050                 ERR("Read Error");
1051                 g_free(buffer);
1052                 return FALSE;
1053         }
1054
1055         lines = g_strsplit_set(buffer, BT_HAL_AGENT_NEW_LINE, 0);
1056         g_free(buffer);
1057
1058         if (lines == NULL) {
1059                 ERR("No lines in the file");
1060                 return FALSE;
1061         }
1062
1063         for (i = 0; lines[i] != NULL; i++) {
1064                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
1065                         if (__bt_hal_find_device_by_address_exactname(
1066                                                 lines[i], address))
1067                                 goto done;
1068                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
1069                         if (__bt_hal_find_device_by_address_exactname(
1070                                                 lines[i], name))
1071                                 goto done;
1072                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
1073                         if (__bt_hal_find_device_by_partial_name(lines[i],
1074                                                 name))
1075                                 goto done;
1076                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
1077                         if (__bt_hal_find_device_by_address_exactname(
1078                                                 lines[i], address))
1079                                 goto done;
1080         }
1081         g_strfreev(lines);
1082         DBG("-");
1083         return FALSE;
1084 done:
1085         DBG("Found the device");
1086         g_strfreev(lines);
1087         return TRUE;
1088 }
1089
1090 static gboolean __bt_hal_device_is_auto_response(uint32_t dev_class,
1091                 const gchar *address, const gchar *name)
1092 {
1093         gboolean is_headset = FALSE;
1094         gboolean is_mouse = FALSE;
1095         unsigned int adapter_class = 0;
1096         char lap_address[BT_HAL_LOWER_ADDRESS_LENGTH];
1097
1098         DBG("bt_agent_is_headset_class, %d +", dev_class);
1099
1100         if (address == NULL)
1101                 return FALSE;
1102
1103         _bt_hal_dbus_get_adapter_class(&adapter_class);
1104
1105         if (((adapter_class & 0x1f00) >> 8) == 0x05)
1106         {
1107                 DBG("Adapter is Peripheral, do not response automatically");
1108                 return FALSE;
1109         }
1110
1111         switch ((dev_class & 0x1f00) >> 8) {
1112         case 0x04:
1113                 switch ((dev_class & 0xfc) >> 2) {
1114                 case 0x01:
1115                 case 0x02:
1116                         /* Headset */
1117                         is_headset = TRUE;
1118                         break;
1119                 case 0x06:
1120                         /* Headphone */
1121                         is_headset = TRUE;
1122                         break;
1123                 case 0x0b:      /* VCR */
1124                 case 0x0c:      /* Video Camera */
1125                 case 0x0d:      /* Camcorder */
1126                         break;
1127                 default:
1128                         /* Other audio device */
1129                         is_headset = TRUE;
1130                         break;
1131                 }
1132                 break;
1133         case 0x05:
1134                 switch (dev_class & 0xff) {
1135                 case 0x80:  /* 0x80: Pointing device(Mouse) */
1136                         is_mouse = TRUE;
1137                         break;
1138
1139                 case 0x40: /* 0x40: input device (BT keyboard) */
1140
1141                         /* Get the LAP(Lower Address part) */
1142                         g_strlcpy(lap_address, address, sizeof(lap_address));
1143
1144                         /* Need to Auto pair the blacklisted Keyboard */
1145                         if (__bt_hal_device_is_device_blacklisted(lap_address, name) != TRUE) {
1146                                 DBG("Device is not black listed\n");
1147                                 return FALSE;
1148                         } else {
1149                                 ERR("Device is black listed\n");
1150                                 return TRUE;
1151                         }
1152                 }
1153         }
1154
1155         if ((!is_headset) && (!is_mouse))
1156                 return FALSE;
1157
1158         /* Get the LAP(Lower Address part) */
1159         g_strlcpy(lap_address, address, sizeof(lap_address));
1160
1161         DBG("Device address = %s\n", address);
1162         DBG("Address 3 byte = %s\n", lap_address);
1163
1164         if (__bt_hal_device_is_device_blacklisted(lap_address, name)) {
1165                 ERR("Device is black listed\n");
1166                 return FALSE;
1167         }
1168
1169         return TRUE;
1170 }
1171
1172 static GVariant *__bt_hal_service_getall(GDBusProxy *device, const char *interface)
1173 {
1174         GError *error = NULL;
1175         GVariant *reply;
1176
1177         reply = g_dbus_proxy_call_sync(device,
1178                         "GetAll", g_variant_new("(s)", interface),
1179                         G_DBUS_CALL_FLAGS_NONE, -1,
1180                         NULL, &error);
1181         if (reply == NULL) {
1182                 ERR("GetAll dBUS-RPC failed");
1183                 if (error) {
1184                         ERR("D-Bus API failure: errCode[%x], message[%s]",
1185                                         error->code, error->message);
1186                         g_clear_error(&error);
1187                 }
1188                 return NULL;
1189         }
1190
1191         return reply;
1192 }
1193
1194 static void __bt_hal_agent_release_memory(void)
1195 {
1196         /* Release Malloc Memory*/
1197         malloc_trim(0);
1198
1199         /* Release Stack Memory*/
1200         stack_trim();
1201 }
1202
1203 static inline void stack_trim(void)
1204 {
1205 #ifdef STACK_FLUSH
1206         unsigned int sp;
1207         char buf[BUF_SIZE];
1208         FILE *file;
1209         unsigned int stacktop;
1210         int found = 0;
1211
1212         asm volatile ("mov %0,sp " : "=r"(sp));
1213
1214         sprintf(buf, "/proc/%d/maps", getpid());
1215         file = fopen(buf, "r");
1216         while (fgets(buf, BUF_SIZE, file) != NULL) {
1217                 if (strstr(buf, "[stack]")) {
1218                         found = 1;
1219                         break;
1220                 }
1221         }
1222         fclose(file);
1223
1224         if (found) {
1225                 sscanf(buf, "%x-", &stacktop);
1226                 if (madvise((void *)PAGE_ALIGN(stacktop), PAGE_ALIGN(sp) - stacktop,
1227                                         MADV_DONTNEED) < 0)
1228                         perror("stack madvise fail");
1229         }
1230 #endif
1231 }