fix: чтение SSLCertificateSHA1Hash через Registry API + версия 1.0.3
Усилена нормализация byte[]/Object[] из реестра; в логе версия модуля для проверки git pull; RestoreTls нормализует thumbprint. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -45,7 +45,7 @@ function Show-RdpRepairClientCacheHint {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Assert-RdpRepairAdministrator
|
Assert-RdpRepairAdministrator
|
||||||
Write-RdpRepairLog "=== Fix-RdpTls start $(Get-Date -Format o) ===" 'STEP' $logPath
|
Write-RdpRepairLog "=== Fix-RdpTls start $(Get-Date -Format o) (RdpRepair $($script:RdpRepairModuleVersion)) ===" 'STEP' $logPath
|
||||||
Write-RdpRepairLog "Компьютер: $env:COMPUTERNAME" 'INFO' $logPath
|
Write-RdpRepairLog "Компьютер: $env:COMPUTERNAME" 'INFO' $logPath
|
||||||
|
|
||||||
$report = Export-RdpRepairDiagnosticReport -LogPath $logPath
|
$report = Export-RdpRepairDiagnosticReport -LogPath $logPath
|
||||||
@@ -76,9 +76,10 @@ try {
|
|||||||
Write-RdpRepairLog 'Все cert просрочены' 'ERROR' $logPath
|
Write-RdpRepairLog 'Все cert просрочены' 'ERROR' $logPath
|
||||||
exit 2
|
exit 2
|
||||||
}
|
}
|
||||||
$thumb = $valid.Thumbprint
|
$thumb = ConvertTo-RdpRepairThumbprintHex -HashValue $valid.Thumbprint
|
||||||
|
if (-not $thumb) { throw 'Invalid certificate thumbprint' }
|
||||||
if (-not (Get-RdpRepairSslCertificateHash)) {
|
if (-not (Get-RdpRepairSslCertificateHash)) {
|
||||||
Write-RdpRepairLog "Привязка $($valid.Thumbprint)..." 'INFO' $logPath
|
Write-RdpRepairLog "Привязка $thumb..." 'INFO' $logPath
|
||||||
Set-RdpRepairCertificateBinding -Thumbprint $thumb -LogPath $logPath | Out-Null
|
Set-RdpRepairCertificateBinding -Thumbprint $thumb -LogPath $logPath | Out-Null
|
||||||
}
|
}
|
||||||
$bind = Test-RdpRepairCertificateBindingPersisted -ExpectedThumbprint $thumb -LogPath $logPath
|
$bind = Test-RdpRepairCertificateBindingPersisted -ExpectedThumbprint $thumb -LogPath $logPath
|
||||||
|
|||||||
@@ -152,6 +152,16 @@ Assert-Test 'ConvertTo-RdpRepairThumbprintHex hex equals byte forms' {
|
|||||||
if ($fromHex -ne $fromBytes) { throw 'format mismatch' }
|
if ($fromHex -ne $fromBytes) { throw 'format mismatch' }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert-Test 'ConvertTo-RdpRepairThumbprintHex from int Object[] (registry style)' {
|
||||||
|
$arr = [object[]]@(20, 77, 141, 24, 197, 69, 45, 187, 141, 61, 233, 254, 108, 97, 230, 158, 36, 151, 225, 169)
|
||||||
|
$hex = ConvertTo-RdpRepairThumbprintHex -HashValue $arr
|
||||||
|
if ($hex -ne '144D8D18C5452DBB8D3DE9FE6C61E69E2497E1A9') { throw "got $hex" }
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert-Test 'RdpRepair module version set' {
|
||||||
|
if ([string]::IsNullOrWhiteSpace($script:RdpRepairModuleVersion)) { throw 'missing version' }
|
||||||
|
}
|
||||||
|
|
||||||
Assert-Test 'Export-RdpRepairDiagnosticReport writes file' {
|
Assert-Test 'Export-RdpRepairDiagnosticReport writes file' {
|
||||||
if (-not (Test-RdpRepairIsAdministrator)) {
|
if (-not (Test-RdpRepairIsAdministrator)) {
|
||||||
Write-Host ' (skip report write - not admin)' -ForegroundColor DarkYellow
|
Write-Host ' (skip report write - not admin)' -ForegroundColor DarkYellow
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Set-StrictMode -Version Latest
|
|||||||
$script:RdpRepairDataRoot = Join-Path $env:ProgramData 'RdpRepair'
|
$script:RdpRepairDataRoot = Join-Path $env:ProgramData 'RdpRepair'
|
||||||
$script:RdpRepairRdpTcpKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'
|
$script:RdpRepairRdpTcpKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'
|
||||||
$script:RdpRepairTsKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'
|
$script:RdpRepairTsKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server'
|
||||||
|
$script:RdpRepairModuleVersion = '1.0.3'
|
||||||
|
|
||||||
function Initialize-RdpRepairDataRoot {
|
function Initialize-RdpRepairDataRoot {
|
||||||
if (-not (Test-Path -LiteralPath $script:RdpRepairDataRoot)) {
|
if (-not (Test-Path -LiteralPath $script:RdpRepairDataRoot)) {
|
||||||
@@ -56,25 +57,26 @@ function Get-RdpRepairComputerDnsNames {
|
|||||||
return $names | Select-Object -Unique
|
return $names | Select-Object -Unique
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Convert-RdpRepairBytesToHex {
|
||||||
|
param([byte[]]$Bytes)
|
||||||
|
if ($null -eq $Bytes -or $Bytes.Length -eq 0) { return $null }
|
||||||
|
return -join ($Bytes | ForEach-Object { '{0:X2}' -f $_ })
|
||||||
|
}
|
||||||
|
|
||||||
function ConvertTo-RdpRepairThumbprintHex {
|
function ConvertTo-RdpRepairThumbprintHex {
|
||||||
param([object]$HashValue)
|
param([object]$HashValue)
|
||||||
if ($null -eq $HashValue) { return $null }
|
if ($null -eq $HashValue) { return $null }
|
||||||
|
|
||||||
if ($HashValue -is [byte[]]) {
|
if ($HashValue -is [byte[]]) {
|
||||||
if ($HashValue.Length -eq 0) { return $null }
|
return Convert-RdpRepairBytesToHex -Bytes $HashValue
|
||||||
return -join ($HashValue | ForEach-Object { '{0:X2}' -f $_ })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($HashValue -is [System.Array] -and $HashValue.Count -gt 0) {
|
if ($HashValue -is [System.Array] -and $HashValue.Length -gt 0) {
|
||||||
$allNumeric = $true
|
if ($HashValue.Length -ge 16 -and $HashValue.Length -le 32) {
|
||||||
foreach ($b in $HashValue) {
|
try {
|
||||||
if ($b -isnot [byte] -and $b -isnot [int] -and $b -isnot [short]) {
|
$bytes = @($HashValue | ForEach-Object { [byte]$_ })
|
||||||
$allNumeric = $false
|
return Convert-RdpRepairBytesToHex -Bytes $bytes
|
||||||
break
|
} catch { }
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($allNumeric -and ($HashValue.Count -eq 20 -or $HashValue.Count -eq 16)) {
|
|
||||||
return -join ($HashValue | ForEach-Object { '{0:X2}' -f [byte]$_ })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,19 +85,34 @@ function ConvertTo-RdpRepairThumbprintHex {
|
|||||||
$text = $text.Trim()
|
$text = $text.Trim()
|
||||||
|
|
||||||
if ($text -match '^\d+( \d+)+$') {
|
if ($text -match '^\d+( \d+)+$') {
|
||||||
$bytes = $text -split '\s+' | ForEach-Object { [byte]$_ }
|
$bytes = @($text -split '\s+' | ForEach-Object { [byte]$_ })
|
||||||
return -join ($bytes | ForEach-Object { '{0:X2}' -f $_ })
|
return Convert-RdpRepairBytesToHex -Bytes $bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
$hex = ($text -replace '\s', '').ToUpper()
|
$hex = ($text -replace '\s', '').ToUpper()
|
||||||
if ($hex -match '^[0-9A-F]+$') { return $hex }
|
if ($hex -match '^[0-9A-F]{32,40}$') { return $hex }
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-RdpRepairSslCertificateHash {
|
function Get-RdpRepairSslCertificateHashRaw {
|
||||||
$p = Get-ItemProperty -Path $script:RdpRepairRdpTcpKey -Name SSLCertificateSHA1Hash -ErrorAction SilentlyContinue
|
$regSubKey = 'SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'
|
||||||
|
try {
|
||||||
|
$key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($regSubKey, $false)
|
||||||
|
if ($key) {
|
||||||
|
try {
|
||||||
|
return $key.GetValue('SSLCertificateSHA1Hash', $null)
|
||||||
|
} finally {
|
||||||
|
$key.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch { }
|
||||||
|
$p = Get-ItemProperty -LiteralPath $script:RdpRepairRdpTcpKey -Name SSLCertificateSHA1Hash -ErrorAction SilentlyContinue
|
||||||
if ($null -eq $p -or -not $p.PSObject.Properties['SSLCertificateSHA1Hash']) { return $null }
|
if ($null -eq $p -or -not $p.PSObject.Properties['SSLCertificateSHA1Hash']) { return $null }
|
||||||
return ConvertTo-RdpRepairThumbprintHex -HashValue $p.SSLCertificateSHA1Hash
|
return $p.SSLCertificateSHA1Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-RdpRepairSslCertificateHash {
|
||||||
|
return ConvertTo-RdpRepairThumbprintHex -HashValue (Get-RdpRepairSslCertificateHashRaw)
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-RdpRepairSecurityLayer {
|
function Get-RdpRepairSecurityLayer {
|
||||||
@@ -245,7 +262,10 @@ function Test-RdpRepairCertificateBindingPersisted {
|
|||||||
$after = Get-RdpRepairSslCertificateHash
|
$after = Get-RdpRepairSslCertificateHash
|
||||||
Write-RdpRepairLog "Hash AFTER TermService start: $(if ($after) { $after } else { '(empty)' })" 'INFO' $LogPath
|
Write-RdpRepairLog "Hash AFTER TermService start: $(if ($after) { $after } else { '(empty)' })" 'INFO' $LogPath
|
||||||
$expected = ConvertTo-RdpRepairThumbprintHex -HashValue $ExpectedThumbprint
|
$expected = ConvertTo-RdpRepairThumbprintHex -HashValue $ExpectedThumbprint
|
||||||
$ok = ($after -eq $expected)
|
$ok = ($null -ne $after) -and ($null -ne $expected) -and ($after -eq $expected)
|
||||||
|
if (-not $ok) {
|
||||||
|
Write-RdpRepairLog "Hash compare: expected=$expected after=$after before=$before" 'INFO' $LogPath
|
||||||
|
}
|
||||||
if ($ok) {
|
if ($ok) {
|
||||||
Write-RdpRepairLog 'Привязка cert принята TermService' 'OK' $LogPath
|
Write-RdpRepairLog 'Привязка cert принята TermService' 'OK' $LogPath
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user