2012-11-30 14:46:55

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 01/12] doc: Update settings-storage.txt

Add missing Master key to LongTermKey group
---
doc/settings-storage.txt | 2 ++
1 file changed, 2 insertions(+)

diff --git a/doc/settings-storage.txt b/doc/settings-storage.txt
index 3fdcb03..e7ba89d 100644
--- a/doc/settings-storage.txt
+++ b/doc/settings-storage.txt
@@ -181,6 +181,8 @@ Long term key) related to a remote device.
Authenticated Boolean True if remote device has been
authenticated

+ Master Boolean True for master key
+
EncSize Integer Encrypted size

EDiv Integer Encrypted diversifier
--
1.7.9.5



2012-11-30 14:47:05

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 11/12] adapter: Upload long term keys from new storage

Remove check of long term keys from device_create,
this moves to load_devices.
---
src/adapter.c | 127 +++++++++++++++++++++++----------------------------------
src/device.c | 6 ---
2 files changed, 51 insertions(+), 82 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index ff9d2e7..a0ae04c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1790,77 +1790,57 @@ failed:
return info;
}

-static struct smp_ltk_info *get_ltk_info(const char *addr, uint8_t bdaddr_type,
- const char *value)
+static struct smp_ltk_info *get_ltk_info(GKeyFile *key_file, const char *peer)
{
- struct smp_ltk_info *ltk;
- char *ptr;
- int i, ret;
+ struct smp_ltk_info *ltk = NULL;
+ char *key;
+ char *rand = NULL;
+ char *type = NULL;
+ uint8_t bdaddr_type;

- if (strlen(value) < 60) {
- error("Unexpectedly short (%zu) LTK", strlen(value));
- return NULL;
- }
+ key = g_key_file_get_string(key_file, "LongTermKey", "Key", NULL);
+ if (!key || strlen(key) != 34)
+ goto failed;

- ltk = g_new0(struct smp_ltk_info, 1);
+ rand = g_key_file_get_string(key_file, "LongTermKey", "Rand", NULL);
+ if (!rand || strlen(rand) != 18)
+ goto failed;

- str2ba(addr, &ltk->bdaddr);
+ type = g_key_file_get_string(key_file, "General", "AddressType", NULL);
+ if (!type)
+ goto failed;

- ltk->bdaddr_type = bdaddr_type;
+ if (g_str_equal(type, "public"))
+ bdaddr_type = BDADDR_LE_PUBLIC;
+ else if (g_str_equal(type, "static"))
+ bdaddr_type = BDADDR_LE_RANDOM;
+ else
+ goto failed;

- str2buf(value, ltk->val, sizeof(ltk->val));
+ ltk = g_new0(struct smp_ltk_info, 1);

- ptr = (char *) value + 2 * sizeof(ltk->val) + 1;
+ str2ba(peer, &ltk->bdaddr);
+ ltk->bdaddr_type = bdaddr_type;
+ str2buf(&key[2], ltk->val, sizeof(ltk->val));
+ str2buf(&rand[2], ltk->rand, sizeof(ltk->rand));

- ret = sscanf(ptr, " %hhd %hhd %hhd %hd %n",
- &ltk->authenticated, &ltk->master, &ltk->enc_size,
- &ltk->ediv, &i);
- if (ret < 2) {
- g_free(ltk);
- return NULL;
- }
- ptr += i;
+ ltk->authenticated = g_key_file_get_integer(key_file, "LongTermKey",
+ "Authenticated", NULL);
+ ltk->master = g_key_file_get_integer(key_file, "LongTermKey", "Master",
+ NULL);
+ ltk->enc_size = g_key_file_get_integer(key_file, "LongTermKey",
+ "EncSize", NULL);
+ ltk->ediv = g_key_file_get_integer(key_file, "LongTermKey", "EDiv",
+ NULL);

- str2buf(ptr, ltk->rand, sizeof(ltk->rand));
+failed:
+ g_free(key);
+ g_free(rand);
+ g_free(type);

return ltk;
}

