summaryrefslogtreecommitdiff
path: root/client/gatt.c
diff options
context:
space:
mode:
authorGrzegorz Kolodziejczyk <grzegorz.kolodziejczyk@codecoup.pl>2018-05-28 10:20:53 +0200
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2018-05-28 16:29:11 +0300
commit822f082063c1992b1d235b0bb998a6c448dd5923 (patch)
tree9286ec26d41adc825f66a5ab41bb81d0422a8357 /client/gatt.c
parent1ebfc68ff53ea5ed5cb424df151bf413c7ffe9be (diff)
downloadbluez-822f082063c1992b1d235b0bb998a6c448dd5923.tar.gz
client: Add authorized property handling to characteristic attribute
This patch adds handling of characteristic prepare write authorized property to bluetoothctl.
Diffstat (limited to 'client/gatt.c')
-rw-r--r--client/gatt.c146
1 files changed, 94 insertions, 52 deletions
diff --git a/client/gatt.c b/client/gatt.c
index d37a6f55c..3e70f365c 100644
--- a/client/gatt.c
+++ b/client/gatt.c
@@ -80,7 +80,6 @@ struct chrc {
struct io *write_io;
struct io *notify_io;
bool authorization_req;
- bool authorized;
};
struct service {
@@ -1609,7 +1608,8 @@ static const char *path_to_address(const char *path)
}
static int parse_options(DBusMessageIter *iter, uint16_t *offset, uint16_t *mtu,
- char **device, char **link)
+ char **device, char **link,
+ bool *prep_authorize)
{
DBusMessageIter dict;
@@ -1650,6 +1650,12 @@ static int parse_options(DBusMessageIter *iter, uint16_t *offset, uint16_t *mtu,
return -EINVAL;
if (link)
dbus_message_iter_get_basic(&value, link);
+ } else if (strcasecmp(key, "prepare-authorize") == 0) {
+ if (var != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+ if (prep_authorize)
+ dbus_message_iter_get_basic(&value,
+ prep_authorize);
}
dbus_message_iter_next(&dict);
@@ -1703,8 +1709,6 @@ static void authorize_read_response(const char *input, void *user_data)
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);
@@ -1727,18 +1731,15 @@ static DBusMessage *chrc_read_value(DBusConnection *conn, DBusMessage *msg,
dbus_message_iter_init(msg, &iter);
- if (parse_options(&iter, &offset, NULL, &device, &link))
+ if (parse_options(&iter, &offset, NULL, &device, &link, NULL))
return g_dbus_create_error(msg,
"org.bluez.Error.InvalidArguments",
NULL);
bt_shell_printf("ReadValue: %s offset %u link %s\n",
- path_to_address(device), offset, link);
-
- if (chrc->authorization_req && offset == 0)
- chrc->authorized = false;
+ path_to_address(device), offset, link);
- if (chrc->authorization_req && !chrc->authorized) {
+ if (chrc->authorization_req) {
struct authorize_attribute_data *aad;
aad = g_new0(struct authorize_attribute_data, 1);
@@ -1765,33 +1766,31 @@ static DBusMessage *chrc_read_value(DBusConnection *conn, DBusMessage *msg,
return read_value(msg, &chrc->value[offset], chrc->value_len - offset);
}
-static int parse_value_arg(DBusMessageIter *iter, uint8_t **value, int *len,
- int max_len)
+static int parse_value_arg(DBusMessageIter *iter, uint8_t **value, int *len)
{
DBusMessageIter array;
- uint16_t offset = 0;
- uint8_t *read_value;
- int read_len;
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
return -EINVAL;
dbus_message_iter_recurse(iter, &array);
- dbus_message_iter_get_fixed_array(&array, &read_value, &read_len);
+ dbus_message_iter_get_fixed_array(&array, value, len);
- dbus_message_iter_next(iter);
- if (parse_options(iter, &offset, NULL, NULL, NULL))
- return -EINVAL;
+ return 0;
+}
- if ((offset + read_len) > max_len)
+static int write_value(int *dst_len, uint8_t **dst_value, uint8_t *src_val,
+ int src_len, uint16_t offset, uint16_t max_len)
+{
+ if ((offset + src_len) > max_len)
return -EOVERFLOW;
- if ((offset + read_len) > *len) {
- *len = offset + read_len;
- *value = g_realloc(*value, *len);
+ if ((offset + src_len) != *dst_len) {
+ *dst_len = offset + src_len;
+ *dst_value = g_realloc(*dst_value, *dst_len);
}
- memcpy(*value + offset, read_value, read_len);
+ memcpy(*dst_value + offset, src_val, src_len);
return 0;
}
@@ -1800,12 +1799,26 @@ static void authorize_write_response(const char *input, void *user_data)
{
struct authorize_attribute_data *aad = user_data;
struct chrc *chrc = aad->attribute;
+ bool prep_authorize = false;
DBusMessageIter iter;
DBusMessage *reply;
+ int value_len;
+ uint8_t *value;
char *err;
- int errsv;
dbus_message_iter_init(pending_message, &iter);
+ if (parse_value_arg(&iter, &value, &value_len)) {
+ err = "org.bluez.Error.InvalidArguments";
+
+ goto error;
+ }
+
+ dbus_message_iter_next(&iter);
+ if (parse_options(&iter, NULL, NULL, NULL, NULL, &prep_authorize)) {
+ err = "org.bluez.Error.InvalidArguments";
+
+ goto error;
+ }
if (!strcmp(input, "no")) {
err = "org.bluez.Error.NotAuthorized";
@@ -1813,15 +1826,17 @@ static void authorize_write_response(const char *input, void *user_data)
goto error;
}
- chrc->authorized = true;
+ /* Authorization check of prepare writes */
+ if (prep_authorize) {
+ reply = g_dbus_create_reply(pending_message, DBUS_TYPE_INVALID);
+ g_dbus_send_message(aad->conn, reply);
+ g_free(aad);
- errsv = parse_value_arg(&iter, &chrc->value, &chrc->value_len,
- chrc->max_val_len);
- if (errsv == -EINVAL) {
- err = "org.bluez.Error.InvalidArguments";
+ return;
+ }
- goto error;
- } else if (errsv == -EOVERFLOW) {
+ if (write_value(&chrc->value_len, &chrc->value, value, value_len,
+ aad->offset, chrc->max_val_len)) {
err = "org.bluez.Error.InvalidValueLength";
goto error;
@@ -1848,18 +1863,31 @@ static DBusMessage *chrc_write_value(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
struct chrc *chrc = user_data;
+ uint16_t offset = 0;
+ bool prep_authorize = false;
DBusMessageIter iter;
+ int value_len;
+ uint8_t *value;
char *str;
- int errsv;
dbus_message_iter_init(msg, &iter);
- if (chrc->authorization_req && !chrc->authorized) {
+ if (parse_value_arg(&iter, &value, &value_len))
+ return g_dbus_create_error(msg,
+ "org.bluez.Error.InvalidArguments", NULL);
+
+ dbus_message_iter_next(&iter);
+ if (parse_options(&iter, &offset, NULL, NULL, NULL, &prep_authorize))
+ return g_dbus_create_error(msg,
+ "org.bluez.Error.InvalidArguments", NULL);
+
+ if (chrc->authorization_req) {
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) write (yes/no):",
chrc->path);
@@ -1873,15 +1901,14 @@ static DBusMessage *chrc_write_value(DBusConnection *conn, DBusMessage *msg,
return NULL;
}
- errsv = parse_value_arg(&iter, &chrc->value, &chrc->value_len,
- chrc->max_val_len);
- if (errsv == -EINVAL) {
- return g_dbus_create_error(msg,
- "org.bluez.Error.InvalidArguments", NULL);
- } else if (errsv == -EOVERFLOW) {
+ /* Authorization check of prepare writes */
+ if (prep_authorize)
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+
+ if (write_value(&chrc->value_len, &chrc->value, value, value_len,
+ offset, chrc->max_val_len))
return g_dbus_create_error(msg,
"org.bluez.Error.InvalidValueLength", NULL);
- }
bt_shell_printf("[" COLORED_CHG "] Attribute %s written" , chrc->path);
@@ -1943,7 +1970,7 @@ static DBusMessage *chrc_acquire_write(DBusConnection *conn, DBusMessage *msg,
"org.bluez.Error.NotPermitted",
NULL);
- if (parse_options(&iter, NULL, &chrc->mtu, &device, &link))
+ if (parse_options(&iter, NULL, &chrc->mtu, &device, &link, NULL))
return g_dbus_create_error(msg,
"org.bluez.Error.InvalidArguments",
NULL);
@@ -1975,7 +2002,7 @@ static DBusMessage *chrc_acquire_notify(DBusConnection *conn, DBusMessage *msg,
"org.bluez.Error.NotPermitted",
NULL);
- if (parse_options(&iter, NULL, &chrc->mtu, &device, &link))
+ if (parse_options(&iter, NULL, &chrc->mtu, &device, &link, NULL))
return g_dbus_create_error(msg,
"org.bluez.Error.InvalidArguments",
NULL);
@@ -2101,6 +2128,18 @@ static void chrc_set_value(const char *input, void *user_data)
chrc->max_val_len = chrc->value_len;
}
+static gboolean attr_authorization_flag_exists(char **flags)
+{
+ int i;
+
+ for (i = 0; flags[i]; i++) {
+ if (!strcmp("authorize", flags[i]))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
void gatt_register_chrc(DBusConnection *conn, GDBusProxy *proxy,
int argc, char *argv[])
{
@@ -2119,7 +2158,7 @@ void gatt_register_chrc(DBusConnection *conn, GDBusProxy *proxy,
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;
+ chrc->authorization_req = attr_authorization_flag_exists(chrc->flags);
if (g_dbus_register_interface(conn, chrc->path, CHRC_INTERFACE,
chrc_methods, NULL, chrc_properties,
@@ -2191,7 +2230,7 @@ static DBusMessage *desc_read_value(DBusConnection *conn, DBusMessage *msg,
dbus_message_iter_init(msg, &iter);
- if (parse_options(&iter, &offset, NULL, &device, &link))
+ if (parse_options(&iter, &offset, NULL, &device, &link, NULL))
return g_dbus_create_error(msg,
"org.bluez.Error.InvalidArguments",
NULL);
@@ -2213,21 +2252,24 @@ static DBusMessage *desc_write_value(DBusConnection *conn, DBusMessage *msg,
DBusMessageIter iter;
uint16_t offset = 0;
char *device = NULL, *link = NULL;
+ int value_len;
+ uint8_t *value;
dbus_message_iter_init(msg, &iter);
- if (parse_value_arg(&iter, &desc->value, &desc->value_len,
- desc->max_val_len))
+ if (parse_value_arg(&iter, &value, &value_len))
return g_dbus_create_error(msg,
- "org.bluez.Error.InvalidArguments",
- NULL);
+ "org.bluez.Error.InvalidArguments", NULL);
dbus_message_iter_next(&iter);
+ if (parse_options(&iter, &offset, NULL, &device, &link, NULL))
+ return g_dbus_create_error(msg,
+ "org.bluez.Error.InvalidArguments", NULL);
- if (parse_options(&iter, &offset, NULL, &device, &link))
+ if (write_value(&desc->value_len, &desc->value, value,
+ value_len, offset, desc->max_val_len))
return g_dbus_create_error(msg,
- "org.bluez.Error.InvalidArguments",
- NULL);
+ "org.bluez.Error.InvalidValueLength", NULL);
bt_shell_printf("WriteValue: %s offset %u link %s\n",
path_to_address(device), offset, link);