Bluetooth: Check GATT attribute permissions
This checks attribute permission returning an error in case they don't match. Change-Id: I56a85ad594cb1ac535b03cdbceb43af84dc6604f Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
8c66427b05
commit
58791718e1
1 changed files with 59 additions and 3 deletions
|
@ -54,6 +54,19 @@
|
|||
#define BT_DBG(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define BT_GATT_PERM_READ_MASK (BT_GATT_PERM_READ | \
|
||||
BT_GATT_PERM_READ_ENCRYPT | \
|
||||
BT_GATT_PERM_READ_AUTHEN | \
|
||||
BT_GATT_PERM_AUTHOR)
|
||||
#define BT_GATT_PERM_WRITE_MASK (BT_GATT_PERM_WRITE | \
|
||||
BT_GATT_PERM_WRITE_ENCRYPT | \
|
||||
BT_GATT_PERM_WRITE_AUTHEN | \
|
||||
BT_GATT_PERM_AUTHOR)
|
||||
#define BT_GATT_PERM_ENCRYPT_MASK (BT_GATT_PERM_READ_ENCRYPT | \
|
||||
BT_GATT_PERM_WRITE_ENCRYPT)
|
||||
#define BT_GATT_PERM_AUTHEN_MASK (BT_GATT_PERM_READ_AUTHEN | \
|
||||
BT_GATT_PERM_WRITE_AUTHEN)
|
||||
|
||||
/* ATT channel specific context */
|
||||
struct bt_att {
|
||||
/* The connection this context is associated with */
|
||||
|
@ -527,11 +540,41 @@ static void att_read_type_req(struct bt_conn *conn, struct bt_buf *data)
|
|||
att_read_type_rsp(conn, &uuid, start_handle, end_handle);
|
||||
}
|
||||
|
||||
static uint8_t check_perm(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
uint8_t mask)
|
||||
{
|
||||
if ((mask & BT_GATT_PERM_READ) && !(attr->perm & BT_GATT_PERM_READ)) {
|
||||
return BT_ATT_ERR_READ_NOT_PERMITTED;
|
||||
}
|
||||
|
||||
if ((mask & BT_GATT_PERM_WRITE) && !(attr->perm & BT_GATT_PERM_WRITE)) {
|
||||
return BT_ATT_ERR_READ_NOT_PERMITTED;
|
||||
}
|
||||
|
||||
mask &= attr->perm;
|
||||
if (mask & BT_GATT_PERM_AUTHEN_MASK) {
|
||||
/* TODO: Check conn authentication */
|
||||
return BT_ATT_ERR_AUTHENTICATION;
|
||||
}
|
||||
|
||||
if (mask & BT_GATT_PERM_ENCRYPT_MASK) {
|
||||
/* TODO: Check conn encryption */
|
||||
return BT_ATT_ERR_INSUFFICIENT_ENCRYPTION;
|
||||
}
|
||||
|
||||
if (mask & BT_GATT_PERM_AUTHOR) {
|
||||
return BT_ATT_ERR_AUTHORIZATION;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct read_data {
|
||||
struct bt_conn *conn;
|
||||
uint16_t offset;
|
||||
struct bt_buf *buf;
|
||||
struct bt_att_read_rsp *rsp;
|
||||
uint8_t err;
|
||||
};
|
||||
|
||||
static uint8_t read_cb(const struct bt_gatt_attr *attr, void *user_data)
|
||||
|
@ -545,7 +588,13 @@ static uint8_t read_cb(const struct bt_gatt_attr *attr, void *user_data)
|
|||
data->rsp = bt_buf_add(data->buf, sizeof(*data->rsp));
|
||||
|
||||
if (!attr->read) {
|
||||
/* TODO: Respond with BT_ATT_ERR_READ_NOT_PERMITTED */
|
||||
data->err = BT_ATT_ERR_READ_NOT_PERMITTED;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
/* Check attribute permissions */
|
||||
data->err = check_perm(data->conn, attr, BT_GATT_PERM_READ_MASK);
|
||||
if (data->err) {
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
|
@ -585,9 +634,10 @@ static void att_read_rsp(struct bt_conn *conn, uint8_t op, uint8_t rsp,
|
|||
|
||||
bt_gatt_foreach_attr(handle, handle, read_cb, &data);
|
||||
|
||||
if (!data.rsp) {
|
||||
/* In case of error discard data and respond with an error */
|
||||
if (data.err) {
|
||||
bt_buf_put(data.buf);
|
||||
send_err_rsp(conn, op, handle, BT_ATT_ERR_INVALID_HANDLE);
|
||||
send_err_rsp(conn, op, handle, data.err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -822,6 +872,12 @@ static uint8_t write_cb(const struct bt_gatt_attr *attr, void *user_data)
|
|||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
/* Check attribute permissions */
|
||||
data->err = check_perm(data->conn, attr, BT_GATT_PERM_WRITE_MASK);
|
||||
if (data->err) {
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
/* Read attribute value and store in the buffer */
|
||||
write = attr->write(&data->conn->dst, attr, data->value, data->len,
|
||||
data->offset);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue