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