Increase components granularity

Minimize target dependency on OpenSSL (easier to drop later).

Outside of OpenVPN tunnel extension, OpenSSL is only used to
decrypt encrypted private keys in CryptoContainer (found in
TunnelKitOpenVPNCore, therefore "temporarily" dependent on
CTunnelKitOpenVPNAppExtension for TLSBox/CryptoBox).
This commit is contained in:
Davide De Rosa 2021-11-07 21:54:05 +01:00
parent d1f70171cb
commit 50064fc3d0
101 changed files with 472 additions and 327 deletions

View File

@ -169,7 +169,7 @@ M69t86apMrAxkUxVJAWLRBd9fbYyzJgTW61tFqXWTZpiz6bhuWApSEzaHcL3/f5l
-----END PRIVATE KEY----- -----END PRIVATE KEY-----
""") """)
static func make(hostname: String, port: UInt16, socketType: SocketType) -> OpenVPNTunnelProvider.Configuration { static func make(hostname: String, port: UInt16, socketType: SocketType) -> OpenVPNProvider.Configuration {
var sessionBuilder = OpenVPN.ConfigurationBuilder() var sessionBuilder = OpenVPN.ConfigurationBuilder()
sessionBuilder.ca = ca sessionBuilder.ca = ca
sessionBuilder.cipher = .aes128cbc sessionBuilder.cipher = .aes128cbc
@ -181,7 +181,7 @@ M69t86apMrAxkUxVJAWLRBd9fbYyzJgTW61tFqXWTZpiz6bhuWApSEzaHcL3/f5l
sessionBuilder.clientCertificate = clientCertificate sessionBuilder.clientCertificate = clientCertificate
sessionBuilder.clientKey = clientKey sessionBuilder.clientKey = clientKey
sessionBuilder.mtu = 1350 sessionBuilder.mtu = 1350
var builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) var builder = OpenVPNProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build())
builder.shouldDebug = true builder.shouldDebug = true
builder.masksPrivateData = false builder.masksPrivateData = false
return builder.build() return builder.build()

View File

@ -23,7 +23,7 @@
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>. // along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
// //
import TunnelKitOpenVPN import TunnelKitOpenVPNAppExtension
class PacketTunnelProvider: OpenVPNTunnelProvider { class PacketTunnelProvider: OpenVPNTunnelProvider {
} }

View File

@ -29,10 +29,10 @@
0E1108B11F77B9F900A92462 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E1108AF1F77B9F900A92462 /* Main.storyboard */; }; 0E1108B11F77B9F900A92462 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E1108AF1F77B9F900A92462 /* Main.storyboard */; };
0E1108B31F77B9F900A92462 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E1108B21F77B9F900A92462 /* Assets.xcassets */; }; 0E1108B31F77B9F900A92462 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0E1108B21F77B9F900A92462 /* Assets.xcassets */; };
0E1108B61F77B9F900A92462 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E1108B41F77B9F900A92462 /* LaunchScreen.storyboard */; }; 0E1108B61F77B9F900A92462 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0E1108B41F77B9F900A92462 /* LaunchScreen.storyboard */; };
0E80FA5127396F5F000F5A45 /* TunnelKitOpenVPNAppExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 0E80FA5027396F5F000F5A45 /* TunnelKitOpenVPNAppExtension */; };
0E80FA5327396F66000F5A45 /* TunnelKitOpenVPNAppExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 0E80FA5227396F66000F5A45 /* TunnelKitOpenVPNAppExtension */; };
0EFD5B312727250500C7D5FD /* TunnelKitOpenVPN in Frameworks */ = {isa = PBXBuildFile; productRef = 0EFD5B302727250500C7D5FD /* TunnelKitOpenVPN */; }; 0EFD5B312727250500C7D5FD /* TunnelKitOpenVPN in Frameworks */ = {isa = PBXBuildFile; productRef = 0EFD5B302727250500C7D5FD /* TunnelKitOpenVPN */; };
0EFD5B332727250B00C7D5FD /* TunnelKitOpenVPN in Frameworks */ = {isa = PBXBuildFile; productRef = 0EFD5B322727250B00C7D5FD /* TunnelKitOpenVPN */; }; 0EFD5B332727250B00C7D5FD /* TunnelKitOpenVPN in Frameworks */ = {isa = PBXBuildFile; productRef = 0EFD5B322727250B00C7D5FD /* TunnelKitOpenVPN */; };
0EFD5B352727250E00C7D5FD /* TunnelKitOpenVPN in Frameworks */ = {isa = PBXBuildFile; productRef = 0EFD5B342727250E00C7D5FD /* TunnelKitOpenVPN */; };
0EFD5B372727251200C7D5FD /* TunnelKitOpenVPN in Frameworks */ = {isa = PBXBuildFile; productRef = 0EFD5B362727251200C7D5FD /* TunnelKitOpenVPN */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -166,8 +166,8 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0EFD5B352727250E00C7D5FD /* TunnelKitOpenVPN in Frameworks */,
0E0541A125A2343500EFC5FF /* NetworkExtension.framework in Frameworks */, 0E0541A125A2343500EFC5FF /* NetworkExtension.framework in Frameworks */,
0E80FA5127396F5F000F5A45 /* TunnelKitOpenVPNAppExtension in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -183,7 +183,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0EFD5B372727251200C7D5FD /* TunnelKitOpenVPN in Frameworks */, 0E80FA5327396F66000F5A45 /* TunnelKitOpenVPNAppExtension in Frameworks */,
0E05427825A239C600EFC5FF /* NetworkExtension.framework in Frameworks */, 0E05427825A239C600EFC5FF /* NetworkExtension.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -343,7 +343,7 @@
); );
name = "TunnelKitDemoTunnel-iOS"; name = "TunnelKitDemoTunnel-iOS";
packageProductDependencies = ( packageProductDependencies = (
0EFD5B342727250E00C7D5FD /* TunnelKitOpenVPN */, 0E80FA5027396F5F000F5A45 /* TunnelKitOpenVPNAppExtension */,
); );
productName = Tunnel; productName = Tunnel;
productReference = 0E05419F25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS.appex */; productReference = 0E05419F25A2343500EFC5FF /* TunnelKitDemoTunnel-iOS.appex */;
@ -386,7 +386,7 @@
); );
name = "TunnelKitDemoTunnel-macOS"; name = "TunnelKitDemoTunnel-macOS";
packageProductDependencies = ( packageProductDependencies = (
0EFD5B362727251200C7D5FD /* TunnelKitOpenVPN */, 0E80FA5227396F66000F5A45 /* TunnelKitOpenVPNAppExtension */,
); );
productName = Tunnel; productName = Tunnel;
productReference = 0E05427725A239C600EFC5FF /* TunnelKitDemoTunnel-macOS.appex */; productReference = 0E05427725A239C600EFC5FF /* TunnelKitDemoTunnel-macOS.appex */;
@ -1032,6 +1032,14 @@
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
0E80FA5027396F5F000F5A45 /* TunnelKitOpenVPNAppExtension */ = {
isa = XCSwiftPackageProductDependency;
productName = TunnelKitOpenVPNAppExtension;
};
0E80FA5227396F66000F5A45 /* TunnelKitOpenVPNAppExtension */ = {
isa = XCSwiftPackageProductDependency;
productName = TunnelKitOpenVPNAppExtension;
};
0EFD5B302727250500C7D5FD /* TunnelKitOpenVPN */ = { 0EFD5B302727250500C7D5FD /* TunnelKitOpenVPN */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = TunnelKitOpenVPN; productName = TunnelKitOpenVPN;
@ -1040,14 +1048,6 @@
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = TunnelKitOpenVPN; productName = TunnelKitOpenVPN;
}; };
0EFD5B342727250E00C7D5FD /* TunnelKitOpenVPN */ = {
isa = XCSwiftPackageProductDependency;
productName = TunnelKitOpenVPN;
};
0EFD5B362727251200C7D5FD /* TunnelKitOpenVPN */ = {
isa = XCSwiftPackageProductDependency;
productName = TunnelKitOpenVPN;
};
/* End XCSwiftPackageProductDependency section */ /* End XCSwiftPackageProductDependency section */
}; };
rootObject = 0E17D7F01F730D9F009EE129 /* Project object */; rootObject = 0E17D7F01F730D9F009EE129 /* Project object */;

