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