Skip to content

Commit 7947e8a

Browse files
author
Scott Powell
committed
* simple_sensor: redesigned permissions
* companion: PUSH_CODE_LOGIN_SUCCESS now has extra byte in frame for ACL permissions
1 parent da8bd71 commit 7947e8a

File tree

3 files changed

+35
-26
lines changed

3 files changed

+35
-26
lines changed

examples/companion_radio/MyMesh.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
471471
i += 6; // pub_key_prefix
472472
memcpy(&out_frame[i], &tag, 4);
473473
i += 4; // NEW: include server timestamp
474+
out_frame[i++] = data[7]; // NEW (v7): ACL permissions
474475
} else {
475476
out_frame[i++] = PUSH_CODE_LOGIN_FAIL;
476477
out_frame[i++] = 0; // reserved

examples/simple_sensor/SensorMesh.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ void SensorMesh::loadContacts() {
9595
while (!full) {
9696
ContactInfo c;
9797
uint8_t pub_key[32];
98-
uint8_t unused[5];
98+
uint8_t unused[6];
9999

100100
bool success = (file.read(pub_key, 32) == 32);
101-
success = success && (file.read((uint8_t *) &c.permissions, 2) == 2);
102-
success = success && (file.read(unused, 5) == 5);
101+
success = success && (file.read((uint8_t *) &c.permissions, 1) == 1);
102+
success = success && (file.read(unused, 6) == 6);
103103
success = success && (file.read((uint8_t *)&c.out_path_len, 1) == 1);
104104
success = success && (file.read(c.out_path, 64) == 64);
105105
success = success && (file.read(c.shared_secret, PUB_KEY_SIZE) == PUB_KEY_SIZE);
@@ -131,8 +131,8 @@ void SensorMesh::saveContacts() {
131131
if (c->permissions == 0) continue; // skip deleted entries
132132

133133
bool success = (file.write(c->id.pub_key, 32) == 32);
134-
success = success && (file.write((uint8_t *) &c->permissions, 2) == 2);
135-
success = success && (file.write(unused, 5) == 5);
134+
success = success && (file.write((uint8_t *) &c->permissions, 1) == 1);
135+
success = success && (file.write(unused, 6) == 6);
136136
success = success && (file.write((uint8_t *)&c->out_path_len, 1) == 1);
137137
success = success && (file.write(c->out_path, 64) == 64);
138138
success = success && (file.write(c->shared_secret, PUB_KEY_SIZE) == PUB_KEY_SIZE);
@@ -240,20 +240,21 @@ static uint8_t putFloat(uint8_t * dest, float value, uint8_t size, uint32_t mult
240240
return size;
241241
}
242242

243-
uint8_t SensorMesh::handleRequest(uint16_t perms, uint32_t sender_timestamp, uint8_t req_type, uint8_t* payload, size_t payload_len) {
243+
uint8_t SensorMesh::handleRequest(uint8_t perms, uint32_t sender_timestamp, uint8_t req_type, uint8_t* payload, size_t payload_len) {
244244
memcpy(reply_data, &sender_timestamp, 4); // reflect sender_timestamp back in response packet (kind of like a 'tag')
245245

246246
if (req_type == REQ_TYPE_GET_TELEMETRY_DATA && (perms & PERM_GET_TELEMETRY) != 0) {
247247
telemetry.reset();
248248
telemetry.addVoltage(TELEM_CHANNEL_SELF, (float)board.getBattMilliVolts() / 1000.0f);
249249
// query other sensors -- target specific
250250
sensors.querySensors(0xFF, telemetry); // allow all telemetry permissions for admin or guest
251+
// TODO: let requester know permissions they have: telemetry.addPresence(TELEM_CHANNEL_SELF, perms);
251252

252253
uint8_t tlen = telemetry.getSize();
253254
memcpy(&reply_data[4], telemetry.getBuffer(), tlen);
254255
return 4 + tlen; // reply_len
255256
}
256-
if (req_type == REQ_TYPE_GET_AVG_MIN_MAX && (perms & PERM_GET_MIN_MAX_AVG) != 0) {
257+
if (req_type == REQ_TYPE_GET_AVG_MIN_MAX && (perms & PERM_GET_OTHER_STATS) != 0) {
257258
uint32_t start_secs_ago, end_secs_ago;
258259
memcpy(&start_secs_ago, &payload[0], 4);
259260
memcpy(&end_secs_ago, &payload[4], 4);
@@ -287,15 +288,15 @@ uint8_t SensorMesh::handleRequest(uint16_t perms, uint32_t sender_timestamp, uin
287288
}
288289
return ofs;
289290
}
290-
if (req_type == REQ_TYPE_GET_ACCESS_LIST && (perms & PERM_IS_ADMIN) != 0) {
291+
if (req_type == REQ_TYPE_GET_ACCESS_LIST && (perms & PERM_ACL_ROLE_MASK) == PERM_ACL_LEVEL3) {
291292
uint8_t res1 = payload[0]; // reserved for future (extra query params)
292293
uint8_t res2 = payload[1];
293294
if (res1 == 0 && res2 == 0) {
294295
uint8_t ofs = 4;
295-
for (int i = 0; i < num_contacts && ofs + 8 <= sizeof(reply_data) - 4; i++) {
296+
for (int i = 0; i < num_contacts && ofs + 7 <= sizeof(reply_data) - 4; i++) {
296297
auto c = &contacts[i];
297298
memcpy(&reply_data[ofs], c->id.pub_key, 6); ofs += 6; // just 6-byte pub_key prefix
298-
memcpy(&reply_data[ofs], &c->permissions, 2); ofs += 2;
299+
reply_data[ofs++] = c->permissions;
299300
}
300301
return ofs;
301302
}
@@ -337,11 +338,11 @@ ContactInfo* SensorMesh::putContact(const mesh::Identity& id) {
337338
return c;
338339
}
339340

340-
void SensorMesh::applyContactPermissions(const uint8_t* pubkey, uint16_t perms) {
341+
void SensorMesh::applyContactPermissions(const uint8_t* pubkey, uint8_t perms) {
341342
mesh::Identity id(pubkey);
342343
auto c = putContact(id);
343344

344-
if (perms == 0) { // no permissions, remove from contacts
345+
if ((perms & PERM_ACL_ROLE_MASK) == PERM_ACL_GUEST) { // guest role is not persisted in contacts
345346
memset(c, 0, sizeof(*c));
346347
} else {
347348
c->permissions = perms; // update their permissions
@@ -449,7 +450,7 @@ uint8_t SensorMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t*
449450
MESH_DEBUG_PRINTLN("Login success!");
450451
client->last_timestamp = sender_timestamp;
451452
client->last_activity = getRTCClock()->getCurrentTime();
452-
client->permissions = PERM_IS_ADMIN | PERM_RECV_ALERTS_HI | PERM_RECV_ALERTS_LO; // initially opt-in to receive alerts (can opt out)
453+
client->permissions = PERM_ACL_LEVEL3 | PERM_RECV_ALERTS_HI | PERM_RECV_ALERTS_LO; // initially opt-in to receive alerts (can opt out)
453454
memcpy(client->shared_secret, secret, PUB_KEY_SIZE);
454455

455456
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
@@ -459,7 +460,7 @@ uint8_t SensorMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t*
459460
reply_data[4] = RESP_SERVER_LOGIN_OK;
460461
reply_data[5] = 0; // NEW: recommended keep-alive interval (secs / 16)
461462
reply_data[6] = 1; // 1 = is admin
462-
reply_data[7] = 0; // FUTURE: reserved
463+
reply_data[7] = client->permissions;
463464
getRNG()->random(&reply_data[8], 4); // random blob to help packet-hash uniqueness
464465

465466
return 12; // reply length
@@ -480,7 +481,7 @@ void SensorMesh::handleCommand(uint32_t sender_timestamp, char* command, char* r
480481
}
481482

482483
// handle sensor-specific CLI commands
483-
if (memcmp(command, "setperm ", 8) == 0) { // format: setperm {pubkey-hex} {permissions-int16}
484+
if (memcmp(command, "setperm ", 8) == 0) { // format: setperm {pubkey-hex} {permissions-int8}
484485
char* hex = &command[8];
485486
char* sp = strchr(hex, ' '); // look for separator char
486487
if (sp == NULL || sp - hex != PUB_KEY_SIZE*2) {
@@ -490,7 +491,7 @@ void SensorMesh::handleCommand(uint32_t sender_timestamp, char* command, char* r
490491

491492
uint8_t pubkey[PUB_KEY_SIZE];
492493
if (mesh::Utils::fromHex(pubkey, PUB_KEY_SIZE, hex)) {
493-
uint16_t perms = atoi(sp);
494+
uint8_t perms = atoi(sp);
494495
applyContactPermissions(pubkey, perms);
495496
strcpy(reply, "OK");
496497
} else {
@@ -502,7 +503,7 @@ void SensorMesh::handleCommand(uint32_t sender_timestamp, char* command, char* r
502503
for (int i = 0; i < num_contacts; i++) {
503504
auto c = &contacts[i];
504505

505-
Serial.printf("%04X ", c->permissions);
506+
Serial.printf("%02X ", c->permissions);
506507
mesh::Utils::printHex(Serial, c->id.pub_key, PUB_KEY_SIZE);
507508
Serial.printf("\n");
508509
}

examples/simple_sensor/SensorMesh.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,29 @@
2323
#include <RTClib.h>
2424
#include <target.h>
2525

26-
#define PERM_IS_ADMIN 0x8000
27-
#define PERM_GET_TELEMETRY 0x0001
28-
#define PERM_GET_MIN_MAX_AVG 0x0002
29-
#define PERM_RECV_ALERTS_LO 0x0100 // low priority alerts
30-
#define PERM_RECV_ALERTS_HI 0x0200 // high priority alerts
26+
#define PERM_ACL_ROLE_MASK 3 // lower 2 bits
27+
#define PERM_ACL_GUEST 0
28+
#define PERM_ACL_LEVEL1 1
29+
#define PERM_ACL_LEVEL2 2
30+
#define PERM_ACL_LEVEL3 3 // admin
31+
32+
#define PERM_GET_TELEMETRY (1 << 2)
33+
#define PERM_GET_OTHER_STATS (1 << 3)
34+
#define PERM_RESERVED1 (1 << 4)
35+
#define PERM_RESERVED2 (1 << 5)
36+
#define PERM_RECV_ALERTS_LO (1 << 6) // low priority alerts
37+
#define PERM_RECV_ALERTS_HI (1 << 7) // high priority alerts
3138

3239
struct ContactInfo {
3340
mesh::Identity id;
34-
uint16_t permissions;
41+
uint8_t permissions;
3542
int8_t out_path_len;
3643
uint8_t out_path[MAX_PATH_SIZE];
3744
uint8_t shared_secret[PUB_KEY_SIZE];
3845
uint32_t last_timestamp; // by THEIR clock (transient)
3946
uint32_t last_activity; // by OUR clock (transient)
4047

41-
bool isAdmin() const { return (permissions & PERM_IS_ADMIN) != 0; }
48+
bool isAdmin() const { return (permissions & PERM_ACL_ROLE_MASK) == PERM_ACL_LEVEL3; }
4249
};
4350

4451
#ifndef FIRMWARE_BUILD_DATE
@@ -151,10 +158,10 @@ class SensorMesh : public mesh::Mesh, public CommonCLICallbacks {
151158
void loadContacts();
152159
void saveContacts();
153160
uint8_t handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data);
154-
uint8_t handleRequest(uint16_t perms, uint32_t sender_timestamp, uint8_t req_type, uint8_t* payload, size_t payload_len);
161+
uint8_t handleRequest(uint8_t perms, uint32_t sender_timestamp, uint8_t req_type, uint8_t* payload, size_t payload_len);
155162
mesh::Packet* createSelfAdvert();
156163
ContactInfo* putContact(const mesh::Identity& id);
157-
void applyContactPermissions(const uint8_t* pubkey, uint16_t perms);
164+
void applyContactPermissions(const uint8_t* pubkey, uint8_t perms);
158165

159166
void sendAlert(ContactInfo* c, Trigger* t);
160167

0 commit comments

Comments
 (0)