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