-static void create_stored_device_from_ltks(char *key, char *value,
- void *user_data)
-{
- struct adapter_keys *keys = user_data;
- struct btd_adapter *adapter = keys->adapter;
- struct btd_device *device;
- struct smp_ltk_info *info;
- char address[18], srcaddr[18];
- uint8_t bdaddr_type;
-
- if (sscanf(key, "%17s#%hhu", address, &bdaddr_type) < 2)
- return;
-
- info = get_ltk_info(address, bdaddr_type, value);
- if (info == NULL)
- return;
-
- keys->keys = g_slist_append(keys->keys, info);
-
- if (g_slist_find_custom(adapter->devices, address,
- (GCompareFunc) device_address_cmp))
- return;
-
- ba2str(&adapter->bdaddr, srcaddr);
-
- if (g_strcmp0(srcaddr, address) == 0)
- return;
-
- device = device_create(adapter, address, bdaddr_type);
- if (device) {
- device_set_temporary(device, FALSE);
- adapter->devices = g_slist_append(adapter->devices, device);
- }
-}
-
static GSList *string_to_primary_list(char *str)
{
GSList *l = NULL;
@@ -1935,18 +1915,12 @@ static void create_stored_device_from_primaries(char *key, char *value,
g_slist_free(uuids);
}

-static void smp_key_free(void *data)
-{
- struct smp_ltk_info *info = data;
-
- g_free(info);
-}
-
static void load_devices(struct btd_adapter *adapter)
{
char filename[PATH_MAX + 1];
char srcaddr[18];
struct adapter_keys keys = { adapter, NULL };
+ struct adapter_keys ltks = { adapter, NULL };
int err;
DIR *dir;
struct dirent *entry;
@@ -1961,16 +1935,6 @@ static void load_devices(struct btd_adapter *adapter)
textfile_foreach(filename, create_stored_device_from_primaries,
adapter);

- create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "longtermkeys");
- textfile_foreach(filename, create_stored_device_from_ltks, &keys);
-
- err = mgmt_load_ltks(adapter->dev_id, keys.keys);
- if (err < 0)
- error("Unable to load ltks: %s (%d)", strerror(-err), -err);
-
- g_slist_free_full(keys.keys, smp_key_free);
- keys.keys = NULL;
-
snprintf(filename, PATH_MAX, STORAGEDIR "/%s", srcaddr);
filename[PATH_MAX] = '\0';

@@ -1985,6 +1949,7 @@ static void load_devices(struct btd_adapter *adapter)
char filename[PATH_MAX + 1];
GKeyFile *key_file;
struct link_key_info *key_info;
+ struct smp_ltk_info *ltk_info;
GSList *l;

if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
@@ -2000,6 +1965,10 @@ static void load_devices(struct btd_adapter *adapter)
if (key_info)
keys.keys = g_slist_append(keys.keys, key_info);

+ ltk_info = get_ltk_info(key_file, entry->d_name);
+ if (ltk_info)
+ ltks.keys = g_slist_append(ltks.keys, ltk_info);
+
g_key_file_free(key_file);

l = g_slist_find_custom(adapter->devices, entry->d_name,
@@ -2017,7 +1986,7 @@ static void load_devices(struct btd_adapter *adapter)
adapter->devices = g_slist_append(adapter->devices, device);

device_exist:
- if (key_info) {
+ if (key_info || ltk_info) {
device_set_paired(device, TRUE);
device_set_bonded(device, TRUE);
}
@@ -2032,6 +2001,12 @@ device_exist:
strerror(-err), -err);

g_slist_free_full(keys.keys, g_free);
+
+ err = mgmt_load_ltks(adapter->dev_id, ltks.keys);
+ if (err < 0)
+ error("Unable to load ltks: %s (%d)", strerror(-err), -err);
+
+ g_slist_free_full(ltks.keys, g_free);
}

int btd_adapter_block_address(struct btd_adapter *adapter,
diff --git a/src/device.c b/src/device.c
index bb5689b..a5bdf4c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1904,12 +1904,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,

load_info(device, srcaddr, address);

- if (device_is_le(device) && has_longtermkeys(src, &device->bdaddr,
- device->bdaddr_type)) {
- device_set_paired(device, TRUE);
- device_set_bonded(device, TRUE);
- }
-
return btd_device_ref(device);
}

--
1.7.9.5


2012-11-30 14:47:06

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 12/12] event: Store long term key infos in device info file

---
src/event.c | 89 ++++++++++++++++++++++++++++++-----------------------------
1 file changed, 46 insertions(+), 43 deletions(-)

diff --git a/src/event.c b/src/event.c
index 5e83c09..61fa0f4 100644
--- a/src/event.c
+++ b/src/event.c
@@ -304,54 +304,59 @@ void btd_event_remote_name(const bdaddr_t *local, bdaddr_t *peer,
device_set_name(device, name);
}

