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