mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 01:00:18 +02:00
- No switching headsets (or changing the active one's user/port, or removing it) while installs run: they read the ssh settings step by step. - Switching reroutes every command to the new headset at once, even if it never answers. - ~/.ssh/config edits are serialized, use unique temp files, and back off if another program wrote the file meanwhile. - stop() ends a handshake in progress and joins the connector. - Pinned keys are written unhashed (HashKnownHosts=no); hashed ones are still found and forgotten via ssh-keygen. - Set Up Connection changing a headset's user or port updates the registry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
80 lines
2.8 KiB
Python
Executable File
80 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""A stand-in for OpenSSH's ssh, for tests/test_link.py: prints what `ssh -v` prints at
|
|
each step of a connection, and plays a ControlMaster. What each HostName does comes
|
|
from $FAKESSH_HOSTS (JSON: host -> "ok", "wrong" (a different host key), "denied" or
|
|
"slow" (hangs after connecting);
|
|
every call is appended to $FAKESSH_LOG as a JSON line. POSIX only."""
|
|
import json
|
|
import os
|
|
import signal
|
|
import sys
|
|
import time
|
|
|
|
args = sys.argv[1:]
|
|
with open(os.environ["FAKESSH_LOG"], "a") as f:
|
|
f.write(json.dumps(args) + "\n")
|
|
hosts = json.loads(os.environ.get("FAKESSH_HOSTS", "{}"))
|
|
opts = {}
|
|
i = 0
|
|
while i < len(args) and args[i].startswith("-"):
|
|
if args[i] in ("-o", "-O", "-p", "-l"):
|
|
key = args[i]
|
|
val = args[i + 1]
|
|
if key == "-o":
|
|
k, _, v = val.partition("=")
|
|
opts[k.lower()] = v
|
|
else:
|
|
opts[key] = val
|
|
i += 2
|
|
else:
|
|
opts[args[i]] = True
|
|
i += 1
|
|
alias = args[i] if i < len(args) else ""
|
|
host = opts.get("hostname", alias).replace("%%", "%")
|
|
marker = os.path.join(os.environ["FAKESSH_DIR"], "master-" + host.replace("/", "_"))
|
|
say = lambda s: (sys.stderr.write(s + "\n"), sys.stderr.flush())
|
|
|
|
if "-G" in opts:
|
|
print(f"hostname {alias}\nport 22\nuser tester")
|
|
sys.exit(0)
|
|
if opts.get("-O") == "check":
|
|
sys.exit(0 if os.path.exists(marker) else 255)
|
|
if opts.get("-O") == "exit":
|
|
if os.path.exists(marker):
|
|
os.unlink(marker)
|
|
sys.exit(0)
|
|
|
|
what = hosts.get(host)
|
|
if what is None:
|
|
say(f"ssh: Could not resolve hostname {host}: nodename nor servname provided, or not known")
|
|
sys.exit(255)
|
|
say(f"debug1: Connecting to {host} [127.0.0.1] port {opts.get('port', 22)}.")
|
|
say("debug1: Connection established.")
|
|
if what == "slow":
|
|
time.sleep(30)
|
|
say(f"debug1: Authenticating to {host}:22 as '{opts.get('user', 'tester')}'")
|
|
say("debug1: Server host key: ssh-ed25519 SHA256:fakefakefakefakefakefakefakefakefakefakefak")
|
|
if what == "wrong":
|
|
say("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
|
|
say("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @")
|
|
say("Host key verification failed.")
|
|
sys.exit(255)
|
|
say(f"debug1: Host '{opts.get('hostkeyalias', host)}' is known and matches the ED25519 host key.")
|
|
say("debug1: Next authentication method: publickey")
|
|
if what == "denied":
|
|
say(f"tester@{host}: Permission denied (publickey).")
|
|
sys.exit(255)
|
|
say(f'Authenticated to {host} ([127.0.0.1]:22) using "publickey".')
|
|
if opts.get("controlmaster") == "yes":
|
|
open(marker, "w").close()
|
|
def bye(*_):
|
|
if os.path.exists(marker):
|
|
os.unlink(marker)
|
|
sys.exit(0)
|
|
signal.signal(signal.SIGTERM, bye)
|
|
while True:
|
|
time.sleep(0.2)
|
|
if not os.path.exists(marker):
|
|
sys.exit(0)
|
|
sys.exit(0)
|