<# Take Emon's SSH access away again (Windows). https://bootstrap.ihemon.me Open PowerShell as Administrator, then: irm https://bootstrap.ihemon.me/revoke.ps1 | iex Also turn the SSH server off (only if nobody else needs SSH on this machine): & ([scriptblock]::Create((irm https://bootstrap.ihemon.me/revoke.ps1))) -StopSsh Removes exactly the Emon-Key line from C:\ProgramData\ssh\administrators_authorized_keys and from every user's .ssh\authorized_keys, and prints what it removed. Every other key stays; file permissions stay as they are. If this PC joined Emon's Tailscale as a guest (grant.ps1 -TailscaleKey), it is logged out of it; a Tailscale of your own (not a guest) is left alone. Needs no internet. Leaves nothing behind. #> param([switch]$StopSsh, [switch]$Force) # Emon-Key (SHA256:wVrLsx8kwxTscCD6oAcmcslPxagnZDKl1yaM2rwl39g), matched by its key blob. tests/ check blob == fingerprint. $EmonKeyBlob = 'AAAAC3NzaC1lZDI1NTE5AAAAIJQNrt4zH0k6C2G4Y7fZX+4S73gLZvrHodPTl2hELfWk' # Emon's tailnet (MagicDNS suffix): only a guest-* node with tag:guest IN this tailnet is ever logged out. $TailnetSuffix = 'tailbdfb8.ts.net' function Write-Step([string]$Text) { Write-Host ''; Write-Host "==> $Text" -ForegroundColor Cyan } function Write-Note([string]$Text) { Write-Host " $Text" } function Remove-KeyLine { # Removes every line containing $Blob from $Path, in place (the file and its ACL stay). Returns the count. param([string]$Path, [string]$Blob) # Latin-1 maps every byte to one char and back, so comments in any encoding are written back unchanged. $enc = [Text.Encoding]::GetEncoding(28591) $text = [IO.File]::ReadAllText($Path, $enc) if (-not $text.Contains($Blob)) { return 0 } $lines = @($text -split "`r?`n") $keep = @($lines | Where-Object { -not $_.Contains($Blob) }) $removed = $lines.Count - $keep.Count while ($keep.Count -gt 0 -and $keep[-1] -eq '') { $keep = @($keep | Select-Object -First ($keep.Count - 1)) } $out = if ($keep.Count) { ($keep -join "`r`n") + "`r`n" } else { '' } [IO.File]::WriteAllText($Path, $out, $enc) return $removed } function Get-AuthorizedKeyFileList { $files = @(Join-Path $env:ProgramData 'ssh\administrators_authorized_keys') $list = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' foreach ($k in @(Get-ChildItem -LiteralPath $list -ErrorAction SilentlyContinue)) { $p = (Get-ItemProperty -LiteralPath $k.PSPath -ErrorAction SilentlyContinue).ProfileImagePath if ($p) { $files += Join-Path ([Environment]::ExpandEnvironmentVariables($p)) '.ssh\authorized_keys' } } return @($files | Select-Object -Unique) } function Exit-TailscaleGuest { # Logs out of Emon's tailnet, but only a guest node (tag:guest) that grant.ps1 -TailscaleKey joined. # -> $true ok/nothing to do, $false failed param([string]$Exe) $exe = $Exe if (-not $exe -and $env:ProgramFiles) { $exe = Join-Path $env:ProgramFiles 'Tailscale\tailscale.exe' if (-not (Test-Path -LiteralPath $exe)) { $exe = $null } } if (-not $exe) { $c = Get-Command tailscale.exe -ErrorAction SilentlyContinue if (-not $c) { return $true } $exe = $c.Source } $j = $null try { $j = (& $exe status --json --peers=false 2>$null | Out-String) | ConvertFrom-Json } catch { $j = $null } $guest = $j -and (@($j.Self.Tags) -contains 'tag:guest') -and ("$($j.Self.DNSName)" -like "guest-*.$TailnetSuffix.") if (-not $guest) { if ($j -and "$($j.BackendState)" -eq 'Running') { Write-Note "Tailscale: this computer is not one of Emon's guests; left as it is" } return $true } Write-Step 'Tailscale (guest)' & $exe logout 2>&1 | Out-Null if ($LASTEXITCODE -ne 0) { Write-Note "could not log out of Tailscale; run: & '$exe' logout"; return $false } Write-Note "logged out of Emon's Tailscale (the guest device disappears from it)" Write-Note 'Tailscale itself stays installed; uninstall it in Settings > Apps if you like.' return $true } function Invoke-EmonRevoke { param([switch]$StopSsh, [switch]$Force) $ErrorActionPreference = 'Stop' Write-Host "Remove Emon's SSH access (https://bootstrap.ihemon.me)" $id = [Security.Principal.WindowsIdentity]::GetCurrent() if (-not ([Security.Principal.WindowsPrincipal]$id).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'PowerShell is not running as Administrator. Right-click PowerShell > "Run as administrator", then run the line again.' } Write-Step "Emon's key" $total = 0 $failed = @() foreach ($f in Get-AuthorizedKeyFileList) { # One bad file (locked, no access) must not stop the others. try { if (-not (Test-Path -LiteralPath $f -PathType Leaf)) { continue } $n = Remove-KeyLine -Path $f -Blob $EmonKeyBlob if ($n -gt 0) { Write-Note "removed $n Emon-Key line(s) from $f"; $total += $n } } catch { Write-Note "COULD NOT clean $f ($($_.Exception.Message)): remove the Emon-Key line by hand" $failed += $f } } if ($failed.Count) { Write-Note "NOT finished: Emon-Key may still be in: $($failed -join ', ')" } elseif ($total -eq 0) { Write-Note 'Emon-Key was not found in any authorized_keys. Nothing to remove.' } else { Write-Note 'done: Emon can no longer log in with his key. Other keys were not touched.' Write-Note '(an SSH session that is open right now keeps running until it ends or you restart)' } [void](Exit-TailscaleGuest) if ($StopSsh) { Write-Step 'SSH server' if ($env:SSH_CLIENT -and -not $Force) { throw 'you are connected over SSH: stopping SSH would cut you off. Run it on the machine itself, or add -Force.' } if (Get-Service -Name sshd -ErrorAction SilentlyContinue) { Stop-Service -Name sshd -Force Set-Service -Name sshd -StartupType Disabled if (Get-Command Disable-NetFirewallRule -ErrorAction SilentlyContinue) { Disable-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -ErrorAction SilentlyContinue } Write-Note 'OpenSSH server stopped, set to Disabled, firewall rule off (OpenSSH itself stays installed)' } else { Write-Note 'no OpenSSH server on this machine' } } else { Write-Host '' Write-Host 'SSH server left as it is. If you turned it on only for Emon and want it off too:' Write-Host ' & ([scriptblock]::Create((irm https://bootstrap.ihemon.me/revoke.ps1))) -StopSsh' } } if (-not $env:BOOTSTRAP_NO_MAIN) { # No `exit`: under `irm | iex` it would close the person's PowerShell window. try { Invoke-EmonRevoke -StopSsh:$StopSsh -Force:$Force } catch { Write-Host ''; Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red } }