"use strict"; const { encodedCommand, parseWindowsOutput } = require("./windowsPrivilegedExec"); // Detects the remote operating system from system facts, never from prompts or host names. // 1) "uname -s" identifies POSIX systems (Linux, BSD, macOS). // 2) Otherwise a self-contained encoded PowerShell command reads the Windows version (registry, plus // Win32_OperatingSystem when WMI is permitted) and the OpenSSH DefaultShell registry value; it works whether // the default shell is cmd.exe, powershell.exe or pwsh. const POSIX_KERNELS = /^(Linux|Darwin|FreeBSD|OpenBSD|NetBSD|DragonFly|SunOS|AIX)\b/; const WINDOWS_PROBE = String.raw`$ProgressPreference='SilentlyContinue' try { # Registry first: standard accounts on an SSH network logon are usually denied WMI/CIM access. $nt = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction SilentlyContinue $shell = (Get-ItemProperty 'HKLM:\SOFTWARE\OpenSSH' -ErrorAction SilentlyContinue).DefaultShell $caption = [string]$nt.ProductName; $build = [string]$nt.CurrentBuildNumber if ($caption -match '^Windows 10' -and [int]("0$build") -ge 22000) { $caption = $caption -replace '^Windows 10', 'Windows 11' } $type = [string](Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\ProductOptions' -ErrorAction SilentlyContinue).ProductType $productType = @{ 'WinNT' = 1; 'LanmanNT' = 2; 'ServerNT' = 3 }[$type] $version = [Environment]::OSVersion.Version.ToString() try { $os = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop; $caption = $os.Caption; $version = $os.Version; $productType = [int]$os.ProductType } catch {} $value = [ordered]@{ caption = $caption; version = $version; build = $build; productType = $productType installationType = [string]$nt.InstallationType; defaultShell = [string]$shell; psVersion = $PSVersionTable.PSVersion.ToString() is64BitProcess = [Environment]::Is64BitProcess; languageMode = [string]$ExecutionContext.SessionState.LanguageMode localAccounts = [bool](Get-Command Get-LocalUser -ErrorAction SilentlyContinue); pwsh = [string](Get-Command pwsh.exe -ErrorAction SilentlyContinue).Source } [Console]::Out.WriteLine('CHJ_RESULT:' + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes(($value | ConvertTo-Json -Compress)))) } catch { [Console]::Out.WriteLine('CHJ_ERR:PLATFORM_PROBE_FAILED:' + [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($_.Exception.Message))) }`; function shellName(defaultShell) { const value = String(defaultShell || "").toLowerCase(); if (!value) return "cmd.exe"; if (/pwsh(\.exe)?$/.test(value)) return "pwsh"; if (/powershell(\.exe)?$/.test(value)) return "powershell"; if (/cmd(\.exe)?$/.test(value)) return "cmd.exe"; if (/bash(\.exe)?$/.test(value)) return "bash"; return value.split(/[\\/]/).pop(); } async function detectPlatform(sessionManager, sessionId, { refresh = false } = {}) { const record = sessionManager._requireConnected(sessionId); if (record.platform && !refresh) return record.platform; const uname = await sessionManager._execStream(record, "uname -s", { timeoutMs: 15000 }).done.catch(() => null); const kernel = String(uname?.stdout || "").trim().split(/\r?\n/)[0] || ""; if (uname?.code === 0 && POSIX_KERNELS.test(kernel)) { record.platform = { os: kernel.startsWith("Linux") ? "linux" : "posix", kernel, detectedBy: "uname" }; return record.platform; } const probe = await sessionManager._execStream(record, encodedCommand(WINDOWS_PROBE), { timeoutMs: 60000 }).done; let info; try { info = parseWindowsOutput(probe.stdout, probe.stderr, probe.code, "PLATFORM_"); } catch (error) { record.platform = { os: "unknown", kernel, detectedBy: "none", reason: error.message }; return record.platform; } record.platform = { os: "windows", detectedBy: "Win32_OperatingSystem", caption: String(info.caption || ""), version: String(info.version || ""), build: String(info.build || ""), server: Number(info.productType) !== 1, serverCore: /server core/i.test(String(info.installationType || "")), installationType: String(info.installationType || ""), defaultShell: shellName(info.defaultShell), defaultShellPath: String(info.defaultShell || ""), powershell: String(info.psVersion || ""), is64BitProcess: info.is64BitProcess === true, languageMode: String(info.languageMode || ""), localAccounts: info.localAccounts === true, pwsh: String(info.pwsh || ""), unameOutput: kernel }; return record.platform; } module.exports = { WINDOWS_PROBE, detectPlatform, shellName };