mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-26 05:34:23 +08:00
Store debug keys in runtime memory
This patch adds the possibility of using debug keys for consequtive connections by storing them in runtime memory instead of discarding them after the connection. This functionality can be enabled using a new DebugKeys boolean parameter in main.conf.
This commit is contained in:
parent
e5e25c7618
commit
a30b7569ba
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
static DBusConnection *connection = NULL;
|
static DBusConnection *connection = NULL;
|
||||||
|
|
||||||
static gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
|
gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
|
||||||
struct btd_adapter **adapter,
|
struct btd_adapter **adapter,
|
||||||
struct btd_device **device,
|
struct btd_device **device,
|
||||||
gboolean create)
|
gboolean create)
|
||||||
@ -669,15 +669,19 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
|
|||||||
struct btd_device *device;
|
struct btd_device *device;
|
||||||
struct btd_adapter *adapter;
|
struct btd_adapter *adapter;
|
||||||
uint8_t local_auth = 0xff, remote_auth, new_key_type;
|
uint8_t local_auth = 0xff, remote_auth, new_key_type;
|
||||||
gboolean bonding, stored;
|
gboolean bonding, temporary = FALSE;
|
||||||
|
|
||||||
if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
|
if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (key_type == 0x06 && old_key_type != 0xff)
|
new_key_type = key_type;
|
||||||
new_key_type = old_key_type;
|
|
||||||
else
|
if (key_type == 0x06) {
|
||||||
new_key_type = key_type;
|
if (device_get_debug_key(device, NULL))
|
||||||
|
old_key_type = 0x03;
|
||||||
|
if (old_key_type != 0xff)
|
||||||
|
new_key_type = old_key_type;
|
||||||
|
}
|
||||||
|
|
||||||
get_auth_requirements(local, peer, &local_auth);
|
get_auth_requirements(local, peer, &local_auth);
|
||||||
remote_auth = device_get_auth(device);
|
remote_auth = device_get_auth(device);
|
||||||
@ -686,7 +690,12 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
|
|||||||
DBG("local auth 0x%02x and remote auth 0x%02x",
|
DBG("local auth 0x%02x and remote auth 0x%02x",
|
||||||
local_auth, remote_auth);
|
local_auth, remote_auth);
|
||||||
|
|
||||||
/* Only store the link key if one of the following is true:
|
/* Clear any previous debug key */
|
||||||
|
device_set_debug_key(device, NULL);
|
||||||
|
|
||||||
|
/* Store the link key only in runtime memory if it's a debug
|
||||||
|
* key, else store the link key persistently if one of the
|
||||||
|
* following is true:
|
||||||
* 1. this is a legacy link key
|
* 1. this is a legacy link key
|
||||||
* 2. this is a changed combination key and there was a previously
|
* 2. this is a changed combination key and there was a previously
|
||||||
* stored one
|
* stored one
|
||||||
@ -694,8 +703,14 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
|
|||||||
* 4. the local side had dedicated bonding as a requirement
|
* 4. the local side had dedicated bonding as a requirement
|
||||||
* 5. the remote side is using dedicated bonding since in that case
|
* 5. the remote side is using dedicated bonding since in that case
|
||||||
* also the local requirements are set to dedicated bonding
|
* also the local requirements are set to dedicated bonding
|
||||||
|
* If none of the above match only keep the link key around for
|
||||||
|
* this connection and set the temporary flag for the device.
|
||||||
*/
|
*/
|
||||||
if (key_type < 0x03 || (key_type == 0x06 && old_key_type != 0xff) ||
|
if (new_key_type == 0x03) {
|
||||||
|
DBG("Storing debug key in runtime memory");
|
||||||
|
device_set_debug_key(device, key);
|
||||||
|
} else if (key_type < 0x03 ||
|
||||||
|
(key_type == 0x06 && old_key_type != 0xff) ||
|
||||||
(local_auth > 0x01 && remote_auth > 0x01) ||
|
(local_auth > 0x01 && remote_auth > 0x01) ||
|
||||||
(local_auth == 0x02 || local_auth == 0x03) ||
|
(local_auth == 0x02 || local_auth == 0x03) ||
|
||||||
(remote_auth == 0x02 || remote_auth == 0x03)) {
|
(remote_auth == 0x02 || remote_auth == 0x03)) {
|
||||||
@ -709,10 +724,8 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
|
|||||||
error("write_link_key: %s (%d)", strerror(-err), -err);
|
error("write_link_key: %s (%d)", strerror(-err), -err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
stored = TRUE;
|
|
||||||
} else
|
} else
|
||||||
stored = FALSE;
|
temporary = TRUE;
|
||||||
|
|
||||||
/* If this is not the first link key set a flag so a subsequent auth
|
/* If this is not the first link key set a flag so a subsequent auth
|
||||||
* complete event doesn't trigger SDP */
|
* complete event doesn't trigger SDP */
|
||||||
@ -724,7 +737,7 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
|
|||||||
else if (!bonding && old_key_type == 0xff)
|
else if (!bonding && old_key_type == 0xff)
|
||||||
hcid_dbus_bonding_process_complete(local, peer, 0);
|
hcid_dbus_bonding_process_complete(local, peer, 0);
|
||||||
|
|
||||||
if (!stored)
|
if (temporary)
|
||||||
device_set_temporary(device, TRUE);
|
device_set_temporary(device, TRUE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -45,6 +45,11 @@ int hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
|
|||||||
uint8_t *key, uint8_t key_type,
|
uint8_t *key, uint8_t key_type,
|
||||||
int pin_length, uint8_t old_key_type);
|
int pin_length, uint8_t old_key_type);
|
||||||
|
|
||||||
|
gboolean get_adapter_and_device(bdaddr_t *src, bdaddr_t *dst,
|
||||||
|
struct btd_adapter **adapter,
|
||||||
|
struct btd_device **device,
|
||||||
|
gboolean create);
|
||||||
|
|
||||||
DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status);
|
DBusMessage *new_authentication_return(DBusMessage *msg, uint8_t status);
|
||||||
|
|
||||||
const char *class_to_icon(uint32_t class);
|
const char *class_to_icon(uint32_t class);
|
||||||
|
27
src/device.c
27
src/device.c
@ -143,6 +143,9 @@ struct btd_device {
|
|||||||
|
|
||||||
gboolean authorizing;
|
gboolean authorizing;
|
||||||
gint ref;
|
gint ref;
|
||||||
|
|
||||||
|
gboolean has_debug_key;
|
||||||
|
uint8_t debug_key[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint16_t uuid_list[] = {
|
static uint16_t uuid_list[] = {
|
||||||
@ -2430,6 +2433,30 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
|
|||||||
return find_record_in_list(device->tmp_records, uuid);
|
return find_record_in_list(device->tmp_records, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean device_set_debug_key(struct btd_device *device, uint8_t *key)
|
||||||
|
{
|
||||||
|
if (key == NULL) {
|
||||||
|
device->has_debug_key = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(device->debug_key, key, 16);
|
||||||
|
device->has_debug_key = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean device_get_debug_key(struct btd_device *device, uint8_t *key)
|
||||||
|
{
|
||||||
|
if (!device->has_debug_key)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (key != NULL)
|
||||||
|
memcpy(key, device->debug_key, 16);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
int btd_register_device_driver(struct btd_device_driver *driver)
|
int btd_register_device_driver(struct btd_device_driver *driver)
|
||||||
{
|
{
|
||||||
device_drivers = g_slist_append(device_drivers, driver);
|
device_drivers = g_slist_append(device_drivers, driver);
|
||||||
|
@ -79,6 +79,8 @@ gboolean device_is_authenticating(struct btd_device *device);
|
|||||||
gboolean device_is_authorizing(struct btd_device *device);
|
gboolean device_is_authorizing(struct btd_device *device);
|
||||||
void device_set_authorizing(struct btd_device *device, gboolean auth);
|
void device_set_authorizing(struct btd_device *device, gboolean auth);
|
||||||
void device_set_renewed_key(struct btd_device *device, gboolean renewed);
|
void device_set_renewed_key(struct btd_device *device, gboolean renewed);
|
||||||
|
gboolean device_set_debug_key(struct btd_device *device, uint8_t *key);
|
||||||
|
gboolean device_get_debug_key(struct btd_device *device, uint8_t *key);
|
||||||
void device_add_connection(struct btd_device *device, DBusConnection *conn,
|
void device_add_connection(struct btd_device *device, DBusConnection *conn,
|
||||||
uint16_t handle);
|
uint16_t handle);
|
||||||
void device_remove_connection(struct btd_device *device, DBusConnection *conn,
|
void device_remove_connection(struct btd_device *device, DBusConnection *conn,
|
||||||
|
@ -60,6 +60,7 @@ struct main_opts {
|
|||||||
gboolean remember_powered;
|
gboolean remember_powered;
|
||||||
gboolean reverse_sdp;
|
gboolean reverse_sdp;
|
||||||
gboolean name_resolv;
|
gboolean name_resolv;
|
||||||
|
gboolean debug_keys;
|
||||||
|
|
||||||
uint8_t scan;
|
uint8_t scan;
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
|
@ -201,6 +201,13 @@ static void parse_config(GKeyFile *config)
|
|||||||
else
|
else
|
||||||
main_opts.name_resolv = boolean;
|
main_opts.name_resolv = boolean;
|
||||||
|
|
||||||
|
boolean = g_key_file_get_boolean(config, "General",
|
||||||
|
"DebugKeys", &err);
|
||||||
|
if (err)
|
||||||
|
g_clear_error(&err);
|
||||||
|
else
|
||||||
|
main_opts.debug_keys = boolean;
|
||||||
|
|
||||||
main_opts.link_mode = HCI_LM_ACCEPT;
|
main_opts.link_mode = HCI_LM_ACCEPT;
|
||||||
|
|
||||||
main_opts.link_policy = HCI_LP_RSWITCH | HCI_LP_SNIFF |
|
main_opts.link_policy = HCI_LP_RSWITCH | HCI_LP_SNIFF |
|
||||||
|
@ -50,3 +50,8 @@ ReverseServiceDiscovery = true
|
|||||||
# Enable name resolving after inquiry. Set it to 'false' if you don't need
|
# Enable name resolving after inquiry. Set it to 'false' if you don't need
|
||||||
# remote devices name and want shorter discovery cycle. Defaults to 'true'.
|
# remote devices name and want shorter discovery cycle. Defaults to 'true'.
|
||||||
NameResolving = true
|
NameResolving = true
|
||||||
|
|
||||||
|
# Enable runtime persistency of debug link keys. Default is false which
|
||||||
|
# makes debug link keys valid only for the duration of the connection
|
||||||
|
# that they were created for.
|
||||||
|
DebugKeys = false
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#include "textfile.h"
|
#include "textfile.h"
|
||||||
|
|
||||||
#include "adapter.h"
|
#include "adapter.h"
|
||||||
|
#include "device.h"
|
||||||
#include "dbus-hci.h"
|
#include "dbus-hci.h"
|
||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
@ -301,12 +302,17 @@ static inline void update_lastused(bdaddr_t *sba, bdaddr_t *dba)
|
|||||||
|
|
||||||
static void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
|
static void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
|
||||||
{
|
{
|
||||||
|
struct btd_adapter *adapter;
|
||||||
|
struct btd_device *device;
|
||||||
struct hci_auth_info_req req;
|
struct hci_auth_info_req req;
|
||||||
unsigned char key[16];
|
unsigned char key[16];
|
||||||
char sa[18], da[18];
|
char sa[18], da[18];
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (!get_adapter_and_device(sba, dba, &adapter, &device, FALSE))
|
||||||
|
device = NULL;
|
||||||
|
|
||||||
ba2str(sba, sa); ba2str(dba, da);
|
ba2str(sba, sa); ba2str(dba, da);
|
||||||
info("link_key_request (sba=%s, dba=%s)", sa, da);
|
info("link_key_request (sba=%s, dba=%s)", sa, da);
|
||||||
|
|
||||||
@ -323,26 +329,30 @@ static void link_key_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
|
|||||||
|
|
||||||
DBG("kernel auth requirements = 0x%02x", req.type);
|
DBG("kernel auth requirements = 0x%02x", req.type);
|
||||||
|
|
||||||
err = read_link_key(sba, dba, key, &type);
|
if (main_opts.debug_keys && device && device_get_debug_key(device, key))
|
||||||
if (err < 0) {
|
type = 0x03;
|
||||||
|
else if (read_link_key(sba, dba, key, &type) < 0 || type == 0x03) {
|
||||||
/* Link key not found */
|
/* Link key not found */
|
||||||
hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 6, dba);
|
hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY, 6, dba);
|
||||||
} else {
|
return;
|
||||||
/* Link key found */
|
}
|
||||||
|
|
||||||
|
/* Link key found */
|
||||||
|
|
||||||
|
DBG("link key type = 0x%02x", type);
|
||||||
|
|
||||||
|
/* Don't use unauthenticated combination keys if MITM is
|
||||||
|
* required */
|
||||||
|
if (type == 0x04 && req.type != 0xff && (req.type & 0x01))
|
||||||
|
hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_NEG_REPLY,
|
||||||
|
6, dba);
|
||||||
|
else {
|
||||||
link_key_reply_cp lr;
|
link_key_reply_cp lr;
|
||||||
|
|
||||||
memcpy(lr.link_key, key, 16);
|
memcpy(lr.link_key, key, 16);
|
||||||
bacpy(&lr.bdaddr, dba);
|
bacpy(&lr.bdaddr, dba);
|
||||||
|
|
||||||
DBG("stored link key type = 0x%02x", type);
|
hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_REPLY,
|
||||||
|
|
||||||
/* Don't use debug link keys (0x03) and also don't use
|
|
||||||
* unauthenticated combination keys if MITM is required */
|
|
||||||
if (type == 0x03 || (type == 0x04 && req.type != 0xff &&
|
|
||||||
(req.type & 0x01)))
|
|
||||||
hci_send_cmd(dev, OGF_LINK_CTL,
|
|
||||||
OCF_LINK_KEY_NEG_REPLY, 6, dba);
|
|
||||||
else
|
|
||||||
hci_send_cmd(dev, OGF_LINK_CTL, OCF_LINK_KEY_REPLY,
|
|
||||||
LINK_KEY_REPLY_CP_SIZE, &lr);
|
LINK_KEY_REPLY_CP_SIZE, &lr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user