View File

@ -6,7 +6,7 @@
"repositoryURL": "https://github.com/keeshux/openssl-apple", "repositoryURL": "https://github.com/keeshux/openssl-apple",
"state": { "state": {
"branch": null, "branch": null,
"revision": "1889136399ba40e4fc358cfe7fafef7170aac3f7", "revision": "37043e7c92c9fb348d1d668b0402148c9fa9873c",
"version": "1.1.112" "version": "1.1.112"
} }
}, },

View File

@ -12,11 +12,7 @@ let package = Package(
// Products define the executables and libraries a package produces, and make them visible to other packages. // Products define the executables and libraries a package produces, and make them visible to other packages.
.library( .library(
name: "TunnelKit", name: "TunnelKit",
targets: [ targets: ["TunnelKit"]
"TunnelKitCore",
"TunnelKitAppExtension",
"TunnelKitManager"
]
), ),
.library( .library(
name: "TunnelKitIKE", name: "TunnelKitIKE",
@ -26,6 +22,10 @@ let package = Package(
name: "TunnelKitOpenVPN", name: "TunnelKitOpenVPN",
targets: ["TunnelKitOpenVPN"] targets: ["TunnelKitOpenVPN"]
), ),
.library(
name: "TunnelKitOpenVPNAppExtension",
targets: ["TunnelKitOpenVPNAppExtension"]
),
.library( .library(
name: "TunnelKitLZO", name: "TunnelKitLZO",
targets: ["TunnelKitLZO"] targets: ["TunnelKitLZO"]
@ -40,41 +40,71 @@ let package = Package(
targets: [ targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on. // Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "TunnelKit",
dependencies: [
"TunnelKitCore",
"TunnelKitManager"
]
),
.target( .target(
name: "TunnelKitCore", name: "TunnelKitCore",
dependencies: [ dependencies: [
"_TunnelKitUtils", "__TunnelKitUtils",
"_TunnelKitCoreObjC", "CTunnelKitCore",
"SwiftyBeaver"]), "SwiftyBeaver"
]),
.target( .target(
name: "_TunnelKitCoreObjC", name: "TunnelKitManager",
dependencies: []), dependencies: [
"TunnelKitCore"
]),
.target( .target(
name: "TunnelKitAppExtension", name: "TunnelKitAppExtension",
dependencies: [ dependencies: [
"TunnelKitCore", "TunnelKitCore",
"SwiftyBeaver"]), "SwiftyBeaver"
.target( ]),
name: "TunnelKitManager",
dependencies: [
"TunnelKitCore"]),
.target( .target(
name: "TunnelKitIKE", name: "TunnelKitIKE",
dependencies: [ dependencies: [
"TunnelKitCore", "TunnelKitCore",
"TunnelKitManager"]), "TunnelKitManager"
]),
.target( .target(
name: "TunnelKitOpenVPN", name: "TunnelKitOpenVPN",
dependencies: [ dependencies: [
"TunnelKitCore", "TunnelKitOpenVPNCore",
"_TunnelKitOpenVPNObjC", "TunnelKitOpenVPNManager"
"TunnelKitAppExtension", ]),
"TunnelKitManager"]), //
.target( .target(
name: "_TunnelKitOpenVPNObjC", name: "TunnelKitOpenVPNCore",
dependencies: [ dependencies: [
"openssl-apple", "TunnelKitCore",
"_TunnelKitCoreObjC"]), "CTunnelKitOpenVPNCore",
"CTunnelKitOpenVPNProtocol" // FIXME: remove dependency on TLSBox
]),
.target(
name: "TunnelKitOpenVPNManager",
dependencies: [
"TunnelKitManager",
"TunnelKitOpenVPNCore"
]),
.target(
name: "TunnelKitOpenVPNProtocol",
dependencies: [
"TunnelKitOpenVPNCore",
"CTunnelKitOpenVPNProtocol"
]),
.target(
name: "TunnelKitOpenVPNAppExtension",
dependencies: [
"TunnelKitAppExtension",
"TunnelKitOpenVPNCore",
"TunnelKitOpenVPNManager",
"TunnelKitOpenVPNProtocol"
]),
.target( .target(
name: "TunnelKitLZO", name: "TunnelKitLZO",
dependencies: [], dependencies: [],
@ -84,9 +114,24 @@ let package = Package(
"lib/README.LZO", "lib/README.LZO",
"lib/testmini.c" "lib/testmini.c"
]), ]),
//
.target( .target(
name: "_TunnelKitUtils", name: "CTunnelKitCore",
dependencies: []), dependencies: []),
.target(
name: "CTunnelKitOpenVPNCore",
dependencies: []),
.target(
name: "CTunnelKitOpenVPNProtocol",
dependencies: [
"CTunnelKitCore",
"CTunnelKitOpenVPNCore",
"openssl-apple"
]),
.target(
name: "__TunnelKitUtils",
dependencies: []),
//
.testTarget( .testTarget(
name: "TunnelKitCoreTests", name: "TunnelKitCoreTests",
dependencies: [ dependencies: [
@ -95,7 +140,8 @@ let package = Package(
.testTarget( .testTarget(
name: "TunnelKitOpenVPNTests", name: "TunnelKitOpenVPNTests",
dependencies: [ dependencies: [
"TunnelKitOpenVPN", "TunnelKitOpenVPNCore",
"TunnelKitOpenVPNAppExtension",
"TunnelKitLZO" "TunnelKitLZO"
], ],
resources: [ resources: [

View File

@ -0,0 +1 @@

View File

@ -36,8 +36,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "CompressionFramingNative.h" @import CTunnelKitOpenVPNCore;
#import "CompressionAlgorithmNative.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN

View File

@ -0,0 +1,2 @@
@_exported import TunnelKitCore
@_exported import TunnelKitManager

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import _TunnelKitCoreObjC import CTunnelKitCore
extension Error { extension Error {
public func isTunnelKitError() -> Bool { public func isTunnelKitError() -> Bool {

View File

@ -36,8 +36,8 @@
import Foundation import Foundation
import Security.SecRandom import Security.SecRandom
import _TunnelKitCoreObjC import CTunnelKitCore
import _TunnelKitUtils import __TunnelKitUtils
/// :nodoc: /// :nodoc:
public enum SecureRandomError: Error { public enum SecureRandomError: Error {

View File

@ -35,7 +35,7 @@
// //
import Foundation import Foundation
import _TunnelKitCoreObjC import CTunnelKitCore
public func Z() -> ZeroingData { public func Z() -> ZeroingData {
return ZeroingData() return ZeroingData()

View File

@ -1 +1 @@
../../_TunnelKitCoreObjC/include/Errors.h ../../CTunnelKitCore/include/Errors.h

View File

@ -1,151 +0,0 @@
//
// OpenVPNTunnelProvider+Interaction.swift
// TunnelKit
//
// Created by Davide De Rosa on 9/24/17.
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of TunnelKit.
//
// TunnelKit is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TunnelKit is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
//
// This file incorporates work covered by the following copyright and
// permission notice:
//
// Copyright (c) 2018-Present Private Internet Access
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
import Foundation
extension OpenVPNTunnelProvider {
// MARK: Interaction
/// The messages accepted by `OpenVPNTunnelProvider`.
public class Message: Equatable {
/// Requests a snapshot of the latest debug log. Returns the log data decoded from UTF-8.
public static let requestLog = Message(0xff)
/// Requests the current bytes count from data channel (if connected).
///
/// Data is 16 bytes: low 8 = received, high 8 = sent.
public static let dataCount = Message(0xfe)
/// Requests the configuration pulled from the server (if connected and available).
///
/// Data is JSON (Decodable).
public static let serverConfiguration = Message(0xfd)
/// The underlying raw message `Data` to forward to the tunnel via IPC.
public let data: Data
private init(_ byte: UInt8) {
data = Data([byte])
}
init(_ data: Data) {
self.data = data
}
// MARK: Equatable
/// :nodoc:
public static func ==(lhs: Message, rhs: Message) -> Bool {
return (lhs.data == rhs.data)
}
}
// mostly programming errors by host app
enum ProviderConfigurationError: Error {
/// A field in the `OpenVPNTunnelProvider.Configuration` provided is incorrect or incomplete.
case parameter(name: String)
/// Credentials are missing or inaccessible.
case credentials(details: String)
/// The pseudo-random number generator could not be initialized.
case prngInitialization
/// The TLS certificate could not be serialized.
case certificateSerialization
}
/// The errors causing a tunnel disconnection.
public enum ProviderError: String, Error {
/// Socket endpoint could not be resolved.
case dnsFailure
/// No more protocols available to try.
case exhaustedProtocols
/// Socket failed to reach active state.
case socketActivity
/// Credentials authentication failed.
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 tlsHandshake
/// The encryption logic could not be initialized (e.g. PRNG, algorithms).
case encryptionInitialization
/// Data encryption/decryption failed.
case encryptionData
/// The LZO engine failed.
case lzo
/// Server uses an unsupported compression algorithm.
case serverCompression
/// Tunnel timed out.
case timeout
/// An error occurred at the link level.
case linkError
/// Network routing information is missing or incomplete.
case routing
/// The current network changed (e.g. switched from WiFi to data connection).
case networkChanged
/// Default gateway could not be attained.
case gatewayUnattainable
/// Remove server has shut down.
case serverShutdown
/// The server replied in an unexpected way.
case unexpectedReply
}
}

View File

@ -0,0 +1,2 @@
@_exported import TunnelKitOpenVPNCore
@_exported import TunnelKitOpenVPNManager

View File

@ -39,6 +39,7 @@ import NetworkExtension
import SwiftyBeaver import SwiftyBeaver
import TunnelKitCore import TunnelKitCore
import TunnelKitAppExtension import TunnelKitAppExtension
import TunnelKitOpenVPNManager
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self
@ -73,7 +74,7 @@ class ConnectionStrategy {
private let resolvedAddresses: [String] private let resolvedAddresses: [String]
init(configuration: OpenVPNTunnelProvider.Configuration) { init(configuration: OpenVPNProvider.Configuration) {
hostname = configuration.sessionConfiguration.hostname hostname = configuration.sessionConfiguration.hostname
guard var endpointProtocols = configuration.sessionConfiguration.endpointProtocols else { guard var endpointProtocols = configuration.sessionConfiguration.endpointProtocols else {
fatalError("No endpoints provided") fatalError("No endpoints provided")
@ -170,7 +171,7 @@ class ConnectionStrategy {
guard let hostname = hostname else { guard let hostname = hostname else {
log.error("DNS resolution unavailable: no hostname provided!") log.error("DNS resolution unavailable: no hostname provided!")
completionHandler(nil, OpenVPNTunnelProvider.ProviderError.dnsFailure) completionHandler(nil, OpenVPNProviderError.dnsFailure)
return return
} }
log.debug("DNS resolve hostname: \(hostname.maskedDescription)") log.debug("DNS resolve hostname: \(hostname.maskedDescription)")
@ -187,7 +188,7 @@ class ConnectionStrategy {
guard self.hasEndpoint() else { guard self.hasEndpoint() else {
log.error("No endpoints available") log.error("No endpoints available")
completionHandler(nil, OpenVPNTunnelProvider.ProviderError.dnsFailure) completionHandler(nil, OpenVPNProviderError.dnsFailure)
return return
} }

View File

@ -27,7 +27,7 @@ import Foundation
import NetworkExtension import NetworkExtension
import TunnelKitCore import TunnelKitCore
import TunnelKitAppExtension import TunnelKitAppExtension
import _TunnelKitOpenVPNObjC import CTunnelKitOpenVPNProtocol
class NETCPLink: LinkInterface { class NETCPLink: LinkInterface {
private let impl: NWTCPConnection private let impl: NWTCPConnection

View File

@ -42,8 +42,12 @@ import SystemConfiguration.CaptiveNetwork
import CoreWLAN import CoreWLAN
#endif #endif
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import TunnelKitManager
import TunnelKitOpenVPNManager
import TunnelKitOpenVPNProtocol
import TunnelKitAppExtension import TunnelKitAppExtension
import CTunnelKitCore
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self
@ -117,7 +121,7 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
private lazy var defaults = UserDefaults(suiteName: appGroup) private lazy var defaults = UserDefaults(suiteName: appGroup)
private var cfg: Configuration! private var cfg: OpenVPNProvider.Configuration!
private var strategy: ConnectionStrategy! private var strategy: ConnectionStrategy!
@ -150,16 +154,16 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
// required configuration // required configuration
do { do {
guard let tunnelProtocol = protocolConfiguration as? NETunnelProviderProtocol else { guard let tunnelProtocol = protocolConfiguration as? NETunnelProviderProtocol else {
throw ProviderConfigurationError.parameter(name: "protocolConfiguration") throw OpenVPNProviderConfigurationError.parameter(name: "protocolConfiguration")
} }
guard let serverAddress = tunnelProtocol.serverAddress else { guard let serverAddress = tunnelProtocol.serverAddress else {
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.serverAddress") throw OpenVPNProviderConfigurationError.parameter(name: "protocolConfiguration.serverAddress")
} }
guard let providerConfiguration = tunnelProtocol.providerConfiguration else { guard let providerConfiguration = tunnelProtocol.providerConfiguration else {
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration") throw OpenVPNProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration")
} }
try appGroup = Configuration.appGroup(from: providerConfiguration) try appGroup = OpenVPNProvider.Configuration.appGroup(from: providerConfiguration)
try cfg = Configuration.parsed(from: providerConfiguration) try cfg = OpenVPNProvider.Configuration.parsed(from: providerConfiguration)
// inject serverAddress into sessionConfiguration.hostname // inject serverAddress into sessionConfiguration.hostname
if !serverAddress.isEmpty { if !serverAddress.isEmpty {
@ -171,7 +175,7 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
} }
} catch let e { } catch let e {
var message: String? var message: String?
if let te = e as? ProviderConfigurationError { if let te = e as? OpenVPNProviderConfigurationError {
switch te { switch te {
case .parameter(let name): case .parameter(let name):
message = "Tunnel configuration incomplete: \(name)" message = "Tunnel configuration incomplete: \(name)"
@ -217,7 +221,7 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
if let username = protocolConfiguration.username, let passwordReference = protocolConfiguration.passwordReference { if let username = protocolConfiguration.username, let passwordReference = protocolConfiguration.passwordReference {
let keychain = Keychain(group: appGroup) let keychain = Keychain(group: appGroup)
guard let password = try? keychain.password(for: username, reference: passwordReference) else { guard let password = try? keychain.password(for: username, reference: passwordReference) else {
completionHandler(ProviderConfigurationError.credentials(details: "keychain.password(for:, reference:)")) completionHandler(OpenVPNProviderConfigurationError.credentials(details: "keychain.password(for:, reference:)"))
return return
} }
credentials = OpenVPN.Credentials(username, password) credentials = OpenVPN.Credentials(username, password)
@ -229,7 +233,7 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
cfg.clearLastError(in: appGroup) cfg.clearLastError(in: appGroup)
guard OpenVPN.prepareRandomNumberGenerator(seedLength: prngSeedLength) else { guard OpenVPN.prepareRandomNumberGenerator(seedLength: prngSeedLength) else {
completionHandler(ProviderConfigurationError.prngInitialization) completionHandler(OpenVPNProviderConfigurationError.prngInitialization)
return return
} }
@ -292,7 +296,7 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
/// :nodoc: /// :nodoc:
open override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) { open override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
var response: Data? var response: Data?
switch Message(messageData) { switch OpenVPNProvider.Message(messageData) {
case .requestLog: case .requestLog:
response = memoryLog.description.data(using: .utf8) response = memoryLog.description.data(using: .utf8)
@ -398,7 +402,7 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
// from stopTunnel(), in which case we don't need to feed an error parameter to // from stopTunnel(), in which case we don't need to feed an error parameter to
// the stop completion handler // the stop completion handler
// //
pendingStartHandler?(error ?? ProviderError.socketActivity) pendingStartHandler?(error ?? OpenVPNProviderError.socketActivity)
pendingStartHandler = nil pendingStartHandler = nil
} }
// stopped intentionally // stopped intentionally
@ -476,7 +480,7 @@ extension OpenVPNTunnelProvider: GenericSocketDelegate {
// look for error causing shutdown // look for error causing shutdown
shutdownError = session.stopError shutdownError = session.stopError
if failure && (shutdownError == nil) { if failure && (shutdownError == nil) {
shutdownError = ProviderError.linkError shutdownError = OpenVPNProviderError.linkError
} }
didTimeoutNegotiation = (shutdownError as? OpenVPNError == .negotiationTimeout) didTimeoutNegotiation = (shutdownError as? OpenVPNError == .negotiationTimeout)
@ -522,7 +526,7 @@ extension OpenVPNTunnelProvider: GenericSocketDelegate {
public func socketHasBetterPath(_ socket: GenericSocket) { public func socketHasBetterPath(_ socket: GenericSocket) {
log.debug("Stopping tunnel due to a new better path") log.debug("Stopping tunnel due to a new better path")
logCurrentSSID() logCurrentSSID()
session?.reconnect(error: ProviderError.networkChanged) session?.reconnect(error: OpenVPNProviderError.networkChanged)
} }
} }
@ -683,7 +687,7 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate {
hasGateway = true hasGateway = true
} }
guard !isGateway || hasGateway else { guard !isGateway || hasGateway else {
session?.shutdown(error: ProviderError.gatewayUnattainable) session?.shutdown(error: OpenVPNProviderError.gatewayUnattainable)
return return
} }
@ -704,7 +708,7 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate {
case .tls: case .tls:
guard let dnsServers = cfg.sessionConfiguration.dnsServers else { guard let dnsServers = cfg.sessionConfiguration.dnsServers else {
session?.shutdown(error: ProviderError.dnsFailure) session?.shutdown(error: OpenVPNProviderError.dnsFailure)
return return
} }
guard let serverName = cfg.sessionConfiguration.dnsTLSServerName else { guard let serverName = cfg.sessionConfiguration.dnsTLSServerName else {
@ -848,7 +852,7 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate {
extension OpenVPNTunnelProvider { extension OpenVPNTunnelProvider {
private func tryNextEndpoint() -> Bool { private func tryNextEndpoint() -> Bool {
guard strategy.tryNextEndpoint() else { guard strategy.tryNextEndpoint() else {
disposeTunnel(error: ProviderError.exhaustedProtocols) disposeTunnel(error: OpenVPNProviderError.exhaustedProtocols)
return false return false
} }
return true return true
@ -900,10 +904,10 @@ extension OpenVPNTunnelProvider {
// MARK: Errors // MARK: Errors
private func setErrorStatus(with error: Error) { private func setErrorStatus(with error: Error) {
defaults?.set(unifiedError(from: error).rawValue, forKey: Configuration.lastErrorKey) defaults?.set(unifiedError(from: error).rawValue, forKey: OpenVPNProvider.Configuration.lastErrorKey)
} }
private func unifiedError(from error: Error) -> ProviderError { private func unifiedError(from error: Error) -> OpenVPNProviderError {
if let te = error.tunnelKitErrorCode() { if let te = error.tunnelKitErrorCode() {
switch te { switch te {
case .cryptoRandomGenerator, .cryptoAlgorithm: case .cryptoRandomGenerator, .cryptoAlgorithm:
@ -957,7 +961,7 @@ extension OpenVPNTunnelProvider {
return .unexpectedReply return .unexpectedReply
} }
} }
return error as? ProviderError ?? .linkError return error as? OpenVPNProviderError ?? .linkError
} }
} }

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import _TunnelKitOpenVPNObjC import CTunnelKitOpenVPNCore
extension OpenVPN { extension OpenVPN {
@ -40,7 +40,8 @@ extension OpenVPN {
/// Any other compression algorithm (unsupported). /// Any other compression algorithm (unsupported).
case other case other
var native: CompressionAlgorithmNative { /// :nodoc:
public var native: CompressionAlgorithmNative {
guard let val = CompressionAlgorithmNative(rawValue: rawValue) else { guard let val = CompressionAlgorithmNative(rawValue: rawValue) else {
fatalError("Unhandled CompressionAlgorithm bridging") fatalError("Unhandled CompressionAlgorithm bridging")
} }

View File

@ -24,7 +24,7 @@
// //
import Foundation import Foundation
import _TunnelKitOpenVPNObjC import CTunnelKitOpenVPNCore
extension OpenVPN { extension OpenVPN {
@ -43,7 +43,8 @@ extension OpenVPN {
/// Framing compatible with 2.4 `compress` (version 2, e.g. stub-v2). /// Framing compatible with 2.4 `compress` (version 2, e.g. stub-v2).
case compressV2 case compressV2
var native: CompressionFramingNative { /// :nodoc:
public var native: CompressionFramingNative {
guard let val = CompressionFramingNative(rawValue: rawValue) else { guard let val = CompressionFramingNative(rawValue: rawValue) else {
fatalError("Unhandled CompressionFraming bridging") fatalError("Unhandled CompressionFraming bridging")
} }

View File

@ -561,7 +561,9 @@ extension OpenVPN.Configuration {
// MARK: Encoding // MARK: Encoding
extension OpenVPN.Configuration { extension OpenVPN.Configuration {
func print() {
/// :nodoc:
public func print() {
guard let endpointProtocols = endpointProtocols else { guard let endpointProtocols = endpointProtocols else {
fatalError("No sessionConfiguration.endpointProtocols set") fatalError("No sessionConfiguration.endpointProtocols set")
} }

View File

@ -26,8 +26,8 @@
import Foundation import Foundation
import SwiftyBeaver import SwiftyBeaver
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import CTunnelKitCore
import _TunnelKitUtils import __TunnelKitUtils
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self
@ -38,7 +38,7 @@ extension OpenVPN {
// XXX: parsing is very optimistic // XXX: parsing is very optimistic
struct Regex { public struct Regex {
// MARK: General // MARK: General
@ -84,7 +84,8 @@ extension OpenVPN {
// MARK: Server // MARK: Server
static let authToken = NSRegularExpression("^auth-token +[a-zA-Z0-9/=+]+") /// :nodoc:
public static let authToken = NSRegularExpression("^auth-token +[a-zA-Z0-9/=+]+")
static let peerId = NSRegularExpression("^peer-id +[0-9]+") static let peerId = NSRegularExpression("^peer-id +[0-9]+")
@ -679,6 +680,7 @@ extension OpenVPN {
sessionBuilder.clientCertificate = optClientCertificate sessionBuilder.clientCertificate = optClientCertificate
if let clientKey = optClientKey, clientKey.isEncrypted { if let clientKey = optClientKey, clientKey.isEncrypted {
// FIXME: remove dependency on TLSBox
guard let passphrase = passphrase else { guard let passphrase = passphrase else {
throw ConfigurationError.encryptionPassphrase throw ConfigurationError.encryptionPassphrase
} }

View File

@ -35,7 +35,9 @@
// //
import Foundation import Foundation
import _TunnelKitOpenVPNObjC
// FIXME: remove dependency on TLSBox
import CTunnelKitOpenVPNProtocol
extension OpenVPN { extension OpenVPN {
@ -65,6 +67,7 @@ extension OpenVPN {
try pem.write(to: url, atomically: true, encoding: .ascii) try pem.write(to: url, atomically: true, encoding: .ascii)
} }
// FIXME: remove dependency on TLSBox
func decrypted(with passphrase: String) throws -> CryptoContainer { func decrypted(with passphrase: String) throws -> CryptoContainer {
let decryptedPEM = try TLSBox.decryptedPrivateKey(fromPEM: pem, passphrase: passphrase) let decryptedPEM = try TLSBox.decryptedPrivateKey(fromPEM: pem, passphrase: passphrase)
return CryptoContainer(pem: decryptedPEM) return CryptoContainer(pem: decryptedPEM)

View File

@ -0,0 +1,30 @@
//
// OpenVPN.swift
// TunnelKit
//
// Created by Davide De Rosa on 5/19/19.
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of TunnelKit.
//
// TunnelKit is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TunnelKit is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
//
import Foundation
/// Container for OpenVPN classes.
public class OpenVPN {
}

View File

@ -25,7 +25,7 @@
import Foundation import Foundation
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import CTunnelKitCore
extension OpenVPN { extension OpenVPN {
@ -61,7 +61,8 @@ extension OpenVPN {
private let secureData: ZeroingData private let secureData: ZeroingData
let direction: Direction? /// :nodoc:
public let direction: Direction?
/// Returns the encryption key. /// Returns the encryption key.
/// ///

View File

@ -1,5 +1,5 @@
// //
// OpenVPNTunnelProvider+Configuration.swift // OpenVPNProvider+Configuration.swift
// TunnelKit // TunnelKit
// //
// Created by Davide De Rosa on 10/23/17. // Created by Davide De Rosa on 10/23/17.
@ -38,20 +38,21 @@ import Foundation
import NetworkExtension import NetworkExtension
import SwiftyBeaver import SwiftyBeaver
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import TunnelKitAppExtension import TunnelKitManager
import _TunnelKitUtils import CTunnelKitCore
import __TunnelKitUtils
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self
extension OpenVPNTunnelProvider { extension OpenVPNProvider {
private struct ExtraKeys { private struct ExtraKeys {
static let appGroup = "appGroup" static let appGroup = "appGroup"
} }
// MARK: Configuration // MARK: Configuration
/// The way to create a `OpenVPNTunnelProvider.Configuration` object for the tunnel profile. /// The way to create a `OpenVPNProvider.Configuration` object for the tunnel profile.
public struct ConfigurationBuilder { public struct ConfigurationBuilder {
/// :nodoc: /// :nodoc:
@ -108,9 +109,9 @@ extension OpenVPNTunnelProvider {
} }
/** /**
Builds a `OpenVPNTunnelProvider.Configuration` object that will connect to the provided endpoint. Builds a `OpenVPNProvider.Configuration` object that will connect to the provided endpoint.
- Returns: A `OpenVPNTunnelProvider.Configuration` object with this builder and the additional method parameters. - Returns: A `OpenVPNProvider.Configuration` object with this builder and the additional method parameters.
*/ */
public func build() -> Configuration { public func build() -> Configuration {
return Configuration( return Configuration(
@ -125,35 +126,36 @@ extension OpenVPNTunnelProvider {
} }
} }
/// Offers a bridge between the abstract `OpenVPNTunnelProvider.ConfigurationBuilder` and a concrete `NETunnelProviderProtocol` profile. /// Offers a bridge between the abstract `OpenVPNProvider.ConfigurationBuilder` and a concrete `NETunnelProviderProtocol` profile.
public struct Configuration: Codable { public struct Configuration: Codable {
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.sessionConfiguration` /// - Seealso: `OpenVPNProvider.ConfigurationBuilder.sessionConfiguration`
public let sessionConfiguration: OpenVPN.Configuration public let sessionConfiguration: OpenVPN.Configuration
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.prefersResolvedAddresses` /// - Seealso: `OpenVPNProvider.ConfigurationBuilder.prefersResolvedAddresses`
public let prefersResolvedAddresses: Bool public let prefersResolvedAddresses: Bool
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.resolvedAddresses` /// - Seealso: `OpenVPNProvider.ConfigurationBuilder.resolvedAddresses`
public let resolvedAddresses: [String]? public let resolvedAddresses: [String]?
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.shouldDebug` /// - Seealso: `OpenVPNProvider.ConfigurationBuilder.shouldDebug`
public let shouldDebug: Bool public let shouldDebug: Bool
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.debugLogFormat` /// - Seealso: `OpenVPNProvider.ConfigurationBuilder.debugLogFormat`
public let debugLogFormat: String? public let debugLogFormat: String?
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.masksPrivateData` /// - Seealso: `OpenVPNProvider.ConfigurationBuilder.masksPrivateData`
public let masksPrivateData: Bool? public let masksPrivateData: Bool?
/// - Seealso: `OpenVPNTunnelProvider.ConfigurationBuilder.versionIdentifier` /// - Seealso: `OpenVPNProvider.ConfigurationBuilder.versionIdentifier`
public let versionIdentifier: String? public let versionIdentifier: String?
// MARK: Shortcuts // MARK: Shortcuts
static let debugLogFilename = "debug.log" static let debugLogFilename = "debug.log"
static let lastErrorKey = "TunnelKitLastError" /// :nodoc:
public static let lastErrorKey = "TunnelKitLastError"
fileprivate static let dataCountKey = "TunnelKitDataCount" fileprivate static let dataCountKey = "TunnelKitDataCount"
@ -192,11 +194,11 @@ extension OpenVPNTunnelProvider {
- Parameter in: The app group where to locate the error key. - Parameter in: The app group where to locate the error key.
- Returns: The last tunnel error, if any. - Returns: The last tunnel error, if any.
*/ */
public func lastError(in appGroup: String) -> ProviderError? { public func lastError(in appGroup: String) -> OpenVPNProviderError? {
guard let rawValue = UserDefaults(suiteName: appGroup)?.string(forKey: Configuration.lastErrorKey) else { guard let rawValue = UserDefaults(suiteName: appGroup)?.string(forKey: Configuration.lastErrorKey) else {
return nil return nil
} }
return ProviderError(rawValue: rawValue) return OpenVPNProviderError(rawValue: rawValue)
} }
/** /**
@ -231,26 +233,26 @@ extension OpenVPNTunnelProvider {
- Parameter from: The map to parse. - Parameter from: The map to parse.
- Returns: The parsed app group. - Returns: The parsed app group.
- Throws: `ProviderError.configuration` if `providerConfiguration` does not contain an app group. - Throws: `OpenVPNProviderError.configuration` if `providerConfiguration` does not contain an app group.
*/ */
public static func appGroup(from providerConfiguration: [String: Any]) throws -> String { public static func appGroup(from providerConfiguration: [String: Any]) throws -> String {
guard let appGroup = providerConfiguration[ExtraKeys.appGroup] as? String else { guard let appGroup = providerConfiguration[ExtraKeys.appGroup] as? String else {
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(ExtraKeys.appGroup)]") throw OpenVPNProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[\(ExtraKeys.appGroup)]")
} }
return appGroup return appGroup
} }
/** /**
Parses a new `OpenVPNTunnelProvider.Configuration` object from a provider configuration map. Parses a new `OpenVPNProvider.Configuration` object from a provider configuration map.
- Parameter from: The map to parse. - Parameter from: The map to parse.
- Returns: The parsed `OpenVPNTunnelProvider.Configuration` object. - Returns: The parsed `OpenVPNProvider.Configuration` object.
- Throws: `ProviderError.configuration` if `providerConfiguration` is incomplete. - Throws: `OpenVPNProviderError.configuration` if `providerConfiguration` is incomplete.
*/ */
public static func parsed(from providerConfiguration: [String: Any]) throws -> Configuration { public static func parsed(from providerConfiguration: [String: Any]) throws -> Configuration {
let cfg = try fromDictionary(OpenVPNTunnelProvider.Configuration.self, providerConfiguration) let cfg = try fromDictionary(OpenVPNProvider.Configuration.self, providerConfiguration)
guard !cfg.prefersResolvedAddresses || !(cfg.resolvedAddresses?.isEmpty ?? true) else { guard !cfg.prefersResolvedAddresses || !(cfg.resolvedAddresses?.isEmpty ?? true) else {
throw ProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[prefersResolvedAddresses] is true but no [resolvedAddresses]") throw OpenVPNProviderConfigurationError.parameter(name: "protocolConfiguration.providerConfiguration[prefersResolvedAddresses] is true but no [resolvedAddresses]")
} }
return cfg return cfg
} }
@ -280,7 +282,7 @@ extension OpenVPNTunnelProvider {
- Parameter context: The keychain context where to look for the password reference. - Parameter context: The keychain context where to look for the password reference.
- Parameter username: The username to authenticate with. - Parameter username: The username to authenticate with.
- Returns: The generated `NETunnelProviderProtocol` object. - Returns: The generated `NETunnelProviderProtocol` object.
- Throws: `ProviderError.credentials` if unable to store `credentials.password` to the `appGroup` keychain. - Throws: `OpenVPNProviderError.credentials` if unable to store `credentials.password` to the `appGroup` keychain.
*/ */
public func generatedTunnelProtocol( public func generatedTunnelProtocol(
withBundleIdentifier bundleIdentifier: String, withBundleIdentifier bundleIdentifier: String,
@ -302,7 +304,8 @@ extension OpenVPNTunnelProvider {
return protocolConfiguration return protocolConfiguration
} }
func print(appVersion: String?) { /// :nodoc:
public func print(appVersion: String?) {
if let appVersion = appVersion { if let appVersion = appVersion {
log.info("App version: \(appVersion)") log.info("App version: \(appVersion)")
} }
@ -315,15 +318,15 @@ extension OpenVPNTunnelProvider {
// MARK: Modification // MARK: Modification
extension OpenVPNTunnelProvider.Configuration { extension OpenVPNProvider.Configuration {
/** /**
Returns a `OpenVPNTunnelProvider.ConfigurationBuilder` to use this configuration as a starting point for a new one. Returns a `OpenVPNProvider.ConfigurationBuilder` to use this configuration as a starting point for a new one.
- Returns: An editable `OpenVPNTunnelProvider.ConfigurationBuilder` initialized with this configuration. - Returns: An editable `OpenVPNProvider.ConfigurationBuilder` initialized with this configuration.
*/ */
public func builder() -> OpenVPNTunnelProvider.ConfigurationBuilder { public func builder() -> OpenVPNProvider.ConfigurationBuilder {
var builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: sessionConfiguration) var builder = OpenVPNProvider.ConfigurationBuilder(sessionConfiguration: sessionConfiguration)
builder.prefersResolvedAddresses = prefersResolvedAddresses builder.prefersResolvedAddresses = prefersResolvedAddresses
builder.resolvedAddresses = resolvedAddresses builder.resolvedAddresses = resolvedAddresses
builder.shouldDebug = shouldDebug builder.shouldDebug = shouldDebug
@ -338,14 +341,14 @@ extension OpenVPNTunnelProvider.Configuration {
public extension UserDefaults { public extension UserDefaults {
@objc var dataCountArray: [Int]? { @objc var dataCountArray: [Int]? {
get { get {
return array(forKey: OpenVPNTunnelProvider.Configuration.dataCountKey) as? [Int] return array(forKey: OpenVPNProvider.Configuration.dataCountKey) as? [Int]
} }
set { set {
set(newValue, forKey: OpenVPNTunnelProvider.Configuration.dataCountKey) set(newValue, forKey: OpenVPNProvider.Configuration.dataCountKey)
} }
} }
func removeDataCountArray() { func removeDataCountArray() {
removeObject(forKey: OpenVPNTunnelProvider.Configuration.dataCountKey) removeObject(forKey: OpenVPNProvider.Configuration.dataCountKey)
} }
} }

View File

@ -0,0 +1,68 @@
//
// OpenVPNProvider+Interaction.swift
// TunnelKit
//
// Created by Davide De Rosa on 9/24/17.
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of TunnelKit.
//
// TunnelKit is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TunnelKit is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
//
// This file incorporates work covered by the following copyright and
// permission notice:
//
import Foundation
extension OpenVPNProvider {
/// The messages accepted by `OpenVPNProvider`.
public class Message: Equatable {
/// Requests a snapshot of the latest debug log. Returns the log data decoded from UTF-8.
public static let requestLog = Message(0xff)
/// Requests the current bytes count from data channel (if connected).
///
/// Data is 16 bytes: low 8 = received, high 8 = sent.
public static let dataCount = Message(0xfe)
/// Requests the configuration pulled from the server (if connected and available).
///
/// Data is JSON (Decodable).
public static let serverConfiguration = Message(0xfd)
/// The underlying raw message `Data` to forward to the tunnel via IPC.
public let data: Data
private init(_ byte: UInt8) {
data = Data([byte])
}
/// :nodoc:
public init(_ data: Data) {
self.data = data
}
// MARK: Equatable
/// :nodoc:
public static func ==(lhs: Message, rhs: Message) -> Bool {
return (lhs.data == rhs.data)
}
}
}

View File

@ -25,6 +25,7 @@
import Foundation import Foundation
import NetworkExtension import NetworkExtension
import TunnelKitOpenVPNCore
import TunnelKitManager import TunnelKitManager
/// `VPNProvider` for OpenVPN protocol. /// `VPNProvider` for OpenVPN protocol.
@ -105,7 +106,7 @@ public class OpenVPNProvider: VPNProvider, VPNProviderIPC {
return return
} }
do { do {
try session.sendProviderMessage(OpenVPNTunnelProvider.Message.dataCount.data) { (data) in try session.sendProviderMessage(Message.dataCount.data) { (data) in
guard let data = data, data.count == 16 else { guard let data = data, data.count == 16 else {
DispatchQueue.main.async { DispatchQueue.main.async {
completionHandler(nil) completionHandler(nil)
@ -135,7 +136,7 @@ public class OpenVPNProvider: VPNProvider, VPNProviderIPC {
return return
} }
do { do {
try session.sendProviderMessage(OpenVPNTunnelProvider.Message.serverConfiguration.data) { (data) in try session.sendProviderMessage(Message.serverConfiguration.data) { (data) in
guard let data = data, let cfg = try? JSONDecoder().decode(OpenVPN.Configuration.self, from: data) else { guard let data = data, let cfg = try? JSONDecoder().decode(OpenVPN.Configuration.self, from: data) else {
DispatchQueue.main.async { DispatchQueue.main.async {
completionHandler(nil) completionHandler(nil)
@ -168,7 +169,7 @@ public class OpenVPNProvider: VPNProvider, VPNProviderIPC {
private static func requestDebugLog(session: NETunnelProviderSession, completionHandler: @escaping (String?) -> Void) { private static func requestDebugLog(session: NETunnelProviderSession, completionHandler: @escaping (String?) -> Void) {
do { do {
try session.sendProviderMessage(OpenVPNTunnelProvider.Message.requestLog.data) { (data) in try session.sendProviderMessage(Message.requestLog.data) { (data) in
guard let data = data, !data.isEmpty else { guard let data = data, !data.isEmpty else {
completionHandler(nil) completionHandler(nil)
return return

View File

@ -0,0 +1,111 @@
//
// OpenVPNProviderError.swift
// TunnelKit
//
// Created by Davide De Rosa on 11/8/21.
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of TunnelKit.
//
// TunnelKit is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TunnelKit is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
//
// This file incorporates work covered by the following copyright and
// permission notice:
//
// Copyright (c) 2018-Present Private Internet Access
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
import Foundation
/// Mostly programming errors by host app.
public enum OpenVPNProviderConfigurationError: Error {
/// A field in the `OpenVPNProvider.Configuration` provided is incorrect or incomplete.
case parameter(name: String)
/// Credentials are missing or inaccessible.
case credentials(details: String)
/// The pseudo-random number generator could not be initialized.
case prngInitialization
/// The TLS certificate could not be serialized.
case certificateSerialization
}
/// The errors causing a tunnel disconnection.
public enum OpenVPNProviderError: String, Error {
/// Socket endpoint could not be resolved.
case dnsFailure
/// No more protocols available to try.
case exhaustedProtocols
/// Socket failed to reach active state.
case socketActivity
/// Credentials authentication failed.
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 tlsHandshake
/// The encryption logic could not be initialized (e.g. PRNG, algorithms).
case encryptionInitialization
/// Data encryption/decryption failed.
case encryptionData
/// The LZO engine failed.
case lzo
/// Server uses an unsupported compression algorithm.
case serverCompression
/// Tunnel timed out.
case timeout
/// An error occurred at the link level.
case linkError
/// Network routing information is missing or incomplete.
case routing
/// The current network changed (e.g. switched from WiFi to data connection).
case networkChanged
/// Default gateway could not be attained.
case gatewayUnattainable
/// Remove server has shut down.
case serverShutdown
/// The server replied in an unexpected way.
case unexpectedReply
}

View File

@ -37,8 +37,9 @@
import Foundation import Foundation
import SwiftyBeaver import SwiftyBeaver
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self

View File

@ -26,8 +26,9 @@
import Foundation import Foundation
import SwiftyBeaver import SwiftyBeaver
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self

View File

@ -26,8 +26,9 @@
import Foundation import Foundation
import SwiftyBeaver import SwiftyBeaver
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self

View File

@ -36,8 +36,8 @@
import Foundation import Foundation
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import CTunnelKitCore
import _TunnelKitOpenVPNObjC import CTunnelKitOpenVPNProtocol
extension CoreConfiguration { extension CoreConfiguration {
struct OpenVPN { struct OpenVPN {

View File

@ -36,8 +36,9 @@
import Foundation import Foundation
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
extension OpenVPN { extension OpenVPN {
class EncryptionBridge { class EncryptionBridge {

View File

@ -1,8 +1,8 @@
// //
// OpenVPN.swift // OpenVPN+PRNG.swift
// TunnelKit // TunnelKit
// //
// Created by Davide De Rosa on 5/19/19. // Created by Davide De Rosa on 11/8/21.
// Copyright (c) 2021 Davide De Rosa. All rights reserved. // Copyright (c) 2021 Davide De Rosa. All rights reserved.
// //
// https://github.com/passepartoutvpn // https://github.com/passepartoutvpn
@ -25,11 +25,11 @@
import Foundation import Foundation
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
/// Container for OpenVPN classes. extension OpenVPN {
public class OpenVPN {
/** /**
Initializes the PRNG. Must be issued before using `OpenVPNSession`. Initializes the PRNG. Must be issued before using `OpenVPNSession`.
@ -45,5 +45,4 @@ public class OpenVPN {
} }
return CryptoBox.preparePRNG(withSeed: seed.bytes, length: seed.count) return CryptoBox.preparePRNG(withSeed: seed.bytes, length: seed.count)
} }
} }

View File

@ -36,6 +36,7 @@
import Foundation import Foundation
import TunnelKitCore import TunnelKitCore
import TunnelKitOpenVPNCore
extension OpenVPNSession { extension OpenVPNSession {
struct PIAHardReset { struct PIAHardReset {

View File

@ -37,8 +37,9 @@
import Foundation import Foundation
import SwiftyBeaver import SwiftyBeaver
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self

View File

@ -36,8 +36,9 @@
import Foundation import Foundation
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
/// :nodoc: /// :nodoc:
extension ControlPacket { extension ControlPacket {

View File

@ -35,6 +35,7 @@
// //
import Foundation import Foundation
import TunnelKitOpenVPNCore
extension OpenVPN { extension OpenVPN {
class ProtocolMacros { class ProtocolMacros {

View File

@ -35,6 +35,7 @@
// //
import Foundation import Foundation
import TunnelKitOpenVPNCore
extension OpenVPN { extension OpenVPN {
struct PushReply: CustomStringConvertible { struct PushReply: CustomStringConvertible {

View File

@ -37,8 +37,9 @@
import Foundation import Foundation
import SwiftyBeaver import SwiftyBeaver
import TunnelKitCore import TunnelKitCore
import _TunnelKitCoreObjC import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
private let log = SwiftyBeaver.self private let log = SwiftyBeaver.self

View File

@ -24,7 +24,7 @@
// //
import XCTest import XCTest
import _TunnelKitCoreObjC import CTunnelKitCore
class RoutingTests: XCTestCase { class RoutingTests: XCTestCase {

View File

@ -25,7 +25,7 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
import _TunnelKitCoreObjC import CTunnelKitCore
import TunnelKitLZO import TunnelKitLZO
class CompressionTests: XCTestCase { class CompressionTests: XCTestCase {

View File

@ -36,9 +36,12 @@
import XCTest import XCTest
import NetworkExtension import NetworkExtension
@testable import TunnelKitCore import TunnelKitCore
@testable import TunnelKitOpenVPN import TunnelKitOpenVPNCore
@testable import TunnelKitAppExtension import TunnelKitAppExtension
@testable import TunnelKitOpenVPNAppExtension
import TunnelKitManager
import TunnelKitOpenVPNManager
class AppExtensionTests: XCTestCase { class AppExtensionTests: XCTestCase {
@ -53,8 +56,8 @@ class AppExtensionTests: XCTestCase {
} }
func testConfiguration() { func testConfiguration() {
var builder: OpenVPNTunnelProvider.ConfigurationBuilder! var builder: OpenVPNProvider.ConfigurationBuilder!
var cfg: OpenVPNTunnelProvider.Configuration! var cfg: OpenVPNProvider.Configuration!
let identifier = "com.example.Provider" let identifier = "com.example.Provider"
let appGroup = "group.com.algoritmico.TunnelKit" let appGroup = "group.com.algoritmico.TunnelKit"
@ -69,7 +72,7 @@ class AppExtensionTests: XCTestCase {
sessionBuilder.hostname = hostname sessionBuilder.hostname = hostname
sessionBuilder.endpointProtocols = [] sessionBuilder.endpointProtocols = []
sessionBuilder.mtu = 1230 sessionBuilder.mtu = 1230
builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build()) builder = OpenVPNProvider.ConfigurationBuilder(sessionConfiguration: sessionBuilder.build())
XCTAssertNotNil(builder) XCTAssertNotNil(builder)
cfg = builder.build() cfg = builder.build()
@ -147,7 +150,7 @@ class AppExtensionTests: XCTestCase {
EndpointProtocol(.udp, 1111), EndpointProtocol(.udp, 1111),
EndpointProtocol(.udp4, 3333) EndpointProtocol(.udp4, 3333)
] ]
var builder2 = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: builder1.build()) var builder2 = OpenVPNProvider.ConfigurationBuilder(sessionConfiguration: builder1.build())
builder2.prefersResolvedAddresses = true builder2.prefersResolvedAddresses = true
builder2.resolvedAddresses = [ builder2.resolvedAddresses = [
"82.102.21.218", "82.102.21.218",

View File

@ -25,7 +25,7 @@
import XCTest import XCTest
import TunnelKitCore import TunnelKitCore
import TunnelKitOpenVPN import TunnelKitOpenVPNCore
class ConfigurationParserTests: XCTestCase { class ConfigurationParserTests: XCTestCase {
override func setUp() { override func setUp() {

View File

@ -25,9 +25,11 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
import _TunnelKitCoreObjC @testable import TunnelKitOpenVPNCore
@testable import TunnelKitOpenVPN @testable import TunnelKitOpenVPNProtocol
import _TunnelKitOpenVPNObjC @testable import TunnelKitOpenVPNAppExtension
import CTunnelKitCore
import CTunnelKitOpenVPNProtocol
class ControlChannelTests: XCTestCase { class ControlChannelTests: XCTestCase {
private let hex = "634a4d2d459d606c8e6abbec168fdcd1871462eaa2eaed84c8f403bdf8c7da737d81b5774cc35fe0a42b38aa053f1335fd4a22d721880433bbb20ae1f2d88315b2d186b3b377685506fa39d85d38da16c2ecc0d631bda64f9d8f5a8d073f18aab97ade23e49ea9e7de86784d1ed5fa356df5f7fa1d163e5537efa8d4ba61239dc301a9aa55de0e06e33a7545f7d0cc153405576464ba92942dafa5fb79c7a60663ff1e7da3122ae09d4561653bef3eeb312ad68b191e2f94cbcf4e21caff0b59f8be86567bd21787070c2dc10a8baf7e87ce2e07d7d7de25ead11bd6d6e6ec030c0a3fd50d2d0ca3c0378022bb642e954868d7b93e18a131ecbb12b0bbedb1ce" private let hex = "634a4d2d459d606c8e6abbec168fdcd1871462eaa2eaed84c8f403bdf8c7da737d81b5774cc35fe0a42b38aa053f1335fd4a22d721880433bbb20ae1f2d88315b2d186b3b377685506fa39d85d38da16c2ecc0d631bda64f9d8f5a8d073f18aab97ade23e49ea9e7de86784d1ed5fa356df5f7fa1d163e5537efa8d4ba61239dc301a9aa55de0e06e33a7545f7d0cc153405576464ba92942dafa5fb79c7a60663ff1e7da3122ae09d4561653bef3eeb312ad68b191e2f94cbcf4e21caff0b59f8be86567bd21787070c2dc10a8baf7e87ce2e07d7d7de25ead11bd6d6e6ec030c0a3fd50d2d0ca3c0378022bb642e954868d7b93e18a131ecbb12b0bbedb1ce"

View File

@ -36,8 +36,8 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
import _TunnelKitCoreObjC import CTunnelKitCore
import _TunnelKitOpenVPNObjC import CTunnelKitOpenVPNProtocol
class DataPathEncryptionTests: XCTestCase { class DataPathEncryptionTests: XCTestCase {
private let cipherKey = try! SecureRandom.safeData(length: 32) private let cipherKey = try! SecureRandom.safeData(length: 32)

View File

@ -36,8 +36,10 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
@testable import TunnelKitOpenVPN @testable import TunnelKitOpenVPNCore
import _TunnelKitOpenVPNObjC @testable import TunnelKitOpenVPNProtocol
@testable import TunnelKitOpenVPNAppExtension
import CTunnelKitOpenVPNProtocol
class DataPathPerformanceTests: XCTestCase { class DataPathPerformanceTests: XCTestCase {
private var dataPath: DataPath! private var dataPath: DataPath!

View File

@ -36,8 +36,8 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
import _TunnelKitCoreObjC import CTunnelKitCore
import _TunnelKitOpenVPNObjC import CTunnelKitOpenVPNProtocol
class EncryptionPerformanceTests: XCTestCase { class EncryptionPerformanceTests: XCTestCase {
private var cbcEncrypter: Encrypter! private var cbcEncrypter: Encrypter!

View File

@ -36,9 +36,9 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
import _TunnelKitCoreObjC @testable import TunnelKitOpenVPNCore
import TunnelKitOpenVPN import CTunnelKitCore
import _TunnelKitOpenVPNObjC import CTunnelKitOpenVPNProtocol
class EncryptionTests: XCTestCase { class EncryptionTests: XCTestCase {
private var cipherEncKey: ZeroingData! private var cipherEncKey: ZeroingData!

View File

@ -36,7 +36,7 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
@testable import _TunnelKitCoreObjC @testable import CTunnelKitCore
class LinkTests: XCTestCase { class LinkTests: XCTestCase {

View File

@ -25,7 +25,7 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
import _TunnelKitOpenVPNObjC import CTunnelKitOpenVPNProtocol
class PacketTests: XCTestCase { class PacketTests: XCTestCase {

View File

@ -25,7 +25,9 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
@testable import TunnelKitOpenVPN @testable import TunnelKitOpenVPNCore
@testable import TunnelKitOpenVPNProtocol
@testable import TunnelKitOpenVPNAppExtension
private extension OpenVPN.PushReply { private extension OpenVPN.PushReply {
func debug() { func debug() {

View File

@ -25,7 +25,7 @@
import XCTest import XCTest
@testable import TunnelKitCore @testable import TunnelKitCore
import TunnelKitOpenVPN import TunnelKitOpenVPNCore
class StaticKeyTests: XCTestCase { class StaticKeyTests: XCTestCase {
private let content = """ private let content = """

Some files were not shown because too many files have changed in this diff Show More