-static char *buf2str(uint8_t *data, int datalen)
+static void store_longtermkey(bdaddr_t *local, bdaddr_t *peer,
+ uint8_t bdaddr_type, unsigned char *key,
+ uint8_t master, uint8_t authenticated,
+ uint8_t enc_size, uint16_t ediv,
+ uint8_t rand[8])
{
- char *buf;
+ char adapter_addr[18];
+ char device_addr[18];
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ char key_str[35];
+ char rand_str[19];
+ char *str;
int i;
+ gsize length = 0;

- buf = g_try_new0(char, (datalen * 2) + 1);
- if (buf == NULL)
- return NULL;
-
- for (i = 0; i < datalen; i++)
- sprintf(buf + (i * 2), "%2.2x", data[i]);
+ ba2str(local, adapter_addr);
+ ba2str(peer, device_addr);

- return buf;
-}
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
+ device_addr);
+ filename[PATH_MAX] = '\0';

-static int store_longtermkey(bdaddr_t *local, bdaddr_t *peer,
- uint8_t bdaddr_type, unsigned char *key,
- uint8_t master, uint8_t authenticated,
- uint8_t enc_size, uint16_t ediv, uint8_t rand[8])
-{
- GString *newkey;
- char *val, *str;
- int err;
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);

- val = buf2str(key, 16);
- if (val == NULL)
- return -ENOMEM;
+ key_str[0] = '0';
+ key_str[1] = 'x';
+ for (i = 0; i < 16; i++)
+ sprintf(key_str + 2 + (i * 2), "%2.2X", key[i]);

- newkey = g_string_new(val);
- g_free(val);
+ g_key_file_set_string(key_file, "LongTermKey", "Key", key_str);

- g_string_append_printf(newkey, " %d %d %d %d ", authenticated, master,
- enc_size, ediv);
+ g_key_file_set_integer(key_file, "LongTermKey", "Authenticated",
+ authenticated);
+ g_key_file_set_integer(key_file, "LongTermKey", "Master", master);
+ g_key_file_set_integer(key_file, "LongTermKey", "EncSize", enc_size);
+ g_key_file_set_integer(key_file, "LongTermKey", "EDiv", ediv);

- str = buf2str(rand, 8);
- if (str == NULL) {
- g_string_free(newkey, TRUE);
- return -ENOMEM;
- }
+ rand_str[0] = '0';
+ rand_str[1] = 'x';
+ for (i = 0; i < 8; i++)
+ sprintf(rand_str + 2 + (i * 2), "%2.2X", rand[i]);

- newkey = g_string_append(newkey, str);
- g_free(str);
+ g_key_file_set_string(key_file, "LongTermKey", "Rand", rand_str);

- err = write_longtermkeys(local, peer, bdaddr_type, newkey->str);
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

- g_string_free(newkey, TRUE);
+ str = g_key_file_to_data(key_file, &length, NULL);
+ g_file_set_contents(filename, str, length, NULL);
+ g_free(str);

- return err;
+ g_key_file_free(key_file);
}

