All of lore.kernel.org
 help / color / mirror / Atom feed
From: Szymon Janc <szymon.janc@tieto.com>
To: <linux-bluetooth@vger.kernel.org>
Cc: Szymon Janc <szymon.janc@tieto.com>
Subject: [PATCHv3 5/7] Add approval request for incoming pairing requests with OOB mechanism
Date: Tue, 16 Nov 2010 16:44:05 +0100	[thread overview]
Message-ID: <1289922247-20712-6-git-send-email-szymon.janc@tieto.com> (raw)
In-Reply-To: <1289922247-20712-1-git-send-email-szymon.janc@tieto.com>

---
 plugins/hciops.c |   42 ++++++++++++++++++++++++++++++--------
 src/adapter.c    |    7 ++++++
 src/adapter.h    |    3 ++
 src/agent.c      |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/agent.h      |    3 ++
 src/device.c     |   22 ++++++++++++++++++++
 src/device.h     |    1 +
 src/event.c      |   41 +++++++++++++++++++++++++++++++++++++
 src/event.h      |    1 +
 9 files changed, 169 insertions(+), 10 deletions(-)

diff --git a/plugins/hciops.c b/plugins/hciops.c
index 75e6b0c..9546874 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -520,15 +520,8 @@ static void remote_oob_data_request(int index, void *ptr)
 	adapter = manager_find_adapter(&BDADDR(index));
 	device = adapter_find_device(adapter, da);
 
-	if (device_has_oob_data(device)) {
-		remote_oob_data_reply_cp cp;
-
-		bacpy(&cp.bdaddr, dba);
-		device_get_oob_data(device,cp.hash,cp.randomizer);
-
-		hci_send_cmd(SK(index), OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_REPLY,
-				REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
-	} else
+	if (!device_has_oob_data(device)
+			|| btd_event_user_approve(&BDADDR(index), dba))
 		hci_send_cmd(SK(index),
 				OGF_LINK_CTL, OCF_REMOTE_OOB_DATA_NEG_REPLY, 6,
 				ptr);
@@ -2217,6 +2210,36 @@ static int hciops_passkey_reply(int index, bdaddr_t *bdaddr, uint32_t passkey)
 	return err;
 }
 
+static int hciops_approve_reply(int index, bdaddr_t *bdaddr, gboolean approved)
+{
+	int err;
+	struct btd_adapter *adapter;
+	struct btd_device *device;
+	char da[18];
+
+	ba2str(bdaddr, da);
+	adapter = manager_find_adapter_by_id(index);
+	device = adapter_find_device(adapter, da);
+
+	if (approved) {
+		remote_oob_data_reply_cp cp;
+
+		bacpy(&cp.bdaddr, bdaddr);
+		device_get_oob_data(device,cp.hash,cp.randomizer);
+
+		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
+				OCF_REMOTE_OOB_DATA_REPLY,
+				REMOTE_OOB_DATA_REPLY_CP_SIZE, &cp);
+	} else
+		err = hci_send_cmd(SK(index), OGF_LINK_CTL,
+				OCF_REMOTE_OOB_DATA_NEG_REPLY, 6, bdaddr);
+
+	if (err < 0)
+		err = -errno;
+
+	return err;
+}
+
 static int hciops_get_auth_info(int index, bdaddr_t *bdaddr, uint8_t *auth)
 {
 	struct hci_auth_info_req req;
@@ -2365,6 +2388,7 @@ static struct btd_adapter_ops hci_ops = {
 	.pincode_reply = hciops_pincode_reply,
 	.confirm_reply = hciops_confirm_reply,
 	.passkey_reply = hciops_passkey_reply,
+	.approve_reply = hciops_approve_reply,
 	.get_auth_info = hciops_get_auth_info,
 	.read_scan_enable = hciops_read_scan_enable,
 	.read_ssp_mode = hciops_read_ssp_mode,
diff --git a/src/adapter.c b/src/adapter.c
index 39a6514..ab680f3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3692,6 +3692,13 @@ int btd_adapter_passkey_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 	return adapter_ops->passkey_reply(adapter->dev_id, bdaddr, passkey);
 }
 
+int btd_adapter_approve_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
+							gboolean success)
+{
+	DBG("reply %u", success);
+	return adapter_ops->approve_reply(adapter->dev_id, bdaddr, success);
+}
+
 int btd_adapter_get_auth_info(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 								uint8_t *auth)
 {
diff --git a/src/adapter.h b/src/adapter.h
index cc62865..cf66129 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -221,6 +221,7 @@ struct btd_adapter_ops {
 	int (*pincode_reply) (int index, bdaddr_t *bdaddr, const char *pin);
 	int (*confirm_reply) (int index, bdaddr_t *bdaddr, gboolean success);
 	int (*passkey_reply) (int index, bdaddr_t *bdaddr, uint32_t passkey);
+	int (*approve_reply) (int index, bdaddr_t *bdaddr, gboolean success);
 	int (*get_auth_info) (int index, bdaddr_t *bdaddr, uint8_t *auth);
 	int (*read_scan_enable) (int index);
 	int (*read_ssp_mode) (int index);
@@ -272,6 +273,8 @@ int btd_adapter_confirm_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 							gboolean success);
 int btd_adapter_passkey_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 							uint32_t passkey);
