Preserve precise author failure reasons and guard SQLite column allocation
This commit is contained in:
1 parent
4b394b75e0
commit
bf941bfd14
2 files changed
+30
-18
No files matched your search
@@ -428,10 +428,13 @@ static int fb_next_channel(struct UTUN_INSTANCE* inst, const char* after, char c
|
||||
/* Пересчитывает только листья, зависящие от изменённого автора/ключа пригласившего. */
|
||||
int chat_feedback_member_update(struct UTUN_INSTANCE* inst, uint64_t node_id) {
|
||||
if (!merkle_sync_registered(inst, MT_DATA_FEEDBACK)) return 0;
|
||||
if (sqlite3_get_autocommit(inst->topo_sqlite_db)) return fb_db_error(inst, "-", "member update requires transaction");
|
||||
if (sqlite3_get_autocommit(inst->topo_sqlite_db)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: member update requires transaction node=%016llx",
|
||||
(unsigned long long)node_id); return -1;
|
||||
}
|
||||
char channel[21] = "", next[21]; int scan;
|
||||
while ((scan = fb_next_channel(inst, channel, next, 1)) > 0) {
|
||||
memcpy(channel, next, sizeof(channel));
|
||||
strcpy(channel, next);
|
||||
char table[40], sql[384]; if (fb_table(inst, channel, table, NULL) < 0) return -1;
|
||||
snprintf(sql, sizeof(sql), "SELECT DISTINCT f.bucket FROM %s f LEFT JOIN peers_%s p ON p.node_id=f.node_id"
|
||||
" WHERE f.node_id=?1 OR p.signed_by=?1 ORDER BY f.bucket", table, channel);
|
||||
@@ -448,7 +451,10 @@ int chat_feedback_member_update(struct UTUN_INSTANCE* inst, uint64_t node_id) {
|
||||
buckets++;
|
||||
}
|
||||
int final = sqlite3_finalize(st);
|
||||
if (rc != SQLITE_DONE || final != SQLITE_OK) return fb_db_error(inst, channel, "member index update");
|
||||
if (rc != SQLITE_DONE || final != SQLITE_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: member index failed ch=%s dependency=%016llx step=%d finalize=%d",
|
||||
channel, (unsigned long long)node_id, rc, final); return -1;
|
||||
}
|
||||
if (buckets) DEBUG_DEBUG(DEBUG_CATEGORY_CHAT_SYNC, "feedback: member index updated ch=%s dependency=%016llx buckets=%u",
|
||||
channel, (unsigned long long)node_id, buckets);
|
||||
}
|
||||
@@ -461,7 +467,7 @@ void chat_feedback_member_committed(struct UTUN_INSTANCE* inst, uint64_t node_id
|
||||
if (!sqlite3_get_autocommit(inst->topo_sqlite_db)) { fb_db_error(inst, "-", "member notify before commit"); return; }
|
||||
char channel[21] = "", next[21];
|
||||
while (fb_next_channel(inst, channel, next, 1) > 0) {
|
||||
memcpy(channel, next, sizeof(channel));
|
||||
strcpy(channel, next);
|
||||
/* Даже без локального feedback ключ может разрешить приём ранее отложенной страницы. */
|
||||
merkle_sync_changed(inst, MT_DATA_FEEDBACK, channel);
|
||||
char table[40], sql[512]; if (fb_table(inst, channel, table, NULL) < 0) return;
|
||||
@@ -502,7 +508,7 @@ int chat_feedback_init(struct UTUN_INSTANCE* inst) {
|
||||
return fb_db_error(inst, "-", "init begin");
|
||||
char channel[21] = "", next[21]; int scan, result = 0; unsigned buckets = 0;
|
||||
while ((scan = fb_next_channel(inst, channel, next, 0)) > 0) {
|
||||
memcpy(channel, next, sizeof(channel));
|
||||
strcpy(channel, next);
|
||||
char table[40], sql[128];
|
||||
if (chat_feedback_ensure_channel(inst, channel) < 0 || fb_table(inst, channel, table, NULL) < 0) { result = -1; break; }
|
||||
snprintf(sql, sizeof(sql), "SELECT DISTINCT bucket FROM %s ORDER BY bucket", table);
|
||||
|
||||
+19
-13
@@ -1344,57 +1344,63 @@ enum ms_author_status member_sync_author_key(struct UTUN_INSTANCE* inst, const c
|
||||
if (rc != SQLITE_ROW) goto done;
|
||||
int x_bytes = sqlite3_column_bytes(st, 0), ed_bytes = sqlite3_column_bytes(st, 1);
|
||||
int tree_bytes = sqlite3_column_bytes(st, 3), join_bytes = sqlite3_column_bytes(st, 4);
|
||||
if (sqlite3_errcode(db) == SQLITE_NOMEM) goto done;
|
||||
if (sqlite3_errcode(db) == SQLITE_NOMEM) { rc = SQLITE_NOMEM; goto done; }
|
||||
status = MS_AUTHOR_INVALID;
|
||||
reason = "invalid member fields";
|
||||
if (x_bytes != 32 || ed_bytes != 32 || (tree_bytes != 0 && tree_bytes != 64)
|
||||
|| (join_bytes != 0 && join_bytes != 64)) goto done;
|
||||
if (!tree_bytes || !join_bytes || sqlite3_column_int64(st, 5) <= 0
|
||||
|| _sig_is_zero64(sqlite3_column_blob(st, 3)) || _sig_is_zero64(sqlite3_column_blob(st, 4))) {
|
||||
status = MS_AUTHOR_PENDING; reason = "join or invitation pending"; goto done;
|
||||
}
|
||||
struct ms_member_rec member = { .node_id = author, .x25519 = sqlite3_column_blob(st, 0),
|
||||
.ed25519 = sqlite3_column_blob(st, 1), .signed_by = (uint64_t)sqlite3_column_int64(st, 2),
|
||||
.signature = sqlite3_column_blob(st, 3), .join_sig = sqlite3_column_blob(st, 4),
|
||||
.join_ts = (uint64_t)sqlite3_column_int64(st, 5) };
|
||||
if (sqlite3_errcode(db) == SQLITE_NOMEM || !member.x25519 || !member.ed25519
|
||||
|| (tree_bytes && !member.signature) || (join_bytes && !member.join_sig)) {
|
||||
status = MS_AUTHOR_ERROR; reason = "member column allocation"; rc = SQLITE_NOMEM; goto done;
|
||||
}
|
||||
if (!tree_bytes || !join_bytes || !member.join_ts
|
||||
|| _sig_is_zero64(member.signature) || _sig_is_zero64(member.join_sig)) {
|
||||
status = MS_AUTHOR_PENDING; reason = "join or invitation pending"; goto done;
|
||||
}
|
||||
reason = "node_id/X25519 mismatch";
|
||||
uint64_t derived = sc_derive_node_id_from_pubkey(member.x25519);
|
||||
if (!derived) { status = MS_AUTHOR_ERROR; reason = "identity digest"; goto done; }
|
||||
if (!derived) { status = MS_AUTHOR_ERROR; reason = "identity digest"; rc = SC_ERR_CRYPTO; goto done; }
|
||||
if (derived != author) goto done;
|
||||
uint8_t trusted[32], x[32], ed[32], body[112];
|
||||
reason = "trusted Ed25519 key unavailable";
|
||||
int lookup = topo_node_sqlite_get_ed25519_pubkey(db, author, trusted);
|
||||
if (lookup != 0) {
|
||||
status = lookup == TOPO_SQLITE_LOOKUP_MISSING ? MS_AUTHOR_PENDING : MS_AUTHOR_ERROR; goto done;
|
||||
status = lookup == TOPO_SQLITE_LOOKUP_MISSING ? MS_AUTHOR_PENDING : MS_AUTHOR_ERROR; rc = lookup; goto done;
|
||||
}
|
||||
reason = "trusted Ed25519 key mismatch";
|
||||
if (memcmp(trusted, member.ed25519, 32)) goto done;
|
||||
reason = "channel keys unavailable";
|
||||
lookup = topo_node_sqlite_channel_get(db, channel, NULL, 0, NULL, x, ed, NULL);
|
||||
if (lookup != 0) {
|
||||
status = lookup == TOPO_SQLITE_LOOKUP_MISSING ? MS_AUTHOR_PENDING : MS_AUTHOR_ERROR; goto done;
|
||||
status = lookup == TOPO_SQLITE_LOOKUP_MISSING ? MS_AUTHOR_PENDING : MS_AUTHOR_ERROR; rc = lookup; goto done;
|
||||
}
|
||||
reason = "invalid join signature";
|
||||
int bytes = member_sync_build_join_msg(x, ed, author, member.x25519, member.join_ts, body, sizeof(body));
|
||||
if (bytes != 112) { status = MS_AUTHOR_ERROR; reason = "join message build"; goto done; }
|
||||
int signature = sc_ed25519_verify(member.ed25519, body, bytes, member.join_sig);
|
||||
if (signature != SC_OK) {
|
||||
status = signature == SC_ERR_AUTH_FAILED ? MS_AUTHOR_INVALID : MS_AUTHOR_ERROR; goto done;
|
||||
status = signature == SC_ERR_AUTH_FAILED ? MS_AUTHOR_INVALID : MS_AUTHOR_ERROR; rc = signature; goto done;
|
||||
}
|
||||
reason = "invitation verification";
|
||||
signature = member_sync_verify_signature(db, channel, &member);
|
||||
if (signature != 1) {
|
||||
status = signature == MS_VERIFY_DEFERRED ? MS_AUTHOR_PENDING
|
||||
: signature == MS_VERIFY_ERROR ? MS_AUTHOR_ERROR : MS_AUTHOR_INVALID;
|
||||
rc = signature;
|
||||
goto done;
|
||||
}
|
||||
memcpy(verified_key, member.ed25519, 32); status = MS_AUTHOR_ACTIVE; reason = "verified";
|
||||
done:
|
||||
if (sqlite3_finalize(st) != SQLITE_OK) { status = MS_AUTHOR_ERROR; reason = "member finalize"; }
|
||||
done:;
|
||||
int final = sqlite3_finalize(st);
|
||||
if (final != SQLITE_OK) { status = MS_AUTHOR_ERROR; reason = "member finalize"; rc = final; }
|
||||
if (status == MS_AUTHOR_ACTIVE) memcpy(key, verified_key, 32);
|
||||
if (status == MS_AUTHOR_ERROR) DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC,
|
||||
"author verification failed ch=%s node=%016llx reason=%s rc=%d: %s",
|
||||
channel, (unsigned long long)author, reason, rc, sqlite3_errmsg(db));
|
||||
"author verification failed ch=%s node=%016llx reason=%s result=%d",
|
||||
channel, (unsigned long long)author, reason, rc);
|
||||
else if (status == MS_AUTHOR_INVALID) DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC,
|
||||
"author invalid ch=%s node=%016llx reason=%s", channel, (unsigned long long)author, reason);
|
||||
else if (status != MS_AUTHOR_ACTIVE) DEBUG_DEBUG(DEBUG_CATEGORY_MEMBER_SYNC,
|
||||
|
||||
Reference in new issue
Block a user