static void store_link_key(struct btd_adapter *adapter,
@@ -425,21 +430,19 @@ int btd_event_ltk_notify(bdaddr_t *local, bdaddr_t *peer, uint8_t bdaddr_type,
{
struct btd_adapter *adapter;
struct btd_device *device;
- int ret;

if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
return -ENODEV;

- ret = store_longtermkey(local, peer, bdaddr_type, key, master,
+ store_longtermkey(local, peer, bdaddr_type, key, master,
authenticated, enc_size, ediv, rand);
- if (ret == 0) {
- device_set_bonded(device, TRUE);

- if (device_is_temporary(device))
- device_set_temporary(device, FALSE);
- }
+ device_set_bonded(device, TRUE);

- return ret;
+ if (device_is_temporary(device))
+ device_set_temporary(device, FALSE);
+
+ return 0;
}

void btd_event_conn_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t bdaddr_type,
--
1.7.9.5


2012-11-30 14:47:04

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 10/12] adapter: Convert storage longtermkeys file

---
src/adapter.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 17f478c..ff9d2e7 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2655,6 +2655,46 @@ static void convert_linkkey_entry(GKeyFile *key_file, void *value)
g_key_file_set_integer(key_file, "LinkKey", "PINLength", val);
}

+static void convert_ltk_entry(GKeyFile *key_file, void *value)
+{
+ char *auth_str, *rand_str, *str;
+ int i, ret;
+ unsigned char auth, master, enc_size;
+ unsigned short ediv;
+
+ auth_str = strchr(value, ' ');
+ if (!auth_str)
+ return;
+
+ *(auth_str++) = 0;
+
+ for (i = 0, rand_str = auth_str; i < 4; i++) {
+ rand_str = strchr(rand_str, ' ');
+ if (!rand_str || rand_str[1] == '\0')
+ return;
+
+ rand_str++;
+ }
+
+ ret = sscanf(auth_str, " %hhd %hhd %hhd %hd", &auth, &master,
+ &enc_size, &ediv);
+ if (ret < 4)
+ return;
+
+ str = g_strconcat("0x", value, NULL);
+ g_key_file_set_string(key_file, "LongTermKey", "Key", str);
+ g_free(str);
+
+ g_key_file_set_integer(key_file, "LongTermKey", "Authenticated", auth);
+ g_key_file_set_integer(key_file, "LongTermKey", "Master", master);
+ g_key_file_set_integer(key_file, "LongTermKey", "EncSize", enc_size);
+ g_key_file_set_integer(key_file, "LongTermKey", "EDiv", ediv);
+
+ str = g_strconcat("0x", rand_str, NULL);
+ g_key_file_set_string(key_file, "LongTermKey", "Rand", str);
+ g_free(str);
+}
+
static void convert_entry(char *key, char *value, void *user_data)
{
struct device_converter *converter = user_data;
@@ -2766,6 +2806,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
/* Convert linkkeys */
convert_file("linkkeys", address, convert_linkkey_entry, TRUE);

+ /* Convert longtermkeys */
+ convert_file("longtermkeys", address, convert_ltk_entry, TRUE);
+
/* Convert classes */
convert_file("classes", address, convert_classes_entry, FALSE);

--
1.7.9.5


2012-11-30 14:47:03

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 09/12] event: Store link key infos in device info file

---
src/event.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 47 insertions(+), 12 deletions(-)

diff --git a/src/event.c b/src/event.c
index 7fc8f02..5e83c09 100644
--- a/src/event.c
+++ b/src/event.c
@@ -354,33 +354,68 @@ static int store_longtermkey(bdaddr_t *local, bdaddr_t *peer,
return err;
}

+static void store_link_key(struct btd_adapter *adapter,
+ struct btd_device *device, uint8_t *key,
+ uint8_t type, uint8_t pin_length)
+{
+ char adapter_addr[18];
+ char device_addr[18];
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ char key_str[35];
+ char *str;
+ int i;
+ gsize length = 0;
+
+ ba2str(adapter_get_address(adapter), adapter_addr);
+ ba2str(device_get_address(device), device_addr);
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
+ device_addr);
+ filename[PATH_MAX] = '\0';
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+ key_str[0] = '0';
+ key_str[1] = 'x';
+ for (i = 0; i < 16; i++)
+ sprintf(key_str + 2 + (i * 2), "%2.2X", key[i]);
+
+ g_key_file_set_string(key_file, "LinkKey", "Key", key_str);
+
+ g_key_file_set_integer(key_file, "LinkKey", "Type", type);
+ g_key_file_set_integer(key_file, "LinkKey", "PINLength", pin_length);
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ str = g_key_file_to_data(key_file, &length, NULL);
+ g_file_set_contents(filename, str, length, NULL);
+ g_free(str);
+
+ g_key_file_free(key_file);
+}
+
int btd_event_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
uint8_t *key, uint8_t key_type,
uint8_t pin_length)
{
struct btd_adapter *adapter;
struct btd_device *device;
- uint8_t peer_type;
- int ret;

if (!get_adapter_and_device(local, peer, &adapter, &device, TRUE))
return -ENODEV;

DBG("storing link key of type 0x%02x", key_type);

- peer_type = device_get_addr_type(device);
+ store_link_key(adapter, device, key, key_type, pin_length);

- ret = write_link_key(local, peer, peer_type, key, key_type,
- pin_length);
+ device_set_bonded(device, TRUE);

- if (ret == 0) {
- device_set_bonded(device, TRUE);
-
- if (device_is_temporary(device))
- device_set_temporary(device, FALSE);
- }
+ if (device_is_temporary(device))
+ device_set_temporary(device, FALSE);

- return ret;
+ return 0;
}

int btd_event_ltk_notify(bdaddr_t *local, bdaddr_t *peer, uint8_t bdaddr_type,
--
1.7.9.5


2012-11-30 14:47:01

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 07/12] adapter: Convert storage linkkeys file

---
src/adapter.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index f3b1c5d..bf20580 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2639,6 +2639,34 @@ static void convert_did_entry(GKeyFile *key_file, void *value)
g_key_file_set_integer(key_file, "DeviceID", "Version", val);
}

