diff --git a/app/SignOnly_detect.ps1 b/app/SignOnly_detect.ps1 index 23f009f..74a99f5 100644 --- a/app/SignOnly_detect.ps1 +++ b/app/SignOnly_detect.ps1 @@ -1,5 +1,6 @@ # ============================================================ # CHANGELOG +# v1.3 - Added detailed logging for detect failures # v1.2 - Get-DesktopPaths: Depth 2 search for OneDrive Desktop # v1.1 - AllUsers switch + Get-DesktopPaths helper # v1.0 - Initial @@ -9,6 +10,21 @@ param( [switch]$AllUsers ) +# Setup logging +$baseFolder = Join-Path $env:SystemDrive "Intune" +$logFile = Join-Path $baseFolder "RDPSign.log" + +if (-not (Test-Path $baseFolder)) { + New-Item -Path $baseFolder -ItemType Directory -Force | Out-Null +} + +function Write-Log { + param($Message) + $logMessage = "$(Get-Date -Format 'dd-MM-yyyy HH:mm'): $Message" + Add-Content -Path $logFile -Value $logMessage + Write-Host $logMessage +} + function Get-DesktopPaths { if ($AllUsers) { Get-ChildItem "$env:SystemDrive\Users" -Directory -Exclude "Public","Default" | ForEach-Object { @@ -19,40 +35,79 @@ function Get-DesktopPaths { [Environment]::GetFolderPath("CommonDesktopDirectory") } } -$certSubject = "CN=RDPSign" -# Check certificate exists in all three stores -$certInMy = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -eq $certSubject } -$certInRoot = Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -eq $certSubject } -$certInPub = Get-ChildItem Cert:\LocalMachine\TrustedPublisher | Where-Object { $_.Subject -eq $certSubject } +try { + Write-Log "=== SignOnly Detect START ===" + Write-Log "Running in mode: $(if ($AllUsers) { 'All Users' } else { 'Public Desktop' })" -if (-not $certInMy -or -not $certInRoot -or -not $certInPub) { - exit 1 -} + $certSubject = "CN=RDPSign" -# Check registry thumbprint -$gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" -$thumbprintValue = (Get-ItemProperty -Path $gpoPath -Name "TrustedCertThumbprints" -ErrorAction SilentlyContinue).TrustedCertThumbprints -if ([string]::IsNullOrWhiteSpace($thumbprintValue)) { - exit 1 -} + # Check certificate exists in all three stores + Write-Log "Checking certificate: $certSubject..." + $certInMy = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -eq $certSubject } + $certInRoot = Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -eq $certSubject } + $certInPub = Get-ChildItem Cert:\LocalMachine\TrustedPublisher | Where-Object { $_.Subject -eq $certSubject } -# Check that all RDP files on desktop(s) are signed -foreach ($desktopPath in (Get-DesktopPaths)) { - $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" -ErrorAction SilentlyContinue - - if ($rdpFiles.Count -eq 0) { + $certOk = $true + if (-not $certInMy) { + Write-Log "FAIL: Certificate not found in LocalMachine\My" + $certOk = $false + } + if (-not $certInRoot) { + Write-Log "FAIL: Certificate not found in LocalMachine\Root" + $certOk = $false + } + if (-not $certInPub) { + Write-Log "FAIL: Certificate not found in LocalMachine\TrustedPublisher" + $certOk = $false + } + if (-not $certOk) { exit 1 } + Write-Log "OK: Certificate found in all stores" - foreach ($file in $rdpFiles) { - $content = Get-Content $file.FullName -ErrorAction SilentlyContinue - $hasSig = $content | Where-Object { $_ -match "^signature:s:" } - if (-not $hasSig) { - exit 1 - } + # Check registry thumbprint + Write-Log "Checking registry thumbprint..." + $gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" + $thumbprintValue = (Get-ItemProperty -Path $gpoPath -Name "TrustedCertThumbprints" -ErrorAction SilentlyContinue).TrustedCertThumbprints + if ([string]::IsNullOrWhiteSpace($thumbprintValue)) { + Write-Log "FAIL: TrustedCertThumbprints not found in registry" + exit 1 } -} + Write-Log "OK: Thumbprint found in registry" -Write-Host "Detected" -exit 0 + # Check that all RDP files on desktop(s) are signed + Write-Log "Checking RDP file signatures..." + $desktopsChecked = 0 + $filesChecked = 0 + + foreach ($desktopPath in (Get-DesktopPaths)) { + $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" -ErrorAction SilentlyContinue + + if ($rdpFiles.Count -eq 0) { + Write-Log "Skip: No .rdp files on $desktopPath" + continue + } + + Write-Log "Found $($rdpFiles.Count) file(s) to check on: $desktopPath" + + foreach ($file in $rdpFiles) { + $filesChecked++ + $content = Get-Content $file.FullName -ErrorAction SilentlyContinue + $hasSig = $content | Where-Object { $_ -match "^signature:s:" } + if (-not $hasSig) { + Write-Log "FAIL: $($file.Name) on $desktopPath is not signed" + exit 1 + } + } + $desktopsChecked++ + } + + Write-Log "OK: All $filesChecked file(s) across $desktopsChecked desktop(s) are signed" + Write-Log "=== SignOnly Detect END - Installed ===" + exit 0 +} +catch { + Write-Log "Error: $_" + exit 1 +} diff --git a/app/sandbox_signonly.ps1 b/app/sandbox_signonly.ps1 new file mode 100644 index 0000000..e5e3fff --- /dev/null +++ b/app/sandbox_signonly.ps1 @@ -0,0 +1,234 @@ +# ============================================================ +# SIGNONLY + DETECT - Sandbox test script +# ============================================================ +# CHANGELOG +# v1.0 - Initial +# ============================================================ + +param( + [switch]$AllUsers +) +Start-Sleep -Seconds 10 +# Setup logging +$baseFolder = Join-Path $env:SystemDrive "Intune" +$logFile = Join-Path $baseFolder "RDPSign.log" + +# Check if Sysnative exists (means script is running in 32-bit mode on x64 OS) +if (Test-Path "$($env:windir)\Sysnative") { + $rdpSignPath = "$($env:windir)\Sysnative\rdpsign.exe" +} else { + $rdpSignPath = "$($env:windir)\System32\rdpsign.exe" +} + +if (-not (Test-Path $baseFolder)) { + New-Item -Path $baseFolder -ItemType Directory -Force | Out-Null +} + +function Write-Log { + param($Message) + $logMessage = "$(Get-Date -Format 'dd-MM-yyyy HH:mm'): $Message" + Add-Content -Path $logFile -Value $logMessage + Write-Host $logMessage +} + +function Get-DesktopPaths { + if ($AllUsers) { + Get-ChildItem "$env:SystemDrive\Users" -Directory -Exclude "Public","Default" | ForEach-Object { + Get-ChildItem $_.FullName -Directory -Filter "Desktop" -Depth 2 -ErrorAction SilentlyContinue | + Select-Object -ExpandProperty FullName + } + } else { + [Environment]::GetFolderPath("CommonDesktopDirectory") + } +} + +# ============================================================ +# SIGNONLY +# ============================================================ +Write-Log "=== START SIGNONLY ===" +Write-Log "Running in mode: $(if ($AllUsers) { 'All Users' } else { 'Public Desktop' })" + +try { + $certSubjectName = "RDPSign" + $certSubject = "CN=$certSubjectName" + + Write-Log "Searching for existing certificate: $certSubjectName..." + $existingCert = Get-ChildItem Cert:\LocalMachine\My | + Where-Object { $_.Subject -eq $certSubject } | + Select-Object -First 1 + + if ($existingCert) { + Write-Log "Found existing certificate with Thumbprint: $($existingCert.Thumbprint)" + $thumbprint = $existingCert.Thumbprint + } else { + Write-Log "No existing certificate found. Creating new one..." + + $cert = New-SelfSignedCertificate ` + -Subject $certSubject ` + -CertStoreLocation "Cert:\LocalMachine\My" ` + -Type CodeSigningCert ` + -KeyExportPolicy NonExportable ` + -NotAfter (Get-Date).AddYears(25) + + $thumbprint = $cert.Thumbprint + + # Add to Trusted Root + $rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("Root", "LocalMachine") + $rootStore.Open("ReadWrite") + $rootStore.Add($cert) + $rootStore.Close() + + # Add to Trusted Publishers + $pubStore = New-Object System.Security.Cryptography.X509Certificates.X509Store("TrustedPublisher", "LocalMachine") + $pubStore.Open("ReadWrite") + $pubStore.Add($cert) + $pubStore.Close() + + # Add thumbprint to RDP trusted certs in registry + $gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" + $keyName = "TrustedCertThumbprints" + + if (-not (Test-Path $gpoPath)) { + New-Item -Path $gpoPath -Force | Out-Null + } + + $currentValue = (Get-ItemProperty -Path $gpoPath -Name $keyName -ErrorAction SilentlyContinue).$keyName + + if ($currentValue -notmatch [regex]::Escape($thumbprint)) { + $newValue = if ([string]::IsNullOrWhiteSpace($currentValue)) { $thumbprint } else { "$currentValue,$thumbprint" } + + if ($null -eq $currentValue) { + New-ItemProperty -Path $gpoPath -Name $keyName -Value $newValue -PropertyType String -Force | Out-Null + } else { + Set-ItemProperty -Path $gpoPath -Name $keyName -Value $newValue + } + Write-Log "Updated TrustedCertThumbprints registry value." + } else { + Write-Log "Thumbprint already exists in registry. Skipping update." + } + + Write-Log "Certificate created and trusted successfully." + } + + $successCount = 0 + $failCount = 0 + + foreach ($desktopPath in (Get-DesktopPaths)) { + $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" -Recurse -ErrorAction SilentlyContinue + + if ($rdpFiles.Count -eq 0) { + Write-Log "Skip: No .rdp files on $desktopPath" + continue + } + + Write-Log "Found $($rdpFiles.Count) file(s) to sign on: $desktopPath" + + foreach ($rdpFile in $rdpFiles) { + Write-Log "Signing: $($rdpFile.Name)" + & $rdpSignPath /sha256 $thumbprint $rdpFile.FullName + + if ($LASTEXITCODE -eq 0) { + Write-Log " [OK] $($rdpFile.Name)" + $successCount++ + } else { + Write-Log " [FAILED] $($rdpFile.Name) - rdpsign exit code: $LASTEXITCODE" + $failCount++ + } + } + } + + # Set registry key to suppress RDP warning dialogs + reg add "HKLM\Software\Policies\Microsoft\Windows NT\Terminal Services\Client" /v RedirectionWarningDialogVersion /t REG_DWORD /d 1 /f + + if ($failCount -eq 0) { + Write-Log "All $successCount file(s) signed successfully." + } else { + Write-Log "$successCount file(s) signed successfully, $failCount file(s) failed." + } + +} catch { + Write-Log "SIGNONLY error: $_" +} + +# ============================================================ +# DETECT +# ============================================================ +Write-Log "=== START DETECT ===" + +try { + $certSubject = "CN=RDPSign" + + Write-Log "Checking certificate: $certSubject..." + $certInMy = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -eq $certSubject } + $certInRoot = Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -eq $certSubject } + $certInPub = Get-ChildItem Cert:\LocalMachine\TrustedPublisher | Where-Object { $_.Subject -eq $certSubject } + + $certOk = $true + if (-not $certInMy) { + Write-Log "FAIL: Certificate not found in LocalMachine\My" + $certOk = $false + } + if (-not $certInRoot) { + Write-Log "FAIL: Certificate not found in LocalMachine\Root" + $certOk = $false + } + if (-not $certInPub) { + Write-Log "FAIL: Certificate not found in LocalMachine\TrustedPublisher" + $certOk = $false + } + if (-not $certOk) { + Write-Log "DETECT [FAIL]: Certificate missing" + } else { + Write-Log "OK: Certificate found in all stores" + } + + # Check registry thumbprint + Write-Log "Checking registry thumbprint..." + $gpoPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" + $thumbprintValue = (Get-ItemProperty -Path $gpoPath -Name "TrustedCertThumbprints" -ErrorAction SilentlyContinue).TrustedCertThumbprints + if ([string]::IsNullOrWhiteSpace($thumbprintValue)) { + Write-Log "FAIL: TrustedCertThumbprints not found in registry" + $certOk = $false + } else { + Write-Log "OK: Thumbprint found in registry" + } + + # Check that all RDP files on desktop(s) are signed + Write-Log "Checking RDP file signatures..." + $desktopsChecked = 0 + $filesChecked = 0 + $allSigned = $true + + foreach ($desktopPath in (Get-DesktopPaths)) { + $rdpFiles = Get-ChildItem -Path $desktopPath -Filter "*.rdp" -ErrorAction SilentlyContinue + + if ($rdpFiles.Count -eq 0) { + Write-Log "Skip: No .rdp files on $desktopPath" + continue + } + + Write-Log "Found $($rdpFiles.Count) file(s) to check on: $desktopPath" + + foreach ($file in $rdpFiles) { + $filesChecked++ + $content = Get-Content $file.FullName -ErrorAction SilentlyContinue + $hasSig = $content | Where-Object { $_ -match "^signature:s:" } + if (-not $hasSig) { + Write-Log "FAIL: $($file.Name) on $desktopPath is not signed" + $allSigned = $false + } + } + $desktopsChecked++ + } + + if ($allSigned -and $certOk) { + Write-Log "DETECT [OK]: $filesChecked file(s) across $desktopsChecked desktop(s) - all signed and configured" + exit 0 + } else { + Write-Log "DETECT [FAIL]: Check log for details" + exit 1 + } +} catch { + Write-Log "Detect error: $_" + exit 1 +} diff --git a/output/Install.intunewin b/output/Install.intunewin new file mode 100644 index 0000000..e7334cd Binary files /dev/null and b/output/Install.intunewin differ