mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
203 lines
6.3 KiB
Swift
203 lines
6.3 KiB
Swift
//
|
|
// Security.swift
|
|
// Meshtastic
|
|
//
|
|
// Copyright(c) Garth Vander Houwen 8/7/24.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
import CoreData
|
|
import MeshtasticProtobufs
|
|
import OSLog
|
|
|
|
struct SecurityConfig: View {
|
|
|
|
@Environment(\.managedObjectContext) var context
|
|
@EnvironmentObject var bleManager: BLEManager
|
|
@Environment(\.dismiss) private var goBack
|
|
|
|
var node: NodeInfoEntity?
|
|
|
|
@State var hasChanges = false
|
|
@State var publicKey = ""
|
|
@State var privateKey = ""
|
|
@State var adminKey = ""
|
|
@State var isManaged = false
|
|
@State var serialEnabled = false
|
|
@State var debugLogApiEnabled = false
|
|
@State var bluetoothLoggingEnabled = false
|
|
@State var adminChannelEnabled = false
|
|
|
|
var boolValues: [Bool] {[
|
|
isManaged,
|
|
serialEnabled,
|
|
debugLogApiEnabled,
|
|
bluetoothLoggingEnabled,
|
|
adminChannelEnabled
|
|
]}
|
|
|
|
var body: some View {
|
|
VStack {
|
|
Form {
|
|
ConfigHeader(title: "Security", config: \.securityConfig, node: node, onAppear: setSecurityValues)
|
|
|
|
Section(header: Text("Admin & Direct Message Keys")) {
|
|
VStack(alignment: .leading) {
|
|
Label("Public Key", systemImage: "key")
|
|
|
|
Text("Sent out to other nodes on the mesh to allow them to compute a shared secret key.")
|
|
.foregroundStyle(.secondary)
|
|
.font(.caption)
|
|
|
|
TextField(
|
|
"Public Key",
|
|
text: $publicKey,
|
|
axis: .vertical
|
|
)
|
|
.padding(5)
|
|
.keyboardType(.alphabet)
|
|
.foregroundColor(.secondary)
|
|
.disableAutocorrection(true)
|
|
.textSelection(.enabled)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 10.0)
|
|
.stroke(true ? Color.clear : Color.red, lineWidth: 2.0)
|
|
)
|
|
|
|
}
|
|
VStack(alignment: .leading) {
|
|
Label("Private Key", systemImage: "key.fill")
|
|
|
|
Text("Used to create a shared key with a remote device.")
|
|
.foregroundStyle(.secondary)
|
|
.font(.caption)
|
|
|
|
TextField(
|
|
"Private Key",
|
|
text: $privateKey,
|
|
axis: .vertical
|
|
)
|
|
.padding(5)
|
|
.disableAutocorrection(true)
|
|
.keyboardType(.alphabet)
|
|
.foregroundColor(.secondary)
|
|
.textSelection(.enabled)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 10.0)
|
|
.stroke(true ? Color.clear : Color.red, lineWidth: 2.0)
|
|
)
|
|
}
|
|
VStack(alignment: .leading) {
|
|
Label("Admin Key", systemImage: "key.viewfinder")
|
|
|
|
Text("The public key authorized to send admin messages to this node.")
|
|
.foregroundStyle(.secondary)
|
|
.font(.caption)
|
|
|
|
TextField(
|
|
"Admin Key",
|
|
text: $adminKey,
|
|
axis: .vertical
|
|
)
|
|
.padding(5)
|
|
.disableAutocorrection(true)
|
|
.keyboardType(.alphabet)
|
|
.foregroundColor(.secondary)
|
|
.textSelection(.enabled)
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 10.0)
|
|
.stroke(true ? Color.clear : Color.red, lineWidth: 2.0)
|
|
)
|
|
}
|
|
}
|
|
Section(header: Text("Logs")) {
|
|
Toggle(isOn: $bluetoothLoggingEnabled) {
|
|
Label("Bluetooth Logs", systemImage: "dot.radiowaves.right")
|
|
Text("View and export position-redacted device logs over Bluetooth")
|
|
Link("View Logs", destination: URL(string: "meshtastic:///settings/debugLogs")!)
|
|
}
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
}
|
|
Section(header: Text("Administration")) {
|
|
if adminKey.length > 0 || adminChannelEnabled {
|
|
Toggle(isOn: $isManaged) {
|
|
Label("Managed Device", systemImage: "gearshape.arrow.triangle.2.circlepath")
|
|
Text("Device is managed by a mesh administrator.")
|
|
}
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
}
|
|
Toggle(isOn: $adminChannelEnabled) {
|
|
Label("Legacy Administration", systemImage: "lock.slash")
|
|
Text("Allow incoming device control over the insecure legacy admin channel.")
|
|
}
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
}
|
|
Section(header: Text("Developer")) {
|
|
Toggle(isOn: $serialEnabled) {
|
|
Label("Serial Console", systemImage: "terminal")
|
|
Text("Serial Console over the Stream API.")
|
|
}
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
if serialEnabled {
|
|
Toggle(isOn: $debugLogApiEnabled) {
|
|
Label("Serial Debug Logs", systemImage: "ant.fill")
|
|
Text("Output live debug logging over serial.")
|
|
}
|
|
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.navigationTitle("Security Config")
|
|
.navigationBarItems(trailing:
|
|
ZStack {
|
|
ConnectedDevice(bluetoothOn: bleManager.isSwitchedOn, deviceConnected: bleManager.connectedPeripheral != nil, name: (bleManager.connectedPeripheral != nil) ? bleManager.connectedPeripheral.shortName : "?")
|
|
})
|
|
.onChange(of: boolValues) { _ in
|
|
hasChanges = true
|
|
}
|
|
SaveConfigButton(node: node, hasChanges: $hasChanges) {
|
|
guard let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context),
|
|
let fromUser = connectedNode.user,
|
|
let toUser = node?.user else {
|
|
return
|
|
}
|
|
|
|
var config = Config.SecurityConfig()
|
|
//config.publicKey = publicKey
|
|
//config.privateKey = privateKey
|
|
//config.adminKey = adminKey
|
|
config.isManaged = isManaged
|
|
config.serialEnabled = serialEnabled
|
|
config.debugLogApiEnabled = debugLogApiEnabled
|
|
config.bluetoothLoggingEnabled = bluetoothLoggingEnabled
|
|
config.adminChannelEnabled = adminChannelEnabled
|
|
|
|
let adminMessageId = bleManager.saveSecurityConfig(
|
|
config: config,
|
|
fromUser: fromUser,
|
|
toUser: toUser,
|
|
adminIndex: connectedNode.myInfo?.adminIndex ?? 0
|
|
)
|
|
if adminMessageId > 0 {
|
|
// Should show a saved successfully alert once I know that to be true
|
|
// for now just disable the button after a successful save
|
|
hasChanges = false
|
|
goBack()
|
|
}
|
|
}
|
|
}
|
|
|
|
func setSecurityValues() {
|
|
self.publicKey = node?.securityConfig?.publicKey?.base64EncodedString() ?? ""
|
|
self.privateKey = node?.securityConfig?.privateKey?.base64EncodedString() ?? ""
|
|
self.adminKey = node?.securityConfig?.adminKey?.base64EncodedString() ?? ""
|
|
self.isManaged = node?.securityConfig?.isManaged ?? false
|
|
self.serialEnabled = node?.securityConfig?.serialEnabled ?? false
|
|
self.debugLogApiEnabled = node?.securityConfig?.debugLogApiEnabled ?? false
|
|
self.bluetoothLoggingEnabled = node?.securityConfig?.bluetoothLoggingEnabled ?? false
|
|
self.adminChannelEnabled = node?.securityConfig?.adminChannelEnabled ?? false
|
|
self.hasChanges = false
|
|
}
|
|
}
|