+static void convert_linkkey_entry(GKeyFile *key_file, void *value)
+{
+ char *type_str, *length_str, *str;
+ gint val;
+
+ type_str = strchr(value, ' ');
+ if (!type_str)
+ return;
+
+ *(type_str++) = 0;
+
+ length_str = strchr(type_str, ' ');
+ if (!length_str)
+ return;
+
+ *(length_str++) = 0;
+
+ str = g_strconcat("0x", value, NULL);
+ g_key_file_set_string(key_file, "LinkKey", "Key", str);
+ g_free(str);
+
+ val = strtol(type_str, NULL, 16);
+ g_key_file_set_integer(key_file, "LinkKey", "Type", val);
+
+ val = strtol(length_str, NULL, 16);
+ g_key_file_set_integer(key_file, "LinkKey", "PINLength", val);
+}
+
static void convert_entry(char *key, char *value, void *user_data)
{
struct device_converter *converter = user_data;
@@ -2747,6 +2775,9 @@ static void convert_device_storage(struct btd_adapter *adapter)
/* Convert blocked */
convert_file("blocked", address, convert_blocked_entry, TRUE);

+ /* Convert linkkeys */
+ convert_file("linkkeys", address, convert_linkkey_entry, TRUE);
+
/* Convert classes */
convert_file("classes", address, convert_classes_entry, FALSE);

--
1.7.9.5


2012-11-30 14:47:02

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 08/12] adapter: Upload link keys from new storage

Remove read_link_key() from device_create, this moves to load_devices.
---
src/adapter.c | 110 +++++++++++++++++++++++++--------------------------------
src/device.c | 6 ----
2 files changed, 49 insertions(+), 67 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index bf20580..17f478c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -1766,31 +1766,26 @@ static int str2buf(const char *str, uint8_t *buf, size_t blen)
return 0;
}

-static struct link_key_info *get_key_info(const char *addr, const char *value)
+static struct link_key_info *get_key_info(GKeyFile *key_file, const char *peer)
{
- struct link_key_info *info;
- char tmp[3];
- long int l;
+ struct link_key_info *info = NULL;
+ char *str;

- if (strlen(value) < 36) {
- error("Unexpectedly short (%zu) link key line", strlen(value));
- return NULL;
- }
+ str = g_key_file_get_string(key_file, "LinkKey", "Key", NULL);
+ if (!str || strlen(str) != 34)
+ goto failed;

info = g_new0(struct link_key_info, 1);

- str2ba(addr, &info->bdaddr);
-
- str2buf(value, info->key, sizeof(info->key));
+ str2ba(peer, &info->bdaddr);
+ str2buf(&str[2], info->key, sizeof(info->key));

- memcpy(tmp, value + 33, 2);
- info->type = (uint8_t) strtol(tmp, NULL, 10);
+ info->type = g_key_file_get_integer(key_file, "LinkKey", "Type", NULL);
+ info->pin_len = g_key_file_get_integer(key_file, "LinkKey", "PINLength",
+ NULL);

- memcpy(tmp, value + 35, 2);
- l = strtol(tmp, NULL, 10);
- if (l < 0)
- l = 0;
- info->pin_len = l;
+failed:
+ g_free(str);

return info;
}
@@ -1831,34 +1826,6 @@ static struct smp_ltk_info *get_ltk_info(const char *addr, uint8_t bdaddr_type,
return ltk;
}

-static void create_stored_device_from_linkkeys(char *key, char *value,
- void *user_data)
-{
- char address[18];
- uint8_t bdaddr_type;
- struct adapter_keys *keys = user_data;
- struct btd_adapter *adapter = keys->adapter;
- struct btd_device *device;
- struct link_key_info *info;
-
- if (sscanf(key, "%17s#%hhu", address, &bdaddr_type) < 2)
- bdaddr_type = BDADDR_BREDR;
-
- info = get_key_info(address, value);
- if (info)
- keys->keys = g_slist_append(keys->keys, info);
-
- if (g_slist_find_custom(adapter->devices, address,
- (GCompareFunc) device_address_cmp))
- return;
-
- device = device_create(adapter, address, bdaddr_type);
- if (device) {
- device_set_temporary(device, FALSE);
- adapter->devices = g_slist_append(adapter->devices, device);
- }
-}
-
static void create_stored_device_from_ltks(char *key, char *value,
void *user_data)
{
@@ -1994,18 +1961,6 @@ static void load_devices(struct btd_adapter *adapter)
textfile_foreach(filename, create_stored_device_from_primaries,
adapter);

- create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "linkkeys");
- textfile_foreach(filename, create_stored_device_from_linkkeys, &keys);
-
- err = mgmt_load_link_keys(adapter->dev_id, keys.keys,
- main_opts.debug_keys);
- if (err < 0)
- error("Unable to load link keys: %s (%d)",
- strerror(-err), -err);
-
- g_slist_free_full(keys.keys, g_free);
- keys.keys = NULL;
-
create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "longtermkeys");
textfile_foreach(filename, create_stored_device_from_ltks, &keys);

