diff options
Diffstat (limited to 'hcid')
-rw-r--r-- | hcid/dbus-device.c | 31 | ||||
-rw-r--r-- | hcid/dbus.c | 6 | ||||
-rw-r--r-- | hcid/hcid.h | 15 | ||||
-rw-r--r-- | hcid/security.c | 33 | ||||
-rw-r--r-- | hcid/storage.c | 36 |
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; |