feat(peer): validate manifests before download mutation
Why: - Remote and UI-echoed file descriptions could reach transaction and storage code one entry at a time, so a hostile late path could mutate earlier files. - Per-file consensus also accepted malformed peer lists and let duplicate rows inflate a source's vote. What: - Add a complete protocol-7 manifest adapter with catalog-root confinement, portable path and alias rules, reserved-path protection, shape and size caps, symlink/reparse inspection, and zero-mutation tests. - Keep download selection in the peer core, validate every peer manifest before consensus, and pass only the validated manifest into storage/orchestration. - Canonicalize locally advertised paths, cap exact chunk receives, and preserve the local-only install fast path. - Record the chosen safety limits and follow-up ownership/catalog decisions. Test Plan: - just clippy - just test - just frontend-test - just build - just fmt (Rust/TOML/Prettier completed; rumdl reports 39 pre-existing issues) - git diff --cached --check
This commit is contained in:
@@ -14,7 +14,7 @@ use std::{
|
||||
|
||||
use eyre::bail;
|
||||
use lanspread_compat::eti::get_games;
|
||||
use lanspread_db::db::{Availability, Game, GameCatalog, GameDB, GameFileDescription};
|
||||
use lanspread_db::db::{Availability, Game, GameCatalog, GameDB};
|
||||
use lanspread_peer::{
|
||||
ActiveOperation,
|
||||
ActiveOperationKind,
|
||||
@@ -2249,9 +2249,9 @@ async fn handle_peer_event(app_handle: &AppHandle, event: PeerEvent) {
|
||||
}
|
||||
PeerEvent::GotGameFiles {
|
||||
id,
|
||||
file_descriptions,
|
||||
file_descriptions: _,
|
||||
} => {
|
||||
handle_got_game_files(app_handle, id, file_descriptions).await;
|
||||
handle_got_game_files(app_handle, id).await;
|
||||
}
|
||||
PeerEvent::NoPeersHaveGame { id } => {
|
||||
log::warn!("PeerEvent::NoPeersHaveGame received for {id}");
|
||||
@@ -2382,20 +2382,13 @@ async fn handle_peer_event(app_handle: &AppHandle, event: PeerEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_got_game_files(
|
||||
app_handle: &AppHandle,
|
||||
id: String,
|
||||
file_descriptions: Vec<GameFileDescription>,
|
||||
) {
|
||||
async fn handle_got_game_files(app_handle: &AppHandle, id: String) {
|
||||
log::info!("PeerEvent::GotGameFiles received");
|
||||
|
||||
let state = app_handle.state::<LanSpreadState>();
|
||||
let peer_ctrl = state.peer_ctrl.read().await.clone();
|
||||
if let Some(peer_ctrl) = peer_ctrl
|
||||
&& let Err(e) = peer_ctrl.send(PeerCommand::DownloadGameFiles {
|
||||
id,
|
||||
file_descriptions,
|
||||
})
|
||||
&& let Err(e) = peer_ctrl.send(PeerCommand::DownloadGameFiles { id })
|
||||
{
|
||||
log::error!("Failed to continue queued game transfer: {e}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user