3457d7788ecef94052c83c326273accc3cafbde6
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-agent.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <malloc.h>
22 #include <stacktrim.h>
23 #include <vconf.h>
24 #include <bundle_internal.h>
25
26 #include <tethering.h>
27
28 #include "bt-internal-types.h"
29 #include "bt-service-common.h"
30 #include "bt-service-agent.h"
31 #include "bt-service-gap-agent.h"
32 #include "bt-service-adapter.h"
33 #include "bt-service-event.h"
34 #include "bt-service-rfcomm-server.h"
35 #include "bt-service-device.h"
36 #include "bt-service-audio.h"
37
38 #ifdef TIZEN_FEATURE_BT_DPM
39 #include "bt-service-dpm.h"
40 #endif
41
42 #define BT_APP_AUTHENTICATION_TIMEOUT           35
43 #define BT_APP_AUTHORIZATION_TIMEOUT            15
44
45 #define HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
46 #define HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb"
47 #define A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB"
48 #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
49 #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
50 #define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb"
51 #define SPP_UUID "00001101-0000-1000-8000-00805f9b34fb"
52 #define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb"
53 #define MAP_UUID "00001132-0000-1000-8000-00805f9b34fb"
54 #define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb"
55 #define GN_UUID "00001117-0000-1000-8000-00805f9b34fb"
56 #define BNEP_UUID "0000000f-0000-1000-8000-00805f9b34fb"
57 #define HID_UUID "00001124-0000-1000-8000-00805f9b34fb"
58 #define HID_DEVICE_UUID         "00001124-0000-1000-8000-00805f9b43bf"
59 #define SAP_UUID_OLD "a49eb41e-cb06-495c-9f4f-bb80a90cdf00"
60 #define SAP_UUID_NEW "a49eb41e-cb06-495c-9f4f-aa80a90cdf4a"
61 #define IOTIVITY_UUID "12341234-1C25-481F-9DFB-59193D238280"
62
63 #define BT_AGENT_OBJECT "/org/bluez/agent/frwk_agent"
64
65 #define BT_AGENT_INTERFACE "org.bluez.Agent1"
66
67 #define BT_AGENT_SIGNAL_RFCOMM_AUTHORIZE "RfcommAuthorize"
68 #define BT_AGENT_SIGNAL_OBEX_AUTHORIZE "ObexAuthorize"
69
70 #define BT_PASSKEY_MAX_LENGTH 4
71
72 #define BT_AGENT_SYSPOPUP_TIMEOUT_FOR_MULTIPLE_POPUPS 200
73 #define BT_AGENT_SYSPOPUP_MAX_ATTEMPT 3
74 #define BT_PAN_MAX_CONNECTION 4
75
76 extern guint nap_connected_device_count;
77
78 static char *passkey_watcher = NULL;
79
80 #define G_VARIANT_UNREF(variant) \
81         g_variant_unref(variant); \
82         variant = NULL
83
84 static int __bt_agent_is_auto_response(uint32_t dev_class, const gchar *address,
85                                                         const gchar *name);
86 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class);
87 static int __bt_agent_generate_passkey(char *passkey, int size);
88
89 static void __bt_agent_release_memory(void)
90 {
91         /* Release Malloc Memory*/
92         malloc_trim(0);
93
94         /* Release Stack Memory*/
95         stack_trim();
96 }
97
98 static GVariant *__bt_service_getall(GDBusProxy *device, const char *interface)
99 {
100         GError *error = NULL;
101         GVariant *reply;
102
103         reply = g_dbus_proxy_call_sync(device,
104                         "GetAll", g_variant_new("(s)", interface),
105                         G_DBUS_CALL_FLAGS_NONE, -1,
106                         NULL, &error);
107         if (reply == NULL) {
108                 ERR("GetAll dBUS-RPC failed");
109                 if (error) {
110                         ERR("D-Bus API failure: errCode[%x], message[%s]",
111                                 error->code, error->message);
112                         g_clear_error(&error);
113                 }
114                 return NULL;
115         }
116
117         return reply;
118 }
119
120 static gboolean __pincode_request(GapAgentPrivate *agent, GDBusProxy *device)
121 {
122         uint32_t device_class;
123         gchar *address = NULL;
124         unsigned char auth_info[5] = {0, };
125         gchar *name = NULL;
126         GVariant *reply = NULL;
127         GVariant *reply_temp = NULL;
128         GVariant *tmp_value;
129         char pin_code[BLUETOOTH_PIN_CODE_MAX_LENGTH + 1];
130         int ret = BLUETOOTH_ERROR_NONE;
131 #ifdef TIZEN_FEATURE_BT_DPM
132         int pairing_state = DPM_STATUS_ERROR;
133 #endif
134
135         BT_DBG("+");
136
137 #ifdef TIZEN_FEATURE_BT_DPM
138         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
139         if (pairing_state == DPM_RESTRICTED) {
140                 BT_ERR("Not allow to pair the device");
141                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
142                 __bt_agent_release_memory();
143                 return TRUE;
144         }
145 #endif
146
147         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
148
149         if (reply_temp == NULL) {
150                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
151                                 NULL);
152                 goto done;
153         }
154
155         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
156
157         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
158         g_variant_get(tmp_value, "u", &device_class);
159         G_VARIANT_UNREF(tmp_value);
160
161         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
162         g_variant_get(tmp_value, "s", &address);
163         G_VARIANT_UNREF(tmp_value);
164         if (!address) {
165                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
166                 goto done;
167         }
168
169         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
170         g_variant_get(tmp_value, "s", &name);
171         G_VARIANT_UNREF(tmp_value);
172         if (!name) {
173                 BT_DBG("Replacing the name with address");
174                 name = g_strdup(address);
175         } else {
176                 BT_INFO("Name = %s, Address = %s, Class = 0x%x", name, address, device_class);
177                 if (name[0] == '\0') {
178                         g_free(name);
179                         BT_DBG("Name[0]=NULL, Replacing the name with address");
180                         name = g_strdup(address);
181                 }
182         }
183
184         __bt_get_auth_info(reply, (char *)auth_info);
185         if (_bt_is_device_creating() == TRUE &&
186                 _bt_is_bonding_device_address(address) == TRUE &&
187                 __bt_agent_is_auto_response(device_class, address, name)) {
188                 BT_DBG("0000 Auto Pair");
189                 /* Use Fixed PIN "0000" for basic pairing */
190                 _bt_set_autopair_status_in_bonding_info(TRUE);
191                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
192                                                                         NULL);
193         } else if (__bt_agent_is_hid_keyboard(device_class)) {
194                 BT_DBG("HID Keyboard");
195                 char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 };
196
197                 if (__bt_agent_generate_passkey(str_passkey,
198                                         BT_PASSKEY_MAX_LENGTH) != 0) {
199                         gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
200                                                 "", NULL);
201                         goto done;
202                 }
203
204                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
205                                                         str_passkey, NULL);
206
207                 if (headed_plugin_info->plugin_headed_enabled) {
208                         headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
209                                         name, auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
210                 } else {
211                         GVariant *param = NULL;
212                         param = g_variant_new("(isss)", ret, address, name, str_passkey);
213                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY, param);
214                 }
215         } else if (_bt_get_device_pin_code(address, pin_code)
216                                 == BLUETOOTH_ERROR_NONE) {
217                 BT_DBG("Use stored PIN code(%s)", pin_code);
218                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, pin_code,
219                                                                         NULL);
220                 goto done;
221         } else {
222                 if (headed_plugin_info->plugin_headed_enabled) {
223                         BT_DBG("Show Pin entry");
224                         headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, auth_info,
225                                         NULL, NULL, _gap_agent_get_path(agent));
226                 } else {
227                         BT_INFO("Plugin Headed not Enabled");
228                         GVariant *param = NULL;
229                         param = g_variant_new("(iss)", ret, address, name);
230                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PIN_REQUEST, param);
231                 }
232         }
233
234 done:
235         g_variant_unref(reply);
236         g_variant_unref(reply_temp);
237         g_free(address);
238         g_free(name);
239         __bt_agent_release_memory();
240         BT_DBG("-");
241
242         return TRUE;
243 }
244
245 static gboolean __passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
246 {
247         gchar *address = NULL;
248         gchar *name = NULL;
249         unsigned char auth_info[5] = {0, };
250         GVariant *reply = NULL;
251         GVariant *reply_temp = NULL;
252         GVariant *tmp_value;
253         int ret = BLUETOOTH_ERROR_NONE;
254 #ifdef TIZEN_FEATURE_BT_DPM
255         int pairing_state = DPM_STATUS_ERROR;
256 #endif
257
258         BT_DBG("+");
259
260 #ifdef TIZEN_FEATURE_BT_DPM
261         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
262         if (pairing_state == DPM_RESTRICTED) {
263                 BT_ERR("Not allow to pair the device");
264                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
265                 __bt_agent_release_memory();
266                 return TRUE;
267         }
268 #endif
269
270         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
271
272         if (reply_temp == NULL) {
273                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
274                                              NULL);
275                 goto done;
276         }
277
278         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
279
280         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
281         g_variant_get(tmp_value, "s", &address);
282         G_VARIANT_UNREF(tmp_value);
283         if (!address) {
284                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
285                 goto done;
286         }
287
288         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
289         g_variant_get(tmp_value, "s", &name);
290         G_VARIANT_UNREF(tmp_value);
291         if (!name)
292                 name = g_strdup(address);
293
294         __bt_get_auth_info(reply, (char *)auth_info);
295
296         if (headed_plugin_info->plugin_headed_enabled) {
297                 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, auth_info,
298                                 NULL, NULL, _gap_agent_get_path(agent));
299         } else {
300                 BT_INFO("Plugin Headed not Enabled");
301                 GVariant *param = NULL;
302                 param = g_variant_new("(iss)", ret, address, name);
303                 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PASSKEY_REQUEST, param);
304         }
305
306
307 done:
308         g_variant_unref(reply);
309         g_variant_unref(reply_temp);
310         g_free(address);
311         g_free(name);
312         __bt_agent_release_memory();
313
314         BT_DBG("-");
315         return TRUE;
316 }
317
318 static gboolean __display_request(GapAgentPrivate *agent, GDBusProxy *device,
319                                                                 guint passkey)
320 {
321         gchar *address = NULL;
322         gchar *name = NULL;
323         unsigned char auth_info[5] = {0, };
324         char *str_passkey;
325         GVariant *reply = NULL;
326         GVariant *reply_temp = NULL;
327         GVariant *tmp_value = NULL;
328         int ret = BLUETOOTH_ERROR_NONE;
329
330         BT_DBG("+");
331
332         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
333         if (reply_temp == NULL) {
334                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
335                                              NULL);
336                 goto done;
337         }
338
339         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
340
341         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
342         g_variant_get(tmp_value, "s", &address);
343         G_VARIANT_UNREF(tmp_value);
344         if (!address) {
345                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
346                 goto done;
347         }
348
349         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
350         g_variant_get(tmp_value, "s", &name);
351         G_VARIANT_UNREF(tmp_value);
352         if (!name)
353                 name = g_strdup(address);
354
355         __bt_get_auth_info(reply, (char *)auth_info);
356
357         str_passkey = g_strdup_printf("%06d", passkey);
358
359         GVariant *param = NULL;
360         param = g_variant_new("(ss)", address, str_passkey);
361
362         if (passkey_watcher) {
363                 BT_INFO("Send passkey to %s", passkey_watcher);
364                 _bt_send_event_to_dest(passkey_watcher, BT_ADAPTER_EVENT,
365                                 BLUETOOTH_EVENT_PASSKEY_NOTIFICATION, param);
366         } else {
367                 if (headed_plugin_info->plugin_headed_enabled) {
368                         BT_INFO("Plugin Headed Enabled");
369                         headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
370                                         auth_info, str_passkey, NULL, _gap_agent_get_path(agent));
371                 } else {
372                         BT_INFO("Plugin Headed not Enabled");
373                         GVariant *param = NULL;
374                         param = g_variant_new("(isss)", ret, address, name, str_passkey);
375                         _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_KEYBOARD_PASSKEY_DISPLAY, param);
376                 }
377         }
378
379         g_free(str_passkey);
380
381 done:
382         g_variant_unref(reply);
383         g_variant_unref(reply_temp);
384         g_free(address);
385         g_free(name);
386         __bt_agent_release_memory();
387
388         BT_DBG("-");
389         return TRUE;
390 }
391
392 static gboolean __confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
393                                                                 guint passkey)
394 {
395         gchar *address = NULL;
396         gchar *name = NULL;
397         unsigned char auth_info[5] = {0, };
398         char str_passkey[7];
399         GVariant *reply_temp = NULL;
400         GVariant *reply = NULL;
401         GVariant *tmp_value;
402         int ret = BLUETOOTH_ERROR_NONE;
403 #ifdef TIZEN_FEATURE_BT_DPM
404                 int pairing_state = DPM_STATUS_ERROR;
405 #endif
406         BT_DBG("+ passkey[%.6d]", passkey);
407
408 #ifdef TIZEN_FEATURE_BT_DPM
409         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
410         if (pairing_state == DPM_RESTRICTED) {
411                 BT_ERR("Not allow to pair the device");
412                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
413                 __bt_agent_release_memory();
414                 return TRUE;
415         }
416 #endif
417
418         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
419
420         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
421
422         if (reply_temp == NULL) {
423                 BT_ERR("Device doesn't exist");
424                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
425                                              NULL);
426                 goto done;
427         }
428
429         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
430
431         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
432         g_variant_get(tmp_value, "s", &address);
433         G_VARIANT_UNREF(tmp_value);
434         if (!address) {
435                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
436                 goto done;
437         }
438
439         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
440         g_variant_get(tmp_value, "s", &name);
441         G_VARIANT_UNREF(tmp_value);
442         if (!name)
443                 name = g_strdup(address);
444         __bt_get_auth_info(reply, (char *)auth_info);
445
446         if (headed_plugin_info->plugin_headed_enabled) {
447                 BT_DBG("LAUNCH SYSPOPUP");
448                 headed_plugin_info->headed_plugin->bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
449                                 auth_info, str_passkey, NULL,
450                                 _gap_agent_get_path(agent));
451         } else {
452                 BT_DBG("Headless Confirmation");
453                 GVariant *param = NULL;
454                 param = g_variant_new("(isss)", ret, address, name, str_passkey);
455                 _bt_send_event(BT_ADAPTER_EVENT, BLUETOOTH_EVENT_PASSKEY_CONFIRM_REQUEST, param);
456         }
457
458 done:
459         g_variant_unref(reply);
460         g_variant_unref(reply_temp);
461         g_free(address);
462         g_free(name);
463         __bt_agent_release_memory();
464         BT_DBG("-");
465
466         return TRUE;
467 }
468
469 static gboolean __pairing_cancel_request(GapAgentPrivate *agent, const char *address)
470 {
471         BT_DBG("On Going Pairing is cancelled by remote\n");
472
473         if (headed_plugin_info->plugin_headed_enabled)
474                 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
475
476         __bt_agent_release_memory();
477
478         return TRUE;
479 }
480
481 static gboolean __a2dp_authorize_request_check(void)
482 {
483         /* Check for existing Media device to disconnect */
484         return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
485 }
486
487 static gboolean __authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
488                                                         const char *uuid)
489 {
490         gchar *address = NULL;
491         gchar *name = NULL;
492         unsigned char auth_info[5] = {0, };
493         gboolean trust;
494         GVariant *reply = NULL;
495         GVariant *reply_temp = NULL;
496         GVariant *tmp_value;
497         bool enabled;
498         int result = BLUETOOTH_ERROR_NONE;
499         int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
500         tethering_h tethering = NULL;
501
502         BT_DBG("+");
503
504         /* Check if already Media connection exsist */
505         if (!strcasecmp(uuid, A2DP_UUID)) {
506                 gboolean ret = FALSE;
507
508                 ret = __a2dp_authorize_request_check();
509
510                 if (ret) {
511                         BT_ERR("Already one A2DP device connected \n");
512                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
513                                               NULL);
514                         goto done;
515                 }
516         }
517         /* Check completed */
518
519         if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
520              !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) ||
521              !strcasecmp(uuid, HFP_HS_UUID) ||
522              !strcasecmp(uuid, HSP_HS_UUID) ||
523              !strcasecmp(uuid, A2DP_UUID) ||
524              !strcasecmp(uuid, HID_UUID) ||
525              !strcasecmp(uuid, HID_DEVICE_UUID) ||
526              !strcasecmp(uuid, SAP_UUID_OLD) ||
527              !strcasecmp(uuid, SAP_UUID_NEW) ||
528              !strcasecmp(uuid, IOTIVITY_UUID) ||
529              !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
530                 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
531                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
532                                               NULL);
533
534                 goto done;
535         }
536
537         if (!strcasecmp(uuid, NAP_UUID) ||
538              !strcasecmp(uuid, GN_UUID) ||
539               !strcasecmp(uuid, BNEP_UUID)) {
540
541                 BT_DBG("Network connection request: %s", uuid);
542                 if (TIZEN_FEATURE_NETWORK_TETHERING_ENABLE) {
543                         if (nap_connected_device_count >=
544                                                 BT_PAN_MAX_CONNECTION) {
545                                 BT_ERR("Max connection exceeded");
546                                 goto fail;
547                         }
548                         int ret;
549                         ret = tethering_create(&tethering);
550
551                         if (ret != TETHERING_ERROR_NONE) {
552                                 BT_ERR("Fail to create tethering: %d", ret);
553                                 goto fail;
554                         }
555
556                         enabled = tethering_is_enabled(tethering, TETHERING_TYPE_BT);
557
558                         ret = tethering_destroy(tethering);
559
560                         if (ret != TETHERING_ERROR_NONE)
561                                 BT_ERR("Fail to create tethering: %d", ret);
562
563                         if (enabled != true) {
564                                 BT_ERR("BT tethering is not enabled");
565                                 goto fail;
566                         }
567                 }
568
569                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
570                                               NULL);
571                 goto done;
572 fail:
573                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
574                       NULL);
575
576                 goto done;
577         }
578
579         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
580         if (reply_temp == NULL) {
581                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
582                                              NULL);
583                 goto done;
584         }
585
586         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
587
588         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
589         g_variant_get(tmp_value, "s", &address);
590         G_VARIANT_UNREF(tmp_value);
591         if (!address) {
592                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
593                 goto done;
594         }
595
596         tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
597         g_variant_get(tmp_value, "s", &name);
598         G_VARIANT_UNREF(tmp_value);
599         if (!name)
600                 name = g_strdup(address);
601
602         tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
603         g_variant_get(tmp_value, "b", &trust);
604         G_VARIANT_UNREF(tmp_value);
605
606         __bt_get_auth_info(reply, (char *)auth_info);
607
608         BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
609
610         if (strcasecmp(uuid, OPP_UUID) == 0 &&
611              _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
612                                         NULL) == TRUE) {
613                 _bt_send_event(BT_OPP_SERVER_EVENT,
614                                 BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
615                                 g_variant_new("(iss)", result, address, name));
616
617                 goto done;
618         }
619         /* TODO: MAP? see above */
620
621         if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
622                                         (char *)uuid) == TRUE) {
623                 bt_agent_osp_server_t *osp_serv;
624                 osp_serv = _gap_agent_get_osp_server(agent,
625                                                 BT_RFCOMM_SERVER, (char *)uuid);
626
627                 if (osp_serv) {
628                         _bt_send_event(BT_RFCOMM_SERVER_EVENT,
629                                 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
630                                 g_variant_new("(issssn)", result, address, uuid,
631                                                 name, osp_serv->path, osp_serv->fd));
632                 }
633
634                 goto done;
635         }
636
637         if (!strcasecmp(uuid, OPP_UUID))
638                 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
639         else if (!strcasecmp(uuid, PBAP_UUID))
640                 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
641         else if (!strcasecmp(uuid, MAP_UUID))
642                 request_type = BT_AGENT_EVENT_MAP_REQUEST;
643         /* TODO: MAP is already here */
644
645         if (trust || !headed_plugin_info->plugin_headed_enabled) {
646                 BT_INFO("Trusted or Headless device, so authorize\n");
647                 gap_agent_reply_authorize(agent,
648                                 GAP_AGENT_ACCEPT, NULL);
649
650                 goto done;
651         }
652
653         if (headed_plugin_info->plugin_headed_enabled) {
654                 headed_plugin_info->headed_plugin->bt_launch_system_popup(request_type, name, auth_info, NULL, NULL,
655                                         _gap_agent_get_path(agent));
656         }
657
658 done:
659         if (reply)
660                 g_variant_unref(reply);
661
662         if (reply_temp)
663                 g_variant_unref(reply_temp);
664
665         g_free(name);
666         g_free(address);
667         __bt_agent_release_memory();
668         BT_DBG("-");
669
670         return TRUE;
671 }
672
673 static gboolean __authorization_cancel_request(GapAgentPrivate *agent,
674                                                         const char *address)
675 {
676         BT_DBG("On Going Authorization is cancelled by remote\n");
677
678         gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
679
680         if (headed_plugin_info->plugin_headed_enabled)
681                 headed_plugin_info->headed_plugin->bt_destroy_popup_all();
682
683         __bt_agent_release_memory();
684
685         return TRUE;
686 }
687
688 void _bt_destroy_agent(void *agent)
689 {
690         if (!agent)
691                 return;
692
693         _gap_agent_reset_dbus((GapAgentPrivate *)agent);
694
695         g_free(agent);
696 }
697
698 void* _bt_create_agent(const char *path, gboolean adapter)
699 {
700         GAP_AGENT_FUNC_CB func_cb;
701         GDBusProxy *adapter_proxy;
702         GapAgentPrivate *agent;
703
704         adapter_proxy = _bt_get_adapter_proxy();
705         if (!adapter_proxy)
706                 return NULL;
707
708         func_cb.pincode_func = __pincode_request;
709         func_cb.display_func = __display_request;
710         func_cb.passkey_func = __passkey_request;
711         func_cb.confirm_func = __confirm_request;
712         func_cb.authorize_func = __authorize_request;
713         func_cb.pairing_cancel_func = __pairing_cancel_request;
714         func_cb.authorization_cancel_func = __authorization_cancel_request;
715
716         /* Allocate memory*/
717         agent = g_new0(GapAgentPrivate, 1);
718
719         _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
720
721         if (adapter) {
722                 if (!_gap_agent_register(agent)) {
723                         _bt_destroy_agent(agent);
724                         agent = NULL;
725                 }
726         }
727
728         return agent;
729 }
730
731 gboolean _bt_agent_register_osp_server(const gint type,
732                 const char *uuid, char *path, int fd)
733 {
734         void *agent = _bt_get_adapter_agent();
735         if (!agent)
736                 return FALSE;
737
738         return _gap_agent_register_osp_server(agent, type, uuid, path, fd);
739
740 }
741
742 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
743 {
744         void *agent = _bt_get_adapter_agent();
745
746         if (!agent)
747                 return FALSE;
748
749         return _gap_agent_unregister_osp_server(agent, type, uuid);
750 }
751
752 gboolean _bt_agent_reply_authorize(gboolean accept)
753 {
754         guint accept_val;
755
756         void *agent = _bt_get_adapter_agent();
757         if (!agent)
758                 return FALSE;
759
760         accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
761
762         return gap_agent_reply_authorize(agent, accept_val, NULL);
763 }
764
765 gboolean _bt_agent_is_canceled(void)
766 {
767         void *agent = _bt_get_adapter_agent();
768         if (!agent)
769                 return FALSE;
770
771         return _gap_agent_is_canceled(agent);
772 }
773
774 void _bt_agent_set_canceled(gboolean value)
775 {
776         void *agent = _bt_get_adapter_agent();
777         if (!agent)
778                 return;
779
780         return _gap_agent_set_canceled(agent, value);
781 }
782
783 int _bt_agent_reply_cancellation(void)
784 {
785         void *agent = _bt_get_adapter_agent();
786
787         if (!agent)
788                 return BLUETOOTH_ERROR_INTERNAL;
789
790         if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
791                 BT_ERR("Fail to reply agent");
792                 return BLUETOOTH_ERROR_INTERNAL;
793         }
794
795         return BLUETOOTH_ERROR_NONE;
796 }
797
798 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
799 {
800         switch ((dev_class & 0x1f00) >> 8) {
801         case 0x05:
802                 switch ((dev_class & 0xc0) >> 6) {
803                 case 0x01:
804                         /* input-keyboard" */
805                         return TRUE;
806                 }
807                 break;
808         }
809
810         return FALSE;
811 }
812
813 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
814                                                         const char *address)
815 {
816         char *pch;
817         char *last;
818
819         pch = strtok_r(buffer, "= ,", &last);
820
821         if (pch == NULL)
822                 return FALSE;
823
824         while ((pch = strtok_r(NULL, ",", &last))) {
825                 if (0 == g_strcmp0(pch, address)) {
826                         BT_DBG("Match found\n");
827                         return TRUE;
828                 }
829         }
830         return FALSE;
831 }
832
833 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
834                                                 const char *partial_name)
835 {
836         char *pch;
837         char *last;
838
839         pch = strtok_r(buffer, "= ,", &last);
840
841         if (pch == NULL)
842                 return FALSE;
843
844         while ((pch = strtok_r(NULL, ",", &last))) {
845                 if (g_str_has_prefix(partial_name, pch)) {
846                         BT_DBG("Match found\n");
847                         return TRUE;
848                 }
849         }
850         return FALSE;
851 }
852
853 static gboolean __bt_agent_is_device_blacklist(const char *address,
854                                                         const char *name)
855 {
856         char *buffer;
857         char **lines;
858         int i;
859         FILE *fp;
860         long size;
861         size_t result;
862
863         BT_DBG("+");
864
865         fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
866
867         if (fp == NULL) {
868                 BT_ERR("Unable to open blacklist file");
869                 return FALSE;
870         }
871
872         fseek(fp, 0, SEEK_END);
873         size = ftell(fp);
874         if (size <= 0) {
875                 BT_DBG("size is not a positive number");
876                 fclose(fp);
877                 return FALSE;
878         }
879
880         rewind(fp);
881
882         buffer = g_malloc0(sizeof(char) * size);
883         result = fread((char *)buffer, 1, size, fp);
884         fclose(fp);
885         if (result != size) {
886                 BT_ERR("Read Error");
887                 g_free(buffer);
888                 return FALSE;
889         }
890
891         BT_DBG("Buffer = %s", buffer);
892
893         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
894         g_free(buffer);
895
896         if (lines == NULL) {
897                 BT_ERR("No lines in the file");
898                 return FALSE;
899         }
900
901         for (i = 0; lines[i] != NULL; i++) {
902                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
903                         if (__bt_agent_find_device_by_address_exactname(
904                                                 lines[i], address))
905                                 goto done;
906                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
907                         if (__bt_agent_find_device_by_address_exactname(
908                                                 lines[i], name))
909                                 goto done;
910                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
911                         if (__bt_agent_find_device_by_partial_name(lines[i],
912                                                                 name))
913                                 goto done;
914                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
915                         if (__bt_agent_find_device_by_address_exactname(
916                                                 lines[i], address))
917                                 goto done;
918         }
919         g_strfreev(lines);
920         BT_DBG("-");
921         return FALSE;
922 done:
923         BT_DBG("Found the device");
924         g_strfreev(lines);
925         return TRUE;
926 }
927
928 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
929                                 const gchar *address, const gchar *name)
930 {
931         gboolean is_headset = FALSE;
932         gboolean is_mouse = FALSE;
933         char lap_address[BT_LOWER_ADDRESS_LENGTH];
934
935         BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
936
937         if (address == NULL)
938                 return FALSE;
939
940         switch ((dev_class & 0x1f00) >> 8) {
941         case 0x04:
942                 switch ((dev_class & 0xfc) >> 2) {
943                 case 0x01:
944                 case 0x02:
945                         /* Headset */
946                         is_headset = TRUE;
947                         break;
948                 case 0x06:
949                         /* Headphone */
950                         is_headset = TRUE;
951                         break;
952                 case 0x0b:      /* VCR */
953                 case 0x0c:      /* Video Camera */
954                 case 0x0d:      /* Camcorder */
955                         break;
956                 default:
957                         /* Other audio device */
958                         is_headset = TRUE;
959                         break;
960                 }
961                 break;
962         case 0x05:
963                 switch (dev_class & 0xff) {
964                 case 0x80:  /* 0x80: Pointing device(Mouse) */
965                         is_mouse = TRUE;
966                         break;
967
968                 case 0x40: /* 0x40: input device (BT keyboard) */
969
970                         /* Get the LAP(Lower Address part) */
971                         g_strlcpy(lap_address, address, sizeof(lap_address));
972
973                         /* Need to Auto pair the blacklisted Keyboard */
974                         if (__bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
975                                 BT_DBG("Device is not black listed\n");
976                                 return FALSE;
977                         } else {
978                                 BT_ERR("Device is black listed\n");
979                                 return TRUE;
980                         }
981                 }
982         }
983
984         if ((!is_headset) && (!is_mouse))
985                 return FALSE;
986
987         /* Get the LAP(Lower Address part) */
988         g_strlcpy(lap_address, address, sizeof(lap_address));
989
990         BT_DBG("Device address = %s\n", address);
991         BT_DBG("Address 3 byte = %s\n", lap_address);
992
993         if (__bt_agent_is_device_blacklist(lap_address, name)) {
994                 BT_ERR("Device is black listed\n");
995                 return FALSE;
996         }
997
998         return TRUE;
999 }
1000
1001 static int __bt_agent_generate_passkey(char *passkey, int size)
1002 {
1003         int i;
1004         ssize_t len;
1005         int random_fd;
1006         unsigned int value = 0;
1007
1008         if (passkey == NULL)
1009                 return -1;
1010
1011         if (size <= 0)
1012                 return -1;
1013
1014         random_fd = open("/dev/urandom", O_RDONLY);
1015
1016         if (random_fd < 0)
1017                 return -1;
1018
1019         for (i = 0; i < size; i++) {
1020                 len = read(random_fd, &value, sizeof(value));
1021                 if (len > 0)
1022                         passkey[i] = '0' + (value % 10);
1023         }
1024
1025         close(random_fd);
1026
1027         BT_DBG("passkey: %s", passkey);
1028
1029         return 0;
1030 }
1031
1032 int _bt_set_passkey_notification(const char *sender, gboolean enable)
1033 {
1034         BT_INFO("Set passkey notification(sender:%s, %s)",
1035                         sender, enable ? "Enable" : "Disable");
1036
1037         g_free(passkey_watcher);
1038         if (enable == TRUE)
1039                 passkey_watcher = g_strdup(sender);
1040         else
1041                 passkey_watcher = NULL;
1042
1043         return BLUETOOTH_ERROR_NONE;
1044 }