Wrap SessionProxy configuration in a builder
This commit is contained in:
parent
a6510cc15c
commit
8a9e99e6a9
|
@ -19,6 +19,10 @@
|
||||||
0E07597F20F0060E00F38FD8 /* CryptoAEAD.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07597C20F0060E00F38FD8 /* CryptoAEAD.h */; };
|
0E07597F20F0060E00F38FD8 /* CryptoAEAD.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E07597C20F0060E00F38FD8 /* CryptoAEAD.h */; };
|
||||||
0E07598020F0060E00F38FD8 /* CryptoAEAD.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E07597D20F0060E00F38FD8 /* CryptoAEAD.m */; };
|
0E07598020F0060E00F38FD8 /* CryptoAEAD.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E07597D20F0060E00F38FD8 /* CryptoAEAD.m */; };
|
||||||
0E07598120F0060E00F38FD8 /* CryptoAEAD.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E07597D20F0060E00F38FD8 /* CryptoAEAD.m */; };
|
0E07598120F0060E00F38FD8 /* CryptoAEAD.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E07597D20F0060E00F38FD8 /* CryptoAEAD.m */; };
|
||||||
|
0E0C2125212ED29D008AB282 /* SessionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0C2123212ED29D008AB282 /* SessionError.swift */; };
|
||||||
|
0E0C2126212ED29D008AB282 /* SessionError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0C2123212ED29D008AB282 /* SessionError.swift */; };
|
||||||
|
0E0C2127212ED29D008AB282 /* SessionProxy+Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0C2124212ED29D008AB282 /* SessionProxy+Configuration.swift */; };
|
||||||
|
0E0C2128212ED29D008AB282 /* SessionProxy+Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0C2124212ED29D008AB282 /* SessionProxy+Configuration.swift */; };
|
||||||
0E11089F1F77B9E800A92462 /* TunnelKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E17D7F91F730D9F009EE129 /* TunnelKit.framework */; };
|
0E11089F1F77B9E800A92462 /* TunnelKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E17D7F91F730D9F009EE129 /* TunnelKit.framework */; };
|
||||||
0E1108AC1F77B9F900A92462 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1108AB1F77B9F900A92462 /* AppDelegate.swift */; };
|
0E1108AC1F77B9F900A92462 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1108AB1F77B9F900A92462 /* AppDelegate.swift */; };
|
||||||
0E1108AE1F77B9F900A92462 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1108AD1F77B9F900A92462 /* ViewController.swift */; };
|
0E1108AE1F77B9F900A92462 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1108AD1F77B9F900A92462 /* ViewController.swift */; };
|
||||||
|
@ -180,6 +184,8 @@
|
||||||
0E07596D20EF79B400F38FD8 /* CryptoCBC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoCBC.h; sourceTree = "<group>"; };
|
0E07596D20EF79B400F38FD8 /* CryptoCBC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoCBC.h; sourceTree = "<group>"; };
|
||||||
0E07597C20F0060E00F38FD8 /* CryptoAEAD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAEAD.h; sourceTree = "<group>"; };
|
0E07597C20F0060E00F38FD8 /* CryptoAEAD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAEAD.h; sourceTree = "<group>"; };
|
||||||
0E07597D20F0060E00F38FD8 /* CryptoAEAD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoAEAD.m; sourceTree = "<group>"; };
|
0E07597D20F0060E00F38FD8 /* CryptoAEAD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoAEAD.m; sourceTree = "<group>"; };
|
||||||
|
0E0C2123212ED29D008AB282 /* SessionError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionError.swift; sourceTree = "<group>"; };
|
||||||
|
0E0C2124212ED29D008AB282 /* SessionProxy+Configuration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SessionProxy+Configuration.swift"; sourceTree = "<group>"; };
|
||||||
0E11089A1F77B9E800A92462 /* TunnelKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TunnelKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
0E11089A1F77B9E800A92462 /* TunnelKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TunnelKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
0E11089E1F77B9E800A92462 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
0E11089E1F77B9E800A92462 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
0E1108A91F77B9F900A92462 /* TunnelKitHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TunnelKitHost.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
0E1108A91F77B9F900A92462 /* TunnelKitHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TunnelKitHost.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
@ -446,8 +452,10 @@
|
||||||
0EFEB4392006D3C800F81029 /* ReplayProtector.h */,
|
0EFEB4392006D3C800F81029 /* ReplayProtector.h */,
|
||||||
0EFEB4482006D3C800F81029 /* ReplayProtector.m */,
|
0EFEB4482006D3C800F81029 /* ReplayProtector.m */,
|
||||||
0EFEB4372006D3C800F81029 /* SecureRandom.swift */,
|
0EFEB4372006D3C800F81029 /* SecureRandom.swift */,
|
||||||
|
0E0C2123212ED29D008AB282 /* SessionError.swift */,
|
||||||
0EFEB42B2006D3C800F81029 /* SessionKey.swift */,
|
0EFEB42B2006D3C800F81029 /* SessionKey.swift */,
|
||||||
0EFEB43C2006D3C800F81029 /* SessionProxy.swift */,
|
0EFEB43C2006D3C800F81029 /* SessionProxy.swift */,
|
||||||
|
0E0C2124212ED29D008AB282 /* SessionProxy+Configuration.swift */,
|
||||||
0EFEB4442006D3C800F81029 /* TLSBox.h */,
|
0EFEB4442006D3C800F81029 /* TLSBox.h */,
|
||||||
0EFEB4302006D3C800F81029 /* TLSBox.m */,
|
0EFEB4302006D3C800F81029 /* TLSBox.m */,
|
||||||
0EFEB42F2006D3C800F81029 /* TunnelInterface.swift */,
|
0EFEB42F2006D3C800F81029 /* TunnelInterface.swift */,
|
||||||
|
@ -885,6 +893,7 @@
|
||||||
0EE7A79520F61EDC00B42E6A /* PacketMacros.h in Sources */,
|
0EE7A79520F61EDC00B42E6A /* PacketMacros.h in Sources */,
|
||||||
0EFEB45D2006D3C800F81029 /* CryptoBox.m in Sources */,
|
0EFEB45D2006D3C800F81029 /* CryptoBox.m in Sources */,
|
||||||
0EBBF2FA2085061600E36B40 /* NETCPInterface.swift in Sources */,
|
0EBBF2FA2085061600E36B40 /* NETCPInterface.swift in Sources */,
|
||||||
|
0E0C2125212ED29D008AB282 /* SessionError.swift in Sources */,
|
||||||
0EFEB4552006D3C800F81029 /* EncryptionProxy.swift in Sources */,
|
0EFEB4552006D3C800F81029 /* EncryptionProxy.swift in Sources */,
|
||||||
0EFEB45C2006D3C800F81029 /* ZeroingData.m in Sources */,
|
0EFEB45C2006D3C800F81029 /* ZeroingData.m in Sources */,
|
||||||
0EFEB4632006D3C800F81029 /* ProtocolMacros.swift in Sources */,
|
0EFEB4632006D3C800F81029 /* ProtocolMacros.swift in Sources */,
|
||||||
|
@ -910,6 +919,7 @@
|
||||||
0EFEB4752006D3C800F81029 /* Errors.m in Sources */,
|
0EFEB4752006D3C800F81029 /* Errors.m in Sources */,
|
||||||
0EBBF2E52084FE6F00E36B40 /* GenericSocket.swift in Sources */,
|
0EBBF2E52084FE6F00E36B40 /* GenericSocket.swift in Sources */,
|
||||||
0EFEB4762006D3C800F81029 /* DataPath.m in Sources */,
|
0EFEB4762006D3C800F81029 /* DataPath.m in Sources */,
|
||||||
|
0E0C2127212ED29D008AB282 /* SessionProxy+Configuration.swift in Sources */,
|
||||||
0EFEB4692006D3C800F81029 /* Packet.swift in Sources */,
|
0EFEB4692006D3C800F81029 /* Packet.swift in Sources */,
|
||||||
0EFEB45A2006D3C800F81029 /* TunnelInterface.swift in Sources */,
|
0EFEB45A2006D3C800F81029 /* TunnelInterface.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
@ -934,6 +944,7 @@
|
||||||
0EFEB4962006D7F300F81029 /* ProtocolMacros.swift in Sources */,
|
0EFEB4962006D7F300F81029 /* ProtocolMacros.swift in Sources */,
|
||||||
0EE7A79620F61EDC00B42E6A /* PacketMacros.h in Sources */,
|
0EE7A79620F61EDC00B42E6A /* PacketMacros.h in Sources */,
|
||||||
0EFEB48A2006D7C400F81029 /* TunnelKitProvider.swift in Sources */,
|
0EFEB48A2006D7C400F81029 /* TunnelKitProvider.swift in Sources */,
|
||||||
|
0E0C2126212ED29D008AB282 /* SessionError.swift in Sources */,
|
||||||
0EBBF2FB2085061600E36B40 /* NETCPInterface.swift in Sources */,
|
0EBBF2FB2085061600E36B40 /* NETCPInterface.swift in Sources */,
|
||||||
0EFEB4982006D7F300F81029 /* ZeroingData.swift in Sources */,
|
0EFEB4982006D7F300F81029 /* ZeroingData.swift in Sources */,
|
||||||
0EFEB4A32006D7F300F81029 /* Errors.m in Sources */,
|
0EFEB4A32006D7F300F81029 /* Errors.m in Sources */,
|
||||||
|
@ -959,6 +970,7 @@
|
||||||
0E3E0F222108A8CC00B371C1 /* PushReply.swift in Sources */,
|
0E3E0F222108A8CC00B371C1 /* PushReply.swift in Sources */,
|
||||||
0EFEB4912006D7F300F81029 /* TLSBox.m in Sources */,
|
0EFEB4912006D7F300F81029 /* TLSBox.m in Sources */,
|
||||||
0EFEB49D2006D7F300F81029 /* IOInterface.swift in Sources */,
|
0EFEB49D2006D7F300F81029 /* IOInterface.swift in Sources */,
|
||||||
|
0E0C2128212ED29D008AB282 /* SessionProxy+Configuration.swift in Sources */,
|
||||||
0EFEB4972006D7F300F81029 /* Authenticator.swift in Sources */,
|
0EFEB4972006D7F300F81029 /* Authenticator.swift in Sources */,
|
||||||
0EFEB49B2006D7F300F81029 /* Packet.swift in Sources */,
|
0EFEB49B2006D7F300F81029 /* Packet.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
|
@ -155,20 +155,22 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
|
||||||
cfg.print(appVersion: appVersion)
|
cfg.print(appVersion: appVersion)
|
||||||
|
|
||||||
// log.info("Temporary CA is stored to: \(caPath)")
|
// log.info("Temporary CA is stored to: \(caPath)")
|
||||||
let encryption = SessionProxy.EncryptionParameters(cfg.cipher.rawValue, cfg.digest.rawValue, caPath)
|
var sessionConfiguration = SessionProxy.ConfigurationBuilder(username: endpoint.username, password: endpoint.password)
|
||||||
let credentials = SessionProxy.Credentials(endpoint.username, endpoint.password)
|
sessionConfiguration.cipherName = cfg.cipher.rawValue
|
||||||
|
sessionConfiguration.digestName = cfg.digest.rawValue
|
||||||
|
sessionConfiguration.caPath = caPath
|
||||||
|
if let renegotiatesAfterSeconds = cfg.renegotiatesAfterSeconds {
|
||||||
|
sessionConfiguration.renegotiatesAfter = Double(renegotiatesAfterSeconds)
|
||||||
|
}
|
||||||
|
sessionConfiguration.keepAliveInterval = CoreConfiguration.pingInterval
|
||||||
|
|
||||||
let proxy: SessionProxy
|
let proxy: SessionProxy
|
||||||
do {
|
do {
|
||||||
proxy = try SessionProxy(queue: tunnelQueue, encryption: encryption, credentials: credentials)
|
proxy = try SessionProxy(queue: tunnelQueue, configuration: sessionConfiguration.build())
|
||||||
} catch let e {
|
} catch let e {
|
||||||
completionHandler(e)
|
completionHandler(e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let renegotiatesAfterSeconds = cfg.renegotiatesAfterSeconds {
|
|
||||||
proxy.renegotiatesAfter = Double(renegotiatesAfterSeconds)
|
|
||||||
}
|
|
||||||
proxy.keepAliveInterval = CoreConfiguration.pingInterval
|
|
||||||
proxy.delegate = self
|
proxy.delegate = self
|
||||||
self.proxy = proxy
|
self.proxy = proxy
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// SessionError.swift
|
||||||
|
// TunnelKit
|
||||||
|
//
|
||||||
|
// Created by Davide De Rosa on 23/08/2018.
|
||||||
|
// Copyright © 2018 Davide De Rosa. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// The possible errors raised/thrown during `SessionProxy` operation.
|
||||||
|
public enum SessionError: Error {
|
||||||
|
|
||||||
|
/// The negotiation timed out.
|
||||||
|
case negotiationTimeout
|
||||||
|
|
||||||
|
/// The peer failed to verify.
|
||||||
|
case peerVerification
|
||||||
|
|
||||||
|
/// The VPN session id is missing.
|
||||||
|
case missingSessionId
|
||||||
|
|
||||||
|
/// The VPN session id doesn't match.
|
||||||
|
case sessionMismatch
|
||||||
|
|
||||||
|
/// The connection key is wrong or wasn't expected.
|
||||||
|
case badKey
|
||||||
|
|
||||||
|
/// The TLS negotiation failed.
|
||||||
|
case tlsError
|
||||||
|
|
||||||
|
/// The control packet has an incorrect prefix payload.
|
||||||
|
case wrongControlDataPrefix
|
||||||
|
|
||||||
|
/// The provided credentials failed authentication.
|
||||||
|
case badCredentials
|
||||||
|
|
||||||
|
/// The reply to PUSH_REQUEST is malformed.
|
||||||
|
case malformedPushReply
|
||||||
|
|
||||||
|
/// A write operation failed at the link layer (e.g. network unreachable).
|
||||||
|
case failedLinkWrite
|
||||||
|
|
||||||
|
/// The server couldn't ping back before timeout.
|
||||||
|
case pingTimeout
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
//
|
||||||
|
// SessionProxy+Configuration.swift
|
||||||
|
// TunnelKit
|
||||||
|
//
|
||||||
|
// Created by Davide De Rosa on 23/08/2018.
|
||||||
|
// Copyright © 2018 Davide De Rosa. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension SessionProxy {
|
||||||
|
|
||||||
|
/// The way to create a `SessionProxy.Configuration` object for a `SessionProxy`.
|
||||||
|
public struct ConfigurationBuilder {
|
||||||
|
|
||||||
|
/// An username.
|
||||||
|
public let username: String
|
||||||
|
|
||||||
|
/// A password.
|
||||||
|
public let password: String
|
||||||
|
|
||||||
|
/// The cipher algorithm for data encryption. Must follow OpenSSL nomenclature, e.g. "AES-128-CBC".
|
||||||
|
public var cipherName: String
|
||||||
|
|
||||||
|
/// The digest algorithm for HMAC. Must follow OpenSSL nomenclature, e.g. "SHA-1".
|
||||||
|
public var digestName: String
|
||||||
|
|
||||||
|
/// The path to the optional CA for TLS negotiation (PEM format).
|
||||||
|
public var caPath: String?
|
||||||
|
|
||||||
|
/// Sends periodical keep-alive packets if set.
|
||||||
|
public var keepAliveInterval: TimeInterval?
|
||||||
|
|
||||||
|
/// The number of seconds after which a renegotiation should be initiated. If `nil`, the client will never initiate a renegotiation.
|
||||||
|
public var renegotiatesAfter: TimeInterval?
|
||||||
|
|
||||||
|
/// :nodoc:
|
||||||
|
public init(username: String, password: String) {
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
cipherName = "AES-128-CBC"
|
||||||
|
digestName = "SHA-1"
|
||||||
|
caPath = nil
|
||||||
|
keepAliveInterval = nil
|
||||||
|
renegotiatesAfter = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Builds a `SessionProxy.Configuration` object.
|
||||||
|
|
||||||
|
- Returns: A `SessionProxy.Configuration` object with this builder.
|
||||||
|
*/
|
||||||
|
public func build() -> Configuration {
|
||||||
|
return Configuration(
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
cipherName: cipherName,
|
||||||
|
digestName: digestName,
|
||||||
|
caPath: caPath,
|
||||||
|
keepAliveInterval: keepAliveInterval,
|
||||||
|
renegotiatesAfter: renegotiatesAfter
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The immutable configuration for `SessionProxy`.
|
||||||
|
public struct Configuration {
|
||||||
|
|
||||||
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.username`
|
||||||
|
public let username: String
|
||||||
|
|
||||||
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.password`
|
||||||
|
public let password: String
|
||||||
|
|
||||||
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.cipherName`
|
||||||
|
public let cipherName: String
|
||||||
|
|
||||||
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.digestName`
|
||||||
|
public let digestName: String
|
||||||
|
|
||||||
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.caPath`
|
||||||
|
public let caPath: String?
|
||||||
|
|
||||||
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.keepAliveInterval`
|
||||||
|
public let keepAliveInterval: TimeInterval?
|
||||||
|
|
||||||
|
/// - Seealso: `SessionProxy.ConfigurationBuilder.renegotiatesAfter`
|
||||||
|
public let renegotiatesAfter: TimeInterval?
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,43 +19,6 @@ private extension Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The possible errors raised/thrown during `SessionProxy` operation.
|
|
||||||
public enum SessionError: Error {
|
|
||||||
|
|
||||||
/// The negotiation timed out.
|
|
||||||
case negotiationTimeout
|
|
||||||
|
|
||||||
/// The peer failed to verify.
|
|
||||||
case peerVerification
|
|
||||||
|
|
||||||
/// The VPN session id is missing.
|
|
||||||
case missingSessionId
|
|
||||||
|
|
||||||
/// The VPN session id doesn't match.
|
|
||||||
case sessionMismatch
|
|
||||||
|
|
||||||
/// The connection key is wrong or wasn't expected.
|
|
||||||
case badKey
|
|
||||||
|
|
||||||
/// The TLS negotiation failed.
|
|
||||||
case tlsError
|
|
||||||
|
|
||||||
/// The control packet has an incorrect prefix payload.
|
|
||||||
case wrongControlDataPrefix
|
|
||||||
|
|
||||||
/// The provided credentials failed authentication.
|
|
||||||
case badCredentials
|
|
||||||
|
|
||||||
/// The reply to PUSH_REQUEST is malformed.
|
|
||||||
case malformedPushReply
|
|
||||||
|
|
||||||
/// A write operation failed at the link layer (e.g. network unreachable).
|
|
||||||
case failedLinkWrite
|
|
||||||
|
|
||||||
/// The server couldn't ping back before timeout.
|
|
||||||
case pingTimeout
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Observes major events notified by a `SessionProxy`.
|
/// Observes major events notified by a `SessionProxy`.
|
||||||
public protocol SessionProxyDelegate: class {
|
public protocol SessionProxyDelegate: class {
|
||||||
|
|
||||||
|
@ -80,43 +43,6 @@ public protocol SessionProxyDelegate: class {
|
||||||
|
|
||||||
/// Provides methods to set up and maintain an OpenVPN session.
|
/// Provides methods to set up and maintain an OpenVPN session.
|
||||||
public class SessionProxy {
|
public class SessionProxy {
|
||||||
|
|
||||||
/// Wraps the encryption parameters of the session.
|
|
||||||
public struct EncryptionParameters {
|
|
||||||
|
|
||||||
/// The cipher algorithm for data encryption. Must follow OpenSSL nomenclature, e.g. "AES-128-CBC".
|
|
||||||
public let cipherName: String
|
|
||||||
|
|
||||||
/// The digest algorithm for HMAC. Must follow OpenSSL nomenclature, e.g. "SHA-1".
|
|
||||||
public let digestName: String
|
|
||||||
|
|
||||||
/// The path to the CA for TLS negotiation (PEM format).
|
|
||||||
public let caPath: String?
|
|
||||||
|
|
||||||
/// :nodoc:
|
|
||||||
public init(_ cipherName: String, _ digestName: String, _ caPath: String?) {
|
|
||||||
self.cipherName = cipherName
|
|
||||||
self.digestName = digestName
|
|
||||||
self.caPath = caPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A set of credentials.
|
|
||||||
public struct Credentials {
|
|
||||||
|
|
||||||
/// An username.
|
|
||||||
public let username: String
|
|
||||||
|
|
||||||
/// A password.
|
|
||||||
public let password: String
|
|
||||||
|
|
||||||
/// :nodoc:
|
|
||||||
public init(_ username: String, _ password: String) {
|
|
||||||
self.username = username
|
|
||||||
self.password = password
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum StopMethod {
|
private enum StopMethod {
|
||||||
case shutdown
|
case shutdown
|
||||||
|
|
||||||
|
@ -125,15 +51,7 @@ public class SessionProxy {
|
||||||
|
|
||||||
// MARK: Configuration
|
// MARK: Configuration
|
||||||
|
|
||||||
private let encryption: EncryptionParameters
|
private let configuration: Configuration
|
||||||
|
|
||||||
private let credentials: Credentials
|
|
||||||
|
|
||||||
/// Sends periodical keep-alive packets if set.
|
|
||||||
public var keepAliveInterval: TimeInterval?
|
|
||||||
|
|
||||||
/// The number of seconds after which a renegotiation should be initiated. If `nil`, the client will never initiate a renegotiation.
|
|
||||||
public var renegotiatesAfter: TimeInterval?
|
|
||||||
|
|
||||||
/// An optional `SessionProxyDelegate` for receiving session events.
|
/// An optional `SessionProxyDelegate` for receiving session events.
|
||||||
public weak var delegate: SessionProxyDelegate?
|
public weak var delegate: SessionProxyDelegate?
|
||||||
|
@ -223,16 +141,11 @@ public class SessionProxy {
|
||||||
Creates a VPN session.
|
Creates a VPN session.
|
||||||
|
|
||||||
- Parameter queue: The `DispatchQueue` where to run the session loop.
|
- Parameter queue: The `DispatchQueue` where to run the session loop.
|
||||||
- Parameter encryption: The `SessionProxy.EncryptionParameters` to establish for this session.
|
- Parameter configuration: The `SessionProxy.Configuration` to use for this session.
|
||||||
- Parameter credentials: The `SessionProxy.Credentials` required for authentication.
|
|
||||||
*/
|
*/
|
||||||
public init(queue: DispatchQueue, encryption: EncryptionParameters, credentials: Credentials) throws {
|
public init(queue: DispatchQueue, configuration: Configuration) throws {
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.encryption = encryption
|
self.configuration = configuration
|
||||||
self.credentials = credentials
|
|
||||||
|
|
||||||
keepAliveInterval = nil
|
|
||||||
renegotiatesAfter = nil
|
|
||||||
|
|
||||||
keys = [:]
|
keys = [:]
|
||||||
oldKeys = []
|
oldKeys = []
|
||||||
|
@ -369,9 +282,6 @@ public class SessionProxy {
|
||||||
tlsObserver = nil
|
tlsObserver = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (_, key) in keys {
|
|
||||||
// key.dispose()
|
|
||||||
// }
|
|
||||||
keys.removeAll()
|
keys.removeAll()
|
||||||
oldKeys.removeAll()
|
oldKeys.removeAll()
|
||||||
negotiationKeyIdx = 0
|
negotiationKeyIdx = 0
|
||||||
|
@ -644,7 +554,7 @@ public class SessionProxy {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if let interval = keepAliveInterval {
|
if let interval = configuration.keepAliveInterval {
|
||||||
let elapsed = now.timeIntervalSince(lastPingOut)
|
let elapsed = now.timeIntervalSince(lastPingOut)
|
||||||
guard (elapsed >= interval) else {
|
guard (elapsed >= interval) else {
|
||||||
let remaining = min(interval, interval - elapsed)
|
let remaining = min(interval, interval - elapsed)
|
||||||
|
@ -659,7 +569,7 @@ public class SessionProxy {
|
||||||
sendDataPackets([DataPacket.pingString])
|
sendDataPackets([DataPacket.pingString])
|
||||||
lastPingOut = Date()
|
lastPingOut = Date()
|
||||||
|
|
||||||
if let interval = keepAliveInterval {
|
if let interval = configuration.keepAliveInterval {
|
||||||
queue.asyncAfter(deadline: .now() + interval) { [weak self] in
|
queue.asyncAfter(deadline: .now() + interval) { [weak self] in
|
||||||
self?.ping()
|
self?.ping()
|
||||||
}
|
}
|
||||||
|
@ -725,7 +635,7 @@ public class SessionProxy {
|
||||||
negotiationKey.controlState = .preAuth
|
negotiationKey.controlState = .preAuth
|
||||||
|
|
||||||
do {
|
do {
|
||||||
authenticator = try Authenticator(credentials.username, authToken ?? credentials.password)
|
authenticator = try Authenticator(configuration.username, authToken ?? configuration.password)
|
||||||
try authenticator?.putAuth(into: negotiationKey.tls)
|
try authenticator?.putAuth(into: negotiationKey.tls)
|
||||||
} catch let e {
|
} catch let e {
|
||||||
deferStop(.shutdown, e)
|
deferStop(.shutdown, e)
|
||||||
|
@ -774,7 +684,7 @@ public class SessionProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func maybeRenegotiate() {
|
private func maybeRenegotiate() {
|
||||||
guard let renegotiatesAfter = renegotiatesAfter else {
|
guard let renegotiatesAfter = configuration.renegotiatesAfter else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard (negotiationKeyIdx == currentKeyIdx) else {
|
guard (negotiationKeyIdx == currentKeyIdx) else {
|
||||||
|
@ -828,7 +738,7 @@ public class SessionProxy {
|
||||||
log.debug("Remote sessionId is \(remoteSessionId.toHex())")
|
log.debug("Remote sessionId is \(remoteSessionId.toHex())")
|
||||||
log.debug("Start TLS handshake")
|
log.debug("Start TLS handshake")
|
||||||
|
|
||||||
negotiationKey.tlsOptional = TLSBox(caPath: encryption.caPath)
|
negotiationKey.tlsOptional = TLSBox(caPath: configuration.caPath)
|
||||||
do {
|
do {
|
||||||
try negotiationKey.tls.start()
|
try negotiationKey.tls.start()
|
||||||
} catch let e {
|
} catch let e {
|
||||||
|
@ -968,7 +878,7 @@ public class SessionProxy {
|
||||||
dnsServers: reply.dnsServers
|
dnsServers: reply.dnsServers
|
||||||
)
|
)
|
||||||
|
|
||||||
if let interval = keepAliveInterval {
|
if let interval = configuration.keepAliveInterval {
|
||||||
queue.asyncAfter(deadline: .now() + interval) { [weak self] in
|
queue.asyncAfter(deadline: .now() + interval) { [weak self] in
|
||||||
self?.ping()
|
self?.ping()
|
||||||
}
|
}
|
||||||
|
@ -1100,7 +1010,7 @@ public class SessionProxy {
|
||||||
|
|
||||||
let proxy: EncryptionProxy
|
let proxy: EncryptionProxy
|
||||||
do {
|
do {
|
||||||
proxy = try EncryptionProxy(encryption.cipherName, encryption.digestName, auth, sessionId, remoteSessionId)
|
proxy = try EncryptionProxy(configuration.cipherName, configuration.digestName, auth, sessionId, remoteSessionId)
|
||||||
} catch let e {
|
} catch let e {
|
||||||
deferStop(.shutdown, e)
|
deferStop(.shutdown, e)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue