Compare commits

...

1 Commits

Author SHA1 Message Date
patchzyy 28a24ea49d Always refresh Retro-WFC payload with fallback 2026-09-28 20:41:51 +02:00
3 changed files with 56 additions and 22 deletions
+28 -7
View File
@@ -127,19 +127,40 @@ internal static class Program
string? retroWfcOfflineDir = null; string? retroWfcOfflineDir = null;
if (downloadPayload) if (downloadPayload)
{ {
// Reused if a previous install already downloaded and it's still valid - matches
// Windows's own reuse-if-valid behavior instead of re-downloading on every install.
var cacheDir = Path.Combine(workspace, "generated", "retro-wfc-payload"); var cacheDir = Path.Combine(workspace, "generated", "retro-wfc-payload");
reporter.Progress(InstallStages.Validate, "Preparing the Retro-WFC payload", 1); reporter.Progress(InstallStages.Validate,
"Downloading the current Retro-WFC payload", 1);
try try
{ {
RetroWfcPayload.ValidateStagedRetroWfcPayloadDirectory(cacheDir); // A valid signature authenticates a payload, but does not prove it is the latest
} // signed revision. Always ask the fixed endpoint for the current snapshot; the
catch (InvalidDataException) // downloader verifies it before atomically replacing the cache.
{
await RetroWfcPayload.DownloadRetroWfcPayloadAsync( await RetroWfcPayload.DownloadRetroWfcPayloadAsync(
RetroWfcPayload.CurrentRetroWfcPayloadUri, cacheDir, token); RetroWfcPayload.CurrentRetroWfcPayloadUri, cacheDir, token);
} }
catch (Exception downloadFailure) when (!token.IsCancellationRequested &&
downloadFailure is HttpRequestException or TimeoutException
or IOException)
{
// Offline installs may continue with a previously authenticated snapshot. Do not
// use this path for a newly downloaded payload that failed signature validation:
// that must remain a hard failure instead of hiding possible endpoint tampering.
try
{
RetroWfcPayload.ValidateStagedRetroWfcPayloadDirectory(cacheDir);
}
catch (Exception cacheFailure) when (cacheFailure is IOException or
UnauthorizedAccessException or InvalidDataException)
{
throw new InvalidOperationException(
"The current Retro-WFC payload could not be downloaded and no valid cached " +
$"payload is available ({cacheFailure.Message.TrimEnd('.')}).", downloadFailure);
}
reporter.Diagnostic(
"The current Retro-WFC payload could not be downloaded; using the previously " +
$"verified cached payload instead ({downloadFailure.Message.TrimEnd('.')}).");
}
retroWfcOfflineDir = cacheDir; retroWfcOfflineDir = cacheDir;
} }
@@ -110,8 +110,7 @@ internal sealed class ProductRepairService
InputValidation.CurrentRetroWfcPayloadUri, payloadScratch, cancellationToken); InputValidation.CurrentRetroWfcPayloadUri, payloadScratch, cancellationToken);
} }
catch (Exception ex) when (!cancellationToken.IsCancellationRequested && catch (Exception ex) when (!cancellationToken.IsCancellationRequested &&
ex is HttpRequestException or IOException or InvalidDataException ex is HttpRequestException or TimeoutException or IOException)
or InvalidOperationException or OperationCanceledException)
{ {
payloadSnapshot = RecoverInstalledRetroWfcPayload(toolkitFingerprint, payloadSnapshot = RecoverInstalledRetroWfcPayload(toolkitFingerprint,
Path.Combine(scratchRoot, "retro-wfc-payload-recovered"), ex, cancellationToken); Path.Combine(scratchRoot, "retro-wfc-payload-recovered"), ex, cancellationToken);
+27 -13
View File
@@ -77,26 +77,40 @@ if [[ -n "$retro_dir" ]]; then
# verify its pinned signature before publishing it into the local cache. # verify its pinned signature before publishing it into the local cache.
retro_wfc_dir="$support_root/RetroWfcPayload" retro_wfc_dir="$support_root/RetroWfcPayload"
retro_wfc_payload="$retro_wfc_dir/binary/payload.RMCPD00.bin" retro_wfc_payload="$retro_wfc_dir/binary/payload.RMCPD00.bin"
if [[ -f "$retro_wfc_payload" ]] && ! "$translator" validate-retro-wfc-payload --directory "$retro_wfc_dir"; then cached_payload_valid=0
printf 'Discarding an invalid cached Retro-WFC payload...\n' >&2 if [[ -f "$retro_wfc_payload" ]]; then
rm -f "$retro_wfc_payload" if "$translator" validate-retro-wfc-payload --directory "$retro_wfc_dir"; then
cached_payload_valid=1
else
printf 'Discarding an invalid cached Retro-WFC payload...\n' >&2
rm -f "$retro_wfc_payload"
fi
fi fi
if [[ ! -f "$retro_wfc_payload" ]]; then
printf 'Downloading the Retro-WFC payload needed for online play...\n' # A signed cache may still be an older vulnerable revision, so always attempt to replace it
mkdir -p "$retro_wfc_dir" # with the current signed snapshot. A transport failure may fall back to the verified cache;
payload_stage=$(mktemp -d "$retro_wfc_dir/.payload-download.XXXXXX") # a downloaded snapshot with an invalid signature remains a hard failure.
temporary_payload="$payload_stage/binary/payload.RMCPD00.bin" printf 'Downloading the current Retro-WFC payload needed for online play...\n'
mkdir -p "$(dirname "$temporary_payload")" mkdir -p "$retro_wfc_dir"
trap 'rm -rf "$payload_stage"' EXIT payload_stage=$(mktemp -d "$retro_wfc_dir/.payload-download.XXXXXX")
/usr/bin/curl --fail --silent --show-error --connect-timeout 10 --max-time 30 \ temporary_payload="$payload_stage/binary/payload.RMCPD00.bin"
--retry 1 --output "$temporary_payload" \ mkdir -p "$(dirname "$temporary_payload")"
'https://rwfc.net/api/wfc/payload?g=RMCPD00' || fail 'could not download the Retro-WFC payload needed for online play' trap 'rm -rf "$payload_stage"' EXIT
if /usr/bin/curl --fail --silent --show-error --connect-timeout 10 --max-time 30 \
--retry 1 --output "$temporary_payload" \
'https://rwfc.net/api/wfc/payload?g=RMCPD00'; then
"$translator" validate-retro-wfc-payload --directory "$payload_stage" || \ "$translator" validate-retro-wfc-payload --directory "$payload_stage" || \
fail 'downloaded Retro-WFC payload failed signature validation' fail 'downloaded Retro-WFC payload failed signature validation'
mkdir -p "$retro_wfc_dir/binary" mkdir -p "$retro_wfc_dir/binary"
mv "$temporary_payload" "$retro_wfc_payload" mv "$temporary_payload" "$retro_wfc_payload"
rmdir "$payload_stage/binary" "$payload_stage" rmdir "$payload_stage/binary" "$payload_stage"
trap - EXIT trap - EXIT
elif (( cached_payload_valid )); then
printf 'Could not download the current Retro-WFC payload; using the previously verified cached payload.\n' >&2
rm -rf "$payload_stage"
trap - EXIT
else
fail 'could not download the current Retro-WFC payload and no valid cached payload is available'
fi fi
build_args+=(--profile both --base-output-dir "$products" --retro-rewind-package-dir "$retro_dir" --retro-wfc-offline-dir "$retro_wfc_dir") build_args+=(--profile both --base-output-dir "$products" --retro-rewind-package-dir "$retro_dir" --retro-wfc-offline-dir "$retro_wfc_dir")
fi fi