+int btd_adapter_approve_reply(struct btd_adapter *adapter, bdaddr_t *bdaddr,
+							gboolean success);
 
 int btd_adapter_get_auth_info(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 								uint8_t *auth);
diff --git a/src/agent.c b/src/agent.c
index 2ddfd6e..a4b26b6 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -55,7 +55,8 @@ typedef enum {
 	AGENT_REQUEST_CONFIRMATION,
 	AGENT_REQUEST_PINCODE,
 	AGENT_REQUEST_AUTHORIZE,
-	AGENT_REQUEST_CONFIRM_MODE
+	AGENT_REQUEST_CONFIRM_MODE,
+	AGENT_REQUEST_APPROVAL
 } agent_request_type_t;
 
 struct agent {
@@ -693,6 +694,62 @@ failed:
 	return err;
 }
 
+static int approval_request_new(struct agent_request *req,
+					const char *device_path)
+{
+	struct agent *agent = req->agent;
+
+	req->msg = dbus_message_new_method_call(agent->name, agent->path,
+				"org.bluez.Agent", "RequestApproval");
+	if (req->msg == NULL) {
+		error("Couldn't allocate D-Bus message");
+		return -ENOMEM;
+	}
+
+	dbus_message_append_args(req->msg,
+				DBUS_TYPE_OBJECT_PATH, &device_path,
+				DBUS_TYPE_INVALID);
+
+	if (dbus_connection_send_with_reply(connection, req->msg,
+				&req->call, REQUEST_TIMEOUT) == FALSE) {
+		error("D-Bus send failed");
+		return -EIO;
+	}
+
+	dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL);
+
+	return 0;
+}
+
+int agent_request_approval (struct agent *agent, struct btd_device *device,
+			agent_cb cb, void *user_data, GDestroyNotify destroy)
+{
+	struct agent_request *req;
+	const gchar *dev_path = device_get_path(device);
+	int err;
+
+	if (agent->request)
+		return -EBUSY;
+
+	DBG("Calling Agent.RequestApproval: name=%s, path=%s", agent->name,
+			agent->path);
+
+	req = agent_request_new(agent, AGENT_REQUEST_APPROVAL, cb,
+				user_data, destroy);
+
+	err = approval_request_new(req, dev_path);
+	if (err < 0)
+		goto failed;
+
+	agent->request = req;
+
+	return 0;
+
+failed:
+	agent_request_free(req, FALSE);
+	return err;
+}
+
 static int request_fallback(struct agent_request *req,
 				DBusPendingCallNotifyFunction function)
 {
diff --git a/src/agent.h b/src/agent.h
index e184250..73dd531 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -64,6 +64,9 @@ int agent_request_confirmation(struct agent *agent, struct btd_device *device,
 int agent_display_passkey(struct agent *agent, struct btd_device *device,
 				uint32_t passkey);
 
+int agent_request_approval (struct agent *agent, struct btd_device *device,
+			agent_cb cb, void *user_data, GDestroyNotify destroy);
+
 int agent_cancel(struct agent *agent);
 
 gboolean agent_is_busy(struct agent *agent, void *user_data);
diff --git a/src/device.c b/src/device.c
index 24fd44d..a507fe8 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2245,6 +2245,21 @@ static void passkey_cb(struct agent *agent, DBusError *err,
 	device->authr->agent = NULL;
 }
 
+static void approve_cb(struct agent *agent, DBusError *err, void *data)
+{
+	struct authentication_req *auth = data;
+	struct btd_device *device = auth->device;
+
+	/* No need to reply anything if the authentication already failed */
+	if (auth->cb == NULL)
+		return;
+
+	((agent_cb) auth->cb)(agent, err, device);
+
+	device->authr->cb = NULL;
+	device->authr->agent = NULL;
+}
+
 int device_request_authentication(struct btd_device *device, auth_type_t type,
 						uint32_t passkey, void *cb)
 {
@@ -2283,6 +2298,10 @@ int device_request_authentication(struct btd_device *device, auth_type_t type,
 	case AUTH_TYPE_NOTIFY:
 		err = agent_display_passkey(agent, device, passkey);
 		break;
+	case AUTH_TYPE_APPROVE:
+		err = agent_request_approval (agent, device, approve_cb, auth,
+				NULL);
+		break;
 	case AUTH_TYPE_AUTO:
 		err = 0;
 		break;
@@ -2324,6 +2343,9 @@ static void cancel_authentication(struct authentication_req *auth)
 	case AUTH_TYPE_PASSKEY:
 		((agent_passkey_cb) auth->cb)(agent, &err, 0, device);
 		break;
+	case AUTH_TYPE_APPROVE:
+		((agent_cb) auth->cb)(agent, &err, device);
+		break;
 	case AUTH_TYPE_NOTIFY:
 	case AUTH_TYPE_AUTO:
 		/* User Notify/Auto doesn't require any reply */
diff --git a/src/device.h b/src/device.h
index b62cdc5..2da3311 100644
--- a/src/device.h
+++ b/src/device.h
@@ -33,6 +33,7 @@ typedef enum {
 	AUTH_TYPE_CONFIRM,
 	AUTH_TYPE_NOTIFY,
 	AUTH_TYPE_AUTO,
+	AUTH_TYPE_APPROVE
 } auth_type_t;
 
 struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter,
diff --git a/src/event.c b/src/event.c
index 5a5a288..957a17d 100644
--- a/src/event.c
+++ b/src/event.c
@@ -175,6 +175,18 @@ static void passkey_cb(struct agent *agent, DBusError *err, uint32_t passkey,
 	btd_adapter_passkey_reply(adapter, &bdaddr, passkey);
 }
 
+static void approve_cb(struct agent *agent, DBusError *err, void *user_data)
+{
+	struct btd_device *device = user_data;
+	struct btd_adapter *adapter = device_get_adapter(device);
+	bdaddr_t bdaddr;
+	gboolean approve = (err == NULL) ? TRUE : FALSE;
+
+	device_get_address(device, &bdaddr);
+
+	btd_adapter_approve_reply(adapter, &bdaddr, approve);
+}
+
 int btd_event_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
 {
 	struct btd_adapter *adapter;
@@ -264,6 +276,35 @@ int btd_event_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey)
 								passkey, NULL);
 }
 
+int btd_event_user_approve(bdaddr_t *sba, bdaddr_t *dba)
+{
+	struct btd_adapter *adapter;
+	struct btd_device *device;
+	struct agent *agent;
+	uint8_t cap;
+
+	if (!get_adapter_and_device(sba, dba, &adapter, &device, TRUE))
+		return -ENODEV;
+
+	agent = device_get_agent(device);
+	if (!agent)
+		return -ENODEV;
+
+	cap = agent_get_io_capability(agent);
+
+	/* If initiator or agent has no input capability approve immediately. */
+	if (device_is_bonding(device, NULL) || cap == 0x00 || cap == 0x03) {
+		bdaddr_t bdaddr;
+
+		device_get_address(device, &bdaddr);
+		btd_adapter_approve_reply(adapter, &bdaddr, TRUE);
+		return 0;
+	}
+
+	return device_request_authentication(device, AUTH_TYPE_APPROVE, 0,
+								approve_cb);
+}
+
 void btd_event_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,
 								uint8_t status)
 {
diff --git a/src/event.h b/src/event.h
index a3e7dda..c1ea2ef 100644
--- a/src/event.h
+++ b/src/event.h
@@ -42,6 +42,7 @@ int btd_event_set_io_cap(bdaddr_t *local, bdaddr_t *remote,
 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_approve(bdaddr_t *sba, bdaddr_t *dba);
 int btd_event_link_key_notify(bdaddr_t *local, bdaddr_t *peer,
 				uint8_t *key, uint8_t key_type,
 				int pin_length, uint8_t old_key_type);
-- 
1.7.1


  parent reply	other threads:[~2010-11-16 15:44 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-16 15:44 [PATCHv3 0/7] Support for out of band association model Szymon Janc
2010-11-16 15:44 ` [PATCHv3 1/7] Add support for Out of Band (OOB) " Szymon Janc
2010-11-16 16:16   ` Johan Hedberg
2010-11-16 15:44 ` [PATCHv3 2/7] Add DBus OOB plugin Szymon Janc
2010-11-16 16:30   ` Johan Hedberg
2010-11-16 15:44 ` [PATCHv3 3/7] Add DBus OOB API documentation Szymon Janc
2010-11-16 16:37   ` Johan Hedberg
2010-11-17 12:49     ` Szymon Janc
2010-11-18 10:51       ` Szymon Janc
2010-11-18 13:45         ` Johan Hedberg
2010-11-16 15:44 ` [PATCHv3 4/7] Add simple-oobprovider for testing Szymon Janc
2010-11-16 15:44 ` Szymon Janc [this message]
2010-11-16 16:24   ` [PATCHv3 5/7] Add approval request for incoming pairing requests with OOB mechanism Johan Hedberg
2010-11-17 16:03     ` Szymon Janc
2010-11-16 15:44 ` [PATCHv3 6/7] Update DBus OOB API with RequestApproval method Szymon Janc
2010-11-16 15:44 ` [PATCHv3 7/7] simple-agent - add RequestApproval method for OOB pairing Szymon Janc

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1289922247-20712-6-git-send-email-szymon.janc@tieto.com \
    --to=szymon.janc@tieto.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.