Verify headless server link commands and self-add rejection

This commit is contained in:
evgeny committed 2026-10-28 11:17:28 +01:00
1 parent 52dadf8b23
commit 7e502f9dd3
3 files changed
+23 -1

No files matched your search

+1 -1
View File
@@ -93,7 +93,7 @@ auto_sockets принимает no/yes/android, auto_socket_protocols — tcp/ud
`print_config` выводит снимок в config/INFO. Private/signing keys заменены признаками наличия;
сети выводятся независимо от количества firewall rules.
`[chatserver] add_key` — 32 ненулевых случайных байта (64 HEX-символа), разрешающие запросить
`[chatserver] add_key` — ненулевой ключ из 32 случайных байтов (64 HEX-символа), разрешающий запросить
добавление сервера в произвольный канал приглашающего. При загрузке из файла отсутствующий ключ
создаёт и атомарно сохраняет config_updater; заданный ошибочный/нулевой ключ отклоняется.
Ключ постоянный: перезапуск сохраняет ссылку, явная замена запрещает новые операции по старой ссылке.
+20
View File
@@ -89,6 +89,7 @@ int main(void) {
struct UASYNC* ua = uasync_create(); assert(ua);
char directory[] = "/tmp/utun-headless-XXXXXX", config[700]; assert(mkdtemp(directory));
snprintf(config, sizeof(config), "[global]\nmy_node_name=headless\ndb_path=%s\n[ntp]\nenabled=no\n"
"[server: udp]\naddr=127.0.0.1:0\ntype=public\n"
"[chatserver]\ngroup_autoconnect=0\nstorage_autoload=0\n", directory);
struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, config); assert(inst && !utun_core_start(inst) && !chat_service_start(inst));
chat_event_set_handler(inst, hc_observe); size_t before = u_get_allocated_count();
@@ -117,6 +118,25 @@ int main(void) {
unsigned old_observed = observed; chat_event_post(inst, CHAT_EVT_STATUS_REFRESH, NULL, 0); assert(observed == old_observed + 1);
hc_request_line(inst, peer, "{\"id\":11,\"cmd\":\"status\"}\n", response); assert(hc_response_ok(inst->topo_sqlite_db, response, 11));
uint64_t channel = chat_core_create_channel_auto(inst, "media"); assert(channel);
hc_request_line(inst, peer, "{\"id\":20,\"cmd\":\"server_link\"}\n", response);
assert(hc_response_ok(inst->topo_sqlite_db, response, 20));
sqlite3_stmt* server_link = NULL;
assert(sqlite3_prepare_v2(inst->topo_sqlite_db, "SELECT json_extract(?1,'$.data.link')", -1, &server_link, NULL) == SQLITE_OK);
assert(sqlite3_bind_text(server_link, 1, response, -1, SQLITE_STATIC) == SQLITE_OK && sqlite3_step(server_link) == SQLITE_ROW);
const char* link = (const char*)sqlite3_column_text(server_link, 0); struct InviteData server_target;
assert(link && !invite_link_decode(link, strlen(link), &server_target, NULL, 0));
assert(server_target.kind == INVITE_KIND_SERVER && server_target.nodeId == inst->node_id);
char add[INVITE_LINK_MAX + 128];
snprintf(add, sizeof(add), "{\"id\":21,\"cmd\":\"server_add\",\"ch\":\"%llu\",\"link\":\"%s\"}\n",
(unsigned long long)channel, link);
assert(sqlite3_finalize(server_link) == SQLITE_OK);
/* Нельзя добавить свой узел самому себе; команда обязана вернуть отказ запуска. */
hc_request_line(inst, peer, add, response); assert(!hc_response_ok(inst->topo_sqlite_db, response, 21));
hc_request_line(inst, peer, "{\"id\":22,\"cmd\":\"server_add\",\"ch\":\"1\"}\n", response);
assert(!hc_response_ok(inst->topo_sqlite_db, response, 22));
inst->config->global.chatserver_has_add_key = 0;
hc_request_line(inst, peer, "{\"id\":23,\"cmd\":\"server_link\"}\n", response);
assert(!hc_response_ok(inst->topo_sqlite_db, response, 23)); inst->config->global.chatserver_has_add_key = 1;
char poll[1024]; snprintf(poll, sizeof(poll), "{\"id\":17,\"cmd\":\"poll_create\",\"ch\":\"%llu\",\"question\":\"Q?\","
"\"mode\":\"single\",\"allow_custom_answer\":true,\"options\":[\"yes\",\"no\"]}\n", (unsigned long long)channel);
hc_request_line(inst, peer, poll, response); assert(hc_response_ok(inst->topo_sqlite_db, response, 17));
+2
View File
@@ -22,6 +22,8 @@
# attach <ch_id> <path> [--video] send a file (or video) as attachment
# invite <ch_id> [node_id] create invite link (auto best node by default)
# invite_nodes <ch_id> list reachable nodes for invite
# server_link get this server's link with its persistent access key
# server_add <ch_id> <utun://...> add our channel on the server identified by its link
# connect <utun://...> join channel via invite link
# create <name> create new channel
# invite_to <ch_id> <node_id> <pubkey_hex> <ip:port> [proto]