mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 13:26:16 +00:00
UI with custom host, username and pw
not hardcoded anymore set host port username and pw currently only password auth lol can get hostkeys replaced lots of fatalerrors with false returns
This commit is contained in:
@@ -12,23 +12,57 @@ import OSLog
|
||||
class SSHHandler: ObservableObject {
|
||||
var session: ssh_session?
|
||||
|
||||
@Published var username: String
|
||||
@Published var password: String
|
||||
@Published var address: String
|
||||
@Published var port: Int
|
||||
|
||||
private let logger = Logger(subsystem: "xy", category: "sshHandler")
|
||||
|
||||
init() {
|
||||
// session = ssh_new()
|
||||
// guard session != nil else { return }
|
||||
init(
|
||||
username: String = "",
|
||||
password: String = "",
|
||||
address: String = "",
|
||||
port: Int = 22
|
||||
) {
|
||||
#if DEBUG
|
||||
self.username = "root"
|
||||
self.password = "root"
|
||||
self.address = "localhost"
|
||||
self.port = 2222
|
||||
#endif
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.address = address
|
||||
self.port = port
|
||||
}
|
||||
|
||||
func getHostkey() {
|
||||
var hostkey: ssh_key?
|
||||
ssh_get_server_publickey(session, &hostkey)
|
||||
|
||||
var hostkeyB64: UnsafeMutablePointer<CChar>? = nil
|
||||
if ssh_pki_export_pubkey_base64(hostkey, &hostkeyB64) == SSH_OK {
|
||||
if let hostkeyB64 = hostkeyB64 {
|
||||
print(String(cString: hostkeyB64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func connect() -> Bool {
|
||||
defer {
|
||||
getHostkey()
|
||||
getAuthMethods()
|
||||
}
|
||||
|
||||
func connect() {
|
||||
var verbosity: Int = 0
|
||||
var port: Int = 2222
|
||||
|
||||
session = ssh_new()
|
||||
guard session != nil else {
|
||||
fatalError("no ssh session??!?!")
|
||||
return false
|
||||
}
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost")
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, address)
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity)
|
||||
ssh_options_set(session, SSH_OPTIONS_PORT, &port)
|
||||
|
||||
@@ -36,49 +70,42 @@ class SSHHandler: ObservableObject {
|
||||
if status != SSH_OK {
|
||||
logger.critical("connection not ok: \(status)")
|
||||
logSshGetError()
|
||||
fatalError()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func disconnect() {
|
||||
guard session != nil else { fatalError("no ssession") }
|
||||
guard session != nil else {
|
||||
print("cant disconnect when im not connected")
|
||||
return
|
||||
}
|
||||
ssh_disconnect(session)
|
||||
ssh_free(session)
|
||||
}
|
||||
|
||||
func hardcodedAuth() {
|
||||
var hostkey: ssh_key?
|
||||
ssh_get_server_publickey(session, &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")
|
||||
func testExec() -> Bool {
|
||||
if ssh_is_connected(session) == 0 {
|
||||
if !connect() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func testExec() {
|
||||
connect()
|
||||
defer { disconnect();ssh_free(session) }
|
||||
|
||||
hardcodedAuth()
|
||||
guard authWithPw() else { return false }
|
||||
|
||||
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") }
|
||||
guard channel != nil else { return false }
|
||||
|
||||
status = ssh_channel_open_session(channel)
|
||||
guard status == SSH_OK else {
|
||||
ssh_channel_free(channel)
|
||||
logger.critical("session opening error")
|
||||
logSshGetError()
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
status = ssh_channel_request_exec(channel, "uptime")
|
||||
@@ -87,7 +114,7 @@ class SSHHandler: ObservableObject {
|
||||
ssh_channel_free(channel)
|
||||
logger.critical("session opening error")
|
||||
logSshGetError()
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
nbytes = ssh_channel_read(
|
||||
@@ -103,7 +130,7 @@ class SSHHandler: ObservableObject {
|
||||
ssh_channel_free(channel)
|
||||
logger.critical("write error")
|
||||
logSshGetError()
|
||||
return
|
||||
return false
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, &buffer, UInt32(MemoryLayout.size(ofValue: Character.self)), 0)
|
||||
}
|
||||
@@ -113,44 +140,56 @@ class SSHHandler: ObservableObject {
|
||||
ssh_channel_free(channel)
|
||||
logger.critical("didnt read?")
|
||||
logSshGetError()
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel)
|
||||
ssh_channel_close(channel)
|
||||
ssh_channel_free(channel)
|
||||
print("testExec succeeded")
|
||||
return true
|
||||
}
|
||||
|
||||
func authWithPubkey() {
|
||||
func authWithPubkey() -> Bool {
|
||||
var status: CInt
|
||||
status = ssh_userauth_publickey_auto(session, nil, nil)
|
||||
if status == SSH_AUTH_ERROR.rawValue {
|
||||
print("pubkey auth failed")
|
||||
logSshGetError()
|
||||
fatalError()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func authWithPw(_ username: String, _ password: String) {
|
||||
func authWithPw() -> Bool {
|
||||
var status: CInt
|
||||
status = ssh_userauth_password(session, username, password)
|
||||
guard status != SSH_ERROR else {
|
||||
guard status != SSH_AUTH_SUCCESS.rawValue else {
|
||||
print("ssh pw auth error")
|
||||
logSshGetError()
|
||||
return
|
||||
return false
|
||||
}
|
||||
print("auth success")
|
||||
return true
|
||||
}
|
||||
|
||||
func authWithKbInt() {
|
||||
func authWithKbInt() -> Bool {
|
||||
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))
|
||||
if let namePtr = ssh_userauth_kbdint_getname(session) {
|
||||
name = String(cString: namePtr)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
if let instrPtr = ssh_userauth_kbdint_getinstruction(session) {
|
||||
instruction = String(cString: instrPtr)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
nprompts = ssh_userauth_kbdint_getnprompts(session)
|
||||
|
||||
if name.count > 0 {
|
||||
@@ -161,28 +200,47 @@ class SSHHandler: ObservableObject {
|
||||
}
|
||||
for promptI in 0..<nprompts {
|
||||
let prompt: UnsafePointer<CChar>
|
||||
var echo: CChar
|
||||
var echo: CChar = 0
|
||||
prompt = ssh_userauth_kbdint_getprompt(session, UInt32(promptI), &echo)
|
||||
if echo != 0 {
|
||||
var buffer: [CChar] = Array(repeating: 0, count: 128)
|
||||
var ptr: UnsafeMutablePointer<CChar> = .init(mutating: buffer)
|
||||
let ptr: UnsafeMutablePointer<CChar> = .init(mutating: buffer)
|
||||
print(prompt)
|
||||
if fgets(&buffer, Int32(MemoryLayout.size(ofValue: buffer)), stdin) == nil {
|
||||
fatalError("autherror")
|
||||
return false
|
||||
}
|
||||
if (ptr = strchr(buffer, 0)) != nil {
|
||||
ptr.pointee = "\0"
|
||||
}
|
||||
if ssh_userauth_kbdint_setanswer(session, promptI, buffer) < 0 {
|
||||
fatalError("autherr")
|
||||
ptr.pointee = 0//prob fucked
|
||||
if ssh_userauth_kbdint_setanswer(session, UInt32(promptI), buffer) < 0 {
|
||||
return false
|
||||
}
|
||||
memset(&buffer, 0, buffer.count)
|
||||
} else {
|
||||
if (ssh_userauth_kbdint_setanswer(session, UInt32(promptI), &password) != 0) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
status = ssh_userauth_kbdint(session, nil, nil)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func authWithNone() -> Bool {
|
||||
let status = ssh_userauth_none(session, nil)
|
||||
if status == SSH_AUTH_SUCCESS.rawValue {
|
||||
print("no security moment lol")
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func getAuthMethods() {
|
||||
var method: CInt
|
||||
method = ssh_userauth_list(session, username)
|
||||
}
|
||||
|
||||
func logSshGetError() {
|
||||
logger.critical("\(String(describing: ssh_get_error(&self.session)))")
|
||||
logger.critical("\(String(cString: ssh_get_error(&self.session)))")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,11 @@ import SwiftUI
|
||||
|
||||
@main
|
||||
struct ShhShellApp: App {
|
||||
@StateObject var sshHandler: SSHHandler = SSHHandler(username: "", password: "")
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
ContentView(handler: sshHandler)
|
||||
}
|
||||
.windowResizability(.contentMinSize)
|
||||
}
|
||||
|
||||
@@ -8,21 +8,41 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
var sshHandler = SSHHandler()
|
||||
@ObservedObject var handler: SSHHandler
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Image(systemName: "globe")
|
||||
.imageScale(.large)
|
||||
.foregroundStyle(.tint)
|
||||
Text("Hello, world!")
|
||||
Button("go") {
|
||||
sshHandler.testExec()
|
||||
TextField("address", text: $handler.address)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
TextField(
|
||||
"port",
|
||||
text: Binding(
|
||||
get: { String(handler.port) },
|
||||
set: { handler.port = Int($0) ?? 22} )
|
||||
)
|
||||
.keyboardType(.numberPad)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
TextField("username", text: $handler.username)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
TextField("password", text: $handler.password)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
Button("connect & auth") {
|
||||
handler.connect()
|
||||
handler.authWithPw()
|
||||
}
|
||||
Button("disconnect & free") {
|
||||
handler.disconnect()
|
||||
}
|
||||
Button("testExec") {
|
||||
handler.testExec()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ContentView()
|
||||
ContentView(
|
||||
handler: SSHHandler(username: "root", password: "root")
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user