@@ -2027,13 +1982,32 @@ static void load_devices(struct btd_adapter *adapter)

while ((entry = readdir(dir)) != NULL) {
struct btd_device *device;
+ char filename[PATH_MAX + 1];
+ GKeyFile *key_file;
+ struct link_key_info *key_info;
+ GSList *l;

if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
continue;

- if (g_slist_find_custom(adapter->devices, entry->d_name,
- (GCompareFunc) device_address_cmp))
- continue;
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", srcaddr,
+ entry->d_name);
+
+ key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+ key_info = get_key_info(key_file, entry->d_name);
+ if (key_info)
+ keys.keys = g_slist_append(keys.keys, key_info);
+
+ g_key_file_free(key_file);
+
+ l = g_slist_find_custom(adapter->devices, entry->d_name,
+ (GCompareFunc) device_address_cmp);
+ if (l) {
+ device = l->data;
+ goto device_exist;
+ }

device = device_create(adapter, entry->d_name, BDADDR_BREDR);
if (!device)
@@ -2041,9 +2015,23 @@ static void load_devices(struct btd_adapter *adapter)

device_set_temporary(device, FALSE);
adapter->devices = g_slist_append(adapter->devices, device);
+
+device_exist:
+ if (key_info) {
+ device_set_paired(device, TRUE);
+ device_set_bonded(device, TRUE);
+ }
}

closedir(dir);
+
+ err = mgmt_load_link_keys(adapter->dev_id, keys.keys,
+ main_opts.debug_keys);
+ if (err < 0)
+ error("Unable to load link keys: %s (%d)",
+ strerror(-err), -err);
+
+ g_slist_free_full(keys.keys, g_free);
}

