if passwordReference == nil {
return nil
}
+ #if os(macOS)
+ providerConfiguration = ["UID": getuid()]
+ #endif
let endpoints = tunnelConfiguration.peers.compactMap { $0.endpoint }
if endpoints.count == 1 {
* in the keychain. But it's still useful to keep the migration
* around so that .mobileconfig files are easier.
*/
- guard let oldConfig = providerConfiguration?["WgQuickConfig"] as? String else { return false }
- providerConfiguration = nil
- guard passwordReference == nil else { return true }
- wg_log(.debug, message: "Migrating tunnel configuration '\(name)'")
- passwordReference = Keychain.makeReference(containing: oldConfig, called: name)
- return true
+ if let oldConfig = providerConfiguration?["WgQuickConfig"] as? String {
+ #if os(macOS)
+ providerConfiguration = ["UID": getuid()]
+ #elseif os(iOS)
+ providerConfiguration = nil
+ #else
+ #error("Unimplemented")
+ #endif
+ guard passwordReference == nil else { return true }
+ wg_log(.debug, message: "Migrating tunnel configuration '\(name)'")
+ passwordReference = Keychain.makeReference(containing: oldConfig, called: name)
+ return true
+ }
+ #if os(macOS)
+ if passwordReference != nil && providerConfiguration?["UID"] == nil && verifyConfigurationReference() {
+ providerConfiguration = ["UID": getuid()]
+ return true
+ }
+ #endif
+ return false
}
}
#if os(iOS)
let passwordRef = proto.verifyConfigurationReference() ? proto.passwordReference : nil
#elseif os(macOS)
- let passwordRef = proto.passwordReference // To handle multiple users in macOS, we skip verifying
+ let passwordRef: Data?
+ if proto.providerConfiguration?["UID"] as? uid_t == getuid() {
+ passwordRef = proto.verifyConfigurationReference() ? proto.passwordReference : nil
+ } else {
+ passwordRef = proto.passwordReference // To handle multiple users in macOS, we skip verifying
+ }
#else
#error("Unimplemented")
#endif
func remove(tunnel: TunnelContainer, completionHandler: @escaping (TunnelsManagerError?) -> Void) {
let tunnelProviderManager = tunnel.tunnelProvider
- if tunnel.isTunnelConfigurationAvailableInKeychain {
+ #if os(macOS)
+ if tunnel.isTunnelAvailableToUser {
(tunnelProviderManager.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference()
}
-
+ #elseif os(iOS)
+ (tunnelProviderManager.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference()
+ #else
+ #error("Unimplemented")
+ #endif
tunnelProviderManager.removeFromPreferences { [weak self] error in
guard error == nil else {
wg_log(.error, message: "Remove: Saving configuration failed: \(error!)")
return tunnelProvider.tunnelConfiguration
}
- var isTunnelConfigurationAvailableInKeychain: Bool {
- return tunnelProvider.isTunnelConfigurationAvailableInKeychain
- }
-
var onDemandOption: ActivateOnDemandOption {
return ActivateOnDemandOption(from: tunnelProvider)
}
+ #if os(macOS)
+ var isTunnelAvailableToUser: Bool {
+ return (tunnelProvider.protocolConfiguration as? NETunnelProviderProtocol)?.providerConfiguration?["UID"] as? uid_t == getuid()
+ }
+ #endif
+
init(tunnel: NETunnelProviderManager) {
name = tunnel.localizedDescription ?? "Unnamed"
let status = TunnelStatus(from: tunnel.connection.status)
}
extension NETunnelProviderManager {
- private static var cachedIsConfigAvailableInKeychainKey: UInt8 = 0
private static var cachedConfigKey: UInt8 = 0
- var isTunnelConfigurationAvailableInKeychain: Bool {
- if let cachedNumber = objc_getAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey) as? NSNumber {
- return cachedNumber.boolValue
- }
- let isAvailable = (protocolConfiguration as? NETunnelProviderProtocol)?.verifyConfigurationReference() ?? false
- objc_setAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey, NSNumber(value: isAvailable), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- return isAvailable
- }
-
var tunnelConfiguration: TunnelConfiguration? {
if let cached = objc_getAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey) as? TunnelConfiguration {
return cached
protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration, previouslyFrom: protocolConfiguration)
localizedDescription = tunnelConfiguration.name
objc_setAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey, tunnelConfiguration, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- objc_setAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey, NSNumber(value: true), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
func isEquivalentTo(_ tunnel: TunnelContainer) -> Bool {
- switch (isTunnelConfigurationAvailableInKeychain, tunnel.isTunnelConfigurationAvailableInKeychain) {
- case (true, true):
- return tunnelConfiguration == tunnel.tunnelConfiguration
- case (false, false):
- return localizedDescription == tunnel.name
- default:
- return false
- }
+ return localizedDescription == tunnel.name && tunnelConfiguration == tunnel.tunnelConfiguration
}
}