* new "set guest.password .." CLI command

This commit is contained in:
Scott Powell 2025-02-10 16:36:14 +11:00
parent 8ab1d495e2
commit 42f2c1ece5
2 changed files with 57 additions and 39 deletions

View file

@ -106,7 +106,8 @@ struct ClientInfo {
mesh::Identity id;
uint32_t last_timestamp;
uint8_t secret[PUB_KEY_SIZE];
int out_path_len;
bool is_admin;
int8_t out_path_len;
uint8_t out_path[MAX_PATH_SIZE];
};
@ -125,6 +126,7 @@ struct NodePrefs { // persisted to file
uint8_t disable_fwd;
uint8_t advert_interval; // minutes / 2
uint8_t unused;
char guest_password[16];
};
class MyMesh : public mesh::Mesh {
@ -157,14 +159,7 @@ class MyMesh : public mesh::Mesh {
memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp
switch (payload[0]) {
case CMD_GET_STATS: {
uint32_t max_age_secs;
if (payload_len >= 5) {
memcpy(&max_age_secs, &payload[1], 4); // first param in request pkt
} else {
max_age_secs = 12*60*60; // default, 12 hours
}
case CMD_GET_STATS: { // guests can also access this now
RepeaterStats stats;
stats.batt_milli_volts = board.getBattMilliVolts();
stats.curr_tx_queue_len = _mgr->getOutboundCount();
@ -228,38 +223,47 @@ protected:
uint32_t timestamp;
memcpy(&timestamp, data, 4);
bool is_admin;
if (memcmp(&data[4], _prefs.password, strlen(_prefs.password)) == 0) { // check for valid password
auto client = putClient(sender); // add to known clients (if not already known)
if (client == NULL || timestamp <= client->last_timestamp) {
MESH_DEBUG_PRINTLN("Client table full, or replay attack!");
return; // FATAL: client table is full -OR- replay attack
}
is_admin = true;
} else if (memcmp(&data[4], _prefs.guest_password, strlen(_prefs.guest_password)) == 0) { // check guest password
is_admin = false;
} else {
#if MESH_DEBUG
data[len] = 0; // ensure null terminator
MESH_DEBUG_PRINTLN("Invalid password: %s", &data[4]);
#endif
return;
}
MESH_DEBUG_PRINTLN("Login success!");
client->last_timestamp = timestamp;
auto client = putClient(sender); // add to known clients (if not already known)
if (client == NULL || timestamp <= client->last_timestamp) {
MESH_DEBUG_PRINTLN("Client table full, or replay attack!");
return; // FATAL: client table is full -OR- replay attack
}
uint32_t now = getRTCClock()->getCurrentTime();
memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp
memcpy(&reply_data[4], "OK", 2);
MESH_DEBUG_PRINTLN("Login success!");
client->last_timestamp = timestamp;
client->is_admin = is_admin;
if (packet->isRouteFlood()) {
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
mesh::Packet* path = createPathReturn(sender, client->secret, packet->path, packet->path_len,
PAYLOAD_TYPE_RESPONSE, reply_data, 4 + 2);
if (path) sendFlood(path);
} else {
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, client->secret, reply_data, 4 + 2);
if (reply) {
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
sendDirect(reply, client->out_path, client->out_path_len);
} else {
sendFlood(reply);
}
uint32_t now = getRTCClock()->getCurrentTime();
memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp
memcpy(&reply_data[4], "OK", 2);
if (packet->isRouteFlood()) {
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
mesh::Packet* path = createPathReturn(sender, client->secret, packet->path, packet->path_len,
PAYLOAD_TYPE_RESPONSE, reply_data, 4 + 2);
if (path) sendFlood(path);
} else {
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, client->secret, reply_data, 4 + 2);
if (reply) {
if (client->out_path_len >= 0) { // we have an out_path, so send DIRECT
sendDirect(reply, client->out_path, client->out_path_len);
} else {
sendFlood(reply);
}
}
} else {
data[4+8] = 0; // ensure null terminator
MESH_DEBUG_PRINTLN("Incorrect password: %s", &data[4]);
}
}
}
@ -321,7 +325,7 @@ protected:
} else {
MESH_DEBUG_PRINTLN("onPeerDataRecv: possible replay attack detected");
}
} else if (type == PAYLOAD_TYPE_TXT_MSG && len > 5) { // a CLI command
} else if (type == PAYLOAD_TYPE_TXT_MSG && len > 5 && client->is_admin) { // a CLI command
uint32_t sender_timestamp;
memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong)
uint flags = (data[4] >> 2); // message attempt number, and other flags
@ -527,6 +531,11 @@ public:
savePrefs();
strcpy(reply, "OK");
}
} else if (memcmp(config, "guest.password ", 15) == 0) {
strncpy(_prefs.guest_password, &config[15], sizeof(_prefs.guest_password)-1);
_prefs.guest_password[sizeof(_prefs.guest_password)-1] = 0; // truncate if necessary
savePrefs();
strcpy(reply, "OK");
} else if (memcmp(config, "name ", 5) == 0) {
strncpy(_prefs.node_name, &config[5], sizeof(_prefs.node_name)-1);
_prefs.node_name[sizeof(_prefs.node_name)-1] = 0; // truncate if nec

View file

@ -142,6 +142,7 @@ struct NodePrefs { // persisted to file
uint8_t disable_fwd;
uint8_t advert_interval; // minutes
uint8_t unused;
char guest_password[16];
};
class MyMesh : public mesh::Mesh {
@ -291,12 +292,11 @@ protected:
is_admin = true;
} else {
is_admin = false;
#ifdef ROOM_PASSWORD
if (memcmp(&data[8], ROOM_PASSWORD, strlen(ROOM_PASSWORD)) != 0) { // check the room/public password
int len = strlen(_prefs.guest_password);
if (len > 0 && memcmp(&data[8], _prefs.guest_password, len) != 0) { // check the room/public password
MESH_DEBUG_PRINTLN("Incorrect room password");
return; // no response. Client will timeout
}
#endif
}
auto client = putClient(sender); // add to known clients (if not already known)
@ -524,6 +524,10 @@ public:
_prefs.tx_power_dbm = LORA_TX_POWER;
_prefs.disable_fwd = 1;
_prefs.advert_interval = 2; // default to 2 minutes for NEW installs
#ifdef ROOM_PASSWORD
strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password)-1);
_prefs.guest_password[sizeof(_prefs.guest_password)-1] = 0; // truncate if necessary
#endif
num_clients = 0;
next_post_idx = 0;
@ -625,6 +629,11 @@ public:
savePrefs();
strcpy(reply, "OK");
}
} else if (memcmp(config, "guest.password ", 15) == 0) {
strncpy(_prefs.guest_password, &config[15], sizeof(_prefs.guest_password)-1);
_prefs.guest_password[sizeof(_prefs.guest_password)-1] = 0; // truncate if necessary
savePrefs();
strcpy(reply, "OK");
} else if (memcmp(config, "name ", 5) == 0) {
strncpy(_prefs.node_name, &config[5], sizeof(_prefs.node_name)-1);
_prefs.node_name[sizeof(_prefs.node_name)-1] = 0; // truncate if nec