int btd_adapter_block_address(struct btd_adapter *adapter,
diff --git a/src/device.c b/src/device.c
index 1db8a48..bb5689b 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1904,12 +1904,6 @@ struct btd_device *device_create(struct btd_adapter *adapter,

load_info(device, srcaddr, address);

- if (read_link_key(src, &device->bdaddr, device->bdaddr_type, NULL,
- NULL) == 0) {
- device_set_paired(device, TRUE);
- device_set_bonded(device, TRUE);
- }
-
if (device_is_le(device) && has_longtermkeys(src, &device->bdaddr,
device->bdaddr_type)) {
device_set_paired(device, TRUE);
--
1.7.9.5


2012-11-30 14:46:59

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 05/12] adapter: Convert device type

Each time an entry is converted, check device technology and
update device info file
---
src/adapter.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index a976793..c5e856d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2530,6 +2530,44 @@ struct device_converter {
gboolean force;
};

+static void set_device_type(GKeyFile *key_file, char type)
+{
+ char *techno;
+ char *addr_type = NULL;
+ char *str;
+
+ switch (type) {
+ case BDADDR_BREDR:
+ techno = "BR/EDR";
+ break;
+ case BDADDR_LE_PUBLIC:
+ techno = "LE";
+ addr_type = "public";
+ break;
+ case BDADDR_LE_RANDOM:
+ techno = "LE";
+ addr_type = "static";
+ break;
+ default:
+ return;
+ }
+
+ str = g_key_file_get_string(key_file, "General",
+ "SupportedTechnologies", NULL);
+ if (!str)
+ g_key_file_set_string(key_file, "General",
+ "SupportedTechnologies", techno);
+ else if (!strstr(str, techno))
+ g_key_file_set_string(key_file, "General",
+ "SupportedTechnologies", "BR/EDR;LE");
+
+ g_free(str);
+
+ if (addr_type)
+ g_key_file_set_string(key_file, "General", "AddressType",
+ addr_type);
+}
+
static void convert_aliases_entry(GKeyFile *key_file, void *value)
{
g_key_file_set_string(key_file, "General", "Alias", value);
@@ -2592,13 +2630,16 @@ static void convert_did_entry(GKeyFile *key_file, void *value)
static void convert_entry(char *key, char *value, void *user_data)
{
struct device_converter *converter = user_data;
+ char device_type = -1;
char filename[PATH_MAX + 1];
GKeyFile *key_file;
char *data;
gsize length = 0;

- if (key[17] == '#')
+ if (key[17] == '#') {
key[17] = '\0';
+ device_type = key[18] - '0';
+ }

if (bachk(key) != 0)
return;
@@ -2622,6 +2663,10 @@ static void convert_entry(char *key, char *value, void *user_data)

key_file = g_key_file_new();
g_key_file_load_from_file(key_file, filename, 0, NULL);
+
+ if (device_type >= 0)
+ set_device_type(key_file, device_type);
+
converter->cb(key_file, value);

data = g_key_file_to_data(key_file, &length, NULL);
--
1.7.9.5


2012-11-30 14:47:00

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 06/12] adapter: Load devices from new storage architecture

Parse storage directory and create devices from device sub-directories.

Remove create device from 'blocked' file, this is already converted.
---
src/adapter.c | 50 +++++++++++++++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index c5e856d..f3b1c5d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -35,6 +35,7 @@
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/stat.h>
+#include <dirent.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
@@ -1893,23 +1894,6 @@ static void create_stored_device_from_ltks(char *key, char *value,
}
}

-static void create_stored_device_from_blocked(char *key, char *value,
- void *user_data)
-{
- struct btd_adapter *adapter = user_data;
- struct btd_device *device;
-
- if (g_slist_find_custom(adapter->devices,
- key, (GCompareFunc) device_address_cmp))
- return;
-
- device = device_create(adapter, key, BDADDR_BREDR);
- if (device) {
- device_set_temporary(device, FALSE);
- adapter->devices = g_slist_append(adapter->devices, device);
- }
-}
-
static GSList *string_to_primary_list(char *str)
{
GSList *l = NULL;
@@ -1997,6 +1981,8 @@ static void load_devices(struct btd_adapter *adapter)
char srcaddr[18];
struct adapter_keys keys = { adapter, NULL };
int err;
+ DIR *dir;
+ struct dirent *entry;

ba2str(&adapter->bdaddr, srcaddr);

@@ -2030,8 +2016,34 @@ static void load_devices(struct btd_adapter *adapter)
g_slist_free_full(keys.keys, smp_key_free);
keys.keys = NULL;

- create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "blocked");
- textfile_foreach(filename, create_stored_device_from_blocked, adapter);
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s", srcaddr);
+ filename[PATH_MAX] = '\0';
+
+ dir = opendir(filename);
+ if (!dir) {
+ error("Unable to open adapter storage directory: %s", filename);
+ return;
+ }
+
+ while ((entry = readdir(dir)) != NULL) {
+ struct btd_device *device;
+
+ if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
+ continue;
+
+ if (g_slist_find_custom(adapter->devices, entry->d_name,
+ (GCompareFunc) device_address_cmp))
+ continue;
+
+ device = device_create(adapter, entry->d_name, BDADDR_BREDR);
+ if (!device)
+ continue;
+
+ device_set_temporary(device, FALSE);
+ adapter->devices = g_slist_append(adapter->devices, device);
+ }
+
+ closedir(dir);
}

int btd_adapter_block_address(struct btd_adapter *adapter,
--
1.7.9.5


2012-11-30 14:46:57

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 03/12] adapter: Fix device storage creation

Create device storage directory and file only if there
is data to write.
---
src/adapter.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index f134dfe..8e3251b 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2604,14 +2604,17 @@ static void convert_entry(char *key, char *value, void *user_data)
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
converter->address, key);
filename[PATH_MAX] = '\0';
- create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

key_file = g_key_file_new();
g_key_file_load_from_file(key_file, filename, 0, NULL);
converter->cb(key_file, value);

data = g_key_file_to_data(key_file, &length, NULL);
- g_file_set_contents(filename, data, length, NULL);
+ if (length > 0) {
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ g_file_set_contents(filename, data, length, NULL);
+ }
+
g_free(data);

g_key_file_free(key_file);
--
1.7.9.5


2012-11-30 14:46:58

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 04/12] adapter: Add force dir creation to convert_file()

Some device information, like class or device id, should only be
converted if directory for this device has already been created
during previous conversion (from aliases, trusts, blocked, ...
files).
---
src/adapter.c | 33 +++++++++++++++++++++++++--------
1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 8e3251b..a976793 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -34,6 +34,7 @@
#include <stdbool.h>
#include <sys/ioctl.h>
#include <sys/file.h>
+#include <sys/stat.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
@@ -2526,6 +2527,7 @@ static void convert_names_entry(char *key, char *value, void *user_data)
struct device_converter {
char *address;
void (*cb)(GKeyFile *key_file, void *value);
+ gboolean force;
};

