Host-Key-Popup mit Fingerprint + ctty-run-Helper (Ctty fuer ssh-Prompts), Doku

This commit is contained in:
x3
2026-09-22 09:31:08 +02:00
parent 8511e4fdae
commit 4209c481dc
9 changed files with 375 additions and 6 deletions
@@ -11,6 +11,9 @@ struct EmbeddedTerminalView: View {
@State private var input = ""
@State private var secureInput = false
@State private var checking = false
@State private var hostKeyInfo: HostKeyInfo?
@State private var hostKeyChange = false
@State private var showingHostKey = false
var body: some View {
VStack(spacing: 0) {
@@ -98,6 +101,18 @@ struct EmbeddedTerminalView: View {
connect() // Auto-Connect beim Öffnen des Tabs
}
}
.sheet(isPresented: $showingHostKey) {
if let info = hostKeyInfo {
HostKeySheet(info: info, isChange: hostKeyChange,
onAccept: acceptHostKey,
onCancel: {
showingHostKey = false
checking = false
hostKeyInfo = nil
term.fail("Host-Key nicht akzeptiert — Verbindung abgebrochen.")
})
}
}
}
func connect() {
@@ -105,16 +120,47 @@ struct EmbeddedTerminalView: View {
checking = true
TCPCheck.check(host: profile.host, port: profile.port) { message in
DispatchQueue.main.async {
checking = false
if let message {
checking = false
term.fail("Vorab-Check: \(message)")
} else {
return
}
// Host-Key vorab per keyscan prüfen (Yes/No-Prompt käme ohne Ctty nicht an)
let hk = HostKeyService.status(host: profile.host, port: profile.port)
switch hk {
case .known, .unreachable:
checking = false
term.start()
case .unknown(let info):
hostKeyInfo = info
hostKeyChange = false
showingHostKey = true
case .changed(let info):
hostKeyInfo = info
hostKeyChange = true
showingHostKey = true
}
}
}
}
func acceptHostKey() {
guard let info = hostKeyInfo else { return }
showingHostKey = false
if hostKeyChange {
_ = HostKeyService.revoke(host: profile.host, port: profile.port)
}
if HostKeyService.accept(info) {
checking = false
term.note("Host-Key akzeptiert (\(info.keyType), \(info.fingerprintSHA256.prefix(19))…).")
term.start()
} else {
checking = false
term.fail("Host-Key konnte nicht in known_hosts gespeichert werden.")
}
hostKeyInfo = nil
}
func diagnose() {
guard !checking else { return }
checking = true