2018-08-23 08:19:25 +00:00
//
2018-08-23 10:07:55 +00:00
// T u n n e l K i t P r o v i d e r + C o n f i g u r a t i o n . s w i f t
// T u n n e l K i t
2018-08-23 08:19:25 +00:00
//
// C r e a t e d b y D a v i d e D e R o s a o n 1 0 / 2 3 / 1 7 .
// C o p y r i g h t © 2 0 1 8 L o n d o n T r u s t M e d i a . A l l r i g h t s r e s e r v e d .
//
import Foundation
import NetworkExtension
import SwiftyBeaver
private let log = SwiftyBeaver . self
2018-08-23 10:07:55 +00:00
extension TunnelKitProvider {
2018-08-23 08:19:25 +00:00
// MARK: C r y p t o g r a p h y
// / T h e a v a i l a b l e e n c r y p t i o n a l g o r i t h m s .
public enum Cipher : String {
// W A R N I N G : m u s t m a t c h O p e n S S L a l g o r i t h m n a m e s
// / A E S e n c r y p t i o n w i t h 1 2 8 - b i t k e y s i z e a n d C B C .
case aes128cbc = " AES-128-CBC "
// / A E S e n c r y p t i o n w i t h 2 5 6 - b i t k e y s i z e a n d C B C .
case aes256cbc = " AES-256-CBC "
// / A E S e n c r y p t i o n w i t h 1 2 8 - b i t k e y s i z e a n d G C M .
case aes128gcm = " AES-128-GCM "
// / A E S e n c r y p t i o n w i t h 2 5 6 - b i t k e y s i z e a n d G C M .
case aes256gcm = " AES-256-GCM "
}
// / T h e a v a i l a b l e m e s s a g e d i g e s t a l g o r i t h m s .
public enum Digest : String {
// W A R N I N G : m u s t m a t c h O p e n S S L a l g o r i t h m n a m e s
// / S H A 1 m e s s a g e d i g e s t .
case sha1 = " SHA1 "
// / S H A 2 5 6 m e s s a g e d i g e s t .
case sha256 = " SHA256 "
}
// / T h e a v a i l a b l e c e r t i f i c a t e s f o r h a n d s h a k e .
public enum Handshake : String {
// / C e r t i f i c a t e w i t h R S A 2 0 4 8 - b i t k e y .
case rsa2048 = " RSA-2048 "
// / C e r t i f i c a t e w i t h R S A 3 0 7 2 - b i t k e y .
case rsa3072 = " RSA-3072 "
// / C e r t i f i c a t e w i t h R S A 4 0 9 6 - b i t k e y .
case rsa4096 = " RSA-4096 "
// / C e r t i f i c a t e w i t h E C C b a s e d o n s e c p 2 5 6 r 1 c u r v e .
case ecc256r1 = " ECC-256r1 "
// / C e r t i f i c a t e w i t h E C C b a s e d o n s e c p 2 5 6 k 1 c u r v e .
case ecc256k1 = " ECC-256k1 "
// / C e r t i f i c a t e w i t h E C C b a s e d o n s e c p 5 2 1 r 1 c u r v e .
case ecc521r1 = " ECC-521r1 "
// / C u s t o m c e r t i f i c a t e .
// /
// / - S e e a l s o :
case custom = " Custom "
private static let allDigests : [ Handshake : String ] = [
. rsa2048 : " e2fccccaba712ccc68449b1c56427ac1 " ,
. rsa3072 : " 2fcdb65712df9db7dae34a1f4a84e32d " ,
. rsa4096 : " ec085790314aa0ad4b01dda7b756a932 " ,
. ecc256r1 : " 6f0f23a616479329ce54614f76b52254 " ,
. ecc256k1 : " 80c3b0f34001e4101e34fde9eb1dfa87 " ,
. ecc521r1 : " 82446e0c80706e33e6e793cebf1b0c59 "
]
var digest : String ? {
return Handshake . allDigests [ self ]
}
func write ( to url : URL , custom : String ? = nil ) throws {
precondition ( ( self != . custom ) || ( custom != nil ) )
// c u s t o m c e r t i f i c a t e ?
if self = = . custom , let content = custom {
try content . write ( to : url , atomically : true , encoding : . ascii )
return
}
2018-08-23 10:07:55 +00:00
let bundle = Bundle ( for : TunnelKitProvider . self )
2018-08-23 08:19:25 +00:00
let certName = " PIA- \( rawValue ) "
guard let certUrl = bundle . url ( forResource : certName , withExtension : " pem " ) else {
fatalError ( " Could not find \( certName ) TLS certificate " )
}
let content = try String ( contentsOf : certUrl )
try content . write ( to : url , atomically : true , encoding : . ascii )
}
}
}
2018-08-23 10:07:55 +00:00
extension TunnelKitProvider {
2018-08-23 08:19:25 +00:00
// MARK: C o n f i g u r a t i o n
// / A s o c k e t t y p e b e t w e e n U D P ( r e c o m m e n d e d ) a n d T C P .
public enum SocketType : String {
// / U D P s o c k e t t y p e .
case udp = " UDP "
// / T C P s o c k e t t y p e .
case tcp = " TCP "
}
// / D e f i n e s t h e c o m m u n i c a t i o n p r o t o c o l o f a n e n d p o i n t .
public struct EndpointProtocol : Equatable , CustomStringConvertible {
// / T h e s o c k e t t y p e .
public let socketType : SocketType
// / T h e r e m o t e p o r t .
public let port : UInt16
// / : n o d o c :
2018-08-23 09:11:15 +00:00
public init ( _ socketType : SocketType , _ port : UInt16 ) {
2018-08-23 08:19:25 +00:00
self . socketType = socketType
self . port = port
}
// MARK: E q u a t a b l e
// / : n o d o c :
public static func = = ( lhs : EndpointProtocol , rhs : EndpointProtocol ) -> Bool {
2018-08-23 09:11:15 +00:00
return ( lhs . socketType = = rhs . socketType ) && ( lhs . port = = rhs . port )
2018-08-23 08:19:25 +00:00
}
// MARK: C u s t o m S t r i n g C o n v e r t i b l e
// / : n o d o c :
public var description : String {
return " \( socketType . rawValue ) : \( port ) "
}
}
// / E n c a p s u l a t e s a n e n d p o i n t a l o n g w i t h t h e a u t h e n t i c a t i o n c r e d e n t i a l s .
public struct AuthenticatedEndpoint {
// / T h e r e m o t e h o s t n a m e o r I P a d d r e s s .
public let hostname : String
// / T h e u s e r n a m e .
public let username : String
// / T h e p a s s w o r d .
public let password : String
// / : n o d o c :
public init ( hostname : String , username : String , password : String ) {
self . hostname = hostname
self . username = username
self . password = password
}
init ( protocolConfiguration : NEVPNProtocol ) throws {
guard let hostname = protocolConfiguration . serverAddress else {
throw ProviderError . configuration ( field : " protocolConfiguration.serverAddress " )
}
guard let username = protocolConfiguration . username else {
throw ProviderError . credentials ( field : " protocolConfiguration.username " )
}
guard let passwordReference = protocolConfiguration . passwordReference else {
throw ProviderError . credentials ( field : " protocolConfiguration.passwordReference " )
}
guard let password = try ? Keychain . password ( for : username , reference : passwordReference ) else {
throw ProviderError . credentials ( field : " protocolConfiguration.passwordReference (keychain) " )
}
self . hostname = hostname
self . username = username
self . password = password
}
}
2018-08-23 10:07:55 +00:00
// / T h e w a y t o c r e a t e a ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n ` o b j e c t f o r t h e t u n n e l p r o f i l e .
2018-08-23 08:19:25 +00:00
public struct ConfigurationBuilder {
// MARK: A p p g r o u p
// / T h e n a m e o f a s h a r e d a p p g r o u p .
public let appGroup : String
// MARK: T u n n e l p a r a m e t e r s
// / P r e f e r s r e s o l v e d a d d r e s s e s o v e r D N S r e s o l u t i o n . ` r e s o l v e d A d d r e s s e s ` m u s t b e s e t a n d n o n - e m p t y . D e f a u l t i s ` f a l s e ` .
// /
// / - S e e a l s o : ` f a l l b a c k S e r v e r A d d r e s s e s `
public var prefersResolvedAddresses : Bool
// / R e s o l v e d a d d r e s s e s i n c a s e D N S f a i l s o r ` p r e f e r s R e s o l v e d A d d r e s s e s ` i s ` t r u e ` .
public var resolvedAddresses : [ String ] ?
// / T h e a c c e p t e d c o m m u n i c a t i o n p r o t o c o l s . M u s t b e n o n - e m p t y .
public var endpointProtocols : [ EndpointProtocol ]
// / T h e e n c r y p t i o n a l g o r i t h m .
public var cipher : Cipher
// / T h e m e s s a g e d i g e s t a l g o r i t h m .
public var digest : Digest
// / T h e h a n d s h a k e c e r t i f i c a t e .
public var handshake : Handshake
// / T h e c u s t o m C A c e r t i f i c a t e i n P E M f o r m a t i n c a s e ` h a n d s h a k e = = . c u s t o m ` . I g n o r e d o t h e r w i s e .
public var ca : String ?
// / T h e M T U o f t h e t u n n e l .
public var mtu : NSNumber
// / T h e n u m b e r o f s e c o n d s a f t e r w h i c h a r e n e g o t i a t i o n i s s t a r t e d . S e t t o ` n i l ` t o d i s a b l e r e n e g o t i a t i o n .
public var renegotiatesAfterSeconds : Int ?
// MARK: D e b u g g i n g
// / E n a b l e s d e b u g g i n g . I f ` t r u e ` , t h e n ` d e b u g L o g K e y ` i s a m a n d a t o r y f i e l d .
public var shouldDebug : Bool
// / T h e k e y i n ` d e f a u l t s ` w h e r e t h e l a t e s t d e b u g l o g s n a p s h o t i s s t o r e d . I g n o r e d i f ` s h o u l d D e b u g ` i s ` f a l s e ` .
public var debugLogKey : String ?
// / O p t i o n a l d e b u g l o g f o r m a t ( S w i f t y B e a v e r f o r m a t ) .
public var debugLogFormat : String ?
// MARK: B u i l d i n g
/* *
Default initializer .
- Parameter appGroup : The name of the app group in which the tunnel extension lives in .
*/
public init ( appGroup : String ) {
self . appGroup = appGroup
prefersResolvedAddresses = false
resolvedAddresses = nil
2018-08-23 09:11:15 +00:00
endpointProtocols = [ EndpointProtocol ( . udp , 1194 ) ]
2018-08-23 08:19:25 +00:00
cipher = . aes128cbc
digest = . sha1
handshake = . rsa2048
ca = nil
mtu = 1500
renegotiatesAfterSeconds = nil
shouldDebug = false
debugLogKey = nil
debugLogFormat = nil
}
fileprivate init ( providerConfiguration : [ String : Any ] ) throws {
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 = Cipher ( rawValue : cipherAlgorithm ) else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . cipherAlgorithm ) ] " )
}
guard let digestAlgorithm = providerConfiguration [ S . digestAlgorithm ] as ? String , let digest = Digest ( rawValue : digestAlgorithm ) else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . digestAlgorithm ) ] " )
}
// f a l l b a c k t o . r s a 2 0 4 8 i n < 0 . 7 c o n f i g u r a t i o n s ( c a / c a D i g e s t )
let fallbackHandshake : Handshake = . rsa2048
var handshake : Handshake = fallbackHandshake
if let handshakeCertificate = providerConfiguration [ S . handshakeCertificate ] as ? String {
handshake = Handshake ( rawValue : handshakeCertificate ) ? ? fallbackHandshake
}
if handshake = = . custom {
guard let ca = providerConfiguration [ S . ca ] as ? String else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . ca ) ] " )
}
self . ca = ca
}
self . appGroup = appGroup
prefersResolvedAddresses = providerConfiguration [ S . prefersResolvedAddresses ] as ? Bool ? ? false
resolvedAddresses = providerConfiguration [ S . resolvedAddresses ] as ? [ String ]
guard let endpointProtocolsStrings = providerConfiguration [ S . endpointProtocols ] as ? [ String ] , ! endpointProtocolsStrings . isEmpty else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . endpointProtocols ) ] is nil or empty " )
}
endpointProtocols = try endpointProtocolsStrings . map {
let components = $0 . components ( separatedBy : " : " )
2018-08-23 09:11:15 +00:00
guard components . count = = 2 else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . endpointProtocols ) ] entries must be in the form 'socketType:port' " )
2018-08-23 08:19:25 +00:00
}
let socketTypeString = components [ 0 ]
let portString = components [ 1 ]
guard let socketType = SocketType ( rawValue : socketTypeString ) else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . endpointProtocols ) ] unrecognized socketType ' \( socketTypeString ) ' " )
}
guard let port = UInt16 ( portString ) else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . endpointProtocols ) ] non-numeric port ' \( portString ) ' " )
}
2018-08-23 09:11:15 +00:00
return EndpointProtocol ( socketType , port )
2018-08-23 08:19:25 +00:00
}
self . cipher = cipher
self . digest = digest
self . handshake = handshake
mtu = providerConfiguration [ S . mtu ] as ? NSNumber ? ? 1500
renegotiatesAfterSeconds = providerConfiguration [ S . renegotiatesAfter ] as ? Int
shouldDebug = providerConfiguration [ S . debug ] as ? Bool ? ? false
if shouldDebug {
guard let debugLogKey = providerConfiguration [ S . debugLogKey ] as ? String else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . debugLogKey ) ] " )
}
self . debugLogKey = debugLogKey
debugLogFormat = providerConfiguration [ S . debugLogFormat ] as ? String
} else {
debugLogKey = nil
}
guard ! prefersResolvedAddresses || ! ( resolvedAddresses ? . isEmpty ? ? true ) else {
throw ProviderError . configuration ( field : " protocolConfiguration.providerConfiguration[ \( S . prefersResolvedAddresses ) ] is true but no [ \( S . resolvedAddresses ) ] " )
}
}
/* *
2018-08-23 10:07:55 +00:00
Builds a ` TunnelKitProvider . Configuration ` object that will connect to the provided endpoint .
2018-08-23 08:19:25 +00:00
2018-08-23 10:07:55 +00:00
- Returns : A ` TunnelKitProvider . Configuration ` object with this builder and the additional method parameters .
2018-08-23 08:19:25 +00:00
*/
public func build ( ) -> Configuration {
return Configuration (
appGroup : appGroup ,
prefersResolvedAddresses : prefersResolvedAddresses ,
resolvedAddresses : resolvedAddresses ,
endpointProtocols : endpointProtocols ,
cipher : cipher ,
digest : digest ,
handshake : handshake ,
ca : ca ,
mtu : mtu ,
renegotiatesAfterSeconds : renegotiatesAfterSeconds ,
shouldDebug : shouldDebug ,
debugLogKey : shouldDebug ? debugLogKey : nil ,
debugLogFormat : shouldDebug ? debugLogFormat : nil
)
}
}
2018-08-23 10:07:55 +00:00
// / O f f e r s a b r i d g e b e t w e e n t h e a b s t r a c t ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r ` a n d a c o n c r e t e ` N E T u n n e l P r o v i d e r P r o t o c o l ` p r o f i l e .
2018-08-23 08:19:25 +00:00
public struct Configuration {
struct Keys {
static let appGroup = " AppGroup "
static let prefersResolvedAddresses = " PrefersResolvedAddresses "
static let resolvedAddresses = " ResolvedAddresses "
static let endpointProtocols = " EndpointProtocols "
static let cipherAlgorithm = " CipherAlgorithm "
static let digestAlgorithm = " DigestAlgorithm "
static let handshakeCertificate = " HandshakeCertificate "
static let ca = " CA "
static let mtu = " MTU "
static let renegotiatesAfter = " RenegotiatesAfter "
static let debug = " Debug "
static let debugLogKey = " DebugLogKey "
static let debugLogFormat = " DebugLogFormat "
}
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . a p p G r o u p `
2018-08-23 08:19:25 +00:00
public let appGroup : String
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . p r e f e r s R e s o l v e d A d d r e s s e s `
2018-08-23 08:19:25 +00:00
public let prefersResolvedAddresses : Bool
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . r e s o l v e d A d d r e s s e s `
2018-08-23 08:19:25 +00:00
public let resolvedAddresses : [ String ] ?
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . e n d p o i n t P r o t o c o l s `
2018-08-23 08:19:25 +00:00
public let endpointProtocols : [ EndpointProtocol ]
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . c i p h e r `
2018-08-23 08:19:25 +00:00
public let cipher : Cipher
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . d i g e s t `
2018-08-23 08:19:25 +00:00
public let digest : Digest
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . h a n d s h a k e `
2018-08-23 08:19:25 +00:00
public let handshake : Handshake
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . c a `
2018-08-23 08:19:25 +00:00
public let ca : String ?
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . m t u `
2018-08-23 08:19:25 +00:00
public let mtu : NSNumber
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . r e n e g o t i a t e s A f t e r S e c o n d s `
2018-08-23 08:19:25 +00:00
public let renegotiatesAfterSeconds : Int ?
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . s h o u l d D e b u g `
2018-08-23 08:19:25 +00:00
public let shouldDebug : Bool
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . d e b u g L o g K e y `
2018-08-23 08:19:25 +00:00
public let debugLogKey : String ?
2018-08-23 10:07:55 +00:00
// / - S e e a l s o : ` T u n n e l K i t P r o v i d e r . C o n f i g u r a t i o n B u i l d e r . d e b u g L o g F o r m a t `
2018-08-23 08:19:25 +00:00
public let debugLogFormat : String ?
// MARK: S h o r t c u t s
var defaults : UserDefaults ? {
return UserDefaults ( suiteName : appGroup )
}
var existingLog : [ String ] ? {
guard shouldDebug , let key = debugLogKey else {
return nil
}
return defaults ? . array ( forKey : key ) as ? [ String ]
}
// MARK: A P I
/* *
2018-08-23 10:07:55 +00:00
Parses a new ` TunnelKitProvider . Configuration ` object from a provider configuration map .
2018-08-23 08:19:25 +00:00
- Parameter from : The map to parse .
2018-08-23 10:07:55 +00:00
- Returns : The parsed ` TunnelKitProvider . Configuration ` object .
2018-08-23 08:19:25 +00:00
- Throws : ` ProviderError . configuration ` if ` providerConfiguration ` is incomplete .
*/
public static func parsed ( from providerConfiguration : [ String : Any ] ) throws -> Configuration {
let builder = try ConfigurationBuilder ( providerConfiguration : providerConfiguration )
return builder . build ( )
}
/* *
Returns a dictionary representation of this configuration for use with ` NETunnelProviderProtocol . providerConfiguration ` .
- Returns : The dictionary representation of ` self ` .
*/
public func generatedProviderConfiguration ( ) -> [ String : Any ] {
let S = Keys . self
var dict : [ String : Any ] = [
S . appGroup : appGroup ,
S . prefersResolvedAddresses : prefersResolvedAddresses ,
S . endpointProtocols : endpointProtocols . map {
2018-08-23 09:11:15 +00:00
" \( $0 . socketType . rawValue ) : \( $0 . port ) "
2018-08-23 08:19:25 +00:00
} ,
S . cipherAlgorithm : cipher . rawValue ,
S . digestAlgorithm : digest . rawValue ,
S . handshakeCertificate : handshake . rawValue ,
S . mtu : mtu ,
S . debug : shouldDebug
]
if let ca = ca {
dict [ S . ca ] = ca
}
if let resolvedAddresses = resolvedAddresses {
dict [ S . resolvedAddresses ] = resolvedAddresses
}
if let renegotiatesAfterSeconds = renegotiatesAfterSeconds {
dict [ S . renegotiatesAfter ] = renegotiatesAfterSeconds
}
if let debugLogKey = debugLogKey {
dict [ S . debugLogKey ] = debugLogKey
}
if let debugLogFormat = debugLogFormat {
dict [ S . debugLogFormat ] = debugLogFormat
}
return dict
}
/* *
Generates a ` NETunnelProviderProtocol ` from this configuration .
- Parameter bundleIdentifier : The provider bundle identifier required to locate the tunnel extension .
2018-08-23 10:07:55 +00:00
- Parameter endpoint : The ` TunnelKitProvider . AuthenticatedEndpoint ` the tunnel will connect to .
2018-08-23 08:19:25 +00:00
- Returns : The generated ` NETunnelProviderProtocol ` object .
- Throws : ` ProviderError . configuration ` if unable to store the ` endpoint . password ` to the ` appGroup ` keychain .
*/
public func generatedTunnelProtocol ( withBundleIdentifier bundleIdentifier : String , endpoint : AuthenticatedEndpoint ) throws -> NETunnelProviderProtocol {
let protocolConfiguration = NETunnelProviderProtocol ( )
let keychain = Keychain ( group : appGroup )
do {
try keychain . set ( password : endpoint . password , for : endpoint . username , label : Bundle . main . bundleIdentifier )
} catch _ {
throw ProviderError . credentials ( field : " keychain.set() " )
}
protocolConfiguration . providerBundleIdentifier = bundleIdentifier
protocolConfiguration . serverAddress = endpoint . hostname
protocolConfiguration . username = endpoint . username
protocolConfiguration . passwordReference = try ? keychain . passwordReference ( for : endpoint . username )
protocolConfiguration . providerConfiguration = generatedProviderConfiguration ( )
return protocolConfiguration
}
func print ( appVersion : String ? ) {
if let appVersion = appVersion {
log . info ( " App version: \( appVersion ) " )
}
// l o g . i n f o ( " A d d r e s s : \ ( e n d p o i n t . h o s t n a m e ) : \ ( e n d p o i n t . p o r t ) " )
log . info ( " Protocols: \( endpointProtocols ) " )
log . info ( " Cipher: \( cipher . rawValue ) " )
log . info ( " Digest: \( digest . rawValue ) " )
log . info ( " Handshake: \( handshake . rawValue ) " )
log . info ( " MTU: \( mtu ) " )
if let renegotiatesAfterSeconds = renegotiatesAfterSeconds {
log . info ( " Renegotiation: \( renegotiatesAfterSeconds ) seconds " )
} else {
log . info ( " Renegotiation: never " )
}
log . info ( " Debug: \( shouldDebug ) " )
}
}
}
// MARK: M o d i f i c a t i o n
2018-08-23 10:07:55 +00:00
extension TunnelKitProvider . Configuration : Equatable {
2018-08-23 08:19:25 +00:00
/* *
2018-08-23 10:07:55 +00:00
Returns a ` TunnelKitProvider . ConfigurationBuilder ` to use this configuration as a starting point for a new one .
2018-08-23 08:19:25 +00:00
2018-08-23 10:07:55 +00:00
- Returns : An editable ` TunnelKitProvider . ConfigurationBuilder ` initialized with this configuration .
2018-08-23 08:19:25 +00:00
*/
2018-08-23 10:07:55 +00:00
public func builder ( ) -> TunnelKitProvider . ConfigurationBuilder {
var builder = TunnelKitProvider . ConfigurationBuilder ( appGroup : appGroup )
2018-08-23 08:19:25 +00:00
builder . endpointProtocols = endpointProtocols
builder . cipher = cipher
builder . digest = digest
builder . handshake = handshake
builder . mtu = mtu
builder . renegotiatesAfterSeconds = renegotiatesAfterSeconds
builder . shouldDebug = shouldDebug
builder . debugLogKey = debugLogKey
return builder
}
// / : n o d o c :
2018-08-23 10:07:55 +00:00
public static func = = ( lhs : TunnelKitProvider . Configuration , rhs : TunnelKitProvider . Configuration ) -> Bool {
2018-08-23 08:19:25 +00:00
return (
( lhs . endpointProtocols = = rhs . endpointProtocols ) &&
( lhs . cipher = = rhs . cipher ) &&
( lhs . digest = = rhs . digest ) &&
( lhs . handshake = = rhs . handshake ) &&
( lhs . mtu = = rhs . mtu ) &&
( lhs . renegotiatesAfterSeconds = = rhs . renegotiatesAfterSeconds )
)
}
}