autopair.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2012 Google Inc.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #include <stdbool.h>
  14. #include <stdlib.h>
  15. #include <fcntl.h>
  16. #include <unistd.h>
  17. #include <errno.h>
  18. #include <glib.h>
  19. #include "lib/bluetooth.h"
  20. #include "lib/sdp.h"
  21. #include "src/plugin.h"
  22. #include "src/adapter.h"
  23. #include "src/device.h"
  24. #include "src/log.h"
  25. #include "src/storage.h"
  26. /*
  27. * Plugin to handle automatic pairing of devices with reduced user
  28. * interaction, including implementing the recommendation of the HID spec
  29. * for keyboard devices.
  30. *
  31. * The plugin works by intercepting the PIN request for devices; if the
  32. * device is a keyboard a random six-digit numeric PIN is generated and
  33. * returned, flagged for displaying using DisplayPinCode.
  34. *
  35. */
  36. static ssize_t autopair_pincb(struct btd_adapter *adapter,
  37. struct btd_device *device,
  38. char *pinbuf, bool *display,
  39. unsigned int attempt)
  40. {
  41. char addr[18];
  42. char pinstr[7];
  43. char name[25];
  44. uint32_t class;
  45. ba2str(device_get_address(device), addr);
  46. class = btd_device_get_class(device);
  47. device_get_name(device, name, sizeof(name));
  48. DBG("device '%s' (%s) class: 0x%x vid/pid: 0x%X/0x%X",
  49. name, addr, class,
  50. btd_device_get_vendor (device),
  51. btd_device_get_product (device));
  52. /* The iCade shouldn't use random PINs like normal keyboards */
  53. if (strstr(name, "iCade") != NULL)
  54. return 0;
  55. /* This is a class-based pincode guesser. Ignore devices with an
  56. * unknown class.
  57. */
  58. if (class == 0)
  59. return 0;
  60. switch ((class & 0x1f00) >> 8) {
  61. case 0x04: /* Audio/Video */
  62. switch ((class & 0xfc) >> 2) {
  63. case 0x01: /* Wearable Headset Device */
  64. case 0x02: /* Hands-free Device */
  65. case 0x06: /* Headphones */
  66. case 0x07: /* Portable Audio */
  67. case 0x0a: /* HiFi Audio Device */
  68. {
  69. const char *pincodes[] = {
  70. "0000",
  71. "1234",
  72. "1111"
  73. };
  74. const char *pincode;
  75. if (attempt > G_N_ELEMENTS(pincodes))
  76. return 0;
  77. pincode = pincodes[attempt - 1];
  78. memcpy(pinbuf, pincode, strlen(pincode));
  79. return strlen(pincode);
  80. }
  81. }
  82. break;
  83. case 0x05: /* Peripheral */
  84. switch ((class & 0xc0) >> 6) {
  85. case 0x00:
  86. switch ((class & 0x1e) >> 2) {
  87. case 0x01: /* Joystick */
  88. case 0x02: /* Gamepad */
  89. case 0x03: /* Remote Control */
  90. if (attempt > 1)
  91. return 0;
  92. memcpy(pinbuf, "0000", 4);
  93. return 4;
  94. }
  95. break;
  96. case 0x01: /* Keyboard */
  97. case 0x03: /* Combo keyboard/pointing device */
  98. /* For keyboards rejecting the first random code
  99. * in less than 500ms, try a fixed code. */
  100. if (attempt > 1 &&
  101. device_bonding_last_duration(device) < 500) {
  102. /* Don't try more than one dumb code */
  103. if (attempt > 2)
  104. return 0;
  105. /* Try "0000" as the code for the second
  106. * attempt. */
  107. memcpy(pinbuf, "0000", 4);
  108. return 4;
  109. }
  110. /* Never try more than 3 random pincodes. */
  111. if (attempt >= 4)
  112. return 0;
  113. snprintf(pinstr, sizeof(pinstr), "%06u",
  114. rand() % 1000000);
  115. *display = true;
  116. memcpy(pinbuf, pinstr, 6);
  117. return 6;
  118. case 0x02: /* Pointing device */
  119. if (attempt > 1)
  120. return 0;
  121. memcpy(pinbuf, "0000", 4);
  122. return 4;
  123. }
  124. break;
  125. case 0x06: /* Imaging */
  126. if (class & 0x80) { /* Printer */
  127. if (attempt > 1)
  128. return 0;
  129. memcpy(pinbuf, "0000", 4);
  130. return 4;
  131. }
  132. break;
  133. }
  134. return 0;
  135. }
  136. static int autopair_probe(struct btd_adapter *adapter)
  137. {
  138. btd_adapter_register_pin_cb(adapter, autopair_pincb);
  139. return 0;
  140. }
  141. static void autopair_remove(struct btd_adapter *adapter)
  142. {
  143. btd_adapter_unregister_pin_cb(adapter, autopair_pincb);
  144. }
  145. static struct btd_adapter_driver autopair_driver = {
  146. .name = "autopair",
  147. .probe = autopair_probe,
  148. .remove = autopair_remove,
  149. };
  150. static int autopair_init(void)
  151. {
  152. /* Initialize the random seed from /dev/urandom */
  153. unsigned int seed;
  154. int fd, err;
  155. ssize_t n;
  156. fd = open("/dev/urandom", O_RDONLY);
  157. if (fd < 0) {
  158. err = -errno;
  159. error("Failed to open /dev/urandom: %s (%d)", strerror(-err),
  160. -err);
  161. return err;
  162. }
  163. n = read(fd, &seed, sizeof(seed));
  164. if (n < (ssize_t) sizeof(seed)) {
  165. err = (n == -1) ? -errno : -EIO;
  166. error("Failed to read %zu bytes from /dev/urandom: %s (%d)",
  167. sizeof(seed), strerror(-err), -err);
  168. close(fd);
  169. return err;
  170. }
  171. close(fd);
  172. srand(seed);
  173. return btd_register_adapter_driver(&autopair_driver);
  174. }
  175. static void autopair_exit(void)
  176. {
  177. btd_unregister_adapter_driver(&autopair_driver);
  178. }
  179. BLUETOOTH_PLUGIN_DEFINE(autopair, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
  180. autopair_init, autopair_exit)