RedFlag/installer/windows/test-agent-verifier.ps1
Fimeg 765ec4188f publish: carry the Windows product into the projection
The tree adds the installer, service and test paths admitted by this source commit. Nothing else changes about what may cross.

Source-Sha: 3e4a3aa4ce092e9e3f51bc78daf3ddc14d9638f8

Policy-Sha: 3e4a3aa4ce092e9e3f51bc78daf3ddc14d9638f8

Tree-Digest: 89d6fce3828a0e0de0c8eeb41ee6750f4462217e2a04b5190297134d7f4a50c3
2026-09-09 12:47:34 -04:00

84 lines
4.5 KiB
PowerShell

# Run in elevated Windows PowerShell 5.1 and PowerShell 7 with operator-installed
# OpenSSL 3 on PATH. Loads only verifier functions; never installs an agent.
$ErrorActionPreference = "Stop"
$Template = Join-Path $PSScriptRoot "../../server/internal/services/templates/install/scripts/windows.ps1.tmpl"
$Tokens = $null
$ParseErrors = $null
$AST = [System.Management.Automation.Language.Parser]::ParseFile(
(Resolve-Path $Template).Path, [ref]$Tokens, [ref]$ParseErrors)
if ($ParseErrors.Count -ne 0) { throw ($ParseErrors | Out-String) }
$Names = @("Convert-HexToBytes", "Stop-Install", "Remove-InstallerScratchDirectory",
"New-InstallerScratchDirectory", "Test-Ed25519Signature", "Assert-Ed25519Verifier")
foreach ($Name in $Names) {
$Function = $AST.Find({ param($Node)
$Node -is [System.Management.Automation.Language.FunctionDefinitionAst] -and $Node.Name -eq $Name
}, $true)
if (-not $Function) { throw "Missing function: $Name" }
. ([scriptblock]::Create($Function.Extent.Text))
}
Assert-Ed25519Verifier
$Key = Convert-HexToBytes "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c"
$Sig = Convert-HexToBytes "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00"
$Message = [byte[]]@(0x72)
$WrongKey = Convert-HexToBytes "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"
if (Test-Ed25519Signature $Message $Sig $WrongKey) { throw "Wrong key accepted" }
$Sig[0] = $Sig[0] -bxor 1
if (Test-Ed25519Signature $Message $Sig $Key) { throw "Tampered signature accepted" }
$Rejected = $false
try { Test-Ed25519Signature $Message ([byte[]]@(1)) $Key | Out-Null } catch { $Rejected = $true }
if (-not $Rejected) { throw "Malformed signature accepted" }
$Rejected = $false
try { Test-Ed25519Signature $Message $Sig ([byte[]]@(1)) | Out-Null } catch { $Rejected = $true }
if (-not $Rejected) { throw "Malformed key accepted" }
$script:Ed25519OpenSSL = $null
$Rejected = $false
try { Test-Ed25519Signature $Message $Sig $Key | Out-Null } catch { $Rejected = $true }
if (-not $Rejected) { throw "Missing verifier accepted" }
# Cleanup must report its own trouble as a warning and leave the real failure
# standing. Removing an absent directory is the cheapest way to force that path.
$Warnings = @()
Remove-InstallerScratchDirectory -Path (Join-Path ([System.IO.Path]::GetTempPath()) "redflag-absent-$([guid]::NewGuid().ToString('N'))") -WarningVariable +Warnings -WarningAction SilentlyContinue
if ($Warnings.Count -eq 0) { throw "Cleanup of a missing directory raised no warning" }
$script:Ed25519OpenSSL = $null
$Primary = $null
try {
try { throw "PRIMARY FAILURE" } finally {
Remove-InstallerScratchDirectory -Path (Join-Path ([System.IO.Path]::GetTempPath()) "redflag-absent-$([guid]::NewGuid().ToString('N'))") -WarningAction SilentlyContinue
}
} catch { $Primary = $_.Exception.Message }
if ($Primary -ne "PRIMARY FAILURE") { throw "Cleanup masked the primary failure: got '$Primary'" }
# Stop-Install exits; run it in a child PowerShell so this script survives.
# The regression it guards: with $ErrorActionPreference = "Stop", a bare
# Write-Error inside the desktop try/catch threw, was caught by that catch,
# printed as a skip warning, and the installer exited 0 on a hash mismatch.
$Self = (Get-Process -Id $PID).Path
$Probe = @"
`$ErrorActionPreference = "Stop"
$($AST.Find({ param($n) $n -is [System.Management.Automation.Language.FunctionDefinitionAst] -and $n.Name -eq "Stop-Install" }, $true).Extent.Text)
try {
Stop-Install @("REFUSAL LINE 1", "REFUSAL LINE 2", "REFUSAL LINE 3")
} catch {
Write-Host "SWALLOWED BY CATCH"
}
Write-Host "CONTINUED PAST REFUSAL"
"@
$ProbeFile = Join-Path ([System.IO.Path]::GetTempPath()) "redflag-probe-$([guid]::NewGuid().ToString('N')).ps1"
Set-Content -LiteralPath $ProbeFile -Value $Probe
try {
$Output = & $Self -NoProfile -File $ProbeFile 2>&1 | Out-String
$Code = $LASTEXITCODE
} finally {
Remove-InstallerScratchDirectory -Path $ProbeFile
}
if ($Code -ne 1) { throw "Refusal exited $Code, expected 1" }
if ($Output -match "SWALLOWED BY CATCH") { throw "An enclosing catch swallowed the refusal" }
if ($Output -match "CONTINUED PAST REFUSAL") { throw "Installer continued past a refusal" }
foreach ($n in 1..3) {
if ($Output -notmatch "REFUSAL LINE $n") { throw "Diagnostic line $n never reached the operator" }
}
Write-Host "PASS: exact installer functions accept valid signatures and reject tampering, wrong keys, malformed inputs, and missing verifier; cleanup warns without masking."