diff --git a/ShhShell/SSHHandler.swift b/ShhShell/SSHHandler.swift index 83875db..662bb84 100644 --- a/ShhShell/SSHHandler.swift +++ b/ShhShell/SSHHandler.swift @@ -7,103 +7,182 @@ import Foundation import LibSSH +import OSLog class SSHHandler: ObservableObject { var session: ssh_session? - + + private let logger = Logger(subsystem: "xy", category: "sshHandler") + init() { // session = ssh_new() // guard session != nil else { return } } - + func connect() { var verbosity: Int = 0 var port: Int = 2222 - + session = ssh_new() guard session != nil else { fatalError("no ssh session??!?!") } - + ssh_options_set(session, SSH_OPTIONS_HOST, "localhost") ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity) ssh_options_set(session, SSH_OPTIONS_PORT, &port) - + let status = ssh_connect(session) - print(status) + if status != SSH_OK { + logger.critical("connection not ok: \(status)") + logSshGetError() + fatalError() + } } - + func disconnect() { guard session != nil else { fatalError("no ssession") } ssh_disconnect(session) } - + func hardcodedAuth() { var hostkey: ssh_key? ssh_get_server_publickey(session, &hostkey) - print("hostkey \(hostkey)") - + if let hostkey = hostkey { + print("hostkey \(hostkey)") + } + let password = "root" - + let rc = ssh_userauth_password(session, "root", password) if rc != SSH_AUTH_SUCCESS.rawValue { print("auth failure") - } else { - print("yay success") } } - + func testExec() { connect() defer { disconnect();ssh_free(session) } - + hardcodedAuth() - - var channel: ssh_channel? - var rc: Int32 - var buffer: [CChar] = Array(repeating: 0, count: 256) - var nbytes: Int32 - - channel = ssh_channel_new(session) - if channel == nil { - fatalError("couldnt create channel \(SSH_ERROR)") - } - - rc = ssh_channel_open_session(channel) - if rc != SSH_OK { + + var status: CInt + var buffer: [Int] = Array(repeating: 0, count: 256) + var nbytes: CInt + + let channel = ssh_channel_new(session) + guard channel != nil else { fatalError("noChannel") } + + status = ssh_channel_open_session(channel) + guard status == SSH_OK else { ssh_channel_free(channel) - print("channel opened \(rc)") + logger.critical("session opening error") + logSshGetError() + return } - - rc = ssh_channel_request_exec(channel, "uptime") - if rc != SSH_OK { + + status = ssh_channel_request_exec(channel, "uptime") + guard status == SSH_OK else { ssh_channel_close(channel) ssh_channel_free(channel) - print("exec request worked \(rc)") + logger.critical("session opening error") + logSshGetError() + return } - nbytes = ssh_channel_read(channel, &buffer, UInt32(buffer.count), 0) + nbytes = ssh_channel_read( + channel, + &buffer, + UInt32(MemoryLayout.size(ofValue: CChar.self)), + 0 + ) while nbytes > 0 { let written = write(1, buffer, Int(nbytes)) - if written != Int(nbytes) { + guard written == Int(nbytes) else { ssh_channel_close(channel) ssh_channel_free(channel) - fatalError("buffer write error \(SSH_ERROR)") + logger.critical("write error") + logSshGetError() + return } - buffer = [CChar](repeating: 0, count: 256) //clear buffer - nbytes = ssh_channel_read(channel, &buffer, UInt32(buffer.count), 0) + nbytes = ssh_channel_read(channel, &buffer, UInt32(MemoryLayout.size(ofValue: Character.self)), 0) } - + if nbytes < 0 { ssh_channel_close(channel) ssh_channel_free(channel) - fatalError("\(SSH_ERROR)") + logger.critical("didnt read?") + logSshGetError() + return } ssh_channel_send_eof(channel) ssh_channel_close(channel) ssh_channel_free(channel) - - print("sshNoOk? \(SSH_OK)") + print("testExec succeeded") + } + + func authWithPubkey() { + var status: CInt + status = ssh_userauth_publickey_auto(session, nil, nil) + if status == SSH_AUTH_ERROR.rawValue { + print("pubkey auth failed") + logSshGetError() + fatalError() + } + } + + func authWithPw(_ username: String, _ password: String) { + var status: CInt + status = ssh_userauth_password(session, username, password) + guard status != SSH_ERROR else { + print("ssh pw auth error") + logSshGetError() + return + } + } + + func authWithKbInt() { + var status: CInt + status = ssh_userauth_kbdint(session, nil, nil) + while status == SSH_AUTH_INFO.rawValue { + let name, instruction: String + var nprompts: CInt + + name = UnsafeRawPointer(String(ssh_userauth_kbdint_getname(session))) + instruction = String(ssh_userauth_kbdint_getinstruction(session)) + nprompts = ssh_userauth_kbdint_getnprompts(session) + + if name.count > 0 { + print(name) + } + if instruction.count > 0 { + print(instruction) + } + for promptI in 0.. + var echo: CChar + prompt = ssh_userauth_kbdint_getprompt(session, UInt32(promptI), &echo) + if echo != 0 { + var buffer: [CChar] = Array(repeating: 0, count: 128) + var ptr: UnsafeMutablePointer = .init(mutating: buffer) + print(prompt) + if fgets(&buffer, Int32(MemoryLayout.size(ofValue: buffer)), stdin) == nil { + fatalError("autherror") + } + if (ptr = strchr(buffer, 0)) != nil { + ptr.pointee = "\0" + } + if ssh_userauth_kbdint_setanswer(session, promptI, buffer) < 0 { + fatalError("autherr") + } + memset(&buffer, 0, buffer.count) + } + } + } + } + + func logSshGetError() { + logger.critical("\(String(describing: ssh_get_error(&self.session)))") } } diff --git a/ShhShell/ShhShellApp.swift b/ShhShell/ShhShellApp.swift index 0afb673..be601cc 100644 --- a/ShhShell/ShhShellApp.swift +++ b/ShhShell/ShhShellApp.swift @@ -13,5 +13,6 @@ struct ShhShellApp: App { WindowGroup { ContentView() } + .windowResizability(.contentMinSize) } } diff --git a/ShhShell/Views/ContentView.swift b/ShhShell/Views/ContentView.swift index 9ebd8d6..10f6992 100644 --- a/ShhShell/Views/ContentView.swift +++ b/ShhShell/Views/ContentView.swift @@ -20,7 +20,6 @@ struct ContentView: View { sshHandler.testExec() } } - .padding() } }