mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-10 14:02:47 +00:00
The previous text match on signtool output was flaky: signtool interleaves stdout (chain details) and stderr (error), so the wrapped "untrusted root" phrase stayed contiguous for one file but was split for another, causing the verify step to pass orca-slicer.exe but throw on OrcaSlicer.dll. Use Get-AuthenticodeSignature instead, whose StatusMessage is a single clean string, to decide the untrusted-root exception. signtool remains the strict primary check; this only governs the -AllowUntrustedRoot test-cert path.
116 lines
4.1 KiB
PowerShell
116 lines
4.1 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[ValidateScript({ Test-Path -LiteralPath $_ -PathType Container })]
|
|
[string]$ArtifactDirectory,
|
|
|
|
[string[]]$Files = @(
|
|
"orca-slicer.exe",
|
|
"OrcaSlicer.dll"
|
|
),
|
|
|
|
[string]$SignToolPath,
|
|
|
|
# Accept signatures whose certificate chain terminates in an untrusted root.
|
|
# Required for the SignPath test certificate (self-signed). Do NOT pass this
|
|
# once a production CA-issued certificate is in use, so release builds enforce
|
|
# a fully trusted chain.
|
|
[switch]$AllowUntrustedRoot
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
function Resolve-SignToolPath {
|
|
param(
|
|
[string]$ExplicitPath
|
|
)
|
|
|
|
if ($ExplicitPath) {
|
|
if (Test-Path -LiteralPath $ExplicitPath -PathType Leaf) {
|
|
return (Resolve-Path -LiteralPath $ExplicitPath).Path
|
|
}
|
|
|
|
throw "SignTool was not found at '$ExplicitPath'."
|
|
}
|
|
|
|
$fromPath = Get-Command -Name "signtool.exe" -ErrorAction SilentlyContinue
|
|
if ($fromPath) {
|
|
return $fromPath.Source
|
|
}
|
|
|
|
$candidateRoots = @(
|
|
"${env:ProgramFiles(x86)}\Windows Kits\10\bin",
|
|
"${env:ProgramFiles}\Windows Kits\10\bin"
|
|
) | Where-Object { $_ -and (Test-Path -LiteralPath $_ -PathType Container) }
|
|
|
|
foreach ($root in $candidateRoots) {
|
|
$candidate = Get-ChildItem -LiteralPath $root -Recurse -Filter "signtool.exe" -File -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.FullName -match "\\(x64|arm64)\\signtool\.exe$" } |
|
|
Sort-Object -Property FullName -Descending |
|
|
Select-Object -First 1
|
|
|
|
if ($candidate) {
|
|
return $candidate.FullName
|
|
}
|
|
}
|
|
|
|
throw "signtool.exe was not found. Install the Windows SDK or pass -SignToolPath."
|
|
}
|
|
|
|
$artifactRoot = (Resolve-Path -LiteralPath $ArtifactDirectory).Path
|
|
$signtool = Resolve-SignToolPath -ExplicitPath $SignToolPath
|
|
|
|
Write-Host "Using SignTool: $signtool"
|
|
Write-Host "Verifying Authenticode signatures in: $artifactRoot"
|
|
|
|
foreach ($relativePath in $Files) {
|
|
$filePath = Join-Path $artifactRoot $relativePath
|
|
if (-not (Test-Path -LiteralPath $filePath -PathType Leaf)) {
|
|
throw "Expected signed file was not found: $filePath"
|
|
}
|
|
|
|
Write-Host "Verifying $relativePath"
|
|
|
|
# Capture signtool output without letting native stderr (redirected via 2>&1)
|
|
# raise a terminating NativeCommandError under $ErrorActionPreference = 'Stop'.
|
|
$previousErrorActionPreference = $ErrorActionPreference
|
|
$ErrorActionPreference = "Continue"
|
|
try {
|
|
$output = & $signtool verify /pa /all /tw /v $filePath 2>&1
|
|
$exitCode = $LASTEXITCODE
|
|
}
|
|
finally {
|
|
$ErrorActionPreference = $previousErrorActionPreference
|
|
}
|
|
|
|
$output | ForEach-Object { Write-Host $_ }
|
|
|
|
if ($exitCode -eq 0) {
|
|
continue
|
|
}
|
|
|
|
if ($AllowUntrustedRoot) {
|
|
# signtool interleaves its stdout (chain details) and stderr (the error)
|
|
# unpredictably, so the error text cannot be matched reliably. Use the
|
|
# structured Get-AuthenticodeSignature result instead: accept only when the
|
|
# file is genuinely signed and the sole problem is that the chain terminates
|
|
# in an untrusted root (i.e. the self-signed SignPath test certificate).
|
|
$signature = Get-AuthenticodeSignature -LiteralPath $filePath
|
|
$isSigned = ($signature.SignatureType -eq "Authenticode") -and ($null -ne $signature.SignerCertificate)
|
|
$untrustedRootOnly = $signature.StatusMessage -match "terminated in a root certificate which is not trusted"
|
|
if ($isSigned -and $untrustedRootOnly) {
|
|
Write-Host " Accepted: '$relativePath' is signed but its certificate chains to an untrusted root (expected for the SignPath test certificate)."
|
|
continue
|
|
}
|
|
}
|
|
|
|
throw "SignTool verification failed for '$relativePath' with exit code $exitCode."
|
|
}
|
|
|
|
Write-Host "Authenticode verification passed."
|
|
|
|
# signtool exits non-zero for the untrusted test-cert root even when we accept
|
|
# it above, leaving $LASTEXITCODE = 1. The GitHub Actions pwsh wrapper exits
|
|
# with that lingering code, so reset it to report success explicitly.
|
|
exit 0
|