Exercise failed root signing during channel creation against committed SQLite
This commit is contained in:
1 parent
1c5faaffc3
commit
a4dd4a10d5
2 files changed
+74
No files matched your search
@@ -301,6 +301,7 @@ if OS_LINUX
|
||||
test_socket_monitor_LDFLAGS += -Wl,--wrap=recvfrom -Wl,--wrap=__recvfrom_chk
|
||||
check_PROGRAMS += test_config_parser
|
||||
check_PROGRAMS += test_chat_setting
|
||||
check_PROGRAMS += test_chat_channel
|
||||
check_PROGRAMS += test_instance_contract
|
||||
test_instance_contract_SOURCES = test_instance_contract.c
|
||||
test_instance_contract_LDADD = $(LIBUTUN) $(COMMON_LIBS)
|
||||
@@ -311,6 +312,9 @@ test_config_parser_LDFLAGS = -Wl,--wrap=u_calloc_impl -Wl,--wrap=u_realloc_impl
|
||||
test_chat_setting_SOURCES = test_chat_setting.c
|
||||
test_chat_setting_LDADD = $(LIBUTUN) $(COMMON_LIBS)
|
||||
test_chat_setting_LDFLAGS = -Wl,--wrap=chat_local_apply_settings
|
||||
test_chat_channel_SOURCES = test_chat_channel.c
|
||||
test_chat_channel_LDADD = $(LIBUTUN) $(COMMON_LIBS)
|
||||
test_chat_channel_LDFLAGS = -Wl,--wrap=EVP_DigestSign
|
||||
else
|
||||
test_socket_monitor_LDFLAGS += -Wl,--wrap=read
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/* Создание канала: настоящие ключи/подписи/SQLite; отказ не публикует незавершённый канал. */
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../src/utun_instance.h"
|
||||
#include "../src/chat/chat_core.h"
|
||||
#include "../src/chat/chat_core_priv.h"
|
||||
#include "../src/chat/chat_event.h"
|
||||
#include "../src/chat/member_sync.h"
|
||||
#include "../src/routing_layer/topo_node_sqlite.h"
|
||||
#include "../lib/platform_compat.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/mem.h"
|
||||
|
||||
static unsigned fail_sign_number, channel_events;
|
||||
static sqlite3* reader;
|
||||
|
||||
extern int __real_EVP_DigestSign(EVP_MD_CTX*, unsigned char*, size_t*, const unsigned char*, size_t);
|
||||
int __wrap_EVP_DigestSign(EVP_MD_CTX* ctx, unsigned char* signature, size_t* length, const unsigned char* data, size_t size) {
|
||||
if (fail_sign_number && !--fail_sign_number) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "channel test: injected signature failure bytes=%zu", size); return 0;
|
||||
}
|
||||
return __real_EVP_DigestSign(ctx, signature, length, data, size);
|
||||
}
|
||||
|
||||
static int channels(void) {
|
||||
sqlite3_stmt* st = NULL;
|
||||
assert(sqlite3_prepare_v2(reader, "SELECT count(*) FROM channels", -1, &st, NULL) == SQLITE_OK && sqlite3_step(st) == SQLITE_ROW);
|
||||
int count = sqlite3_column_int(st, 0); assert(sqlite3_finalize(st) == SQLITE_OK); return count;
|
||||
}
|
||||
|
||||
/* Обработчик видит канал и проверенного участника уже после commit. */
|
||||
static void event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int size) {
|
||||
if (type != CHAT_EVT_CHANNEL_UPDATED) return;
|
||||
assert(sqlite3_get_autocommit(inst->topo_sqlite_db) && size == data[0] + 1 && data[0] < 20);
|
||||
char channel[20]; memcpy(channel, data + 1, data[0]); channel[data[0]] = 0;
|
||||
sqlite3_stmt* st = NULL;
|
||||
assert(sqlite3_prepare_v2(reader, "SELECT owner_node_id,length(x25519_pubkey),length(x25519_privkey),"
|
||||
"length(ed25519_pubkey),length(ed25519_privkey),length(signature) FROM channels WHERE channel_id=?", -1, &st, NULL) == SQLITE_OK);
|
||||
assert(sqlite3_bind_text(st, 1, channel, -1, SQLITE_STATIC) == SQLITE_OK && sqlite3_step(st) == SQLITE_ROW);
|
||||
assert((uint64_t)sqlite3_column_int64(st, 0) == inst->node_id);
|
||||
for (int i = 1; i <= 5; i++) assert(sqlite3_column_int(st, i) == (i == 5 ? 64 : 32));
|
||||
assert(sqlite3_finalize(st) == SQLITE_OK);
|
||||
uint8_t key[32]; assert(member_sync_author_key(inst, channel, inst->node_id, key) == MS_AUTHOR_ACTIVE);
|
||||
assert(!memcmp(key, inst->my_ed25519_pubkey, 32)); channel_events++;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_INFO); size_t baseline = u_get_allocated_count();
|
||||
utun_instance_set_tun_init_enabled(0);
|
||||
char directory[] = "/tmp/utun-channel-create-XXXXXX"; assert(mkdtemp(directory));
|
||||
char config[512], database[256];
|
||||
snprintf(config, sizeof(config), "[global]\ndb_path=%s\n[ntp]\nenabled=no\n"
|
||||
"[chatserver]\ngroup_autoconnect=0\nstorage_autoload=0\n", directory);
|
||||
struct UASYNC* ua = uasync_create(); assert(ua);
|
||||
struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, config);
|
||||
assert(inst && !utun_core_start(inst) && !chat_service_start(inst));
|
||||
snprintf(database, sizeof(database), "%s/chats.db", directory);
|
||||
assert(sqlite3_open_v2(database, &reader, SQLITE_OPEN_READONLY, NULL) == SQLITE_OK);
|
||||
chat_event_set_handler(inst, event); assert(!channels());
|
||||
fail_sign_number = 2; chat_core_create_channel_auto(inst, "root signature failure");
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "channel test: after signature fault channels=%d events=%u", channels(), channel_events);
|
||||
assert(!fail_sign_number && !channels() && !channel_events);
|
||||
chat_core_create_channel_auto(inst, "successful retry"); assert(channels() == 1 && channel_events == 1);
|
||||
utun_instance_destroy(inst); assert(channels() == 1 && sqlite3_close(reader) == SQLITE_OK); reader = NULL;
|
||||
uasync_poll(ua, 0); uasync_destroy(ua, 0); assert(u_get_allocated_count() == baseline);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CHAT_SYNC, "PASS channel creation: failed root signature leaves no channel/event; retry publishes valid membership after commit");
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user