From ffcbeee8f1871052ec2ae8489d47171c71c660e8 Mon Sep 17 00:00:00 2001 From: Jason Houk Date: Wed, 17 Dec 2025 23:01:36 -0500 Subject: [PATCH] Disable Range Test module when primary channel is public/unsecured (#1512) * Update Muzi R1 Neo to actively supported * Disable Range Test module when primary channel is public/unsecured Updated RangeTestConfig.swift to determine whether the primary channel (index 0) is operating without encryption or with a 1-byte minimal PSK. Disabled Range Test UI controls when on a public/default channel to prevent user interaction. Added safety enforcement in the save operation: Range Test enabled flag is automatically forced to false before sending updates to the device. Introduced a computed property isPrimaryChannelPublic following existing code patterns and security indicators (e.g., hexDescription PSK length). Matches the behavior implemented in the Android client for consistent policy across platforms. --------- Co-authored-by: Jonathan Bennett Co-authored-by: Ben Meadors --- .../Config/Module/RangeTestConfig.swift | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift index a4bfbd85..ed65ce4e 100644 --- a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift @@ -5,6 +5,7 @@ // Copyright (c) Garth Vander Houwen 6/13/22. // import MeshtasticProtobufs +import CoreData import OSLog import SwiftUI @@ -21,6 +22,19 @@ struct RangeTestConfig: View { @State var enabled = false @State var save = false @State private var sender: UpdateInterval = UpdateInterval(from: 0) + private var isPrimaryChannelPublic: Bool { + guard let channels = node?.myInfo?.channels?.array as? [ChannelEntity] else { + return false + } + // Treat the primary channel on this node as "public" when it is effectively unencrypted + // or using a minimal 1-byte key (hexDescription shorter than 3 characters). + guard let primary = channels.first(where: { $0.index == 0 && $0.role > 0 }) else { + return false + } + let hexLen = primary.psk?.hexDescription.count ?? 0 + return hexLen < 3 + } + var body: some View { Form { @@ -51,14 +65,15 @@ struct RangeTestConfig: View { } } - .disabled(!accessoryManager.isConnected || node?.rangeTestConfig == nil) + .disabled(!accessoryManager.isConnected || node?.rangeTestConfig == nil || isPrimaryChannelPublic) .safeAreaInset(edge: .bottom, alignment: .center) { HStack(spacing: 0) { SaveConfigButton(node: node, hasChanges: $hasChanges) { let connectedNode = getNodeInfo(id: accessoryManager.activeDeviceNum ?? -1, context: context) if connectedNode != nil { var rtc = ModuleConfig.RangeTestConfig() - rtc.enabled = enabled + let effectiveEnabled = isPrimaryChannelPublic ? false : enabled + rtc.enabled = effectiveEnabled rtc.save = save rtc.sender = UInt32(sender.intValue) Task {