--- Begin Message ---
Package: bluez
Version: 5.23-2+b1
Certain keyboards (including the Logitech Bluetooth Keyboard K760;
Logitech Bluetooth Keyboard K810; and the HP Bluetooth Keyboard K4000)
require a technology called "Simple Secure Pairing" which is broken in
the version of bluez currently available in Jessie. For further details
of the problem, see Launchpad bug #1035431.
The attached patch to the package fixes the problem. This patch has
been included in Ubuntu's trusty-updates repository and I would like to
suggest that it be proposed as an update to Debian Jessie.
I believe that the fix depends on a corresponding patch to
gnome-bluetooth; I am filing a bug against that package too.
--
Sean Whitton
Description: ssp parameter fix
* Add ssp parameter fix, add a missing parameter entered in agent dbus API.
Fixed Logitech Bluetooth Keyboard K760, Logitech Bluetooth Keyboard K810,
HP Bluetooth Keyboard K4000 secure simple pairing failed issue.
(LP: #1035431, #1291756)
backported bluez5 commits:
upstream commit 546fee067daedc2b7860481aeaebd1771d192dfb
mgmt: Implement support for Passkey Notify event
upstream commit 97b930870dcd016b9cdd612e47b832736b4d0c5d
core: Refactor authentication handling
upstream commit e86fe268c77017731b792296eea16206918f1852
agent: Add missing parameter to DisplayPasskey
upstream commit 6a394b2c7f19b53b630bef2e865f9bc289d4b75c
agent-api: DisplayPasskey: D-Bus doesn't have a uint8 type
Author: Jian-Ding Chen (timchen119) <[email protected]>
Bug-Ubuntu: https://bugs.launchpad.net/bugs/1035431
Bug-Ubuntu: https://bugs.launchpad.net/bugs/1291756
Last-Update: 2014-05-02
--- bluez-4.101.orig/doc/agent-api.txt
+++ bluez-4.101/doc/agent-api.txt
@@ -42,7 +42,8 @@ Methods void Release()
Possible errors: org.bluez.Error.Rejected
org.bluez.Error.Canceled
- void DisplayPasskey(object device, uint32 passkey, uint8 entered)
+ void DisplayPasskey(object device, uint32 passkey,
+ uint16 entered)
This method gets called when the service daemon
needs to display a passkey for an authentication.
--- bluez-4.101.orig/lib/hci.h
+++ bluez-4.101/lib/hci.h
@@ -2075,8 +2075,9 @@ typedef struct {
typedef struct {
bdaddr_t bdaddr;
uint32_t passkey;
+ uint8_t entered;
} __attribute__ ((packed)) evt_user_passkey_notify;
-#define EVT_USER_PASSKEY_NOTIFY_SIZE 10
+#define EVT_USER_PASSKEY_NOTIFY_SIZE 11
#define EVT_KEYPRESS_NOTIFY 0x3C
typedef struct {
--- bluez-4.101.orig/lib/mgmt.h
+++ bluez-4.101/lib/mgmt.h
@@ -437,6 +437,13 @@ struct mgmt_ev_device_unpaired {
struct mgmt_addr_info addr;
} __packed;
+#define MGMT_EV_PASSKEY_NOTIFY 0x0017
+struct mgmt_ev_passkey_notify {
+ struct mgmt_addr_info addr;
+ uint32_t passkey;
+ uint8_t entered;
+} __packed;
+
static const char *mgmt_op[] = {
"<0x0000>",
"Read Version",
--- bluez-4.101.orig/plugins/hciops.c
+++ bluez-4.101/plugins/hciops.c
@@ -1340,7 +1340,7 @@ static void user_passkey_notify(int inde
DBG("hci%d", index);
btd_event_user_notify(&dev->bdaddr, &req->bdaddr,
- btohl(req->passkey));
+ btohl(req->passkey), req->entered);
}
static gint oob_bdaddr_cmp(gconstpointer a, gconstpointer b)
--- bluez-4.101.orig/plugins/mgmtops.c
+++ bluez-4.101/plugins/mgmtops.c
@@ -749,6 +749,40 @@ static void mgmt_passkey_request(int sk,
}
}
+static void mgmt_passkey_notify(int sk, uint16_t index, void *buf, size_t len)
+{
+ struct mgmt_ev_passkey_notify *ev = buf;
+ struct controller_info *info;
+ uint32_t passkey;
+ char addr[18];
+ int err;
+
+ if (len < sizeof(*ev)) {
+ error("Too small passkey_notify event");
+ return;
+ }
+
+ ba2str(&ev->addr.bdaddr, addr);
+
+ DBG("hci%u %s", index, addr);
+
+ if (index > max_index) {
+ error("Unexpected index %u in passkey_notify event", index);
+ return;
+ }
+
+ info = &controllers[index];
+
+ passkey = bt_get_le32(&ev->passkey);
+
+ DBG("passkey %06u entered %u", passkey, ev->entered);
+
+ err = btd_event_user_notify(&info->bdaddr, &ev->addr.bdaddr,
+ passkey, ev->entered);
+ if (err < 0)
+ error("btd_event_user_notify: %s", strerror(-err));
+}
+
struct confirm_data {
int index;
bdaddr_t bdaddr;
@@ -1860,6 +1894,9 @@ static gboolean mgmt_event(GIOChannel *i
case MGMT_EV_USER_PASSKEY_REQUEST:
mgmt_passkey_request(sk, index, buf + MGMT_HDR_SIZE, len);
break;
+ case MGMT_EV_PASSKEY_NOTIFY:
+ mgmt_passkey_notify(sk, index, buf + MGMT_HDR_SIZE, len);
+ break;
case MGMT_EV_NEW_LONG_TERM_KEY:
mgmt_new_ltk(sk, index, buf + MGMT_HDR_SIZE, len);
break;
--- bluez-4.101.orig/src/agent.c
+++ bluez-4.101/src/agent.c
@@ -675,7 +675,7 @@ failed:
}
int agent_display_passkey(struct agent *agent, struct btd_device *device,
- uint32_t passkey)
+ uint32_t passkey, uint16_t entered)
{
DBusMessage *message;
const gchar *dev_path = device_get_path(device);
@@ -686,10 +686,13 @@ int agent_display_passkey(struct agent *
error("Couldn't allocate D-Bus message");
return -1;
}
+
+ DBG("agent_display_passkey: %d,%d",passkey,entered);
dbus_message_append_args(message,
DBUS_TYPE_OBJECT_PATH, &dev_path,
DBUS_TYPE_UINT32, &passkey,
+ DBUS_TYPE_UINT16, &entered,
DBUS_TYPE_INVALID);
if (!g_dbus_send_message(connection, message)) {
--- bluez-4.101.orig/src/agent.h
+++ bluez-4.101/src/agent.h
@@ -62,7 +62,7 @@ int agent_request_confirmation(struct ag
void *user_data, GDestroyNotify destroy);
int agent_display_passkey(struct agent *agent, struct btd_device *device,
- uint32_t passkey);
+ uint32_t passkey, uint16_t entered);
int agent_display_pincode(struct agent *agent, struct btd_device *device,
const char *pincode, agent_cb cb,
--- bluez-4.101.orig/src/device.c
+++ bluez-4.101/src/device.c
@@ -2821,26 +2821,26 @@ done:
}
-int device_request_authentication(struct btd_device *device, auth_type_t type,
- void *data, gboolean secure, void *cb)
+static struct authentication_req *new_auth(struct btd_device *device,
+ auth_type_t type, gboolean secure,
+ void *cb)
{
struct authentication_req *auth;
struct agent *agent;
char addr[18];
- int err;
ba2str(&device->bdaddr, addr);
DBG("Requesting agent authentication for %s", addr);
if (device->authr) {
error("Authentication already requested for %s", addr);
- return -EALREADY;
+ return NULL;
}
agent = device_get_agent(device);
if (!agent) {
error("No agent available for request type %d", type);
- return -EPERM;
+ return NULL;
}
auth = g_new0(struct authentication_req, 1);
@@ -2851,33 +2851,87 @@ int device_request_authentication(struct
auth->secure = secure;
device->authr = auth;
- switch (type) {
- case AUTH_TYPE_PINCODE:
- err = agent_request_pincode(agent, device, pincode_cb, secure,
- auth, NULL);
- break;
- case AUTH_TYPE_PASSKEY:
- err = agent_request_passkey(agent, device, passkey_cb,
- auth, NULL);
- break;
- case AUTH_TYPE_CONFIRM:
- auth->passkey = *((uint32_t *) data);
- err = agent_request_confirmation(agent, device, auth->passkey,
- confirm_cb, auth, NULL);
- break;
- case AUTH_TYPE_NOTIFY_PASSKEY:
- auth->passkey = *((uint32_t *) data);
- err = agent_display_passkey(agent, device, auth->passkey);
- break;
- case AUTH_TYPE_NOTIFY_PINCODE:
- auth->pincode = g_strdup((const char *) data);
- err = agent_display_pincode(agent, device, auth->pincode,
- display_pincode_cb, auth, NULL);
- break;
- default:
- err = -EINVAL;
+ return auth;
+}
+
+int device_request_pincode(struct btd_device *device, gboolean secure,
+ void *cb)
+{
+ struct authentication_req *auth;
+ int err;
+
+ auth = new_auth(device, AUTH_TYPE_PINCODE, secure, cb);
+ if (!auth)
+ return -EPERM;
+
+ err = agent_request_pincode(auth->agent, device, pincode_cb, secure,
+ auth, NULL);
+ if (err < 0) {
+ error("Failed requesting authentication");
+ device_auth_req_free(device);
+ }
+
+ return err;
+}
+
+int device_request_passkey(struct btd_device *device, void *cb)
+{
+ struct authentication_req *auth;
+ int err;
+
+ auth = new_auth(device, AUTH_TYPE_PASSKEY, FALSE, cb);
+ if (!auth)
+ return -EPERM;
+
+ err = agent_request_passkey(auth->agent, device, passkey_cb, auth,
+ NULL);
+ if (err < 0) {
+ error("Failed requesting authentication");
+ device_auth_req_free(device);
+ }
+
+ return err;
+}
+
+int device_confirm_passkey(struct btd_device *device, uint32_t passkey,
+ void *cb)
+{
+ struct authentication_req *auth;
+ int err;
+
+ auth = new_auth(device, AUTH_TYPE_CONFIRM, FALSE, cb);
+ if (!auth)
+ return -EPERM;
+
+ auth->passkey = passkey;
+
+ err = agent_request_confirmation(auth->agent, device, passkey,
+ confirm_cb, auth, NULL);
+ if (err < 0) {
+ error("Failed requesting authentication");
+ device_auth_req_free(device);
}
+ return err;
+}
+
+int device_notify_passkey(struct btd_device *device, uint32_t passkey,
+ uint8_t entered)
+{
+ struct authentication_req *auth;
+ int err;
+
+ if (device->authr) {
+ auth = device->authr;
+ if (auth->type != AUTH_TYPE_NOTIFY_PASSKEY)
+ return -EPERM;
+ } else {
+ auth = new_auth(device, AUTH_TYPE_NOTIFY_PASSKEY, FALSE, NULL);
+ if (!auth)
+ return -EPERM;
+ }
+
+ err = agent_display_passkey(auth->agent, device, passkey, entered);
if (err < 0) {
error("Failed requesting authentication");
device_auth_req_free(device);
@@ -2886,6 +2940,28 @@ int device_request_authentication(struct
return err;
}
+int device_notify_pincode(struct btd_device *device, gboolean secure,
+ const char *pincode, void *cb)
+{
+ struct authentication_req *auth;
+ int err;
+
+ auth = new_auth(device, AUTH_TYPE_NOTIFY_PINCODE, secure, cb);
+ if (!auth)
+ return -EPERM;
+
+ auth->pincode = g_strdup(pincode);
+
+ err = agent_display_pincode(auth->agent, device, pincode,
+ display_pincode_cb, auth, NULL);
+ if (err < 0) {
+ error("Failed requesting authentication");
+ device_auth_req_free(device);
+ }
+
+ return err;
+}
+
static void cancel_authentication(struct authentication_req *auth)
{
struct btd_device *device;
--- bluez-4.101.orig/src/device.h
+++ bluez-4.101/src/device.h
@@ -85,8 +85,15 @@ void device_simple_pairing_complete(stru
gboolean device_is_creating(struct btd_device *device, const char *sender);
gboolean device_is_bonding(struct btd_device *device, const char *sender);
void device_cancel_bonding(struct btd_device *device, uint8_t status);
-int device_request_authentication(struct btd_device *device, auth_type_t type,
- void *data, gboolean secure, void *cb);
+int device_request_pincode(struct btd_device *device, gboolean secure,
+ void *cb);
+int device_request_passkey(struct btd_device *device, void *cb);
+int device_confirm_passkey(struct btd_device *device, uint32_t passkey,
+ void *cb);
+int device_notify_passkey(struct btd_device *device, uint32_t passkey,
+ uint8_t entered);
+int device_notify_pincode(struct btd_device *device, gboolean secure,
+ const char *pincode, void *cb);
void device_cancel_authentication(struct btd_device *device, gboolean aborted);
gboolean device_is_authenticating(struct btd_device *device);
gboolean device_is_authorizing(struct btd_device *device);
--- bluez-4.101.orig/src/event.c
+++ bluez-4.101/src/event.c
@@ -128,16 +128,14 @@ int btd_event_request_pin(bdaddr_t *sba,
pinlen = btd_adapter_get_pin(adapter, device, pin, &display);
if (pinlen > 0 && (!secure || pinlen == 16)) {
if (display && device_is_bonding(device, NULL))
- return device_request_authentication(device,
- AUTH_TYPE_NOTIFY_PINCODE, pin,
- secure, pincode_cb);
+ return device_notify_pincode(device, secure, pin,
+ pincode_cb);
btd_adapter_pincode_reply(adapter, dba, pin, pinlen);
return 0;
}
- return device_request_authentication(device, AUTH_TYPE_PINCODE, NULL,
- secure, pincode_cb);
+ return device_request_pincode(device, secure, pincode_cb);
}
static int confirm_reply(struct btd_adapter *adapter,
@@ -185,8 +183,7 @@ int btd_event_user_confirm(bdaddr_t *sba
if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
return -ENODEV;
- return device_request_authentication(device, AUTH_TYPE_CONFIRM,
- &passkey, FALSE, confirm_cb);
+ return device_confirm_passkey(device, passkey, confirm_cb);
}
int btd_event_user_passkey(bdaddr_t *sba, bdaddr_t *dba)
@@ -197,11 +194,10 @@ int btd_event_user_passkey(bdaddr_t *sba
if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
return -ENODEV;
- return device_request_authentication(device, AUTH_TYPE_PASSKEY, NULL,
- FALSE, passkey_cb);
+ return device_request_passkey(device, passkey_cb);
}
-int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
+int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey, uint8_t entered)
{
struct btd_adapter *adapter;
struct btd_device *device;
@@ -209,8 +205,7 @@ int btd_event_user_notify(bdaddr_t *sba,
if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
return -ENODEV;
- return device_request_authentication(device, AUTH_TYPE_NOTIFY_PASSKEY,
- &passkey, FALSE, NULL);
+ return device_notify_passkey(device, passkey, entered);
}
void btd_event_simple_pairing_complete(bdaddr_t *local, bdaddr_t *peer,
--- bluez-4.101.orig/src/event.h
+++ bluez-4.101/src/event.h
@@ -37,7 +37,7 @@ void btd_event_simple_pairing_complete(b
void btd_event_returned_link_key(bdaddr_t *local, bdaddr_t *peer);
int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey);
int btd_event_user_passkey(bdaddr_t *sba, bdaddr_t *dba);
-int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey);
+int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey, uint8_t entered);
void btd_event_device_blocked(bdaddr_t *local, bdaddr_t *peer);
void btd_event_device_unblocked(bdaddr_t *local, bdaddr_t *peer);
void btd_event_device_unpaired(bdaddr_t *local, bdaddr_t *peer);
--- bluez-4.101.orig/test/simple-agent
+++ bluez-4.101/test/simple-agent
@@ -55,9 +55,9 @@ class Agent(dbus.service.Object):
return dbus.UInt32(passkey)
@dbus.service.method("org.bluez.Agent",
- in_signature="ou", out_signature="")
- def DisplayPasskey(self, device, passkey):
- print("DisplayPasskey (%s, %06d)" % (device, passkey))
+ in_signature="ouq", out_signature="")
+ def DisplayPasskey(self, device, passkey, entered):
+ print("DisplayPasskey (%s, %06u entered %u)" % (device, passkey, entered))
@dbus.service.method("org.bluez.Agent",
in_signature="os", out_signature="")
signature.asc
Description: PGP signature
--- End Message ---