-
Notifications
You must be signed in to change notification settings - Fork 274
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(apple): Use keychain from the tunnel process *only* #4335
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Ignored Deployment
|
Terraform Cloud Plan Output
|
Performance Test ResultsTCP
UDP
|
a540116
to
a81c963
Compare
adapter?.getResourcesIfVersionDifferentFrom(hash: hash) { | ||
resourceListJSON in | ||
completionHandler?(resourceListJSON?.data(using: .utf8)) | ||
override func handleAppMessage(_ message: Data, completionHandler: ((Data?) -> Void)? = nil) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the primary IPC callback from GUI -> Tunnel.
We overload the message
parameter to determine what the GUI is asking the tunnel to do. This could be expanded in the future using JSON and more structured format, but I kept it simple for now as it only handle 2 commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Data
is Vec<u8>
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so, it's a byte array
@AndrewDryga This was tested on macOS 12.7.4 and the keychain issue is fixed. |
Fixes #2324 (finally!) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand all the code changes but the reasoning makes sense.
On Windows and Linux I'm planning to go the other way and have the GUI process store the token in the keyring, since it should be more secure if the OS protects it with the user's password. So the GUI process will do almost everything with the token, except for sending it to the portal.
@@ -20,8 +20,11 @@ public enum KeychainError: Error { | |||
public actor Keychain { | |||
private let label = "Firezone token" | |||
private let description = "Firezone access token used to authenticate the client." | |||
private let account = "Firezone" | |||
private let service = Bundle.main.bundleIdentifier! | |||
private let service = "dev.firezone.firezone" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw this change the other direction in another PR. Is it because the bundle ID is not available in the NetworkExtension?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other PR is based on this one, so it changes it back (sorry -- kinda a pita to switch branches when working on the Apple/Android clients)
@@ -138,13 +135,14 @@ public actor Keychain { | |||
} | |||
} | |||
|
|||
func search() async -> PersistentRef? { | |||
public func search() async -> PersistentRef? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is search
what it's called when you get a token from the keychain?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
search
gives you a Persistent Ref which is just a 20-byte pointer to the item
kSecAttrLabel: self.label, | ||
kSecAttrAccount: self.account, | ||
kSecAttrDescription: self.description, | ||
kSecAttrService: self.service, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where were these values coming from before if they weren't members of self
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still from the class -- the scope changes when inside Task
adapter?.getResourcesIfVersionDifferentFrom(hash: hash) { | ||
resourceListJSON in | ||
completionHandler?(resourceListJSON?.data(using: .utf8)) | ||
override func handleAppMessage(_ message: Data, completionHandler: ((Data?) -> Void)? = nil) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Data
is Vec<u8>
, right?
Yeah, I considered that as well, but we need headless on the Apple clients because on iOS our GUI process can be reaped by the system at any time. |
So if the GUI and tunnel process are both reaped, the tunnel must be able to bring itself back without the GUI helping? Makes sense |
This fixes another long-standing bug with the Apple client: Keychain groups.
Apple's Keychain docs are woefully unclear and lacking on the Keychain.
These are the main takeaways:
startTunnel
call, which the system then passes to ourPacketTunnelProvider
class.This uses the file-based Keychain, but since we need to use that keychain as the root tunnel proc, we don't have much choice. The "Allow access" dialog bug on macOS 12 is fixed by the fact that we are only accessing it from the same user (tunnel proc) that created it now.