Skip to content

Commit 3b12f5a

Browse files
SumeetSingh19piotrnarajowski
authored andcommitted
nimble/host: add support for asynchronous authorization
This introduces handling authorization in nimble. Each operation on characteristic that has authorize flags will require authorization. Application can respond to GAP authorization event with accept, reject or pending response. The latter response should trigger user action to either accept or reject request and finish handling att request. This is done on top of PR #1668 by SumeetSingh19
1 parent 5ab995f commit 3b12f5a

File tree

7 files changed

+175
-3
lines changed

7 files changed

+175
-3
lines changed

apps/bleprph/src/main.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,14 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg)
270270
phy_update(event->phy_updated.tx_phy);
271271
return 0;
272272
#endif
273+
274+
case BLE_GAP_EVENT_AUTHORIZE:
275+
MODLOG_DFLT(INFO, "authorize event: conn_handle=%d attr_handle=%d is_read=%d",
276+
event->authorize.conn_handle,
277+
event->authorize.attr_handle,
278+
event->authorize.access_opcode);
279+
/* Always reject for async authorization testing */
280+
return BLE_GAP_AUTHORIZE_REJECT;
273281
}
274282

275283
return 0;

nimble/host/include/host/ble_gap.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ struct hci_conn_update;
261261
/** GAP event: BIG (Broadcast Isochronous Group) information report */
262262
#define BLE_GAP_EVENT_BIGINFO_REPORT 30
263263

264+
/** GAP event: Authorization request for GATT operations */
265+
#define BLE_GAP_EVENT_AUTHORIZE 31
266+
264267
/** @} */
265268

266269
/**
@@ -295,6 +298,28 @@ struct hci_conn_update;
295298

296299
/** @} */
297300

301+
/**
302+
* @defgroup GAP Authorize event possible responses.
303+
* @{
304+
*/
305+
306+
/** GAP Authorize event response: reject */
307+
#define BLE_GAP_AUTHORIZE_REJECT 0
308+
309+
/** GAP Authorize event response: accept */
310+
#define BLE_GAP_AUTHORIZE_ACCEPT 1
311+
312+
/** GAP Authorize event response: pending */
313+
#define BLE_GAP_AUTHORIZE_PENDING 2
314+
315+
/** @} */
316+
317+
///** GATT Access Opcodes operations */
318+
//enum acces_op {
319+
// GATT_ACCESS_OP_READ_CHR = 0,
320+
// GATT_ACCESS_OP_WRITE_CHR,
321+
//};
322+
298323
/** Connection security state */
299324
struct ble_gap_sec_state {
300325
/** If connection is encrypted */
@@ -1308,6 +1333,29 @@ struct ble_gap_event {
13081333
uint8_t length;
13091334
} unhandled_hci;
13101335
#endif
1336+
1337+
/**
1338+
* GATT Authorization Event. Ask the user to authorize a GATT
1339+
* read/write operation.
1340+
*
1341+
* Valid for the following event types:
1342+
* o BLE_GAP_EVENT_AUTHORIZE
1343+
*
1344+
* Valid responses from user:
1345+
* o BLE_GAP_AUTHORIZE_ACCEPT
1346+
* o BLE_GAP_AUTHORIZE_REJECT
1347+
* o BLE_GAP_AUTHORIZE_PENDING
1348+
*/
1349+
struct {
1350+
/* Connection Handle */
1351+
uint16_t conn_handle;
1352+
1353+
/* Attribute handle of the attribute being accessed. */
1354+
uint16_t attr_handle;
1355+
1356+
/* ATT access opcode. */
1357+
uint8_t access_opcode;
1358+
} authorize;
13111359
};
13121360
};
13131361

