Skip to content

Commit 3358783

Browse files
author
Scott Powell
committed
* sensor: "setperm {pubkey-hex} 0" command can now remove by partial pubkey
* sensor: login with blank password now just checks if sender is in ACL, and returns permissions (if so)
1 parent 5881b04 commit 3358783

File tree

2 files changed

+64
-29
lines changed

2 files changed

+64
-29
lines changed

examples/simple_sensor/SensorMesh.cpp

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,13 @@ mesh::Packet* SensorMesh::createSelfAdvert() {
316316
return createAdvert(self_id, app_data, app_data_len);
317317
}
318318

319+
ContactInfo* SensorMesh::getContact(const uint8_t* pubkey, int key_len) {
320+
for (int i = 0; i < num_contacts; i++) {
321+
if (memcmp(pubkey, contacts[i].id.pub_key, key_len) == 0) return &contacts[i]; // already known
322+
}
323+
return NULL; // not found
324+
}
325+
319326
ContactInfo* SensorMesh::putContact(const mesh::Identity& id, uint8_t init_perms) {
320327
uint32_t min_time = 0xFFFFFFFF;
321328
ContactInfo* oldest = &contacts[MAX_CONTACTS - 1];
@@ -340,17 +347,29 @@ ContactInfo* SensorMesh::putContact(const mesh::Identity& id, uint8_t init_perms
340347
return c;
341348
}
342349

343-
void SensorMesh::applyContactPermissions(const uint8_t* pubkey, uint8_t perms) {
344-
mesh::Identity id(pubkey);
345-
auto c = putContact(id, 0);
346-
350+
bool SensorMesh::applyContactPermissions(const uint8_t* pubkey, int key_len, uint8_t perms) {
351+
ContactInfo* c;
347352
if ((perms & PERM_ACL_ROLE_MASK) == PERM_ACL_GUEST) { // guest role is not persisted in contacts
348-
memset(c, 0, sizeof(*c));
353+
c = getContact(pubkey, key_len);
354+
if (c == NULL) return false; // partial pubkey not found
355+
356+
num_contacts--; // delete from contacts[]
357+
int i = c - contacts;
358+
while (i < num_contacts) {
359+
contacts[i] = contacts[i + 1];
360+
i++;
361+
}
349362
} else {
363+
if (key_len < PUB_KEY_SIZE) return false; // need complete pubkey when adding/modifying
364+
365+
mesh::Identity id(pubkey);
366+
c = putContact(id, 0);
367+
350368
c->permissions = perms; // update their permissions
351369
self_id.calcSharedSecret(c->shared_secret, pubkey);
352370
}
353371
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); // trigger saveContacts()
372+
return true;
354373
}
355374

356375
void SensorMesh::sendAlert(ContactInfo* c, Trigger* t) {
@@ -436,32 +455,43 @@ int SensorMesh::getAGCResetInterval() const {
436455
}
437456

438457
uint8_t SensorMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data) {
439-
if (strcmp((char *) data, _prefs.password) != 0) { // check for valid password
440-
#if MESH_DEBUG
441-
MESH_DEBUG_PRINTLN("Invalid password: %s", &data[4]);
442-
#endif
443-
return 0;
444-
}
458+
ContactInfo* client;
459+
if (data[0] == 0) { // blank password, just check if sender is in ACL
460+
client = getContact(sender.pub_key, PUB_KEY_SIZE);
461+
if (client == NULL) {
462+
#if MESH_DEBUG
463+
MESH_DEBUG_PRINTLN("Login, sender not in ACL");
464+
#endif
465+
return 0;
466+
}
467+
} else {
468+
if (strcmp((char *) data, _prefs.password) != 0) { // check for valid admin password
469+
#if MESH_DEBUG
470+
MESH_DEBUG_PRINTLN("Invalid password: %s", &data[4]);
471+
#endif
472+
return 0;
473+
}
445474

446-
auto client = putContact(sender, PERM_RECV_ALERTS_HI | PERM_RECV_ALERTS_LO); // add to contacts (if not already known)
447-
if (sender_timestamp <= client->last_timestamp) {
448-
MESH_DEBUG_PRINTLN("Possible login replay attack!");
449-
return 0; // FATAL: client table is full -OR- replay attack
450-
}
475+
client = putContact(sender, PERM_RECV_ALERTS_HI | PERM_RECV_ALERTS_LO); // add to contacts (if not already known)
476+
if (sender_timestamp <= client->last_timestamp) {
477+
MESH_DEBUG_PRINTLN("Possible login replay attack!");
478+
return 0; // FATAL: client table is full -OR- replay attack
479+
}
451480

452-
MESH_DEBUG_PRINTLN("Login success!");
453-
client->last_timestamp = sender_timestamp;
454-
client->last_activity = getRTCClock()->getCurrentTime();
455-
client->permissions |= PERM_ACL_ADMIN;
456-
memcpy(client->shared_secret, secret, PUB_KEY_SIZE);
481+
MESH_DEBUG_PRINTLN("Login success!");
482+
client->last_timestamp = sender_timestamp;
483+
client->last_activity = getRTCClock()->getCurrentTime();
484+
client->permissions |= PERM_ACL_ADMIN;
485+
memcpy(client->shared_secret, secret, PUB_KEY_SIZE);
457486

458-
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
487+
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
488+
}
459489

460490
uint32_t now = getRTCClock()->getCurrentTimeUnique();
461491
memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp
462492
reply_data[4] = RESP_SERVER_LOGIN_OK;
463493
reply_data[5] = 0; // NEW: recommended keep-alive interval (secs / 16)
464-
reply_data[6] = 1; // 1 = is admin
494+
reply_data[6] = client->isAdmin() ? 1 : 0;
465495
reply_data[7] = client->permissions;
466496
getRNG()->random(&reply_data[8], 4); // random blob to help packet-hash uniqueness
467497

@@ -486,16 +516,20 @@ void SensorMesh::handleCommand(uint32_t sender_timestamp, char* command, char* r
486516
if (memcmp(command, "setperm ", 8) == 0) { // format: setperm {pubkey-hex} {permissions-int8}
487517
char* hex = &command[8];
488518
char* sp = strchr(hex, ' '); // look for separator char
489-
if (sp == NULL || sp - hex != PUB_KEY_SIZE*2) {
490-
strcpy(reply, "Err - bad pubkey len");
519+
if (sp == NULL) {
520+
strcpy(reply, "Err - bad params");
491521
} else {
492522
*sp++ = 0; // replace space with null terminator
493523

494524
uint8_t pubkey[PUB_KEY_SIZE];
495-
if (mesh::Utils::fromHex(pubkey, PUB_KEY_SIZE, hex)) {
525+
int hex_len = min(sp - hex, PUB_KEY_SIZE*2);
526+
if (mesh::Utils::fromHex(pubkey, hex_len / 2, hex)) {
496527
uint8_t perms = atoi(sp);
497-
applyContactPermissions(pubkey, perms);
498-
strcpy(reply, "OK");
528+
if (applyContactPermissions(pubkey, hex_len / 2, perms)) {
529+
strcpy(reply, "OK");
530+
} else {
531+
strcpy(reply, "Err - invalid params");
532+
}
499533
} else {
500534
strcpy(reply, "Err - bad pubkey");
501535
}

examples/simple_sensor/SensorMesh.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ class SensorMesh : public mesh::Mesh, public CommonCLICallbacks {
160160
uint8_t handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data);
161161
uint8_t handleRequest(uint8_t perms, uint32_t sender_timestamp, uint8_t req_type, uint8_t* payload, size_t payload_len);
162162
mesh::Packet* createSelfAdvert();
163+
ContactInfo* getContact(const uint8_t* pubkey, int key_len);
163164
ContactInfo* putContact(const mesh::Identity& id, uint8_t init_perms);
164-
void applyContactPermissions(const uint8_t* pubkey, uint8_t perms);
165+
bool applyContactPermissions(const uint8_t* pubkey, int key_len, uint8_t perms);
165166

166167
void sendAlert(ContactInfo* c, Trigger* t);
167168

0 commit comments

Comments
 (0)