Merge pull request #194 from passepartoutvpn/refactor-provider-configuration
Refactor internal provider configuration
This commit is contained in:
commit
1bf6c9084a
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Encoding of internal provider configuration.
|
||||||
|
|
||||||
## 3.1.0 (2020-12-28)
|
## 3.1.0 (2020-12-28)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
PODS:
|
PODS:
|
||||||
- OpenSSL-Apple (1.1.1h.8)
|
- OpenSSL-Apple (1.1.1h.10)
|
||||||
- SwiftyBeaver (1.9.3)
|
- SwiftyBeaver (1.9.3)
|
||||||
- TunnelKit (3.1.0):
|
- TunnelKit (3.2.0):
|
||||||
- TunnelKit/Protocols/OpenVPN (= 3.1.0)
|
- TunnelKit/Protocols/OpenVPN (= 3.2.0)
|
||||||
- TunnelKit/AppExtension (3.1.0):
|
- TunnelKit/AppExtension (3.2.0):
|
||||||
- SwiftyBeaver
|
- SwiftyBeaver
|
||||||
- TunnelKit/Core
|
- TunnelKit/Core
|
||||||
- TunnelKit/Core (3.1.0):
|
- TunnelKit/Core (3.2.0):
|
||||||
- SwiftyBeaver
|
- SwiftyBeaver
|
||||||
- TunnelKit/Manager (3.1.0):
|
- TunnelKit/Manager (3.2.0):
|
||||||
- SwiftyBeaver
|
- SwiftyBeaver
|
||||||
- TunnelKit/Protocols/OpenVPN (3.1.0):
|
- TunnelKit/Protocols/OpenVPN (3.2.0):
|
||||||
- OpenSSL-Apple (~> 1.1.1h.8)
|
- OpenSSL-Apple (~> 1.1.1h.10)
|
||||||
- TunnelKit/AppExtension
|
- TunnelKit/AppExtension
|
||||||
- TunnelKit/Core
|
- TunnelKit/Core
|
||||||
- TunnelKit/Manager
|
- TunnelKit/Manager
|
||||||
|
@ -30,9 +30,9 @@ EXTERNAL SOURCES:
|
||||||
:path: ".."
|
:path: ".."
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
OpenSSL-Apple: 70990157548ecf94885310231aff52db698e1077
|
OpenSSL-Apple: 8a8fcb06fb66f9c2f7aed45ce363668493b8e5f6
|
||||||
SwiftyBeaver: 2e8acd6fc90c6d0a27055867a290794926d57c02
|
SwiftyBeaver: 2e8acd6fc90c6d0a27055867a290794926d57c02
|
||||||
TunnelKit: 4db9180956f8aaf4ab152fd0d38c6c9c63a46cf8
|
TunnelKit: b9ea352cbcce641f98687109c2e7d8cb1fa40e19
|
||||||
|
|
||||||
PODFILE CHECKSUM: 518aaea9a529c96ba3024918bc0850dd6e92ac61
|
PODFILE CHECKSUM: 518aaea9a529c96ba3024918bc0850dd6e92ac61
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# TunnelKit
|
# TunnelKit
|
||||||
|
|
||||||
![iOS 12+](https://img.shields.io/badge/ios-12+-green.svg)
|
![iOS 12+](https://img.shields.io/badge/ios-12+-green.svg)
|
||||||
|
![macOS 10.15+](https://img.shields.io/badge/macos-10.15+-green.svg)
|
||||||
[![OpenSSL 1.1.1h](https://img.shields.io/badge/openssl-1.1.1h-d69c68.svg)](https://www.openssl.org/news/openssl-1.1.1-notes.html)
|
[![OpenSSL 1.1.1h](https://img.shields.io/badge/openssl-1.1.1h-d69c68.svg)](https://www.openssl.org/news/openssl-1.1.1-notes.html)
|
||||||
[![License GPLv3](https://img.shields.io/badge/license-GPLv3-lightgray.svg)](LICENSE)
|
[![License GPLv3](https://img.shields.io/badge/license-GPLv3-lightgray.svg)](LICENSE)
|
||||||
[![Travis-CI](https://api.travis-ci.org/passepartoutvpn/tunnelkit.svg?branch=master)](https://travis-ci.org/passepartoutvpn/tunnelkit)
|
[![Travis-CI](https://api.travis-ci.org/passepartoutvpn/tunnelkit.svg?branch=master)](https://travis-ci.org/passepartoutvpn/tunnelkit)
|
||||||
|
@ -52,8 +53,8 @@ Unsupported:
|
||||||
|
|
||||||
Ignored:
|
Ignored:
|
||||||
|
|
||||||
- MTU overrides
|
- Some MTU overrides
|
||||||
- `--*-mtu` and variants
|
- `--link-mtu` and variants
|
||||||
- `--mssfix`
|
- `--mssfix`
|
||||||
- Multiple `--remote` with different `host` values (first wins)
|
- Multiple `--remote` with different `host` values (first wins)
|
||||||
- Static client-side routes
|
- Static client-side routes
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = "TunnelKit"
|
s.name = "TunnelKit"
|
||||||
s.version = "3.1.0"
|
s.version = "3.2.0"
|
||||||
s.summary = "Non-official OpenVPN client for Apple platforms."
|
s.summary = "Non-official OpenVPN client for Apple platforms."
|
||||||
|
|
||||||
s.homepage = "https://github.com/passepartoutvpn/tunnelkit"
|
s.homepage = "https://github.com/passepartoutvpn/tunnelkit"
|
||||||
|
|
|
@ -750,12 +750,12 @@
|
||||||
0E23B3F722982AF800304C30 /* AppExtension */ = {
|
0E23B3F722982AF800304C30 /* AppExtension */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
0E23B3F822982AF800304C30 /* OpenVPNTunnelProvider+Interaction.swift */,
|
|
||||||
0E23B3F922982AF800304C30 /* NEUDPLink.swift */,
|
|
||||||
0E23B3FA22982AF800304C30 /* ConnectionStrategy.swift */,
|
0E23B3FA22982AF800304C30 /* ConnectionStrategy.swift */,
|
||||||
0E23B3FB22982AF800304C30 /* OpenVPNTunnelProvider+Configuration.swift */,
|
|
||||||
0E23B3FC22982AF800304C30 /* NETCPLink.swift */,
|
0E23B3FC22982AF800304C30 /* NETCPLink.swift */,
|
||||||
|
0E23B3F922982AF800304C30 /* NEUDPLink.swift */,
|
||||||
0E23B3FD22982AF800304C30 /* OpenVPNTunnelProvider.swift */,
|
0E23B3FD22982AF800304C30 /* OpenVPNTunnelProvider.swift */,
|
||||||
|
0E23B3FB22982AF800304C30 /* OpenVPNTunnelProvider+Configuration.swift */,
|
||||||
|
0E23B3F822982AF800304C30 /* OpenVPNTunnelProvider+Interaction.swift */,
|
||||||
);
|
);
|
||||||
path = AppExtension;
|
path = AppExtension;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1781,7 +1781,7 @@
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 766;
|
CURRENT_PROJECT_VERSION = 825;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
|
@ -1846,7 +1846,7 @@
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 766;
|
CURRENT_PROJECT_VERSION = 825;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
@ -1879,7 +1879,7 @@
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 766;
|
DYLIB_CURRENT_VERSION = 825;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-iOS/Info.plist";
|
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-iOS/Info.plist";
|
||||||
|
@ -1904,7 +1904,7 @@
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 766;
|
DYLIB_CURRENT_VERSION = 825;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-iOS/Info.plist";
|
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-iOS/Info.plist";
|
||||||
|
@ -1929,7 +1929,7 @@
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 766;
|
DYLIB_CURRENT_VERSION = 825;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
FRAMEWORK_VERSION = A;
|
FRAMEWORK_VERSION = A;
|
||||||
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-macOS/Info.plist";
|
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-macOS/Info.plist";
|
||||||
|
@ -1953,7 +1953,7 @@
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 766;
|
DYLIB_CURRENT_VERSION = 825;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
FRAMEWORK_VERSION = A;
|
FRAMEWORK_VERSION = A;
|
||||||
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-macOS/Info.plist";
|
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-macOS/Info.plist";
|
||||||
|
|
|
@ -42,3 +42,20 @@ public extension DispatchQueue {
|
||||||
asyncAfter(deadline: .now() + after, execute: block)
|
asyncAfter(deadline: .now() + after, execute: block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// :nodoc:
|
||||||
|
func fromDictionary<T: Decodable>(_ type: T.Type, _ dictionary: [String: Any]) throws -> T {
|
||||||
|
let data = try JSONSerialization.data(withJSONObject: dictionary, options: .fragmentsAllowed)
|
||||||
|
return try JSONDecoder().decode(T.self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// :nodoc:
|
||||||
|
public extension Encodable {
|
||||||
|
func asDictionary() throws -> [String: Any] {
|
||||||
|
let data = try JSONEncoder().encode(self)
|
||||||
|
guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed) as? [String: Any] else {
|
||||||
|
fatalError("JSONSerialization failed to encode")
|
||||||
|
}
|
||||||
|
return dictionary
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ import SwiftyBeaver
|
||||||
private let log = SwiftyBeaver.self
|
private let log = SwiftyBeaver.self
|
||||||
|
|
||||||
extension OpenVPNTunnelProvider {
|
extension OpenVPNTunnelProvider {
|
||||||
|
private struct ExtraKeys {
|
||||||
|
static let appGroup = "appGroup"
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Configuration
|
// MARK: Configuration
|
||||||
|
|
||||||
|
@ -100,24 +103,6 @@ extension OpenVPNTunnelProvider {
|
||||||
versionIdentifier = ConfigurationBuilder.defaults.versionIdentifier
|
versionIdentifier = ConfigurationBuilder.defaults.versionIdentifier
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate init(providerConfiguration: [String: Any]) throws {
|
|
||||||
let S = Configuration.Keys.self
|
|
||||||
|
|
||||||
sessionConfiguration = try OpenVPN.Configuration.with(providerConfiguration: providerConfiguration)
|
|
||||||
prefersResolvedAddresses = providerConfiguration[S.prefersResolvedAddresses] as? Bool ?? ConfigurationBuilder.defaults.prefersResolvedAddresses
|
|
||||||
resolvedAddresses = providerConfiguration[S.resolvedAddresses] as? [String]
|
|
||||||
shouldDebug = providerConfiguration[S.debug] as? Bool ?? ConfigurationBuilder.defaults.shouldDebug
|
|
||||||
if shouldDebug {
|
|
||||||
debugLogFormat = providerConfiguration[S.debugLogFormat] as? String
|
|
||||||
}
|
|
||||||
masksPrivateData = providerConfiguration[S.masksPrivateData] as? Bool ?? ConfigurationBuilder.defaults.masksPrivateData
|
|
||||||
versionIdentifier = providerConfiguration[S.versionIdentifier] as? String ?? ConfigurationBuilder.defaults.versionIdentifier
|
|
||||||
|
|
||||||
guard !prefersResolvedAddresses || !(resolvedAddresses?.isEmpty ?? true) else {
|
|
||||||
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.prefersResolvedAddresses)] is true but no [\(S.resolvedAddresses)]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Builds a `OpenVPNTunnelProvider.Configuration` object that will connect to the provided endpoint.
|
Builds a `OpenVPNTunnelProvider.Configuration` object that will connect to the provided endpoint.
|
||||||
|
|
||||||
|
@ -138,79 +123,6 @@ extension OpenVPNTunnelProvider {
|
||||||
|
|
||||||
/// Offers a bridge between the abstract `OpenVPNTunnelProvider.ConfigurationBuilder` and a concrete `NETunnelProviderProtocol` profile.
|
/// Offers a bridge between the abstract `OpenVPNTunnelProvider.ConfigurationBuilder` and a concrete `NETunnelProviderProtocol` profile.
|
||||||
public struct Configuration: Codable {
|
public struct Configuration: Codable {
|
||||||
struct Keys {
|
|
||||||
static let appGroup = "AppGroup"
|
|
||||||
|
|
||||||
static let versionIdentifier = "VersionIdentifier"
|
|
||||||
|
|
||||||
// MARK: SessionConfiguration
|
|
||||||
|
|
||||||
static let cipherAlgorithm = "CipherAlgorithm"
|
|
||||||
|
|
||||||
static let digestAlgorithm = "DigestAlgorithm"
|
|
||||||
|
|
||||||
static let compressionFraming = "CompressionFraming"
|
|
||||||
|
|
||||||
static let compressionAlgorithm = "CompressionAlgorithm"
|
|
||||||
|
|
||||||
static let ca = "CA"
|
|
||||||
|
|
||||||
static let clientCertificate = "ClientCertificate"
|
|
||||||
|
|
||||||
static let clientKey = "ClientKey"
|
|
||||||
|
|
||||||
static let tlsWrap = "TLSWrap"
|
|
||||||
|
|
||||||
static let tlsSecurityLevel = "TLSSecurityLevel"
|
|
||||||
|
|
||||||
static let keepAlive = "KeepAlive"
|
|
||||||
|
|
||||||
static let keepAliveTimeout = "KeepAliveTimeout"
|
|
||||||
|
|
||||||
static let endpointProtocols = "EndpointProtocols"
|
|
||||||
|
|
||||||
static let renegotiatesAfter = "RenegotiatesAfter"
|
|
||||||
|
|
||||||
static let checksEKU = "ChecksEKU"
|
|
||||||
|
|
||||||
static let checksSANHost = "checksSANHost"
|
|
||||||
|
|
||||||
static let sanHost = "sanHost"
|
|
||||||
|
|
||||||
static let randomizeEndpoint = "RandomizeEndpoint"
|
|
||||||
|
|
||||||
static let usesPIAPatches = "UsesPIAPatches"
|
|
||||||
|
|
||||||
static let mtu = "MTU"
|
|
||||||
|
|
||||||
static let dnsServers = "DNSServers"
|
|
||||||
|
|
||||||
static let searchDomains = "SearchDomains"
|
|
||||||
|
|
||||||
static let httpProxy = "HTTPProxy"
|
|
||||||
|
|
||||||
static let httpsProxy = "HTTPSProxy"
|
|
||||||
|
|
||||||
static let proxyAutoConfigurationURL = "ProxyAutoConfigurationURL"
|
|
||||||
|
|
||||||
static let proxyBypassDomains = "ProxyBypassDomains"
|
|
||||||
|
|
||||||
static let routingPolicies = "RoutingPolicies"
|
|
||||||
|
|
||||||
// MARK: Customization
|
|
||||||
|
|
||||||
static let prefersResolvedAddresses = "PrefersResolvedAddresses"
|
|
||||||
|
|
||||||
static let resolvedAddresses = "ResolvedAddresses"
|
|
||||||
|
|
||||||
// MARK: Debugging
|
|
||||||
|
|
||||||
static let debug = "Debug"
|
|
||||||
|
|
||||||
static let debugLogFormat = "DebugLogFormat"
|
|
||||||
|
|
||||||
static let masksPrivateData = "MasksPrivateData"
|
|
||||||
}
|
|
||||||
|
|
||||||
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.sessionConfiguration`
|
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.sessionConfiguration`
|
||||||
public let sessionConfiguration: OpenVPN.Configuration
|
public let sessionConfiguration: OpenVPN.Configuration
|
||||||
|
@ -318,8 +230,8 @@ extension OpenVPNTunnelProvider {
|
||||||
- Throws: `ProviderError.configuration` if `providerConfiguration` does not contain an app group.
|
- Throws: `ProviderError.configuration` if `providerConfiguration` does not contain an app group.
|
||||||
*/
|
*/
|
||||||
public static func appGroup(from providerConfiguration: [String: Any]) throws -> String {
|
public static func appGroup(from providerConfiguration: [String: Any]) throws -> String {
|
||||||
guard let appGroup = providerConfiguration[Keys.appGroup] as? String else {
|
guard let appGroup = providerConfiguration[ExtraKeys.appGroup] as? String else {
|
||||||
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(Keys.appGroup)]")
|
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(ExtraKeys.appGroup)]")
|
||||||
}
|
}
|
||||||
return appGroup
|
return appGroup
|
||||||
}
|
}
|
||||||
|
@ -332,8 +244,11 @@ extension OpenVPNTunnelProvider {
|
||||||
- Throws: `ProviderError.configuration` if `providerConfiguration` is incomplete.
|
- Throws: `ProviderError.configuration` if `providerConfiguration` is incomplete.
|
||||||
*/
|
*/
|
||||||
public static func parsed(from providerConfiguration: [String: Any]) throws -> Configuration {
|
public static func parsed(from providerConfiguration: [String: Any]) throws -> Configuration {
|
||||||
let builder = try ConfigurationBuilder(providerConfiguration: providerConfiguration)
|
let cfg = try fromDictionary(OpenVPNTunnelProvider.Configuration.self, providerConfiguration)
|
||||||
return builder.build()
|
guard !cfg.prefersResolvedAddresses || !(cfg.resolvedAddresses?.isEmpty ?? true) else {
|
||||||
|
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[prefersResolvedAddresses] is true but no [resolvedAddresses]")
|
||||||
|
}
|
||||||
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -343,36 +258,14 @@ extension OpenVPNTunnelProvider {
|
||||||
- Returns: The dictionary representation of `self`.
|
- Returns: The dictionary representation of `self`.
|
||||||
*/
|
*/
|
||||||
public func generatedProviderConfiguration(appGroup: String) -> [String: Any] {
|
public func generatedProviderConfiguration(appGroup: String) -> [String: Any] {
|
||||||
let S = Keys.self
|
do {
|
||||||
|
var dict = try asDictionary()
|
||||||
guard let ca = sessionConfiguration.ca else {
|
dict[ExtraKeys.appGroup] = appGroup
|
||||||
fatalError("No sessionConfiguration.ca set")
|
|
||||||
}
|
|
||||||
guard let endpointProtocols = sessionConfiguration.endpointProtocols else {
|
|
||||||
fatalError("No sessionConfiguration.endpointProtocols set")
|
|
||||||
}
|
|
||||||
|
|
||||||
var dict: [String: Any] = [
|
|
||||||
S.appGroup: appGroup,
|
|
||||||
S.prefersResolvedAddresses: prefersResolvedAddresses,
|
|
||||||
S.ca: ca.pem,
|
|
||||||
S.endpointProtocols: endpointProtocols.map { $0.rawValue },
|
|
||||||
S.debug: shouldDebug
|
|
||||||
]
|
|
||||||
sessionConfiguration.store(to: &dict)
|
|
||||||
if let resolvedAddresses = resolvedAddresses {
|
|
||||||
dict[S.resolvedAddresses] = resolvedAddresses
|
|
||||||
}
|
|
||||||
if let debugLogFormat = debugLogFormat {
|
|
||||||
dict[S.debugLogFormat] = debugLogFormat
|
|
||||||
}
|
|
||||||
if let masksPrivateData = masksPrivateData {
|
|
||||||
dict[S.masksPrivateData] = masksPrivateData
|
|
||||||
}
|
|
||||||
if let versionIdentifier = versionIdentifier {
|
|
||||||
dict[S.versionIdentifier] = versionIdentifier
|
|
||||||
}
|
|
||||||
return dict
|
return dict
|
||||||
|
} catch let e {
|
||||||
|
log.error("Unable to encode OpenVPN.Configuration: \(e)")
|
||||||
|
}
|
||||||
|
return [:]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -451,284 +344,3 @@ public extension UserDefaults {
|
||||||
removeObject(forKey: OpenVPNTunnelProvider.Configuration.dataCountKey)
|
removeObject(forKey: OpenVPNTunnelProvider.Configuration.dataCountKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: OpenVPN configuration
|
|
||||||
|
|
||||||
private extension OpenVPN.Configuration {
|
|
||||||
static func with(providerConfiguration: [String: Any]) throws -> OpenVPN.Configuration {
|
|
||||||
let S = OpenVPNTunnelProvider.Configuration.Keys.self
|
|
||||||
let E = OpenVPNTunnelProvider.ProviderConfigurationError.self
|
|
||||||
|
|
||||||
guard let caPEM = providerConfiguration[S.ca] as? String else {
|
|
||||||
throw E.parameter(name: "protocolConfiguration.providerConfiguration[\(S.ca)]")
|
|
||||||
}
|
|
||||||
guard let endpointProtocolsStrings = providerConfiguration[S.endpointProtocols] as? [String], !endpointProtocolsStrings.isEmpty else {
|
|
||||||
throw E.parameter(name: "protocolConfiguration.providerConfiguration[\(S.endpointProtocols)] is nil or empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
var builder = OpenVPNTunnelProvider.ConfigurationBuilder.defaults.sessionConfiguration.builder()
|
|
||||||
|
|
||||||
builder.ca = OpenVPN.CryptoContainer(pem: caPEM)
|
|
||||||
builder.endpointProtocols = try endpointProtocolsStrings.map {
|
|
||||||
guard let ep = EndpointProtocol(rawValue: $0) else {
|
|
||||||
throw E.parameter(name: "protocolConfiguration.providerConfiguration[\(S.endpointProtocols)] has a badly formed element")
|
|
||||||
}
|
|
||||||
return ep
|
|
||||||
}
|
|
||||||
|
|
||||||
if let cipherAlgorithm = providerConfiguration[S.cipherAlgorithm] as? String {
|
|
||||||
builder.cipher = OpenVPN.Cipher(rawValue: cipherAlgorithm)
|
|
||||||
}
|
|
||||||
if let digestAlgorithm = providerConfiguration[S.digestAlgorithm] as? String {
|
|
||||||
builder.digest = OpenVPN.Digest(rawValue: digestAlgorithm)
|
|
||||||
}
|
|
||||||
if let compressionFramingValue = providerConfiguration[S.compressionFraming] as? Int, let compressionFraming = OpenVPN.CompressionFraming(rawValue: compressionFramingValue) {
|
|
||||||
builder.compressionFraming = compressionFraming
|
|
||||||
}
|
|
||||||
if let compressionAlgorithmValue = providerConfiguration[S.compressionAlgorithm] as? Int, let compressionAlgorithm = OpenVPN.CompressionAlgorithm(rawValue: compressionAlgorithmValue) {
|
|
||||||
builder.compressionAlgorithm = compressionAlgorithm
|
|
||||||
}
|
|
||||||
if let clientPEM = providerConfiguration[S.clientCertificate] as? String {
|
|
||||||
guard let keyPEM = providerConfiguration[S.clientKey] as? String else {
|
|
||||||
throw E.parameter(name: "protocolConfiguration.providerConfiguration[\(S.clientKey)]")
|
|
||||||
}
|
|
||||||
builder.clientCertificate = OpenVPN.CryptoContainer(pem: clientPEM)
|
|
||||||
builder.clientKey = OpenVPN.CryptoContainer(pem: keyPEM)
|
|
||||||
}
|
|
||||||
if let tlsWrapData = providerConfiguration[S.tlsWrap] as? Data {
|
|
||||||
do {
|
|
||||||
builder.tlsWrap = try OpenVPN.TLSWrap.deserialized(tlsWrapData)
|
|
||||||
} catch {
|
|
||||||
throw E.parameter(name: "protocolConfiguration.providerConfiguration[\(S.tlsWrap)]")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let tlsSecurityLevel = providerConfiguration[S.tlsSecurityLevel] as? Int {
|
|
||||||
builder.tlsSecurityLevel = tlsSecurityLevel
|
|
||||||
}
|
|
||||||
if let keepAliveInterval = providerConfiguration[S.keepAlive] as? TimeInterval {
|
|
||||||
builder.keepAliveInterval = keepAliveInterval
|
|
||||||
}
|
|
||||||
if let keepAliveTimeout = providerConfiguration[S.keepAliveTimeout] as? TimeInterval {
|
|
||||||
builder.keepAliveTimeout = keepAliveTimeout
|
|
||||||
}
|
|
||||||
if let renegotiatesAfter = providerConfiguration[S.renegotiatesAfter] as? TimeInterval {
|
|
||||||
builder.renegotiatesAfter = renegotiatesAfter
|
|
||||||
}
|
|
||||||
if let checksEKU = providerConfiguration[S.checksEKU] as? Bool {
|
|
||||||
builder.checksEKU = checksEKU
|
|
||||||
}
|
|
||||||
if let checksSANHost = providerConfiguration[S.checksSANHost] as? Bool {
|
|
||||||
builder.checksSANHost = checksSANHost
|
|
||||||
}
|
|
||||||
if let sanHost = providerConfiguration[S.sanHost] as? String {
|
|
||||||
builder.sanHost = sanHost
|
|
||||||
}
|
|
||||||
if let randomizeEndpoint = providerConfiguration[S.randomizeEndpoint] as? Bool {
|
|
||||||
builder.randomizeEndpoint = randomizeEndpoint
|
|
||||||
}
|
|
||||||
if let usesPIAPatches = providerConfiguration[S.usesPIAPatches] as? Bool {
|
|
||||||
builder.usesPIAPatches = usesPIAPatches
|
|
||||||
}
|
|
||||||
if let mtu = providerConfiguration[S.mtu] as? Int {
|
|
||||||
builder.mtu = mtu
|
|
||||||
}
|
|
||||||
if let dnsServers = providerConfiguration[S.dnsServers] as? [String] {
|
|
||||||
builder.dnsServers = dnsServers
|
|
||||||
}
|
|
||||||
if let searchDomains = providerConfiguration[S.searchDomains] as? [String] {
|
|
||||||
builder.searchDomains = searchDomains
|
|
||||||
}
|
|
||||||
if let proxyString = providerConfiguration[S.httpProxy] as? String {
|
|
||||||
guard let proxy = Proxy(rawValue: proxyString) else {
|
|
||||||
throw E.parameter(name: "protocolConfiguration.providerConfiguration[\(S.httpProxy)] has a badly formed element")
|
|
||||||
}
|
|
||||||
builder.httpProxy = proxy
|
|
||||||
}
|
|
||||||
if let proxyString = providerConfiguration[S.httpsProxy] as? String {
|
|
||||||
guard let proxy = Proxy(rawValue: proxyString) else {
|
|
||||||
throw E.parameter(name: "protocolConfiguration.providerConfiguration[\(S.httpsProxy)] has a badly formed element")
|
|
||||||
}
|
|
||||||
builder.httpsProxy = proxy
|
|
||||||
}
|
|
||||||
if let proxyAutoConfigurationURLString = providerConfiguration[S.proxyAutoConfigurationURL] as? String, let proxyAutoConfigurationURL = URL(string: proxyAutoConfigurationURLString) {
|
|
||||||
builder.proxyAutoConfigurationURL = proxyAutoConfigurationURL
|
|
||||||
}
|
|
||||||
if let proxyBypassDomains = providerConfiguration[S.proxyBypassDomains] as? [String] {
|
|
||||||
builder.proxyBypassDomains = proxyBypassDomains
|
|
||||||
}
|
|
||||||
if let routingPoliciesStrings = providerConfiguration[S.routingPolicies] as? [String] {
|
|
||||||
builder.routingPolicies = try routingPoliciesStrings.map {
|
|
||||||
guard let policy = OpenVPN.RoutingPolicy(rawValue: $0) else {
|
|
||||||
throw E.parameter(name: "protocolConfiguration.providerConfiguration[\(S.routingPolicies)] has a badly formed element")
|
|
||||||
}
|
|
||||||
return policy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
func store(to dict: inout [String: Any]) {
|
|
||||||
let S = OpenVPNTunnelProvider.Configuration.Keys.self
|
|
||||||
|
|
||||||
if let cipher = cipher {
|
|
||||||
dict[S.cipherAlgorithm] = cipher.rawValue
|
|
||||||
}
|
|
||||||
if let digest = digest {
|
|
||||||
dict[S.digestAlgorithm] = digest.rawValue
|
|
||||||
}
|
|
||||||
if let compressionFraming = compressionFraming {
|
|
||||||
dict[S.compressionFraming] = compressionFraming.rawValue
|
|
||||||
}
|
|
||||||
if let compressionAlgorithm = compressionAlgorithm {
|
|
||||||
dict[S.compressionAlgorithm] = compressionAlgorithm.rawValue
|
|
||||||
}
|
|
||||||
if let clientCertificate = clientCertificate {
|
|
||||||
dict[S.clientCertificate] = clientCertificate.pem
|
|
||||||
}
|
|
||||||
if let clientKey = clientKey {
|
|
||||||
dict[S.clientKey] = clientKey.pem
|
|
||||||
}
|
|
||||||
if let tlsWrapData = tlsWrap?.serialized() {
|
|
||||||
dict[S.tlsWrap] = tlsWrapData
|
|
||||||
}
|
|
||||||
if let tlsSecurityLevel = tlsSecurityLevel {
|
|
||||||
dict[S.tlsSecurityLevel] = tlsSecurityLevel
|
|
||||||
}
|
|
||||||
if let keepAliveSeconds = keepAliveInterval {
|
|
||||||
dict[S.keepAlive] = keepAliveSeconds
|
|
||||||
}
|
|
||||||
if let keepAliveTimeoutSeconds = keepAliveTimeout {
|
|
||||||
dict[S.keepAliveTimeout] = keepAliveTimeoutSeconds
|
|
||||||
}
|
|
||||||
if let renegotiatesAfterSeconds = renegotiatesAfter {
|
|
||||||
dict[S.renegotiatesAfter] = renegotiatesAfterSeconds
|
|
||||||
}
|
|
||||||
if let checksEKU = checksEKU {
|
|
||||||
dict[S.checksEKU] = checksEKU
|
|
||||||
}
|
|
||||||
if let checksSANHost = checksSANHost {
|
|
||||||
dict[S.checksSANHost] = checksSANHost
|
|
||||||
}
|
|
||||||
if let sanHost = sanHost {
|
|
||||||
dict[S.sanHost] = sanHost
|
|
||||||
}
|
|
||||||
if let randomizeEndpoint = randomizeEndpoint {
|
|
||||||
dict[S.randomizeEndpoint] = randomizeEndpoint
|
|
||||||
}
|
|
||||||
if let usesPIAPatches = usesPIAPatches {
|
|
||||||
dict[S.usesPIAPatches] = usesPIAPatches
|
|
||||||
}
|
|
||||||
if let mtu = mtu {
|
|
||||||
dict[S.mtu] = mtu
|
|
||||||
}
|
|
||||||
if let dnsServers = dnsServers {
|
|
||||||
dict[S.dnsServers] = dnsServers
|
|
||||||
}
|
|
||||||
if let searchDomains = searchDomains {
|
|
||||||
dict[S.searchDomains] = searchDomains
|
|
||||||
}
|
|
||||||
if let httpProxy = httpProxy {
|
|
||||||
dict[S.httpProxy] = httpProxy.rawValue
|
|
||||||
}
|
|
||||||
if let httpsProxy = httpsProxy {
|
|
||||||
dict[S.httpsProxy] = httpsProxy.rawValue
|
|
||||||
}
|
|
||||||
if let proxyAutoConfigurationURL = proxyAutoConfigurationURL {
|
|
||||||
dict[S.proxyAutoConfigurationURL] = proxyAutoConfigurationURL.absoluteString
|
|
||||||
}
|
|
||||||
if let proxyBypassDomains = proxyBypassDomains {
|
|
||||||
dict[S.proxyBypassDomains] = proxyBypassDomains
|
|
||||||
}
|
|
||||||
if let routingPolicies = routingPolicies {
|
|
||||||
dict[S.routingPolicies] = routingPolicies.map { $0.rawValue }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func print() {
|
|
||||||
guard let endpointProtocols = endpointProtocols else {
|
|
||||||
fatalError("No sessionConfiguration.endpointProtocols set")
|
|
||||||
}
|
|
||||||
log.info("\tProtocols: \(endpointProtocols)")
|
|
||||||
log.info("\tCipher: \(fallbackCipher)")
|
|
||||||
log.info("\tDigest: \(fallbackDigest)")
|
|
||||||
log.info("\tCompression framing: \(fallbackCompressionFraming)")
|
|
||||||
if let compressionAlgorithm = compressionAlgorithm, compressionAlgorithm != .disabled {
|
|
||||||
log.info("\tCompression algorithm: \(compressionAlgorithm)")
|
|
||||||
} else {
|
|
||||||
log.info("\tCompression algorithm: disabled")
|
|
||||||
}
|
|
||||||
if let _ = clientCertificate {
|
|
||||||
log.info("\tClient verification: enabled")
|
|
||||||
} else {
|
|
||||||
log.info("\tClient verification: disabled")
|
|
||||||
}
|
|
||||||
if let tlsWrap = tlsWrap {
|
|
||||||
log.info("\tTLS wrapping: \(tlsWrap.strategy)")
|
|
||||||
} else {
|
|
||||||
log.info("\tTLS wrapping: disabled")
|
|
||||||
}
|
|
||||||
if let tlsSecurityLevel = tlsSecurityLevel {
|
|
||||||
log.info("\tTLS security level: \(tlsSecurityLevel)")
|
|
||||||
} else {
|
|
||||||
log.info("\tTLS security level: default")
|
|
||||||
}
|
|
||||||
if let keepAliveSeconds = keepAliveInterval, keepAliveSeconds > 0 {
|
|
||||||
log.info("\tKeep-alive interval: \(keepAliveSeconds) seconds")
|
|
||||||
} else {
|
|
||||||
log.info("\tKeep-alive interval: never")
|
|
||||||
}
|
|
||||||
if let keepAliveTimeoutSeconds = keepAliveTimeout, keepAliveTimeoutSeconds > 0 {
|
|
||||||
log.info("\tKeep-alive timeout: \(keepAliveTimeoutSeconds) seconds")
|
|
||||||
} else {
|
|
||||||
log.info("\tKeep-alive timeout: never")
|
|
||||||
}
|
|
||||||
if let renegotiatesAfterSeconds = renegotiatesAfter, renegotiatesAfterSeconds > 0 {
|
|
||||||
log.info("\tRenegotiation: \(renegotiatesAfterSeconds) seconds")
|
|
||||||
} else {
|
|
||||||
log.info("\tRenegotiation: never")
|
|
||||||
}
|
|
||||||
if checksEKU ?? false {
|
|
||||||
log.info("\tServer EKU verification: enabled")
|
|
||||||
} else {
|
|
||||||
log.info("\tServer EKU verification: disabled")
|
|
||||||
}
|
|
||||||
if checksSANHost ?? false {
|
|
||||||
log.info("\tHost SAN verification: enabled (\(sanHost ?? "-"))")
|
|
||||||
} else {
|
|
||||||
log.info("\tHost SAN verification: disabled")
|
|
||||||
}
|
|
||||||
if randomizeEndpoint ?? false {
|
|
||||||
log.info("\tRandomize endpoint: true")
|
|
||||||
}
|
|
||||||
if let routingPolicies = routingPolicies {
|
|
||||||
log.info("\tGateway: \(routingPolicies.map { $0.rawValue })")
|
|
||||||
} else {
|
|
||||||
log.info("\tGateway: not configured")
|
|
||||||
}
|
|
||||||
if let dnsServers = dnsServers, !dnsServers.isEmpty {
|
|
||||||
log.info("\tDNS: \(dnsServers.maskedDescription)")
|
|
||||||
} else {
|
|
||||||
log.info("\tDNS: not configured")
|
|
||||||
}
|
|
||||||
if let searchDomains = searchDomains, !searchDomains.isEmpty {
|
|
||||||
log.info("\tSearch domains: \(searchDomains.maskedDescription)")
|
|
||||||
}
|
|
||||||
if let httpProxy = httpProxy {
|
|
||||||
log.info("\tHTTP proxy: \(httpProxy.maskedDescription)")
|
|
||||||
}
|
|
||||||
if let httpsProxy = httpsProxy {
|
|
||||||
log.info("\tHTTPS proxy: \(httpsProxy.maskedDescription)")
|
|
||||||
}
|
|
||||||
if let proxyAutoConfigurationURL = proxyAutoConfigurationURL {
|
|
||||||
log.info("\tPAC: \(proxyAutoConfigurationURL)")
|
|
||||||
}
|
|
||||||
if let proxyBypassDomains = proxyBypassDomains {
|
|
||||||
log.info("\tProxy bypass domains: \(proxyBypassDomains.maskedDescription)")
|
|
||||||
}
|
|
||||||
if let mtu = mtu {
|
|
||||||
log.info("\tMTU: \(mtu)")
|
|
||||||
} else {
|
|
||||||
log.info("\tMTU: default")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -35,6 +35,9 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import SwiftyBeaver
|
||||||
|
|
||||||
|
private let log = SwiftyBeaver.self
|
||||||
|
|
||||||
extension OpenVPN {
|
extension OpenVPN {
|
||||||
|
|
||||||
|
@ -506,3 +509,95 @@ extension OpenVPN.Configuration {
|
||||||
return builder
|
return builder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Encoding
|
||||||
|
|
||||||
|
extension OpenVPN.Configuration {
|
||||||
|
func print() {
|
||||||
|
guard let endpointProtocols = endpointProtocols else {
|
||||||
|
fatalError("No sessionConfiguration.endpointProtocols set")
|
||||||
|
}
|
||||||
|
log.info("\tProtocols: \(endpointProtocols)")
|
||||||
|
log.info("\tCipher: \(fallbackCipher)")
|
||||||
|
log.info("\tDigest: \(fallbackDigest)")
|
||||||
|
log.info("\tCompression framing: \(fallbackCompressionFraming)")
|
||||||
|
if let compressionAlgorithm = compressionAlgorithm, compressionAlgorithm != .disabled {
|
||||||
|
log.info("\tCompression algorithm: \(compressionAlgorithm)")
|
||||||
|
} else {
|
||||||
|
log.info("\tCompression algorithm: disabled")
|
||||||
|
}
|
||||||
|
if let _ = clientCertificate {
|
||||||
|
log.info("\tClient verification: enabled")
|
||||||
|
} else {
|
||||||
|
log.info("\tClient verification: disabled")
|
||||||
|
}
|
||||||
|
if let tlsWrap = tlsWrap {
|
||||||
|
log.info("\tTLS wrapping: \(tlsWrap.strategy)")
|
||||||
|
} else {
|
||||||
|
log.info("\tTLS wrapping: disabled")
|
||||||
|
}
|
||||||
|
if let tlsSecurityLevel = tlsSecurityLevel {
|
||||||
|
log.info("\tTLS security level: \(tlsSecurityLevel)")
|
||||||
|
} else {
|
||||||
|
log.info("\tTLS security level: default")
|
||||||
|
}
|
||||||
|
if let keepAliveSeconds = keepAliveInterval, keepAliveSeconds > 0 {
|
||||||
|
log.info("\tKeep-alive interval: \(keepAliveSeconds) seconds")
|
||||||
|
} else {
|
||||||
|
log.info("\tKeep-alive interval: never")
|
||||||
|
}
|
||||||
|
if let keepAliveTimeoutSeconds = keepAliveTimeout, keepAliveTimeoutSeconds > 0 {
|
||||||
|
log.info("\tKeep-alive timeout: \(keepAliveTimeoutSeconds) seconds")
|
||||||
|
} else {
|
||||||
|
log.info("\tKeep-alive timeout: never")
|
||||||
|
}
|
||||||
|
if let renegotiatesAfterSeconds = renegotiatesAfter, renegotiatesAfterSeconds > 0 {
|
||||||
|
log.info("\tRenegotiation: \(renegotiatesAfterSeconds) seconds")
|
||||||
|
} else {
|
||||||
|
log.info("\tRenegotiation: never")
|
||||||
|
}
|
||||||
|
if checksEKU ?? false {
|
||||||
|
log.info("\tServer EKU verification: enabled")
|
||||||
|
} else {
|
||||||
|
log.info("\tServer EKU verification: disabled")
|
||||||
|
}
|
||||||
|
if checksSANHost ?? false {
|
||||||
|
log.info("\tHost SAN verification: enabled (\(sanHost ?? "-"))")
|
||||||
|
} else {
|
||||||
|
log.info("\tHost SAN verification: disabled")
|
||||||
|
}
|
||||||
|
if randomizeEndpoint ?? false {
|
||||||
|
log.info("\tRandomize endpoint: true")
|
||||||
|
}
|
||||||
|
if let routingPolicies = routingPolicies {
|
||||||
|
log.info("\tGateway: \(routingPolicies.map { $0.rawValue })")
|
||||||
|
} else {
|
||||||
|
log.info("\tGateway: not configured")
|
||||||
|
}
|
||||||
|
if let dnsServers = dnsServers, !dnsServers.isEmpty {
|
||||||
|
log.info("\tDNS: \(dnsServers.maskedDescription)")
|
||||||
|
} else {
|
||||||
|
log.info("\tDNS: not configured")
|
||||||
|
}
|
||||||
|
if let searchDomains = searchDomains, !searchDomains.isEmpty {
|
||||||
|
log.info("\tSearch domains: \(searchDomains.maskedDescription)")
|
||||||
|
}
|
||||||
|
if let httpProxy = httpProxy {
|
||||||
|
log.info("\tHTTP proxy: \(httpProxy.maskedDescription)")
|
||||||
|
}
|
||||||
|
if let httpsProxy = httpsProxy {
|
||||||
|
log.info("\tHTTPS proxy: \(httpsProxy.maskedDescription)")
|
||||||
|
}
|
||||||
|
if let proxyAutoConfigurationURL = proxyAutoConfigurationURL {
|
||||||
|
log.info("\tPAC: \(proxyAutoConfigurationURL)")
|
||||||
|
}
|
||||||
|
if let proxyBypassDomains = proxyBypassDomains {
|
||||||
|
log.info("\tProxy bypass domains: \(proxyBypassDomains.maskedDescription)")
|
||||||
|
}
|
||||||
|
if let mtu = mtu {
|
||||||
|
log.info("\tMTU: \(mtu)")
|
||||||
|
} else {
|
||||||
|
log.info("\tMTU: default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.1.0</string>
|
<string>3.2.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>BNDL</string>
|
<string>BNDL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.1.0</string>
|
<string>3.2.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>BNDL</string>
|
<string>BNDL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>3.1.0</string>
|
<string>3.2.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|
|
@ -79,18 +79,19 @@ class AppExtensionTests: XCTestCase {
|
||||||
XCTAssertEqual(proto?.username, credentials.username)
|
XCTAssertEqual(proto?.username, credentials.username)
|
||||||
XCTAssertEqual(proto?.passwordReference, try? Keychain(group: appGroup).passwordReference(for: credentials.username))
|
XCTAssertEqual(proto?.passwordReference, try? Keychain(group: appGroup).passwordReference(for: credentials.username))
|
||||||
|
|
||||||
if let pc = proto?.providerConfiguration {
|
guard let pc = proto?.providerConfiguration else {
|
||||||
print("\(pc)")
|
return
|
||||||
}
|
}
|
||||||
|
print("\(pc)")
|
||||||
|
|
||||||
let K = OpenVPNTunnelProvider.Configuration.Keys.self
|
let pcSession = pc["sessionConfiguration"] as? [String: Any]
|
||||||
XCTAssertEqual(proto?.providerConfiguration?[K.appGroup] as? String, appGroup)
|
XCTAssertEqual(pc["appGroup"] as? String, appGroup)
|
||||||
XCTAssertEqual(proto?.providerConfiguration?[K.cipherAlgorithm] as? String, cfg.sessionConfiguration.cipher?.rawValue)
|
XCTAssertEqual(pc["shouldDebug"] as? Bool, cfg.shouldDebug)
|
||||||
XCTAssertEqual(proto?.providerConfiguration?[K.digestAlgorithm] as? String, cfg.sessionConfiguration.digest?.rawValue)
|
XCTAssertEqual(pcSession?["cipher"] as? String, cfg.sessionConfiguration.cipher?.rawValue)
|
||||||
XCTAssertEqual(proto?.providerConfiguration?[K.ca] as? String, cfg.sessionConfiguration.ca?.pem)
|
XCTAssertEqual(pcSession?["digest"] as? String, cfg.sessionConfiguration.digest?.rawValue)
|
||||||
XCTAssertEqual(proto?.providerConfiguration?[K.mtu] as? Int, cfg.sessionConfiguration.mtu)
|
XCTAssertEqual(pcSession?["ca"] as? String, cfg.sessionConfiguration.ca?.pem)
|
||||||
XCTAssertEqual(proto?.providerConfiguration?[K.renegotiatesAfter] as? TimeInterval, cfg.sessionConfiguration.renegotiatesAfter)
|
XCTAssertEqual(pcSession?["mtu"] as? Int, cfg.sessionConfiguration.mtu)
|
||||||
XCTAssertEqual(proto?.providerConfiguration?[K.debug] as? Bool, cfg.shouldDebug)
|
XCTAssertEqual(pcSession?["renegotiatesAfter"] as? TimeInterval, cfg.sessionConfiguration.renegotiatesAfter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDNSResolver() {
|
func testDNSResolver() {
|
||||||
|
|
Loading…
Reference in New Issue