Merge branch 'complete-error-mapping'
This commit is contained in:
commit
d354a672d5
|
@ -100,10 +100,22 @@ extension TunnelKitProvider {
|
|||
case socketActivity
|
||||
|
||||
/// Credentials authentication failed.
|
||||
case authenticationFailed
|
||||
case authentication
|
||||
|
||||
/// TLS could not be initialized (e.g. malformed CA or client PEMs).
|
||||
case tlsInitialization
|
||||
|
||||
/// TLS server verification failed.
|
||||
case tlsServerVerification
|
||||
|
||||
/// TLS handshake failed.
|
||||
case tlsFailed
|
||||
case tlsHandshake
|
||||
|
||||
/// The encryption logic could not be initialized (e.g. PRNG, algorithms).
|
||||
case encryptionInitialization
|
||||
|
||||
/// Data encryption/decryption failed.
|
||||
case encryptionData
|
||||
|
||||
/// Tunnel timed out.
|
||||
case timeout
|
||||
|
|
|
@ -575,7 +575,7 @@ extension TunnelKitProvider: SessionProxyDelegate {
|
|||
|
||||
extension TunnelKitProvider {
|
||||
|
||||
// MARK: Helpers
|
||||
// MARK: Logging
|
||||
|
||||
private func configureLogging(debug: Bool, customFormat: String? = nil) {
|
||||
let logLevel: SwiftyBeaver.Level = (debug ? .debug : .info)
|
||||
|
@ -603,38 +603,6 @@ extension TunnelKitProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private func setErrorStatus(with error: Error) {
|
||||
guard let lastErrorKey = cfg.lastErrorKey else {
|
||||
return
|
||||
}
|
||||
let providerError: ProviderError
|
||||
if let se = error as? SessionError {
|
||||
switch se {
|
||||
case .badCredentials:
|
||||
providerError = .authenticationFailed
|
||||
|
||||
case .peerVerification, .tlsError:
|
||||
providerError = .tlsFailed
|
||||
|
||||
case .negotiationTimeout, .pingTimeout:
|
||||
providerError = .timeout
|
||||
|
||||
default:
|
||||
providerError = .unexpectedReply
|
||||
}
|
||||
} else {
|
||||
providerError = error as? ProviderError ?? .linkError
|
||||
}
|
||||
defaults?.set(providerError.rawValue, forKey: lastErrorKey)
|
||||
}
|
||||
|
||||
private func clearErrorStatus() {
|
||||
guard let lastErrorKey = cfg.lastErrorKey else {
|
||||
return
|
||||
}
|
||||
defaults?.removeObject(forKey: lastErrorKey)
|
||||
}
|
||||
|
||||
private func logCurrentSSID() {
|
||||
if let ssid = observer.currentWifiNetworkName() {
|
||||
log.debug("Current SSID: '\(ssid)'")
|
||||
|
@ -647,4 +615,59 @@ extension TunnelKitProvider {
|
|||
// let anyObject = object as AnyObject
|
||||
// return Unmanaged<AnyObject>.passUnretained(anyObject).toOpaque()
|
||||
// }
|
||||
|
||||
// MARK: Errors
|
||||
|
||||
private func setErrorStatus(with error: Error) {
|
||||
guard let lastErrorKey = cfg.lastErrorKey else {
|
||||
return
|
||||
}
|
||||
defaults?.set(unifiedError(from: error).rawValue, forKey: lastErrorKey)
|
||||
}
|
||||
|
||||
private func clearErrorStatus() {
|
||||
guard let lastErrorKey = cfg.lastErrorKey else {
|
||||
return
|
||||
}
|
||||
defaults?.removeObject(forKey: lastErrorKey)
|
||||
}
|
||||
|
||||
private func unifiedError(from error: Error) -> ProviderError {
|
||||
if let te = error.tunnelKitErrorCode() {
|
||||
switch te {
|
||||
case .cryptoBoxRandomGenerator, .cryptoBoxAlgorithm:
|
||||
return .encryptionInitialization
|
||||
|
||||
case .cryptoBoxEncryption, .cryptoBoxHMAC:
|
||||
return .encryptionData
|
||||
|
||||
case .tlsBoxCA, .tlsBoxClientCertificate, .tlsBoxClientKey:
|
||||
return .tlsInitialization
|
||||
|
||||
case .tlsBoxServerCertificate, .tlsBoxServerEKU:
|
||||
return .tlsServerVerification
|
||||
|
||||
case .tlsBoxHandshake:
|
||||
return .tlsHandshake
|
||||
|
||||
case .dataPathOverflow, .dataPathPeerIdMismatch:
|
||||
return .unexpectedReply
|
||||
}
|
||||
} else if let se = error as? SessionError {
|
||||
switch se {
|
||||
case .negotiationTimeout, .pingTimeout:
|
||||
return .timeout
|
||||
|
||||
case .badCredentials:
|
||||
return .authentication
|
||||
|
||||
case .failedLinkWrite:
|
||||
return .linkError
|
||||
|
||||
default:
|
||||
return .unexpectedReply
|
||||
}
|
||||
}
|
||||
return error as? ProviderError ?? .linkError
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSString *const TunnelKitErrorDomain;
|
||||
extern NSString *const TunnelKitErrorKey;
|
||||
|
||||
typedef NS_ENUM(NSInteger, TunnelKitErrorCode) {
|
||||
TunnelKitErrorCodeCryptoBoxRandomGenerator = 101,
|
||||
|
@ -45,9 +46,9 @@ typedef NS_ENUM(NSInteger, TunnelKitErrorCode) {
|
|||
TunnelKitErrorCodeCryptoBoxAlgorithm = 104,
|
||||
TunnelKitErrorCodeTLSBoxCA = 201,
|
||||
TunnelKitErrorCodeTLSBoxHandshake = 202,
|
||||
TunnelKitErrorCodeTLSBoxGeneric = 203,
|
||||
TunnelKitErrorCodeTLSBoxClientCertificate = 204,
|
||||
TunnelKitErrorCodeTLSBoxClientKey = 205,
|
||||
TunnelKitErrorCodeTLSBoxServerCertificate = 206,
|
||||
TunnelKitErrorCodeDataPathOverflow = 301,
|
||||
TunnelKitErrorCodeDataPathPeerIdMismatch = 302
|
||||
};
|
||||
|
|
|
@ -36,4 +36,5 @@
|
|||
|
||||
#import "Errors.h"
|
||||
|
||||
NSString *const TunnelKitErrorDomain = @"TunnelKitNative";
|
||||
NSString *const TunnelKitErrorDomain = @"TunnelKitNative";
|
||||
NSString *const TunnelKitErrorKey = @"TunnelKitErrorKey";
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import __TunnelKitNative
|
||||
|
||||
/// The possible errors raised/thrown during `SessionProxy` operation.
|
||||
public enum SessionError: String, Error {
|
||||
|
@ -43,9 +44,6 @@ public enum SessionError: String, Error {
|
|||
/// The negotiation timed out.
|
||||
case negotiationTimeout
|
||||
|
||||
/// The peer failed to verify.
|
||||
case peerVerification
|
||||
|
||||
/// The VPN session id is missing.
|
||||
case missingSessionId
|
||||
|
||||
|
@ -55,9 +53,6 @@ public enum SessionError: String, Error {
|
|||
/// The connection key is wrong or wasn't expected.
|
||||
case badKey
|
||||
|
||||
/// The TLS negotiation failed.
|
||||
case tlsError
|
||||
|
||||
/// The control packet has an incorrect prefix payload.
|
||||
case wrongControlDataPrefix
|
||||
|
||||
|
@ -73,3 +68,18 @@ public enum SessionError: String, Error {
|
|||
/// The server couldn't ping back before timeout.
|
||||
case pingTimeout
|
||||
}
|
||||
|
||||
extension Error {
|
||||
func isTunnelKitError() -> Bool {
|
||||
let te = self as NSError
|
||||
return te.domain == TunnelKitErrorDomain
|
||||
}
|
||||
|
||||
func tunnelKitErrorCode() -> TunnelKitErrorCode? {
|
||||
let te = self as NSError
|
||||
guard te.domain == TunnelKitErrorDomain else {
|
||||
return nil
|
||||
}
|
||||
return TunnelKitErrorCode(rawValue: te.code)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,18 +41,6 @@ import __TunnelKitNative
|
|||
|
||||
private let log = SwiftyBeaver.self
|
||||
|
||||
private extension Error {
|
||||
func isTunnelError() -> Bool {
|
||||
let te = self as NSError
|
||||
return te.domain == TunnelKitErrorDomain
|
||||
}
|
||||
|
||||
func isDataPathOverflow() -> Bool {
|
||||
let te = self as NSError
|
||||
return te.domain == TunnelKitErrorDomain && te.code == TunnelKitErrorCode.dataPathOverflow.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
/// Observes major events notified by a `SessionProxy`.
|
||||
public protocol SessionProxyDelegate: class {
|
||||
|
||||
|
@ -209,8 +197,9 @@ public class SessionProxy {
|
|||
|
||||
// WARNING: runs in notification source queue (we know it's "queue", but better be safe than sorry)
|
||||
tlsObserver = NotificationCenter.default.addObserver(forName: .TLSBoxPeerVerificationError, object: nil, queue: nil) { (notification) in
|
||||
let error = notification.userInfo?[TunnelKitErrorKey] as? Error
|
||||
self.queue.async {
|
||||
self.deferStop(.shutdown, SessionError.peerVerification)
|
||||
self.deferStop(.shutdown, error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -614,7 +603,15 @@ public class SessionProxy {
|
|||
return
|
||||
}
|
||||
|
||||
guard let cipherTextOut = try? negotiationKey.tls.pullCipherText() else {
|
||||
let cipherTextOut: Data
|
||||
do {
|
||||
cipherTextOut = try negotiationKey.tls.pullCipherText()
|
||||
} catch let e {
|
||||
if let _ = e.tunnelKitErrorCode() {
|
||||
log.error("TLS.auth: Failed pulling ciphertext (error: \(e))")
|
||||
shutdown(error: e)
|
||||
return
|
||||
}
|
||||
log.verbose("TLS.auth: Still can't pull ciphertext")
|
||||
return
|
||||
}
|
||||
|
@ -637,7 +634,15 @@ public class SessionProxy {
|
|||
log.debug("TLS.ifconfig: Put plaintext (PUSH_REQUEST)")
|
||||
try? negotiationKey.tls.putPlainText("PUSH_REQUEST\0")
|
||||
|
||||
guard let cipherTextOut = try? negotiationKey.tls.pullCipherText() else {
|
||||
let cipherTextOut: Data
|
||||
do {
|
||||
cipherTextOut = try negotiationKey.tls.pullCipherText()
|
||||
} catch let e {
|
||||
if let _ = e.tunnelKitErrorCode() {
|
||||
log.error("TLS.auth: Failed pulling ciphertext (error: \(e))")
|
||||
shutdown(error: e)
|
||||
return
|
||||
}
|
||||
log.verbose("TLS.ifconfig: Still can't pull ciphertext")
|
||||
return
|
||||
}
|
||||
|
@ -717,8 +722,16 @@ public class SessionProxy {
|
|||
return
|
||||
}
|
||||
|
||||
guard let cipherTextOut = try? negotiationKey.tls.pullCipherText() else {
|
||||
deferStop(.shutdown, SessionError.tlsError)
|
||||
let cipherTextOut: Data
|
||||
do {
|
||||
cipherTextOut = try negotiationKey.tls.pullCipherText()
|
||||
} catch let e {
|
||||
if let _ = e.tunnelKitErrorCode() {
|
||||
log.error("TLS.connect: Failed pulling ciphertext (error: \(e))")
|
||||
shutdown(error: e)
|
||||
return
|
||||
}
|
||||
deferStop(.shutdown, e)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -745,9 +758,18 @@ public class SessionProxy {
|
|||
log.debug("TLS.connect: Put received ciphertext (\(cipherTextIn.count) bytes)")
|
||||
try? negotiationKey.tls.putCipherText(cipherTextIn)
|
||||
|
||||
if let cipherTextOut = try? negotiationKey.tls.pullCipherText() {
|
||||
let cipherTextOut: Data
|
||||
do {
|
||||
cipherTextOut = try negotiationKey.tls.pullCipherText()
|
||||
log.debug("TLS.connect: Send pulled ciphertext (\(cipherTextOut.count) bytes)")
|
||||
enqueueControlPackets(code: .controlV1, key: negotiationKey.id, payload: cipherTextOut)
|
||||
} catch let e {
|
||||
if let _ = e.tunnelKitErrorCode() {
|
||||
log.error("TLS.connect: Failed pulling ciphertext (error: \(e))")
|
||||
shutdown(error: e)
|
||||
return
|
||||
}
|
||||
log.verbose("TLS.connect: No available ciphertext to pull")
|
||||
}
|
||||
|
||||
if negotiationKey.shouldOnTLSConnect() {
|
||||
|
@ -976,7 +998,7 @@ public class SessionProxy {
|
|||
|
||||
tunnel?.writePackets(decryptedPackets, completionHandler: nil)
|
||||
} catch let e {
|
||||
guard !e.isTunnelError() else {
|
||||
guard !e.isTunnelKitError() else {
|
||||
deferStop(.shutdown, e)
|
||||
return
|
||||
}
|
||||
|
@ -1011,7 +1033,7 @@ public class SessionProxy {
|
|||
// log.verbose("Data: \(encryptedPackets.count) packets successfully written to LINK")
|
||||
}
|
||||
} catch let e {
|
||||
guard !e.isTunnelError() else {
|
||||
guard !e.isTunnelKitError() else {
|
||||
deferStop(.shutdown, e)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -51,7 +51,10 @@ static BOOL TLSBoxIsOpenSSLLoaded;
|
|||
|
||||
int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
||||
if (!ok) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:TLSBoxPeerVerificationErrorNotification object:nil];
|
||||
NSError *error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxCA);
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:TLSBoxPeerVerificationErrorNotification
|
||||
object:nil
|
||||
userInfo:@{TunnelKitErrorKey: error}];
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
@ -201,7 +204,7 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
|||
}
|
||||
if ((ret < 0) && !BIO_should_retry(self.bioCipherTextOut)) {
|
||||
if (error) {
|
||||
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxGeneric);
|
||||
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxHandshake);
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
|
@ -219,7 +222,7 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
|||
}
|
||||
if ((ret < 0) && !BIO_should_retry(self.bioPlainText)) {
|
||||
if (error) {
|
||||
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxGeneric);
|
||||
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxHandshake);
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
|
@ -241,7 +244,7 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
|||
const int ret = BIO_write(self.bioCipherTextIn, text, (int)length);
|
||||
if (ret != length) {
|
||||
if (error) {
|
||||
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxGeneric);
|
||||
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxHandshake);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
@ -262,7 +265,7 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
|||
const int ret = BIO_write(self.bioPlainText, text, (int)length);
|
||||
if (ret != length) {
|
||||
if (error) {
|
||||
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxGeneric);
|
||||
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxHandshake);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue