From 0b79ce41940ff923780a9abd4cb5bdd4fb037644 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Wed, 24 Oct 2018 10:40:48 +0200 Subject: [PATCH] Handle server-initiated SOFT_RESET --- TunnelKit/Sources/Core/SessionProxy.swift | 27 ++++++++++++++++------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/TunnelKit/Sources/Core/SessionProxy.swift b/TunnelKit/Sources/Core/SessionProxy.swift index 53a6d94..3e62a4e 100644 --- a/TunnelKit/Sources/Core/SessionProxy.swift +++ b/TunnelKit/Sources/Core/SessionProxy.swift @@ -466,6 +466,9 @@ public class SessionProxy { // deferStop(.shutdown, e) // return } + if (code == .softResetV1) && (negotiationKey.state != .softReset) { + softReset(isServerInitiated: true) + } sendAck(for: controlPacket) @@ -574,8 +577,12 @@ public class SessionProxy { } // Ruby: soft_reset - private func softReset() { - log.debug("Send soft reset") + private func softReset(isServerInitiated: Bool) { + if isServerInitiated { + log.debug("Handle soft reset") + } else { + log.debug("Send soft reset") + } resetControlChannel(forNewSession: false) negotiationKeyIdx = max(1, (negotiationKeyIdx + 1) % ProtocolMacros.numberOfKeys) @@ -586,7 +593,9 @@ public class SessionProxy { negotiationKey.state = .softReset negotiationKey.softReset = true loopNegotiation() - enqueueControlPackets(code: .softResetV1, key: UInt8(negotiationKeyIdx), payload: Data()) + if !isServerInitiated { + enqueueControlPackets(code: .softResetV1, key: UInt8(negotiationKeyIdx), payload: Data()) + } } // Ruby: on_tls_connect @@ -667,7 +676,7 @@ public class SessionProxy { let elapsed = -negotiationKey.startTime.timeIntervalSinceNow if (elapsed > renegotiatesAfter) { log.debug("Renegotiating after \(elapsed) seconds") - softReset() + softReset(isServerInitiated: false) } } @@ -683,15 +692,16 @@ public class SessionProxy { // Ruby: handle_ctrl_pkt private func handleControlPacket(_ packet: ControlPacket) { - guard (packet.key == negotiationKey.id) else { + guard packet.key == negotiationKey.id else { log.error("Bad key in control packet (\(packet.key) != \(negotiationKey.id))") // deferStop(.shutdown, SessionError.badKey) return } - if (((packet.code == .hardResetServerV2) && (negotiationKey.state == .hardReset)) || - ((packet.code == .softResetV1) && (negotiationKey.state == .softReset))) { - + // start new TLS handshake + if ((packet.code == .hardResetServerV2) && (negotiationKey.state == .hardReset)) || + ((packet.code == .softResetV1) && (negotiationKey.state == .softReset)) { + if negotiationKey.state == .hardReset { controlChannel.remoteSessionId = packet.sessionId } @@ -738,6 +748,7 @@ public class SessionProxy { log.debug("TLS.connect: Pulled ciphertext (\(cipherTextOut.count) bytes)") enqueueControlPackets(code: .controlV1, key: negotiationKey.id, payload: cipherTextOut) } + // exchange TLS ciphertext else if ((packet.code == .controlV1) && (negotiationKey.state == .tls)) { guard let remoteSessionId = controlChannel.remoteSessionId else { log.error("No remote sessionId found in packet (control packets before server HARD_RESET)")