mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-16 08:31:35 +10:00
Block coordinate traffic on configured event channels (#11045)
* Block coordinate traffic on configured event channels Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Suppress event coordinates in reliable relay paths Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Reject blocked phone coordinates before rate limiting Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Prevent event coordinates from reaching MQTT Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Add event coordinate policy preference Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test event coordinate policy in native CI Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Make event policy test tolerate a full NodeDB Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test Router event coordinate enforcement Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test PhoneAPI event coordinate retry handling Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test reliable event coordinate suppression Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test MQTT event coordinate suppression Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Run event policy behavioral suites in native CI Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * tests: address CodeRabbit review feedback - test_event_channel_phone_api: complete the setUp/tearDown save-restore pair. GlobalState now carries cryptLock and myNodeInfo; setUp() nulls cryptLock before constructing MockRouter (Router's ctor asserts it is unset), and tearDown() restores both so the suite leaves no global mutated. Not reachable today - the globals start null in this binary - but the pair was asymmetric. - Replace the strcpy calls this branch added on Channel.settings.name (char[12]) with the bounded form the rest of the test tree already uses, strncpy(dst, src, sizeof(dst) - 1). Covers the flagged site in test_nexthop_routing plus the six equivalents in test_event_channel_phone_api, test_mqtt and test_position_precision, which trip the same ast-grep dangerous-buffer-functions-cpp rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Co-authored-by: Ben Meadors <benmmeadors@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Sisyphus
Claude Opus 5
Ben Meadors
parent
fb17f6ddbe
commit
546b9d9e40
+70
-4
@@ -69,6 +69,52 @@ Allocator<meshtastic_MeshPacket> &packetPool = staticPool;
|
||||
|
||||
static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1] __attribute__((__aligned__));
|
||||
|
||||
static ChannelIndex getEffectiveChannelIndex(const meshtastic_MeshPacket *p)
|
||||
{
|
||||
ChannelIndex chIndex = p->channel;
|
||||
if (nodeDB && isFromUs(p) && !chIndex && !p->pki_encrypted && !isBroadcast(p->to)) {
|
||||
const meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(p->to);
|
||||
if (node)
|
||||
chIndex = node->channel;
|
||||
}
|
||||
return chIndex;
|
||||
}
|
||||
|
||||
bool isBlockedEventCoordinatePacket(const meshtastic_MeshPacket *p)
|
||||
{
|
||||
#if USERPREFS_BLOCK_POSITION_ON_EVENT_CHANNEL
|
||||
if (p->pki_encrypted || willUsePki(p)) {
|
||||
return false;
|
||||
}
|
||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
return isCoordinatePortnum(p->decoded.portnum) && channels.isEventChannel(getEffectiveChannelIndex(p));
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
(void)p;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool willUsePki(const meshtastic_MeshPacket *p)
|
||||
{
|
||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||
if (p->which_payload_variant != meshtastic_MeshPacket_decoded_tag || !isFromUs(p))
|
||||
return false;
|
||||
bool haveDestKey = false;
|
||||
if (p->decoded.portnum == meshtastic_PortNum_KEY_VERIFICATION_APP) {
|
||||
meshtastic_NodeInfoLite_public_key_t destKey = {0, {0}};
|
||||
haveDestKey = nodeDB->copyPublicKey(p->to, destKey);
|
||||
if (!haveDestKey && p->pki_encrypted)
|
||||
haveDestKey = crypto->getPendingPublicKey(p->to, destKey);
|
||||
}
|
||||
return wouldEncryptWithPKC(p, getEffectiveChannelIndex(p), haveDestKey);
|
||||
#else
|
||||
(void)p;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct RoutingAuthCache {
|
||||
bool valid = false;
|
||||
// Deliberately NOT initialized in-class as this eats flash space.
|
||||
@@ -141,7 +187,6 @@ void resetRoutingAuthEvaluationCount()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@@ -360,9 +405,9 @@ ErrorCode Router::sendLocal(meshtastic_MeshPacket *p, RxSource src)
|
||||
|
||||
// don't override if a channel was requested and no need to set it when PKI is enforced
|
||||
if (!p->channel && !p->pki_encrypted && !isBroadcast(p->to)) {
|
||||
meshtastic_NodeInfoLite const *node = nodeDB->getMeshNode(p->to);
|
||||
if (node) {
|
||||
p->channel = node->channel;
|
||||
ChannelIndex chIndex = getEffectiveChannelIndex(p);
|
||||
if (chIndex) {
|
||||
p->channel = chIndex;
|
||||
LOG_DEBUG("localSend to channel %d", p->channel);
|
||||
}
|
||||
}
|
||||
@@ -473,6 +518,12 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
fixPriority(p); // Before encryption, fix the priority if it's unset
|
||||
// Position precision is an originator-only privacy policy. Relays keep
|
||||
// p->from as the original sender, so do not rewrite their POSITION_APP payload.
|
||||
if (isBlockedEventCoordinatePacket(p)) {
|
||||
LOG_DEBUG("Suppress coordinate send on event (everyone) channel");
|
||||
packetPool.release(p);
|
||||
return meshtastic_Routing_Error_NOT_AUTHORIZED;
|
||||
}
|
||||
|
||||
if (isFromUs(p)) {
|
||||
if (!applyPositionPrecisionForChannel(*p, p->channel)) {
|
||||
LOG_ERROR("Drop malformed position packet before send");
|
||||
@@ -959,6 +1010,11 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
|
||||
return DecodeState::DECODE_POLICY_REJECT;
|
||||
#endif
|
||||
|
||||
if (isBlockedEventCoordinatePacket(p)) {
|
||||
LOG_DEBUG("Decoded coordinate packet on event channel; suppress payload logging");
|
||||
return DecodeState::DECODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (p->decoded.has_bitfield)
|
||||
p->decoded.want_response |= p->decoded.bitfield & BITFIELD_WANT_RESPONSE_MASK;
|
||||
|
||||
@@ -1436,6 +1492,16 @@ void Router::dispatchReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
|
||||
#if USERPREFS_BLOCK_POSITION_ON_EVENT_CHANNEL
|
||||
// Discard coordinate-bearing packets that arrive on the event ("everyone")
|
||||
// channel: don't process, store in NodeDB, or rebroadcast them.
|
||||
if (!skipHandle && isBlockedEventCoordinatePacket(p)) {
|
||||
LOG_DEBUG("Drop coordinate packet on event (everyone) channel");
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user