From 55cffc9fe253923f98f4eed82e119bc4288bb68b Mon Sep 17 00:00:00 2001 From: Roman Sukhorukov Date: Sat, 25 Jan 2025 13:01:28 +0300 Subject: [PATCH] nimble/host: Don't bypass attribute permissions when reading value for notification or indication --- nimble/host/src/ble_att_priv.h | 1 + nimble/host/src/ble_att_svr.c | 12 +++- nimble/host/src/ble_gattc.c | 112 ++++++++++++++++++--------------- 3 files changed, 70 insertions(+), 55 deletions(-) diff --git a/nimble/host/src/ble_att_priv.h b/nimble/host/src/ble_att_priv.h index 2bc3da361b..5dab1257ff 100644 --- a/nimble/host/src/ble_att_priv.h +++ b/nimble/host/src/ble_att_priv.h @@ -217,6 +217,7 @@ void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list); int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, uint16_t offset, struct os_mbuf *om, uint8_t *out_att_err); +int ble_att_svr_read_local_with_perms(uint16_t conn_handle, uint16_t attr_handle, struct os_mbuf **out_om); void ble_att_svr_reset(void); int ble_att_svr_init(void); diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index e584cae32d..be1b421e7a 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -496,7 +496,7 @@ ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, } int -ble_att_svr_read_local(uint16_t attr_handle, struct os_mbuf **out_om) +ble_att_svr_read_local_with_perms(uint16_t conn_handle, uint16_t attr_handle, struct os_mbuf **out_om) { struct os_mbuf *om; int rc; @@ -507,13 +507,13 @@ ble_att_svr_read_local(uint16_t attr_handle, struct os_mbuf **out_om) goto err; } - rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE, attr_handle, 0, om, - NULL); + rc = ble_att_svr_read_handle(conn_handle, attr_handle, 0, om, NULL); if (rc != 0) { goto err; } *out_om = om; + return 0; err: @@ -521,6 +521,12 @@ ble_att_svr_read_local(uint16_t attr_handle, struct os_mbuf **out_om) return rc; } +int +ble_att_svr_read_local(uint16_t attr_handle, struct os_mbuf **out_om) +{ + return ble_att_svr_read_local_with_perms(BLE_HS_CONN_HANDLE_NONE, attr_handle, out_om); +} + static int ble_att_svr_write(uint16_t conn_handle, struct ble_att_svr_entry *entry, uint16_t offset, struct os_mbuf **om, uint8_t *out_att_err) diff --git a/nimble/host/src/ble_gattc.c b/nimble/host/src/ble_gattc.c index 0ff4ec28e6..8e02b96e30 100644 --- a/nimble/host/src/ble_gattc.c +++ b/nimble/host/src/ble_gattc.c @@ -4368,11 +4368,27 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t chr_val_handle, rc = BLE_HS_ENOMEM; goto done; } - rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE, - chr_val_handle, 0, txom, NULL); + + rc = ble_att_svr_read_handle(conn_handle, chr_val_handle, 0, txom, NULL); if (rc != 0) { - /* Fatal error; application disallowed attribute read. */ - rc = BLE_HS_EAPP; + switch (rc) { + case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC): + rc = BLE_HS_EENCRYPT; + break; + + case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN): + rc = BLE_HS_EAUTHEN; + break; + + case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR): + rc = BLE_HS_EAUTHOR; + break; + + default: + /* Fatal error; application disallowed attribute read. */ + rc = BLE_HS_EAPP; + break; + } goto done; } } @@ -4437,43 +4453,41 @@ ble_gatts_notify_multiple_custom(uint16_t conn_handle, struct os_mbuf *txom; struct ble_hs_conn *conn; - txom = ble_hs_mbuf_att_pkt(); - if (txom == NULL) { - return BLE_HS_ENOMEM; - } + BLE_HS_LOG_DEBUG("conn_handle %d\n", conn_handle); conn = ble_hs_conn_find(conn_handle); if (conn == NULL) { return BLE_HS_ENOTCONN; } - /* Read missing values */ - for (i = 0; i < chr_count; i++) { - if (tuples->handle == 0) { - rc = BLE_HS_EINVAL; - goto done; - } - if (tuples[i].value == NULL) { - rc = ble_att_svr_read_local(tuples[i].handle, &tuples[i].value); + BLE_HS_LOG_DEBUG("ble_gatts_notify_multiple: peer_cl_sup_feat %d\n", + conn->bhc_gatt_svr.peer_cl_sup_feat[0]); + + /* If peer does not support fall back to multiple single value Notifications */ + if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & 0x04) == 0) { + for (i = 0; i < chr_count; i++) { + rc = ble_gatts_notify(conn_handle, tuples[i].handle); if (rc != 0) { goto done; } } + + return 0; } - /* If peer does not support fall back to multiple single value - * Notifications */ - if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & 0x04) == 0) { - for (i = 0; i < chr_count; i++) { - rc = ble_att_clt_tx_notify(conn_handle, tuples[chr_count].handle, - tuples[chr_count].value); + txom = ble_hs_mbuf_att_pkt(); + if (txom == NULL) { + return BLE_HS_ENOMEM; + } + + for (i = 0; i < chr_count; i++) { + if (tuples[i].value == NULL) { + rc = ble_att_svr_read_local_with_perms(conn_handle, tuples[i].handle, &tuples[i].value); if (rc != 0) { goto done; } } - } - for (i = 0; i < chr_count; i++) { if (txom->om_len + tuples[i].value->om_len > mtu && cur_chr_cnt < 2) { rc = ble_att_clt_tx_notify(conn_handle, tuples[i].handle, tuples[i].value); @@ -4520,28 +4534,9 @@ ble_gatts_notify_multiple(uint16_t conn_handle, #if !MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) return BLE_HS_ENOTSUP; #endif - int rc, i; - struct ble_gatt_notif tuples[num_handles]; - struct ble_hs_conn *conn; - - BLE_HS_LOG_DEBUG("conn_handle %d\n", conn_handle); - conn = ble_hs_conn_find(conn_handle); - if (conn == NULL) { - return BLE_HS_ENOTCONN; - } - /** Skip sending to client that doesn't support this feature */ - BLE_HS_LOG_DEBUG("ble_gatts_notify_multiple: peer_cl_sup_feat %d\n", - conn->bhc_gatt_svr.peer_cl_sup_feat[0]); - if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & 0x04) == 0) { - for (i = 0; i < num_handles; i++) { - rc = ble_gatts_notify(conn_handle, chr_val_handles[i]); - if (rc != 0) { - return rc; - } - } - return 0; - } + int i; + struct ble_gatt_notif tuples[num_handles]; for (i = 0; i < num_handles; i++) { tuples[i].handle = chr_val_handles[i]; @@ -4549,8 +4544,7 @@ ble_gatts_notify_multiple(uint16_t conn_handle, BLE_HS_LOG(DEBUG, "handle 0x%02x\n", tuples[i].handle); } - rc = ble_gatts_notify_multiple_custom(conn_handle, num_handles, tuples); - return rc; + return ble_gatts_notify_multiple_custom(conn_handle, num_handles, tuples); } /** @@ -4677,12 +4671,26 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, goto done; } - rc = ble_att_svr_read_handle(BLE_HS_CONN_HANDLE_NONE, chr_val_handle, - 0, txom, NULL); + rc = ble_att_svr_read_handle(conn_handle, chr_val_handle, 0, txom, NULL); if (rc != 0) { - /* Fatal error; application disallowed attribute read. */ - BLE_HS_DBG_ASSERT(0); - rc = BLE_HS_EAPP; + switch (rc) { + case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_ENC): + rc = BLE_HS_EENCRYPT; + break; + + case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHEN): + rc = BLE_HS_EAUTHEN; + break; + + case BLE_HS_ATT_ERR(BLE_ATT_ERR_INSUFFICIENT_AUTHOR): + rc = BLE_HS_EAUTHOR; + break; + + default: + /* Fatal error; application disallowed attribute read. */ + rc = BLE_HS_EAPP; + break; + } goto done; } }