Cover registration isolation and authorization through a relay
This commit is contained in:
1 parent
6be77de7f6
commit
eac0163b69
3 files changed
+40
-10
No files matched your search
@@ -70,9 +70,8 @@ struct md_file_load {
|
||||
* Верхняя граница выдачи — sqlite_sequence, включая удалённые ID и промежутки других групп. */
|
||||
|
||||
struct media_served_node {
|
||||
struct ll_entry ll; // индекс по node_id (8 байт)
|
||||
uint64_t node_id;
|
||||
uint64_t group_id;
|
||||
uint64_t node_id; // начало составного ключа (узел, группа), 16 байт
|
||||
uint64_t group_id; // CHAT-группа регистрации
|
||||
int64_t joined_at; // timestamp регистрации
|
||||
};
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ static void rx_reset(uint8_t marker) {
|
||||
// ======================== Inject helper ========================
|
||||
static struct ETCP_CONN fake_conn;
|
||||
static uint8_t g_sign_ed25519_privkey[SC_PRIVKEY_SIZE];
|
||||
static uint64_t inject_relay;
|
||||
|
||||
static void handshake_packet(etcp_recv_fn cb, struct UTUN_INSTANCE* inst, struct SVC_ROUTE_HDR* h) {
|
||||
int sign = (inst->router_bindings.required_crypto[h->svc_id] & ROUTER_FLAG_SIGNED) != 0;
|
||||
@@ -76,10 +77,12 @@ static void handshake_packet(etcp_recv_fn cb, struct UTUN_INSTANCE* inst, struct
|
||||
static void inject_wire(struct ETCP_CONN* conn, struct ll_entry* e) {
|
||||
size_t len = e->len;
|
||||
uint64_t src = ((struct SVC_ROUTE_HDR*)e->dgram)->src_node_id;
|
||||
uint8_t* wire = u_malloc(len + 9); if (!wire) abort();
|
||||
memcpy(wire, e->dgram, len); memcpy(wire + len, &src, 8); wire[len + 8] = 1;
|
||||
queue_dgram_free(e); e->dgram = wire; e->len = len + 9;
|
||||
conn->peer_node_id = src;
|
||||
size_t size = len + (inject_relay ? 17 : 9);
|
||||
uint8_t* wire = u_malloc(size); if (!wire) abort();
|
||||
memcpy(wire, e->dgram, len); memcpy(wire + len, &src, 8); wire[size - 1] = inject_relay ? 2 : 1;
|
||||
if (inject_relay) memcpy(wire + len + 8, &inject_relay, 8);
|
||||
queue_dgram_free(e); e->dgram = wire; e->len = size;
|
||||
conn->peer_node_id = inject_relay ? inject_relay : src;
|
||||
conn->instance->api_bindings.callbacks[ETCP_ID_SVC_ROUTE](conn, e);
|
||||
}
|
||||
|
||||
@@ -1479,14 +1482,19 @@ static int test_authenticated_access(void) {
|
||||
TESTASSERT(!c->closed && c->peer_reset_id == SIGNER_NODE && !c->tx_acked && !c->peer_receive_blocked);
|
||||
}
|
||||
TESTASSERT(g_notify_count == before);
|
||||
// Допуск конечного автора сохраняется через посредника, которого политика сервиса не допускает.
|
||||
uint8_t byte = 0x61;
|
||||
inject_relay = TEST_REMOTE_NODE;
|
||||
inject_signed(recv_cb, &inst, SIGNER_NODE, TEST_SVC_ID, 0, &byte, 1, 0, 0);
|
||||
inject_relay = 0;
|
||||
TESTASSERT(rx.delivered == 1 && c->rx_seq == 1); rx_reset(0x61);
|
||||
TESTASSERT(!etcp_router_bind(&inst, TEST_SVC_ID2, test_handler));
|
||||
struct ETCP_ROUTER_CONN* other_group = etcp_router_conn_get(&inst, 222, SIGNER_NODE, TEST_SVC_ID);
|
||||
struct ETCP_ROUTER_CONN* other_service = etcp_router_conn_get(&inst, h.group_id, SIGNER_NODE, TEST_SVC_ID2);
|
||||
TESTASSERT(other_group && other_service);
|
||||
// Готовые пакеты остаются в reorder-очереди до допуска потребителя.
|
||||
receive_capacity = 0; etcp_router_set_receive_ready(&inst, TEST_SVC_ID, receive_ready);
|
||||
uint8_t byte = 0x61;
|
||||
for (int i = 0; i < 3; i++) inject_signed(recv_cb, &inst, SIGNER_NODE, TEST_SVC_ID, i, &byte, 1, 0, 0);
|
||||
for (int i = 0; i < 3; i++) inject_signed(recv_cb, &inst, SIGNER_NODE, TEST_SVC_ID, i + 1, &byte, 1, 0, 0);
|
||||
for (int i = 0; i < 8; i++) uasync_poll(ua, 0);
|
||||
TESTASSERT(c->recv_q->count == 3 && !rx.delivered);
|
||||
// После первой доставки политика меняется: остальные буферизованные пакеты не попадут в сервис.
|
||||
|
||||
@@ -573,6 +573,29 @@ static void test_membership_revocation(void) {
|
||||
puts("membership revoke: stop relay, reject inactive peers, fail over holder, stop self, preserve neighbour: PASS");
|
||||
}
|
||||
|
||||
static void test_service_group_scope(void) {
|
||||
reset(); struct UTUN_INSTANCE* inst = instance(SERVER);
|
||||
uint64_t peer = CLIENT, key[2] = {CLIENT, 222};
|
||||
media_test_group(inst, 222, &peer, 1);
|
||||
struct packet p = {.from = peer, .group = GROUP, .len = sizeof(struct media_pkt_serve_reg)};
|
||||
struct media_pkt_serve_reg* reg = (void*)p.data;
|
||||
reg->subcmd = MEDIA_SUBCMD_SERVE_REG; reg->group_id = 222;
|
||||
receive(inst, &p); REQUIRE(!inst->md.served_nodes);
|
||||
reg->group_id = GROUP; receive(inst, &p);
|
||||
reg->group_id = p.group = 222; receive(inst, &p);
|
||||
REQUIRE(inst->md.served_nodes->count == 2 && queue_find_data_by_index(inst->md.served_nodes, key));
|
||||
struct media_pkt_serve_leave* leave = (void*)p.data;
|
||||
p.group = GROUP; p.len = sizeof(*leave); leave->subcmd = MEDIA_SUBCMD_SERVE_LEAVE; leave->group_id = 222;
|
||||
receive(inst, &p); REQUIRE(inst->md.served_nodes->count == 2);
|
||||
leave->group_id = GROUP; receive(inst, &p);
|
||||
REQUIRE(inst->md.served_nodes->count == 1 && queue_find_data_by_index(inst->md.served_nodes, key));
|
||||
REQUIRE(etcp_router_conn_get(inst, 222, peer, ETCP_RT_ID_MEDIA_DELIVERY));
|
||||
REQUIRE(sqlite3_exec(inst->md.db, "UPDATE peers_222 SET admitted=0 WHERE node_id=512", NULL, NULL, NULL) == SQLITE_OK);
|
||||
etcp_router_revalidate_group(inst, 222); REQUIRE(!inst->md.served_nodes->count);
|
||||
destroy(inst);
|
||||
puts("SERVE_REG/LEAVE: signed envelope group, independent registrations and revoke cleanup: PASS");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
|
||||
if (getenv("UTUN_TEST_DEBUG")) debug_set_category_level(DEBUG_CATEGORY_MEDIA, DEBUG_LEVEL_DEBUG);
|
||||
@@ -588,7 +611,7 @@ int main(void) {
|
||||
test_identity_and_bounds(); test_rejected_attempts(); test_io_failures(); test_reentrant_cancel();
|
||||
test_growing_relay(); test_relay_cancel(); test_relay_generation(); test_destinations();
|
||||
test_registration_failure_and_keys(); test_relay_limit_and_idle();
|
||||
test_indexed_source(); test_membership_revocation();
|
||||
test_indexed_source(); test_membership_revocation(); test_service_group_scope();
|
||||
REQUIRE(!rmdir(directory)); uasync_destroy(ua, 0);
|
||||
puts("media block regressions: PASS"); return 0;
|
||||
}
|
||||
Reference in new issue
Block a user