From f2c89935890a0fb16e3f66c79421028a0417c080 Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 3 Nov 2026 19:52:24 +0100 Subject: [PATCH] Reject raw CHAT data before delivery and forwarding --- src/broadcast.c | 6 ++++-- src/radio/radio.c | 18 +++++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/broadcast.c b/src/broadcast.c index dc85baa67..1b993ed03 100644 --- a/src/broadcast.c +++ b/src/broadcast.c @@ -81,6 +81,7 @@ void broadcast_destroy(struct TOPO_GROUP* group) { int broadcast_send(struct TOPO_GROUP* group, const uint8_t* data, uint16_t data_len) { if (!group || !group->broadcast || !data || data_len > BROADCAST_MAX_DATA) return -1; + if (!topo_group_data_allowed(group, NULL)) return -1; struct broadcast_ctx* ctx = group->broadcast; uint8_t uuid[BROADCAST_UUID_SIZE]; @@ -108,7 +109,7 @@ int broadcast_send(struct TOPO_GROUP* group, const uint8_t* data, uint16_t data_ struct ll_entry* se = group->senders_list->head; while (se) { struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)se->data; - if (item && item->conn) { + if (item && item->conn && topo_group_data_allowed(group, item->conn)) { uint16_t total = 1 + 8 + BROADCAST_UUID_SIZE + 2 + data_len; uint8_t* pkt = u_malloc(total); if (!pkt) { se = se->next; continue; } @@ -189,6 +190,7 @@ static void broadcast_cleanup_timer_cb(void* arg) { void broadcast_recv(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* payload, size_t payload_len) { if (!group || !group->broadcast || !payload || payload_len < BROADCAST_UUID_SIZE + 2) return; + if (!topo_group_data_allowed(group, from_conn)) return; struct broadcast_ctx* ctx = group->broadcast; const uint8_t* uuid = payload; @@ -217,7 +219,7 @@ void broadcast_recv(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const struct ll_entry* se = group->senders_list->head; while (se) { struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)se->data; - if (item && item->conn && item->conn != from_conn) { + if (item && item->conn && item->conn != from_conn && topo_group_data_allowed(group, item->conn)) { uint16_t total = 1 + 8 + BROADCAST_UUID_SIZE + 2 + data_len; uint8_t* pkt = u_malloc(total); if (!pkt) { se = se->next; continue; } diff --git a/src/radio/radio.c b/src/radio/radio.c index fe605163a..3bf0a8d36 100644 --- a/src/radio/radio.c +++ b/src/radio/radio.c @@ -217,7 +217,7 @@ static void radio_flood(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, struct ll_entry* se = group->senders_list->head; while (se) { struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)se->data; - if (item && item->conn && item->conn != from_conn) { + if (item && item->conn && item->conn != from_conn && topo_group_data_allowed(group, item->conn)) { if (radio_neighbor_has_subscriber(group, item->conn, hop_list, hop_count)) { radio_send_to(group, item->conn, payload, payload_len); ctx->c_fwd_frames++; @@ -332,6 +332,7 @@ static void radio_recv(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* payload, size_t payload_len) { struct radio_ctx* ctx = radio_of(group); if (!ctx || !from_conn || payload_len < RADIO_HDR_SIZE) return; + if (!topo_group_data_allowed(group, from_conn)) return; const uint8_t* p = payload; uint64_t group_id, src; @@ -401,10 +402,14 @@ static void radio_recv(struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, if (group->radio_active && ctx->group) { struct radio_instance* ri = radio_inst(group->instance); if (ri && ri->frame_fn) { - for (unsigned i = 0; i < count; i++) + for (unsigned i = 0; i < count; i++) { + if (!topo_group_data_allowed(group, from_conn)) return; ri->frame_fn(group->instance, group_id, src, stream, (uint16_t)(seq + i), 0, frames[i], lengths[i], ri->frame_arg); + ctx->c_rx_frames++; + } + if (!topo_group_data_allowed(group, from_conn)) return; if (flags & RADIO_FLAG_FIN) ri->frame_fn(group->instance, group_id, src, stream, seq, 1, NULL, 0, ri->frame_arg); - ctx->c_rx_frames += count + !!(flags & RADIO_FLAG_FIN); + ctx->c_rx_frames += !!(flags & RADIO_FLAG_FIN); } /* индикация говорящих: старт/стоп передачи */ if (flags & RADIO_FLAG_FIN) radio_talker_off(ctx, src); @@ -658,6 +663,11 @@ static void radio_flush(struct radio_ctx* ctx, const char* reason) { uasync_cancel_timeout(ctx->group->instance->ua, ctx->burst_timer); ctx->burst_timer = NULL; } if (!ctx->burst_count) return; + if (!topo_group_data_allowed(ctx->group, NULL)) { + DEBUG_WARN(DEBUG_CATEGORY_RADIO, "radio: discard revoked batch group=%llx frames=%u", + (unsigned long long)ctx->group->group_id, ctx->burst_count); + ctx->burst_count = 0; ctx->burst_bytes = 0; ctx->talking = 0; return; + } uint64_t self = ctx->group->instance->node_id; uint8_t out[RADIO_HDR_SIZE + 8 + RADIO_MAX_BODY]; uint16_t first_seq = (uint16_t)(ctx->seq - ctx->burst_count); @@ -682,6 +692,7 @@ int radio_talk_begin(struct UTUN_INSTANCE* inst, uint64_t group_id) { if (!group) { DEBUG_WARN(DEBUG_CATEGORY_RADIO, "%s: talk_begin group 0x%016llx not found", RADIO_ID, (unsigned long long)group_id); return -1; } struct radio_ctx* ctx = radio_of(group); if (!ctx) return -1; + if (!topo_group_data_allowed(group, NULL)) return -1; if (ctx->talking) { DEBUG_WARN(DEBUG_CATEGORY_RADIO, "radio: BEGIN closes unfinished stream=%u", ctx->stream_id); radio_talk_end(inst, group_id); @@ -702,6 +713,7 @@ int radio_talk_send(struct UTUN_INSTANCE* inst, uint64_t group_id, const uint8_t struct TOPO_GROUP* group = topo_groups_find(inst->topo_groups, group_id); struct radio_ctx* ctx = radio_of(group); if (!ctx) { DEBUG_ERROR(DEBUG_CATEGORY_RADIO, "radio: send group unavailable group=%llx", (unsigned long long)group_id); return -1; } + if (!topo_group_data_allowed(group, NULL)) { radio_flush(ctx, "revoked"); ctx->talking = 0; return -1; } if (!ctx->talking) { /* burst не открыт: хвостовой кадр, пришедший после radio_talk_end (гонка релиза PTT) — * не переоткрываем передачу, иначе получится burst без FIN и «говорит» зависнет у пиров. */