Work around cipher/digest/framing issues

- Make them optional
- Set default values inside SessionProxy

Fallback is not needed anywhere else.
This commit is contained in:
Davide De Rosa 2019-04-04 13:01:32 +02:00
parent 0d86bd20b6
commit 55534df6fa
6 changed files with 85 additions and 68 deletions

View File

@ -431,16 +431,22 @@ extension TunnelKitProvider {
var dict: [String: Any] = [ var dict: [String: Any] = [
S.appGroup: appGroup, S.appGroup: appGroup,
S.prefersResolvedAddresses: prefersResolvedAddresses, S.prefersResolvedAddresses: prefersResolvedAddresses,
S.cipherAlgorithm: sessionConfiguration.cipher.rawValue,
S.digestAlgorithm: sessionConfiguration.digest.rawValue,
S.compressionFraming: sessionConfiguration.compressionFraming.rawValue,
S.ca: ca.pem, S.ca: ca.pem,
S.endpointProtocols: endpointProtocols.map { $0.rawValue }, S.endpointProtocols: endpointProtocols.map { $0.rawValue },
S.mtu: mtu, S.mtu: mtu,
S.debug: shouldDebug S.debug: shouldDebug
] ]
if let compressionAlgorithm = sessionConfiguration.compressionAlgorithm?.rawValue { if let cipher = sessionConfiguration.cipher {
dict[S.compressionAlgorithm] = compressionAlgorithm 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 { if let clientCertificate = sessionConfiguration.clientCertificate {
dict[S.clientCertificate] = clientCertificate.pem dict[S.clientCertificate] = clientCertificate.pem
@ -525,9 +531,9 @@ extension TunnelKitProvider {
} }
log.info("\tProtocols: \(endpointProtocols)") log.info("\tProtocols: \(endpointProtocols)")
log.info("\tCipher: \(sessionConfiguration.cipher)") log.info("\tCipher: \(sessionConfiguration.fallbackCipher)")
log.info("\tDigest: \(sessionConfiguration.digest)") log.info("\tDigest: \(sessionConfiguration.fallbackDigest)")
log.info("\tCompression framing: \(sessionConfiguration.compressionFraming)") log.info("\tCompression framing: \(sessionConfiguration.fallbackCompressionFraming)")
if let compressionAlgorithm = sessionConfiguration.compressionAlgorithm, compressionAlgorithm != .disabled { if let compressionAlgorithm = sessionConfiguration.compressionAlgorithm, compressionAlgorithm != .disabled {
log.info("\tCompression algorithm: \(compressionAlgorithm)") log.info("\tCompression algorithm: \(compressionAlgorithm)")
} else { } else {

View File

@ -483,10 +483,10 @@ public class ConfigurationParser {
// MARK: General // MARK: General
sessionBuilder.cipher = optCipher ?? .aes128cbc // FIXME: non-optional breaks PUSH_REPLY sessionBuilder.cipher = optCipher
sessionBuilder.digest = optDigest ?? .sha1 // FIXME: non-optional breaks PUSH_REPLY sessionBuilder.digest = optDigest
sessionBuilder.compressionFraming = optCompressionFraming ?? .disabled // FIXME: non-optional breaks PUSH_REPLY sessionBuilder.compressionFraming = optCompressionFraming
sessionBuilder.compressionAlgorithm = optCompressionAlgorithm ?? .disabled sessionBuilder.compressionAlgorithm = optCompressionAlgorithm
sessionBuilder.ca = optCA sessionBuilder.ca = optCA
sessionBuilder.clientCertificate = optClientCertificate sessionBuilder.clientCertificate = optClientCertificate

View File

@ -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`. /// The way to create a `SessionProxy.Configuration` object for a `SessionProxy`.
public struct ConfigurationBuilder { public struct ConfigurationBuilder {
// MARK: General // MARK: General
/// The cipher algorithm for data encryption. /// The cipher algorithm for data encryption.
public var cipher: SessionProxy.Cipher public var cipher: SessionProxy.Cipher?
/// The digest algorithm for HMAC. /// The digest algorithm for HMAC.
public var digest: SessionProxy.Digest public var digest: SessionProxy.Digest?
/// Compression framing, disabled by default. /// Compression framing, disabled by default.
public var compressionFraming: SessionProxy.CompressionFraming public var compressionFraming: SessionProxy.CompressionFraming?
/// Compression algorithm, disabled by default. /// Compression algorithm, disabled by default.
public var compressionAlgorithm: SessionProxy.CompressionAlgorithm? public var compressionAlgorithm: SessionProxy.CompressionAlgorithm?
@ -210,31 +219,6 @@ extension SessionProxy {
public init() { 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. Builds a `SessionProxy.Configuration` object.
@ -265,19 +249,36 @@ extension SessionProxy {
searchDomain: searchDomain 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`. /// The immutable configuration for `SessionProxy`.
public struct Configuration: Codable { public struct Configuration: Codable {
/// - Seealso: `SessionProxy.ConfigurationBuilder.cipher` /// - Seealso: `SessionProxy.ConfigurationBuilder.cipher`
public let cipher: Cipher public let cipher: Cipher?
/// - Seealso: `SessionProxy.ConfigurationBuilder.digest` /// - Seealso: `SessionProxy.ConfigurationBuilder.digest`
public let digest: Digest public let digest: Digest?
/// - Seealso: `SessionProxy.ConfigurationBuilder.compressionFraming` /// - Seealso: `SessionProxy.ConfigurationBuilder.compressionFraming`
public let compressionFraming: CompressionFraming public let compressionFraming: CompressionFraming?
/// - Seealso: `SessionProxy.ConfigurationBuilder.compressionAlgorithm` /// - Seealso: `SessionProxy.ConfigurationBuilder.compressionAlgorithm`
public let compressionAlgorithm: CompressionAlgorithm? public let compressionAlgorithm: CompressionAlgorithm?
@ -362,6 +363,23 @@ extension SessionProxy {
builder.searchDomain = searchDomain builder.searchDomain = searchDomain
return builder 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
}
} }
} }

View File

@ -196,7 +196,7 @@ public class SessionProxy {
if let tlsWrap = configuration.tlsWrap { if let tlsWrap = configuration.tlsWrap {
switch tlsWrap.strategy { switch tlsWrap.strategy {
case .auth: case .auth:
controlChannel = try ControlChannel(withAuthKey: tlsWrap.key, digest: configuration.digest) controlChannel = try ControlChannel(withAuthKey: tlsWrap.key, digest: configuration.fallbackDigest)
case .crypt: case .crypt:
controlChannel = try ControlChannel(withCryptKey: tlsWrap.key) controlChannel = try ControlChannel(withCryptKey: tlsWrap.key)
@ -634,8 +634,8 @@ public class SessionProxy {
log.debug("CA MD5 is: \(caMD5)") log.debug("CA MD5 is: \(caMD5)")
return try? PIAHardReset( return try? PIAHardReset(
caMd5Digest: caMD5, caMd5Digest: caMD5,
cipher: configuration.cipher, cipher: configuration.fallbackCipher,
digest: configuration.digest digest: configuration.fallbackDigest
).encodedData() ).encodedData()
} }
return nil return nil
@ -923,10 +923,7 @@ public class SessionProxy {
reply = optionalReply reply = optionalReply
log.debug("Received PUSH_REPLY: \"\(reply.maskedDescription)\"") log.debug("Received PUSH_REPLY: \"\(reply.maskedDescription)\"")
// FIXME: non-optional breaks PUSH_REPLY if let framing = reply.options.compressionFraming, let compression = reply.options.compressionAlgorithm {
// if let framing = reply.options.compressionFraming, let compression = reply.options.compressionAlgorithm {
let framing = reply.options.compressionFraming
if framing != .disabled, let compression = reply.options.compressionAlgorithm {
switch compression { switch compression {
case .disabled: case .disabled:
break break
@ -1043,20 +1040,18 @@ public class SessionProxy {
log.debug("Set up encryption") 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 let pushedFraming = pushReply.options.compressionFraming
// FIXME: non-optional breaks PUSH_REPLY if let negFraming = pushedFraming {
// if let negFraming = pushedFraming { log.info("\tNegotiated compression framing: \(negFraming)")
// log.info("\tNegotiated compression framing: \(negFraming)") }
// }
let pushedCompression = pushReply.options.compressionAlgorithm let pushedCompression = pushReply.options.compressionAlgorithm
if let negCompression = pushedCompression { if let negCompression = pushedCompression {
log.info("\tNegotiated compression algorithm: \(negCompression)") 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 { if let negPing = pushReply.options.keepAliveInterval {
log.info("\tNegotiated keep-alive: \(negPing) seconds") log.info("\tNegotiated keep-alive: \(negPing) seconds")
} }
@ -1064,9 +1059,8 @@ public class SessionProxy {
let bridge: EncryptionBridge let bridge: EncryptionBridge
do { do {
bridge = try EncryptionBridge( bridge = try EncryptionBridge(
// FIXME: non-optional breaks PUSH_REPLY pushedCipher ?? configuration.fallbackCipher,
pushedCipher ?? configuration.cipher, configuration.fallbackDigest,
configuration.digest,
auth, auth,
sessionId, sessionId,
remoteSessionId remoteSessionId
@ -1080,8 +1074,7 @@ public class SessionProxy {
encrypter: bridge.encrypter(), encrypter: bridge.encrypter(),
decrypter: bridge.decrypter(), decrypter: bridge.decrypter(),
peerId: pushReply.options.peerId ?? PacketPeerIdDisabled, peerId: pushReply.options.peerId ?? PacketPeerIdDisabled,
// FIXME: non-optional breaks PUSH_REPLY compressionFraming: (pushedFraming ?? configuration.fallbackCompressionFraming).native,
compressionFraming: (pushedFraming ?? configuration.compressionFraming).native,
compressionAlgorithm: (pushedCompression ?? configuration.compressionAlgorithm ?? .disabled).native, compressionAlgorithm: (pushedCompression ?? configuration.compressionAlgorithm ?? .disabled).native,
maxPackets: link?.packetBufferSize ?? 200, maxPackets: link?.packetBufferSize ?? 200,
usesReplayProtection: CoreConfiguration.usesReplayProtection usesReplayProtection: CoreConfiguration.usesReplayProtection

View File

@ -84,8 +84,8 @@ class AppExtensionTests: XCTestCase {
let K = TunnelKitProvider.Configuration.Keys.self let K = TunnelKitProvider.Configuration.Keys.self
XCTAssertEqual(proto?.providerConfiguration?[K.appGroup] as? String, appGroup) XCTAssertEqual(proto?.providerConfiguration?[K.appGroup] as? String, appGroup)
XCTAssertEqual(proto?.providerConfiguration?[K.cipherAlgorithm] as? String, cfg.sessionConfiguration.cipher.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.digestAlgorithm] as? String, cfg.sessionConfiguration.digest?.rawValue)
XCTAssertEqual(proto?.providerConfiguration?[K.ca] as? String, cfg.sessionConfiguration.ca?.pem) XCTAssertEqual(proto?.providerConfiguration?[K.ca] as? String, cfg.sessionConfiguration.ca?.pem)
XCTAssertEqual(proto?.providerConfiguration?[K.mtu] as? Int, cfg.mtu) XCTAssertEqual(proto?.providerConfiguration?[K.mtu] as? Int, cfg.mtu)
XCTAssertEqual(proto?.providerConfiguration?[K.renegotiatesAfter] as? TimeInterval, cfg.sessionConfiguration.renegotiatesAfter) XCTAssertEqual(proto?.providerConfiguration?[K.renegotiatesAfter] as? TimeInterval, cfg.sessionConfiguration.renegotiatesAfter)

View File

@ -28,8 +28,8 @@ import XCTest
private extension SessionReply { private extension SessionReply {
func debug() { func debug() {
print("Compression framing: \(options.compressionFraming.description ?? "none")") print("Compression framing: \(options.compressionFraming?.description ?? "disabled")")
print("Compression algorithm: \(options.compressionAlgorithm?.description ?? "none")") print("Compression algorithm: \(options.compressionAlgorithm?.description ?? "disabled")")
print("IPv4: \(options.ipv4?.description ?? "none")") print("IPv4: \(options.ipv4?.description ?? "none")")
print("IPv6: \(options.ipv6?.description ?? "none")") print("IPv6: \(options.ipv6?.description ?? "none")")
print("DNS: \(options.dnsServers?.description ?? "none")") print("DNS: \(options.dnsServers?.description ?? "none")")