Merge branch 'develop' into feature/documentation

* develop: (32 commits)
  Add header guards
  Update project settings
  Update tests
  Fix crash if empty data was provided
  Apply style guide rules to the remaining classes
  Update tracking property name regarding style guide
  Apply style guide rules to the openvpn configuration class
  Add missing import of reachability status header
  Apply style guide rules to certificate, key and reachability classes
  Refactor generation of mbedTLS errors
  Add Nullability Annotations to OpenVPNAdapterPacketFlow (#43)
  Refactor generation of OpenVPN adapter errors
  Refactor implementation of OpenVPNAdapter class
  Redefine networkSettings as method instead of property
  Return false if URL is nil
  Initializer shouldn't return nil, and return socket setup error during socket configuration
  Add socket setup error
  Rename a few delegate methods and fix memory warning
  Add extra spaces and empty lines
  Add pragma marks
  ...
This commit is contained in:
Sergey Abramchuk
2018-01-23 17:25:19 +03:00
50 changed files with 1324 additions and 876 deletions

View File

@@ -6,22 +6,15 @@
//
import NetworkExtension
@testable import OpenVPNAdapter
class CustomFlow: NEPacketTunnelFlow {
override func readPackets(completionHandler: @escaping ([Data], [NSNumber]) -> Void) {
class CustomFlow: NSObject, OpenVPNAdapterPacketFlow {
func readPackets(completionHandler: @escaping ([Data], [NSNumber]) -> Void) {
}
override func writePackets(_ packets: [Data], withProtocols protocols: [NSNumber]) -> Bool {
return true
}
override func readPacketObjects(completionHandler: @escaping ([NEPacket]) -> Void) {
}
override func writePacketObjects(_ packets: [NEPacket]) -> Bool {
func writePackets(_ packets: [Data], withProtocols protocols: [NSNumber]) -> Bool {
return true
}

View File

@@ -135,7 +135,7 @@ class OpenVPNAdapterTests: XCTestCase {
extension OpenVPNAdapterTests: OpenVPNAdapterDelegate {
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings, completionHandler: @escaping (NEPacketTunnelFlow?) -> Void) {
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings, completionHandler: @escaping (OpenVPNAdapterPacketFlow?) -> Void) {
completionHandler(customFlow)
}

View File

@@ -124,12 +124,22 @@
C9C1E4111FA47117006ECA7D /* remote_vpn_server.ovpn in Resources */ = {isa = PBXBuildFile; fileRef = C9C1E40F1FA47117006ECA7D /* remote_vpn_server.ovpn */; };
C9C1E4141FA475B7006ECA7D /* CustomFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */; };
C9C1E4151FA475B7006ECA7D /* CustomFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */; };
C9C2B2B7200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */; settings = {ATTRIBUTES = (Public, ); }; };
C9C2B2B8200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */; settings = {ATTRIBUTES = (Public, ); }; };
C9C2B2BB200CC42A00CA0FF3 /* OpenVPNPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */; };
C9C2B2BC200CC42A00CA0FF3 /* OpenVPNPacket.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */; };
C9C2B2BD200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */; };
C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */; };
C9CA4DD31F602F7B00C4F184 /* OpenVPNCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; };
C9CA4DD41F602F7B00C4F184 /* OpenVPNCertificate.h in Headers */ = {isa = PBXBuildFile; fileRef = C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */; settings = {ATTRIBUTES = (Public, ); }; };
C9CA4DD51F602F7B00C4F184 /* OpenVPNCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */; };
C9CA4DD61F602F7B00C4F184 /* OpenVPNCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */; };
C9CA4DE11F603A5300C4F184 /* OpenVPNCertificateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */; };
C9CA4DE21F603A5300C4F184 /* OpenVPNCertificateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */; };
C9CDFDDB200781AF00323B73 /* OpenVPNClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */; };
C9CDFDDC200781AF00323B73 /* OpenVPNClient.h in Headers */ = {isa = PBXBuildFile; fileRef = C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */; };
C9CDFDDD200781AF00323B73 /* OpenVPNClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */; };
C9CDFDDE200781AF00323B73 /* OpenVPNClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */; };
C9D2ABDE1EA20F99007EDF9D /* ovpncli.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9FD92191E9A667600374FC4 /* ovpncli.cpp */; };
C9D2ABE01EA20F99007EDF9D /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C912BB241E7C3339002B9414 /* NetworkExtension.framework */; };
C9D2ABE11EA20F99007EDF9D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C90BAD301E73FF6C00DEFB32 /* SystemConfiguration.framework */; };
@@ -140,10 +150,10 @@
C9D2ABF61EA212A3007EDF9D /* OpenVPNAdapterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BB47901E71821A00F3F98C /* OpenVPNAdapterTests.swift */; };
C9D2ABF71EA212A3007EDF9D /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9BB47A11E7183DB00F3F98C /* Bundle.swift */; };
C9D2AC051EA214EA007EDF9D /* OpenVPNAdapter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9D2ABF01EA20F99007EDF9D /* OpenVPNAdapter.framework */; };
C9E4401D1F6086A1001D7C41 /* NSError+Message.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E4401B1F6086A1001D7C41 /* NSError+Message.h */; };
C9E4401E1F6086A1001D7C41 /* NSError+Message.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E4401B1F6086A1001D7C41 /* NSError+Message.h */; };
C9E4401F1F6086A1001D7C41 /* NSError+Message.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E4401C1F6086A1001D7C41 /* NSError+Message.m */; };
C9E440201F6086A1001D7C41 /* NSError+Message.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E4401C1F6086A1001D7C41 /* NSError+Message.m */; };
C9E350C1200F6EC0000820D9 /* NSError+OpenVPNError.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */; };
C9E350C2200F6EC0000820D9 /* NSError+OpenVPNError.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */; };
C9E350C3200F6EC0000820D9 /* NSError+OpenVPNError.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */; };
C9E350C4200F6EC0000820D9 /* NSError+OpenVPNError.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */; };
C9FD921A1E9A667600374FC4 /* ovpncli.hpp in Headers */ = {isa = PBXBuildFile; fileRef = C9FD92181E9A667600374FC4 /* ovpncli.hpp */; };
C9FD921B1E9A667600374FC4 /* ovpncli.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9FD92191E9A667600374FC4 /* ovpncli.cpp */; };
/* End PBXBuildFile section */
@@ -237,13 +247,18 @@
C9BCE25C1EB3C201009D6AC1 /* OpenVPNSessionToken+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "OpenVPNSessionToken+Internal.h"; sourceTree = "<group>"; };
C9C1E40F1FA47117006ECA7D /* remote_vpn_server.ovpn */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = remote_vpn_server.ovpn; sourceTree = "<group>"; };
C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomFlow.swift; sourceTree = "<group>"; };
C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNAdapterPacketFlow.h; sourceTree = "<group>"; };
C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNPacket.h; sourceTree = "<group>"; };
C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OpenVPNPacket.mm; sourceTree = "<group>"; };
C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenVPNCertificate.h; sourceTree = "<group>"; };
C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenVPNCertificate.m; sourceTree = "<group>"; };
C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNCertificateTests.swift; sourceTree = "<group>"; };
C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNClient.h; sourceTree = "<group>"; };
C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OpenVPNClient.mm; sourceTree = "<group>"; };
C9D2ABF01EA20F99007EDF9D /* OpenVPNAdapter.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OpenVPNAdapter.framework; sourceTree = BUILT_PRODUCTS_DIR; };
C9D2ABFF1EA212A3007EDF9D /* OpenVPNAdapterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OpenVPNAdapterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C9E4401B1F6086A1001D7C41 /* NSError+Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+Message.h"; sourceTree = "<group>"; };
C9E4401C1F6086A1001D7C41 /* NSError+Message.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+Message.m"; sourceTree = "<group>"; };
C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+OpenVPNError.h"; sourceTree = "<group>"; };
C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+OpenVPNError.m"; sourceTree = "<group>"; };
C9FD92181E9A667600374FC4 /* ovpncli.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ovpncli.hpp; path = Vendors/openvpn/client/ovpncli.hpp; sourceTree = "<group>"; };
C9FD92191E9A667600374FC4 /* ovpncli.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ovpncli.cpp; path = Vendors/openvpn/client/ovpncli.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -334,6 +349,11 @@
C9235AC41EB24F0100C7D303 /* Configuration */ = {
isa = PBXGroup;
children = (
C9657A5D1EB0D60700EFF210 /* OpenVPNTransportProtocol.h */,
C9657A601EB0D64E00EFF210 /* OpenVPNIPv6Preference.h */,
C9657A631EB0D6AD00EFF210 /* OpenVPNCompressionMode.h */,
C9657A661EB0D73200EFF210 /* OpenVPNMinTLSVersion.h */,
C9657A691EB0D75700EFF210 /* OpenVPNTLSCertProfile.h */,
C98467A41EAA5B7700272A9A /* OpenVPNConfiguration.h */,
C98467AA1EAA5BB500272A9A /* OpenVPNConfiguration+Internal.h */,
C98467A51EAA5B7700272A9A /* OpenVPNConfiguration.mm */,
@@ -369,26 +389,10 @@
name = "Stats and Info";
sourceTree = "<group>";
};
C9235AC61EB24F2A00C7D303 /* Types and Constants */ = {
isa = PBXGroup;
children = (
C9BB476F1E7171A100F3F98C /* OpenVPNError.h */,
C93A4F611EE18009004DC561 /* OpenVPNError.m */,
C9BB47701E7171A100F3F98C /* OpenVPNAdapterEvent.h */,
C9657A5D1EB0D60700EFF210 /* OpenVPNTransportProtocol.h */,
C9657A601EB0D64E00EFF210 /* OpenVPNIPv6Preference.h */,
C9657A631EB0D6AD00EFF210 /* OpenVPNCompressionMode.h */,
C9657A661EB0D73200EFF210 /* OpenVPNMinTLSVersion.h */,
C9657A691EB0D75700EFF210 /* OpenVPNTLSCertProfile.h */,
C915F1FD1F6164CF00B3DF23 /* OpenVPNKeyType.h */,
C9B795681F1D219C00CF35FE /* OpenVPNReachabilityStatus.h */,
);
name = "Types and Constants";
sourceTree = "<group>";
};
C9B7955B1F1D165700CF35FE /* Reachability */ = {
isa = PBXGroup;
children = (
C9B795681F1D219C00CF35FE /* OpenVPNReachabilityStatus.h */,
C9B795621F1D182500CF35FE /* OpenVPNReachabilityTracker.h */,
C9B795631F1D182500CF35FE /* OpenVPNReachabilityTracker.mm */,
C9B7955C1F1D16AA00CF35FE /* OpenVPNReachability.h */,
@@ -432,12 +436,20 @@
C9BB47671E7169F000F3F98C /* Adapter */ = {
isa = PBXGroup;
children = (
ABD6EF151F8F9C37007D3D90 /* OpenVPNAdapter.h */,
ABD6EF161F8F9C38007D3D90 /* OpenVPNAdapter.mm */,
C9BB47701E7171A100F3F98C /* OpenVPNAdapterEvent.h */,
C9BB476F1E7171A100F3F98C /* OpenVPNError.h */,
C93A4F611EE18009004DC561 /* OpenVPNError.m */,
C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */,
C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */,
ABD6EF071F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h */,
ABD6EF081F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m */,
C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */,
C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */,
C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */,
ABD6EF0E1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.h */,
ABD6EF0F1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm */,
ABD6EF151F8F9C37007D3D90 /* OpenVPNAdapter.h */,
ABD6EF161F8F9C38007D3D90 /* OpenVPNAdapter.mm */,
);
name = Adapter;
sourceTree = "<group>";
@@ -538,6 +550,7 @@
C9CA4DD01F602D8300C4F184 /* Certificates and Keys */ = {
isa = PBXGroup;
children = (
C915F1FD1F6164CF00B3DF23 /* OpenVPNKeyType.h */,
C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */,
C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */,
C915F1F21F612F3300B3DF23 /* OpenVPNPrivateKey.h */,
@@ -546,20 +559,19 @@
name = "Certificates and Keys";
sourceTree = "<group>";
};
C9E4401A1F6081FF001D7C41 /* Utils */ = {
C9E350C5200F70CA000820D9 /* Extensions */ = {
isa = PBXGroup;
children = (
C9E4401B1F6086A1001D7C41 /* NSError+Message.h */,
C9E4401C1F6086A1001D7C41 /* NSError+Message.m */,
C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */,
C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */,
);
name = Utils;
name = Extensions;
sourceTree = "<group>";
};
C9FF73B71EB7421600E995AC /* Helpers */ = {
isa = PBXGroup;
children = (
C9235AC61EB24F2A00C7D303 /* Types and Constants */,
C9E4401A1F6081FF001D7C41 /* Utils */,
C9E350C5200F70CA000820D9 /* Extensions */,
);
name = Helpers;
sourceTree = "<group>";
@@ -572,6 +584,7 @@
buildActionMask = 2147483647;
files = (
C9CA4DD31F602F7B00C4F184 /* OpenVPNCertificate.h in Headers */,
C9CDFDDB200781AF00323B73 /* OpenVPNClient.h in Headers */,
C9657A3A1EB0BAAB00EFF210 /* OpenVPNInterfaceStats+Internal.h in Headers */,
C9354F451F1E4A4500F4C935 /* OpenVPNReachabilityStatus.h in Headers */,
C9BCE25E1EB3C201009D6AC1 /* OpenVPNSessionToken+Internal.h in Headers */,
@@ -596,13 +609,15 @@
C9657A171EB0A7F800EFF210 /* OpenVPNConnectionInfo.h in Headers */,
C9BB47711E7171A100F3F98C /* OpenVPNError.h in Headers */,
C9B795641F1D182500CF35FE /* OpenVPNReachabilityTracker.h in Headers */,
C9E4401D1F6086A1001D7C41 /* NSError+Message.h in Headers */,
ABD6EF091F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h in Headers */,
C9657A611EB0D64E00EFF210 /* OpenVPNIPv6Preference.h in Headers */,
C9657A671EB0D73200EFF210 /* OpenVPNMinTLSVersion.h in Headers */,
C9C2B2BB200CC42A00CA0FF3 /* OpenVPNPacket.h in Headers */,
C93779D51EAE32670030A362 /* OpenVPNCredentials.h in Headers */,
C9657A641EB0D6C200EFF210 /* OpenVPNCompressionMode.h in Headers */,
C9FD921A1E9A667600374FC4 /* ovpncli.hpp in Headers */,
C9C2B2B7200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */,
C9E350C1200F6EC0000820D9 /* NSError+OpenVPNError.h in Headers */,
C93779DB1EAE32880030A362 /* OpenVPNCredentials+Internal.h in Headers */,
C9657A6A1EB0D75700EFF210 /* OpenVPNTLSCertProfile.h in Headers */,
C9657A461EB0CB5900EFF210 /* OpenVPNServerEntry+Internal.h in Headers */,
@@ -615,6 +630,7 @@
buildActionMask = 2147483647;
files = (
C9CA4DD41F602F7B00C4F184 /* OpenVPNCertificate.h in Headers */,
C9CDFDDC200781AF00323B73 /* OpenVPNClient.h in Headers */,
C9657A3B1EB0BAAB00EFF210 /* OpenVPNInterfaceStats+Internal.h in Headers */,
C9354F461F1E4A4600F4C935 /* OpenVPNReachabilityStatus.h in Headers */,
C9BCE25F1EB3C201009D6AC1 /* OpenVPNSessionToken+Internal.h in Headers */,
@@ -639,13 +655,15 @@
C9657A181EB0A7F800EFF210 /* OpenVPNConnectionInfo.h in Headers */,
C9D2ABE81EA20F99007EDF9D /* OpenVPNError.h in Headers */,
C9B795651F1D182500CF35FE /* OpenVPNReachabilityTracker.h in Headers */,
C9E4401E1F6086A1001D7C41 /* NSError+Message.h in Headers */,
ABD6EF0A1F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h in Headers */,
C9657A621EB0D64E00EFF210 /* OpenVPNIPv6Preference.h in Headers */,
C9657A681EB0D73200EFF210 /* OpenVPNMinTLSVersion.h in Headers */,
C9C2B2BC200CC42A00CA0FF3 /* OpenVPNPacket.h in Headers */,
C93779D61EAE32670030A362 /* OpenVPNCredentials.h in Headers */,
C9657A651EB0D6C200EFF210 /* OpenVPNCompressionMode.h in Headers */,
C9D2ABEA1EA20F99007EDF9D /* ovpncli.hpp in Headers */,
C9C2B2B8200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */,
C9E350C2200F6EC0000820D9 /* NSError+OpenVPNError.h in Headers */,
C93779DC1EAE32880030A362 /* OpenVPNCredentials+Internal.h in Headers */,
C9657A6B1EB0D75700EFF210 /* OpenVPNTLSCertProfile.h in Headers */,
C9657A471EB0CB5900EFF210 /* OpenVPNServerEntry+Internal.h in Headers */,
@@ -860,18 +878,20 @@
ABD6EF181F8F9C38007D3D90 /* OpenVPNAdapter.mm in Sources */,
C9657A421EB0CAC200EFF210 /* OpenVPNServerEntry.mm in Sources */,
C9BCE25A1EB3C0D9009D6AC1 /* OpenVPNSessionToken.mm in Sources */,
C9E350C3200F6EC0000820D9 /* NSError+OpenVPNError.m in Sources */,
ABD6EF0B1F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m in Sources */,
C98467A81EAA5B7700272A9A /* OpenVPNConfiguration.mm in Sources */,
ABD6EF121F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm in Sources */,
C9E4401F1F6086A1001D7C41 /* NSError+Message.m in Sources */,
C9657A311EB0B7A900EFF210 /* OpenVPNTransportStats.mm in Sources */,
C9B795661F1D182500CF35FE /* OpenVPNReachabilityTracker.mm in Sources */,
C9657A581EB0CE1300EFF210 /* OpenVPNProperties.mm in Sources */,
C9CA4DD51F602F7B00C4F184 /* OpenVPNCertificate.m in Sources */,
C9CDFDDD200781AF00323B73 /* OpenVPNClient.mm in Sources */,
C915F1F61F612F3300B3DF23 /* OpenVPNPrivateKey.m in Sources */,
C9FD921B1E9A667600374FC4 /* ovpncli.cpp in Sources */,
C9657A361EB0BA3900EFF210 /* OpenVPNInterfaceStats.mm in Sources */,
C9657A211EB0ACAE00EFF210 /* OpenVPNConnectionInfo.mm in Sources */,
C9C2B2BD200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */,
C93A4F621EE18009004DC561 /* OpenVPNError.m in Sources */,
C93779D71EAE32670030A362 /* OpenVPNCredentials.mm in Sources */,
C9B795601F1D16AA00CF35FE /* OpenVPNReachability.mm in Sources */,
@@ -899,18 +919,20 @@
ABD6EF1A1F8F9C3B007D3D90 /* OpenVPNAdapter.mm in Sources */,
C9657A431EB0CAC200EFF210 /* OpenVPNServerEntry.mm in Sources */,
C9BCE25B1EB3C0D9009D6AC1 /* OpenVPNSessionToken.mm in Sources */,
C9E350C4200F6EC0000820D9 /* NSError+OpenVPNError.m in Sources */,
ABD6EF0C1F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m in Sources */,
C98467A91EAA5B7700272A9A /* OpenVPNConfiguration.mm in Sources */,
ABD6EF131F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm in Sources */,
C9E440201F6086A1001D7C41 /* NSError+Message.m in Sources */,
C9657A301EB0B7A600EFF210 /* OpenVPNTransportStats.mm in Sources */,
C9B795671F1D182500CF35FE /* OpenVPNReachabilityTracker.mm in Sources */,
C9657A591EB0CE1400EFF210 /* OpenVPNProperties.mm in Sources */,
C9CA4DD61F602F7B00C4F184 /* OpenVPNCertificate.m in Sources */,
C9CDFDDE200781AF00323B73 /* OpenVPNClient.mm in Sources */,
C915F1F71F612F3300B3DF23 /* OpenVPNPrivateKey.m in Sources */,
C9D2ABDE1EA20F99007EDF9D /* ovpncli.cpp in Sources */,
C9657A371EB0BA3900EFF210 /* OpenVPNInterfaceStats.mm in Sources */,
C9657A221EB0ACAE00EFF210 /* OpenVPNConnectionInfo.mm in Sources */,
C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */,
C93A4F631EE18009004DC561 /* OpenVPNError.m in Sources */,
C93779D81EAE32670030A362 /* OpenVPNCredentials.mm in Sources */,
C9B795611F1D16AA00CF35FE /* OpenVPNReachability.mm in Sources */,
@@ -1357,7 +1379,6 @@
SUPPORTED_PLATFORMS = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.0;
};
name = Debug;
@@ -1404,7 +1425,6 @@
SDKROOT = macosx;
SUPPORTED_PLATFORMS = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES;
};

View File

@@ -1,15 +0,0 @@
//
// NSError+Message.h
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 06.09.17.
//
//
#import <Foundation/Foundation.h>
@interface NSError (Message)
+ (NSString *)reasonFromResult:(NSInteger)result;
@end

View File

@@ -1,28 +0,0 @@
//
// NSError+Message.m
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 06.09.17.
//
//
#import <mbedtls/error.h>
#import "NSError+Message.h"
@implementation NSError (Message)
+ (NSString *)reasonFromResult:(NSInteger)result {
size_t length = 1024;
char *buffer = malloc(length);
mbedtls_strerror(result, buffer, length);
NSString *reason = [NSString stringWithUTF8String:buffer];
free(buffer);
return reason;
}
@end

View File

@@ -0,0 +1,33 @@
//
// NSError+OpenVPNError.h
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 17.01.2018.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
FOUNDATION_EXPORT NSString *const OpenVPNAdapterErrorDomain;
typedef NS_ERROR_ENUM(OpenVPNAdapterErrorDomain, OpenVPNAdapterError);
@interface NSError (OpenVPNAdapterErrorGeneration)
+ (NSError *)ovpn_errorObjectForAdapterError:(OpenVPNAdapterError)adapterError
description:(NSString *)description
message:(nullable NSString *)message
fatal:(BOOL)fatal;
+ (OpenVPNAdapterError)ovpn_adapterErrorByName:(NSString *)errorName;
@end
@interface NSError (OpenVPNMbedTLSErrorGeneration)
+ (NSError *)ovpn_errorObjectForMbedTLSError:(NSInteger)errorCode description:(NSString *)description;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,203 @@
//
// NSError+OpenVPNError.m
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 17.01.2018.
//
#import "NSError+OpenVPNError.h"
#import <mbedtls/error.h>
#import "OpenVPNError.h"
@implementation NSError (OpenVPNAdapterErrorGeneration)
+ (NSError *)ovpn_errorObjectForAdapterError:(OpenVPNAdapterError)adapterError
description:(NSString *)description
message:(NSString *)message
fatal:(BOOL)fatal
{
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{
NSLocalizedDescriptionKey: description,
OpenVPNAdapterErrorFatalKey: @(fatal)
}];
NSString *errorReason = [NSError ovpn_reasonForAdapterError:adapterError];
if (errorReason) {
userInfo[NSLocalizedFailureReasonErrorKey] = errorReason;
}
if (message.length) {
userInfo[OpenVPNAdapterErrorMessageKey] = message;
}
return [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:adapterError userInfo:userInfo];
}
+ (OpenVPNAdapterError)ovpn_adapterErrorByName:(NSString *)errorName {
NSDictionary *errors = @{
@"NETWORK_RECV_ERROR": @(OpenVPNAdapterErrorNetworkRecvError),
@"NETWORK_EOF_ERROR": @(OpenVPNAdapterErrorNetworkEOFError),
@"NETWORK_SEND_ERROR": @(OpenVPNAdapterErrorNetworkSendError),
@"NETWORK_UNAVAILABLE": @(OpenVPNAdapterErrorNetworkUnavailable),
@"DECRYPT_ERROR": @(OpenVPNAdapterErrorDecryptError),
@"HMAC_ERROR": @(OpenVPNAdapterErrorDecryptError),
@"REPLAY_ERROR": @(OpenVPNAdapterErrorReplayError),
@"BUFFER_ERROR": @(OpenVPNAdapterErrorBufferError),
@"CC_ERROR": @(OpenVPNAdapterErrorCCError),
@"BAD_SRC_ADDR": @(OpenVPNAdapterErrorBadSrcAddr),
@"COMPRESS_ERROR": @(OpenVPNAdapterErrorCompressError),
@"RESOLVE_ERROR": @(OpenVPNAdapterErrorResolveError),
@"SOCKET_PROTECT_ERROR": @(OpenVPNAdapterErrorSocketProtectError),
@"TUN_READ_ERROR": @(OpenVPNAdapterErrorTUNReadError),
@"TUN_WRITE_ERROR": @(OpenVPNAdapterErrorTUNWriteError),
@"TUN_FRAMING_ERROR": @(OpenVPNAdapterErrorTUNFramingError),
@"TUN_SETUP_FAILED": @(OpenVPNAdapterErrorTUNSetupFailed),
@"TUN_IFACE_CREATE": @(OpenVPNAdapterErrorTUNIfaceCreate),
@"TUN_IFACE_DISABLED": @(OpenVPNAdapterErrorTUNIfaceDisabled),
@"TUN_ERROR": @(OpenVPNAdapterErrorTUNError),
@"TAP_NOT_SUPPORTED": @(OpenVPNAdapterErrorTAPNotSupported),
@"REROUTE_GW_NO_DNS": @(OpenVPNAdapterErrorRerouteGatewayNoDns),
@"TRANSPORT_ERROR": @(OpenVPNAdapterErrorTransportError),
@"TCP_OVERFLOW": @(OpenVPNAdapterErrorTCPOverflow),
@"TCP_SIZE_ERROR": @(OpenVPNAdapterErrorTCPSizeError),
@"TCP_CONNECT_ERROR": @(OpenVPNAdapterErrorTCPConnectError),
@"UDP_CONNECT_ERROR": @(OpenVPNAdapterErrorUDPConnectError),
@"SSL_ERROR": @(OpenVPNAdapterErrorSSLError),
@"SSL_PARTIAL_WRITE": @(OpenVPNAdapterErrorSSLPartialWrite),
@"ENCAPSULATION_ERROR": @(OpenVPNAdapterErrorEncapsulationError),
@"EPKI_CERT_ERROR": @(OpenVPNAdapterErrorEPKICertError),
@"EPKI_SIGN_ERROR": @(OpenVPNAdapterErrorEPKISignError),
@"HANDSHAKE_TIMEOUT": @(OpenVPNAdapterErrorHandshakeTimeout),
@"KEEPALIVE_TIMEOUT": @(OpenVPNAdapterErrorKeepaliveTimeout),
@"INACTIVE_TIMEOUT": @(OpenVPNAdapterErrorInactiveTimeout),
@"CONNECTION_TIMEOUT": @(OpenVPNAdapterErrorConnectionTimeout),
@"PRIMARY_EXPIRE": @(OpenVPNAdapterErrorPrimaryExpire),
@"TLS_VERSION_MIN": @(OpenVPNAdapterErrorTLSVersionMin),
@"TLS_AUTH_FAIL": @(OpenVPNAdapterErrorTLSAuthFail),
@"CERT_VERIFY_FAIL": @(OpenVPNAdapterErrorCertVerifyFail),
@"PEM_PASSWORD_FAIL": @(OpenVPNAdapterErrorPEMPasswordFail),
@"AUTH_FAILED": @(OpenVPNAdapterErrorAuthFailed),
@"CLIENT_HALT": @(OpenVPNAdapterErrorClientHalt),
@"CLIENT_RESTART": @(OpenVPNAdapterErrorClientRestart),
@"RELAY": @(OpenVPNAdapterErrorRelay),
@"RELAY_ERROR": @(OpenVPNAdapterErrorRelayError),
@"N_PAUSE": @(OpenVPNAdapterErrorPauseNumber),
@"N_RECONNECT": @(OpenVPNAdapterErrorReconnectNumber),
@"N_KEY_LIMIT_RENEG": @(OpenVPNAdapterErrorKeyLimitRenegNumber),
@"KEY_STATE_ERROR": @(OpenVPNAdapterErrorKeyStateError),
@"PROXY_ERROR": @(OpenVPNAdapterErrorProxyError),
@"PROXY_NEED_CREDS": @(OpenVPNAdapterErrorProxyNeedCreds),
@"KEV_NEGOTIATE_ERROR": @(OpenVPNAdapterErrorKevNegotiateError),
@"KEV_PENDING_ERROR": @(OpenVPNAdapterErrorKevPendingError),
@"N_KEV_EXPIRE": @(OpenVPNAdapterErrorKevExpireNumber),
@"PKTID_INVALID": @(OpenVPNAdapterErrorPKTIDInvalid),
@"PKTID_BACKTRACK": @(OpenVPNAdapterErrorPKTIDBacktrack),
@"PKTID_EXPIRE": @(OpenVPNAdapterErrorPKTIDExpire),
@"PKTID_REPLAY": @(OpenVPNAdapterErrorPKTIDReplay),
@"PKTID_TIME_BACKTRACK": @(OpenVPNAdapterErrorPKTIDTimeBacktrack),
@"DYNAMIC_CHALLENGE": @(OpenVPNAdapterErrorDynamicChallenge),
@"EPKI_ERROR": @(OpenVPNAdapterErrorEPKIError),
@"EPKI_INVALID_ALIAS": @(OpenVPNAdapterErrorEPKIInvalidAlias)
};
OpenVPNAdapterError error = errors[errorName] != nil ?
(OpenVPNAdapterError)[errors[errorName] integerValue] : OpenVPNAdapterErrorUnknown;
return error;
}
+ (NSString *)ovpn_reasonForAdapterError:(OpenVPNAdapterError)error {
switch (error) {
case OpenVPNAdapterErrorConfigurationFailure: return @"See OpenVPN error message for more details.";
case OpenVPNAdapterErrorCredentialsFailure: return @"See OpenVPN error message for more details.";
case OpenVPNAdapterErrorNetworkRecvError: return @"Errors receiving on network socket.";
case OpenVPNAdapterErrorNetworkEOFError: return @"EOF received on TCP network socket.";
case OpenVPNAdapterErrorNetworkSendError: return @"Errors sending on network socket";
case OpenVPNAdapterErrorNetworkUnavailable: return @"Network unavailable.";
case OpenVPNAdapterErrorDecryptError: return @"Data channel encrypt/decrypt error.";
case OpenVPNAdapterErrorHMACError: return @"HMAC verification failure.";
case OpenVPNAdapterErrorReplayError: return @"Error from PacketIDReceive.";
case OpenVPNAdapterErrorBufferError: return @"Exception thrown in Buffer methods.";
case OpenVPNAdapterErrorCCError: return @"General control channel errors.";
case OpenVPNAdapterErrorBadSrcAddr: return @"Packet from unknown source address.";
case OpenVPNAdapterErrorCompressError: return @"Compress/Decompress errors on data channel.";
case OpenVPNAdapterErrorResolveError: return @"DNS resolution error.";
case OpenVPNAdapterErrorSocketSetupFailed: return nil;
case OpenVPNAdapterErrorSocketProtectError: return @"Error calling protect() method on socket.";
case OpenVPNAdapterErrorTUNReadError: return @"Read errors on TUN/TAP interface.";
case OpenVPNAdapterErrorTUNWriteError: return @"Write errors on TUN/TAP interface.";
case OpenVPNAdapterErrorTUNFramingError: return @"Error with tun PF_INET/PF_INET6 prefix.";
case OpenVPNAdapterErrorTUNSetupFailed: return @"Error setting up TUN/TAP interface.";
case OpenVPNAdapterErrorTUNIfaceCreate: return @"Error creating TUN/TAP interface.";
case OpenVPNAdapterErrorTUNIfaceDisabled: return @"TUN/TAP interface is disabled.";
case OpenVPNAdapterErrorTUNError: return @"General tun error.";
case OpenVPNAdapterErrorTAPNotSupported: return @"Dev TAP is present in profile but not supported.";
case OpenVPNAdapterErrorRerouteGatewayNoDns: return @"redirect-gateway specified without alt DNS servers.";
case OpenVPNAdapterErrorTransportError: return @"General transport error";
case OpenVPNAdapterErrorTCPOverflow: return @"TCP output queue overflow.";
case OpenVPNAdapterErrorTCPSizeError: return @"Bad embedded uint16_t TCP packet size.";
case OpenVPNAdapterErrorTCPConnectError: return @"Client error on TCP connect.";
case OpenVPNAdapterErrorUDPConnectError: return @"Client error on UDP connect.";
case OpenVPNAdapterErrorSSLError: return @"Errors resulting from read/write on SSL object.";
case OpenVPNAdapterErrorSSLPartialWrite: return @"SSL object did not process all written cleartext.";
case OpenVPNAdapterErrorEncapsulationError: return @"Exceptions thrown during packet encapsulation.";
case OpenVPNAdapterErrorEPKICertError: return @"Error obtaining certificate from External PKI provider.";
case OpenVPNAdapterErrorEPKISignError: return @"Error obtaining RSA signature from External PKI provider.";
case OpenVPNAdapterErrorHandshakeTimeout: return @"Handshake failed to complete within given time frame.";
case OpenVPNAdapterErrorKeepaliveTimeout: return @"Lost contact with peer.";
case OpenVPNAdapterErrorInactiveTimeout: return @"Disconnected due to inactive timer.";
case OpenVPNAdapterErrorConnectionTimeout: return @"Connection failed to establish within given time.";
case OpenVPNAdapterErrorPrimaryExpire: return @"Primary key context expired.";
case OpenVPNAdapterErrorTLSVersionMin: return @"Peer cannot handshake at our minimum required TLS version.";
case OpenVPNAdapterErrorTLSAuthFail: return @"tls-auth HMAC verification failed.";
case OpenVPNAdapterErrorCertVerifyFail: return @"Peer certificate verification failure.";
case OpenVPNAdapterErrorPEMPasswordFail: return @"Incorrect or missing PEM private key decryption password.";
case OpenVPNAdapterErrorAuthFailed: return @"General authentication failure";
case OpenVPNAdapterErrorClientHalt: return @"HALT message from server received.";
case OpenVPNAdapterErrorClientRestart: return @"RESTART message from server received.";
case OpenVPNAdapterErrorRelay: return @"RELAY message from server received.";
case OpenVPNAdapterErrorRelayError: return @"RELAY error.";
case OpenVPNAdapterErrorPauseNumber: return nil;
case OpenVPNAdapterErrorReconnectNumber: return nil;
case OpenVPNAdapterErrorKeyLimitRenegNumber: return nil;
case OpenVPNAdapterErrorKeyStateError: return @"Received packet didn't match expected key state.";
case OpenVPNAdapterErrorProxyError: return @"HTTP proxy error.";
case OpenVPNAdapterErrorProxyNeedCreds: return @"HTTP proxy needs credentials.";
case OpenVPNAdapterErrorKevNegotiateError: return nil;
case OpenVPNAdapterErrorKevPendingError: return nil;
case OpenVPNAdapterErrorKevExpireNumber: return nil;
case OpenVPNAdapterErrorPKTIDInvalid: return nil;
case OpenVPNAdapterErrorPKTIDBacktrack: return nil;
case OpenVPNAdapterErrorPKTIDExpire: return nil;
case OpenVPNAdapterErrorPKTIDReplay: return nil;
case OpenVPNAdapterErrorPKTIDTimeBacktrack: return nil;
case OpenVPNAdapterErrorDynamicChallenge: return nil;
case OpenVPNAdapterErrorEPKIError: return nil;
case OpenVPNAdapterErrorEPKIInvalidAlias: return nil;
case OpenVPNAdapterErrorUnknown: return @"Unknown error.";
}
}
@end
@implementation NSError (OpenVPNMbedTLSErrorGeneration)
+ (NSError *)ovpn_errorObjectForMbedTLSError:(NSInteger)errorCode description:(NSString *)description {
size_t length = 1024;
char *buffer = malloc(length);
mbedtls_strerror(errorCode, buffer, length);
NSString *reason = [NSString stringWithUTF8String:buffer];
free(buffer);
return [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:errorCode userInfo:@{
NSLocalizedDescriptionKey: description,
NSLocalizedFailureReasonErrorKey: reason
}];
}
@end

View File

@@ -7,12 +7,16 @@
//
#import <Foundation/Foundation.h>
#import "OpenVPNAdapterEvent.h"
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, OpenVPNAdapterEvent);
@class NEPacketTunnelFlow;
@class NEPacketTunnelNetworkSettings;
@protocol OpenVPNAdapterPacketFlow;
@class OpenVPNAdapter;
@class OpenVPNConfiguration;
@class OpenVPNConnectionInfo;
@@ -26,17 +30,22 @@ NS_ASSUME_NONNULL_BEGIN
/**
This method is called once the network settings to be used have been established.
The receiver should call the completion handler once these settings have been set, returning a NEPacketTunnelFlow object for the TUN interface, or nil if an error occurred.
The receiver should call the completion handler once these settings have been set, returning a NEPacketTunnelFlow object for
the TUN interface, or nil if an error occurred.
@param openVPNAdapter The OpenVPNAdapter instance requesting this information.
@param networkSettings The NEPacketTunnelNetworkSettings to be used for the tunnel.
@param completionHandler The completion handler to be called with a NEPacketTunnelFlow object, or nil if an error occurred.
*/
- (void)openVPNAdapter:(OpenVPNAdapter *)openVPNAdapter configureTunnelWithNetworkSettings:(NEPacketTunnelNetworkSettings *)networkSettings completionHandler:(void (^)(NEPacketTunnelFlow * _Nullable packetFlow))completionHandler NS_SWIFT_NAME(openVPNAdapter(_:configureTunnelWithNetworkSettings:completionHandler:));
- (void)openVPNAdapter:(OpenVPNAdapter *)openVPNAdapter
configureTunnelWithNetworkSettings:(NEPacketTunnelNetworkSettings *)networkSettings
completionHandler:(void (^)(id<OpenVPNAdapterPacketFlow> _Nullable packetFlow))completionHandler
NS_SWIFT_NAME(openVPNAdapter(_:configureTunnelWithNetworkSettings:completionHandler:));
/**
Informs the receiver that an OpenVPN error has occurred.
Some errors are fatal and should trigger the diconnection of the tunnel, check for fatal errors with the OpenVPNAdapterErrorFatalKey.
Some errors are fatal and should trigger the diconnection of the tunnel, check for fatal errors with the
OpenVPNAdapterErrorFatalKey.
@param openVPNAdapter The OpenVPNAdapter instance which encountered the error.
@param error The error which has occurred.
@@ -50,7 +59,10 @@ NS_ASSUME_NONNULL_BEGIN
@param event The event which has occurred.
@param message An accompanying message, may be nil.
*/
- (void)openVPNAdapter:(OpenVPNAdapter *)openVPNAdapter handleEvent:(OpenVPNAdapterEvent)event message:(nullable NSString *)message NS_SWIFT_NAME(openVPNAdapter(_:handleEvent:message:));
- (void)openVPNAdapter:(OpenVPNAdapter *)openVPNAdapter
handleEvent:(OpenVPNAdapterEvent)event
message:(nullable NSString *)message
NS_SWIFT_NAME(openVPNAdapter(_:handleEvent:message:));
@optional
@@ -122,7 +134,9 @@ NS_ASSUME_NONNULL_BEGIN
@param error If there is an error applying the configuration, upon return contains an error object that describes the problem.
@return A properties object describing the configuration which has been applied.
*/
- (nullable OpenVPNProperties *)applyConfiguration:(OpenVPNConfiguration *)configuration error:(NSError **)error NS_SWIFT_NAME(apply(configuration:));
- (nullable OpenVPNProperties *)applyConfiguration:(OpenVPNConfiguration *)configuration
error:(NSError **)error
NS_SWIFT_NAME(apply(configuration:));
/**
Provides credentials to the receiver.

View File

@@ -8,265 +8,39 @@
#define OPENVPN_EXTERN extern
#import "OpenVPNAdapter.h"
#import <NetworkExtension/NetworkExtension.h>
#import <client/ovpncli.hpp>
#import <openvpn/tun/client/tunbase.hpp>
#import "OpenVPNClient.h"
#import "OpenVPNError.h"
#import "OpenVPNAdapterEvent.h"
#import "OpenVPNPacketFlowBridge.h"
#import "OpenVPNNetworkSettingsBuilder.h"
#import "OpenVPNAdapterPacketFlow.h"
#import "OpenVPNCredentials+Internal.h"
#import "OpenVPNConfiguration+Internal.h"
#import "OpenVPNConnectionInfo+Internal.h"
#import "OpenVPNError.h"
#import "OpenVPNInterfaceStats+Internal.h"
#import "OpenVPNNetworkSettingsBuilder.h"
#import "OpenVPNPacketFlowBridge.h"
#import "OpenVPNProperties+Internal.h"
#import "OpenVPNSessionToken+Internal.h"
#import "OpenVPNTransportStats+Internal.h"
#import "OpenVPNAdapter.h"
#import "NSError+OpenVPNError.h"
class Client;
@interface OpenVPNAdapter () <OpenVPNClientDelegate>
@interface OpenVPNAdapter ()
@property (nonatomic) Client *client;
@property (nonatomic) NSString *sessionName;
@property (nonatomic) OpenVPNNetworkSettingsBuilder *networkSettingsBuilder;
@property (nonatomic) OpenVPNClient *vpnClient;
@property (nonatomic) OpenVPNPacketFlowBridge *packetFlowBridge;
- (OpenVPNAdapterError)errorByName:(NSString *)errorName;
- (OpenVPNAdapterEvent)eventByName:(NSString *)errorName;
- (NSString *)reasonForError:(OpenVPNAdapterError)error;
@property (nonatomic) OpenVPNNetworkSettingsBuilder *networkSettingsBuilder;
@end
using namespace openvpn;
class Client : public ClientAPI::OpenVPNClient {
public:
Client(OpenVPNAdapter *adapter) {
this->adapter = adapter;
}
bool tun_builder_set_remote_address(const std::string& address, bool ipv6) override {
NSString *remoteAddress = [[NSString alloc] initWithUTF8String:address.c_str()];
adapter.networkSettingsBuilder.remoteAddress = remoteAddress;
return true;
}
bool tun_builder_add_address(const std::string& address, int prefix_length, const std::string& gateway, bool ipv6, bool net30) override {
NSString *localAddress = [[NSString alloc] initWithUTF8String:address.c_str()];
NSString *gatewayAddress = [[NSString alloc] initWithUTF8String:gateway.c_str()];
NSString *defaultGateway = gatewayAddress.length == 0 || [gatewayAddress isEqualToString:@"UNSPEC"] ? nil : gatewayAddress;
if (ipv6) {
adapter.networkSettingsBuilder.ipv6DefaultGateway = defaultGateway;
[adapter.networkSettingsBuilder.ipv6LocalAddresses addObject:localAddress];
[adapter.networkSettingsBuilder.ipv6NetworkPrefixLengths addObject:@(prefix_length)];
} else {
NSString *subnetMask = [[NSString alloc] initWithUTF8String:IPv4::Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
adapter.networkSettingsBuilder.ipv4DefaultGateway = defaultGateway;
[adapter.networkSettingsBuilder.ipv4LocalAddresses addObject:localAddress];
[adapter.networkSettingsBuilder.ipv4SubnetMasks addObject:subnetMask];
}
return true;
}
bool tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) override {
if (ipv4) {
NEIPv4Route *includedRoute = [NEIPv4Route defaultRoute];
includedRoute.gatewayAddress = adapter.networkSettingsBuilder.ipv4DefaultGateway;
[adapter.networkSettingsBuilder.ipv4IncludedRoutes addObject:includedRoute];
}
if (ipv6) {
NEIPv6Route *includedRoute = [NEIPv6Route defaultRoute];
includedRoute.gatewayAddress = adapter.networkSettingsBuilder.ipv6DefaultGateway;
[adapter.networkSettingsBuilder.ipv6IncludedRoutes addObject:includedRoute];
}
return true;
}
bool tun_builder_add_route(const std::string& address, int prefix_length, int metric, bool ipv6) override {
NSString *route = [[NSString alloc] initWithUTF8String:address.c_str()];
if (ipv6) {
NEIPv6Route *includedRoute = [[NEIPv6Route alloc] initWithDestinationAddress:route networkPrefixLength:@(prefix_length)];
includedRoute.gatewayAddress = adapter.networkSettingsBuilder.ipv6DefaultGateway;
[adapter.networkSettingsBuilder.ipv6IncludedRoutes addObject:includedRoute];
} else {
NSString *subnetMask = [[NSString alloc] initWithUTF8String:IPv4::Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
NEIPv4Route *includedRoute = [[NEIPv4Route alloc] initWithDestinationAddress:route subnetMask:subnetMask];
includedRoute.gatewayAddress = adapter.networkSettingsBuilder.ipv4DefaultGateway;
[adapter.networkSettingsBuilder.ipv4IncludedRoutes addObject:includedRoute];
}
return true;
}
bool tun_builder_exclude_route(const std::string& address, int prefix_length, int metric, bool ipv6) override {
NSString *route = [[NSString alloc] initWithUTF8String:address.c_str()];
if (ipv6) {
NEIPv6Route *excludedRoute = [[NEIPv6Route alloc] initWithDestinationAddress:route networkPrefixLength:@(prefix_length)];
[adapter.networkSettingsBuilder.ipv6ExcludedRoutes addObject:excludedRoute];
} else {
NSString *subnetMask = [[NSString alloc] initWithUTF8String:IPv4::Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
NEIPv4Route *excludedRoute = [[NEIPv4Route alloc] initWithDestinationAddress:route subnetMask:subnetMask];
[adapter.networkSettingsBuilder.ipv4ExcludedRoutes addObject:excludedRoute];
}
return true;
}
bool tun_builder_add_dns_server(const std::string& address, bool ipv6) override {
NSString *dnsAddress = [[NSString alloc] initWithUTF8String:address.c_str()];
[adapter.networkSettingsBuilder.dnsServers addObject:dnsAddress];
return true;
}
bool tun_builder_add_search_domain(const std::string& domain) override {
NSString *searchDomain = [[NSString alloc] initWithUTF8String:domain.c_str()];
[adapter.networkSettingsBuilder.searchDomains addObject:searchDomain];
return true;
}
bool tun_builder_set_mtu(int mtu) override {
adapter.networkSettingsBuilder.mtu = @(mtu);
return true;
}
bool tun_builder_set_session_name(const std::string& name) override {
adapter.sessionName = [[NSString alloc] initWithUTF8String:name.c_str()];
return true;
}
bool tun_builder_add_proxy_bypass(const std::string& bypass_host) override {
NSString *bypassHost = [[NSString alloc] initWithUTF8String:bypass_host.c_str()];
[adapter.networkSettingsBuilder.proxyExceptionList addObject:bypassHost];
return true;
}
bool tun_builder_set_proxy_auto_config_url(const std::string& urlString) override {
NSURL *url = [[NSURL alloc] initWithString:[[NSString alloc] initWithUTF8String:urlString.c_str()]];
adapter.networkSettingsBuilder.autoProxyConfigurationEnabled = url != nil;
adapter.networkSettingsBuilder.proxyAutoConfigurationURL = url;
return true;
}
bool tun_builder_set_proxy_http(const std::string& host, int port) override {
NSString *address = [[NSString alloc] initWithUTF8String:host.c_str()];
adapter.networkSettingsBuilder.httpProxyServerEnabled = YES;
adapter.networkSettingsBuilder.httpProxyServer = [[NEProxyServer alloc] initWithAddress:address port:port];
return true;
}
bool tun_builder_set_proxy_https(const std::string& host, int port) override {
NSString *address = [[NSString alloc] initWithUTF8String:host.c_str()];
adapter.networkSettingsBuilder.httpsProxyServerEnabled = YES;
adapter.networkSettingsBuilder.httpsProxyServer = [[NEProxyServer alloc] initWithAddress:address port:port];
return true;
}
bool tun_builder_set_block_ipv6(bool block_ipv6) override {
return false;
}
bool tun_builder_new() override {
reset_tun();
return true;
}
int tun_builder_establish() override {
NEPacketTunnelNetworkSettings *networkSettings = adapter.networkSettingsBuilder.networkSettings;
if (!networkSettings) {
return -1;
}
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[adapter.delegate openVPNAdapter:adapter configureTunnelWithNetworkSettings:networkSettings completionHandler:^(NEPacketTunnelFlow * _Nullable flow) {
adapter.packetFlowBridge = [[OpenVPNPacketFlowBridge alloc] initWithPacketFlow:flow];
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC));
if (adapter.packetFlowBridge) {
return adapter.packetFlowBridge.socketHandle;
} else {
return -1;
}
}
void tun_builder_teardown(bool disconnect) override {
reset_tun();
}
bool tun_builder_persist() override {
return true;
}
bool socket_protect(int socket) override {
return true;
}
bool pause_on_connection_timeout() override {
return false;
}
void external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) override {
}
void external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) override {
}
void event(const ClientAPI::Event& event) override {
NSString *name = [[NSString alloc] initWithUTF8String:event.name.c_str()];
NSString *message = [[NSString alloc] initWithUTF8String:event.info.c_str()];
if (event.error) {
OpenVPNAdapterError errorCode = [adapter errorByName:name];
NSString *errorReason = [adapter reasonForError:errorCode];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"OpenVPN error occured.",
NSLocalizedFailureReasonErrorKey: errorReason,
OpenVPNAdapterErrorMessageKey: message != nil ? message : @"",
OpenVPNAdapterErrorFatalKey: @(event.fatal) };
NSError *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo];
[adapter.delegate openVPNAdapter:adapter handleError:error];
} else {
OpenVPNAdapterEvent eventIdentifier = [adapter eventByName:name];
[adapter.delegate openVPNAdapter:adapter handleEvent:eventIdentifier message:message.length ? message : nil];
}
}
void log(const ClientAPI::LogInfo& log) override {
if ([adapter.delegate respondsToSelector:@selector(openVPNAdapter:handleLogMessage:)]) {
[adapter.delegate openVPNAdapter:adapter handleLogMessage:[[NSString alloc] initWithUTF8String:log.text.c_str()]];
}
}
void clock_tick() override {
if ([adapter.delegate respondsToSelector:@selector(openVPNAdapterDidReceiveClockTick:)]) {
[adapter.delegate openVPNAdapterDidReceiveClockTick:adapter];
}
}
void reset_tun() {
adapter.packetFlowBridge = nil;
adapter.networkSettingsBuilder = nil;
adapter.sessionName = nil;
}
private:
OpenVPNAdapter *adapter;
};
@implementation OpenVPNAdapter
#pragma mark - Initialization
- (instancetype)init {
if ((self = [super init])) {
self.client = new Client(self);
if (self = [super init]) {
_vpnClient = new OpenVPNClient(self);
}
return self;
}
@@ -274,19 +48,17 @@ private:
#pragma mark - OpenVPNClient Lifecycle
- (OpenVPNProperties *)applyConfiguration:(OpenVPNConfiguration *)configuration error:(NSError * _Nullable __autoreleasing *)error {
ClientAPI::EvalConfig eval = self.client->eval_config(configuration.config);
ClientAPI::EvalConfig eval = self.vpnClient->eval_config(configuration.config);
if (eval.error) {
if (error) {
NSString *errorReason = [self reasonForError:OpenVPNAdapterErrorConfigurationFailure];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to apply OpenVPN configuration.",
NSLocalizedFailureReasonErrorKey: errorReason,
OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:eval.message.c_str()],
OpenVPNAdapterErrorFatalKey: @YES };
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:OpenVPNAdapterErrorConfigurationFailure userInfo: userInfo];
NSString *message = [NSString stringWithUTF8String:eval.message.c_str()];
*error = [NSError ovpn_errorObjectForAdapterError:OpenVPNAdapterErrorConfigurationFailure
description:@"Failed to apply OpenVPN configuration"
message:message
fatal:YES];
}
return nil;
}
@@ -294,22 +66,15 @@ private:
}
- (BOOL)provideCredentials:(OpenVPNCredentials *)credentials error:(NSError * _Nullable __autoreleasing *)error {
ClientAPI::Status status = self.client->provide_creds(credentials.credentials);
ClientAPI::Status status = self.vpnClient->provide_creds(credentials.credentials);
if (status.error) {
if (error) {
OpenVPNAdapterError errorCode = !status.status.empty() ?
[self errorByName:[[NSString alloc] initWithUTF8String:status.status.c_str()]] :
OpenVPNAdapterErrorCredentialsFailure;
NSString *errorReason = [self reasonForError:errorCode];
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to provide OpenVPN credentials.",
NSLocalizedFailureReasonErrorKey: errorReason,
OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:status.message.c_str()],
OpenVPNAdapterErrorFatalKey: @YES };
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo];
NSString *message = [NSString stringWithUTF8String:status.message.c_str()];
*error = [NSError ovpn_errorObjectForAdapterError:OpenVPNAdapterErrorCredentialsFailure
description:@"Failed to provide OpenVPN credentials"
message:message
fatal:YES];
}
return NO;
@@ -320,255 +85,273 @@ private:
- (void)connect {
dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_UTILITY, 0);
dispatch_queue_t connectQueue = dispatch_queue_create("com.openvpnadapter.connection", attributes);
dispatch_queue_t connectQueue = dispatch_queue_create("me.ss-abramchuk.openvpn-adapter.connection", attributes);
dispatch_async(connectQueue, ^{
Client::init_process();
ClientAPI::Status status = self.client->connect();
OpenVPNClient::init_process();
ClientAPI::Status status = self.vpnClient->connect();
[self handleConnectionStatus:status];
Client::uninit_process();
OpenVPNClient::uninit_process();
});
}
- (void)reconnectAfterTimeInterval:(NSTimeInterval)timeInterval {
self.client->reconnect(timeInterval);
self.vpnClient->reconnect(timeInterval);
}
- (void)disconnect {
self.client->stop();
self.vpnClient->stop();
}
- (void)pauseWithReason:(NSString *)reason {
self.client->pause(std::string(reason.UTF8String));
self.vpnClient->pause(std::string(reason.UTF8String));
}
- (void)resume {
self.client->resume();
self.vpnClient->resume();
}
- (void)handleConnectionStatus:(ClientAPI::Status)status {
if (!status.error) {
return;
}
if (!status.error) { return; }
OpenVPNAdapterError errorCode = !status.status.empty() ? [self errorByName:[[NSString alloc] initWithUTF8String:status.status.c_str()]] : OpenVPNAdapterErrorUnknown;
NSString *errorReason = [self reasonForError:errorCode];
OpenVPNAdapterError adapterError = !status.status.empty() ?
[NSError ovpn_adapterErrorByName:[NSString stringWithUTF8String:status.status.c_str()]] :
OpenVPNAdapterErrorUnknown;
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to establish connection with OpenVPN server.",
NSLocalizedFailureReasonErrorKey: errorReason,
OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:status.message.c_str()],
OpenVPNAdapterErrorFatalKey: @YES };
NSError *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo];
NSString *message = [NSString stringWithUTF8String:status.message.c_str()];
NSError *error = [NSError ovpn_errorObjectForAdapterError:adapterError
description:@"Failed to establish connection with OpenVPN server"
message:message
fatal:YES];
[self.delegate openVPNAdapter:self handleError:error];
}
#pragma mark - OpenVPNClient Information
+ (NSString *)copyright {
return [[NSString alloc] initWithUTF8String:Client::copyright().c_str()];
return [NSString stringWithUTF8String:OpenVPNClient::copyright().c_str()];
}
+ (NSString *)platform {
return [[NSString alloc] initWithUTF8String:Client::platform().c_str()];
return [NSString stringWithUTF8String:OpenVPNClient::platform().c_str()];
}
- (OpenVPNConnectionInfo *)connectionInformation {
ClientAPI::ConnectionInfo information = self.client->connection_info();
ClientAPI::ConnectionInfo information = self.vpnClient->connection_info();
return information.defined ? [[OpenVPNConnectionInfo alloc] initWithConnectionInfo:information] : nil;
}
- (OpenVPNInterfaceStats *)interfaceStatistics {
return [[OpenVPNInterfaceStats alloc] initWithInterfaceStats:self.client->tun_stats()];
return [[OpenVPNInterfaceStats alloc] initWithInterfaceStats:self.vpnClient->tun_stats()];
}
- (OpenVPNSessionToken *)sessionToken {
ClientAPI::SessionToken token;
return self.client->session_token(token) ? [[OpenVPNSessionToken alloc] initWithSessionToken:token] : nil;
return self.vpnClient->session_token(token) ? [[OpenVPNSessionToken alloc] initWithSessionToken:token] : nil;
}
- (OpenVPNTransportStats *)transportStatistics {
return [[OpenVPNTransportStats alloc] initWithTransportStats:self.client->transport_stats()];
}
#pragma mark - OpenVPNAdapterEvent Helpers
- (OpenVPNAdapterEvent)eventByName:(NSString *)eventName {
NSDictionary *events = @{@"DISCONNECTED": @(OpenVPNAdapterEventDisconnected),
@"CONNECTED": @(OpenVPNAdapterEventConnected),
@"RECONNECTING": @(OpenVPNAdapterEventReconnecting),
@"RESOLVE": @(OpenVPNAdapterEventResolve),
@"WAIT": @(OpenVPNAdapterEventWait),
@"WAIT_PROXY": @(OpenVPNAdapterEventWaitProxy),
@"CONNECTING": @(OpenVPNAdapterEventConnecting),
@"GET_CONFIG": @(OpenVPNAdapterEventGetConfig),
@"ASSIGN_IP": @(OpenVPNAdapterEventAssignIP),
@"ADD_ROUTES": @(OpenVPNAdapterEventAddRoutes),
@"ECHO": @(OpenVPNAdapterEventEcho),
@"INFO": @(OpenVPNAdapterEventInfo),
@"PAUSE": @(OpenVPNAdapterEventPause),
@"RESUME": @(OpenVPNAdapterEventResume),
@"RELAY": @(OpenVPNAdapterEventRelay)};
OpenVPNAdapterEvent event = events[eventName] != nil ? (OpenVPNAdapterEvent)[events[eventName] integerValue] : OpenVPNAdapterEventUnknown;
return event;
}
#pragma mark - OpenVPNAdapterError Helpers
- (OpenVPNAdapterError)errorByName:(NSString *)errorName {
NSDictionary *errors = @{@"NETWORK_RECV_ERROR": @(OpenVPNAdapterErrorNetworkRecvError),
@"NETWORK_EOF_ERROR": @(OpenVPNAdapterErrorNetworkEOFError),
@"NETWORK_SEND_ERROR": @(OpenVPNAdapterErrorNetworkSendError),
@"NETWORK_UNAVAILABLE": @(OpenVPNAdapterErrorNetworkUnavailable),
@"DECRYPT_ERROR": @(OpenVPNAdapterErrorDecryptError),
@"HMAC_ERROR": @(OpenVPNAdapterErrorDecryptError),
@"REPLAY_ERROR": @(OpenVPNAdapterErrorReplayError),
@"BUFFER_ERROR": @(OpenVPNAdapterErrorBufferError),
@"CC_ERROR": @(OpenVPNAdapterErrorCCError),
@"BAD_SRC_ADDR": @(OpenVPNAdapterErrorBadSrcAddr),
@"COMPRESS_ERROR": @(OpenVPNAdapterErrorCompressError),
@"RESOLVE_ERROR": @(OpenVPNAdapterErrorResolveError),
@"SOCKET_PROTECT_ERROR": @(OpenVPNAdapterErrorSocketProtectError),
@"TUN_READ_ERROR": @(OpenVPNAdapterErrorTUNReadError),
@"TUN_WRITE_ERROR": @(OpenVPNAdapterErrorTUNWriteError),
@"TUN_FRAMING_ERROR": @(OpenVPNAdapterErrorTUNFramingError),
@"TUN_SETUP_FAILED": @(OpenVPNAdapterErrorTUNSetupFailed),
@"TUN_IFACE_CREATE": @(OpenVPNAdapterErrorTUNIfaceCreate),
@"TUN_IFACE_DISABLED": @(OpenVPNAdapterErrorTUNIfaceDisabled),
@"TUN_ERROR": @(OpenVPNAdapterErrorTUNError),
@"TAP_NOT_SUPPORTED": @(OpenVPNAdapterErrorTAPNotSupported),
@"REROUTE_GW_NO_DNS": @(OpenVPNAdapterErrorRerouteGatewayNoDns),
@"TRANSPORT_ERROR": @(OpenVPNAdapterErrorTransportError),
@"TCP_OVERFLOW": @(OpenVPNAdapterErrorTCPOverflow),
@"TCP_SIZE_ERROR": @(OpenVPNAdapterErrorTCPSizeError),
@"TCP_CONNECT_ERROR": @(OpenVPNAdapterErrorTCPConnectError),
@"UDP_CONNECT_ERROR": @(OpenVPNAdapterErrorUDPConnectError),
@"SSL_ERROR": @(OpenVPNAdapterErrorSSLError),
@"SSL_PARTIAL_WRITE": @(OpenVPNAdapterErrorSSLPartialWrite),
@"ENCAPSULATION_ERROR": @(OpenVPNAdapterErrorEncapsulationError),
@"EPKI_CERT_ERROR": @(OpenVPNAdapterErrorEPKICertError),
@"EPKI_SIGN_ERROR": @(OpenVPNAdapterErrorEPKISignError),
@"HANDSHAKE_TIMEOUT": @(OpenVPNAdapterErrorHandshakeTimeout),
@"KEEPALIVE_TIMEOUT": @(OpenVPNAdapterErrorKeepaliveTimeout),
@"INACTIVE_TIMEOUT": @(OpenVPNAdapterErrorInactiveTimeout),
@"CONNECTION_TIMEOUT": @(OpenVPNAdapterErrorConnectionTimeout),
@"PRIMARY_EXPIRE": @(OpenVPNAdapterErrorPrimaryExpire),
@"TLS_VERSION_MIN": @(OpenVPNAdapterErrorTLSVersionMin),
@"TLS_AUTH_FAIL": @(OpenVPNAdapterErrorTLSAuthFail),
@"CERT_VERIFY_FAIL": @(OpenVPNAdapterErrorCertVerifyFail),
@"PEM_PASSWORD_FAIL": @(OpenVPNAdapterErrorPEMPasswordFail),
@"AUTH_FAILED": @(OpenVPNAdapterErrorAuthFailed),
@"CLIENT_HALT": @(OpenVPNAdapterErrorClientHalt),
@"CLIENT_RESTART": @(OpenVPNAdapterErrorClientRestart),
@"RELAY": @(OpenVPNAdapterErrorRelay),
@"RELAY_ERROR": @(OpenVPNAdapterErrorRelayError),
@"N_PAUSE": @(OpenVPNAdapterErrorPauseNumber),
@"N_RECONNECT": @(OpenVPNAdapterErrorReconnectNumber),
@"N_KEY_LIMIT_RENEG": @(OpenVPNAdapterErrorKeyLimitRenegNumber),
@"KEY_STATE_ERROR": @(OpenVPNAdapterErrorKeyStateError),
@"PROXY_ERROR": @(OpenVPNAdapterErrorProxyError),
@"PROXY_NEED_CREDS": @(OpenVPNAdapterErrorProxyNeedCreds),
@"KEV_NEGOTIATE_ERROR": @(OpenVPNAdapterErrorKevNegotiateError),
@"KEV_PENDING_ERROR": @(OpenVPNAdapterErrorKevPendingError),
@"N_KEV_EXPIRE": @(OpenVPNAdapterErrorKevExpireNumber),
@"PKTID_INVALID": @(OpenVPNAdapterErrorPKTIDInvalid),
@"PKTID_BACKTRACK": @(OpenVPNAdapterErrorPKTIDBacktrack),
@"PKTID_EXPIRE": @(OpenVPNAdapterErrorPKTIDExpire),
@"PKTID_REPLAY": @(OpenVPNAdapterErrorPKTIDReplay),
@"PKTID_TIME_BACKTRACK": @(OpenVPNAdapterErrorPKTIDTimeBacktrack),
@"DYNAMIC_CHALLENGE": @(OpenVPNAdapterErrorDynamicChallenge),
@"EPKI_ERROR": @(OpenVPNAdapterErrorEPKIError),
@"EPKI_INVALID_ALIAS": @(OpenVPNAdapterErrorEPKIInvalidAlias)};
OpenVPNAdapterError error = errors[errorName] != nil ? (OpenVPNAdapterError)[errors[errorName] integerValue] : OpenVPNAdapterErrorUnknown;
return error;
}
- (NSString *)reasonForError:(OpenVPNAdapterError)error {
// TODO: Add missing error reasons
switch (error) {
case OpenVPNAdapterErrorConfigurationFailure: return @"See OpenVPN error message for more details.";
case OpenVPNAdapterErrorCredentialsFailure: return @"See OpenVPN error message for more details.";
case OpenVPNAdapterErrorNetworkRecvError: return @"Errors receiving on network socket.";
case OpenVPNAdapterErrorNetworkEOFError: return @"EOF received on TCP network socket.";
case OpenVPNAdapterErrorNetworkSendError: return @"Errors sending on network socket";
case OpenVPNAdapterErrorNetworkUnavailable: return @"Network unavailable.";
case OpenVPNAdapterErrorDecryptError: return @"Data channel encrypt/decrypt error.";
case OpenVPNAdapterErrorHMACError: return @"HMAC verification failure.";
case OpenVPNAdapterErrorReplayError: return @"Error from PacketIDReceive.";
case OpenVPNAdapterErrorBufferError: return @"Exception thrown in Buffer methods.";
case OpenVPNAdapterErrorCCError: return @"General control channel errors.";
case OpenVPNAdapterErrorBadSrcAddr: return @"Packet from unknown source address.";
case OpenVPNAdapterErrorCompressError: return @"Compress/Decompress errors on data channel.";
case OpenVPNAdapterErrorResolveError: return @"DNS resolution error.";
case OpenVPNAdapterErrorSocketProtectError: return @"Error calling protect() method on socket.";
case OpenVPNAdapterErrorTUNReadError: return @"Read errors on TUN/TAP interface.";
case OpenVPNAdapterErrorTUNWriteError: return @"Write errors on TUN/TAP interface.";
case OpenVPNAdapterErrorTUNFramingError: return @"Error with tun PF_INET/PF_INET6 prefix.";
case OpenVPNAdapterErrorTUNSetupFailed: return @"Error setting up TUN/TAP interface.";
case OpenVPNAdapterErrorTUNIfaceCreate: return @"Error creating TUN/TAP interface.";
case OpenVPNAdapterErrorTUNIfaceDisabled: return @"TUN/TAP interface is disabled.";
case OpenVPNAdapterErrorTUNError: return @"General tun error.";
case OpenVPNAdapterErrorTAPNotSupported: return @"Dev TAP is present in profile but not supported.";
case OpenVPNAdapterErrorRerouteGatewayNoDns: return @"redirect-gateway specified without alt DNS servers.";
case OpenVPNAdapterErrorTransportError: return @"General transport error";
case OpenVPNAdapterErrorTCPOverflow: return @"TCP output queue overflow.";
case OpenVPNAdapterErrorTCPSizeError: return @"Bad embedded uint16_t TCP packet size.";
case OpenVPNAdapterErrorTCPConnectError: return @"Client error on TCP connect.";
case OpenVPNAdapterErrorUDPConnectError: return @"Client error on UDP connect.";
case OpenVPNAdapterErrorSSLError: return @"Errors resulting from read/write on SSL object.";
case OpenVPNAdapterErrorSSLPartialWrite: return @"SSL object did not process all written cleartext.";
case OpenVPNAdapterErrorEncapsulationError: return @"Exceptions thrown during packet encapsulation.";
case OpenVPNAdapterErrorEPKICertError: return @"Error obtaining certificate from External PKI provider.";
case OpenVPNAdapterErrorEPKISignError: return @"Error obtaining RSA signature from External PKI provider.";
case OpenVPNAdapterErrorHandshakeTimeout: return @"Handshake failed to complete within given time frame.";
case OpenVPNAdapterErrorKeepaliveTimeout: return @"Lost contact with peer.";
case OpenVPNAdapterErrorInactiveTimeout: return @"Disconnected due to inactive timer.";
case OpenVPNAdapterErrorConnectionTimeout: return @"Connection failed to establish within given time.";
case OpenVPNAdapterErrorPrimaryExpire: return @"Primary key context expired.";
case OpenVPNAdapterErrorTLSVersionMin: return @"Peer cannot handshake at our minimum required TLS version.";
case OpenVPNAdapterErrorTLSAuthFail: return @"tls-auth HMAC verification failed.";
case OpenVPNAdapterErrorCertVerifyFail: return @"Peer certificate verification failure.";
case OpenVPNAdapterErrorPEMPasswordFail: return @"Incorrect or missing PEM private key decryption password.";
case OpenVPNAdapterErrorAuthFailed: return @"General authentication failure";
case OpenVPNAdapterErrorClientHalt: return @"HALT message from server received.";
case OpenVPNAdapterErrorClientRestart: return @"RESTART message from server received.";
case OpenVPNAdapterErrorRelay: return @"RELAY message from server received.";
case OpenVPNAdapterErrorRelayError: return @"RELAY error.";
case OpenVPNAdapterErrorPauseNumber: return @"";
case OpenVPNAdapterErrorReconnectNumber: return @"";
case OpenVPNAdapterErrorKeyLimitRenegNumber: return @"";
case OpenVPNAdapterErrorKeyStateError: return @"Received packet didn't match expected key state.";
case OpenVPNAdapterErrorProxyError: return @"HTTP proxy error.";
case OpenVPNAdapterErrorProxyNeedCreds: return @"HTTP proxy needs credentials.";
case OpenVPNAdapterErrorKevNegotiateError: return @"";
case OpenVPNAdapterErrorKevPendingError: return @"";
case OpenVPNAdapterErrorKevExpireNumber: return @"";
case OpenVPNAdapterErrorPKTIDInvalid: return @"";
case OpenVPNAdapterErrorPKTIDBacktrack: return @"";
case OpenVPNAdapterErrorPKTIDExpire: return @"";
case OpenVPNAdapterErrorPKTIDReplay: return @"";
case OpenVPNAdapterErrorPKTIDTimeBacktrack: return @"";
case OpenVPNAdapterErrorDynamicChallenge: return @"";
case OpenVPNAdapterErrorEPKIError: return @"";
case OpenVPNAdapterErrorEPKIInvalidAlias: return @"";
case OpenVPNAdapterErrorUnknown: return @"Unknown error.";
}
return [[OpenVPNTransportStats alloc] initWithTransportStats:self.vpnClient->transport_stats()];
}
#pragma mark - Lazy Initialization
- (OpenVPNNetworkSettingsBuilder *)networkSettingsBuilder {
if (!_networkSettingsBuilder) {
_networkSettingsBuilder = [[OpenVPNNetworkSettingsBuilder alloc] init];
}
if (!_networkSettingsBuilder) { _networkSettingsBuilder = [[OpenVPNNetworkSettingsBuilder alloc] init]; }
return _networkSettingsBuilder;
}
#pragma mark - Dealloc
#pragma mark - OpenVPNClientDelegate
- (BOOL)setRemoteAddress:(NSString *)address {
self.networkSettingsBuilder.remoteAddress = address;
return YES;
}
- (BOOL)addIPV4Address:(NSString *)address subnetMask:(NSString *)subnetMask gateway:(NSString *)gateway {
self.networkSettingsBuilder.ipv4DefaultGateway = gateway;
[self.networkSettingsBuilder.ipv4LocalAddresses addObject:address];
[self.networkSettingsBuilder.ipv4SubnetMasks addObject:subnetMask];
return YES;
}
- (BOOL)addIPV6Address:(NSString *)address prefixLength:(NSNumber *)prefixLength gateway:(NSString *)gateway {
self.networkSettingsBuilder.ipv6DefaultGateway = gateway;
[self.networkSettingsBuilder.ipv6LocalAddresses addObject:address];
[self.networkSettingsBuilder.ipv6NetworkPrefixLengths addObject:prefixLength];
return YES;
}
- (BOOL)addIPV4Route:(NEIPv4Route *)route {
route.gatewayAddress = self.networkSettingsBuilder.ipv4DefaultGateway;
[self.networkSettingsBuilder.ipv4IncludedRoutes addObject:route];
return YES;
}
- (BOOL)addIPV6Route:(NEIPv6Route *)route {
route.gatewayAddress = self.networkSettingsBuilder.ipv6DefaultGateway;
[self.networkSettingsBuilder.ipv6IncludedRoutes addObject:route];
return YES;
}
- (BOOL)excludeIPV4Route:(NEIPv4Route *)route {
[self.networkSettingsBuilder.ipv4ExcludedRoutes addObject:route];
return YES;
}
- (BOOL)excludeIPV6Route:(NEIPv6Route *)route {
[self.networkSettingsBuilder.ipv6ExcludedRoutes addObject:route];
return YES;
}
- (BOOL)addDNS:(NSString *)dns {
[self.networkSettingsBuilder.dnsServers addObject:dns];
return YES;
}
- (BOOL)addSearchDomain:(NSString *)domain {
[self.networkSettingsBuilder.searchDomains addObject:domain];
return YES;
}
- (BOOL)setMTU:(NSNumber *)mtu {
self.networkSettingsBuilder.mtu = mtu;
return YES;
}
- (BOOL)setSessionName:(NSString *)name {
_sessionName = name;
return YES;
}
- (BOOL)addProxyBypassHost:(NSString *)bypassHost {
[self.networkSettingsBuilder.proxyExceptionList addObject:bypassHost];
return YES;
}
- (BOOL)setProxyAutoConfigurationURL:(NSURL *)url {
self.networkSettingsBuilder.autoProxyConfigurationEnabled = YES;
self.networkSettingsBuilder.proxyAutoConfigurationURL = url;
return YES;
}
- (BOOL)setProxyServer:(NEProxyServer *)server protocol:(OpenVPNProxyServerProtocol)protocol {
switch (protocol) {
case OpenVPNProxyServerProtocolHTTP:
self.networkSettingsBuilder.httpProxyServerEnabled = YES;
self.networkSettingsBuilder.httpProxyServer = server;
break;
case OpenVPNProxyServerProtocolHTTPS:
self.networkSettingsBuilder.httpsProxyServerEnabled = YES;
self.networkSettingsBuilder.httpsProxyServer = server;
break;
}
return YES;
}
- (BOOL)establishTunnel {
NEPacketTunnelNetworkSettings *networkSettings = [self.networkSettingsBuilder networkSettings];
if (!networkSettings) { return NO; }
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__weak typeof(self) weakSelf = self;
void (^completionHandler)(id<OpenVPNAdapterPacketFlow> _Nullable) = ^(id<OpenVPNAdapterPacketFlow> flow) {
__strong typeof(self) self = weakSelf;
if (flow) {
self.packetFlowBridge = [[OpenVPNPacketFlowBridge alloc] initWithPacketFlow:flow];
}
dispatch_semaphore_signal(semaphore);
};
[self.delegate openVPNAdapter:self configureTunnelWithNetworkSettings:networkSettings completionHandler:completionHandler];
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC));
NSError *socketError;
if (self.packetFlowBridge && [self.packetFlowBridge configureSocketsWithError:&socketError]) {
[self.packetFlowBridge startReading];
return YES;
} else {
if (socketError) { [self.delegate openVPNAdapter:self handleError:socketError]; }
return NO;
}
}
- (CFSocketNativeHandle)socketHandle {
return CFSocketGetNative(self.packetFlowBridge.openVPNSocket);
}
- (void)clientEventName:(NSString *)eventName message:(NSString *)message {
NSDictionary *events = @{
@"DISCONNECTED": @(OpenVPNAdapterEventDisconnected),
@"CONNECTED": @(OpenVPNAdapterEventConnected),
@"RECONNECTING": @(OpenVPNAdapterEventReconnecting),
@"RESOLVE": @(OpenVPNAdapterEventResolve),
@"WAIT": @(OpenVPNAdapterEventWait),
@"WAIT_PROXY": @(OpenVPNAdapterEventWaitProxy),
@"CONNECTING": @(OpenVPNAdapterEventConnecting),
@"GET_CONFIG": @(OpenVPNAdapterEventGetConfig),
@"ASSIGN_IP": @(OpenVPNAdapterEventAssignIP),
@"ADD_ROUTES": @(OpenVPNAdapterEventAddRoutes),
@"ECHO": @(OpenVPNAdapterEventEcho),
@"INFO": @(OpenVPNAdapterEventInfo),
@"PAUSE": @(OpenVPNAdapterEventPause),
@"RESUME": @(OpenVPNAdapterEventResume),
@"RELAY": @(OpenVPNAdapterEventRelay)
};
OpenVPNAdapterEvent event = events[eventName] != nil ?
(OpenVPNAdapterEvent)[events[eventName] integerValue] : OpenVPNAdapterEventUnknown;
[self.delegate openVPNAdapter:self handleEvent:event message:message];
}
- (void)clientErrorName:(NSString *)errorName fatal:(BOOL)fatal message:(NSString *)message {
OpenVPNAdapterError adapterError = [NSError ovpn_adapterErrorByName:errorName];
NSString *description = fatal ? @"OpenVPN fatal error occured" : @"OpenVPN error occured";
NSError *error = [NSError ovpn_errorObjectForAdapterError:adapterError
description:description
message:message
fatal:YES];
[self.delegate openVPNAdapter:self handleError:error];
}
- (void)clientLogMessage:(NSString *)logMessage {
if ([self.delegate respondsToSelector:@selector(openVPNAdapter:handleLogMessage:)]) {
[self.delegate openVPNAdapter:self handleLogMessage:logMessage];
}
}
- (void)tick {
if ([self.delegate respondsToSelector:@selector(openVPNAdapterDidReceiveClockTick:)]) {
[self.delegate openVPNAdapterDidReceiveClockTick:self];
}
}
- (void)resetSettings {
_sessionName = nil;
_packetFlowBridge = nil;
_networkSettingsBuilder = nil;
}
#pragma mark -
- (void)dealloc {
delete _client;
delete _vpnClient;
}
@end

View File

@@ -0,0 +1,39 @@
//
// OpenVPNAdapterPacketFlow.h
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 15.01.2018.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol OpenVPNAdapterPacketFlow <NSObject>
/**
Read IP packets from the TUN interface.
@param completionHandler A block that is executed when some packets are read from the TUN interface. The packets that were
read are passed to this block in the packets array. The protocol numbers of the packets that were read are passed to this
block in the protocols array. Each packet has a protocol number in the corresponding index in the protocols array. The
protocol numbers are given in host byte order. Valid protocol numbers include PF_INET and PF_INET6. See /usr/include/sys/socket.h.
*/
- (void)readPacketsWithCompletionHandler:(void (^)(NSArray<NSData *> *packets, NSArray<NSNumber *> *protocols))completionHandler;
/**
Write IP packets to the TUN interface
@param packets An array of NSData objects containing the IP packets to the written.
@param protocols An array of NSNumber objects containing the protocol numbers (e.g. PF_INET or PF_INET6) of the IP packets
in packets in host byte order.
@discussion The number of NSData objects in packets must be exactly equal to the number of NSNumber objects in protocols.
@return YES on success, otherwise NO.
*/
- (BOOL)writePackets:(NSArray<NSData *> *)packets withProtocols:(NSArray<NSNumber *> *)protocols;
@end
NS_ASSUME_NONNULL_END

View File

@@ -11,14 +11,14 @@
@interface OpenVPNCertificate : NSObject
+ (nullable OpenVPNCertificate *)certificateWithPEM:(nonnull NSData *)pemData
error:(out NSError * __nullable * __nullable)error;
error:(out NSError * _Nullable * _Nullable)error;
+ (nullable OpenVPNCertificate *)certificateWithDER:(nonnull NSData *)derData
error:(out NSError * __nullable * __nullable)error;
error:(out NSError * _Nullable * _Nullable)error;
- (nonnull instancetype) __unavailable init;
- (nonnull instancetype) init NS_UNAVAILABLE;
- (nullable NSData *)pemData:(out NSError * __nullable * __nullable)error;
- (nullable NSData *)derData:(out NSError * __nullable * __nullable)error;
- (nullable NSData *)pemData:(out NSError * _Nullable * _Nullable)error;
- (nullable NSData *)derData:(out NSError * _Nullable * _Nullable)error;
@end

View File

@@ -5,14 +5,13 @@
// Created by Sergey Abramchuk on 06.09.17.
//
//
#import <mbedtls/x509_crt.h>
#import <mbedtls/pem.h>
#import "NSError+Message.h"
#import "OpenVPNError.h"
#import "OpenVPNCertificate.h"
#include <mbedtls/x509_crt.h>
#include <mbedtls/pem.h>
#import "NSError+OpenVPNError.h"
@interface OpenVPNCertificate ()
@property (nonatomic, assign) mbedtls_x509_crt *crt;
@@ -21,16 +20,6 @@
@implementation OpenVPNCertificate
- (instancetype)init
{
self = [super init];
if (self) {
self.crt = malloc(sizeof(mbedtls_x509_crt));
mbedtls_x509_crt_init(self.crt);
}
return self;
}
+ (OpenVPNCertificate *)certificateWithPEM:(NSData *)pemData error:(out NSError **)error {
OpenVPNCertificate *certificate = [OpenVPNCertificate new];
@@ -39,11 +28,7 @@
int result = mbedtls_x509_crt_parse(certificate.crt, (const unsigned char *)pemString.UTF8String, pemData.length + 1);
if (result < 0) {
if (error) {
NSString *reason = [NSError reasonFromResult:result];
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
NSLocalizedDescriptionKey: @"Failed to read PEM data.",
NSLocalizedFailureReasonErrorKey: reason
}];
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to read PEM data"];
}
return nil;
@@ -58,11 +43,7 @@
int result = mbedtls_x509_crt_parse_der(certificate.crt, derData.bytes, derData.length);
if (result < 0) {
if (error) {
NSString *reason = [NSError reasonFromResult:result];
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
NSLocalizedDescriptionKey: @"Failed to read DER data.",
NSLocalizedFailureReasonErrorKey: reason
}];
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to read DER data"];
}
return nil;
@@ -71,6 +52,15 @@
return certificate;
}
- (instancetype)init
{
if (self = [super init]) {
_crt = malloc(sizeof(mbedtls_x509_crt));
mbedtls_x509_crt_init(_crt);
}
return self;
}
- (NSData *)pemData:(out NSError **)error {
NSString *header = @"-----BEGIN CERTIFICATE-----\n";
NSString *footer = @"-----END CERTIFICATE-----\n";
@@ -80,14 +70,11 @@
size_t output_length = 0;
int result = mbedtls_pem_write_buffer(header.UTF8String, footer.UTF8String, self.crt->raw.p, self.crt->raw.len, pem_buffer, buffer_length, &output_length);
int result = mbedtls_pem_write_buffer(header.UTF8String, footer.UTF8String, self.crt->raw.p,
self.crt->raw.len, pem_buffer, buffer_length, &output_length);
if (result < 0) {
if (error) {
NSString *reason = [NSError reasonFromResult:result];
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
NSLocalizedDescriptionKey: @"Failed to write PEM data.",
NSLocalizedFailureReasonErrorKey: reason
}];
*error = [NSError ovpn_errorObjectForMbedTLSError:result description: @"Failed to write PEM data"];
}
free(pem_buffer);
@@ -103,11 +90,8 @@
- (NSData *)derData:(out NSError **)error {
if (self.crt->raw.p == NULL || self.crt->raw.len == 0) {
if (error) {
NSString *reason = [NSError reasonFromResult:MBEDTLS_ERR_X509_BAD_INPUT_DATA];
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:MBEDTLS_ERR_X509_BAD_INPUT_DATA userInfo:@{
NSLocalizedDescriptionKey: @"Failed to write DER data.",
NSLocalizedFailureReasonErrorKey:reason
}];
*error = [NSError ovpn_errorObjectForMbedTLSError:MBEDTLS_ERR_X509_BAD_INPUT_DATA
description: @"Failed to write DER data"];
}
return nil;
@@ -117,8 +101,8 @@
}
- (void)dealloc {
mbedtls_x509_crt_free(self.crt);
free(self.crt);
mbedtls_x509_crt_free(_crt);
free(_crt);
}
@end

View File

@@ -0,0 +1,101 @@
//
// OpenVPNClient.h
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 11.01.2018.
//
#import <Foundation/Foundation.h>
#include <client/ovpncli.hpp>
@class NEIPv4Route;
@class NEIPv6Route;
@class NEProxyServer;
typedef NS_ENUM(NSInteger, OpenVPNProxyServerProtocol) {
OpenVPNProxyServerProtocolHTTP,
OpenVPNProxyServerProtocolHTTPS
};
NS_ASSUME_NONNULL_BEGIN
@protocol OpenVPNClientDelegate <NSObject>
- (BOOL)setRemoteAddress:(NSString *)address;
- (BOOL)addIPV4Address:(NSString *)address subnetMask:(NSString *)subnetMask gateway:(nullable NSString *)gateway;
- (BOOL)addIPV6Address:(NSString *)address prefixLength:(NSNumber *)prefixLength gateway:(nullable NSString *)gateway;
- (BOOL)addIPV4Route:(NEIPv4Route *)route;
- (BOOL)addIPV6Route:(NEIPv6Route *)route;
- (BOOL)excludeIPV4Route:(NEIPv4Route *)route;
- (BOOL)excludeIPV6Route:(NEIPv6Route *)route;
- (BOOL)addDNS:(NSString *)dns;
- (BOOL)addSearchDomain:(NSString *)domain;
- (BOOL)setMTU:(NSNumber *)mtu;
- (BOOL)setSessionName:(NSString *)name;
- (BOOL)addProxyBypassHost:(NSString *)bypassHost;
- (BOOL)setProxyAutoConfigurationURL:(NSURL *)url;
- (BOOL)setProxyServer:(NEProxyServer *)server protocol:(OpenVPNProxyServerProtocol)protocol;
- (BOOL)establishTunnel;
- (CFSocketNativeHandle)socketHandle;
- (void)clientEventName:(NSString *)eventName message:(nullable NSString *)message;
- (void)clientErrorName:(NSString *)errorName fatal:(BOOL)fatal message:(nullable NSString *)message;
- (void)clientLogMessage:(NSString *)logMessage;
- (void)tick;
- (void)resetSettings;
@end
NS_ASSUME_NONNULL_END
using namespace openvpn;
class OpenVPNClient : public ClientAPI::OpenVPNClient {
public:
OpenVPNClient(id<OpenVPNClientDelegate> _Nonnull delegate);
bool tun_builder_new() override;
bool tun_builder_set_remote_address(const std::string& address, bool ipv6) override;
bool tun_builder_add_address(const std::string& address, int prefix_length, const std::string& gateway,
bool ipv6, bool net30) override;
bool tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) override;
bool tun_builder_add_route(const std::string& address, int prefix_length, int metric, bool ipv6) override;
bool tun_builder_exclude_route(const std::string& address, int prefix_length, int metric, bool ipv6) override;
bool tun_builder_add_dns_server(const std::string& address, bool ipv6) override;
bool tun_builder_add_search_domain(const std::string& domain) override;
bool tun_builder_set_mtu(int mtu) override;
bool tun_builder_set_session_name(const std::string& name) override;
bool tun_builder_add_proxy_bypass(const std::string& bypass_host) override;
bool tun_builder_set_proxy_auto_config_url(const std::string& urlString) override;
bool tun_builder_set_proxy_http(const std::string& host, int port) override;
bool tun_builder_set_proxy_https(const std::string& host, int port) override;
bool tun_builder_set_block_ipv6(bool block_ipv6) override;
int tun_builder_establish() override;
bool tun_builder_persist() override;
void tun_builder_teardown(bool disconnect) override;
bool socket_protect(int socket) override;
bool pause_on_connection_timeout() override;
void external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) override;
void external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) override;
void event(const ClientAPI::Event& event) override;
void log(const ClientAPI::LogInfo& log) override;
void clock_tick() override;
private:
__weak id<OpenVPNClientDelegate> _Nonnull delegate;
};

