SSH-Agent-Socket an ssh durchreichen (wie Terminal), Banner-Tipp, Doku
This commit is contained in:
@@ -42,6 +42,30 @@ enum SSHService {
|
||||
|
||||
// MARK: - Passwort / Auto-Login
|
||||
|
||||
/// SSH-Agent-Socket für GUI-Prozesse auflösen (Finder-Apps erben SSH_AUTH_SOCK
|
||||
/// nicht, Terminal schon — ohne diesen Unterschied nutzt Terminal evtl. einen
|
||||
/// Agent-Key, während die App nach dem Passwort fragt und scheitert).
|
||||
static func agentSocket() -> String? {
|
||||
let p = Process()
|
||||
p.executableURL = URL(fileURLWithPath: "/bin/launchctl")
|
||||
p.arguments = ["getenv", "SSH_AUTH_SOCK"]
|
||||
let out = Pipe()
|
||||
let err = Pipe()
|
||||
p.standardOutput = out
|
||||
p.standardError = err
|
||||
do {
|
||||
try p.run()
|
||||
p.waitUntilExit()
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
let path = String(data: out.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8)?
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
guard !path.isEmpty,
|
||||
FileManager.default.fileExists(atPath: path) else { return nil }
|
||||
return path
|
||||
}
|
||||
|
||||
/// Gespeichertes Login-Secret: erst Profil-Passwort, dann Key-Passphrase (Keychain, nie JSON).
|
||||
static func loginSecret(for profile: ConnectionProfile, key: StoredSSHKey?) -> String? {
|
||||
if let acct = profile.passwordAccount,
|
||||
|
||||
@@ -298,12 +298,17 @@ final class TerminalManager: ObservableObject {
|
||||
baseExe = "/usr/bin/ssh"
|
||||
baseArgs = SSHService.sshArguments(for: profile, key: key)
|
||||
}
|
||||
// Auto-Login nur mit Keychain-Secret + sshpass, sonst interaktiver Prompt im Terminal
|
||||
// Auto-Login nur mit Keychain-Secret + sshpass, sonst interaktiver Prompt im Terminal.
|
||||
// SSH-Agent durchreichen (falls vorhanden): gleiche Keys wie in Terminal.app.
|
||||
let cfg = SSHService.sessionConfig(executable: baseExe, args: baseArgs,
|
||||
password: SSHService.loginSecret(for: profile, key: key),
|
||||
sshpassPath: SSHService.findSshpass())
|
||||
s.configure(executable: cfg.executable, arguments: cfg.arguments)
|
||||
s.customEnv = cfg.extraEnv
|
||||
var env = cfg.extraEnv
|
||||
if let sock = SSHService.agentSocket() {
|
||||
env["SSH_AUTH_SOCK"] = sock
|
||||
}
|
||||
s.customEnv = env
|
||||
s.setAutoLogin(cfg.autoLogin)
|
||||
sessions[profile.id] = s
|
||||
return s
|
||||
|
||||
@@ -42,7 +42,7 @@ struct EmbeddedTerminalView: View {
|
||||
.font(.caption).foregroundStyle(Dracula.foreground)
|
||||
.lineLimit(3)
|
||||
if lastMessage.localizedCaseInsensitiveContains("permission denied") {
|
||||
Text("Tipp: Passwort im Auge-Modus eingeben, auf Tastaturlayout (z. B. Z/Y) achten, Keychain-Eintrag prüfen.")
|
||||
Text("Tipp: Passwort im Auge-Modus eingeben, Tastaturlayout prüfen. Falls Terminal.app ohne Passwort einloggt (Agent-Key: ssh-add -l), Key in der App hinterlegen oder Agent nutzen.")
|
||||
.font(.caption).foregroundStyle(Dracula.orange)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user