Skip to content

Commit 929c831

Browse files
committed
chore: ensure downloaded slim binary version matches server
1 parent e9e15db commit 929c831

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

Coder-Desktop/Coder-DesktopHelper/Manager.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ actor Manager {
7474
}
7575
pushProgress(stage: .validating)
7676
do {
77-
try Validator.validate(path: dest)
77+
try Validator.validateSignature(binaryPath: dest)
78+
try await Validator.validateVersion(binaryPath: dest, serverVersion: buildInfo.version)
7879
} catch {
7980
throw .validation(error)
8081
}

Coder-Desktop/VPNLib/Validate.swift

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Foundation
2+
import Subprocess
23

34
public enum ValidationError: Error {
45
case fileNotFound
@@ -7,7 +8,8 @@ public enum ValidationError: Error {
78
case unableToRetrieveSignature
89
case invalidIdentifier(identifier: String?)
910
case invalidTeamIdentifier(identifier: String?)
10-
case invalidVersion(version: String?)
11+
case unableToReadVersion(any Error)
12+
case binaryVersionMismatch(binaryVersion: String, serverVersion: String)
1113

1214
public var description: String {
1315
switch self {
@@ -21,10 +23,12 @@ public enum ValidationError: Error {
2123
"Unable to retrieve signing information."
2224
case let .invalidIdentifier(identifier):
2325
"Invalid identifier: \(identifier ?? "unknown")."
24-
case let .invalidVersion(version):
25-
"Invalid runtime version: \(version ?? "unknown")."
26+
case let .binaryVersionMismatch(binaryVersion, serverVersion):
27+
"Binary version does not match server. Binary: \(binaryVersion), Server: \(serverVersion)."
2628
case let .invalidTeamIdentifier(identifier):
2729
"Invalid team identifier: \(identifier ?? "unknown")."
30+
case .unableToReadVersion:
31+
"Unable to execute the binary to read version"
2832
}
2933
}
3034

@@ -41,13 +45,13 @@ public class Validator {
4145

4246
private static let signInfoFlags: SecCSFlags = .init(rawValue: kSecCSSigningInformation)
4347

44-
public static func validate(path: URL) throws(ValidationError) {
45-
guard FileManager.default.fileExists(atPath: path.path) else {
48+
public static func validateSignature(binaryPath: URL) throws(ValidationError) {
49+
guard FileManager.default.fileExists(atPath: binaryPath.path) else {
4650
throw .fileNotFound
4751
}
4852

4953
var staticCode: SecStaticCode?
50-
let status = SecStaticCodeCreateWithPath(path as CFURL, SecCSFlags(), &staticCode)
54+
let status = SecStaticCodeCreateWithPath(binaryPath as CFURL, SecCSFlags(), &staticCode)
5155
guard status == errSecSuccess, let code = staticCode else {
5256
throw .unableToCreateStaticCode
5357
}
@@ -78,6 +82,29 @@ public class Validator {
7882
}
7983
}
8084

85+
public static func validateVersion(binaryPath: URL, serverVersion: String) async throws(ValidationError) {
86+
guard FileManager.default.fileExists(atPath: binaryPath.path) else {
87+
throw .fileNotFound
88+
}
89+
90+
let version: String
91+
do {
92+
let versionOutput = try await Subprocess.data(for: [binaryPath.path, "version", "--output=json"])
93+
let parsed: VersionOutput = try JSONDecoder().decode(VersionOutput.self, from: versionOutput)
94+
version = parsed.version
95+
} catch {
96+
throw .unableToReadVersion(error)
97+
}
98+
99+
guard version == serverVersion else {
100+
throw .binaryVersionMismatch(binaryVersion: version, serverVersion: serverVersion)
101+
}
102+
}
103+
104+
struct VersionOutput: Codable {
105+
let version: String
106+
}
107+
81108
public static let xpcPeerRequirement = "anchor apple generic" + // Apple-issued certificate chain
82109
" and certificate leaf[subject.OU] = \"" + expectedTeamIdentifier + "\"" // Signed by the Coder team
83110
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy