diff --git a/Passepartout-iOS/Global/ParsingResult+Alerts.swift b/Passepartout-iOS/Global/ParsingResult+Alerts.swift index 6f174a51..a7b2f357 100644 --- a/Passepartout-iOS/Global/ParsingResult+Alerts.swift +++ b/Passepartout-iOS/Global/ParsingResult+Alerts.swift @@ -41,7 +41,7 @@ extension ConfigurationParser.ParsingResult { log.debug("Parsing configuration URL: \(url)") do { result = try ConfigurationParser.parsed(fromURL: url, passphrase: passphrase) - } catch let e as ConfigurationParser.ParsingError { + } catch let e as ConfigurationError { switch e { case .encryptionPassphrase, .unableToDecrypt(_): let alert = Macros.alert(url.normalizedFilename, L10n.ParsedFile.Alerts.EncryptionPassphrase.message) @@ -85,7 +85,7 @@ extension ConfigurationParser.ParsingResult { vc.present(alert, animated: true, completion: nil) } - static func alertImportWarning(url: URL, in vc: UIViewController, withWarning warning: ConfigurationParser.ParsingError, completionHandler: @escaping (Bool) -> Void) { + static func alertImportWarning(url: URL, in vc: UIViewController, withWarning warning: ConfigurationError, completionHandler: @escaping (Bool) -> Void) { let message = details(forWarning: warning) let alert = Macros.alert(url.normalizedFilename, L10n.ParsedFile.Alerts.PotentiallyUnsupported.message(message)) alert.addDefaultAction(L10n.Global.ok) { @@ -98,8 +98,12 @@ extension ConfigurationParser.ParsingResult { } private static func localizedMessage(forError error: Error) -> String { - if let appError = error as? ConfigurationParser.ParsingError { + if let appError = error as? ConfigurationError { switch appError { + case .malformed(let option): + log.error("Could not parse configuration URL: malformed option, \(option)") + return L10n.ParsedFile.Alerts.Malformed.message(option) + case .missingConfiguration(let option): log.error("Could not parse configuration URL: missing configuration, \(option)") return L10n.ParsedFile.Alerts.Missing.message(option) @@ -116,8 +120,11 @@ extension ConfigurationParser.ParsingResult { return L10n.ParsedFile.Alerts.Parsing.message(error.localizedDescription) } - private static func details(forWarning warning: ConfigurationParser.ParsingError) -> String { + private static func details(forWarning warning: ConfigurationError) -> String { switch warning { + case .malformed(let option): + return option + case .missingConfiguration(let option): return option diff --git a/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift b/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift index 47fcae07..08330cf1 100644 --- a/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/WizardHostViewController.swift @@ -99,10 +99,12 @@ class WizardHostViewController: UITableViewController, TableModelHost { guard let result = parsingResult else { return } - - let profile = HostConnectionProfile(title: enteredTitle, hostname: result.hostname) - var builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: result.configuration) - builder.endpointProtocols = result.protocols + guard let hostname = result.configuration.hostname else { + return + } + + let profile = HostConnectionProfile(title: enteredTitle, hostname: hostname) + let builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: result.configuration) profile.parameters = builder.build() let service = TransientStore.shared.service diff --git a/Passepartout/Resources/en.lproj/Localizable.strings b/Passepartout/Resources/en.lproj/Localizable.strings index 0e39e44f..f795f677 100644 --- a/Passepartout/Resources/en.lproj/Localizable.strings +++ b/Passepartout/Resources/en.lproj/Localizable.strings @@ -56,6 +56,7 @@ "wizards.host.sections.existing.header" = "Existing profiles"; "wizards.host.alerts.existing.message" = "A host profile with the same title already exists. Replace it?"; +"parsed_file.alerts.malformed.message" = "The configuration file contains a malformed option (%@)."; "parsed_file.alerts.missing.message" = "The configuration file lacks a required option (%@)."; "parsed_file.alerts.unsupported.message" = "The configuration file contains an unsupported option (%@)."; "parsed_file.alerts.potentially_unsupported.message" = "The configuration file is correct but contains a potentially unsupported option (%@).\n\nConnectivity may break depending on server settings."; diff --git a/Passepartout/Sources/Model/Profiles/HostConnectionProfile.swift b/Passepartout/Sources/Model/Profiles/HostConnectionProfile.swift index 3c4d06ab..07e45220 100644 --- a/Passepartout/Sources/Model/Profiles/HostConnectionProfile.swift +++ b/Passepartout/Sources/Model/Profiles/HostConnectionProfile.swift @@ -36,7 +36,7 @@ public class HostConnectionProfile: ConnectionProfile, Codable, Equatable { public init(title: String, hostname: String) { self.title = title self.hostname = hostname - let sessionConfiguration = SessionProxy.ConfigurationBuilder(ca: CryptoContainer(pem: "")).build() + let sessionConfiguration = SessionProxy.ConfigurationBuilder().build() parameters = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionConfiguration).build() } @@ -55,7 +55,9 @@ public class HostConnectionProfile: ConnectionProfile, Codable, Equatable { } public func generate(from configuration: TunnelKitProvider.Configuration, preferences: Preferences) throws -> TunnelKitProvider.Configuration { - precondition(!parameters.endpointProtocols.isEmpty) + guard let endpointProtocols = parameters.sessionConfiguration.endpointProtocols, !endpointProtocols.isEmpty else { + preconditionFailure("No endpointProtocols") + } // XXX: copy paste, error prone var builder = parameters.builder() @@ -91,7 +93,7 @@ public extension HostConnectionProfile { } var protocols: [EndpointProtocol] { - return parameters.endpointProtocols + return parameters.sessionConfiguration.endpointProtocols ?? [] } var canCustomizeEndpoint: Bool { diff --git a/Passepartout/Sources/Model/Profiles/ProviderConnectionProfile.swift b/Passepartout/Sources/Model/Profiles/ProviderConnectionProfile.swift index 8d3fbcb2..4a587805 100644 --- a/Passepartout/Sources/Model/Profiles/ProviderConnectionProfile.swift +++ b/Passepartout/Sources/Model/Profiles/ProviderConnectionProfile.swift @@ -130,10 +130,10 @@ public class ProviderConnectionProfile: ConnectionProfile, Codable, Equatable { } if let proto = manualProtocol { - builder.endpointProtocols = [proto] + builder.sessionConfiguration.endpointProtocols = [proto] } else { - builder.endpointProtocols = preset.configuration.endpointProtocols -// builder.endpointProtocols = [ + builder.sessionConfiguration.endpointProtocols = preset.configuration.sessionConfiguration.endpointProtocols +// builder.sessionConfiguration.endpointProtocols = [ // EndpointProtocol(.udp, 8080), // EndpointProtocol(.tcp, 443) // ] @@ -163,7 +163,7 @@ public extension ProviderConnectionProfile { } var protocols: [EndpointProtocol] { - return preset?.configuration.endpointProtocols ?? [] + return preset?.configuration.sessionConfiguration.endpointProtocols ?? [] } var canCustomizeEndpoint: Bool { diff --git a/Passepartout/Sources/Model/TransientStore.swift b/Passepartout/Sources/Model/TransientStore.swift index bf243697..0f284a19 100644 --- a/Passepartout/Sources/Model/TransientStore.swift +++ b/Passepartout/Sources/Model/TransientStore.swift @@ -63,7 +63,7 @@ public class TransientStore { } public static var baseVPNConfiguration: TunnelKitProvider.ConfigurationBuilder { - let sessionBuilder = SessionProxy.ConfigurationBuilder(ca: CryptoContainer(pem: "")) + let sessionBuilder = SessionProxy.ConfigurationBuilder() var builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) builder.mtu = 1250 builder.shouldDebug = true diff --git a/Passepartout/Sources/Services/InfrastructurePreset.swift b/Passepartout/Sources/Services/InfrastructurePreset.swift index a9c217d6..51674b85 100644 --- a/Passepartout/Sources/Services/InfrastructurePreset.swift +++ b/Passepartout/Sources/Services/InfrastructurePreset.swift @@ -79,7 +79,7 @@ public struct InfrastructurePreset: Codable { public let configuration: TunnelKitProvider.Configuration public func hasProtocol(_ proto: EndpointProtocol) -> Bool { - return configuration.endpointProtocols.index(of: proto) != nil + return configuration.sessionConfiguration.endpointProtocols?.index(of: proto) != nil } // MARK: Codable @@ -91,50 +91,56 @@ public struct InfrastructurePreset: Codable { comment = try container.decode(String.self, forKey: .comment) let cfgContainer = try container.nestedContainer(keyedBy: ConfigurationKeys.self, forKey: .configuration) - let ca = try cfgContainer.decode(CryptoContainer.self, forKey: .ca) - var sessionBuilder = SessionProxy.ConfigurationBuilder(ca: ca) + var sessionBuilder = SessionProxy.ConfigurationBuilder() sessionBuilder.cipher = try cfgContainer.decode(SessionProxy.Cipher.self, forKey: .cipher) if let digest = try cfgContainer.decodeIfPresent(SessionProxy.Digest.self, forKey: .digest) { sessionBuilder.digest = digest } - sessionBuilder.clientCertificate = try cfgContainer.decodeIfPresent(CryptoContainer.self, forKey: .clientCertificate) - sessionBuilder.clientKey = try cfgContainer.decodeIfPresent(CryptoContainer.self, forKey: .clientKey) sessionBuilder.compressionFraming = try cfgContainer.decode(SessionProxy.CompressionFraming.self, forKey: .compressionFraming) sessionBuilder.compressionAlgorithm = try cfgContainer.decodeIfPresent(SessionProxy.CompressionAlgorithm.self, forKey: .compressionAlgorithm) ?? .disabled + sessionBuilder.ca = try cfgContainer.decode(CryptoContainer.self, forKey: .ca) + sessionBuilder.clientCertificate = try cfgContainer.decodeIfPresent(CryptoContainer.self, forKey: .clientCertificate) + sessionBuilder.clientKey = try cfgContainer.decodeIfPresent(CryptoContainer.self, forKey: .clientKey) sessionBuilder.tlsWrap = try cfgContainer.decodeIfPresent(SessionProxy.TLSWrap.self, forKey: .tlsWrap) sessionBuilder.keepAliveInterval = try cfgContainer.decodeIfPresent(TimeInterval.self, forKey: .keepAliveSeconds) sessionBuilder.renegotiatesAfter = try cfgContainer.decodeIfPresent(TimeInterval.self, forKey: .renegotiatesAfterSeconds) - sessionBuilder.usesPIAPatches = try cfgContainer.decodeIfPresent(Bool.self, forKey: .usesPIAPatches) ?? false + sessionBuilder.endpointProtocols = try cfgContainer.decode([EndpointProtocol].self, forKey: .endpointProtocols) sessionBuilder.checksEKU = try cfgContainer.decodeIfPresent(Bool.self, forKey: .checksEKU) ?? false sessionBuilder.randomizeEndpoint = try cfgContainer.decodeIfPresent(Bool.self, forKey: .randomizeEndpoint) ?? false + sessionBuilder.usesPIAPatches = try cfgContainer.decodeIfPresent(Bool.self, forKey: .usesPIAPatches) ?? false - var builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) - builder.endpointProtocols = try cfgContainer.decode([EndpointProtocol].self, forKey: .endpointProtocols) + let builder = TunnelKitProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) configuration = builder.build() } public func encode(to encoder: Encoder) throws { + guard let ca = configuration.sessionConfiguration.ca else { + fatalError("Could not encode nil ca") + } + guard let endpointProtocols = configuration.sessionConfiguration.endpointProtocols else { + fatalError("Could not encode nil endpointProtocols") + } + var container = encoder.container(keyedBy: PresetKeys.self) try container.encode(id, forKey: .id) try container.encode(name, forKey: .name) try container.encode(comment, forKey: .comment) var cfgContainer = container.nestedContainer(keyedBy: ConfigurationKeys.self, forKey: .configuration) - try cfgContainer.encode(configuration.endpointProtocols, forKey: .endpointProtocols) - try cfgContainer.encode(configuration.sessionConfiguration.cipher, forKey: .cipher) try cfgContainer.encode(configuration.sessionConfiguration.digest, forKey: .digest) - try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.ca, forKey: .ca) - try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.clientCertificate, forKey: .clientCertificate) - try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.clientKey, forKey: .clientKey) try cfgContainer.encode(configuration.sessionConfiguration.compressionFraming, forKey: .compressionFraming) try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.compressionAlgorithm, forKey: .compressionAlgorithm) + try cfgContainer.encode(ca, forKey: .ca) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.clientCertificate, forKey: .clientCertificate) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.clientKey, forKey: .clientKey) try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.tlsWrap, forKey: .tlsWrap) try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.keepAliveInterval, forKey: .keepAliveSeconds) try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.renegotiatesAfter, forKey: .renegotiatesAfterSeconds) - try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.usesPIAPatches, forKey: .usesPIAPatches) + try cfgContainer.encode(endpointProtocols, forKey: .endpointProtocols) try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.checksEKU, forKey: .checksEKU) try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.randomizeEndpoint, forKey: .randomizeEndpoint) + try cfgContainer.encodeIfPresent(configuration.sessionConfiguration.usesPIAPatches, forKey: .usesPIAPatches) } } diff --git a/Passepartout/Sources/SwiftGen+Strings.swift b/Passepartout/Sources/SwiftGen+Strings.swift index 1a757f8a..4fd56f69 100644 --- a/Passepartout/Sources/SwiftGen+Strings.swift +++ b/Passepartout/Sources/SwiftGen+Strings.swift @@ -419,6 +419,12 @@ public enum L10n { /// Please enter the encryption passphrase. public static let message = L10n.tr("Localizable", "parsed_file.alerts.encryption_passphrase.message") } + public enum Malformed { + /// The configuration file contains a malformed option (%@). + public static func message(_ p1: String) -> String { + return L10n.tr("Localizable", "parsed_file.alerts.malformed.message", p1) + } + } public enum Missing { /// The configuration file lacks a required option (%@). public static func message(_ p1: String) -> String { diff --git a/Podfile b/Podfile index ef66588a..a85882b9 100644 --- a/Podfile +++ b/Podfile @@ -3,10 +3,10 @@ platform :ios, '11.0' use_frameworks! def shared_pods - #pod 'TunnelKit', '~> 1.5.0' - #pod 'TunnelKit/LZO', '~> 1.5.0' - pod 'TunnelKit', :git => 'https://github.com/keeshux/tunnelkit', :commit => 'ccb6329' - pod 'TunnelKit/LZO', :git => 'https://github.com/keeshux/tunnelkit', :commit => 'ccb6329' + #pod 'TunnelKit', '~> 1.6.0' + #pod 'TunnelKit/LZO', '~> 1.6.0' + pod 'TunnelKit', :git => 'https://github.com/keeshux/tunnelkit', :commit => '7333ea2' + pod 'TunnelKit/LZO', :git => 'https://github.com/keeshux/tunnelkit', :commit => '7333ea2' #pod 'TunnelKit', :path => '../../personal/tunnelkit' #pod 'TunnelKit/LZO', :path => '../../personal/tunnelkit' end diff --git a/Podfile.lock b/Podfile.lock index e7a13ffc..6e681249 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -2,21 +2,21 @@ PODS: - MBProgressHUD (1.1.0) - OpenSSL-Apple (1.1.0i.2) - SwiftyBeaver (1.7.0) - - TunnelKit (1.5.3): - - TunnelKit/AppExtension (= 1.5.3) - - TunnelKit/Core (= 1.5.3) - - TunnelKit/AppExtension (1.5.3): + - TunnelKit (1.6.0): + - TunnelKit/AppExtension (= 1.6.0) + - TunnelKit/Core (= 1.6.0) + - TunnelKit/AppExtension (1.6.0): - SwiftyBeaver - TunnelKit/Core - - TunnelKit/Core (1.5.3): + - TunnelKit/Core (1.6.0): - OpenSSL-Apple (~> 1.1.0i.2) - SwiftyBeaver - - TunnelKit/LZO (1.5.3) + - TunnelKit/LZO (1.6.0) DEPENDENCIES: - MBProgressHUD - - TunnelKit (from `https://github.com/keeshux/tunnelkit`, commit `ccb6329`) - - TunnelKit/LZO (from `https://github.com/keeshux/tunnelkit`, commit `ccb6329`) + - TunnelKit (from `https://github.com/keeshux/tunnelkit`, commit `7333ea2`) + - TunnelKit/LZO (from `https://github.com/keeshux/tunnelkit`, commit `7333ea2`) SPEC REPOS: https://github.com/cocoapods/specs.git: @@ -26,20 +26,20 @@ SPEC REPOS: EXTERNAL SOURCES: TunnelKit: - :commit: ccb6329 + :commit: 7333ea2 :git: https://github.com/keeshux/tunnelkit CHECKOUT OPTIONS: TunnelKit: - :commit: ccb6329 + :commit: 7333ea2 :git: https://github.com/keeshux/tunnelkit SPEC CHECKSUMS: MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9 OpenSSL-Apple: 37a8c0b04df4bb8971deef4671cc29222861319c SwiftyBeaver: 4cc0080d2e23f980652e28978db11a5c9da39165 - TunnelKit: 21f5d336698d2de6126232f6b5d7e9be4d999af0 + TunnelKit: cd10ff6f4368e82414a72e6a111dae369252964e -PODFILE CHECKSUM: cc0564f2cee9d614d40e73ea13d19c96e0ddb1f2 +PODFILE CHECKSUM: ab7fe69f86411d5848909b12bfeb846d738d004d COCOAPODS: 1.6.1 diff --git a/README.md b/README.md index 506d63b5..d1b174bb 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # [Passepartout][about-website] ![iOS 11+](https://img.shields.io/badge/ios-11+-green.svg) -[![TunnelKit 1.5.x](https://img.shields.io/badge/tunnelkit-1.5-d69c68.svg)][dep-tunnelkit] +[![TunnelKit 1.6.x](https://img.shields.io/badge/tunnelkit-1.6-d69c68.svg)][dep-tunnelkit] [![License GPLv3](https://img.shields.io/badge/license-GPLv3-lightgray.svg)](LICENSE) [![Join Reddit](https://img.shields.io/badge/discuss-Reddit-orange.svg)][about-reddit] [![Join Telegram](https://img.shields.io/badge/chat-Telegram-blue.svg)][about-telegram]