fix: сравнение SSLCertificateSHA1Hash — байты реестра vs hex thumbprint
Реестр отдаёт byte[]; TermService принимал cert, но проверка Persisted ложно падала. Добавлены ConvertTo-RdpRepairThumbprintHex и самотесты на форматы DAK-PC. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -18,6 +18,19 @@ TermService **отверг** сертификат при старте. Возм
|
|||||||
- CNG vs CSP — скрипт пробует `RSA\MachineKeys`.
|
- CNG vs CSP — скрипт пробует `RSA\MachineKeys`.
|
||||||
- Повреждение Schannel → repair install.
|
- Повреждение Schannel → repair install.
|
||||||
|
|
||||||
|
**Важно:** в реестре `SSLCertificateSHA1Hash` часто хранится как **массив байт**, а не hex-строка thumbprint. Скрипт нормализует оба формата перед сравнением. Если BEFORE и AFTER совпадают (в hex), привязка успешна — включайте `SecurityLayer=2` (`-RestoreTls`).
|
||||||
|
|
||||||
|
## Просмотр store Remote Desktop
|
||||||
|
|
||||||
|
`Get-ChildItem Cert:\LocalMachine\Remote Desktop` на части систем не работает (пробел в имени store). Используйте:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
. .\lib\RdpRepair.Common.ps1
|
||||||
|
Get-RdpRepairRemoteDesktopCertificates | Format-List
|
||||||
|
```
|
||||||
|
|
||||||
|
или `.\Fix-RdpTls.ps1 -DiagnoseOnly`.
|
||||||
|
|
||||||
## Нативный cert не создаётся после reboot
|
## Нативный cert не создаётся после reboot
|
||||||
|
|
||||||
Store `Remote Desktop` пустой после цикла «выкл RDP → очистка → вкл RDP → reboot»:
|
Store `Remote Desktop` пустой после цикла «выкл RDP → очистка → вкл RDP → reboot»:
|
||||||
|
|||||||
@@ -135,6 +135,23 @@ Assert-Test 'Registry path constants well-formed' {
|
|||||||
if ($script:RdpRepairRdpTcpKey -notmatch 'RDP-Tcp$') { throw 'bad rdp tcp key' }
|
if ($script:RdpRepairRdpTcpKey -notmatch 'RDP-Tcp$') { throw 'bad rdp tcp key' }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert-Test 'ConvertTo-RdpRepairThumbprintHex from decimal byte string' {
|
||||||
|
$hex = ConvertTo-RdpRepairThumbprintHex -HashValue '20 77 141 24 197 69 45 187 141 61 233 254 108 97 230 158 36 151 225 169'
|
||||||
|
if ($hex -ne '144D8D18C5452DBB8D3DE9FE6C61E69E2497E1A9') { throw "got $hex" }
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert-Test 'ConvertTo-RdpRepairThumbprintHex from byte array' {
|
||||||
|
$bytes = [byte[]](0x14, 0x4D, 0x8D, 0x18, 0xC5, 0x45, 0x2D, 0xBB, 0x8D, 0x3D, 0xE9, 0xFE, 0x6C, 0x61, 0xE6, 0x9E, 0x24, 0x97, 0xE1, 0xA9)
|
||||||
|
$hex = ConvertTo-RdpRepairThumbprintHex -HashValue $bytes
|
||||||
|
if ($hex -ne '144D8D18C5452DBB8D3DE9FE6C61E69E2497E1A9') { throw "got $hex" }
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert-Test 'ConvertTo-RdpRepairThumbprintHex hex equals byte forms' {
|
||||||
|
$fromHex = ConvertTo-RdpRepairThumbprintHex -HashValue '144D8D18C5452DBB8D3DE9FE6C61E69E2497E1A9'
|
||||||
|
$fromBytes = ConvertTo-RdpRepairThumbprintHex -HashValue ([byte[]](20, 77, 141, 24, 197, 69, 45, 187, 141, 61, 233, 254, 108, 97, 230, 158, 36, 151, 225, 169))
|
||||||
|
if ($fromHex -ne $fromBytes) { throw 'format mismatch' }
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@@ -56,12 +56,46 @@ function Get-RdpRepairComputerDnsNames {
|
|||||||
return $names | Select-Object -Unique
|
return $names | Select-Object -Unique
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-RdpRepairSslCertificateHash {
|
function ConvertTo-RdpRepairThumbprintHex {
|
||||||
$p = Get-ItemProperty -Path $script:RdpRepairRdpTcpKey -Name SSLCertificateSHA1Hash -ErrorAction SilentlyContinue
|
param([object]$HashValue)
|
||||||
if ($null -eq $p -or [string]::IsNullOrWhiteSpace($p.SSLCertificateSHA1Hash)) {
|
if ($null -eq $HashValue) { return $null }
|
||||||
|
|
||||||
|
if ($HashValue -is [byte[]]) {
|
||||||
|
if ($HashValue.Length -eq 0) { return $null }
|
||||||
|
return -join ($HashValue | ForEach-Object { '{0:X2}' -f $_ })
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($HashValue -is [System.Array] -and $HashValue.Count -gt 0) {
|
||||||
|
$allNumeric = $true
|
||||||
|
foreach ($b in $HashValue) {
|
||||||
|
if ($b -isnot [byte] -and $b -isnot [int] -and $b -isnot [short]) {
|
||||||
|
$allNumeric = $false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($allNumeric -and ($HashValue.Count -eq 20 -or $HashValue.Count -eq 16)) {
|
||||||
|
return -join ($HashValue | ForEach-Object { '{0:X2}' -f [byte]$_ })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = [string]$HashValue
|
||||||
|
if ([string]::IsNullOrWhiteSpace($text)) { return $null }
|
||||||
|
$text = $text.Trim()
|
||||||
|
|
||||||
|
if ($text -match '^\d+( \d+)+$') {
|
||||||
|
$bytes = $text -split '\s+' | ForEach-Object { [byte]$_ }
|
||||||
|
return -join ($bytes | ForEach-Object { '{0:X2}' -f $_ })
|
||||||
|
}
|
||||||
|
|
||||||
|
$hex = ($text -replace '\s', '').ToUpper()
|
||||||
|
if ($hex -match '^[0-9A-F]+$') { return $hex }
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
return $p.SSLCertificateSHA1Hash
|
|
||||||
|
function Get-RdpRepairSslCertificateHash {
|
||||||
|
$p = Get-ItemProperty -Path $script:RdpRepairRdpTcpKey -Name SSLCertificateSHA1Hash -ErrorAction SilentlyContinue
|
||||||
|
if ($null -eq $p -or -not $p.PSObject.Properties['SSLCertificateSHA1Hash']) { return $null }
|
||||||
|
return ConvertTo-RdpRepairThumbprintHex -HashValue $p.SSLCertificateSHA1Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-RdpRepairSecurityLayer {
|
function Get-RdpRepairSecurityLayer {
|
||||||
@@ -210,7 +244,8 @@ function Test-RdpRepairCertificateBindingPersisted {
|
|||||||
Restart-RdpRepairTermService
|
Restart-RdpRepairTermService
|
||||||
$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
|
||||||
$ok = ($after -eq $ExpectedThumbprint.ToUpper())
|
$expected = ConvertTo-RdpRepairThumbprintHex -HashValue $ExpectedThumbprint
|
||||||
|
$ok = ($after -eq $expected)
|
||||||
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