Wrap TKP.Configuration fields in SP.Configuration

Take credentials out of SP.Configuration. Makes sense as they
never appear in e.g. an .ovpn file.
This commit is contained in:
Davide De Rosa 2018-10-25 08:33:40 +02:00
parent e962603098
commit 8f328709c8
4 changed files with 67 additions and 170 deletions

View File

@ -121,38 +121,11 @@ extension TunnelKitProvider {
/// The accepted communication protocols. Must be non-empty. /// The accepted communication protocols. Must be non-empty.
public var endpointProtocols: [EndpointProtocol] public var endpointProtocols: [EndpointProtocol]
/// The encryption algorithm.
public var cipher: SessionProxy.Cipher
/// The message digest algorithm.
public var digest: SessionProxy.Digest
/// The CA certificate to validate server against.
public let ca: CryptoContainer
/// The optional client certificate to authenticate with. Set to `nil` to disable client authentication (default).
public var clientCertificate: CryptoContainer?
/// The optional key for `clientCertificate`. Set to `nil` if client authentication unused (default).
public var clientKey: CryptoContainer?
/// The MTU of the link. /// The MTU of the link.
public var mtu: Int public var mtu: Int
/// Sets compression framing, disabled by default. /// The session configuration.
public var compressionFraming: SessionProxy.CompressionFraming public var sessionConfiguration: SessionProxy.Configuration
/// The optional TLS wrapping. When `strategy == .auth`, uses `digest` as HMAC algorithm.
public var tlsWrap: SessionProxy.TLSWrap?
/// Sends periodical keep-alive packets (ping) if set. Useful with stateful firewalls.
public var keepAliveSeconds: Int?
/// The number of seconds after which a renegotiation is started. Set to `nil` to disable renegotiation (default).
public var renegotiatesAfterSeconds: Int?
/// Server is patched for the PIA VPN provider.
public var usesPIAPatches: Bool?
// MARK: Debugging // MARK: Debugging
@ -175,21 +148,12 @@ extension TunnelKitProvider {
- Parameter ca: The CA certificate. - Parameter ca: The CA certificate.
*/ */
public init(ca: CryptoContainer) { public init(sessionConfiguration: SessionProxy.Configuration) {
prefersResolvedAddresses = false prefersResolvedAddresses = false
resolvedAddresses = nil resolvedAddresses = nil
endpointProtocols = [EndpointProtocol(.udp, 1194)] endpointProtocols = [EndpointProtocol(.udp, 1194)]
cipher = .aes128cbc
digest = .sha1
self.ca = ca
clientCertificate = nil
clientKey = nil
mtu = 1500 mtu = 1500
compressionFraming = .disabled self.sessionConfiguration = sessionConfiguration
tlsWrap = nil
keepAliveSeconds = nil
renegotiatesAfterSeconds = nil
usesPIAPatches = false
shouldDebug = false shouldDebug = false
debugLogKey = nil debugLogKey = nil
debugLogFormat = nil debugLogFormat = nil
@ -199,6 +163,21 @@ extension TunnelKitProvider {
fileprivate init(providerConfiguration: [String: Any]) throws { fileprivate init(providerConfiguration: [String: Any]) throws {
let S = Configuration.Keys.self let S = Configuration.Keys.self
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 ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.endpointProtocols)] is nil or empty")
}
endpointProtocols = try endpointProtocolsStrings.map {
guard let ep = EndpointProtocol(rawValue: $0) else {
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.endpointProtocols)] has a badly formed element")
}
return ep
}
mtu = providerConfiguration[S.mtu] as? Int ?? 1250
//
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 ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.cipherAlgorithm)]") throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.cipherAlgorithm)]")
} }
@ -224,41 +203,28 @@ extension TunnelKitProvider {
clientCertificate = nil clientCertificate = nil
clientKey = nil clientKey = nil
} }
prefersResolvedAddresses = providerConfiguration[S.prefersResolvedAddresses] as? Bool ?? false var sessionConfigurationBuilder = SessionProxy.ConfigurationBuilder(ca: ca)
resolvedAddresses = providerConfiguration[S.resolvedAddresses] as? [String] sessionConfigurationBuilder.cipher = cipher
sessionConfigurationBuilder.digest = digest
guard let endpointProtocolsStrings = providerConfiguration[S.endpointProtocols] as? [String], !endpointProtocolsStrings.isEmpty else { sessionConfigurationBuilder.clientCertificate = clientCertificate
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.endpointProtocols)] is nil or empty") sessionConfigurationBuilder.clientKey = clientKey
}
endpointProtocols = try endpointProtocolsStrings.map {
guard let ep = EndpointProtocol(rawValue: $0) else {
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.endpointProtocols)] has a badly formed element")
}
return ep
}
self.cipher = cipher
self.digest = digest
self.ca = ca
self.clientCertificate = clientCertificate
self.clientKey = clientKey
mtu = providerConfiguration[S.mtu] as? Int ?? 1250
if let compressionFramingValue = providerConfiguration[S.compressionFraming] as? Int, let compressionFraming = SessionProxy.CompressionFraming(rawValue: compressionFramingValue) { if let compressionFramingValue = providerConfiguration[S.compressionFraming] as? Int, let compressionFraming = SessionProxy.CompressionFraming(rawValue: compressionFramingValue) {
self.compressionFraming = compressionFraming sessionConfigurationBuilder.compressionFraming = compressionFraming
} else { } else {
compressionFraming = .disabled sessionConfigurationBuilder.compressionFraming = .disabled
} }
if let tlsWrapData = providerConfiguration[S.tlsWrap] as? Data { if let tlsWrapData = providerConfiguration[S.tlsWrap] as? Data {
do { do {
tlsWrap = try SessionProxy.TLSWrap.deserialized(tlsWrapData) sessionConfigurationBuilder.tlsWrap = try SessionProxy.TLSWrap.deserialized(tlsWrapData)
} catch { } catch {
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.tlsWrap)]") throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(S.tlsWrap)]")
} }
} }
keepAliveSeconds = providerConfiguration[S.keepAlive] as? Int sessionConfigurationBuilder.keepAliveInterval = providerConfiguration[S.keepAlive] as? TimeInterval
renegotiatesAfterSeconds = providerConfiguration[S.renegotiatesAfter] as? Int sessionConfigurationBuilder.renegotiatesAfter = providerConfiguration[S.renegotiatesAfter] as? TimeInterval
usesPIAPatches = providerConfiguration[S.usesPIAPatches] as? Bool ?? false sessionConfigurationBuilder.usesPIAPatches = providerConfiguration[S.usesPIAPatches] as? Bool ?? false
sessionConfiguration = sessionConfigurationBuilder.build()
shouldDebug = providerConfiguration[S.debug] as? Bool ?? false shouldDebug = providerConfiguration[S.debug] as? Bool ?? false
if shouldDebug { if shouldDebug {
@ -287,17 +253,8 @@ extension TunnelKitProvider {
prefersResolvedAddresses: prefersResolvedAddresses, prefersResolvedAddresses: prefersResolvedAddresses,
resolvedAddresses: resolvedAddresses, resolvedAddresses: resolvedAddresses,
endpointProtocols: endpointProtocols, endpointProtocols: endpointProtocols,
cipher: cipher,
digest: digest,
ca: ca,
clientCertificate: clientCertificate,
clientKey: clientKey,
mtu: mtu, mtu: mtu,
compressionFraming: compressionFraming, sessionConfiguration: sessionConfiguration,
tlsWrap: tlsWrap,
keepAliveSeconds: keepAliveSeconds,
renegotiatesAfterSeconds: renegotiatesAfterSeconds,
usesPIAPatches: usesPIAPatches,
shouldDebug: shouldDebug, shouldDebug: shouldDebug,
debugLogKey: shouldDebug ? debugLogKey : nil, debugLogKey: shouldDebug ? debugLogKey : nil,
debugLogFormat: shouldDebug ? debugLogFormat : nil, debugLogFormat: shouldDebug ? debugLogFormat : nil,
@ -317,6 +274,10 @@ extension TunnelKitProvider {
static let endpointProtocols = "EndpointProtocols" static let endpointProtocols = "EndpointProtocols"
static let mtu = "MTU"
// MARK: SessionConfiguration
static let cipherAlgorithm = "CipherAlgorithm" static let cipherAlgorithm = "CipherAlgorithm"
static let digestAlgorithm = "DigestAlgorithm" static let digestAlgorithm = "DigestAlgorithm"
@ -327,8 +288,6 @@ extension TunnelKitProvider {
static let clientKey = "ClientKey" static let clientKey = "ClientKey"
static let mtu = "MTU"
static let compressionFraming = "CompressionFraming" static let compressionFraming = "CompressionFraming"
static let tlsWrap = "TLSWrap" static let tlsWrap = "TLSWrap"
@ -338,6 +297,8 @@ extension TunnelKitProvider {
static let renegotiatesAfter = "RenegotiatesAfter" static let renegotiatesAfter = "RenegotiatesAfter"
static let usesPIAPatches = "UsesPIAPatches" static let usesPIAPatches = "UsesPIAPatches"
// MARK: Debugging
static let debug = "Debug" static let debug = "Debug"
@ -357,38 +318,11 @@ extension TunnelKitProvider {
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.endpointProtocols` /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.endpointProtocols`
public let endpointProtocols: [EndpointProtocol] public let endpointProtocols: [EndpointProtocol]
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.cipher`
public let cipher: SessionProxy.Cipher
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.digest`
public let digest: SessionProxy.Digest
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.ca`
public let ca: CryptoContainer
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.clientCertificate`
public let clientCertificate: CryptoContainer?
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.clientKey`
public let clientKey: CryptoContainer?
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.mtu` /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.mtu`
public let mtu: Int public let mtu: Int
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.compressionFraming` /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.sessionConfiguration`
public let compressionFraming: SessionProxy.CompressionFraming public let sessionConfiguration: SessionProxy.Configuration
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.tlsWrap`
public let tlsWrap: SessionProxy.TLSWrap?
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.keepAliveSeconds`
public let keepAliveSeconds: Int?
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.renegotiatesAfterSeconds`
public let renegotiatesAfterSeconds: Int?
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.usesPIAPatches`
public let usesPIAPatches: Bool?
/// - Seealso: `TunnelKitProvider.ConfigurationBuilder.shouldDebug` /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.shouldDebug`
public let shouldDebug: Bool public let shouldDebug: Bool
@ -474,32 +408,32 @@ extension TunnelKitProvider {
S.appGroup: appGroup, S.appGroup: appGroup,
S.prefersResolvedAddresses: prefersResolvedAddresses, S.prefersResolvedAddresses: prefersResolvedAddresses,
S.endpointProtocols: endpointProtocols.map { $0.rawValue }, S.endpointProtocols: endpointProtocols.map { $0.rawValue },
S.cipherAlgorithm: cipher.rawValue, S.cipherAlgorithm: sessionConfiguration.cipher.rawValue,
S.digestAlgorithm: digest.rawValue, S.digestAlgorithm: sessionConfiguration.digest.rawValue,
S.ca: ca.pem, S.ca: sessionConfiguration.ca.pem,
S.mtu: mtu, S.mtu: mtu,
S.debug: shouldDebug S.debug: shouldDebug
] ]
if let clientCertificate = clientCertificate { if let clientCertificate = sessionConfiguration.clientCertificate {
dict[S.clientCertificate] = clientCertificate.pem dict[S.clientCertificate] = clientCertificate.pem
} }
if let clientKey = clientKey { if let clientKey = sessionConfiguration.clientKey {
dict[S.clientKey] = clientKey.pem dict[S.clientKey] = clientKey.pem
} }
if let resolvedAddresses = resolvedAddresses { if let resolvedAddresses = resolvedAddresses {
dict[S.resolvedAddresses] = resolvedAddresses dict[S.resolvedAddresses] = resolvedAddresses
} }
dict[S.compressionFraming] = compressionFraming.rawValue dict[S.compressionFraming] = sessionConfiguration.compressionFraming.rawValue
if let tlsWrapData = tlsWrap?.serialized() { if let tlsWrapData = sessionConfiguration.tlsWrap?.serialized() {
dict[S.tlsWrap] = tlsWrapData dict[S.tlsWrap] = tlsWrapData
} }
if let keepAliveSeconds = keepAliveSeconds { if let keepAliveSeconds = sessionConfiguration.keepAliveInterval {
dict[S.keepAlive] = keepAliveSeconds dict[S.keepAlive] = keepAliveSeconds
} }
if let renegotiatesAfterSeconds = renegotiatesAfterSeconds { if let renegotiatesAfterSeconds = sessionConfiguration.renegotiatesAfter {
dict[S.renegotiatesAfter] = renegotiatesAfterSeconds dict[S.renegotiatesAfter] = renegotiatesAfterSeconds
} }
if let usesPIAPatches = usesPIAPatches { if let usesPIAPatches = sessionConfiguration.usesPIAPatches {
dict[S.usesPIAPatches] = usesPIAPatches dict[S.usesPIAPatches] = usesPIAPatches
} }
if let debugLogKey = debugLogKey { if let debugLogKey = debugLogKey {
@ -550,26 +484,26 @@ extension TunnelKitProvider {
} }
log.info("\tProtocols: \(endpointProtocols)") log.info("\tProtocols: \(endpointProtocols)")
log.info("\tCipher: \(cipher)") log.info("\tCipher: \(sessionConfiguration.cipher)")
log.info("\tDigest: \(digest)") log.info("\tDigest: \(sessionConfiguration.digest)")
if let _ = clientCertificate { if let _ = sessionConfiguration.clientCertificate {
log.info("\tClient verification: enabled") log.info("\tClient verification: enabled")
} else { } else {
log.info("\tClient verification: disabled") log.info("\tClient verification: disabled")
} }
log.info("\tMTU: \(mtu)") log.info("\tMTU: \(mtu)")
log.info("\tCompression framing: \(compressionFraming)") log.info("\tCompression framing: \(sessionConfiguration.compressionFraming)")
if let keepAliveSeconds = keepAliveSeconds, keepAliveSeconds > 0 { if let keepAliveSeconds = sessionConfiguration.keepAliveInterval, keepAliveSeconds > 0 {
log.info("\tKeep-alive: \(keepAliveSeconds) seconds") log.info("\tKeep-alive: \(keepAliveSeconds) seconds")
} else { } else {
log.info("\tKeep-alive: never") log.info("\tKeep-alive: never")
} }
if let renegotiatesAfterSeconds = renegotiatesAfterSeconds, renegotiatesAfterSeconds > 0 { if let renegotiatesAfterSeconds = sessionConfiguration.renegotiatesAfter, renegotiatesAfterSeconds > 0 {
log.info("\tRenegotiation: \(renegotiatesAfterSeconds) seconds") log.info("\tRenegotiation: \(renegotiatesAfterSeconds) seconds")
} else { } else {
log.info("\tRenegotiation: never") log.info("\tRenegotiation: never")
} }
if let tlsWrap = tlsWrap { if let tlsWrap = sessionConfiguration.tlsWrap {
log.info("\tTLS wrapping: \(tlsWrap.strategy)") log.info("\tTLS wrapping: \(tlsWrap.strategy)")
} else { } else {
log.info("\tTLS wrapping: disabled") log.info("\tTLS wrapping: disabled")
@ -589,18 +523,9 @@ 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(ca: ca) var builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionConfiguration)
builder.endpointProtocols = endpointProtocols builder.endpointProtocols = endpointProtocols
builder.cipher = cipher
builder.digest = digest
builder.clientCertificate = clientCertificate
builder.clientKey = clientKey
builder.mtu = mtu builder.mtu = mtu
builder.compressionFraming = compressionFraming
builder.tlsWrap = tlsWrap
builder.keepAliveSeconds = keepAliveSeconds
builder.renegotiatesAfterSeconds = renegotiatesAfterSeconds
builder.usesPIAPatches = usesPIAPatches
builder.shouldDebug = shouldDebug builder.shouldDebug = shouldDebug
builder.debugLogKey = debugLogKey builder.debugLogKey = debugLogKey
builder.debugLogFormat = debugLogFormat builder.debugLogFormat = debugLogFormat
@ -612,15 +537,8 @@ extension TunnelKitProvider.Configuration: Equatable {
public static func ==(lhs: TunnelKitProvider.Configuration, rhs: TunnelKitProvider.Configuration) -> Bool { public static func ==(lhs: TunnelKitProvider.Configuration, rhs: TunnelKitProvider.Configuration) -> Bool {
return ( return (
(lhs.endpointProtocols == rhs.endpointProtocols) && (lhs.endpointProtocols == rhs.endpointProtocols) &&
(lhs.cipher == rhs.cipher) &&
(lhs.digest == rhs.digest) &&
(lhs.ca == rhs.ca) &&
(lhs.clientCertificate == rhs.clientCertificate) &&
(lhs.clientKey == rhs.clientKey) &&
(lhs.mtu == rhs.mtu) && (lhs.mtu == rhs.mtu) &&
(lhs.compressionFraming == rhs.compressionFraming) && (lhs.sessionConfiguration == rhs.sessionConfiguration)
(lhs.keepAliveSeconds == rhs.keepAliveSeconds) &&
(lhs.renegotiatesAfterSeconds == rhs.renegotiatesAfterSeconds)
// XXX: tlsWrap not copied // XXX: tlsWrap not copied
) )
} }

View File

@ -186,30 +186,14 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
cfg.print(appVersion: appVersion) cfg.print(appVersion: appVersion)
// log.info("Temporary CA is stored to: \(caPath)")
var sessionConfiguration = SessionProxy.ConfigurationBuilder(ca: cfg.ca)
sessionConfiguration.credentials = credentials
sessionConfiguration.cipher = cfg.cipher
sessionConfiguration.digest = cfg.digest
sessionConfiguration.clientCertificate = cfg.clientCertificate
sessionConfiguration.clientKey = cfg.clientKey
sessionConfiguration.compressionFraming = cfg.compressionFraming
sessionConfiguration.tlsWrap = cfg.tlsWrap
if let keepAliveSeconds = cfg.keepAliveSeconds {
sessionConfiguration.keepAliveInterval = TimeInterval(keepAliveSeconds)
}
if let renegotiatesAfterSeconds = cfg.renegotiatesAfterSeconds {
sessionConfiguration.renegotiatesAfter = TimeInterval(renegotiatesAfterSeconds)
}
sessionConfiguration.usesPIAPatches = cfg.usesPIAPatches ?? false
let proxy: SessionProxy let proxy: SessionProxy
do { do {
proxy = try SessionProxy(queue: tunnelQueue, configuration: sessionConfiguration.build(), cachesURL: cachesURL) proxy = try SessionProxy(queue: tunnelQueue, configuration: cfg.sessionConfiguration, cachesURL: cachesURL)
} catch let e { } catch let e {
completionHandler(e) completionHandler(e)
return return
} }
proxy.credentials = credentials
proxy.delegate = self proxy.delegate = self
self.proxy = proxy self.proxy = proxy

View File

@ -135,9 +135,6 @@ extension SessionProxy {
/// The way to create a `SessionProxy.Configuration` object for a `SessionProxy`. /// The way to create a `SessionProxy.Configuration` object for a `SessionProxy`.
public struct ConfigurationBuilder { public struct ConfigurationBuilder {
/// The credentials.
public var credentials: Credentials?
/// The cipher algorithm for data encryption. /// The cipher algorithm for data encryption.
public var cipher: Cipher public var cipher: Cipher
@ -170,7 +167,6 @@ extension SessionProxy {
/// :nodoc: /// :nodoc:
public init(ca: CryptoContainer) { public init(ca: CryptoContainer) {
credentials = nil
cipher = .aes128cbc cipher = .aes128cbc
digest = .sha1 digest = .sha1
self.ca = ca self.ca = ca
@ -190,7 +186,6 @@ extension SessionProxy {
*/ */
public func build() -> Configuration { public func build() -> Configuration {
return Configuration( return Configuration(
credentials: credentials,
cipher: cipher, cipher: cipher,
digest: digest, digest: digest,
ca: ca, ca: ca,
@ -206,11 +201,8 @@ extension SessionProxy {
} }
/// The immutable configuration for `SessionProxy`. /// The immutable configuration for `SessionProxy`.
public struct Configuration: Codable { public struct Configuration: Codable, Equatable {
/// - Seealso: `SessionProxy.ConfigurationBuilder.credentials`
public let credentials: Credentials?
/// - Seealso: `SessionProxy.ConfigurationBuilder.cipher` /// - Seealso: `SessionProxy.ConfigurationBuilder.cipher`
public let cipher: Cipher public let cipher: Cipher

View File

@ -81,6 +81,9 @@ public class SessionProxy {
private let configuration: Configuration private let configuration: Configuration
/// The optional credentials.
public var credentials: Credentials?
private var keepAliveInterval: TimeInterval? { private var keepAliveInterval: TimeInterval? {
let interval: TimeInterval? let interval: TimeInterval?
if let negInterval = pushReply?.ping, negInterval > 0 { if let negInterval = pushReply?.ping, negInterval > 0 {
@ -650,7 +653,7 @@ public class SessionProxy {
negotiationKey.controlState = .preAuth negotiationKey.controlState = .preAuth
do { do {
authenticator = try Authenticator(configuration.credentials?.username, pushReply?.authToken ?? configuration.credentials?.password) authenticator = try Authenticator(credentials?.username, pushReply?.authToken ?? credentials?.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)