Move appGroup out of Configuration

Decouple VPN parameters.
This commit is contained in:
Davide De Rosa 2018-09-07 00:23:25 +02:00
parent a54c767f57
commit 14f5a68c12
3 changed files with 35 additions and 34 deletions

View File

@ -147,13 +147,6 @@ extension TunnelKitProvider {
/// The way to create a `TunnelKitProvider.Configuration` object for the tunnel profile. /// The way to create a `TunnelKitProvider.Configuration` object for the tunnel profile.
public struct ConfigurationBuilder { public struct ConfigurationBuilder {
// MARK: App group
/// The name of a shared app group.
public let appGroup: String
// MARK: Tunnel parameters
/// Prefers resolved addresses over DNS resolution. `resolvedAddresses` must be set and non-empty. Default is `false`. /// Prefers resolved addresses over DNS resolution. `resolvedAddresses` must be set and non-empty. Default is `false`.
/// ///
/// - Seealso: `fallbackServerAddresses` /// - Seealso: `fallbackServerAddresses`
@ -204,17 +197,16 @@ extension TunnelKitProvider {
/** /**
Default initializer. Default initializer.
- Parameter appGroup: The name of the app group in which the tunnel extension lives in.
*/ */
public init(appGroup: String) { public init() {
self.appGroup = appGroup
prefersResolvedAddresses = false prefersResolvedAddresses = false
resolvedAddresses = nil resolvedAddresses = nil
endpointProtocols = [EndpointProtocol(.udp, 1194)] endpointProtocols = [EndpointProtocol(.udp, 1194)]
cipher = .aes128cbc cipher = .aes128cbc
digest = .sha1 digest = .sha1
ca = nil ca = nil
clientCertificate = nil
clientKey = nil
mtu = 1500 mtu = 1500
compressionFraming = .disabled compressionFraming = .disabled
renegotiatesAfterSeconds = nil renegotiatesAfterSeconds = nil
@ -226,9 +218,6 @@ extension TunnelKitProvider {
fileprivate init(providerConfiguration: [String: Any]) throws { fileprivate init(providerConfiguration: [String: Any]) throws {
let S = Configuration.Keys.self let S = Configuration.Keys.self
guard let appGroup = providerConfiguration[S.appGroup] as? String else {
throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(S.appGroup)]")
}
guard let cipherAlgorithm = providerConfiguration[S.cipherAlgorithm] as? String, let cipher = SessionProxy.Cipher(rawValue: cipherAlgorithm) else { guard let cipherAlgorithm = providerConfiguration[S.cipherAlgorithm] as? String, let cipher = SessionProxy.Cipher(rawValue: cipherAlgorithm) else {
throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(S.cipherAlgorithm)]") throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(S.cipherAlgorithm)]")
} }
@ -264,7 +253,6 @@ extension TunnelKitProvider {
} }
endpointProtocols = try endpointProtocolsStrings.map { try EndpointProtocol.deserialized($0) } endpointProtocols = try endpointProtocolsStrings.map { try EndpointProtocol.deserialized($0) }
self.appGroup = appGroup
self.cipher = cipher self.cipher = cipher
self.digest = digest self.digest = digest
self.ca = ca self.ca = ca
@ -301,7 +289,6 @@ extension TunnelKitProvider {
*/ */
public func build() -> Configuration { public func build() -> Configuration {
return Configuration( return Configuration(
appGroup: appGroup,
prefersResolvedAddresses: prefersResolvedAddresses, prefersResolvedAddresses: prefersResolvedAddresses,
resolvedAddresses: resolvedAddresses, resolvedAddresses: resolvedAddresses,
endpointProtocols: endpointProtocols, endpointProtocols: endpointProtocols,
@ -354,9 +341,6 @@ extension TunnelKitProvider {
static let debugLogFormat = "DebugLogFormat" static let debugLogFormat = "DebugLogFormat"
} }
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.appGroup`
public let appGroup: String
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.prefersResolvedAddresses` /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.prefersResolvedAddresses`
public let prefersResolvedAddresses: Bool public let prefersResolvedAddresses: Bool
@ -401,19 +385,29 @@ extension TunnelKitProvider {
// MARK: Shortcuts // MARK: Shortcuts
var defaults: UserDefaults? { func existingLog(in defaults: UserDefaults) -> [String]? {
return UserDefaults(suiteName: appGroup)
}
var existingLog: [String]? {
guard shouldDebug, let key = debugLogKey else { guard shouldDebug, let key = debugLogKey else {
return nil return nil
} }
return defaults?.array(forKey: key) as? [String] return defaults.array(forKey: key) as? [String]
} }
// MARK: API // MARK: API
/**
Parses the app group from a provider configuration map.
- Parameter from: The map to parse.
- Returns: The parsed app group.
- Throws: `ProviderError.configuration` if `providerConfiguration` does not contain an app group.
*/
public static func appGroup(from providerConfiguration: [String: Any]) throws -> String {
guard let appGroup = providerConfiguration[Keys.appGroup] as? String else {
throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration[\(Keys.appGroup)]")
}
return appGroup
}
/** /**
Parses a new `TunnelKitProvider.Configuration` object from a provider configuration map. Parses a new `TunnelKitProvider.Configuration` object from a provider configuration map.
@ -429,9 +423,10 @@ extension TunnelKitProvider {
/** /**
Returns a dictionary representation of this configuration for use with `NETunnelProviderProtocol.providerConfiguration`. Returns a dictionary representation of this configuration for use with `NETunnelProviderProtocol.providerConfiguration`.
- Parameter appGroup: The name of the app group in which the tunnel extension lives in.
- Returns: The dictionary representation of `self`. - Returns: The dictionary representation of `self`.
*/ */
public func generatedProviderConfiguration() -> [String: Any] { public func generatedProviderConfiguration(appGroup: String) -> [String: Any] {
let S = Keys.self let S = Keys.self
var dict: [String: Any] = [ var dict: [String: Any] = [
@ -472,11 +467,12 @@ extension TunnelKitProvider {
Generates a `NETunnelProviderProtocol` from this configuration. Generates a `NETunnelProviderProtocol` from this configuration.
- Parameter bundleIdentifier: The provider bundle identifier required to locate the tunnel extension. - Parameter bundleIdentifier: The provider bundle identifier required to locate the tunnel extension.
- Parameter appGroup: The name of the app group in which the tunnel extension lives in.
- Parameter endpoint: The `TunnelKitProvider.AuthenticatedEndpoint` the tunnel will connect to. - Parameter endpoint: The `TunnelKitProvider.AuthenticatedEndpoint` the tunnel will connect to.
- Returns: The generated `NETunnelProviderProtocol` object. - Returns: The generated `NETunnelProviderProtocol` object.
- Throws: `ProviderError.configuration` if unable to store the `endpoint.password` to the `appGroup` keychain. - Throws: `ProviderError.configuration` if unable to store the `endpoint.password` to the `appGroup` keychain.
*/ */
public func generatedTunnelProtocol(withBundleIdentifier bundleIdentifier: String, endpoint: AuthenticatedEndpoint) throws -> NETunnelProviderProtocol { public func generatedTunnelProtocol(withBundleIdentifier bundleIdentifier: String, appGroup: String, endpoint: AuthenticatedEndpoint) throws -> NETunnelProviderProtocol {
let protocolConfiguration = NETunnelProviderProtocol() let protocolConfiguration = NETunnelProviderProtocol()
let keychain = Keychain(group: appGroup) let keychain = Keychain(group: appGroup)
@ -490,7 +486,7 @@ extension TunnelKitProvider {
protocolConfiguration.serverAddress = endpoint.hostname protocolConfiguration.serverAddress = endpoint.hostname
protocolConfiguration.username = endpoint.username protocolConfiguration.username = endpoint.username
protocolConfiguration.passwordReference = try? keychain.passwordReference(for: endpoint.username) protocolConfiguration.passwordReference = try? keychain.passwordReference(for: endpoint.username)
protocolConfiguration.providerConfiguration = generatedProviderConfiguration() protocolConfiguration.providerConfiguration = generatedProviderConfiguration(appGroup: appGroup)
return protocolConfiguration return protocolConfiguration
} }
@ -536,7 +532,7 @@ extension TunnelKitProvider.Configuration: Equatable {
- Returns: An editable `TunnelKitProvider.ConfigurationBuilder` initialized with this configuration. - Returns: An editable `TunnelKitProvider.ConfigurationBuilder` initialized with this configuration.
*/ */
public func builder() -> TunnelKitProvider.ConfigurationBuilder { public func builder() -> TunnelKitProvider.ConfigurationBuilder {
var builder = TunnelKitProvider.ConfigurationBuilder(appGroup: appGroup) var builder = TunnelKitProvider.ConfigurationBuilder()
builder.endpointProtocols = endpointProtocols builder.endpointProtocols = endpointProtocols
builder.cipher = cipher builder.cipher = cipher
builder.digest = digest builder.digest = digest

View File

@ -92,10 +92,14 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
// MARK: Tunnel configuration // MARK: Tunnel configuration
private var appGroup: String!
private var cfg: Configuration! private var cfg: Configuration!
private var strategy: ConnectionStrategy! private var strategy: ConnectionStrategy!
private lazy var defaults = UserDefaults(suiteName: appGroup)
// MARK: Internal state // MARK: Internal state
private var proxy: SessionProxy? private var proxy: SessionProxy?
@ -121,6 +125,7 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration") throw ProviderError.configuration(field: "protocolConfiguration.providerConfiguration")
} }
try endpoint = AuthenticatedEndpoint(protocolConfiguration: tunnelProtocol) try endpoint = AuthenticatedEndpoint(protocolConfiguration: tunnelProtocol)
try appGroup = Configuration.appGroup(from: providerConfiguration)
try cfg = Configuration.parsed(from: providerConfiguration) try cfg = Configuration.parsed(from: providerConfiguration)
} catch let e { } catch let e {
var message: String? var message: String?
@ -143,7 +148,7 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
strategy = ConnectionStrategy(hostname: endpoint.hostname, configuration: cfg) strategy = ConnectionStrategy(hostname: endpoint.hostname, configuration: cfg)
if var existingLog = cfg.existingLog { if let defaults = defaults, var existingLog = cfg.existingLog(in: defaults) {
if let i = existingLog.index(of: logSeparator) { if let i = existingLog.index(of: logSeparator) {
existingLog.removeFirst(i + 2) existingLog.removeFirst(i + 2)
} }
@ -565,7 +570,7 @@ extension TunnelKitProvider {
private func flushLog() { private func flushLog() {
log.debug("Flushing log...") log.debug("Flushing log...")
if let defaults = cfg.defaults, let key = cfg.debugLogKey { if let defaults = defaults, let key = cfg.debugLogKey {
memoryLog.flush(to: defaults, with: key) memoryLog.flush(to: defaults, with: key)
} }
} }

View File

@ -63,7 +63,7 @@ class AppExtensionTests: XCTestCase {
password: "bar" password: "bar"
) )
builder = TunnelKitProvider.ConfigurationBuilder(appGroup: appGroup) builder = TunnelKitProvider.ConfigurationBuilder()
XCTAssertNotNil(builder) XCTAssertNotNil(builder)
builder.cipher = .aes128cbc builder.cipher = .aes128cbc
@ -71,7 +71,7 @@ class AppExtensionTests: XCTestCase {
builder.ca = CryptoContainer(pem: "abcdef") builder.ca = CryptoContainer(pem: "abcdef")
cfg = builder.build() cfg = builder.build()
let proto = try? cfg.generatedTunnelProtocol(withBundleIdentifier: identifier, endpoint: endpoint) let proto = try? cfg.generatedTunnelProtocol(withBundleIdentifier: identifier, appGroup: appGroup, endpoint: endpoint)
XCTAssertNotNil(proto) XCTAssertNotNil(proto)
XCTAssertEqual(proto?.providerBundleIdentifier, identifier) XCTAssertEqual(proto?.providerBundleIdentifier, identifier)
@ -84,7 +84,7 @@ class AppExtensionTests: XCTestCase {
} }
let K = TunnelKitProvider.Configuration.Keys.self let K = TunnelKitProvider.Configuration.Keys.self
XCTAssertEqual(proto?.providerConfiguration?[K.appGroup] as? String, cfg.appGroup) XCTAssertEqual(proto?.providerConfiguration?[K.appGroup] as? String, appGroup)
XCTAssertEqual(proto?.providerConfiguration?[K.cipherAlgorithm] as? String, cfg.cipher.rawValue) XCTAssertEqual(proto?.providerConfiguration?[K.cipherAlgorithm] as? String, cfg.cipher.rawValue)
XCTAssertEqual(proto?.providerConfiguration?[K.digestAlgorithm] as? String, cfg.digest.rawValue) XCTAssertEqual(proto?.providerConfiguration?[K.digestAlgorithm] as? String, cfg.digest.rawValue)
XCTAssertEqual(proto?.providerConfiguration?[K.ca] as? String, cfg.ca?.pem) XCTAssertEqual(proto?.providerConfiguration?[K.ca] as? String, cfg.ca?.pem)