Check connectable when authorize for HID device is requested.
[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_FEATURE_BT_DPM
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;
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 #ifdef TIZEN_FEATURE_BT_DPM
265         int pairing_state = DPM_STATUS_ERROR;
266 #endif
267
268         BT_DBG("+");
269
270 #ifdef TIZEN_FEATURE_BT_DPM
271         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
272         if (pairing_state == DPM_RESTRICTED) {
273                 BT_ERR("Not allow to pair the device");
274                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
275                 __bt_agent_release_memory();
276                 return TRUE;
277         }
278 #endif
279
280         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
281
282         if (reply_temp == NULL) {
283                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
284                                 NULL);
285                 goto done;
286         }
287
288         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
289
290         tmp_value = g_variant_lookup_value(reply, "Class", G_VARIANT_TYPE_UINT32);
291         g_variant_get(tmp_value, "u", &device_class);
292         G_VARIANT_UNREF(tmp_value);
293
294         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
295         g_variant_get(tmp_value, "s", &address);
296         G_VARIANT_UNREF(tmp_value);
297         if (!address) {
298                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
299                 goto done;
300         }
301
302         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
303         g_variant_get(tmp_value, "s", &name);
304         G_VARIANT_UNREF(tmp_value);
305         if (!name) {
306                 BT_DBG("Replacing the name with address");
307                 name = g_strdup(address);
308         } else {
309                 BT_INFO("Name = %s, Address = %s, Class = 0x%x", name, address, device_class);
310                 if (name[0] == '\0') {
311                         g_free(name);
312                         BT_DBG("Name[0]=NULL, Replacing the name with address");
313                         name = g_strdup(address);
314                 }
315         }
316
317         __bt_get_auth_info(reply, (char *)auth_info);
318         if (_bt_is_device_creating() == TRUE &&
319                 _bt_is_bonding_device_address(address) == TRUE &&
320                 __bt_agent_is_auto_response(device_class, address, name)) {
321                 BT_DBG("0000 Auto Pair");
322                 /* Use Fixed PIN "0000" for basic pairing */
323                 _bt_set_autopair_status_in_bonding_info(TRUE);
324                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, "0000",
325                                                                         NULL);
326         } else if (__bt_agent_is_hid_keyboard(device_class)) {
327                 BT_DBG("HID Keyboard");
328                 char str_passkey[BT_PASSKEY_MAX_LENGTH + 1] = { 0 };
329
330                 if (__bt_agent_generate_passkey(str_passkey,
331                                         BT_PASSKEY_MAX_LENGTH) != 0) {
332                         gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT,
333                                                 "", NULL);
334                         goto done;
335                 }
336
337                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT,
338                                                         str_passkey, NULL);
339
340                 _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST,
341                                                 name, auth_info, str_passkey, NULL,
342                                                 _gap_agent_get_path(agent));
343         } else if (_bt_get_device_pin_code(address, pin_code)
344                                 == BLUETOOTH_ERROR_NONE) {
345                 BT_DBG("Use stored PIN code(%s)", pin_code);
346                 gap_agent_reply_pin_code(agent, GAP_AGENT_ACCEPT, pin_code,
347                                                                         NULL);
348                 goto done;
349         } else {
350                 BT_DBG("Show Pin entry");
351                 _bt_launch_system_popup(BT_AGENT_EVENT_PIN_REQUEST, name, auth_info,
352                                         NULL, NULL, _gap_agent_get_path(agent));
353         }
354
355 done:
356         g_variant_unref(reply);
357         g_variant_unref(reply_temp);
358         g_free(address);
359         g_free(name);
360         __bt_agent_release_memory();
361         BT_DBG("-");
362
363         return TRUE;
364 }
365
366 static gboolean __passkey_request(GapAgentPrivate *agent, GDBusProxy *device)
367 {
368         gchar *address = NULL;
369         gchar *name = NULL;
370         unsigned char auth_info[5] = {0, };
371         GVariant *reply = NULL;
372         GVariant *reply_temp = NULL;
373         GVariant *tmp_value;
374 #ifdef TIZEN_FEATURE_BT_DPM
375         int pairing_state = DPM_STATUS_ERROR;
376 #endif
377
378         BT_DBG("+");
379
380 #ifdef TIZEN_FEATURE_BT_DPM
381         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
382         if (pairing_state == DPM_RESTRICTED) {
383                 BT_ERR("Not allow to pair the device");
384                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
385                 __bt_agent_release_memory();
386                 return TRUE;
387         }
388 #endif
389
390         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
391
392         if (reply_temp == NULL) {
393                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
394                                              NULL);
395                 goto done;
396         }
397
398         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
399
400         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
401         g_variant_get(tmp_value, "s", &address);
402         G_VARIANT_UNREF(tmp_value);
403         if (!address) {
404                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
405                 goto done;
406         }
407
408         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
409         g_variant_get(tmp_value, "s", &name);
410         G_VARIANT_UNREF(tmp_value);
411         if (!name)
412                 name = g_strdup(address);
413
414         __bt_get_auth_info(reply, (char *)auth_info);
415
416         _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_REQUEST, name, auth_info,
417                                                 NULL, NULL, _gap_agent_get_path(agent));
418
419 done:
420         g_variant_unref(reply);
421         g_variant_unref(reply_temp);
422         g_free(address);
423         g_free(name);
424         __bt_agent_release_memory();
425
426         BT_DBG("-");
427         return TRUE;
428 }
429
430 static gboolean __display_request(GapAgentPrivate *agent, GDBusProxy *device,
431                                                                 guint passkey)
432 {
433         gchar *address = NULL;
434         gchar *name = NULL;
435         unsigned char auth_info[5] = {0, };
436         char *str_passkey;
437         GVariant *reply = NULL;
438         GVariant *reply_temp = NULL;
439         GVariant *tmp_value = NULL;
440
441         BT_DBG("+");
442
443         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
444         if (reply_temp == NULL) {
445                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
446                                              NULL);
447                 goto done;
448         }
449
450         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
451
452         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
453         g_variant_get(tmp_value, "s", &address);
454         G_VARIANT_UNREF(tmp_value);
455         if (!address) {
456                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
457                 goto done;
458         }
459
460         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
461         g_variant_get(tmp_value, "s", &name);
462         G_VARIANT_UNREF(tmp_value);
463         if (!name)
464                 name = g_strdup(address);
465
466         __bt_get_auth_info(reply, (char *)auth_info);
467
468         str_passkey = g_strdup_printf("%06d", passkey);
469
470         if (passkey_watcher) {
471                 GVariant *param = NULL;
472
473                 BT_INFO("Send passkey to %s", passkey_watcher);
474
475                 param = g_variant_new("(ss)", address, str_passkey);
476
477                 _bt_send_event_to_dest(passkey_watcher, BT_ADAPTER_EVENT,
478                                 BLUETOOTH_EVENT_PASSKEY_NOTIFICATION, param);
479         } else {
480                 _bt_launch_system_popup(BT_AGENT_EVENT_KEYBOARD_PASSKEY_REQUEST, name,
481                                                 auth_info, str_passkey, NULL,
482                                                 _gap_agent_get_path(agent));
483         }
484
485         g_free(str_passkey);
486
487 done:
488         g_variant_unref(reply);
489         g_variant_unref(reply_temp);
490         g_free(address);
491         g_free(name);
492         __bt_agent_release_memory();
493
494         BT_DBG("-");
495         return TRUE;
496 }
497
498 static gboolean __confirm_request(GapAgentPrivate *agent, GDBusProxy *device,
499                                                                 guint passkey)
500 {
501         gchar *address = NULL;
502         gchar *name = NULL;
503         unsigned char auth_info[5] = {0, };
504         char str_passkey[7];
505         GVariant *reply_temp = NULL;
506         GVariant *reply = NULL;
507         GVariant *tmp_value;
508 #ifdef TIZEN_FEATURE_BT_DPM
509                 int pairing_state = DPM_STATUS_ERROR;
510 #endif
511         BT_DBG("+ passkey[%.6d]", passkey);
512
513 #ifdef TIZEN_FEATURE_BT_DPM
514         _bt_dpm_get_bluetooth_pairing_state(&pairing_state);
515         if (pairing_state == DPM_RESTRICTED) {
516                 BT_ERR("Not allow to pair the device");
517                 gap_agent_reply_confirmation(agent, GAP_AGENT_REJECT, NULL);
518                 __bt_agent_release_memory();
519                 return TRUE;
520         }
521 #endif
522
523         snprintf(str_passkey, sizeof(str_passkey), "%.6d", passkey);
524
525         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
526
527         if (reply_temp == NULL) {
528                 BT_ERR("Device doesn't exist");
529                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
530                                              NULL);
531                 goto done;
532         }
533
534         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
535
536         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
537         g_variant_get(tmp_value, "s", &address);
538         G_VARIANT_UNREF(tmp_value);
539         if (!address) {
540                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
541                 goto done;
542         }
543
544         tmp_value = g_variant_lookup_value(reply, "Name", G_VARIANT_TYPE_STRING);
545         g_variant_get(tmp_value, "s", &name);
546         G_VARIANT_UNREF(tmp_value);
547         if (!name)
548                 name = g_strdup(address);
549         __bt_get_auth_info(reply, (char *)auth_info);
550
551         BT_DBG("LAUNCH SYSPOPUP");
552         _bt_launch_system_popup(BT_AGENT_EVENT_PASSKEY_CONFIRM_REQUEST, name,
553                                                 auth_info, str_passkey, NULL,
554                                                 _gap_agent_get_path(agent));
555
556 done:
557         g_variant_unref(reply);
558         g_variant_unref(reply_temp);
559         g_free(address);
560         g_free(name);
561         __bt_agent_release_memory();
562         BT_DBG("-");
563
564         return TRUE;
565 }
566
567 static gboolean __pairing_cancel_request(GapAgentPrivate *agent, const char *address)
568 {
569         BT_DBG("On Going Pairing is cancelled by remote\n");
570
571         syspopup_destroy_all();
572
573         __bt_agent_release_memory();
574
575         return TRUE;
576 }
577
578 static gboolean __a2dp_authorize_request_check(void)
579 {
580         /* Check for existing Media device to disconnect */
581         return _bt_is_headset_type_connected(BT_AUDIO_A2DP, NULL);
582 }
583
584 static gboolean __bt_agent_is_hid_device_connectable(void)
585 {
586         GDBusProxy *proxy = NULL;
587         GVariant *reply = NULL;
588         GError *err = NULL;
589         gboolean connectable = FALSE;
590
591         proxy = _bt_gdbus_get_hid_agent_proxy();
592         retv_if(proxy == NULL, FALSE);
593
594         reply = g_dbus_proxy_call_sync(proxy, "IsHidConnectable", NULL,
595                                 G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &err);
596         if (reply == NULL) {
597                 BT_ERR("Error returned in method call");
598                 if (err != NULL) {
599                         BT_ERR("Error message = %s", err->message);
600                         g_error_free(err);
601                 }
602                 connectable = FALSE;
603         } else {
604                 g_variant_get(reply, "(b)", &connectable);
605                 g_variant_unref(reply);
606         }
607         g_object_unref(proxy);
608
609         BT_INFO("HID Device is %s",
610                         connectable ? "Connectable" : "Non-connectable");
611
612         return connectable;
613 }
614
615 static gboolean __authorize_request(GapAgentPrivate *agent, GDBusProxy *device,
616                                                         const char *uuid)
617 {
618         gchar *address = NULL;
619         gchar *name = NULL;
620         unsigned char auth_info[5] = {0, };
621         gboolean trust;
622         GVariant *reply = NULL;
623         GVariant *reply_temp = NULL;
624         GVariant *tmp_value;
625 #ifdef TIZEN_FEATURE_NETWORK_TETHERING_ENABLE
626         bool enabled;
627         tethering_h tethering = NULL;
628 #endif
629         int result = BLUETOOTH_ERROR_NONE;
630         int request_type = BT_AGENT_EVENT_AUTHORIZE_REQUEST;
631
632         BT_DBG("+");
633
634         /* Check if already Media connection exsist */
635         if (!strcasecmp(uuid, A2DP_UUID)) {
636                 gboolean ret = FALSE;
637
638                 ret = __a2dp_authorize_request_check();
639
640                 if (ret) {
641                         BT_ERR("Already one A2DP device connected \n");
642                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
643                                               NULL);
644                         goto done;
645                 }
646         }
647         /* Check completed */
648
649         if (!strcasecmp(uuid, HID_UUID)) {
650                 gboolean is_connectable = __bt_agent_is_hid_device_connectable();
651                 BT_DBG("Automatically %s authorization for HID",
652                         is_connectable ? "accept" : "reject");
653                 if (is_connectable == TRUE)
654                         gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT, NULL);
655                 else
656                         gap_agent_reply_authorize(agent, GAP_AGENT_REJECT, NULL);
657                 goto done;
658         }
659
660         if (!strcasecmp(uuid, HFP_AUDIO_GATEWAY_UUID) ||
661              !strcasecmp(uuid, HSP_AUDIO_GATEWAY_UUID) ||
662              !strcasecmp(uuid, HFP_HS_UUID) ||
663              !strcasecmp(uuid, HSP_HS_UUID) ||
664              !strcasecmp(uuid, A2DP_UUID) ||
665              !strcasecmp(uuid, HID_DEVICE_UUID) ||
666              !strcasecmp(uuid, SAP_UUID_OLD) ||
667              !strcasecmp(uuid, SAP_UUID_NEW) ||
668              !strcasecmp(uuid, IOTIVITY_UUID) ||
669              !strcasecmp(uuid, AVRCP_TARGET_UUID)) {
670                 BT_DBG("Auto accept authorization for audio device (HFP, A2DP, AVRCP) [%s]", uuid);
671                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
672                                               NULL);
673
674                 goto done;
675         }
676
677         if (!strcasecmp(uuid, NAP_UUID) ||
678              !strcasecmp(uuid, GN_UUID) ||
679               !strcasecmp(uuid, BNEP_UUID)) {
680
681                 BT_DBG("Network connection request: %s", uuid);
682 #ifdef TIZEN_FEATURE_NETWORK_TETHERING_ENABLE
683                 if (nap_connected_device_count >=
684                                         BT_PAN_MAX_CONNECTION) {
685                         BT_ERR("Max connection exceeded");
686                         goto fail;
687                 }
688                 int ret;
689                 ret = tethering_create(&tethering);
690
691                 if (ret != TETHERING_ERROR_NONE) {
692                         BT_ERR("Fail to create tethering: %d", ret);
693                         goto fail;
694                 }
695
696                 enabled = tethering_is_enabled(tethering, TETHERING_TYPE_BT);
697
698                 ret = tethering_destroy(tethering);
699
700                 if (ret != TETHERING_ERROR_NONE)
701                         BT_ERR("Fail to create tethering: %d", ret);
702
703                 if (enabled != true) {
704                         BT_ERR("BT tethering is not enabled");
705                         goto fail;
706                 }
707 #endif
708
709                 gap_agent_reply_authorize(agent, GAP_AGENT_ACCEPT,
710                                               NULL);
711                 goto done;
712 #ifdef TIZEN_FEATURE_NETWORK_TETHERING_ENABLE
713 fail:
714                 gap_agent_reply_authorize(agent, GAP_AGENT_REJECT,
715                       NULL);
716
717                 goto done;
718 #endif
719         }
720
721         reply_temp = __bt_service_getall(device, BT_DEVICE_INTERFACE);
722         if (reply_temp == NULL) {
723                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "",
724                                              NULL);
725                 goto done;
726         }
727
728         g_variant_get(reply_temp, "(@a{sv})", &reply); /* Format of reply a{sv}*/
729
730         tmp_value = g_variant_lookup_value(reply, "Address", G_VARIANT_TYPE_STRING);
731         g_variant_get(tmp_value, "s", &address);
732         G_VARIANT_UNREF(tmp_value);
733         if (!address) {
734                 gap_agent_reply_pin_code(agent, GAP_AGENT_REJECT, "", NULL);
735                 goto done;
736         }
737
738         tmp_value = g_variant_lookup_value(reply, "Alias", G_VARIANT_TYPE_STRING);
739         g_variant_get(tmp_value, "s", &name);
740         G_VARIANT_UNREF(tmp_value);
741         if (!name)
742                 name = g_strdup(address);
743
744         tmp_value = g_variant_lookup_value(reply, "Trusted", G_VARIANT_TYPE_BOOLEAN);
745         g_variant_get(tmp_value, "b", &trust);
746         G_VARIANT_UNREF(tmp_value);
747
748         __bt_get_auth_info(reply, (char *)auth_info);
749
750         BT_INFO("Authorization request for device [%s] Service:[%s]\n", address, uuid);
751
752         if (strcasecmp(uuid, OPP_UUID) == 0 &&
753              _gap_agent_exist_osp_server(agent, BT_OBEX_SERVER,
754                                         NULL) == TRUE) {
755                 _bt_send_event(BT_OPP_SERVER_EVENT,
756                                 BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
757                                 g_variant_new("(iss)", result, address, name));
758
759                 goto done;
760         }
761         /* TODO: MAP? see above */
762
763         if (_gap_agent_exist_osp_server(agent, BT_RFCOMM_SERVER,
764                                         (char *)uuid) == TRUE) {
765                 bt_agent_osp_server_t *osp_serv;
766                 osp_serv = _gap_agent_get_osp_server(agent,
767                                                 BT_RFCOMM_SERVER, (char *)uuid);
768
769                 if (osp_serv) {
770                         _bt_send_event(BT_RFCOMM_SERVER_EVENT,
771                                 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
772                                 g_variant_new("(issssn)", result, address, uuid,
773                                                 name, osp_serv->path, osp_serv->fd));
774                 }
775
776                 goto done;
777         }
778
779         if (!strcasecmp(uuid, OPP_UUID))
780                 request_type = BT_AGENT_EVENT_EXCHANGE_REQUEST;
781         else if (!strcasecmp(uuid, PBAP_UUID))
782                 request_type = BT_AGENT_EVENT_PBAP_REQUEST;
783         else if (!strcasecmp(uuid, MAP_UUID))
784                 request_type = BT_AGENT_EVENT_MAP_REQUEST;
785         /* TODO: MAP is already here */
786
787         if (trust) {
788                 BT_INFO("Trusted device, so authorize\n");
789                 gap_agent_reply_authorize(agent,
790                                               GAP_AGENT_ACCEPT, NULL);
791         } else {
792                 _bt_launch_system_popup(request_type, name, auth_info, NULL, NULL,
793                                                 _gap_agent_get_path(agent));
794         }
795
796 done:
797         if (reply)
798                 g_variant_unref(reply);
799
800         if (reply_temp)
801                 g_variant_unref(reply_temp);
802
803         g_free(name);
804         g_free(address);
805         __bt_agent_release_memory();
806         BT_DBG("-");
807
808         return TRUE;
809 }
810
811 static gboolean __authorization_cancel_request(GapAgentPrivate *agent,
812                                                         const char *address)
813 {
814         BT_DBG("On Going Authorization is cancelled by remote\n");
815
816         gap_agent_reply_authorize(agent, GAP_AGENT_CANCEL, NULL);
817
818         syspopup_destroy_all();
819
820         __bt_agent_release_memory();
821
822         return TRUE;
823 }
824
825 void _bt_destroy_agent(void *agent)
826 {
827         if (!agent)
828                 return;
829
830         _gap_agent_reset_dbus((GapAgentPrivate *)agent);
831
832         g_free(agent);
833 }
834
835 void* _bt_create_agent(const char *path, gboolean adapter)
836 {
837         GAP_AGENT_FUNC_CB func_cb;
838         GDBusProxy *adapter_proxy;
839         GapAgentPrivate *agent;
840
841         adapter_proxy = _bt_get_adapter_proxy();
842         if (!adapter_proxy)
843                 return NULL;
844
845         func_cb.pincode_func = __pincode_request;
846         func_cb.display_func = __display_request;
847         func_cb.passkey_func = __passkey_request;
848         func_cb.confirm_func = __confirm_request;
849         func_cb.authorize_func = __authorize_request;
850         func_cb.pairing_cancel_func = __pairing_cancel_request;
851         func_cb.authorization_cancel_func = __authorization_cancel_request;
852
853         /* Allocate memory*/
854         agent = g_new0(GapAgentPrivate, 1);
855
856         _gap_agent_setup_dbus(agent, &func_cb, path, adapter_proxy);
857
858         if (adapter) {
859                 if (!_gap_agent_register(agent)) {
860                         _bt_destroy_agent(agent);
861                         agent = NULL;
862                 }
863         }
864
865         return agent;
866 }
867
868 gboolean _bt_agent_register_osp_server(const gint type,
869                 const char *uuid, char *path, int fd)
870 {
871         void *agent = _bt_get_adapter_agent();
872         if (!agent)
873                 return FALSE;
874
875         return _gap_agent_register_osp_server(agent, type, uuid, path, fd);
876
877 }
878
879 gboolean _bt_agent_unregister_osp_server(const gint type, const char *uuid)
880 {
881         void *agent = _bt_get_adapter_agent();
882
883         if (!agent)
884                 return FALSE;
885
886         return _gap_agent_unregister_osp_server(agent, type, uuid);
887 }
888
889 gboolean _bt_agent_reply_authorize(gboolean accept)
890 {
891         guint accept_val;
892
893         void *agent = _bt_get_adapter_agent();
894         if (!agent)
895                 return FALSE;
896
897         accept_val = accept ? GAP_AGENT_ACCEPT : GAP_AGENT_REJECT;
898
899         return gap_agent_reply_authorize(agent, accept_val, NULL);
900 }
901
902 gboolean _bt_agent_is_canceled(void)
903 {
904         void *agent = _bt_get_adapter_agent();
905         if (!agent)
906                 return FALSE;
907
908         return _gap_agent_is_canceled(agent);
909 }
910
911 void _bt_agent_set_canceled(gboolean value)
912 {
913         void *agent = _bt_get_adapter_agent();
914         if (!agent)
915                 return;
916
917         return _gap_agent_set_canceled(agent, value);
918 }
919
920 int _bt_agent_reply_cancellation(void)
921 {
922         void *agent = _bt_get_adapter_agent();
923
924         if (!agent)
925                 return BLUETOOTH_ERROR_INTERNAL;
926
927         if (gap_agent_reply_confirmation(agent, GAP_AGENT_CANCEL, NULL) != TRUE) {
928                 BT_ERR("Fail to reply agent");
929                 return BLUETOOTH_ERROR_INTERNAL;
930         }
931
932         return BLUETOOTH_ERROR_NONE;
933 }
934
935 static gboolean __bt_agent_is_hid_keyboard(uint32_t dev_class)
936 {
937         switch ((dev_class & 0x1f00) >> 8) {
938         case 0x05:
939                 switch ((dev_class & 0xc0) >> 6) {
940                 case 0x01:
941                         /* input-keyboard" */
942                         return TRUE;
943                 }
944                 break;
945         }
946
947         return FALSE;
948 }
949
950 static gboolean __bt_agent_find_device_by_address_exactname(char *buffer,
951                                                         const char *address)
952 {
953         char *pch;
954         char *last;
955
956         pch = strtok_r(buffer, "= ,", &last);
957
958         if (pch == NULL)
959                 return FALSE;
960
961         while ((pch = strtok_r(NULL, ",", &last))) {
962                 if (0 == g_strcmp0(pch, address)) {
963                         BT_DBG("Match found\n");
964                         return TRUE;
965                 }
966         }
967         return FALSE;
968 }
969
970 static gboolean __bt_agent_find_device_by_partial_name(char *buffer,
971                                                 const char *partial_name)
972 {
973         char *pch;
974         char *last;
975
976         pch = strtok_r(buffer, "= ,", &last);
977
978         if (pch == NULL)
979                 return FALSE;
980
981         while ((pch = strtok_r(NULL, ",", &last))) {
982                 if (g_str_has_prefix(partial_name, pch)) {
983                         BT_DBG("Match found\n");
984                         return TRUE;
985                 }
986         }
987         return FALSE;
988 }
989
990 static gboolean __bt_agent_is_device_blacklist(const char *address,
991                                                         const char *name)
992 {
993         char *buffer;
994         char **lines;
995         int i;
996         FILE *fp;
997         long size;
998         size_t result;
999
1000         BT_DBG("+");
1001
1002         fp = fopen(BT_AGENT_AUTO_PAIR_BLACKLIST_FILE, "r");
1003
1004         if (fp == NULL) {
1005                 BT_ERR("Unable to open blacklist file");
1006                 return FALSE;
1007         }
1008
1009         fseek(fp, 0, SEEK_END);
1010         size = ftell(fp);
1011         if (size <= 0) {
1012                 BT_DBG("size is not a positive number");
1013                 fclose(fp);
1014                 return FALSE;
1015         }
1016
1017         rewind(fp);
1018
1019         buffer = g_malloc0(sizeof(char) * size);
1020         result = fread((char *)buffer, 1, size, fp);
1021         fclose(fp);
1022         if (result != size) {
1023                 BT_ERR("Read Error");
1024                 g_free(buffer);
1025                 return FALSE;
1026         }
1027
1028         BT_DBG("Buffer = %s", buffer);
1029
1030         lines = g_strsplit_set(buffer, BT_AGENT_NEW_LINE, 0);
1031         g_free(buffer);
1032
1033         if (lines == NULL) {
1034                 BT_ERR("No lines in the file");
1035                 return FALSE;
1036         }
1037
1038         for (i = 0; lines[i] != NULL; i++) {
1039                 if (g_str_has_prefix(lines[i], "AddressBlacklist"))
1040                         if (__bt_agent_find_device_by_address_exactname(
1041                                                 lines[i], address))
1042                                 goto done;
1043                 if (g_str_has_prefix(lines[i], "ExactNameBlacklist"))
1044                         if (__bt_agent_find_device_by_address_exactname(
1045                                                 lines[i], name))
1046                                 goto done;
1047                 if (g_str_has_prefix(lines[i], "PartialNameBlacklist"))
1048                         if (__bt_agent_find_device_by_partial_name(lines[i],
1049                                                                 name))
1050                                 goto done;
1051                 if (g_str_has_prefix(lines[i], "KeyboardAutoPair"))
1052                         if (__bt_agent_find_device_by_address_exactname(
1053                                                 lines[i], address))
1054                                 goto done;
1055         }
1056         g_strfreev(lines);
1057         BT_DBG("-");
1058         return FALSE;
1059 done:
1060         BT_DBG("Found the device");
1061         g_strfreev(lines);
1062         return TRUE;
1063 }
1064
1065 static gboolean __bt_agent_is_auto_response(uint32_t dev_class,
1066                                 const gchar *address, const gchar *name)
1067 {
1068         gboolean is_headset = FALSE;
1069         gboolean is_mouse = FALSE;
1070         char lap_address[BT_LOWER_ADDRESS_LENGTH];
1071
1072         BT_DBG("bt_agent_is_headset_class, %d +", dev_class);
1073
1074         if (address == NULL)
1075                 return FALSE;
1076
1077         switch ((dev_class & 0x1f00) >> 8) {
1078         case 0x04:
1079                 switch ((dev_class & 0xfc) >> 2) {
1080                 case 0x01:
1081                 case 0x02:
1082                         /* Headset */
1083                         is_headset = TRUE;
1084                         break;
1085                 case 0x06:
1086                         /* Headphone */
1087                         is_headset = TRUE;
1088                         break;
1089                 case 0x0b:      /* VCR */
1090                 case 0x0c:      /* Video Camera */
1091                 case 0x0d:      /* Camcorder */
1092                         break;
1093                 default:
1094                         /* Other audio device */
1095                         is_headset = TRUE;
1096                         break;
1097                 }
1098                 break;
1099         case 0x05:
1100                 switch (dev_class & 0xff) {
1101                 case 0x80:  /* 0x80: Pointing device(Mouse) */
1102                         is_mouse = TRUE;
1103                         break;
1104
1105                 case 0x40: /* 0x40: input device (BT keyboard) */
1106
1107                         /* Get the LAP(Lower Address part) */
1108                         g_strlcpy(lap_address, address, sizeof(lap_address));
1109
1110                         /* Need to Auto pair the blacklisted Keyboard */
1111                         if (__bt_agent_is_device_blacklist(lap_address, name) != TRUE) {
1112                                 BT_DBG("Device is not black listed\n");
1113                                 return FALSE;
1114                         } else {
1115                                 BT_ERR("Device is black listed\n");
1116                                 return TRUE;
1117                         }
1118                 }
1119         }
1120
1121         if ((!is_headset) && (!is_mouse))
1122                 return FALSE;
1123
1124         /* Get the LAP(Lower Address part) */
1125         g_strlcpy(lap_address, address, sizeof(lap_address));
1126
1127         BT_DBG("Device address = %s\n", address);
1128         BT_DBG("Address 3 byte = %s\n", lap_address);
1129
1130         if (__bt_agent_is_device_blacklist(lap_address, name)) {
1131                 BT_ERR("Device is black listed\n");
1132                 return FALSE;
1133         }
1134
1135         return TRUE;
1136 }
1137
1138 static int __bt_agent_generate_passkey(char *passkey, int size)
1139 {
1140         int i;
1141         ssize_t len;
1142         int random_fd;
1143         unsigned int value = 0;
1144
1145         if (passkey == NULL)
1146                 return -1;
1147
1148         if (size <= 0)
1149                 return -1;
1150
1151         random_fd = open("/dev/urandom", O_RDONLY);
1152
1153         if (random_fd < 0)
1154                 return -1;
1155
1156         for (i = 0; i < size; i++) {
1157                 len = read(random_fd, &value, sizeof(value));
1158                 if (len > 0)
1159                         passkey[i] = '0' + (value % 10);
1160         }
1161
1162         close(random_fd);
1163
1164         BT_DBG("passkey: %s", passkey);
1165
1166         return 0;
1167 }
1168
1169 int _bt_set_passkey_notification(const char *sender, gboolean enable)
1170 {
1171         BT_INFO("Set passkey notification(sender:%s, %s)",
1172                         sender, enable ? "Enable" : "Disable");
1173
1174         g_free(passkey_watcher);
1175         if (enable == TRUE)
1176                 passkey_watcher = g_strdup(sender);
1177         else
1178                 passkey_watcher = NULL;
1179
1180         return BLUETOOTH_ERROR_NONE;
1181 }
1182