nimble/host/include/host/ble_hs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ extern "C" {
159159
/** Operation stalled. */
160160
#define BLE_HS_ESTALLED 31
161161

162+
/** Operation pending. */
163+
#define BLE_HS_EPENDING 32
164+
162165
/** Error base for ATT errors */
163166
#define BLE_HS_ERR_ATT_BASE 0x100
164167

nimble/host/src/ble_att_priv.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ struct ble_att_svr_conn {
125125
ble_npl_time_t basc_prep_timeout_at;
126126
};
127127

128+
struct pending_attr {
129+
SLIST_ENTRY(pending_attr) next;
130+
uint16_t conn_handle;
131+
struct ble_att_svr_entry *entry;
132+
uint16_t offset;
133+
struct os_mbuf *om;
134+
uint16_t opcode;
135+
};
136+
137+
SLIST_HEAD(pending_attr_list_head, pending_attr);
138+
extern struct pending_attr_list_head pending_attr_list;
139+
128140
/**
129141
* Handles a host attribute request.
130142
*

nimble/host/src/ble_att_svr.c

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,46 @@ ble_att_svr_entry_free(struct ble_att_svr_entry *entry)
8181
os_memblock_put(&ble_att_svr_entry_pool, entry);
8282
}
8383

84+
struct pending_attr_list_head pending_attr_list =
85+
SLIST_HEAD_INITIALIZER(pending_attr_list);
86+
87+
static void pending_att_prepare(uint16_t conn_handle,
88+
struct ble_att_svr_entry *entry,
89+
uint16_t offset, struct os_mbuf *om,
90+
uint8_t access_opcode, uint8_t att_opcode)
91+
{
92+
struct pending_attr *pending;
93+
struct pending_attr *e;
94+
struct pending_attr *last;
95+
96+
pending = malloc(sizeof(struct pending_attr));
97+
98+
memset(pending, 0, sizeof(*pending));
99+
100+
pending->conn_handle = conn_handle;
101+
pending->entry = (struct ble_att_svr_entry *) entry;
102+
pending->offset = offset;
103+
pending->om = om;
104+
pending->access_opcode = access_opcode;
105+
pending->att_opcode = att_opcode;
106+
ble_hs_lock();
107+
if (SLIST_EMPTY(&pending_attr_list)) {
108+
SLIST_INSERT_HEAD(&pending_attr_list, pending, next);
109+
} else {
110+
last = NULL;
111+
/* find last and insert at tail */
112+
SLIST_FOREACH(e, &pending_attr_list, next) {
113+
if ((SLIST_NEXT(e, next) = NULL)) {
114+
last = e;
115+
SLIST_INSERT_AFTER(last, pending, next);
116+
}
117+
}
118+
}
119+
ble_hs_unlock();
120+
121+
return;
122+
}
123+
84124
/**
85125
* Allocate the next handle id and return it.
86126
*
@@ -333,7 +373,19 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read,
333373
}
334374

335375
if (author) {
336-
/* XXX: Prompt user for authorization. */
376+
rc = ble_gap_authorize_event(conn_handle, entry->ha_handle_id,
377+
is_read);
378+
switch (rc) {
379+
case BLE_GAP_AUTHORIZE_ACCEPT:
380+
break;
381+
382+
case BLE_GAP_AUTHORIZE_REJECT:
383+
*out_att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHOR;
384+
return BLE_HS_ATT_ERR(*out_att_err);
385+
386+
case BLE_GAP_AUTHORIZE_PENDING:
387+
return BLE_HS_EPENDING;
388+
}
337389
}
338390

