mirror of
https://github.com/neon443/ShhShell.git
synced 2026-03-11 05:19:13 +00:00
Wrote a Host Protocol for easy stroing of hosts
a debugHost for reusable root:root@localhost:2222 blankHost for - well - blank hosts gonna add userdefaults added iclodu entitlement added viewmodifier: foregroundStyle if 17.0+ and foregroundColor for else
This commit is contained in:
@@ -15,13 +15,14 @@
|
||||
A92538D12DEE0745007E0A18 /* ShhShellUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92538CE2DEE0745007E0A18 /* ShhShellUITests.swift */; };
|
||||
A92538D22DEE0745007E0A18 /* ShhShellUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A92538CF2DEE0745007E0A18 /* ShhShellUITestsLaunchTests.swift */; };
|
||||
A93143BE2DF4D0B300FCD5DB /* libpthread.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = A93143BD2DF4D0A700FCD5DB /* libpthread.tbd */; };
|
||||
A93143C02DF61B3200FCD5DB /* Host.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93143BF2DF61B3200FCD5DB /* Host.swift */; };
|
||||
A93143C62DF61FE300FCD5DB /* ViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93143C52DF61FE300FCD5DB /* ViewModifiers.swift */; };
|
||||
A95FAA472DF3884B00DE2F5A /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = A95FAA462DF3884B00DE2F5A /* Config.xcconfig */; };
|
||||
A95FAA542DF4B62900DE2F5A /* LibSSH.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A95FAA502DF4B62100DE2F5A /* LibSSH.xcframework */; };
|
||||
A95FAA552DF4B62900DE2F5A /* LibSSH.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A95FAA502DF4B62100DE2F5A /* LibSSH.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
A95FAA562DF4B62A00DE2F5A /* openssl.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = A95FAA512DF4B62100DE2F5A /* openssl.xcframework */; };
|
||||
A95FAA572DF4B62A00DE2F5A /* openssl.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = A95FAA512DF4B62100DE2F5A /* openssl.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */; };
|
||||
A9C897F12DF1AB5700EF9A5F /* ShellHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C897F02DF1AB5700EF9A5F /* ShellHandler.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -68,6 +69,9 @@
|
||||
A92538CE2DEE0745007E0A18 /* ShhShellUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShhShellUITests.swift; sourceTree = "<group>"; };
|
||||
A92538CF2DEE0745007E0A18 /* ShhShellUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShhShellUITestsLaunchTests.swift; sourceTree = "<group>"; };
|
||||
A93143BD2DF4D0A700FCD5DB /* libpthread.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libpthread.tbd; path = usr/lib/libpthread.tbd; sourceTree = SDKROOT; };
|
||||
A93143BF2DF61B3200FCD5DB /* Host.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Host.swift; sourceTree = "<group>"; };
|
||||
A93143C22DF61F5700FCD5DB /* ShhShell.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShhShell.entitlements; sourceTree = "<group>"; };
|
||||
A93143C52DF61FE300FCD5DB /* ViewModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModifiers.swift; sourceTree = "<group>"; };
|
||||
A95FAA462DF3884B00DE2F5A /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
A95FAA502DF4B62100DE2F5A /* LibSSH.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = LibSSH.xcframework; path = Frameworks/LibSSH.xcframework; sourceTree = "<group>"; };
|
||||
A95FAA512DF4B62100DE2F5A /* openssl.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = openssl.xcframework; path = Frameworks/openssl.xcframework; sourceTree = "<group>"; };
|
||||
@@ -75,7 +79,6 @@
|
||||
A95FAA5B2DF4B7A000DE2F5A /* ci_pre_xcodebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ci_pre_xcodebuild.sh; sourceTree = "<group>"; };
|
||||
A95FAA5C2DF4B7A300DE2F5A /* ci_prost_xcodebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ci_prost_xcodebuild.sh; sourceTree = "<group>"; };
|
||||
A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSHHandler.swift; sourceTree = "<group>"; };
|
||||
A9C897F02DF1AB5700EF9A5F /* ShellHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShellHandler.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -134,10 +137,10 @@
|
||||
A92538C72DEE0742007E0A18 /* ShhShell */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A93143C22DF61F5700FCD5DB /* ShhShell.entitlements */,
|
||||
A92538C62DEE0742007E0A18 /* ShhShellApp.swift */,
|
||||
A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */,
|
||||
A9C897F02DF1AB5700EF9A5F /* ShellHandler.swift */,
|
||||
A92538D32DEE0749007E0A18 /* Views */,
|
||||
A93143C12DF61E8500FCD5DB /* SSH */,
|
||||
);
|
||||
path = ShhShell;
|
||||
sourceTree = "<group>";
|
||||
@@ -163,6 +166,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A92538C52DEE0742007E0A18 /* ContentView.swift */,
|
||||
A93143C52DF61FE300FCD5DB /* ViewModifiers.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@@ -175,6 +179,15 @@
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A93143C12DF61E8500FCD5DB /* SSH */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A93143BF2DF61B3200FCD5DB /* Host.swift */,
|
||||
A9C897EE2DF1A9A400EF9A5F /* SSHHandler.swift */,
|
||||
);
|
||||
path = SSH;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A95FAA582DF4B71F00DE2F5A /* ci_scripts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -336,10 +349,11 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A93143C62DF61FE300FCD5DB /* ViewModifiers.swift in Sources */,
|
||||
A92538C82DEE0742007E0A18 /* ContentView.swift in Sources */,
|
||||
A93143C02DF61B3200FCD5DB /* Host.swift in Sources */,
|
||||
A92538C92DEE0742007E0A18 /* ShhShellApp.swift in Sources */,
|
||||
A9C897EF2DF1A9A400EF9A5F /* SSHHandler.swift in Sources */,
|
||||
A9C897F12DF1AB5700EF9A5F /* ShellHandler.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -504,6 +518,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = ShhShell/ShhShell.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(BUILD)";
|
||||
DEVELOPMENT_TEAM = 8JGND254B7;
|
||||
@@ -515,7 +530,7 @@
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -534,6 +549,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = ShhShell/ShhShell.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(BUILD)";
|
||||
DEVELOPMENT_TEAM = 8JGND254B7;
|
||||
@@ -545,7 +561,7 @@
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
||||
54
ShhShell/SSH/Host.swift
Normal file
54
ShhShell/SSH/Host.swift
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// Host.swift
|
||||
// ShhShell
|
||||
//
|
||||
// Created by neon443 on 08/06/2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol HostPr: Codable {
|
||||
var address: String { get set }
|
||||
var port: Int { get set }
|
||||
var username: String { get set }
|
||||
var password: String { get set }
|
||||
var key: Data? { get set }
|
||||
}
|
||||
|
||||
struct Host: HostPr {
|
||||
var address: String = "address"
|
||||
var port: Int
|
||||
var username: String
|
||||
var password: String
|
||||
var key: Data?
|
||||
|
||||
init(
|
||||
address: String,
|
||||
port: Int = 22,
|
||||
username: String,
|
||||
password: String,
|
||||
hostkey: Data? = nil
|
||||
) {
|
||||
self.address = address
|
||||
self.port = port
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.key = hostkey
|
||||
}
|
||||
}
|
||||
|
||||
struct blankHost: HostPr {
|
||||
var address: String = ""
|
||||
var port: Int = 22
|
||||
var username: String = ""
|
||||
var password: String = ""
|
||||
var key: Data? = nil
|
||||
}
|
||||
|
||||
struct debugHost: HostPr {
|
||||
var address: String = "localhost"
|
||||
var port: Int = 2222
|
||||
var username: String = "root"
|
||||
var password: String = "root"
|
||||
var key: Data? = nil
|
||||
}
|
||||
@@ -14,30 +14,18 @@ class SSHHandler: ObservableObject {
|
||||
private var channel: ssh_channel?
|
||||
|
||||
@Published var authorized: Bool = false
|
||||
@Published var username: String
|
||||
@Published var password: String
|
||||
@Published var address: String
|
||||
@Published var port: Int
|
||||
|
||||
@Published var hostkey: Data?
|
||||
|
||||
@Published var host: HostPr
|
||||
|
||||
private let userDefaults = NSUbiquitousKeyValueStore.default
|
||||
private let logger = Logger(subsystem: "xy", category: "sshHandler")
|
||||
|
||||
init(
|
||||
username: String = "",
|
||||
password: String = "",
|
||||
address: String = "",
|
||||
port: Int = 22
|
||||
host: HostPr
|
||||
) {
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.address = address
|
||||
self.port = port
|
||||
self.host = host
|
||||
#if DEBUG
|
||||
self.username = "root"
|
||||
self.password = "root"
|
||||
self.address = "localhost"
|
||||
self.port = 2222
|
||||
self.host = debugHost()
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -57,7 +45,7 @@ class SSHHandler: ObservableObject {
|
||||
func connect() -> Bool {
|
||||
defer {
|
||||
getAuthMethods()
|
||||
self.hostkey = getHostkey()
|
||||
self.host.key = getHostkey()
|
||||
}
|
||||
|
||||
var verbosity: Int = 0
|
||||
@@ -67,9 +55,9 @@ class SSHHandler: ObservableObject {
|
||||
return false
|
||||
}
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, address)
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, host.address)
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity)
|
||||
ssh_options_set(session, SSH_OPTIONS_PORT, &port)
|
||||
ssh_options_set(session, SSH_OPTIONS_PORT, &host.port)
|
||||
|
||||
let status = ssh_connect(session)
|
||||
if status != SSH_OK {
|
||||
@@ -89,7 +77,7 @@ class SSHHandler: ObservableObject {
|
||||
ssh_free(session)
|
||||
session = nil
|
||||
authorized = false
|
||||
hostkey = nil
|
||||
host.key = nil
|
||||
}
|
||||
|
||||
func testExec() -> Bool {
|
||||
@@ -170,7 +158,7 @@ class SSHHandler: ObservableObject {
|
||||
|
||||
func authWithPw() -> Bool {
|
||||
var status: CInt
|
||||
status = ssh_userauth_password(session, username, password)
|
||||
status = ssh_userauth_password(session, host.username, host.password)
|
||||
guard status == SSH_AUTH_SUCCESS.rawValue else {
|
||||
print("ssh pw auth error")
|
||||
logSshGetError()
|
||||
@@ -245,7 +233,7 @@ class SSHHandler: ObservableObject {
|
||||
|
||||
func getAuthMethods() {
|
||||
var method: CInt
|
||||
method = ssh_userauth_list(session, username)
|
||||
method = ssh_userauth_list(session, host.username)
|
||||
}
|
||||
|
||||
func openShell() {
|
||||
@@ -287,7 +275,7 @@ class SSHHandler: ObservableObject {
|
||||
write(1, buffer, Int(nbytes))
|
||||
|
||||
let data = Data(bytes: buffer, count: buffer.count)
|
||||
print(String(data: data, encoding: .utf8))
|
||||
print(String(data: data, encoding: .utf8)!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
//
|
||||
// ShellHandler.swift
|
||||
// ShhShell
|
||||
//
|
||||
// Created by neon443 on 05/06/2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
10
ShhShell/ShhShell.entitlements
Normal file
10
ShhShell/ShhShell.entitlements
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.icloud-container-identifiers</key>
|
||||
<array/>
|
||||
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
|
||||
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -9,7 +9,7 @@ import SwiftUI
|
||||
|
||||
@main
|
||||
struct ShhShellApp: App {
|
||||
@StateObject var sshHandler: SSHHandler = SSHHandler(username: "", password: "")
|
||||
@StateObject var sshHandler: SSHHandler = SSHHandler(host: blankHost())
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
|
||||
@@ -17,36 +17,36 @@ struct ContentView: View {
|
||||
var body: some View {
|
||||
VStack {
|
||||
Text(connected ? "connected" : "not connected")
|
||||
.foregroundStyle(connected ? .green : .red)
|
||||
.modifier(foregroundColorStyle(connected ? .green : .red))
|
||||
|
||||
Text(handler.authorized ? "authorized" : "unauthorized")
|
||||
.foregroundStyle(handler.authorized ? .green : .red)
|
||||
.modifier(foregroundColorStyle(handler.authorized ? .green : .red))
|
||||
|
||||
if let testSucceded = testSucceded {
|
||||
Image(systemName: testSucceded ? "checkmark.circle" : "xmark.circle")
|
||||
.foregroundStyle(testSucceded ? .green : .red)
|
||||
.modifier(foregroundColorStyle(testSucceded ? .green : .red))
|
||||
}
|
||||
|
||||
if handler.hostkey != nil {
|
||||
Text("Hostkey: \(handler.hostkey!.base64EncodedString())")
|
||||
if handler.host.key != nil {
|
||||
Text("Hostkey: \(handler.host.key!.base64EncodedString())")
|
||||
}
|
||||
|
||||
TextField("address", text: $handler.address)
|
||||
TextField("address", text: $handler.host.address)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
TextField(
|
||||
"port",
|
||||
text: Binding(
|
||||
get: { String(handler.port) },
|
||||
set: { handler.port = Int($0) ?? 22} )
|
||||
get: { String(handler.host.port) },
|
||||
set: { handler.host.port = Int($0) ?? 22} )
|
||||
)
|
||||
.keyboardType(.numberPad)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
TextField("username", text: $handler.username)
|
||||
TextField("username", text: $handler.host.username)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
TextField("password", text: $handler.password)
|
||||
TextField("password", text: $handler.host.password)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
Button("connect") {
|
||||
@@ -90,6 +90,6 @@ struct ContentView: View {
|
||||
|
||||
#Preview {
|
||||
ContentView(
|
||||
handler: SSHHandler(username: "root", password: "root")
|
||||
handler: SSHHandler(host: debugHost())
|
||||
)
|
||||
}
|
||||
|
||||
28
ShhShell/Views/ViewModifiers.swift
Normal file
28
ShhShell/Views/ViewModifiers.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// ViewModifiers.swift
|
||||
// ShhShell
|
||||
//
|
||||
// Created by neon443 on 08/06/2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct foregroundColorStyle: ViewModifier {
|
||||
var color: Color?
|
||||
|
||||
init(_ color: Color?) {
|
||||
self.color = color
|
||||
}
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if #available(iOS 17.0, *) {
|
||||
if let color = color {
|
||||
content.foregroundStyle(color)
|
||||
}
|
||||
content
|
||||
} else {
|
||||
content.foregroundColor(color)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user