2018-11-08 10:24:12 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// Copyright © 2018 WireGuard LLC. All Rights Reserved.
|
|
|
|
|
|
|
|
import NetworkExtension
|
|
|
|
|
2018-12-21 04:52:45 +00:00
|
|
|
let tunnelConfigurationVersion = 2
|
|
|
|
|
2018-11-08 10:24:12 +00:00
|
|
|
extension NETunnelProviderProtocol {
|
2018-12-21 04:52:45 +00:00
|
|
|
|
|
|
|
enum Keys: String {
|
|
|
|
case tunnelConfiguration = "TunnelConfiguration"
|
|
|
|
case tunnelConfigurationVersion = "TunnelConfigurationVersion"
|
|
|
|
}
|
|
|
|
|
|
|
|
var tunnelConfiguration: TunnelConfiguration? {
|
|
|
|
migrateConfigurationIfNeeded()
|
|
|
|
|
|
|
|
let tunnelConfigurationData: Data?
|
|
|
|
if let configurationDictionary = providerConfiguration?[Keys.tunnelConfiguration.rawValue] {
|
|
|
|
tunnelConfigurationData = try? JSONSerialization.data(withJSONObject: configurationDictionary, options: [])
|
|
|
|
} else {
|
|
|
|
tunnelConfigurationData = nil
|
|
|
|
}
|
|
|
|
|
|
|
|
guard tunnelConfigurationData != nil else { return nil }
|
|
|
|
return try? JSONDecoder().decode(TunnelConfiguration.self, from: tunnelConfigurationData!)
|
|
|
|
}
|
|
|
|
|
2018-12-21 17:50:32 +00:00
|
|
|
convenience init?(tunnelConfiguration: TunnelConfiguration) {
|
2018-11-08 10:24:12 +00:00
|
|
|
assert(!tunnelConfiguration.interface.name.isEmpty)
|
2018-12-21 04:52:45 +00:00
|
|
|
|
|
|
|
guard let tunnelConfigData = try? JSONEncoder().encode(tunnelConfiguration) else { return nil }
|
|
|
|
guard let tunnelConfigDictionary = try? JSONSerialization.jsonObject(with: tunnelConfigData, options: .allowFragments) else { return nil }
|
|
|
|
|
2018-11-08 10:24:12 +00:00
|
|
|
self.init()
|
|
|
|
|
|
|
|
let appId = Bundle.main.bundleIdentifier!
|
|
|
|
providerBundleIdentifier = "\(appId).network-extension"
|
|
|
|
providerConfiguration = [
|
2018-12-21 04:52:45 +00:00
|
|
|
Keys.tunnelConfiguration.rawValue: tunnelConfigDictionary,
|
2018-12-21 17:50:32 +00:00
|
|
|
Keys.tunnelConfigurationVersion.rawValue: tunnelConfigurationVersion
|
2018-11-08 10:24:12 +00:00
|
|
|
]
|
|
|
|
|
2018-12-21 04:52:45 +00:00
|
|
|
let endpoints = tunnelConfiguration.peers.compactMap { $0.endpoint }
|
2018-11-08 10:24:12 +00:00
|
|
|
if endpoints.count == 1 {
|
2018-12-21 04:52:45 +00:00
|
|
|
serverAddress = endpoints[0].stringRepresentation
|
2018-11-08 10:24:12 +00:00
|
|
|
} else if endpoints.isEmpty {
|
|
|
|
serverAddress = "Unspecified"
|
|
|
|
} else {
|
|
|
|
serverAddress = "Multiple endpoints"
|
|
|
|
}
|
|
|
|
username = tunnelConfiguration.interface.name
|
|
|
|
}
|
|
|
|
|
2018-12-19 10:32:48 +00:00
|
|
|
func hasTunnelConfiguration(tunnelConfiguration otherTunnelConfiguration: TunnelConfiguration) -> Bool {
|
2018-12-21 04:52:45 +00:00
|
|
|
guard let serializedThisTunnelConfiguration = try? JSONEncoder().encode(tunnelConfiguration) else { return false }
|
2018-12-19 10:32:48 +00:00
|
|
|
guard let serializedOtherTunnelConfiguration = try? JSONEncoder().encode(otherTunnelConfiguration) else { return false }
|
|
|
|
return serializedThisTunnelConfiguration == serializedOtherTunnelConfiguration
|
|
|
|
}
|
2018-12-21 04:52:45 +00:00
|
|
|
|
|
|
|
@discardableResult
|
|
|
|
func migrateConfigurationIfNeeded() -> Bool {
|
|
|
|
guard let providerConfiguration = providerConfiguration else { return false }
|
|
|
|
guard let configurationVersion = providerConfiguration[Keys.tunnelConfigurationVersion.rawValue] as? Int ?? providerConfiguration["tunnelConfigurationVersion"] as? Int else { return false }
|
|
|
|
|
|
|
|
if configurationVersion < tunnelConfigurationVersion {
|
|
|
|
switch configurationVersion {
|
|
|
|
case 1:
|
|
|
|
migrateFromConfigurationV1()
|
|
|
|
default:
|
|
|
|
fatalError("No migration from configuration version \(configurationVersion) exists.")
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
private func migrateFromConfigurationV1() {
|
|
|
|
guard let serializedTunnelConfiguration = providerConfiguration?["tunnelConfiguration"] as? Data else { return }
|
|
|
|
guard let configuration = try? JSONDecoder().decode(LegacyTunnelConfiguration.self, from: serializedTunnelConfiguration) else { return }
|
|
|
|
guard let tunnelConfigData = try? JSONEncoder().encode(configuration.migrated) else { return }
|
|
|
|
guard let tunnelConfigDictionary = try? JSONSerialization.jsonObject(with: tunnelConfigData, options: .allowFragments) else { return }
|
|
|
|
|
|
|
|
providerConfiguration = [
|
|
|
|
Keys.tunnelConfiguration.rawValue: tunnelConfigDictionary,
|
2018-12-21 17:50:32 +00:00
|
|
|
Keys.tunnelConfigurationVersion.rawValue: tunnelConfigurationVersion
|
2018-12-21 04:52:45 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2018-11-08 10:24:12 +00:00
|
|
|
}
|