View File

@@ -0,0 +1,173 @@
//
// OpenVPNClient.m
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 11.01.2018.
//
#define INVALID_SOCKET -1
#import "OpenVPNClient.h"
#import <NetworkExtension/NetworkExtension.h>
#include <openvpn/addr/ipv4.hpp>
using ::IPv4::Addr;
OpenVPNClient::OpenVPNClient(id<OpenVPNClientDelegate> delegate): ClientAPI::OpenVPNClient() {
this->delegate = delegate;
}
bool OpenVPNClient::tun_builder_new() {
[this->delegate resetSettings];
return true;
}
bool OpenVPNClient::tun_builder_set_remote_address(const std::string &address, bool ipv6) {
NSString *remoteAddress = [NSString stringWithUTF8String:address.c_str()];
return [this->delegate setRemoteAddress:remoteAddress];
}
bool OpenVPNClient::tun_builder_add_address(const std::string &address, int prefix_length, const std::string &gateway, bool ipv6, bool net30) {
NSString *localAddress = [NSString stringWithUTF8String:address.c_str()];
NSString *gatewayAddress = gateway.length() == 0 || gateway.compare("UNSPEC") == 0 ? nil :
[NSString stringWithUTF8String:gateway.c_str()];
if (ipv6) {
return [this->delegate addIPV6Address:localAddress prefixLength:@(prefix_length) gateway:gatewayAddress];
} else {
NSString *subnetMask = [NSString stringWithUTF8String:Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
return [this->delegate addIPV4Address:localAddress subnetMask:subnetMask gateway:gatewayAddress];
}
}
bool OpenVPNClient::tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) {
if (ipv4 && ![this->delegate addIPV4Route:[NEIPv4Route defaultRoute]]) {
return false;
}
if (ipv6 && ![this->delegate addIPV6Route:[NEIPv6Route defaultRoute]]) {
return false;
}
return true;
}
bool OpenVPNClient::tun_builder_add_route(const std::string& address, int prefix_length, int metric, bool ipv6) {
NSString *routeAddress = [NSString stringWithUTF8String:address.c_str()];
if (ipv6) {
NEIPv6Route *route = [[NEIPv6Route alloc] initWithDestinationAddress:routeAddress networkPrefixLength:@(prefix_length)];
return [this->delegate addIPV6Route:route];
} else {
NSString *subnetMask = [NSString stringWithUTF8String:Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
NEIPv4Route *route = [[NEIPv4Route alloc] initWithDestinationAddress:routeAddress subnetMask:subnetMask];
return [this->delegate addIPV4Route:route];
}
}
bool OpenVPNClient::tun_builder_exclude_route(const std::string& address, int prefix_length, int metric, bool ipv6) {
NSString *routeAddress = [NSString stringWithUTF8String:address.c_str()];
if (ipv6) {
NEIPv6Route *route = [[NEIPv6Route alloc] initWithDestinationAddress:routeAddress networkPrefixLength:@(prefix_length)];
return [this->delegate excludeIPV6Route:route];
} else {
NSString *subnetMask = [NSString stringWithUTF8String:Addr::netmask_from_prefix_len(prefix_length).to_string().c_str()];
NEIPv4Route *route = [[NEIPv4Route alloc] initWithDestinationAddress:routeAddress subnetMask:subnetMask];
return [this->delegate excludeIPV4Route:route];
}
}
bool OpenVPNClient::tun_builder_add_dns_server(const std::string& address, bool ipv6) {
NSString *dns = [NSString stringWithUTF8String:address.c_str()];
return [this->delegate addDNS:dns];
}
bool OpenVPNClient::tun_builder_add_search_domain(const std::string& domain) {
NSString *searchDomain = [NSString stringWithUTF8String:domain.c_str()];
return [this->delegate addSearchDomain:searchDomain];
}
bool OpenVPNClient::tun_builder_set_mtu(int mtu) {
return [this->delegate setMTU:@(mtu)];
}
bool OpenVPNClient::tun_builder_set_session_name(const std::string& name) {
NSString *sessionName = [NSString stringWithUTF8String:name.c_str()];
return [this->delegate setSessionName:sessionName];
}
bool OpenVPNClient::tun_builder_add_proxy_bypass(const std::string& bypass_host) {
NSString *bypassHost = [NSString stringWithUTF8String:bypass_host.c_str()];
return [this->delegate addProxyBypassHost:bypassHost];
}
bool OpenVPNClient::tun_builder_set_proxy_auto_config_url(const std::string& url) {
NSURL *configURL = [[NSURL alloc] initWithString:[NSString stringWithUTF8String:url.c_str()]];
if (configURL) {
return [this->delegate setProxyAutoConfigurationURL:configURL];
} else {
return false;
}
}
bool OpenVPNClient::tun_builder_set_proxy_http(const std::string& host, int port) {
NSString *proxyHost = [NSString stringWithUTF8String:host.c_str()];
NEProxyServer *proxyServer = [[NEProxyServer alloc] initWithAddress:proxyHost port:port];
return [this->delegate setProxyServer:proxyServer protocol:OpenVPNProxyServerProtocolHTTP];
}
bool OpenVPNClient::tun_builder_set_proxy_https(const std::string& host, int port) {
NSString *proxyHost = [NSString stringWithUTF8String:host.c_str()];
NEProxyServer *proxyServer = [[NEProxyServer alloc] initWithAddress:proxyHost port:port];
return [this->delegate setProxyServer:proxyServer protocol:OpenVPNProxyServerProtocolHTTPS];
}
bool OpenVPNClient::tun_builder_set_block_ipv6(bool block_ipv6) {
return block_ipv6;
}
int OpenVPNClient::tun_builder_establish() {
return [this->delegate establishTunnel] ? [this->delegate socketHandle] : INVALID_SOCKET;
}
bool OpenVPNClient::tun_builder_persist() {
return true;
}
void OpenVPNClient::tun_builder_teardown(bool disconnect) {
[this->delegate resetSettings];
}
bool OpenVPNClient::socket_protect(int socket) {
return true;
}
bool OpenVPNClient::pause_on_connection_timeout() {
return false;
}
void OpenVPNClient::external_pki_cert_request(ClientAPI::ExternalPKICertRequest& certreq) { }
void OpenVPNClient::external_pki_sign_request(ClientAPI::ExternalPKISignRequest& signreq) { }
void OpenVPNClient::event(const ClientAPI::Event& ev) {
NSString *name = [NSString stringWithUTF8String:ev.name.c_str()];
NSString *message = [NSString stringWithUTF8String:ev.info.c_str()];
if (ev.error) {
[this->delegate clientErrorName:name fatal:ev.fatal message:message.length ? message : nil];
} else {
[this->delegate clientEventName:name message:message.length ? message : nil];
}
}
void OpenVPNClient::log(const ClientAPI::LogInfo& log) {
NSString *logMessage = [NSString stringWithUTF8String:log.text.c_str()];
[this->delegate clientLogMessage:logMessage];
}
void OpenVPNClient::clock_tick() {
[this->delegate tick];
}

View File

@@ -6,29 +6,33 @@
//
//
#import <client/ovpncli.hpp>
#import "OpenVPNConfiguration.h"
#include <client/ovpncli.hpp>
using namespace openvpn;
NS_ASSUME_NONNULL_BEGIN
@interface OpenVPNConfiguration (Internal)
@property (readonly) ClientAPI::Config config;
+ (OpenVPNTransportProtocol)getTransportProtocolFromValue:(nullable NSString *)value;
+ (nonnull NSString *)getValueFromTransportProtocol:(OpenVPNTransportProtocol)protocol;
+ (NSString *)getValueFromTransportProtocol:(OpenVPNTransportProtocol)protocol;
+ (OpenVPNIPv6Preference)getIPv6PreferenceFromValue:(nullable NSString *)value;
+ (nonnull NSString *)getValueFromIPv6Preference:(OpenVPNIPv6Preference)preference;
+ (NSString *)getValueFromIPv6Preference:(OpenVPNIPv6Preference)preference;
+ (OpenVPNCompressionMode)getCompressionModeFromValue:(nullable NSString *)value;
+ (nonnull NSString *)getValueFromCompressionMode:(OpenVPNCompressionMode)compressionMode;
+ (NSString *)getValueFromCompressionMode:(OpenVPNCompressionMode)compressionMode;
+ (OpenVPNMinTLSVersion)getMinTLSFromValue:(nullable NSString *)value;
+ (nonnull NSString *)getValueFromMinTLS:(OpenVPNMinTLSVersion)minTLS;
+ (NSString *)getValueFromMinTLS:(OpenVPNMinTLSVersion)minTLS;
+ (OpenVPNTLSCertProfile)getTLSCertProfileFromValue:(nullable NSString *)value;
+ (nonnull NSString *)getValueFromTLSCertProfile:(OpenVPNTLSCertProfile)tlsCertProfile;
+ (NSString *)getValueFromTLSCertProfile:(OpenVPNTLSCertProfile)tlsCertProfile;
@end
NS_ASSUME_NONNULL_END

View File

@@ -8,11 +8,11 @@
#import <Foundation/Foundation.h>
#import "OpenVPNTransportProtocol.h"
#import "OpenVPNIPv6Preference.h"
#import "OpenVPNCompressionMode.h"
#import "OpenVPNMinTLSVersion.h"
#import "OpenVPNTLSCertProfile.h"
typedef NS_ENUM(NSInteger, OpenVPNTransportProtocol);
typedef NS_ENUM(NSInteger, OpenVPNIPv6Preference);
typedef NS_ENUM(NSInteger, OpenVPNCompressionMode);
typedef NS_ENUM(NSInteger, OpenVPNMinTLSVersion);
typedef NS_ENUM(NSInteger, OpenVPNTLSCertProfile);
/**
Class used to pass configuration

View File

@@ -6,8 +6,15 @@
//
//
#import "OpenVPNConfiguration.h"
#import "OpenVPNConfiguration+Internal.h"
#import "OpenVPNTransportProtocol.h"
#import "OpenVPNIPv6Preference.h"
#import "OpenVPNCompressionMode.h"
#import "OpenVPNMinTLSVersion.h"
#import "OpenVPNTLSCertProfile.h"
using namespace openvpn;
NSString *const OpenVPNTransportProtocolUDPValue = @"udp";
@@ -212,7 +219,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default";
}
- (void)setFileContent:(NSData *)fileContent {
_config.content = fileContent ? std::string((const char *)fileContent.bytes) : "";
_config.content = fileContent.length ? std::string((const char *)fileContent.bytes) : "";
}
- (NSDictionary<NSString *,NSString *> *)settings {
@@ -494,7 +501,7 @@ NSString *const OpenVPNTLSCertProfileDefaultValue = @"default";
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if ((self = [self init])) {
if (self = [self init]) {
self.fileContent = [aDecoder decodeObjectOfClass:[NSData class] forKey:NSStringFromSelector(@selector(fileContent))];
self.settings = [aDecoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(settings))];
self.guiVersion = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(guiVersion))];

View File

@@ -6,10 +6,10 @@
//
//
#import <client/ovpncli.hpp>
#import "OpenVPNConnectionInfo.h"
#include <client/ovpncli.hpp>
using namespace openvpn;
@interface OpenVPNConnectionInfo (Internal)

View File

@@ -28,7 +28,7 @@ using namespace openvpn;
@implementation OpenVPNConnectionInfo
- (instancetype)initWithConnectionInfo:(ClientAPI::ConnectionInfo)info {
if ((self = [super init])) {
if (self = [super init]) {
self.user = !info.user.empty() ? [NSString stringWithUTF8String:info.user.c_str()] : nil;
self.serverHost = !info.serverHost.empty() ? [NSString stringWithUTF8String:info.serverHost.c_str()] : nil;
self.serverPort = !info.serverPort.empty() ? [NSString stringWithUTF8String:info.serverPort.c_str()] : nil;
@@ -75,7 +75,7 @@ using namespace openvpn;
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
if ((self = [self init])) {
if (self = [self init]) {
self.user = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(user))];
self.serverHost = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(serverHost))];
self.serverPort = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(serverPort))];

View File

@@ -5,11 +5,10 @@
// Created by Sergey Abramchuk on 24.04.17.
//
//
#import <client/ovpncli.hpp>
#import "OpenVPNCredentials.h"
#include <client/ovpncli.hpp>
using namespace openvpn;
@interface OpenVPNCredentials (Internal)

View File

@@ -52,7 +52,8 @@ using namespace openvpn;
}
- (NSString *)dynamicChallengeCookie {
return !_credentials.dynamicChallengeCookie.empty() ? [NSString stringWithUTF8String:_credentials.dynamicChallengeCookie.c_str()] : nil;
return !_credentials.dynamicChallengeCookie.empty() ?
[NSString stringWithUTF8String:_credentials.dynamicChallengeCookie.c_str()] : nil;
}
- (void)setDynamicChallengeCookie:(NSString *)dynamicChallengeCookie {

View File

@@ -8,11 +8,15 @@
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT NSString * __nonnull const OpenVPNAdapterErrorDomain;
FOUNDATION_EXPORT NSString * __nonnull const OpenVPNIdentityErrorDomain;
NS_ASSUME_NONNULL_BEGIN
FOUNDATION_EXPORT NSString * __nonnull const OpenVPNAdapterErrorFatalKey;
FOUNDATION_EXPORT NSString * __nonnull const OpenVPNAdapterErrorMessageKey;
FOUNDATION_EXPORT NSString *const OpenVPNAdapterErrorDomain;
FOUNDATION_EXPORT NSString *const OpenVPNIdentityErrorDomain;
FOUNDATION_EXPORT NSString *const OpenVPNAdapterErrorFatalKey;
FOUNDATION_EXPORT NSString *const OpenVPNAdapterErrorMessageKey;
NS_ASSUME_NONNULL_END
/**
OpenVPN error codes
@@ -32,6 +36,7 @@ typedef NS_ERROR_ENUM(OpenVPNAdapterErrorDomain, OpenVPNAdapterError) {
OpenVPNAdapterErrorBadSrcAddr,
OpenVPNAdapterErrorCompressError,
OpenVPNAdapterErrorResolveError,
OpenVPNAdapterErrorSocketSetupFailed,
OpenVPNAdapterErrorSocketProtectError,
OpenVPNAdapterErrorTUNReadError,
OpenVPNAdapterErrorTUNWriteError,

View File

@@ -8,8 +8,8 @@
#import <OpenVPNError.h>
NSString * const OpenVPNAdapterErrorDomain = @"me.ss-abramchuk.openvpn-adapter.error-domain";
NSString * const OpenVPNIdentityErrorDomain = @"me.ss-abramchuk.openvpn-identity.error-domain";
NSString *const OpenVPNAdapterErrorDomain = @"me.ss-abramchuk.openvpn-adapter.error-domain";
NSString *const OpenVPNIdentityErrorDomain = @"me.ss-abramchuk.openvpn-identity.error-domain";
NSString * const OpenVPNAdapterErrorFatalKey = @"me.ss-abramchuk.openvpn-adapter.error-key.fatal";
NSString * const OpenVPNAdapterErrorMessageKey = @"me.ss-abramchuk.openvpn-adapter.error-key.message";
NSString *const OpenVPNAdapterErrorFatalKey = @"me.ss-abramchuk.openvpn-adapter.error-key.fatal";
NSString *const OpenVPNAdapterErrorMessageKey = @"me.ss-abramchuk.openvpn-adapter.error-key.message";

View File

@@ -6,10 +6,10 @@
//
//
#import <client/ovpncli.hpp>
#import "OpenVPNInterfaceStats.h"
#include <client/ovpncli.hpp>
using namespace openvpn;
@interface OpenVPNInterfaceStats (Internal)

View File

@@ -21,7 +21,7 @@
@implementation OpenVPNInterfaceStats
- (instancetype)initWithInterfaceStats:(ClientAPI::InterfaceStats)stats {
if ((self = [super init])) {
if (self = [super init]) {
self.bytesIn = stats.bytesIn;
self.bytesOut = stats.bytesOut;
self.packetsIn = stats.packetsIn;
@@ -53,7 +53,7 @@
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
if ((self = [self init])) {
if (self = [self init]) {
self.bytesIn = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(bytesIn))];
self.bytesOut = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(bytesOut))];
self.packetsIn = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(packetsIn))];

View File

@@ -11,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
@class NEIPv4Route;
@class NEIPv6Route;
@class NEPacketTunnelNetworkSettings;
@class NEProxyServer;
@class NEPacketTunnelNetworkSettings;
@interface OpenVPNNetworkSettingsBuilder : NSObject
@@ -45,7 +45,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) BOOL httpsProxyServerEnabled;
@property (nonatomic, copy, nullable) NEProxyServer *httpsProxyServer;
@property (nonatomic, readonly, nullable) NEPacketTunnelNetworkSettings *networkSettings;
- (nullable NEPacketTunnelNetworkSettings *)networkSettings;
@end

View File

@@ -5,21 +5,27 @@
// Created by Jonathan Downing on 12/10/2017.
//
#import <NetworkExtension/NetworkExtension.h>
#import "OpenVPNNetworkSettingsBuilder.h"
#import <NetworkExtension/NetworkExtension.h>
@interface OpenVPNNetworkSettingsBuilder ()
@property (nonatomic) NSMutableArray<NSString *> *ipv4LocalAddresses;
@property (nonatomic) NSMutableArray<NSString *> *ipv4SubnetMasks;
@property (nonatomic) NSMutableArray<NEIPv4Route *> *ipv4IncludedRoutes;
@property (nonatomic) NSMutableArray<NEIPv4Route *> *ipv4ExcludedRoutes;
@property (nonatomic) NSMutableArray<NSString *> *ipv6LocalAddresses;
@property (nonatomic) NSMutableArray<NSNumber *> *ipv6NetworkPrefixLengths;
@property (nonatomic) NSMutableArray<NEIPv6Route *> *ipv6IncludedRoutes;
@property (nonatomic) NSMutableArray<NEIPv6Route *> *ipv6ExcludedRoutes;
@property (nonatomic) NSMutableArray<NSString *> *dnsServers;
@property (nonatomic) NSMutableArray<NSString *> *searchDomains;
@property (nonatomic) NSMutableArray<NSString *> *proxyExceptionList;
@end
@implementation OpenVPNNetworkSettingsBuilder
@@ -27,23 +33,27 @@
#pragma mark - NEPacketTunnelNetworkSettings Generation
- (NEPacketTunnelNetworkSettings *)networkSettings {
if (!self.remoteAddress.length) {
return nil;
}
if (!self.remoteAddress.length) { return nil; }
NEPacketTunnelNetworkSettings *networkSettings = [[NEPacketTunnelNetworkSettings alloc] initWithTunnelRemoteAddress:self.remoteAddress];
if (self.ipv4LocalAddresses.count && (self.ipv4LocalAddresses.count == self.ipv4SubnetMasks.count)) {
NEIPv4Settings *ipv4Settings = [[NEIPv4Settings alloc] initWithAddresses:self.ipv4LocalAddresses subnetMasks:self.ipv4SubnetMasks];
NEIPv4Settings *ipv4Settings = [[NEIPv4Settings alloc] initWithAddresses:self.ipv4LocalAddresses
subnetMasks:self.ipv4SubnetMasks];
ipv4Settings.includedRoutes = self.ipv4IncludedRoutes;
ipv4Settings.excludedRoutes = self.ipv4ExcludedRoutes;
networkSettings.IPv4Settings = ipv4Settings;
}
if (self.ipv6LocalAddresses.count && (self.ipv6LocalAddresses.count == self.ipv6NetworkPrefixLengths.count)) {
NEIPv6Settings *ipv6Settings = [[NEIPv6Settings alloc] initWithAddresses:self.ipv6LocalAddresses networkPrefixLengths:self.ipv6NetworkPrefixLengths];
NEIPv6Settings *ipv6Settings = [[NEIPv6Settings alloc] initWithAddresses:self.ipv6LocalAddresses
networkPrefixLengths:self.ipv6NetworkPrefixLengths];
ipv6Settings.includedRoutes = self.ipv6IncludedRoutes;
ipv6Settings.excludedRoutes = self.ipv6ExcludedRoutes;
networkSettings.IPv6Settings = ipv6Settings;
}
@@ -55,6 +65,7 @@
if (self.autoProxyConfigurationEnabled || self.httpProxyServerEnabled || self.httpsProxyServerEnabled) {
NEProxySettings *proxySettings = [[NEProxySettings alloc] init];
proxySettings.autoProxyConfigurationEnabled = self.autoProxyConfigurationEnabled;
proxySettings.proxyAutoConfigurationURL = self.proxyAutoConfigurationURL;
proxySettings.exceptionList = self.proxyExceptionList;
@@ -62,6 +73,7 @@
proxySettings.HTTPEnabled = self.httpProxyServerEnabled;
proxySettings.HTTPSServer = self.httpsProxyServer;
proxySettings.HTTPSEnabled = self.httpsProxyServerEnabled;
networkSettings.proxySettings = proxySettings;
}
@@ -73,79 +85,57 @@
#pragma mark - Lazy Initializers
- (NSMutableArray<NSString *> *)ipv4LocalAddresses {
if (!_ipv4LocalAddresses) {
_ipv4LocalAddresses = [[NSMutableArray alloc] init];
}
if (!_ipv4LocalAddresses) { _ipv4LocalAddresses = [[NSMutableArray alloc] init]; }
return _ipv4LocalAddresses;
}
- (NSMutableArray<NSString *> *)ipv4SubnetMasks {
if (!_ipv4SubnetMasks) {
_ipv4SubnetMasks = [[NSMutableArray alloc] init];
}
if (!_ipv4SubnetMasks) { _ipv4SubnetMasks = [[NSMutableArray alloc] init]; }
return _ipv4SubnetMasks;
}
- (NSMutableArray<NEIPv4Route *> *)ipv4IncludedRoutes {
if (!_ipv4IncludedRoutes) {
_ipv4IncludedRoutes = [[NSMutableArray alloc] init];
}
if (!_ipv4IncludedRoutes) { _ipv4IncludedRoutes = [[NSMutableArray alloc] init]; }
return _ipv4IncludedRoutes;
}
- (NSMutableArray<NEIPv4Route *> *)ipv4ExcludedRoutes {
if (!_ipv4ExcludedRoutes) {
_ipv4ExcludedRoutes = [[NSMutableArray alloc] init];
}
if (!_ipv4ExcludedRoutes) { _ipv4ExcludedRoutes = [[NSMutableArray alloc] init]; }
return _ipv4ExcludedRoutes;
}
- (NSMutableArray<NSString *> *)ipv6LocalAddresses {
if (!_ipv6LocalAddresses) {
_ipv6LocalAddresses = [[NSMutableArray alloc] init];
}
if (!_ipv6LocalAddresses) { _ipv6LocalAddresses = [[NSMutableArray alloc] init]; }
return _ipv6LocalAddresses;
}
- (NSMutableArray<NSNumber *> *)ipv6NetworkPrefixLengths {
if (!_ipv6NetworkPrefixLengths) {
_ipv6NetworkPrefixLengths = [[NSMutableArray alloc] init];
}
if (!_ipv6NetworkPrefixLengths) { _ipv6NetworkPrefixLengths = [[NSMutableArray alloc] init]; }
return _ipv6NetworkPrefixLengths;
}
- (NSMutableArray<NEIPv6Route *> *)ipv6IncludedRoutes {
if (!_ipv6IncludedRoutes) {
_ipv6IncludedRoutes = [[NSMutableArray alloc] init];
}
if (!_ipv6IncludedRoutes) { _ipv6IncludedRoutes = [[NSMutableArray alloc] init]; }
return _ipv6IncludedRoutes;
}
- (NSMutableArray<NEIPv6Route *> *)ipv6ExcludedRoutes {
if (!_ipv6ExcludedRoutes) {
_ipv6ExcludedRoutes = [[NSMutableArray alloc] init];
}
if (!_ipv6ExcludedRoutes) { _ipv6ExcludedRoutes = [[NSMutableArray alloc] init]; }
return _ipv6ExcludedRoutes;
}
- (NSMutableArray<NSString *> *)dnsServers {
if (!_dnsServers) {
_dnsServers = [[NSMutableArray alloc] init];
}
if (!_dnsServers) { _dnsServers = [[NSMutableArray alloc] init]; }
return _dnsServers;
}
- (NSMutableArray<NSString *> *)searchDomains {
if (!_searchDomains) {
_searchDomains = [[NSMutableArray alloc] init];
}
if (!_searchDomains) { _searchDomains = [[NSMutableArray alloc] init]; }
return _searchDomains;
}
- (NSMutableArray<NSString *> *)proxyExceptionList {
if (!_proxyExceptionList) {
_proxyExceptionList = [[NSMutableArray alloc] init];
}
if (!_proxyExceptionList) { _proxyExceptionList = [[NSMutableArray alloc] init]; }
return _proxyExceptionList;
}

View File

@@ -0,0 +1,35 @@
//
// OpenVPNPacket.h
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 15.01.2018.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface OpenVPNPacket : NSObject
/**
Data that can be written to the VPN socket.
*/
@property (readonly, nonatomic) NSData *vpnData;
/**
Data that can be written to the packet flow.
*/
@property (readonly, nonatomic) NSData *packetFlowData;
/**
Protocol number (e.g. PF_INET or PF_INET6) of the packet.
*/
@property (readonly, nonatomic) NSNumber *protocolFamily;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithVPNData:(NSData *)data NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithPacketFlowData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,95 @@
//
// OpenVPNPacket.m
// OpenVPN Adapter
//
// Created by Sergey Abramchuk on 15.01.2018.
//
#import "OpenVPNPacket.h"
#include <arpa/inet.h>
#include <openvpn/ip/ip.hpp>
@interface OpenVPNPacket () {
NSData *_data;
NSNumber *_protocolFamily;
}
@end
@implementation OpenVPNPacket
- (instancetype)initWithVPNData:(NSData *)data {
if (self = [super init]) {
#if TARGET_OS_IPHONE
// Get network protocol family from data prefix
NSUInteger prefix_size = sizeof(uint32_t);
uint32_t protocol = PF_UNSPEC;
[data getBytes:&protocol length:prefix_size];
protocol = CFSwapInt32BigToHost(protocol);
NSRange range = NSMakeRange(prefix_size, data.length - prefix_size);
NSData *packetData = [data subdataWithRange:range];
#else
// Get network protocol family from packet header
uint8_t header = 0;
[data getBytes:&header length:1];
uint32_t protocol = PF_UNSPEC;
uint32_t version = openvpn::IPHeader::version(header);
switch (version) {
case 4:
protocol = PF_INET;
break;
case 6:
protocol = PF_INET6;
break;
}
NSData *packetData = data;
#endif
_data = packetData;
_protocolFamily = @(protocol);
}
return self;
}
- (instancetype)initWithPacketFlowData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily {
if (self = [super init]) {
_data = data;
_protocolFamily = protocolFamily;
}
return self;
}
- (NSData *)vpnData {
#if TARGET_OS_IPHONE
// Prepend data with network protocol. It should be done because OpenVPN on iOS uses uint32_t prefixes containing network
// protocol.
uint32_t prefix = CFSwapInt32HostToBig(_protocolFamily.unsignedIntegerValue);
NSUInteger prefix_size = sizeof(uint32_t);
NSMutableData *data = [NSMutableData dataWithCapacity:prefix_size + _data.length];
[data appendBytes:&prefix length:prefix_size];
[data appendData:_data];
return data;
#else
return _data;
#endif
}
- (NSData *)packetFlowData {
return _data;
}
- (NSNumber *)protocolFamily {
return _protocolFamily;
}
@end

View File

@@ -3,21 +3,25 @@
// OpenVPN Adapter
//
// Created by Jonathan Downing on 12/10/2017.
// Modified by Sergey Abramchuk on 15/01/2018.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class NEPacketTunnelFlow;
@protocol OpenVPNAdapterPacketFlow;
@interface OpenVPNPacketFlowBridge : NSObject
@interface OpenVPNPacketFlowBridge: NSObject
@property (nonatomic, readonly) CFSocketNativeHandle socketHandle;
@property (nonatomic, readonly) CFSocketRef openVPNSocket;
@property (nonatomic, readonly) CFSocketRef packetFlowSocket;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithPacketFlow:(id<OpenVPNAdapterPacketFlow>)packetFlow NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithPacketFlow:(NEPacketTunnelFlow *)packetFlow NS_DESIGNATED_INITIALIZER;
- (BOOL)configureSocketsWithError:(NSError **)error;
- (void)startReading;
@end

View File

@@ -3,65 +3,85 @@
// OpenVPN Adapter
//
// Created by Jonathan Downing on 12/10/2017.
// Modified by Sergey Abramchuk on 15/01/2018.
//
#import <NetworkExtension/NetworkExtension.h>
#import <openvpn/ip/ip.hpp>
#import "OpenVPNPacketFlowBridge.h"
@interface OpenVPNPacketFlowBridge () {
CFSocketRef _openVPNClientSocket;
CFSocketRef _packetFlowSocket;
}
#include <sys/socket.h>
#include <arpa/inet.h>
@property (nonatomic) NEPacketTunnelFlow *packetFlow;
#import "OpenVPNError.h"
#import "OpenVPNPacket.h"
#import "OpenVPNAdapterPacketFlow.h"
@interface OpenVPNPacketFlowBridge ()
@property (nonatomic) id<OpenVPNAdapterPacketFlow> packetFlow;
@end
@implementation OpenVPNPacketFlowBridge
- (CFSocketNativeHandle)socketHandle {
return CFSocketGetNative(_openVPNClientSocket);
}
- (instancetype)initWithPacketFlow:(NEPacketTunnelFlow *)packetFlow {
if ((self = [super init])) {
self.packetFlow = packetFlow;
if (![self configureSockets]) {
return nil;
}
[self readPacketFlowPackets];
- (instancetype)initWithPacketFlow:(id<OpenVPNAdapterPacketFlow>)packetFlow {
if (self = [super init]) {
_packetFlow = packetFlow;
}
return self;
}
static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *adapter) {
[(__bridge OpenVPNPacketFlowBridge *)adapter writeDataToPacketFlow:(__bridge NSData *)data];
#pragma mark - Sockets Configuration
static void SocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *obj) {
if (type != kCFSocketDataCallBack) { return; }
OpenVPNPacket *packet = [[OpenVPNPacket alloc] initWithVPNData:(__bridge NSData *)data];
OpenVPNPacketFlowBridge *bridge = (__bridge OpenVPNPacketFlowBridge *)obj;
[bridge writePackets:@[packet] toPacketFlow:bridge.packetFlow];
}
- (BOOL)configureSockets {
- (BOOL)configureSocketsWithError:(NSError **)error {
int sockets[2];
if (socketpair(PF_LOCAL, SOCK_DGRAM, IPPROTO_IP, sockets) == -1) {
NSLog(@"Failed to create a pair of connected sockets: %@", [NSString stringWithUTF8String:strerror(errno)]);
if (error) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: @"Failed to create a pair of connected sockets",
NSLocalizedFailureReasonErrorKey: [NSString stringWithUTF8String:strerror(errno)],
OpenVPNAdapterErrorFatalKey: @(YES)
};
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain
code:OpenVPNAdapterErrorSocketSetupFailed
userInfo:userInfo];
}
return NO;
}
CFSocketContext socketCtxt = {0, (__bridge void *)self, NULL, NULL, NULL};
_packetFlowSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[0], kCFSocketDataCallBack, PacketFlowSocketCallback, &socketCtxt);
_openVPNClientSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[1], kCFSocketNoCallBack, NULL, NULL);
_packetFlowSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[0], kCFSocketDataCallBack,
SocketCallback, &socketCtxt);
_openVPNSocket = CFSocketCreateWithNative(kCFAllocatorDefault, sockets[1], kCFSocketNoCallBack, NULL, NULL);
if (!(_packetFlowSocket && _openVPNClientSocket)) {
NSLog(@"Failed to create core foundation sockets from native sockets");
if (!(_packetFlowSocket && _openVPNSocket)) {
if (error) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: @"Failed to create core foundation sockets from native sockets",
OpenVPNAdapterErrorFatalKey: @(YES)
};
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain
code:OpenVPNAdapterErrorSocketSetupFailed
userInfo:userInfo];
}
return NO;
}
if (!([self configureOptionsForSocket:_packetFlowSocket] && [self configureOptionsForSocket:_openVPNClientSocket])) {
NSLog(@"Failed to configure buffer size of the sockets");
return NO;
}
if (!([self configureOptionsForSocket:_packetFlowSocket error:error] &&
[self configureOptionsForSocket:_openVPNSocket error:error])) { return NO; }
CFRunLoopSourceRef packetFlowSocketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, _packetFlowSocket, 0);
CFRunLoopAddSource(CFRunLoopGetMain(), packetFlowSocketSource, kCFRunLoopDefaultMode);
@@ -70,104 +90,88 @@ static inline void PacketFlowSocketCallback(CFSocketRef socket, CFSocketCallBack
return YES;
}
- (BOOL)configureOptionsForSocket:(CFSocketRef)socket {
- (BOOL)configureOptionsForSocket:(CFSocketRef)socket error:(NSError **)error {
CFSocketNativeHandle socketHandle = CFSocketGetNative(socket);
int buf_value = 65536;
socklen_t buf_len = sizeof(buf_value);
if (setsockopt(socketHandle, SOL_SOCKET, SO_RCVBUF, &buf_value, buf_len) == -1) {
NSLog(@"Failed to setup buffer size for input: %@", [NSString stringWithUTF8String:strerror(errno)]);
if (error) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: @"Failed to setup buffer size for input",
NSLocalizedFailureReasonErrorKey: [NSString stringWithUTF8String:strerror(errno)],
OpenVPNAdapterErrorFatalKey: @(YES)
};
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain
code:OpenVPNAdapterErrorSocketSetupFailed
userInfo:userInfo];
}
return NO;
}
if (setsockopt(socketHandle, SOL_SOCKET, SO_SNDBUF, &buf_value, buf_len) == -1) {
NSLog(@"Failed to setup buffer size for output: %@", [NSString stringWithUTF8String:strerror(errno)]);
if (error) {
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: @"Failed to setup buffer size for output",
NSLocalizedFailureReasonErrorKey: [NSString stringWithUTF8String:strerror(errno)],
OpenVPNAdapterErrorFatalKey: @(YES)
};
*error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain
code:OpenVPNAdapterErrorSocketSetupFailed
userInfo:userInfo];
}
return NO;
}
return YES;
}
- (void)readPacketFlowPackets {
- (void)startReading {
__weak typeof(self) weakSelf = self;
[self.packetFlow readPacketObjectsWithCompletionHandler:^(NSArray<NEPacket *> * _Nonnull packets) {
[self.packetFlow readPacketsWithCompletionHandler:^(NSArray<NSData *> *packets, NSArray<NSNumber *> *protocols) {
__strong typeof(self) self = weakSelf;
[self writeVPNPacketObjects:packets];
[self readPacketFlowPackets];
[self writePackets:packets protocols:protocols toSocket:self.packetFlowSocket];
[self startReading];
}];
}
- (void)writeVPNPacketObjects:(NSArray<NEPacket *> *)packets {
for (NEPacket *packet in packets) {
CFSocketSendData(_packetFlowSocket, NULL, (CFDataRef)[self dataFromPacket:packet], 0.05);
}
#pragma mark - TUN -> VPN
- (void)writePackets:(NSArray<NSData *> *)packets protocols:(NSArray<NSNumber *> *)protocols toSocket:(CFSocketRef)socket {
[packets enumerateObjectsUsingBlock:^(NSData *data, NSUInteger idx, BOOL *stop) {
NSNumber *protocolFamily = protocols[idx];
OpenVPNPacket *packet = [[OpenVPNPacket alloc] initWithPacketFlowData:data protocolFamily:protocolFamily];
CFSocketSendData(socket, NULL, (CFDataRef)packet.vpnData, 0.05);
}];
}
- (NSData *)dataFromPacket:(NEPacket *)packet {
#if TARGET_OS_IPHONE
// Prepend data with network protocol. It should be done because OpenVPN on iOS uses uint32_t prefixes containing network protocol.
uint32_t prefix = CFSwapInt32HostToBig((uint32_t)packet.protocolFamily);
NSMutableData *data = [[NSMutableData alloc] initWithCapacity:sizeof(prefix) + packet.data.length];
[data appendBytes:&prefix length:sizeof(prefix)];
[data appendData:packet.data];
return data;
#else
return packet.data;
#endif
#pragma mark - VPN -> TUN
- (void)writePackets:(NSArray<OpenVPNPacket *> *)packets toPacketFlow:(id<OpenVPNAdapterPacketFlow>)packetFlow {
NSMutableArray<NSData *> *flowPackets = [[NSMutableArray alloc] init];
NSMutableArray<NSNumber *> *protocols = [[NSMutableArray alloc] init];
[packets enumerateObjectsUsingBlock:^(OpenVPNPacket * _Nonnull packet, NSUInteger idx, BOOL * _Nonnull stop) {
[flowPackets addObject:packet.packetFlowData];
[protocols addObject:packet.protocolFamily];
}];
[packetFlow writePackets:flowPackets withProtocols:protocols];
}
- (NEPacket *)packetFromData:(NSData *)data {
#if TARGET_OS_IPHONE
// Get network protocol from prefix
NSUInteger prefixSize = sizeof(uint32_t);
if (data.length < prefixSize) {
return nil;
}
uint32_t protocol = PF_UNSPEC;
[data getBytes:&protocol length:prefixSize];
protocol = CFSwapInt32BigToHost(protocol);
NSRange range = NSMakeRange(prefixSize, data.length - prefixSize);
NSData *packetData = [data subdataWithRange:range];
#else
// Get network protocol from header
uint8_t header = 0;
[data getBytes:&header length:1];
uint32_t version = openvpn::IPHeader::version(header);
sa_family_t protocol = [self protocolFamilyForVersion:version];
NSData *packetData = data;
#endif
return [[NEPacket alloc] initWithData:packetData protocolFamily:protocol];
}
- (void)writeDataToPacketFlow:(NSData *)data {
NEPacket *packet = [self packetFromData:data];
if (!packet) {
return;
}
[self.packetFlow writePacketObjects:@[packet]];
}
- (sa_family_t)protocolFamilyForVersion:(uint32_t)version {
switch (version) {
case 4: return PF_INET;
case 6: return PF_INET6;
default: return PF_UNSPEC;
}
}
#pragma mark -
- (void)dealloc {
CFSocketInvalidate(_openVPNClientSocket);
CFRelease(_openVPNClientSocket);
CFSocketInvalidate(_openVPNSocket);
CFRelease(_openVPNSocket);
CFSocketInvalidate(_packetFlowSocket);
CFRelease(_packetFlowSocket);

View File

@@ -8,24 +8,24 @@
#import <Foundation/Foundation.h>
#import "OpenVPNKeyType.h"
typedef NS_ENUM(NSInteger, OpenVPNKeyType);
@interface OpenVPNPrivateKey : NSObject
+ (nullable OpenVPNPrivateKey *)keyWithPEM:(nonnull NSData *)pemData
password:(nullable NSString *)password
error:(out NSError * __nullable * __nullable)error;
error:(out NSError * _Nullable * _Nullable)error;
+ (nullable OpenVPNPrivateKey *)keyWithDER:(nonnull NSData *)derData
password:(nullable NSString *)password
error:(out NSError * __nullable * __nullable)error;
error:(out NSError * _Nullable * _Nullable)error;
- (nonnull instancetype) __unavailable init;
- (nonnull instancetype) init NS_UNAVAILABLE;
@property (nonatomic, readonly) NSInteger size;
@property (nonatomic, readonly) OpenVPNKeyType type;
- (nullable NSData *)pemData:(out NSError * __nullable * __nullable)error;
- (nullable NSData *)derData:(out NSError * __nullable * __nullable)error;
- (nullable NSData *)pemData:(out NSError * _Nullable * _Nullable)error;
- (nullable NSData *)derData:(out NSError * _Nullable * _Nullable)error;
@end

View File

@@ -6,12 +6,13 @@
//
//
#import <mbedtls/pk.h>
#import "NSError+Message.h"
#import "OpenVPNError.h"
#import "OpenVPNPrivateKey.h"
#include <mbedtls/pk.h>
#import "OpenVPNKeyType.h"
#import "NSError+OpenVPNError.h"
@interface OpenVPNPrivateKey ()
@property (nonatomic, assign) mbedtls_pk_context *ctx;
@@ -20,23 +21,6 @@
@implementation OpenVPNPrivateKey
- (instancetype)init {
self = [super init];
if (self) {
self.ctx = malloc(sizeof(mbedtls_pk_context));
mbedtls_pk_init(self.ctx);
}
return self;
}
- (NSInteger)size {
return mbedtls_pk_get_bitlen(self.ctx);
}
- (OpenVPNKeyType)type {
return (OpenVPNKeyType)mbedtls_pk_get_type(self.ctx);
}
+ (nullable OpenVPNPrivateKey *)keyWithPEM:(NSData *)pemData password:(NSString *)password error:(out NSError **)error {
OpenVPNPrivateKey *key = [OpenVPNPrivateKey new];
@@ -45,14 +29,12 @@
size_t pem_length = strlen(pemString.UTF8String) + 1;
size_t password_length = password != nil ? strlen(password.UTF8String) : 0;
int result = mbedtls_pk_parse_key(key.ctx, (const unsigned char *)pemString.UTF8String, pem_length, (const unsigned char *)password.UTF8String, password_length);
int result = mbedtls_pk_parse_key(key.ctx, (const unsigned char *)pemString.UTF8String,
pem_length, (const unsigned char *)password.UTF8String, password_length);
if (result < 0) {
if (error) {
NSString *reason = [NSError reasonFromResult:result];
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
NSLocalizedDescriptionKey: @"Failed to read PEM data.",
NSLocalizedFailureReasonErrorKey: reason
}];
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to read PEM data"];
}
return nil;
@@ -66,14 +48,12 @@
size_t password_length = password != nil ? strlen(password.UTF8String) : 0;
int result = mbedtls_pk_parse_key(key.ctx, derData.bytes, derData.length, (const unsigned char *)password.UTF8String, password_length);
int result = mbedtls_pk_parse_key(key.ctx, derData.bytes,
derData.length, (const unsigned char *)password.UTF8String, password_length);
if (result < 0) {
if (error) {
NSString *reason = [NSError reasonFromResult:result];
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
NSLocalizedDescriptionKey: @"Failed to read DER data.",
NSLocalizedFailureReasonErrorKey: reason
}];
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to read DER data"];
}
return nil;
@@ -82,6 +62,22 @@
return key;
}
- (instancetype)init {
if (self = [super init]) {
_ctx = malloc(sizeof(mbedtls_pk_context));
mbedtls_pk_init(_ctx);
}
return self;
}
- (NSInteger)size {
return mbedtls_pk_get_bitlen(self.ctx);
}
- (OpenVPNKeyType)type {
return (OpenVPNKeyType)mbedtls_pk_get_type(self.ctx);
}
- (NSData *)pemData:(out NSError **)error {
size_t buffer_length = mbedtls_pk_get_len(self.ctx) * 10;
unsigned char *pem_buffer = malloc(buffer_length);
@@ -89,18 +85,15 @@
int result = mbedtls_pk_write_key_pem(self.ctx, pem_buffer, buffer_length);
if (result < 0) {
if (error) {
NSString *reason = [NSError reasonFromResult:result];
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
NSLocalizedDescriptionKey: @"Failed to write PEM data.",
NSLocalizedFailureReasonErrorKey: reason
}];
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to write PEM data"];
}
free(pem_buffer);
return nil;
}
NSData *pemData = [[NSString stringWithCString:(const char *)pem_buffer encoding:NSUTF8StringEncoding] dataUsingEncoding:NSUTF8StringEncoding];
NSData *pemData = [[NSString stringWithCString:(const char *)pem_buffer
encoding:NSUTF8StringEncoding] dataUsingEncoding:NSUTF8StringEncoding];
free(pem_buffer);
return pemData;
@@ -113,11 +106,7 @@
int result = mbedtls_pk_write_key_der(self.ctx, der_buffer, buffer_length);
if (result < 0) {
if (error) {
NSString *reason = [NSError reasonFromResult:result];
*error = [NSError errorWithDomain:OpenVPNIdentityErrorDomain code:result userInfo:@{
NSLocalizedDescriptionKey: @"Failed to write DER data.",
NSLocalizedFailureReasonErrorKey: reason
}];
*error = [NSError ovpn_errorObjectForMbedTLSError:result description:@"Failed to write DER data"];
}
free(der_buffer);
@@ -134,8 +123,8 @@
}
- (void)dealloc {
mbedtls_pk_free(self.ctx);
free(self.ctx);
mbedtls_pk_free(_ctx);
free(_ctx);
}
@end

View File

@@ -6,10 +6,10 @@
//
//
#import <client/ovpncli.hpp>
#import "OpenVPNProperties.h"
#include <client/ovpncli.hpp>
using namespace openvpn;
@interface OpenVPNProperties (Internal)

View File

@@ -8,8 +8,7 @@
#import <Foundation/Foundation.h>
#import "OpenVPNTransportProtocol.h"
typedef NS_ENUM(NSInteger, OpenVPNTransportProtocol);
@class OpenVPNServerEntry;
@interface OpenVPNProperties : NSObject
@@ -47,7 +46,7 @@
/**
YES if this profile requires a private key password
*/
@property (readonly, nonatomic) BOOL privateKeyPasswordRequired;
@property (readonly, nonatomic, getter=isPrivateKeyPasswordRequired) BOOL privateKeyPasswordRequired;
/**
YES if user is allowed to save authentication password in UI
@@ -74,6 +73,6 @@
*/
@property (nullable, readonly, nonatomic) NSArray<OpenVPNServerEntry *> *servers;
- (nonnull instancetype) __unavailable init;
- (nonnull instancetype) init NS_UNAVAILABLE;
@end

View File

@@ -6,20 +6,20 @@
//
//
#import <openvpn/common/number.hpp>
#import "OpenVPNProperties.h"
#import "OpenVPNProperties+Internal.h"
#include <openvpn/common/number.hpp>
#import "OpenVPNConfiguration+Internal.h"
#import "OpenVPNServerEntry+Internal.h"
#import "OpenVPNProperties.h"
#import "OpenVPNProperties+Internal.h"
using namespace openvpn;
@implementation OpenVPNProperties
- (instancetype)initWithEvalConfig:(ClientAPI::EvalConfig)eval {
self = [super init];
if (self) {
if (self = [super init]) {
_username = !eval.userlockedUsername.empty() ? [NSString stringWithUTF8String:eval.userlockedUsername.c_str()] : nil;
_profileName = !eval.profileName.empty() ? [NSString stringWithUTF8String:eval.profileName.c_str()] : nil;
@@ -44,6 +44,7 @@ using namespace openvpn;
_remoteProto = [OpenVPNConfiguration getTransportProtocolFromValue:currentProto];
_servers = nil;
if (!eval.serverList.empty()) {
NSMutableArray *servers = [NSMutableArray new];

View File

@@ -6,7 +6,6 @@
//
//
#import "OpenVPNReachabilityTracker.h"
#import "OpenVPNReachability.h"
@interface OpenVPNReachability (Internal)

View File

@@ -7,11 +7,12 @@
//
#import <Foundation/Foundation.h>
#import "OpenVPNReachabilityStatus.h"
typedef NS_ENUM(NSInteger, OpenVPNReachabilityStatus);
@interface OpenVPNReachability : NSObject
@property (readonly, nonatomic) BOOL isTracking;
@property (readonly, nonatomic, getter=isTracking) BOOL tracking;
@property (readonly, nonatomic) OpenVPNReachabilityStatus reachabilityStatus;
- (nonnull instancetype)init;

View File

@@ -6,11 +6,14 @@
//
//
#import <openvpn/apple/reachable.hpp>
#import "OpenVPNReachability.h"
#import "OpenVPNReachability+Internal.h"
#include <openvpn/apple/reachable.hpp>
#import "OpenVPNReachabilityTracker.h"
#import "OpenVPNReachabilityStatus.h"
@interface OpenVPNReachability () {
BOOL _isTracking;
}
@@ -45,13 +48,12 @@
}
}
- (nonnull instancetype)init {
self = [super init];
if (self) {
- (instancetype)init {
if (self = [super init]) {
_isTracking = NO;
self.tracker = new OpenVPNReachabilityTracker(true, false, (__bridge void *)self);
self.reachability = new Reachability(true, true);
_tracker = new OpenVPNReachabilityTracker(true, false, (__bridge void *)self);
_reachability = new Reachability(true, true);
}
return self;
}
@@ -77,8 +79,8 @@
}
- (void)dealloc {
delete self.tracker;
delete self.reachability;
delete _tracker;
delete _reachability;
}
@end

View File

@@ -6,7 +6,7 @@
//
//
#import <openvpn/apple/reachable.hpp>
#include <openvpn/apple/reachable.hpp>
using namespace openvpn;

View File

@@ -6,10 +6,14 @@
//
//
#import "OpenVPNReachability+Internal.h"
#import "OpenVPNReachabilityTracker.h"
OpenVPNReachabilityTracker::OpenVPNReachabilityTracker(const bool enable_internet, const bool enable_wifi, void* handler) : ReachabilityTracker(enable_internet, enable_wifi) {
#import "OpenVPNReachability+Internal.h"
#import "OpenVPNReachabilityStatus.h"
OpenVPNReachabilityTracker::OpenVPNReachabilityTracker(const bool enable_internet, const bool enable_wifi, void* handler) :
ReachabilityTracker(enable_internet, enable_wifi)
{
this->handler = handler;
}

View File

@@ -6,10 +6,10 @@
//
//
#import <client/ovpncli.hpp>
#import "OpenVPNServerEntry.h"
#include <client/ovpncli.hpp>
using namespace openvpn;
@interface OpenVPNServerEntry (Internal)

View File

@@ -13,6 +13,6 @@
@property (nullable, readonly, nonatomic) NSString *server;
@property (nullable, readonly, nonatomic) NSString *friendlyName;
- (nonnull instancetype) __unavailable init;
- (nonnull instancetype) init NS_UNAVAILABLE;
@end

View File

@@ -12,8 +12,7 @@
@implementation OpenVPNServerEntry
- (instancetype)initWithServerEntry:(ClientAPI::ServerEntry)entry {
self = [super init];
if (self) {
if (self = [super init]) {
_server = !entry.server.empty() ? [NSString stringWithUTF8String:entry.server.c_str()] : nil;
_friendlyName = !entry.friendlyName.empty() ? [NSString stringWithUTF8String:entry.friendlyName.c_str()] : nil;
}

View File

@@ -6,10 +6,10 @@
//
//
#import <client/ovpncli.hpp>
#import "OpenVPNSessionToken.h"
#include <client/ovpncli.hpp>
using namespace openvpn;
@interface OpenVPNSessionToken (Internal)

View File

@@ -6,6 +6,7 @@
//
//
#import "OpenVPNSessionToken.h"
#import "OpenVPNSessionToken+Internal.h"
using namespace openvpn;
@@ -18,7 +19,7 @@ using namespace openvpn;
@implementation OpenVPNSessionToken
- (instancetype)initWithSessionToken:(ClientAPI::SessionToken)token {
if ((self = [super init])) {
if (self = [super init]) {
self.username = !token.username.empty() ? [NSString stringWithUTF8String:token.username.c_str()] : nil;
self.session = !token.session_id.empty() ? [NSString stringWithUTF8String:token.session_id.c_str()] : nil;
}
@@ -38,7 +39,7 @@ using namespace openvpn;
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
if ((self = [self init])) {
if (self = [self init]) {
self.username = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(username))];
self.session = [aDecoder decodeObjectOfClass:[NSString class] forKey:NSStringFromSelector(@selector(session))];
}

View File

@@ -6,10 +6,10 @@
//
//
#import <client/ovpncli.hpp>
#import "OpenVPNTransportStats.h"
#include <client/ovpncli.hpp>
using namespace openvpn;
@interface OpenVPNTransportStats (Internal)

View File

@@ -6,6 +6,7 @@
//
//
#import "OpenVPNTransportStats.h"
#import "OpenVPNTransportStats+Internal.h"
using namespace openvpn;
@@ -21,12 +22,13 @@ using namespace openvpn;
@implementation OpenVPNTransportStats
- (instancetype)initWithTransportStats:(ClientAPI::TransportStats)stats {
if ((self = [self init])) {
if (self = [self init]) {
self.bytesIn = stats.bytesIn;
self.bytesOut = stats.bytesOut;
self.packetsIn = stats.packetsIn;
self.packetsOut = stats.packetsOut;
self.lastPacketReceived = stats.lastPacketReceived >= 0 ? [NSDate dateWithTimeIntervalSinceNow:stats.lastPacketReceived / -1024.0] : nil;
self.lastPacketReceived = stats.lastPacketReceived >= 0 ?
[NSDate dateWithTimeIntervalSinceNow:stats.lastPacketReceived / -1024.0] : nil;
}
return self;
}
@@ -50,12 +52,13 @@ using namespace openvpn;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super init])) {
if (self = [super init]) {
self.bytesIn = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(bytesIn))];
self.bytesOut = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(bytesOut))];
self.packetsIn = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(packetsIn))];
self.packetsOut = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(packetsOut))];
self.lastPacketReceived = [aDecoder decodeObjectOfClass:[NSDate class] forKey:NSStringFromSelector(@selector(lastPacketReceived))];
self.lastPacketReceived = [aDecoder decodeObjectOfClass:[NSDate class]
forKey:NSStringFromSelector(@selector(lastPacketReceived))];
}
return self;
}

View File

@@ -32,6 +32,7 @@ FOUNDATION_EXPORT const unsigned char OpenVPNAdapterVersionString[];
#import <OpenVPNAdapter/OpenVPNTransportStats.h>
#import <OpenVPNAdapter/OpenVPNInterfaceStats.h>
#import <OpenVPNAdapter/OpenVPNAdapter.h>
#import <OpenVPNAdapter/OpenVPNAdapterPacketFlow.h>
#import <OpenVPNAdapter/OpenVPNKeyType.h>
#import <OpenVPNAdapter/OpenVPNCertificate.h>
#import <OpenVPNAdapter/OpenVPNPrivateKey.h>

View File

@@ -24,6 +24,9 @@
// The crux of the API is defined in OpenVPNClient (below)
// and TunBuilderBase.
#ifndef OVPNCLI_HPP
#define OVPNCLI_HPP
#include <string>
#include <vector>
#include <utility>
@@ -600,3 +603,5 @@ namespace openvpn {
}
}
#endif