Re: [PATCH BlueZ v2 4/5] shared/gatt-server: Request authorization for prepare writes.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Grzegorz,

On Wed, May 16, 2018 at 4:52 PM, Grzegorz Kolodziejczyk
<grzegorz.kolodziejczyk@xxxxxxxxxxx> wrote:
> This patch adds gatt-server possibility to request authorization from
> application if needed and previously wasn't authorized. Authorization is
> requested by sending message with set prepare write authorization reqest
> to client.
> ---
>  src/gatt-database.c      | 86 ++++++++++++++++++++++++++++++++++++++++--------
>  src/shared/gatt-server.c | 64 ++++++++++++++++++++++++++++++-----
>  2 files changed, 127 insertions(+), 23 deletions(-)
>
> diff --git a/src/gatt-database.c b/src/gatt-database.c
> index 0ac5b75b0..3326b40db 100644
> --- a/src/gatt-database.c
> +++ b/src/gatt-database.c
> @@ -133,6 +133,7 @@ struct external_chrc {
>         struct queue *pending_reads;
>         struct queue *pending_writes;
>         unsigned int ntfy_cnt;
> +       bool authorized;
>  };
>
>  struct external_desc {
> @@ -144,6 +145,7 @@ struct external_desc {
>         bool handled;
>         struct queue *pending_reads;
>         struct queue *pending_writes;
> +       bool authorized;
>  };
>
>  struct pending_op {
> @@ -154,6 +156,8 @@ struct pending_op {
>         struct gatt_db_attribute *attrib;
>         struct queue *owner_queue;
>         struct iovec data;
> +       bool is_characteristic;
> +       bool authorize;
>  };
>
>  struct notify {
> @@ -1937,6 +1941,9 @@ static void append_options(DBusMessageIter *iter, void *user_data)
>                                                         &op->offset);
>         if (link)
>                 dict_append_entry(iter, "link", DBUS_TYPE_STRING, &link);
> +       if (op->authorize)
> +               dict_append_entry(iter, "authorize", DBUS_TYPE_BOOLEAN,
> +                                                       &op->authorize);
>  }
>
>  static void read_setup_cb(DBusMessageIter *iter, void *user_data)
> @@ -2008,6 +2015,8 @@ static void write_setup_cb(DBusMessageIter *iter, void *user_data)
>  static void write_reply_cb(DBusMessage *message, void *user_data)
>  {
>         struct pending_op *op = user_data;
> +       struct external_chrc *chrc;
> +       struct external_desc *desc;
>         DBusError err;
>         DBusMessageIter iter;
>         uint8_t ecode = 0;
> @@ -2027,6 +2036,16 @@ static void write_reply_cb(DBusMessage *message, void *user_data)
>                 goto done;
>         }
>
> +       if (op->authorize) {
> +               if (op->is_characteristic) {
> +                       chrc = gatt_db_attribute_get_user_data(op->attrib);
> +                       chrc->authorized = true;
> +               } else {
> +                       desc = gatt_db_attribute_get_user_data(op->attrib);
> +                       desc->authorized = true;
> +               }
> +       }
> +
>         dbus_message_iter_init(message, &iter);
>         if (dbus_message_iter_has_next(&iter)) {
>                 /*
> @@ -2045,9 +2064,10 @@ static struct pending_op *pending_write_new(struct btd_device *device,
>                                         struct queue *owner_queue,
>                                         struct gatt_db_attribute *attrib,
>                                         unsigned int id,
> -                                       const uint8_t *value,
> -                                       size_t len,
> -                                       uint16_t offset, uint8_t link_type)
> +                                       const uint8_t *value, size_t len,
> +                                       uint16_t offset, uint8_t link_type,
> +                                       bool is_characteristic,
> +                                       bool authorize)
>  {
>         struct pending_op *op;
>
> @@ -2062,6 +2082,8 @@ static struct pending_op *pending_write_new(struct btd_device *device,
>         op->id = id;
>         op->offset = offset;
>         op->link_type = link_type;
> +       op->is_characteristic = is_characteristic;
> +       op->authorize = authorize;
>         queue_push_tail(owner_queue, op);
>
>         return op;
> @@ -2073,12 +2095,15 @@ static struct pending_op *send_write(struct btd_device *device,
>                                         struct queue *owner_queue,
>                                         unsigned int id,
>                                         const uint8_t *value, size_t len,
> -                                       uint16_t offset, uint8_t link_type)
> +                                       uint16_t offset, uint8_t link_type,
> +                                       bool is_characteristic,
> +                                       bool authorize)
>  {
>         struct pending_op *op;
>
>         op = pending_write_new(device, owner_queue, attrib, id, value, len,
> -                                                       offset, link_type);
> +                                       offset, link_type, is_characteristic,
> +                                       authorize);
>
>         if (g_dbus_proxy_method_call(proxy, "WriteValue", write_setup_cb,
>                                         owner_queue ? write_reply_cb : NULL,
> @@ -2191,7 +2216,7 @@ static void acquire_write_reply(DBusMessage *message, void *user_data)
>  retry:
>         send_write(op->device, op->attrib, chrc->proxy, NULL, op->id,
>                                 op->data.iov_base, op->data.iov_len, 0,
> -                               op->link_type);
> +                               op->link_type, false, false);
>  }
>
>  static void acquire_write_setup(DBusMessageIter *iter, void *user_data)
> @@ -2229,7 +2254,7 @@ static struct pending_op *acquire_write(struct external_chrc *chrc,
>         struct pending_op *op;
>
>         op = pending_write_new(device, NULL, attrib, id, value, len, 0,
> -                                                       link_type);
> +                                               link_type, false, false);
>
>         if (g_dbus_proxy_method_call(chrc->proxy, "AcquireWrite",
>                                         acquire_write_setup,
> @@ -2520,6 +2545,7 @@ static void desc_write_cb(struct gatt_db_attribute *attrib,
>  {
>         struct external_desc *desc = user_data;
>         struct btd_device *device;
> +       DBusMessageIter iter;
>
>         if (desc->attrib != attrib) {
>                 error("Read callback called with incorrect attribute");
> @@ -2532,8 +2558,25 @@ static void desc_write_cb(struct gatt_db_attribute *attrib,
>                 goto fail;
>         }
>
> +       if (opcode == BT_ATT_OP_PREP_WRITE_REQ) {
> +               if (!desc->authorized && g_dbus_proxy_get_property(desc->proxy,
> +                                                       "Authorize", &iter))
> +                       send_write(device, attrib, desc->proxy,
> +                                       desc->pending_writes, id, value, len,
> +                                       offset, bt_att_get_link_type(att),
> +                                       false, true);
> +               else
> +                       gatt_db_attribute_write_result(attrib, id, 0);
> +
> +               return;
> +       }
> +
> +       if (opcode == BT_ATT_OP_EXEC_WRITE_REQ)
> +               desc->authorized = false;
> +
>         if (send_write(device, attrib, desc->proxy, desc->pending_writes, id,
> -                               value, len, offset, bt_att_get_link_type(att)))
> +                       value, len, offset, bt_att_get_link_type(att), false,
> +                       false))
>                 return;
>
>  fail:
> @@ -2614,6 +2657,26 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib,
>                 goto fail;
>         }
>
> +       if (!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP))
> +               queue = chrc->pending_writes;
> +       else
> +               queue = NULL;
> +
> +       if (opcode == BT_ATT_OP_PREP_WRITE_REQ) {
> +               if (!chrc->authorized && g_dbus_proxy_get_property(chrc->proxy,
> +                                                       "Authorize", &iter))
> +                       send_write(device, attrib, chrc->proxy, queue,
> +                                       id, value, len, offset,
> +                                       bt_att_get_link_type(att), true, true);
> +               else
> +                       gatt_db_attribute_write_result(attrib, id, 0);
> +
> +               return;
> +       }
> +
> +       if (id == BT_ATT_OP_EXEC_WRITE_REQ)
> +               chrc->authorized = false;
> +

I guess you meant opcode == BT_ATT_OP_EXEC_WRITE_REQ.

>         if (chrc->write_io) {
>                 if (pipe_io_send(chrc->write_io, value, len) < 0) {
>                         error("Unable to write: %s", strerror(errno));
> @@ -2630,13 +2693,8 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib,
>                         return;
>         }
>
> -       if (!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP))
> -               queue = chrc->pending_writes;
> -       else
> -               queue = NULL;
> -
>         if (send_write(device, attrib, chrc->proxy, queue, id, value, len,
> -                                       offset, bt_att_get_link_type(att)))
> +                       offset, bt_att_get_link_type(att), false, false))
>                 return;
>
>  fail:
> diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
> index 4b554f665..cdade76f8 100644
> --- a/src/shared/gatt-server.c
> +++ b/src/shared/gatt-server.c
> @@ -1208,6 +1208,45 @@ static bool store_prep_data(struct bt_gatt_server *server,
>         return prep_data_new(server, handle, offset, length, value);
>  }
>
> +struct prep_write_complete_data {
> +       void *pdu;
> +       uint16_t length;
> +       struct bt_gatt_server *server;
> +};
> +
> +static void prep_write_complete_cb(struct gatt_db_attribute *attr, int err,
> +                                                               void *user_data)
> +{
> +       struct prep_write_complete_data *pwcd = user_data;
> +       uint16_t handle = 0;
> +       uint16_t offset;
> +
> +       handle = get_le16(pwcd->pdu);
> +
> +       if (err) {
> +               bt_att_send_error_rsp(pwcd->server->att,
> +                                       BT_ATT_OP_PREP_WRITE_REQ, handle, err);
> +               free(pwcd->pdu);
> +               free(pwcd);
> +
> +               return;
> +       }
> +
> +       offset = get_le16(pwcd->pdu + 2);
> +
> +       if (!store_prep_data(pwcd->server, handle, offset, pwcd->length - 4,
> +                                               &((uint8_t *) pwcd->pdu)[4]))
> +               bt_att_send_error_rsp(pwcd->server->att,
> +                                       BT_ATT_OP_PREP_WRITE_RSP, handle,
> +                                       BT_ATT_ERROR_INSUFFICIENT_RESOURCES);
> +
> +       bt_att_send(pwcd->server->att, BT_ATT_OP_PREP_WRITE_RSP, pwcd->pdu,
> +                                               pwcd->length, NULL, NULL, NULL);
> +
> +       free(pwcd->pdu);
> +       free(pwcd);
> +}
> +
>  static void prep_write_cb(uint8_t opcode, const void *pdu,
>                                         uint16_t length, void *user_data)
>  {
> @@ -1215,7 +1254,8 @@ static void prep_write_cb(uint8_t opcode, const void *pdu,
>         uint16_t handle = 0;
>         uint16_t offset;
>         struct gatt_db_attribute *attr;
> -       uint8_t ecode;
> +       struct prep_write_complete_data *pwcd;
> +       uint8_t ecode, status;
>
>         if (length < 4) {
>                 ecode = BT_ATT_ERROR_INVALID_PDU;
> @@ -1245,15 +1285,21 @@ static void prep_write_cb(uint8_t opcode, const void *pdu,
>         if (ecode)
>                 goto error;
>
> -       if (!store_prep_data(server, handle, offset, length - 4,
> -                                               &((uint8_t *) pdu)[4])) {
> -               ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
> -               goto error;
> -       }
> +       pwcd = new0(struct prep_write_complete_data, 1);
> +       pwcd->pdu = malloc(length);
> +       memcpy(pwcd->pdu, pdu, length);
> +       pwcd->length = length;
> +       pwcd->server = server;
>
> -       bt_att_send(server->att, BT_ATT_OP_PREP_WRITE_RSP, pdu, length, NULL,
> -                                                               NULL, NULL);
> -       return;
> +       status = gatt_db_attribute_write(attr, offset, NULL, 0,
> +                                               BT_ATT_OP_PREP_WRITE_REQ,
> +                                               server->att,
> +                                               prep_write_complete_cb, pwcd);
> +
> +       if (status)
> +               return;
> +
> +       ecode = BT_ATT_ERROR_UNLIKELY;
>
>  error:
>         bt_att_send_error_rsp(server->att, opcode, handle, ecode);
> --
> 2.13.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Luiz Augusto von Dentz
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux