Skip to content

Commit 94fd28e

Browse files
committed
feat: add DangerousDisableDownloadSignatureValidation UserDefault to skip tunnel binary codesign check
1 parent 81d03d7 commit 94fd28e

6 files changed

Lines changed: 25 additions & 8 deletions

File tree

Coder-Desktop/Coder-Desktop/State.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class AppState: ObservableObject {
1010
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "AppState")
1111
let appId = Bundle.main.bundleIdentifier!
1212

13+
let dangerousDisableDownloadSignatureValidation: Bool
14+
1315
// Stored in UserDefaults
1416
@Published private(set) var hasSession: Bool {
1517
didSet {
@@ -87,6 +89,7 @@ class AppState: ObservableObject {
8789
if useLiteralHeaders, let headers = try? JSONEncoder().encode(literalHeaders) {
8890
proto.providerConfiguration?["literalHeaders"] = headers
8991
}
92+
proto.providerConfiguration?["dangerousDisableDownloadSignatureValidation"] = dangerousDisableDownloadSignatureValidation
9093
proto.serverAddress = baseAccessURL!.absoluteString
9194
return proto
9295
}
@@ -106,6 +109,9 @@ class AppState: ObservableObject {
106109
{
107110
self.persistent = persistent
108111
self.onChange = onChange
112+
dangerousDisableDownloadSignatureValidation = persistent
113+
? UserDefaults.standard.bool(forKey: Keys.dangerousDisableDownloadSignatureValidation)
114+
: false
109115
keychain = Keychain(service: Bundle.main.bundleIdentifier!)
110116
_hasSession = Published(initialValue: persistent ? UserDefaults.standard.bool(forKey: Keys.hasSession) : false)
111117
_baseAccessURL = Published(
@@ -219,6 +225,7 @@ class AppState: ObservableObject {
219225
static let stopVPNOnQuit = "StopVPNOnQuit"
220226
static let startVPNOnLaunch = "StartVPNOnLaunch"
221227

228+
static let dangerousDisableDownloadSignatureValidation = "DangerousDisableDownloadSignatureValidation"
222229
static let skipHiddenIconAlert = "SkipHiddenIconAlert"
223230
}
224231
}

Coder-Desktop/Coder-DesktopHelper/HelperXPCListeners.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ extension HelperNEXPCServer: HelperNEXPCInterface {
8080
token: String,
8181
tun: FileHandle,
8282
headers: Data?,
83+
dangerousDisableSignatureValidation: Bool,
8384
reply: @escaping (Error?) -> Void
8485
) {
8586
logger.info("startDaemon called")
@@ -92,7 +93,8 @@ extension HelperNEXPCServer: HelperNEXPCInterface {
9293
apiToken: token,
9394
serverUrl: accessURL,
9495
tunFd: tun.fileDescriptor,
95-
literalHeaders: headers.flatMap { try? JSONDecoder().decode([HTTPHeader].self, from: $0) } ?? []
96+
literalHeaders: headers.flatMap { try? JSONDecoder().decode([HTTPHeader].self, from: $0) } ?? [],
97+
dangerousDisableSignatureValidation: dangerousDisableSignatureValidation
9698
)
9799
)
98100
try await manager.startVPN()

Coder-Desktop/Coder-DesktopHelper/Manager.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,17 @@ actor Manager {
7474
} catch {
7575
throw .download(error)
7676
}
77-
pushProgress(stage: .validating)
77+
7878
do {
79-
try Validator.validateSignature(binaryPath: dest)
79+
if cfg.dangerousDisableSignatureValidation {
80+
logger.warning("Skipping code signature validation of downloaded binary (disabled by configuration)")
81+
} else {
82+
pushProgress(stage: .validating)
83+
try Validator.validateSignature(binaryPath: dest)
84+
}
8085
try await Validator.validateVersion(binaryPath: dest, serverVersion: buildInfo.version)
8186
} catch {
82-
// Cleanup unvalid binary
87+
// Cleanup invalid binary
8388
try? FileManager.default.removeItem(at: dest)
8489
throw .validation(error)
8590
}
@@ -270,6 +275,7 @@ struct ManagerConfig {
270275
let serverUrl: URL
271276
let tunFd: Int32
272277
let literalHeaders: [HTTPHeader]
278+
let dangerousDisableSignatureValidation: Bool
273279
}
274280

275281
enum ManagerError: Error {

Coder-Desktop/VPN/NEHelperXPCClient.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ final class HelperXPCClient: @unchecked Sendable {
3535
return connection
3636
}
3737

38-
func startDaemon(accessURL: URL, token: String, tun: FileHandle, headers: Data?) async throws {
38+
func startDaemon(accessURL: URL, token: String, tun: FileHandle, headers: Data?, dangerousDisableSignatureValidation: Bool) async throws {
3939
let conn = connect()
4040
return try await withCheckedThrowingContinuation { continuation in
4141
guard let proxy = conn.remoteObjectProxyWithErrorHandler({ err in
@@ -46,7 +46,7 @@ final class HelperXPCClient: @unchecked Sendable {
4646
continuation.resume(throwing: XPCError.wrongProxyType)
4747
return
4848
}
49-
proxy.startDaemon(accessURL: accessURL, token: token, tun: tun, headers: headers) { err in
49+
proxy.startDaemon(accessURL: accessURL, token: token, tun: tun, headers: headers, dangerousDisableSignatureValidation: dangerousDisableSignatureValidation) { err in
5050
if let error = err {
5151
self.logger.error("Failed to start daemon: \(error.localizedDescription, privacy: .public)")
5252
continuation.resume(throwing: error)

Coder-Desktop/VPN/PacketTunnelProvider.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
5959
throw makeNSError(suffix: "PTP", desc: "Missing Token")
6060
}
6161
let headers = proto.providerConfiguration?["literalHeaders"] as? Data
62+
let dangerousDisableSigValidation = proto.providerConfiguration?["dangerousDisableDownloadSignatureValidation"] as? Bool ?? false
6263
logger.debug("retrieved token & access URL")
6364
guard let tunFd = tunnelFileDescriptor else {
6465
logger.error("startTunnel called with nil tunnelFileDescriptor")
@@ -68,7 +69,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
6869
accessURL: .init(string: baseAccessURL)!,
6970
token: token,
7071
tun: FileHandle(fileDescriptor: tunFd),
71-
headers: headers
72+
headers: headers,
73+
dangerousDisableSignatureValidation: dangerousDisableSigValidation
7274
)
7375
}
7476

Coder-Desktop/VPNLib/XPC.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public let helperNEMachServiceName = "4399GN35BJ.com.coder.Coder-Desktop.HelperN
2626
@preconcurrency
2727
@objc public protocol HelperNEXPCInterface {
2828
// headers is a JSON `[HTTPHeader]`
29-
func startDaemon(accessURL: URL, token: String, tun: FileHandle, headers: Data?, reply: @escaping (Error?) -> Void)
29+
func startDaemon(accessURL: URL, token: String, tun: FileHandle, headers: Data?, dangerousDisableSignatureValidation: Bool, reply: @escaping (Error?) -> Void)
3030
func stopDaemon(reply: @escaping (Error?) -> Void)
3131
}
3232

0 commit comments

Comments
 (0)