diff --git a/src/dm/dm_identity.c b/src/dm/dm_identity.c index 66a2c84f8..f354887f6 100644 --- a/src/dm/dm_identity.c +++ b/src/dm/dm_identity.c @@ -46,6 +46,11 @@ int dm_party_equal(const struct dm_party* a, const struct dm_party* b) { return a && b && a->kind == b->kind && a->node == b->node && !memcmp(a->ed, b->ed, 32) && !memcmp(a->x, b->x, 32); } +/* Разные ключи одного ID означают конфликт, а не вторую сторону беседы. */ +static int party_same_id(const struct dm_party* a, const struct dm_party* b) { + return a->kind == b->kind && (a->kind == DM_PARTY_DEVICE ? a->node == b->node : !memcmp(a->ed, b->ed, 32)); +} + /* Собственное устройство берём из ядра, удалённое — из проверенной проекции nodes. */ int dm_party_resolve(struct UTUN_INSTANCE* inst, uint64_t node, enum dm_mode mode, struct dm_party* out) { if (!inst || !inst->topo_sqlite_db || !node || !out || (mode != DM_MODE_DEVICE && mode != DM_MODE_GROUPS)) @@ -129,7 +134,7 @@ int dm_party_private(struct UTUN_INSTANCE* inst, const struct dm_party* party, u uint64_t dm_identity_conv_id(enum dm_mode mode, const struct dm_party parties[2]) { if (!parties || (mode != DM_MODE_DEVICE && mode != DM_MODE_GROUPS) || !party_valid(parties) || - !party_valid(parties + 1) || dm_party_equal(parties, parties + 1)) { + !party_valid(parties + 1) || party_same_id(parties, parties + 1)) { identity_error(NULL, "invalid conversation parties", 0); return 0; } if (mode == DM_MODE_DEVICE) { @@ -171,9 +176,9 @@ static int target_compare(const void* a, const void* b) { int dm_identity_targets(struct UTUN_INSTANCE* inst, const struct dm_party parties[2], struct dm_target* out, size_t capacity, size_t* count) { if (!inst || !inst->topo_sqlite_db || !parties || !out || !count || !capacity || - !party_valid(parties) || !party_valid(parties + 1) || dm_party_equal(parties, parties + 1)) + !party_valid(parties) || !party_valid(parties + 1) || party_same_id(parties, parties + 1)) return identity_error(inst, "invalid recipient snapshot arguments", 0); - struct dm_target targets[DM_TARGET_MAX]; size_t n = 0; + struct dm_target targets[DM_TARGET_MAX] = {{0}}; size_t n = 0; for (unsigned side = 0; side < 2; side++) { const struct dm_party* party = parties + side; if (party->kind == DM_PARTY_DEVICE) { diff --git a/tests/test_dm_identity.c b/tests/test_dm_identity.c index cbeb34f59..e4041fab6 100644 --- a/tests/test_dm_identity.c +++ b/tests/test_dm_identity.c @@ -67,7 +67,7 @@ int main(void) { assert(!dm_party_resolve(&inst, nodes[0].node_id, DM_MODE_DEVICE, direct)); assert(!dm_party_resolve(&inst, nodes[2].node_id, DM_MODE_DEVICE, direct + 1)); assert(dm_identity_conv_id(DM_MODE_DEVICE, direct) == dm_derive_conv_id(nodes[0].node_id, nodes[2].node_id)); - struct dm_target targets[DM_TARGET_MAX]; size_t count = 99; + struct dm_target targets[DM_TARGET_MAX] = {{0}}; size_t count = 99; assert(!dm_identity_targets(&inst, direct, targets, DM_TARGET_MAX, &count) && count == 2); assert(has_target(targets, count, nodes[0].node_id, 0) && has_target(targets, count, nodes[2].node_id, 1)); assert(!dm_party_resolve(&inst, nodes[1].node_id, DM_MODE_DEVICE, direct + 1)); @@ -100,6 +100,9 @@ int main(void) { reversed[0] = parties[0]; reversed[1] = parties[0]; assert(!dm_identity_conv_id(DM_MODE_GROUPS, reversed)); assert(dm_identity_targets(&inst, reversed, targets, DM_TARGET_MAX, &count) < 0); + reversed[1].x[0] ^= 1; + assert(!dm_identity_conv_id(DM_MODE_GROUPS, reversed)); + assert(dm_identity_targets(&inst, reversed, targets, DM_TARGET_MAX, &count) < 0); group(nodes + 2, group_ed[1], group_x[1], "Renamed peer devices", 2); assert(!devgroup_project(inst.topo_sqlite_db, nodes + 2));