static void convert_aliases_entry(GKeyFile *key_file, void *value)
@@ -2601,6 +2603,19 @@ static void convert_entry(char *key, char *value, void *user_data)
if (bachk(key) != 0)
return;

+ if (converter->force == FALSE) {
+ struct stat st;
+ int err;
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s",
+ converter->address, key);
+ filename[PATH_MAX] = '\0';
+
+ err = stat(filename, &st);
+ if (err || !S_ISDIR(st.st_mode))
+ return;
+ }
+
snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
converter->address, key);
filename[PATH_MAX] = '\0';
@@ -2621,7 +2636,8 @@ static void convert_entry(char *key, char *value, void *user_data)
}

static void convert_file(char *file, char *address,
- void (*cb)(GKeyFile *key_file, void *value))
+ void (*cb)(GKeyFile *key_file, void *value),
+ gboolean force)
{
char filename[PATH_MAX + 1];
struct device_converter converter;
@@ -2636,6 +2652,7 @@ static void convert_file(char *file, char *address,
} else {
converter.address = address;
converter.cb = cb;
+ converter.force = force;

textfile_foreach(filename, convert_entry, &converter);
textfile_put(filename, "converted", "yes");
@@ -2665,19 +2682,19 @@ static void convert_device_storage(struct btd_adapter *adapter)
free(str);

/* Convert aliases */
- convert_file("aliases", address, convert_aliases_entry);
+ convert_file("aliases", address, convert_aliases_entry, TRUE);

/* Convert trusts */
- convert_file("trusts", address, convert_trusts_entry);
-
- /* Convert classes */
- convert_file("classes", address, convert_classes_entry);
+ convert_file("trusts", address, convert_trusts_entry, TRUE);

/* Convert blocked */
- convert_file("blocked", address, convert_blocked_entry);
+ convert_file("blocked", address, convert_blocked_entry, TRUE);
+
+ /* Convert classes */
+ convert_file("classes", address, convert_classes_entry, FALSE);

/* Convert device ids */
- convert_file("did", address, convert_did_entry);
+ convert_file("did", address, convert_did_entry, FALSE);
}

static void convert_config(struct btd_adapter *adapter, const char *filename,
--
1.7.9.5


2012-11-30 14:46:56

by Frederic Danis

[permalink] [raw]
Subject: [RFC V3 02/12] device: Load device info before updating info file

Data in device info file should not be lost during save
even if they are not in device structure (like link key
and long term key).
---
src/device.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/device.c b/src/device.c
index a99ca34..1db8a48 100644
--- a/src/device.c
+++ b/src/device.c
@@ -217,17 +217,28 @@ static gboolean store_device_info_cb(gpointer user_data)

device->store_id = 0;

+ ba2str(adapter_get_address(device->adapter), adapter_addr);
+ ba2str(&device->bdaddr, device_addr);
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
+ device_addr);
+ filename[PATH_MAX] = '\0';
+
key_file = g_key_file_new();
+ g_key_file_load_from_file(key_file, filename, 0, NULL);

g_key_file_set_string(key_file, "General", "Name", device->name);

if (device->alias != NULL)
g_key_file_set_string(key_file, "General", "Alias",
device->alias);
+ else
+ g_key_file_remove_key(key_file, "General", "Alias", NULL);

if (device->class) {
sprintf(class, "0x%6.6x", device->class);
g_key_file_set_string(key_file, "General", "Class", class);
+ } else {
+ g_key_file_remove_key(key_file, "General", "Class", NULL);
}

g_key_file_set_boolean(key_file, "General", "Trusted",
@@ -245,14 +256,10 @@ static gboolean store_device_info_cb(gpointer user_data)
device->product);
g_key_file_set_integer(key_file, "DeviceID", "Version",
device->version);
+ } else {
+ g_key_file_remove_group(key_file, "DeviceID", NULL);
}

- ba2str(adapter_get_address(device->adapter), adapter_addr);
- ba2str(&device->bdaddr, device_addr);
- snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info", adapter_addr,
- device_addr);
- filename[PATH_MAX] = '\0';
-
create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

str = g_key_file_to_data(key_file, &length, NULL);
--
1.7.9.5


2012-12-04 08:18:40

by Johan Hedberg

[permalink] [raw]
Subject: Re: [RFC V3 01/12] doc: Update settings-storage.txt

Hi Frederic,

On Fri, Nov 30, 2012, Fr?d?ric Danis wrote:
> Add missing Master key to LongTermKey group
> ---
> doc/settings-storage.txt | 2 ++
> 1 file changed, 2 insertions(+)

All patches in this set have been applied. Thanks.

Johan