Retry auth once without local options

Hack around picky server implementations.

Fixes #95
This commit is contained in:
Davide De Rosa 2019-05-01 10:37:39 +02:00
parent 14b7f08fb5
commit 037f08ed62
3 changed files with 54 additions and 27 deletions

View File

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Fixed
- Authentication failure due to local options. [#95](https://github.com/keeshux/tunnelkit/issues/95)
## 1.7.0 (2019-04-28) ## 1.7.0 (2019-04-28)
### Changed ### Changed

View File

@ -66,6 +66,8 @@ extension SessionProxy {
let password: ZeroingData? let password: ZeroingData?
var withLocalOptions: Bool
init(_ username: String?, _ password: String?) throws { init(_ username: String?, _ password: String?) throws {
preMaster = try SecureRandom.safeData(length: CoreConfiguration.preMasterLength) preMaster = try SecureRandom.safeData(length: CoreConfiguration.preMasterLength)
random1 = try SecureRandom.safeData(length: CoreConfiguration.randomLength) random1 = try SecureRandom.safeData(length: CoreConfiguration.randomLength)
@ -80,6 +82,8 @@ extension SessionProxy {
self.password = nil self.password = nil
} }
withLocalOptions = true
controlBuffer = Z() controlBuffer = Z()
} }
@ -95,11 +99,12 @@ extension SessionProxy {
raw.append(random2) raw.append(random2)
// options string // options string
let optsString: String
if withLocalOptions {
var opts = [ var opts = [
"V4", "V4",
"dev-type tun" "dev-type tun"
] ]
//////
if let comp = options.compressionFraming { if let comp = options.compressionFraming {
switch comp { switch comp {
case .compLZO: case .compLZO:
@ -123,7 +128,10 @@ extension SessionProxy {
} }
opts.append("key-method 2") opts.append("key-method 2")
opts.append("tls-client") opts.append("tls-client")
let optsString = opts.joined(separator: ",") optsString = opts.joined(separator: ",")
} else {
optsString = "V0 UNDEF"
}
log.debug("TLS.auth: Local options: \(optsString)") log.debug("TLS.auth: Local options: \(optsString)")
raw.appendSized(Z(optsString, nullTerminated: true)) raw.appendSized(Z(optsString, nullTerminated: true))

View File

@ -106,6 +106,8 @@ public class SessionProxy {
private var tlsObserver: NSObjectProtocol? private var tlsObserver: NSObjectProtocol?
private var withLocalOptions: Bool
private var keys: [UInt8: SessionKey] private var keys: [UInt8: SessionKey]
private var oldKeys: [SessionKey] private var oldKeys: [SessionKey]
@ -190,6 +192,7 @@ public class SessionProxy {
self.configuration = configuration self.configuration = configuration
self.cachesURL = cachesURL self.cachesURL = cachesURL
withLocalOptions = true
keys = [:] keys = [:]
oldKeys = [] oldKeys = []
negotiationKeyIdx = 0 negotiationKeyIdx = 0
@ -676,6 +679,7 @@ public class SessionProxy {
do { do {
authenticator = try Authenticator(credentials?.username, pushReply?.options.authToken ?? credentials?.password) authenticator = try Authenticator(credentials?.username, pushReply?.options.authToken ?? credentials?.password)
authenticator?.withLocalOptions = withLocalOptions
try authenticator?.putAuth(into: negotiationKey.tls, options: configuration) try authenticator?.putAuth(into: negotiationKey.tls, options: configuration)
} catch let e { } catch let e {
deferStop(.shutdown, e) deferStop(.shutdown, e)
@ -908,6 +912,15 @@ public class SessionProxy {
// Ruby: handle_ctrl_msg // Ruby: handle_ctrl_msg
private func handleControlMessage(_ message: String) { private func handleControlMessage(_ message: String) {
guard !message.hasPrefix("AUTH_FAILED") else { guard !message.hasPrefix("AUTH_FAILED") else {
// XXX: retry without client options
if authenticator?.withLocalOptions ?? false {
log.warning("Authentication failure, retrying without local options")
withLocalOptions = false
deferStop(.reconnect, SessionError.badCredentials)
return
}
deferStop(.shutdown, SessionError.badCredentials) deferStop(.shutdown, SessionError.badCredentials)
return return
} }