diff --git a/src/dm/dm_media.c b/src/dm/dm_media.c index b5c31b22..1d157230 100644 --- a/src/dm/dm_media.c +++ b/src/dm/dm_media.c @@ -740,10 +740,7 @@ static void dm_custody_delete(struct UTUN_INSTANCE* inst, uint64_t group, uint64 if (dm_media_verify_receipt(inst, r, NULL, 0)) return; uint64_t author, recipient; memcpy(&author, r + 24, 8); memcpy(&recipient, r + 32, 8); - if (!dm_media_scope(inst, group, source, "supernode", author, recipient) || - !dm_media_scope(inst, group, inst->node_id, "storage", author, recipient)) { - DEBUG_WARN(DEBUG_CATEGORY_DM, "dm_media: unauthorized DELETE source=%llu", (unsigned long long)source); return; - } + /* Для существующей копии точная подпись B разрешает удаление даже после отзыва роли M/S. */ sqlite3_stmt* st = dm_media_prepare(inst, "SELECT body FROM dm_custody WHERE id=?"); if (!st) return; sqlite3_bind_blob(st, 1, r + 40, 16, SQLITE_STATIC); @@ -770,6 +767,10 @@ static void dm_custody_delete(struct UTUN_INSTANCE* inst, uint64_t group, uint64 !memcmp(sqlite3_column_blob(st, 0), r + 56, 32)); sqlite3_finalize(st); if (!exact) { DEBUG_WARN(DEBUG_CATEGORY_DM, "dm_media: delete conflicts with retired artifact"); return; } + if (rc == SQLITE_DONE && (!dm_media_scope(inst, group, source, "supernode", author, recipient) || + !dm_media_scope(inst, group, inst->node_id, "storage", author, recipient))) { + DEBUG_WARN(DEBUG_CATEGORY_DM, "dm_media: unknown DELETE without custody grant source=%llu", (unsigned long long)source); return; + } st = dm_media_prepare(inst, "INSERT INTO dm_custody_done(id,body_hash,receipt) VALUES(?,?,?)" " ON CONFLICT(id) DO UPDATE SET receipt=excluded.receipt"); if (!st) return; diff --git a/src/dm/dm_media.h b/src/dm/dm_media.h index d225eae7..4dfc3918 100644 --- a/src/dm/dm_media.h +++ b/src/dm/dm_media.h @@ -1,5 +1,5 @@ /* dm_media — файлы личных бесед и ограниченное ciphertext-хранилище M. - * Шифрование/проверка в media_async, БД/сеть/публикация в uasync. + * Шифрование/проверка/публикация файлов в media_async; БД и сеть в uasync. * dm_core вызывает track внутри своей транзакции. Квитанция файла независима * от квитанции сообщения; создаётся после проверки, публикации и commit. * Суперузлом и заданиями удаления владеет dm_mailbox_media.