[CmdletBinding()] param( [Parameter(Mandatory)] [string]$DataRoot, [Parameter(Mandatory)] [ValidatePattern('^[A-Fa-f0-9]{40}$')] [string]$CertificateThumbprint ) $ErrorActionPreference = 'Stop' $requestsRoot = Join-Path $DataRoot 'Public\Requests' $archiveRoot = Join-Path $DataRoot 'Public\Archive' $rejectedRoot = Join-Path $DataRoot 'Public\Rejected' $registrationScript = Join-Path $env:ProgramData 'SGU\RustDesk\Register-SguRustDeskDevice.ps1' function Write-Result { param( [Parameter(Mandatory)][string]$RequestId, [Parameter(Mandatory)][hashtable]$Value ) $path = Join-Path $requestsRoot "$RequestId.result.json" [IO.File]::WriteAllText($path, ($Value | ConvertTo-Json), [Text.UTF8Encoding]::new($false)) } function Get-ComputerNameFromOwner { param([Parameter(Mandatory)][string]$Owner) if ($Owner -notmatch '^[^\\]+\\(?[A-Za-z0-9][A-Za-z0-9-]{0,62})\$$') { throw 'The request file owner is not an Active Directory computer account.' } return $Matches.Name.ToUpperInvariant() } if (-not (Test-Path -LiteralPath $registrationScript -PathType Leaf)) { throw "The RustDesk inventory registration script is missing: $registrationScript" } Import-Module ActiveDirectory -ErrorAction Stop $certificate = Get-Item -LiteralPath "Cert:\LocalMachine\My\$CertificateThumbprint" -ErrorAction Stop $rsa = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate) if (-not $rsa) { throw 'The Linux RustDesk enrollment certificate does not have an RSA private key.' } New-Item -ItemType Directory -Path $requestsRoot, $archiveRoot, $rejectedRoot -Force | Out-Null Get-ChildItem -LiteralPath $requestsRoot -Filter '*.request' -File | ForEach-Object { $requestFile = $_ $requestIdMatch = [regex]::Match($requestFile.BaseName, '(?[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$') if (-not $requestIdMatch.Success) { Move-Item -LiteralPath $requestFile.FullName -Destination (Join-Path $rejectedRoot $requestFile.Name) -Force return } $requestId = $requestIdMatch.Groups['Id'].Value try { $ownerComputerName = Get-ComputerNameFromOwner -Owner (Get-Acl -LiteralPath $requestFile.FullName).Owner $plainText = [Text.Encoding]::UTF8.GetString($rsa.Decrypt( [IO.File]::ReadAllBytes($requestFile.FullName), [Security.Cryptography.RSAEncryptionPadding]::OaepSHA256)) $request = $plainText | ConvertFrom-Json -ErrorAction Stop $computerName = [string]$request.ComputerName $rustDeskId = [string]$request.RustDeskId $accessPassword = [string]$request.AccessPassword $declaredRequestId = [string]$request.RequestId if ($computerName -notmatch '^[A-Za-z0-9][A-Za-z0-9-]{0,62}$' -or $computerName.ToUpperInvariant() -ne $ownerComputerName -or $rustDeskId -notmatch '^\d+$' -or $accessPassword.Length -lt 12 -or $declaredRequestId -notmatch '^[0-9a-fA-F-]{36}$') { throw 'The encrypted Linux RustDesk registration payload is invalid.' } Get-ADComputer -Identity $ownerComputerName -ErrorAction Stop | Out-Null & $registrationScript -ComputerName $ownerComputerName -RustDeskId $rustDeskId ` -AccessPassword $accessPassword -Confirm:$false | Out-Null Write-Result -RequestId $declaredRequestId -Value @{ Status = 'Registered' ComputerName = $ownerComputerName RustDeskId = $rustDeskId RegisteredAt = (Get-Date).ToString('o') } Move-Item -LiteralPath $requestFile.FullName -Destination (Join-Path $archiveRoot $requestFile.Name) -Force } catch { $safeError = $_.Exception.Message -replace '(?i)password[^\r\n]*', 'credential validation failed' Write-Result -RequestId $requestId -Value @{ Status = 'Rejected' Error = $safeError } Move-Item -LiteralPath $requestFile.FullName -Destination (Join-Path $rejectedRoot $requestFile.Name) -Force -ErrorAction SilentlyContinue } }