summaryrefslogtreecommitdiffstats
path: root/hcid
diff options
context:
space:
mode:
Diffstat (limited to 'hcid')
-rw-r--r--hcid/dbus-device.c31
-rw-r--r--hcid/dbus.c6
-rw-r--r--hcid/hcid.h15
-rw-r--r--hcid/security.c33
-rw-r--r--hcid/storage.c36
5 files changed, 97 insertions, 24 deletions
diff --git a/hcid/dbus-device.c b/hcid/dbus-device.c
index 3935df12..97bb590f 100644
--- a/hcid/dbus-device.c
+++ b/hcid/dbus-device.c
@@ -1021,8 +1021,35 @@ failed:
static DBusMessage *handle_dev_pin_code_length_req(DBusMessage *msg, void *data)
{
- /*FIXME: */
- return bluez_new_failure_msg(msg, BLUEZ_EDBUS_NOT_IMPLEMENTED);
+ struct hci_dbus_data *dbus_data = data;
+ DBusMessageIter iter;
+ DBusMessage *reply;
+ bdaddr_t local, peer;
+ char addr[18], *addr_ptr;
+ uint8_t length;
+ int len;
+
+ get_device_address(dbus_data->dev_id, addr, sizeof(addr));
+
+ str2ba(addr, &local);
+
+ dbus_message_iter_init(msg, &iter);
+ dbus_message_iter_get_basic(&iter, &addr_ptr);
+
+ str2ba(addr_ptr, &peer);
+
+ len = read_pin_length(&local, &peer);
+ if (len < 0)
+ return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | -len);
+
+ reply = dbus_message_new_method_return(msg);
+
+ length = len;
+
+ dbus_message_append_args(reply, DBUS_TYPE_BYTE, &length,
+ DBUS_TYPE_INVALID);
+
+ return reply;
}
static DBusMessage *handle_dev_encryption_key_size_req(DBusMessage *msg, void *data)
diff --git a/hcid/dbus.c b/hcid/dbus.c
index be348b2c..9b9ab270 100644
--- a/hcid/dbus.c
+++ b/hcid/dbus.c
@@ -64,6 +64,7 @@ static volatile sig_atomic_t __timeout_active = 0;
struct pin_request {
int dev;
+ bdaddr_t sba;
bdaddr_t bda;
};
@@ -193,6 +194,8 @@ static void reply_handler_function(DBusPendingCall *call, void *user_data)
dbus_message_iter_get_basic(&iter, &pin);
len = strlen(pin);
+ set_pin_length(&req->sba, len);
+
memset(&pr, 0, sizeof(pr));
bacpy(&pr.bdaddr, &req->bda);
memcpy(pr.pin_code, pin, len);
@@ -399,7 +402,7 @@ failed:
return ret;
}
-void hcid_dbus_request_pin(int dev, struct hci_conn_info *ci)
+void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
{
DBusMessage *message = NULL;
DBusPendingCall *pending = NULL;
@@ -421,6 +424,7 @@ void hcid_dbus_request_pin(int dev, struct hci_conn_info *ci)
req = malloc(sizeof(*req));
req->dev = dev;
+ bacpy(&req->sba, sba);
bacpy(&req->bda, &ci->bdaddr);
dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &out,
diff --git a/hcid/hcid.h b/hcid/hcid.h
index 87afaaa2..ff1f2f5a 100644
--- a/hcid/hcid.h
+++ b/hcid/hcid.h
@@ -72,14 +72,6 @@ struct device_list {
struct device_opts opts;
};
-struct link_key {
- bdaddr_t sba;
- bdaddr_t dba;
- uint8_t key[16];
- uint8_t type;
- time_t time;
-};
-
struct hcid_opts {
char *host_name;
int auto_init;
@@ -115,6 +107,8 @@ void start_security_manager(int hdev);
void stop_security_manager(int hdev);
void toggle_pairing(int enable);
+void set_pin_length(bdaddr_t *sba, int length);
+
#ifdef ENABLE_DBUS
gboolean hcid_dbus_init(void);
void hcid_dbus_exit(void);
@@ -122,7 +116,7 @@ gboolean hcid_dbus_register_device(uint16_t id);
gboolean hcid_dbus_unregister_device(uint16_t id);
gboolean hcid_dbus_dev_up(uint16_t id);
gboolean hcid_dbus_dev_down(uint16_t id);
-void hcid_dbus_request_pin(int dev, struct hci_conn_info *ci);
+void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci);
void hcid_dbus_inquiry_start(bdaddr_t *local);
void hcid_dbus_inquiry_complete(bdaddr_t *local);
@@ -168,8 +162,9 @@ int write_version_info(bdaddr_t *local, bdaddr_t *peer, uint16_t manufacturer, u
int write_features_info(bdaddr_t *local, bdaddr_t *peer, unsigned char *features);
int write_lastseen_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm);
int write_lastused_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm);
-int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, int type);
+int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, int type, int length);
int read_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key);
+int read_pin_length(bdaddr_t *local, bdaddr_t *peer);
int read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin);
static inline int find_conn(int dd, int dev_id, long arg)
diff --git a/hcid/security.c b/hcid/security.c
index ba00fb80..02cc8ed8 100644
--- a/hcid/security.c
+++ b/hcid/security.c
@@ -54,6 +54,7 @@
struct g_io_info {
GIOChannel *channel;
int watch_id;
+ int pin_length;
};
static struct g_io_info io_data[HCI_MAX_DEV];
@@ -153,19 +154,18 @@ static void link_key_notify(int dev, bdaddr_t *sba, void *ptr)
{
evt_link_key_notify *evt = ptr;
bdaddr_t *dba = &evt->bdaddr;
- struct link_key key;
char sa[18], da[18];
+ int dev_id;
ba2str(sba, sa); ba2str(dba, da);
syslog(LOG_INFO, "link_key_notify (sba=%s, dba=%s)", sa, da);
- memcpy(key.key, evt->link_key, 16);
- bacpy(&key.sba, sba);
- bacpy(&key.dba, dba);
- key.type = evt->key_type;
- key.time = time(0);
+ dev_id = hci_devid(sa);
- write_link_key(sba, dba, evt->link_key, evt->key_type);
+ write_link_key(sba, dba, evt->link_key, evt->key_type,
+ io_data[dev_id].pin_length);
+
+ io_data[dev_id].pin_length = -1;
}
static void return_link_keys(int dev, bdaddr_t *sba, void *ptr)
@@ -192,6 +192,17 @@ static void return_link_keys(int dev, bdaddr_t *sba, void *ptr)
/* PIN code handling */
+void set_pin_length(bdaddr_t *sba, int length)
+{
+ char addr[18];
+ int dev_id;
+
+ ba2str(sba, addr);
+ dev_id = hci_devid(addr);
+
+ io_data[dev_id].pin_length = length;
+}
+
/*
PIN helper is an external app that asks user for a PIN. It can
implement its own PIN code generation policy and methods like
@@ -285,6 +296,8 @@ static void call_pin_helper(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
pin += 4;
len = strlen(pin);
+ set_pin_length(sba, len);
+
memset(&pr, 0, sizeof(pr));
bacpy(&pr.bdaddr, &ci->bdaddr);
memcpy(pr.pin_code, pin, len);
@@ -306,7 +319,7 @@ static void request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)
{
#ifdef ENABLE_DBUS
if (hcid.dbus_pin_helper) {
- hcid_dbus_request_pin(dev, ci);
+ hcid_dbus_request_pin(dev, sba, ci);
return;
}
#endif
@@ -357,6 +370,7 @@ static void pin_code_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
if (hcid.security == HCID_SEC_AUTO) {
if (!ci->out) {
/* Incomming connection */
+ set_pin_length(sba, hcid.pin_len);
memcpy(pr.pin_code, hcid.pin_code, hcid.pin_len);
pr.pin_len = hcid.pin_len;
hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY,
@@ -364,6 +378,7 @@ static void pin_code_request(int dev, bdaddr_t *sba, bdaddr_t *dba)
} else {
/* Outgoing connection */
if (pinlen > 0) {
+ set_pin_length(sba, pinlen);
memcpy(pr.pin_code, pin, pinlen);
pr.pin_len = pinlen;
hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY,
@@ -769,6 +784,7 @@ void start_security_manager(int hdev)
io_security_event, (void *) di);
io_data[hdev].channel = chan;
+ io_data[hdev].pin_length = -1;
if (hci_test_bit(HCI_RAW, &di->flags))
return;
@@ -796,6 +812,7 @@ void stop_security_manager(int hdev)
g_io_remove_watch(io_data[hdev].watch_id);
io_data[hdev].watch_id = -1;
io_data[hdev].channel = NULL;
+ io_data[hdev].pin_length = -1;
}
void init_security_data(void)
diff --git a/hcid/storage.c b/hcid/storage.c
index a553ae96..3040264d 100644
--- a/hcid/storage.c
+++ b/hcid/storage.c
@@ -153,15 +153,15 @@ int write_lastused_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm)
return textfile_put(filename, addr, str);
}
-int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, int type)
+int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, int type, int length)
{
- char filename[PATH_MAX + 1], addr[18], str[35];
+ char filename[PATH_MAX + 1], addr[18], str[38];
int i;
memset(str, 0, sizeof(str));
for (i = 0; i < 16; i++)
sprintf(str + (i * 2), "%2.2X", key[i]);
- sprintf(str + 32, " %d", type);
+ sprintf(str + 32, " %d %d", type, length);
ba2str(local, addr);
snprintf(filename, PATH_MAX, "%s/%s/linkkeys", STORAGEDIR, addr);
@@ -169,6 +169,13 @@ int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, int type
create_file(filename, S_IRUSR | S_IWUSR);
ba2str(peer, addr);
+
+ if (length < 0) {
+ char *tmp = textfile_get(filename, addr);
+ if (tmp && strlen(tmp) > 34)
+ memcpy(str + 34, tmp + 34, 3);
+ }
+
return textfile_put(filename, addr, str);
}
@@ -196,6 +203,29 @@ int read_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key)
return 0;
}
+int read_pin_length(bdaddr_t *local, bdaddr_t *peer)
+{
+ char filename[PATH_MAX + 1], addr[18], *str;
+ int len;
+
+ ba2str(local, addr);
+ snprintf(filename, PATH_MAX, "%s/%s/linkkeys", STORAGEDIR, addr);
+
+ ba2str(peer, addr);
+ str = textfile_get(filename, addr);
+ if (!str)
+ return -ENOENT;
+
+ if (strlen(str) < 36)
+ return -ENOENT;
+
+ len = atoi(str + 35);
+
+ free(str);
+
+ return len;
+}
+
int read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin)
{
char filename[PATH_MAX + 1], addr[18], *str;