Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb74def3

Browse files
chore: ensure downloaded slim binary version matches server (#211)
Relates to#201.**After we've validated the binary signature**, we exec `coder version --output=json` to validate the version of the downloaded binary matches the server. This is done to prevent against downgrade attacks, and to match the checking we had on the dylib before.Additionally, this PR also ensures the certificate used to sign the binary is part of an Apple-issued certificate chain.I assumed we were checking this before (by default) but we weren't. Though we weren't previously checking it, we were only ever downloading and executing a dylib. My understanding is that macOS won't execute a dylib unless the executing process and the dylib were signed by the same Apple developer team (at [least in a sandboxed process](https://developer.apple.com/forums/thread/683914), as is the Network Extension).Only now, when `posix_spawn`ing the slim binary from an unsandboxed LaunchDaemon, is this check absolutely necessary.
1 parent8c08563 commitb74def3

File tree

2 files changed

+53
-9
lines changed

2 files changed

+53
-9
lines changed

‎Coder-Desktop/Coder-DesktopHelper/Manager.swift‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ actor Manager {
7676
}
7777
pushProgress(stage:.validating)
7878
do{
79-
tryValidator.validate(path: dest)
79+
tryValidator.validateSignature(binaryPath: dest)
80+
tryawaitValidator.validateVersion(binaryPath: dest, serverVersion: buildInfo.version)
8081
}catch{
8182
// Cleanup unvalid binary
8283
try?FileManager.default.removeItem(at: dest)

‎Coder-Desktop/VPNLib/Validate.swift‎

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

34
publicenumValidationError:Error{
45
case fileNotFound
@@ -7,7 +8,9 @@ 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(anyError)
12+
case binaryVersionMismatch(binaryVersion:String, serverVersion:String)
13+
case internalError(OSStatus)
1114

1215
publicvardescription:String{
1316
switchself{
@@ -21,10 +24,14 @@ public enum ValidationError: Error {
2124
"Unable to retrieve signing information."
2225
caselet.invalidIdentifier(identifier):
2326
"Invalid identifier:\(identifier??"unknown")."
24-
caselet.invalidVersion(version):
25-
"Invalid runtimeversion:\(version??"unknown")."
27+
caselet.binaryVersionMismatch(binaryVersion, serverVersion):
28+
"Binaryversion does not match server. Binary:\(binaryVersion), Server:\(serverVersion)."
2629
caselet.invalidTeamIdentifier(identifier):
2730
"Invalid team identifier:\(identifier??"unknown")."
31+
caselet.unableToReadVersion(error):
32+
"Unable to execute the binary to read version:\(error.localizedDescription)"
33+
caselet.internalError(status):
34+
"Internal error with OSStatus code:\(status)."
2835
}
2936
}
3037

@@ -37,22 +44,32 @@ public class Validator {
3744
publicstaticletminimumCoderVersion="2.24.2"
3845

3946
privatestaticletexpectedIdentifier="com.coder.cli"
47+
// The Coder team identifier
4048
privatestaticletexpectedTeamIdentifier="4399GN35BJ"
4149

50+
// Apple-issued certificate chain
51+
publicstaticletanchorRequirement="anchor apple generic"
52+
4253
privatestaticletsignInfoFlags:SecCSFlags=.init(rawValue: kSecCSSigningInformation)
4354

44-
publicstaticfuncvalidate(path:URL)throws(ValidationError){
45-
guardFileManager.default.fileExists(atPath:path.path)else{
55+
publicstaticfuncvalidateSignature(binaryPath:URL)throws(ValidationError){
56+
guardFileManager.default.fileExists(atPath:binaryPath.path)else{
4657
throw.fileNotFound
4758
}
4859

4960
varstaticCode:SecStaticCode?
50-
letstatus=SecStaticCodeCreateWithPath(pathasCFURL,SecCSFlags(),&staticCode)
61+
letstatus=SecStaticCodeCreateWithPath(binaryPathasCFURL,SecCSFlags(),&staticCode)
5162
guard status== errSecSuccess,let code= staticCodeelse{
5263
throw.unableToCreateStaticCode
5364
}
5465

55-
letvalidateStatus=SecStaticCodeCheckValidity(code,SecCSFlags(),nil)
66+
varrequirement:SecRequirement?
67+
letreqStatus=SecRequirementCreateWithString(anchorRequirementasCFString,SecCSFlags(),&requirement)
68+
guard reqStatus== errSecSuccess,let requirementelse{
69+
throw.internalError(OSStatus(reqStatus))
70+
}
71+
72+
letvalidateStatus=SecStaticCodeCheckValidity(code,SecCSFlags(), requirement)
5673
guard validateStatus== errSecSuccesselse{
5774
throw.invalidSignature
5875
}
@@ -78,6 +95,32 @@ public class Validator {
7895
}
7996
}
8097

81-
publicstaticletxpcPeerRequirement="anchor apple generic"+ // Apple-issued certificate chain
98+
// This function executes the binary to read its version, and so it assumes
99+
// the signature has already been validated.
100+
publicstaticfunc validateVersion(binaryPath:URL, serverVersion:String)asyncthrows(ValidationError){
101+
guardFileManager.default.fileExists(atPath: binaryPath.path)else{
102+
throw.fileNotFound
103+
}
104+
105+
letversion:String
106+
do{
107+
trychmodX(at: binaryPath)
108+
letversionOutput=tryawaitSubprocess.data(for:[binaryPath.path,"version","--output=json"])
109+
letparsed:VersionOutput=tryJSONDecoder().decode(VersionOutput.self, from: versionOutput)
110+
version= parsed.version
111+
}catch{
112+
throw.unableToReadVersion(error)
113+
}
114+
115+
guard version== serverVersionelse{
116+
throw.binaryVersionMismatch(binaryVersion: version, serverVersion: serverVersion)
117+
}
118+
}
119+
120+
structVersionOutput:Codable{
121+
letversion:String
122+
}
123+
124+
publicstaticletxpcPeerRequirement= anchorRequirement+
82125
" and certificate leaf[subject.OU] =\""+ expectedTeamIdentifier+"\"" // Signed by the Coder team
83126
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp