From 55534df6fa5eb9fb2afc06ffc4b8f76a3fbfc445 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Thu, 4 Apr 2019 13:01:32 +0200 Subject: [PATCH] Work around cipher/digest/framing issues - Make them optional - Set default values inside SessionProxy Fallback is not needed anywhere else. --- .../TunnelKitProvider+Configuration.swift | 22 +++-- .../Sources/Core/ConfigurationParser.swift | 8 +- .../Core/SessionProxy+Configuration.swift | 80 ++++++++++++------- TunnelKit/Sources/Core/SessionProxy.swift | 35 ++++---- TunnelKitTests/AppExtensionTests.swift | 4 +- TunnelKitTests/PushTests.swift | 4 +- 6 files changed, 85 insertions(+), 68 deletions(-) diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift index 1f3111f..a72c16a 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift @@ -431,16 +431,22 @@ extension TunnelKitProvider { var dict: [String: Any] = [ S.appGroup: appGroup, S.prefersResolvedAddresses: prefersResolvedAddresses, - S.cipherAlgorithm: sessionConfiguration.cipher.rawValue, - S.digestAlgorithm: sessionConfiguration.digest.rawValue, - S.compressionFraming: sessionConfiguration.compressionFraming.rawValue, S.ca: ca.pem, S.endpointProtocols: endpointProtocols.map { $0.rawValue }, S.mtu: mtu, S.debug: shouldDebug ] - if let compressionAlgorithm = sessionConfiguration.compressionAlgorithm?.rawValue { - dict[S.compressionAlgorithm] = compressionAlgorithm + if let cipher = sessionConfiguration.cipher { + dict[S.cipherAlgorithm] = cipher.rawValue + } + if let digest = sessionConfiguration.digest { + dict[S.digestAlgorithm] = digest.rawValue + } + if let compressionFraming = sessionConfiguration.compressionFraming { + dict[S.compressionFraming] = compressionFraming.rawValue + } + if let compressionAlgorithm = sessionConfiguration.compressionAlgorithm { + dict[S.compressionAlgorithm] = compressionAlgorithm.rawValue } if let clientCertificate = sessionConfiguration.clientCertificate { dict[S.clientCertificate] = clientCertificate.pem @@ -525,9 +531,9 @@ extension TunnelKitProvider { } log.info("\tProtocols: \(endpointProtocols)") - log.info("\tCipher: \(sessionConfiguration.cipher)") - log.info("\tDigest: \(sessionConfiguration.digest)") - log.info("\tCompression framing: \(sessionConfiguration.compressionFraming)") + log.info("\tCipher: \(sessionConfiguration.fallbackCipher)") + log.info("\tDigest: \(sessionConfiguration.fallbackDigest)") + log.info("\tCompression framing: \(sessionConfiguration.fallbackCompressionFraming)") if let compressionAlgorithm = sessionConfiguration.compressionAlgorithm, compressionAlgorithm != .disabled { log.info("\tCompression algorithm: \(compressionAlgorithm)") } else { diff --git a/TunnelKit/Sources/Core/ConfigurationParser.swift b/TunnelKit/Sources/Core/ConfigurationParser.swift index 260d9fb..e65a5e6 100644 --- a/TunnelKit/Sources/Core/ConfigurationParser.swift +++ b/TunnelKit/Sources/Core/ConfigurationParser.swift @@ -483,10 +483,10 @@ public class ConfigurationParser { // MARK: General - sessionBuilder.cipher = optCipher ?? .aes128cbc // FIXME: non-optional breaks PUSH_REPLY - sessionBuilder.digest = optDigest ?? .sha1 // FIXME: non-optional breaks PUSH_REPLY - sessionBuilder.compressionFraming = optCompressionFraming ?? .disabled // FIXME: non-optional breaks PUSH_REPLY - sessionBuilder.compressionAlgorithm = optCompressionAlgorithm ?? .disabled + sessionBuilder.cipher = optCipher + sessionBuilder.digest = optDigest + sessionBuilder.compressionFraming = optCompressionFraming + sessionBuilder.compressionAlgorithm = optCompressionAlgorithm sessionBuilder.ca = optCA sessionBuilder.clientCertificate = optClientCertificate diff --git a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift index 7b00d29..fcfd996 100644 --- a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift +++ b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift @@ -132,19 +132,28 @@ extension SessionProxy { } } + /// :nodoc: + private struct Fallback { + static let cipher: Cipher = .aes128cbc + + static let digest: Digest = .sha1 + + static let compressionFraming: CompressionFraming = .disabled + } + /// The way to create a `SessionProxy.Configuration` object for a `SessionProxy`. public struct ConfigurationBuilder { // MARK: General /// The cipher algorithm for data encryption. - public var cipher: SessionProxy.Cipher + public var cipher: SessionProxy.Cipher? /// The digest algorithm for HMAC. - public var digest: SessionProxy.Digest + public var digest: SessionProxy.Digest? /// Compression framing, disabled by default. - public var compressionFraming: SessionProxy.CompressionFraming + public var compressionFraming: SessionProxy.CompressionFraming? /// Compression algorithm, disabled by default. public var compressionAlgorithm: SessionProxy.CompressionAlgorithm? @@ -210,31 +219,6 @@ extension SessionProxy { public init() { } - /// :nodoc: - public init() { - cipher = .aes128cbc - digest = .sha1 - compressionFraming = .disabled - compressionAlgorithm = nil - ca = nil - clientCertificate = nil - clientKey = nil - tlsWrap = nil - keepAliveInterval = nil - renegotiatesAfter = nil - hostname = nil - endpointProtocols = nil - checksEKU = false - randomizeEndpoint = false - usesPIAPatches = false - authToken = nil - peerId = nil - ipv4 = nil - ipv6 = nil - dnsServers = nil - searchDomain = nil - } - /** Builds a `SessionProxy.Configuration` object. @@ -265,19 +249,36 @@ extension SessionProxy { searchDomain: searchDomain ) } + + // MARK: Shortcuts + + /// :nodoc: + public var fallbackCipher: Cipher { + return cipher ?? Fallback.cipher + } + + /// :nodoc: + public var fallbackDigest: Digest { + return digest ?? Fallback.digest + } + + /// :nodoc: + public var fallbackCompressionFraming: CompressionFraming { + return compressionFraming ?? Fallback.compressionFraming + } } /// The immutable configuration for `SessionProxy`. public struct Configuration: Codable { /// - Seealso: `SessionProxy.ConfigurationBuilder.cipher` - public let cipher: Cipher + public let cipher: Cipher? /// - Seealso: `SessionProxy.ConfigurationBuilder.digest` - public let digest: Digest + public let digest: Digest? /// - Seealso: `SessionProxy.ConfigurationBuilder.compressionFraming` - public let compressionFraming: CompressionFraming + public let compressionFraming: CompressionFraming? /// - Seealso: `SessionProxy.ConfigurationBuilder.compressionAlgorithm` public let compressionAlgorithm: CompressionAlgorithm? @@ -362,6 +363,23 @@ extension SessionProxy { builder.searchDomain = searchDomain return builder } + + // MARK: Shortcuts + + /// :nodoc: + public var fallbackCipher: Cipher { + return cipher ?? Fallback.cipher + } + + /// :nodoc: + public var fallbackDigest: Digest { + return digest ?? Fallback.digest + } + + /// :nodoc: + public var fallbackCompressionFraming: CompressionFraming { + return compressionFraming ?? Fallback.compressionFraming + } } } diff --git a/TunnelKit/Sources/Core/SessionProxy.swift b/TunnelKit/Sources/Core/SessionProxy.swift index 7251956..5f278ce 100644 --- a/TunnelKit/Sources/Core/SessionProxy.swift +++ b/TunnelKit/Sources/Core/SessionProxy.swift @@ -196,7 +196,7 @@ public class SessionProxy { if let tlsWrap = configuration.tlsWrap { switch tlsWrap.strategy { case .auth: - controlChannel = try ControlChannel(withAuthKey: tlsWrap.key, digest: configuration.digest) + controlChannel = try ControlChannel(withAuthKey: tlsWrap.key, digest: configuration.fallbackDigest) case .crypt: controlChannel = try ControlChannel(withCryptKey: tlsWrap.key) @@ -634,8 +634,8 @@ public class SessionProxy { log.debug("CA MD5 is: \(caMD5)") return try? PIAHardReset( caMd5Digest: caMD5, - cipher: configuration.cipher, - digest: configuration.digest + cipher: configuration.fallbackCipher, + digest: configuration.fallbackDigest ).encodedData() } return nil @@ -923,10 +923,7 @@ public class SessionProxy { reply = optionalReply log.debug("Received PUSH_REPLY: \"\(reply.maskedDescription)\"") - // FIXME: non-optional breaks PUSH_REPLY -// if let framing = reply.options.compressionFraming, let compression = reply.options.compressionAlgorithm { - let framing = reply.options.compressionFraming - if framing != .disabled, let compression = reply.options.compressionAlgorithm { + if let framing = reply.options.compressionFraming, let compression = reply.options.compressionAlgorithm { switch compression { case .disabled: break @@ -1043,20 +1040,18 @@ public class SessionProxy { log.debug("Set up encryption") } + let pushedCipher = pushReply.options.cipher + if let negCipher = pushedCipher { + log.info("\tNegotiated cipher: \(negCipher.rawValue)") + } let pushedFraming = pushReply.options.compressionFraming - // FIXME: non-optional breaks PUSH_REPLY -// if let negFraming = pushedFraming { -// log.info("\tNegotiated compression framing: \(negFraming)") -// } + if let negFraming = pushedFraming { + log.info("\tNegotiated compression framing: \(negFraming)") + } let pushedCompression = pushReply.options.compressionAlgorithm if let negCompression = pushedCompression { log.info("\tNegotiated compression algorithm: \(negCompression)") } - let pushedCipher = pushReply.options.cipher - // FIXME: non-optional breaks PUSH_REPLY -// if let negCipher = pushedCipher { -// log.info("\tNegotiated cipher: \(negCipher.rawValue)") -// } if let negPing = pushReply.options.keepAliveInterval { log.info("\tNegotiated keep-alive: \(negPing) seconds") } @@ -1064,9 +1059,8 @@ public class SessionProxy { let bridge: EncryptionBridge do { bridge = try EncryptionBridge( - // FIXME: non-optional breaks PUSH_REPLY - pushedCipher ?? configuration.cipher, - configuration.digest, + pushedCipher ?? configuration.fallbackCipher, + configuration.fallbackDigest, auth, sessionId, remoteSessionId @@ -1080,8 +1074,7 @@ public class SessionProxy { encrypter: bridge.encrypter(), decrypter: bridge.decrypter(), peerId: pushReply.options.peerId ?? PacketPeerIdDisabled, - // FIXME: non-optional breaks PUSH_REPLY - compressionFraming: (pushedFraming ?? configuration.compressionFraming).native, + compressionFraming: (pushedFraming ?? configuration.fallbackCompressionFraming).native, compressionAlgorithm: (pushedCompression ?? configuration.compressionAlgorithm ?? .disabled).native, maxPackets: link?.packetBufferSize ?? 200, usesReplayProtection: CoreConfiguration.usesReplayProtection diff --git a/TunnelKitTests/AppExtensionTests.swift b/TunnelKitTests/AppExtensionTests.swift index 3ae98d9..ff212e3 100644 --- a/TunnelKitTests/AppExtensionTests.swift +++ b/TunnelKitTests/AppExtensionTests.swift @@ -84,8 +84,8 @@ class AppExtensionTests: XCTestCase { let K = TunnelKitProvider.Configuration.Keys.self XCTAssertEqual(proto?.providerConfiguration?[K.appGroup] as? String, appGroup) - XCTAssertEqual(proto?.providerConfiguration?[K.cipherAlgorithm] as? String, cfg.sessionConfiguration.cipher.rawValue) - XCTAssertEqual(proto?.providerConfiguration?[K.digestAlgorithm] as? String, cfg.sessionConfiguration.digest.rawValue) + XCTAssertEqual(proto?.providerConfiguration?[K.cipherAlgorithm] as? String, cfg.sessionConfiguration.cipher?.rawValue) + XCTAssertEqual(proto?.providerConfiguration?[K.digestAlgorithm] as? String, cfg.sessionConfiguration.digest?.rawValue) XCTAssertEqual(proto?.providerConfiguration?[K.ca] as? String, cfg.sessionConfiguration.ca?.pem) XCTAssertEqual(proto?.providerConfiguration?[K.mtu] as? Int, cfg.mtu) XCTAssertEqual(proto?.providerConfiguration?[K.renegotiatesAfter] as? TimeInterval, cfg.sessionConfiguration.renegotiatesAfter) diff --git a/TunnelKitTests/PushTests.swift b/TunnelKitTests/PushTests.swift index 3b4fd82..9c4495b 100644 --- a/TunnelKitTests/PushTests.swift +++ b/TunnelKitTests/PushTests.swift @@ -28,8 +28,8 @@ import XCTest private extension SessionReply { func debug() { - print("Compression framing: \(options.compressionFraming.description ?? "none")") - print("Compression algorithm: \(options.compressionAlgorithm?.description ?? "none")") + print("Compression framing: \(options.compressionFraming?.description ?? "disabled")") + print("Compression algorithm: \(options.compressionAlgorithm?.description ?? "disabled")") print("IPv4: \(options.ipv4?.description ?? "none")") print("IPv6: \(options.ipv6?.description ?? "none")") print("DNS: \(options.dnsServers?.description ?? "none")")