339391
return 0;
@@ -406,6 +458,11 @@ ble_att_svr_read(uint16_t conn_handle,
406458

407459
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
408460
rc = ble_att_svr_check_perms(conn_handle, 1, entry, &att_err);
461+
if (rc == BLE_HS_EPENDING) {
462+
pending_att_prepare(conn_handle, entry, offset, om,
463+
BLE_ATT_ACCESS_OP_READ, BLE_ATT_OP_READ_REQ);
464+
return rc;
465+
}
409466
if (rc != 0) {
410467
goto err;
411468
}
@@ -532,6 +589,11 @@ ble_att_svr_write(uint16_t conn_handle, struct ble_att_svr_entry *entry,
532589

533590
if (conn_handle != BLE_HS_CONN_HANDLE_NONE) {
534591
rc = ble_att_svr_check_perms(conn_handle, 0, entry, &att_err);
592+
if (rc == BLE_HS_EPENDING) {
593+
pending_att_prepare(conn_handle, entry, offset, *om,
594+
BLE_ATT_ACCESS_OP_WRITE, BLE_ATT_OP_WRITE_REQ);
595+
return rc;
596+
}
535597
if (rc != 0) {
536598
goto done;
537599
}
@@ -621,7 +683,7 @@ ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txo
621683
* of the error message's attribute handle
622684
* field.
623685
*/
624-
static int
686+
int
625687
ble_att_svr_tx_rsp(uint16_t conn_handle, uint16_t cid, int hs_status, struct os_mbuf *om,
626688
uint8_t att_op, uint8_t err_status, uint16_t err_handle)
627689
{
@@ -1502,6 +1564,9 @@ ble_att_svr_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom)
15021564
}
15031565

15041566
rc = ble_att_svr_read_handle(conn_handle, err_handle, 0, txom, &att_err);
1567+
if (rc == BLE_HS_EPENDING) {
1568+
return rc;
1569+
}
15051570
if (rc != 0) {
15061571
goto done;
15071572
}
@@ -1553,6 +1618,9 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rx
15531618

15541619
rc = ble_att_svr_read_handle(conn_handle, err_handle, offset,
15551620
txom, &att_err);
1621+
if (rc == BLE_HS_EPENDING) {
1622+
return rc;
1623+
}
15561624
if (rc != 0) {
15571625
goto done;
15581626
}
@@ -2068,7 +2136,7 @@ ble_att_svr_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbu
20682136
return rc;
20692137
}
20702138

2071-
static int
2139+
int
20722140
ble_att_svr_build_write_rsp(struct os_mbuf **rxom, struct os_mbuf **out_txom,
20732141
uint8_t *att_err)
20742142
{
@@ -2135,6 +2203,9 @@ ble_att_svr_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom)
21352203
os_mbuf_adj(*rxom, sizeof(*req));
21362204

21372205
rc = ble_att_svr_write_handle(conn_handle, handle, 0, rxom, &att_err);
2206+
if (rc == BLE_HS_EPENDING) {
2207+
return rc;
2208+
}
21382209
if (rc != 0) {
21392210
goto done;
21402211
}
@@ -2481,6 +2552,11 @@ ble_att_svr_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **r
24812552

24822553
/* <1>, <2>, <4>, <6> */
24832554
rc = ble_att_svr_check_perms(conn_handle, 0, attr_entry, &att_err);
2555+
if (rc == BLE_HS_EPENDING) {
2556+
pending_att_prepare(conn_handle, attr_entry, 0, txom,
2557+
0, BLE_ATT_OP_PREP_WRITE_REQ);
2558+
return rc;
2559+
}
24842560
if (rc != 0) {
24852561
goto done;
24862562
}
@@ -2942,6 +3018,7 @@ ble_att_svr_init(void)
29423018

29433019
STAILQ_INIT(&ble_att_svr_list);
29443020
STAILQ_INIT(&ble_att_svr_hidden_list);
3021+
SLIST_INIT(&pending_attr_list);
29453022

29463023
ble_att_svr_id = 0;
29473024

nimble/host/src/ble_gap.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6864,6 +6864,29 @@ ble_gap_unhandled_hci_event(bool is_le_meta, bool is_vs, const void *buf,
68646864
}
68656865
#endif
68666866

6867+
int
6868+
ble_gap_authorize_event(uint16_t conn_handle, uint16_t attr_handle,
6869+
int is_read)
6870+
{
6871+
#if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
6872+
struct ble_gap_event event;
6873+
uint8_t op;
6874+
int rc;
6875+
6876+
op = is_read ? BLE_ATT_ACCESS_OP_READ : BLE_ATT_ACCESS_OP_WRITE;
6877+
6878+
memset(&event, 0, sizeof event);
6879+
event.type = BLE_GAP_EVENT_AUTHORIZE;
6880+
event.authorize.conn_handle = conn_handle;
6881+
event.authorize.attr_handle = attr_handle;
6882+
event.authorize.access_opcode = op;
6883+
6884+
rc = ble_gap_call_conn_event_cb(&event, conn_handle);
6885+
return rc;
6886+
#endif
6887+
return BLE_GAP_AUTHORIZE_REJECT;
6888+
}
6889+
68676890
/*****************************************************************************
68686891
* $preempt *
68696892
*****************************************************************************/

nimble/host/src/ble_gap_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ void ble_gap_pairing_complete_event(uint16_t conn_handle, int status);
144144
void ble_gap_unhandled_hci_event(bool is_le_meta, bool is_vs, const void *buf,
145145
uint8_t len);
146146
int ble_gap_master_in_progress(void);
147+
int ble_gap_authorize_event(uint16_t conn_handle, uint16_t attr_handle, int is_read);
147148

148149
void ble_gap_preempt(void);
149150
void ble_gap_preempt_done(void);

0 commit comments

Comments
 (0)