client: Add authorization request handling for attribute operations
This patch adds optional authorization request for reading, writing of
gatt database attributes.
diff --git a/client/gatt.c b/client/gatt.c
index 3fa490b..930a646 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -75,6 +75,8 @@
uint16_t mtu;
struct io *write_io;
struct io *notify_io;
+ bool authorization_req;
+ bool authorized;
};
struct service {
@@ -91,6 +93,7 @@
static GList *descriptors;
static GList *managers;
static GList *uuids;
+static DBusMessage *pending_message = NULL;
struct pipe_io {
GDBusProxy *proxy;
@@ -1462,17 +1465,81 @@
return reply;
}
+struct authorize_attribute_data {
+ DBusConnection *conn;
+ void *attribute;
+ uint16_t offset;
+};
+
+static void authorize_read_response(const char *input, void *user_data)
+{
+ struct authorize_attribute_data *aad = user_data;
+ struct chrc *chrc = aad->attribute;
+ DBusMessage *reply;
+ char *err;
+
+ if (!strcmp(input, "no")) {
+ err = "org.bluez.Error.NotAuthorized";
+
+ goto error;
+ }
+
+ if (aad->offset > chrc->value_len) {
+ err = "org.bluez.Error.InvalidOffset";
+
+ goto error;
+ }
+
+ reply = read_value(pending_message, &chrc->value[aad->offset],
+ chrc->value_len - aad->offset);
+
+ chrc->authorized = true;
+
+ g_dbus_send_message(aad->conn, reply);
+
+ g_free(aad);
+
+ return;
+
+error:
+ g_dbus_send_error(aad->conn, pending_message, err, NULL);
+ g_free(aad);
+}
+
static DBusMessage *chrc_read_value(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
struct chrc *chrc = user_data;
DBusMessageIter iter;
uint16_t offset = 0;
+ char *str;
dbus_message_iter_init(msg, &iter);
parse_offset(&iter, &offset);
+ if (chrc->authorization_req && offset == 0)
+ chrc->authorized = false;
+
+ if (chrc->authorization_req && !chrc->authorized) {
+ struct authorize_attribute_data *aad;
+
+ aad = g_new0(struct authorize_attribute_data, 1);
+ aad->conn = conn;
+ aad->attribute = chrc;
+ aad->offset = offset;
+
+ str = g_strdup_printf("Authorize attribute(%s) read (yes/no):",
+ chrc->path);
+
+ bt_shell_prompt_input("gatt", str, authorize_read_response,
+ aad);
+
+ pending_message = dbus_message_ref(msg);
+
+ return NULL;
+ }
+
if (offset > chrc->value_len)
return g_dbus_create_error(msg, "org.bluez.Error.InvalidOffset",
NULL);
@@ -1493,14 +1560,74 @@
return 0;
}
+static void authorize_write_response(const char *input, void *user_data)
+{
+ struct authorize_attribute_data *aad = user_data;
+ struct chrc *chrc = aad->attribute;
+ DBusMessageIter iter;
+ DBusMessage *reply;
+ char *err;
+
+ dbus_message_iter_init(pending_message, &iter);
+
+ if (!strcmp(input, "no")) {
+ err = "org.bluez.Error.NotAuthorized";
+
+ goto error;
+ }
+
+ chrc->authorized = true;
+
+ if (parse_value_arg(&iter, &chrc->value, &chrc->value_len)) {
+ err = "org.bluez.Error.InvalidArguments";
+
+ goto error;
+ }
+
+ bt_shell_printf("[" COLORED_CHG "] Attribute %s written" , chrc->path);
+
+ g_dbus_emit_property_changed(aad->conn, chrc->path, CHRC_INTERFACE,
+ "Value");
+
+ reply = g_dbus_create_reply(pending_message, DBUS_TYPE_INVALID);
+ g_dbus_send_message(aad->conn, reply);
+
+ g_free(aad);
+
+ return;
+
+error:
+ g_dbus_send_error(aad->conn, pending_message, err, NULL);
+ g_free(aad);
+}
+
static DBusMessage *chrc_write_value(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
struct chrc *chrc = user_data;
DBusMessageIter iter;
+ char *str;
dbus_message_iter_init(msg, &iter);
+ if (chrc->authorization_req && !chrc->authorized) {
+ struct authorize_attribute_data *aad;
+
+ aad = g_new0(struct authorize_attribute_data, 1);
+ aad->conn = conn;
+ aad->attribute = chrc;
+
+ str = g_strdup_printf("Authorize attribute(%s) write (yes/no):",
+ chrc->path);
+
+ bt_shell_prompt_input("gatt", str, authorize_write_response,
+ aad);
+
+ pending_message = dbus_message_ref(msg);
+
+ return NULL;
+ }
+
if (parse_value_arg(&iter, &chrc->value, &chrc->value_len))
return g_dbus_create_error(msg,
"org.bluez.Error.InvalidArguments",
@@ -1763,6 +1890,7 @@
chrc->uuid = g_strdup(argv[1]);
chrc->path = g_strdup_printf("%s/chrc%p", service->path, chrc);
chrc->flags = g_strsplit(argv[2], ",", -1);
+ chrc->authorization_req = argc > 3 ? true : false;
if (g_dbus_register_interface(conn, chrc->path, CHRC_INTERFACE,
chrc_methods, NULL, chrc_properties,
diff --git a/client/main.c b/client/main.c
index a83010b..9cc0a29 100644
--- a/client/main.c
+++ b/client/main.c
@@ -2011,6 +2011,11 @@
if (check_default_ctrl() == FALSE)
return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ if (argc > 3 && strcmp(argv[3], "authorize")) {
+ bt_shell_printf("Invalid authorize argument\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
gatt_register_chrc(dbus_conn, default_ctrl->proxy, argc, argv);
}
@@ -2428,9 +2433,9 @@
"Register application service." },
{ "unregister-service", "<UUID/object>", cmd_unregister_service,
"Unregister application service" },
- { "register-characteristic", "<UUID> <Flags=read,write,notify...>",
- cmd_register_characteristic,
- "Register application characteristic" },
+ { "register-characteristic", "<UUID> <Flags=read,write,notify...> "
+ "[authorize]", cmd_register_characteristic,
+ "Register application characteristic" },
{ "unregister-characteristic", "<UUID/object>",
cmd_unregister_characteristic,
"Unregister application characteristic" },