From 5fd8a82934494a32b81c3e8f942a3e6dfd458792 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Fri, 12 Jan 2018 13:50:44 +0300 Subject: [PATCH 01/32] Move definition and implementation of OpenVPNClient into separate files --- OpenVPN Adapter/OpenVPNClient.h | 99 ++++++++++++++++++ OpenVPN Adapter/OpenVPNClient.mm | 169 +++++++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 OpenVPN Adapter/OpenVPNClient.h create mode 100644 OpenVPN Adapter/OpenVPNClient.mm diff --git a/OpenVPN Adapter/OpenVPNClient.h b/OpenVPN Adapter/OpenVPNClient.h new file mode 100644 index 0000000..08cb11c --- /dev/null +++ b/OpenVPN Adapter/OpenVPNClient.h @@ -0,0 +1,99 @@ +// +// OpenVPNClient.h +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 11.01.2018. +// + +#import + +#include + +@class NEIPv4Route; +@class NEIPv6Route; +@class NEProxyServer; + +typedef NS_ENUM(NSInteger, OpenVPNProxyServerProtocol) { + OpenVPNProxyServerProtocolHTTP, + OpenVPNProxyServerProtocolHTTPS +}; + +NS_ASSUME_NONNULL_BEGIN + +@protocol OpenVPNClientDelegate +- (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)clientEvent:(NSString *)eventName message:(nullable NSString *)message; +- (void)clientError:(NSString *)errorName fatal:(BOOL)fatal message:(nullable NSString *)message; +- (void)clientLog:(NSString *)logMessage; + +- (void)tick; + +- (void)resetSettings; +@end + +using namespace openvpn; + +class OpenVPNClient : public ClientAPI::OpenVPNClient { +public: + OpenVPNClient(id _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 delegate; +}; + +NS_ASSUME_NONNULL_END diff --git a/OpenVPN Adapter/OpenVPNClient.mm b/OpenVPN Adapter/OpenVPNClient.mm new file mode 100644 index 0000000..efdb96f --- /dev/null +++ b/OpenVPN Adapter/OpenVPNClient.mm @@ -0,0 +1,169 @@ +// +// OpenVPNClient.m +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 11.01.2018. +// + +#define INVALID_SOCKET -1 + +#import "OpenVPNClient.h" + +#import + +#include + +using ::IPv4::Addr; + +OpenVPNClient::OpenVPNClient(id 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()]]; + return [this->delegate setProxyAutoConfigurationURL:configURL]; +} + +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 clientError:name fatal:ev.fatal message:message.length ? message : nil]; + } else { + [this->delegate clientEvent:name message:message.length ? message : nil]; + } +} + +void OpenVPNClient::log(const ClientAPI::LogInfo& log) { + NSString *logMessage = [NSString stringWithUTF8String:log.text.c_str()]; + [this->delegate clientLog:logMessage]; +} + +void OpenVPNClient::clock_tick() { + [this->delegate tick]; +} From 82efe6e021fe4b78921db6ceded63c62a1d7cc86 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Fri, 12 Jan 2018 13:52:16 +0300 Subject: [PATCH 02/32] Add OpenVPNClient files to the project --- OpenVPN Adapter.xcodeproj/project.pbxproj | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index 2ff6418..602c12e 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -130,6 +130,10 @@ 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 */; }; @@ -240,6 +244,8 @@ C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenVPNCertificate.h; sourceTree = ""; }; C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenVPNCertificate.m; sourceTree = ""; }; C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNCertificateTests.swift; sourceTree = ""; }; + C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNClient.h; sourceTree = ""; }; + C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OpenVPNClient.mm; sourceTree = ""; }; 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 = ""; }; @@ -432,6 +438,8 @@ C9BB47671E7169F000F3F98C /* Adapter */ = { isa = PBXGroup; children = ( + C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */, + C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */, ABD6EF151F8F9C37007D3D90 /* OpenVPNAdapter.h */, ABD6EF161F8F9C38007D3D90 /* OpenVPNAdapter.mm */, ABD6EF071F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h */, @@ -572,6 +580,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 */, @@ -615,6 +624,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 */, @@ -868,6 +878,7 @@ 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 */, @@ -907,6 +918,7 @@ 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 */, From ee5d190087a3274ffc0b95ca94840fd0d9ef6508 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Fri, 12 Jan 2018 14:04:27 +0300 Subject: [PATCH 03/32] Fix position of asterix in const definitions and remove nullability specifiers --- OpenVPN Adapter/OpenVPNError.h | 12 ++++++++---- OpenVPN Adapter/OpenVPNError.m | 8 ++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNError.h b/OpenVPN Adapter/OpenVPNError.h index d054a0a..a8dd13c 100644 --- a/OpenVPN Adapter/OpenVPNError.h +++ b/OpenVPN Adapter/OpenVPNError.h @@ -8,11 +8,15 @@ #import -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 diff --git a/OpenVPN Adapter/OpenVPNError.m b/OpenVPN Adapter/OpenVPNError.m index b7785b8..447494e 100644 --- a/OpenVPN Adapter/OpenVPNError.m +++ b/OpenVPN Adapter/OpenVPNError.m @@ -8,8 +8,8 @@ #import -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"; From a0702c7d6e61b64fc2abed1d74f48c2fcf385cc6 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 15 Jan 2018 12:15:07 +0300 Subject: [PATCH 04/32] Change structure of the project --- OpenVPN Adapter.xcodeproj/project.pbxproj | 28 ++++++++--------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index 602c12e..dccbcb0 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -340,6 +340,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 */, @@ -375,26 +380,10 @@ name = "Stats and Info"; sourceTree = ""; }; - 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 = ""; - }; C9B7955B1F1D165700CF35FE /* Reachability */ = { isa = PBXGroup; children = ( + C9B795681F1D219C00CF35FE /* OpenVPNReachabilityStatus.h */, C9B795621F1D182500CF35FE /* OpenVPNReachabilityTracker.h */, C9B795631F1D182500CF35FE /* OpenVPNReachabilityTracker.mm */, C9B7955C1F1D16AA00CF35FE /* OpenVPNReachability.h */, @@ -438,6 +427,9 @@ C9BB47671E7169F000F3F98C /* Adapter */ = { isa = PBXGroup; children = ( + C9BB47701E7171A100F3F98C /* OpenVPNAdapterEvent.h */, + C9BB476F1E7171A100F3F98C /* OpenVPNError.h */, + C93A4F611EE18009004DC561 /* OpenVPNError.m */, C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */, C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */, ABD6EF151F8F9C37007D3D90 /* OpenVPNAdapter.h */, @@ -546,6 +538,7 @@ C9CA4DD01F602D8300C4F184 /* Certificates and Keys */ = { isa = PBXGroup; children = ( + C915F1FD1F6164CF00B3DF23 /* OpenVPNKeyType.h */, C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */, C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */, C915F1F21F612F3300B3DF23 /* OpenVPNPrivateKey.h */, @@ -566,7 +559,6 @@ C9FF73B71EB7421600E995AC /* Helpers */ = { isa = PBXGroup; children = ( - C9235AC61EB24F2A00C7D303 /* Types and Constants */, C9E4401A1F6081FF001D7C41 /* Utils */, ); name = Helpers; From 338e5b853d5b704f933940bfdc1535f3812bd880 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 15 Jan 2018 12:45:20 +0300 Subject: [PATCH 05/32] Return definition of OpenVPNAdapterPacketFlow protocol --- OpenVPN Adapter/OpenVPNAdapter.h | 41 +++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNAdapter.h b/OpenVPN Adapter/OpenVPNAdapter.h index b5714cb..92825aa 100644 --- a/OpenVPN Adapter/OpenVPNAdapter.h +++ b/OpenVPN Adapter/OpenVPNAdapter.h @@ -22,6 +22,33 @@ NS_ASSUME_NONNULL_BEGIN @class OpenVPNTransportStats; @class OpenVPNSessionToken; +@protocol OpenVPNAdapterPacketFlow + +/** + 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 *packets, NSArray *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 *)packets withProtocols:(NSArray *)protocols; + +@end + @protocol OpenVPNAdapterDelegate /** @@ -32,7 +59,10 @@ NS_ASSUME_NONNULL_BEGIN @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 _Nullable packetFlow))completionHandler +NS_SWIFT_NAME(openVPNAdapter(_:configureTunnelWithNetworkSettings:completionHandler:)); /** Informs the receiver that an OpenVPN error has occurred. @@ -50,7 +80,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 +155,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. From aa6a4bf66bb2614800ea285b2bf316d3789a3844 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 15 Jan 2018 12:48:03 +0300 Subject: [PATCH 06/32] Use forward declaration of events instead of direct import --- OpenVPN Adapter/OpenVPNAdapter.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenVPN Adapter/OpenVPNAdapter.h b/OpenVPN Adapter/OpenVPNAdapter.h index 92825aa..e6b6aa3 100644 --- a/OpenVPN Adapter/OpenVPNAdapter.h +++ b/OpenVPN Adapter/OpenVPNAdapter.h @@ -7,10 +7,11 @@ // #import -#import "OpenVPNAdapterEvent.h" NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, OpenVPNAdapterEvent); + @class NEPacketTunnelFlow; @class NEPacketTunnelNetworkSettings; @class OpenVPNAdapter; From 2dd1e98e1833cb9f63049881ec7f7ab5939728d7 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 15 Jan 2018 12:50:25 +0300 Subject: [PATCH 07/32] Break long comment lines --- OpenVPN Adapter/OpenVPNAdapter.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNAdapter.h b/OpenVPN Adapter/OpenVPNAdapter.h index e6b6aa3..fb8ec37 100644 --- a/OpenVPN Adapter/OpenVPNAdapter.h +++ b/OpenVPN Adapter/OpenVPNAdapter.h @@ -54,7 +54,8 @@ typedef NS_ENUM(NSInteger, OpenVPNAdapterEvent); /** 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. @@ -67,7 +68,8 @@ NS_SWIFT_NAME(openVPNAdapter(_:configureTunnelWithNetworkSettings:completionHand /** 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. From 1ca2f3a54feccaf1cf61e7636bf63ab63b74de21 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 15 Jan 2018 13:08:54 +0300 Subject: [PATCH 08/32] Move definition of OpenVPNAdapterPacketFlow protocol to its own header file --- OpenVPN Adapter.xcodeproj/project.pbxproj | 6 ++++ OpenVPN Adapter/OpenVPNAdapterPacketFlow.h | 35 ++++++++++++++++++++++ OpenVPN Adapter/Umbrella-Header.h | 1 + 3 files changed, 42 insertions(+) create mode 100644 OpenVPN Adapter/OpenVPNAdapterPacketFlow.h diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index dccbcb0..88439b3 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -124,6 +124,8 @@ 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, ); }; }; 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 */; }; @@ -241,6 +243,7 @@ C9BCE25C1EB3C201009D6AC1 /* OpenVPNSessionToken+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "OpenVPNSessionToken+Internal.h"; sourceTree = ""; }; C9C1E40F1FA47117006ECA7D /* remote_vpn_server.ovpn */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = remote_vpn_server.ovpn; sourceTree = ""; }; C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomFlow.swift; sourceTree = ""; }; + C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNAdapterPacketFlow.h; sourceTree = ""; }; C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenVPNCertificate.h; sourceTree = ""; }; C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenVPNCertificate.m; sourceTree = ""; }; C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNCertificateTests.swift; sourceTree = ""; }; @@ -436,6 +439,7 @@ ABD6EF161F8F9C38007D3D90 /* OpenVPNAdapter.mm */, ABD6EF071F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h */, ABD6EF081F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m */, + C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */, ABD6EF0E1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.h */, ABD6EF0F1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm */, ); @@ -604,6 +608,7 @@ C93779D51EAE32670030A362 /* OpenVPNCredentials.h in Headers */, C9657A641EB0D6C200EFF210 /* OpenVPNCompressionMode.h in Headers */, C9FD921A1E9A667600374FC4 /* ovpncli.hpp in Headers */, + C9C2B2B7200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */, C93779DB1EAE32880030A362 /* OpenVPNCredentials+Internal.h in Headers */, C9657A6A1EB0D75700EFF210 /* OpenVPNTLSCertProfile.h in Headers */, C9657A461EB0CB5900EFF210 /* OpenVPNServerEntry+Internal.h in Headers */, @@ -648,6 +653,7 @@ C93779D61EAE32670030A362 /* OpenVPNCredentials.h in Headers */, C9657A651EB0D6C200EFF210 /* OpenVPNCompressionMode.h in Headers */, C9D2ABEA1EA20F99007EDF9D /* ovpncli.hpp in Headers */, + C9C2B2B8200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h in Headers */, C93779DC1EAE32880030A362 /* OpenVPNCredentials+Internal.h in Headers */, C9657A6B1EB0D75700EFF210 /* OpenVPNTLSCertProfile.h in Headers */, C9657A471EB0CB5900EFF210 /* OpenVPNServerEntry+Internal.h in Headers */, diff --git a/OpenVPN Adapter/OpenVPNAdapterPacketFlow.h b/OpenVPN Adapter/OpenVPNAdapterPacketFlow.h new file mode 100644 index 0000000..958a5ba --- /dev/null +++ b/OpenVPN Adapter/OpenVPNAdapterPacketFlow.h @@ -0,0 +1,35 @@ +// +// OpenVPNAdapterPacketFlow.h +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 15.01.2018. +// + +#import + +@protocol OpenVPNAdapterPacketFlow + +/** + 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 *packets, NSArray *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 *)packets withProtocols:(NSArray *)protocols; + +@end diff --git a/OpenVPN Adapter/Umbrella-Header.h b/OpenVPN Adapter/Umbrella-Header.h index 95b98cf..f195964 100644 --- a/OpenVPN Adapter/Umbrella-Header.h +++ b/OpenVPN Adapter/Umbrella-Header.h @@ -32,6 +32,7 @@ FOUNDATION_EXPORT const unsigned char OpenVPNAdapterVersionString[]; #import #import #import +#import #import #import #import From c19bd1df76de7b4c5b04af8de65546153f2f74e8 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 15 Jan 2018 16:33:02 +0300 Subject: [PATCH 09/32] Define OpenVPNPacket class --- OpenVPN Adapter.xcodeproj/project.pbxproj | 12 ++++++++++++ OpenVPN Adapter/OpenVPNPacket.h | 22 ++++++++++++++++++++++ OpenVPN Adapter/OpenVPNPacket.m | 20 ++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 OpenVPN Adapter/OpenVPNPacket.h create mode 100644 OpenVPN Adapter/OpenVPNPacket.m diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index 88439b3..a3523c0 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -126,6 +126,10 @@ 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.m in Sources */ = {isa = PBXBuildFile; fileRef = C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.m */; }; + C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.m */; }; 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 */; }; @@ -244,6 +248,8 @@ C9C1E40F1FA47117006ECA7D /* remote_vpn_server.ovpn */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = remote_vpn_server.ovpn; sourceTree = ""; }; C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomFlow.swift; sourceTree = ""; }; C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNAdapterPacketFlow.h; sourceTree = ""; }; + C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNPacket.h; sourceTree = ""; }; + C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OpenVPNPacket.m; sourceTree = ""; }; C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenVPNCertificate.h; sourceTree = ""; }; C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenVPNCertificate.m; sourceTree = ""; }; C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNCertificateTests.swift; sourceTree = ""; }; @@ -440,6 +446,8 @@ ABD6EF071F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h */, ABD6EF081F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m */, C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */, + C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */, + C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.m */, ABD6EF0E1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.h */, ABD6EF0F1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm */, ); @@ -605,6 +613,7 @@ 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 */, @@ -650,6 +659,7 @@ 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 */, @@ -881,6 +891,7 @@ C9FD921B1E9A667600374FC4 /* ovpncli.cpp in Sources */, C9657A361EB0BA3900EFF210 /* OpenVPNInterfaceStats.mm in Sources */, C9657A211EB0ACAE00EFF210 /* OpenVPNConnectionInfo.mm in Sources */, + C9C2B2BD200CC42A00CA0FF3 /* OpenVPNPacket.m in Sources */, C93A4F621EE18009004DC561 /* OpenVPNError.m in Sources */, C93779D71EAE32670030A362 /* OpenVPNCredentials.mm in Sources */, C9B795601F1D16AA00CF35FE /* OpenVPNReachability.mm in Sources */, @@ -921,6 +932,7 @@ C9D2ABDE1EA20F99007EDF9D /* ovpncli.cpp in Sources */, C9657A371EB0BA3900EFF210 /* OpenVPNInterfaceStats.mm in Sources */, C9657A221EB0ACAE00EFF210 /* OpenVPNConnectionInfo.mm in Sources */, + C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.m in Sources */, C93A4F631EE18009004DC561 /* OpenVPNError.m in Sources */, C93779D81EAE32670030A362 /* OpenVPNCredentials.mm in Sources */, C9B795611F1D16AA00CF35FE /* OpenVPNReachability.mm in Sources */, diff --git a/OpenVPN Adapter/OpenVPNPacket.h b/OpenVPN Adapter/OpenVPNPacket.h new file mode 100644 index 0000000..9e423dd --- /dev/null +++ b/OpenVPN Adapter/OpenVPNPacket.h @@ -0,0 +1,22 @@ +// +// OpenVPNPacket.h +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 15.01.2018. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface OpenVPNPacket : NSObject + +@property (readonly, nonatomic) NSData *data; +@property (readonly, nonatomic) NSNumber *protocolFamily; + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/OpenVPN Adapter/OpenVPNPacket.m b/OpenVPN Adapter/OpenVPNPacket.m new file mode 100644 index 0000000..99aee01 --- /dev/null +++ b/OpenVPN Adapter/OpenVPNPacket.m @@ -0,0 +1,20 @@ +// +// OpenVPNPacket.m +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 15.01.2018. +// + +#import "OpenVPNPacket.h" + +@implementation OpenVPNPacket + +- (instancetype)initWithData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily { + if ((self = [super init])) { + _data = data; + _protocolFamily = protocolFamily; + } + return self; +} + +@end From f840b4a04631f4fded5013505aadb39e7ea5c255 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 15 Jan 2018 17:13:04 +0300 Subject: [PATCH 10/32] Move data preparation to the implementation of OpenVPNPacket --- OpenVPN Adapter/OpenVPNPacket.h | 17 +++++- OpenVPN Adapter/OpenVPNPacket.m | 20 ------- OpenVPN Adapter/OpenVPNPacket.mm | 95 ++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 22 deletions(-) delete mode 100644 OpenVPN Adapter/OpenVPNPacket.m create mode 100644 OpenVPN Adapter/OpenVPNPacket.mm diff --git a/OpenVPN Adapter/OpenVPNPacket.h b/OpenVPN Adapter/OpenVPNPacket.h index 9e423dd..5b0bacc 100644 --- a/OpenVPN Adapter/OpenVPNPacket.h +++ b/OpenVPN Adapter/OpenVPNPacket.h @@ -11,11 +11,24 @@ NS_ASSUME_NONNULL_BEGIN @interface OpenVPNPacket : NSObject -@property (readonly, nonatomic) NSData *data; +/** + 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)initWithData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithVPNData:(NSData *)data NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithPacketFlowData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily NS_DESIGNATED_INITIALIZER; @end diff --git a/OpenVPN Adapter/OpenVPNPacket.m b/OpenVPN Adapter/OpenVPNPacket.m deleted file mode 100644 index 99aee01..0000000 --- a/OpenVPN Adapter/OpenVPNPacket.m +++ /dev/null @@ -1,20 +0,0 @@ -// -// OpenVPNPacket.m -// OpenVPN Adapter -// -// Created by Sergey Abramchuk on 15.01.2018. -// - -#import "OpenVPNPacket.h" - -@implementation OpenVPNPacket - -- (instancetype)initWithData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily { - if ((self = [super init])) { - _data = data; - _protocolFamily = protocolFamily; - } - return self; -} - -@end diff --git a/OpenVPN Adapter/OpenVPNPacket.mm b/OpenVPN Adapter/OpenVPNPacket.mm new file mode 100644 index 0000000..f9344fb --- /dev/null +++ b/OpenVPN Adapter/OpenVPNPacket.mm @@ -0,0 +1,95 @@ +// +// OpenVPNPacket.m +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 15.01.2018. +// + +#import "OpenVPNPacket.h" + +#include + +#include + +@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 From fa2417c4af587ad67a6fa9ca0478385780044d1f Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Mon, 15 Jan 2018 17:13:33 +0300 Subject: [PATCH 11/32] Change file extension to mm --- OpenVPN Adapter.xcodeproj/project.pbxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index a3523c0..3dddfa9 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -128,8 +128,8 @@ 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.m in Sources */ = {isa = PBXBuildFile; fileRef = C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.m */; }; - C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.m */; }; + 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 */; }; @@ -249,7 +249,7 @@ C9C1E4131FA475B7006ECA7D /* CustomFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomFlow.swift; sourceTree = ""; }; C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNAdapterPacketFlow.h; sourceTree = ""; }; C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OpenVPNPacket.h; sourceTree = ""; }; - C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OpenVPNPacket.m; sourceTree = ""; }; + C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OpenVPNPacket.mm; sourceTree = ""; }; C9CA4DD11F602F7B00C4F184 /* OpenVPNCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenVPNCertificate.h; sourceTree = ""; }; C9CA4DD21F602F7B00C4F184 /* OpenVPNCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenVPNCertificate.m; sourceTree = ""; }; C9CA4DE01F603A5300C4F184 /* OpenVPNCertificateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNCertificateTests.swift; sourceTree = ""; }; @@ -447,7 +447,7 @@ ABD6EF081F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m */, C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */, C9C2B2B9200CC42A00CA0FF3 /* OpenVPNPacket.h */, - C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.m */, + C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */, ABD6EF0E1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.h */, ABD6EF0F1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm */, ); @@ -891,7 +891,7 @@ C9FD921B1E9A667600374FC4 /* ovpncli.cpp in Sources */, C9657A361EB0BA3900EFF210 /* OpenVPNInterfaceStats.mm in Sources */, C9657A211EB0ACAE00EFF210 /* OpenVPNConnectionInfo.mm in Sources */, - C9C2B2BD200CC42A00CA0FF3 /* OpenVPNPacket.m in Sources */, + C9C2B2BD200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */, C93A4F621EE18009004DC561 /* OpenVPNError.m in Sources */, C93779D71EAE32670030A362 /* OpenVPNCredentials.mm in Sources */, C9B795601F1D16AA00CF35FE /* OpenVPNReachability.mm in Sources */, @@ -932,7 +932,7 @@ C9D2ABDE1EA20F99007EDF9D /* ovpncli.cpp in Sources */, C9657A371EB0BA3900EFF210 /* OpenVPNInterfaceStats.mm in Sources */, C9657A221EB0ACAE00EFF210 /* OpenVPNConnectionInfo.mm in Sources */, - C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.m in Sources */, + C9C2B2BE200CC42A00CA0FF3 /* OpenVPNPacket.mm in Sources */, C93A4F631EE18009004DC561 /* OpenVPNError.m in Sources */, C93779D81EAE32670030A362 /* OpenVPNCredentials.mm in Sources */, C9B795611F1D16AA00CF35FE /* OpenVPNReachability.mm in Sources */, From 3eba7cc615ee1788c4577c548f0413be48622caf Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 16 Jan 2018 17:00:41 +0300 Subject: [PATCH 12/32] Refactor implementation of OpenVPNPacketFlowBridge class --- OpenVPN Adapter/OpenVPNPacketFlowBridge.h | 12 +- OpenVPN Adapter/OpenVPNPacketFlowBridge.mm | 210 +++++++++++---------- 2 files changed, 115 insertions(+), 107 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNPacketFlowBridge.h b/OpenVPN Adapter/OpenVPNPacketFlowBridge.h index 438e881..e025354 100644 --- a/OpenVPN Adapter/OpenVPNPacketFlowBridge.h +++ b/OpenVPN Adapter/OpenVPNPacketFlowBridge.h @@ -3,21 +3,25 @@ // OpenVPN Adapter // // Created by Jonathan Downing on 12/10/2017. +// Modified by Sergey Abramchuk on 15/01/2018. // #import 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; +- (nullable instancetype)initWithPacketFlow:(id)packetFlow NS_DESIGNATED_INITIALIZER; -- (nullable instancetype)initWithPacketFlow:(NEPacketTunnelFlow *)packetFlow NS_DESIGNATED_INITIALIZER; +- (BOOL)configureSocketsWithError:(NSError **)error; +- (void)startReading; @end diff --git a/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm b/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm index e4efd36..d979643 100644 --- a/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm +++ b/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm @@ -3,65 +3,85 @@ // OpenVPN Adapter // // Created by Jonathan Downing on 12/10/2017. +// Modified by Sergey Abramchuk on 15/01/2018. // -#import -#import #import "OpenVPNPacketFlowBridge.h" -@interface OpenVPNPacketFlowBridge () { - CFSocketRef _openVPNClientSocket; - CFSocketRef _packetFlowSocket; -} +#include +#include -@property (nonatomic) NEPacketTunnelFlow *packetFlow; +#import "OpenVPNError.h" +#import "OpenVPNPacket.h" +#import "OpenVPNAdapterPacketFlow.h" + +@interface OpenVPNPacketFlowBridge () + +@property (nonatomic) id 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)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:OpenVPNAdapterErrorTUNSetupFailed + 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:OpenVPNAdapterErrorTUNSetupFailed + 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:OpenVPNAdapterErrorTUNSetupFailed + 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:OpenVPNAdapterErrorTUNSetupFailed + userInfo:userInfo]; + } + return NO; } return YES; } -- (void)readPacketFlowPackets { +- (void)startReading { __weak typeof(self) weakSelf = self; - [self.packetFlow readPacketObjectsWithCompletionHandler:^(NSArray * _Nonnull packets) { + + [self.packetFlow readPacketsWithCompletionHandler:^(NSArray *packets, NSArray *protocols) { __strong typeof(self) self = weakSelf; - - [self writeVPNPacketObjects:packets]; - [self readPacketFlowPackets]; + + [self writePackets:packets protocols:protocols toSocket:self.packetFlowSocket]; + [self startReading]; }]; } -- (void)writeVPNPacketObjects:(NSArray *)packets { - for (NEPacket *packet in packets) { - CFSocketSendData(_packetFlowSocket, NULL, (CFDataRef)[self dataFromPacket:packet], 0.05); - } +#pragma mark - + +- (void)writePackets:(NSArray *)packets protocols:(NSArray *)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 - + +- (void)writePackets:(NSArray *)packets toPacketFlow:(id)packetFlow { + NSMutableArray *flowPackets = [[NSMutableArray alloc] init]; + NSMutableArray *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); From d3a2d6ec0caa40e3b50619954cf3e3a1c32e88cb Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 16 Jan 2018 17:08:00 +0300 Subject: [PATCH 13/32] Add pragma marks --- OpenVPN Adapter/OpenVPNPacketFlowBridge.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm b/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm index d979643..a92dc3b 100644 --- a/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm +++ b/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm @@ -142,7 +142,7 @@ static void SocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFData }]; } -#pragma mark - +#pragma mark - TUN -> VPN - (void)writePackets:(NSArray *)packets protocols:(NSArray *)protocols toSocket:(CFSocketRef)socket { [packets enumerateObjectsUsingBlock:^(NSData *data, NSUInteger idx, BOOL *stop) { @@ -153,7 +153,7 @@ static void SocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFData }]; } -#pragma mark - +#pragma mark - VPN -> TUN - (void)writePackets:(NSArray *)packets toPacketFlow:(id)packetFlow { NSMutableArray *flowPackets = [[NSMutableArray alloc] init]; From c956d61597433f1f9e4eaa09c0ff27ae3e88351c Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Wed, 17 Jan 2018 11:33:05 +0300 Subject: [PATCH 14/32] Add extra spaces and empty lines --- .../OpenVPNNetworkSettingsBuilder.h | 2 +- .../OpenVPNNetworkSettingsBuilder.m | 68 ++++++++----------- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h b/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h index afe083d..a524938 100644 --- a/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h +++ b/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h @@ -11,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN @class NEIPv4Route; @class NEIPv6Route; -@class NEPacketTunnelNetworkSettings; @class NEProxyServer; +@class NEPacketTunnelNetworkSettings; @interface OpenVPNNetworkSettingsBuilder : NSObject diff --git a/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.m b/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.m index c9292d4..11a31f1 100644 --- a/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.m +++ b/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.m @@ -5,21 +5,27 @@ // Created by Jonathan Downing on 12/10/2017. // -#import #import "OpenVPNNetworkSettingsBuilder.h" +#import + @interface OpenVPNNetworkSettingsBuilder () + @property (nonatomic) NSMutableArray *ipv4LocalAddresses; @property (nonatomic) NSMutableArray *ipv4SubnetMasks; @property (nonatomic) NSMutableArray *ipv4IncludedRoutes; @property (nonatomic) NSMutableArray *ipv4ExcludedRoutes; + @property (nonatomic) NSMutableArray *ipv6LocalAddresses; @property (nonatomic) NSMutableArray *ipv6NetworkPrefixLengths; @property (nonatomic) NSMutableArray *ipv6IncludedRoutes; @property (nonatomic) NSMutableArray *ipv6ExcludedRoutes; + @property (nonatomic) NSMutableArray *dnsServers; @property (nonatomic) NSMutableArray *searchDomains; + @property (nonatomic) NSMutableArray *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 *)ipv4LocalAddresses { - if (!_ipv4LocalAddresses) { - _ipv4LocalAddresses = [[NSMutableArray alloc] init]; - } + if (!_ipv4LocalAddresses) { _ipv4LocalAddresses = [[NSMutableArray alloc] init]; } return _ipv4LocalAddresses; } - (NSMutableArray *)ipv4SubnetMasks { - if (!_ipv4SubnetMasks) { - _ipv4SubnetMasks = [[NSMutableArray alloc] init]; - } + if (!_ipv4SubnetMasks) { _ipv4SubnetMasks = [[NSMutableArray alloc] init]; } return _ipv4SubnetMasks; } - (NSMutableArray *)ipv4IncludedRoutes { - if (!_ipv4IncludedRoutes) { - _ipv4IncludedRoutes = [[NSMutableArray alloc] init]; - } + if (!_ipv4IncludedRoutes) { _ipv4IncludedRoutes = [[NSMutableArray alloc] init]; } return _ipv4IncludedRoutes; } - (NSMutableArray *)ipv4ExcludedRoutes { - if (!_ipv4ExcludedRoutes) { - _ipv4ExcludedRoutes = [[NSMutableArray alloc] init]; - } + if (!_ipv4ExcludedRoutes) { _ipv4ExcludedRoutes = [[NSMutableArray alloc] init]; } return _ipv4ExcludedRoutes; } - (NSMutableArray *)ipv6LocalAddresses { - if (!_ipv6LocalAddresses) { - _ipv6LocalAddresses = [[NSMutableArray alloc] init]; - } + if (!_ipv6LocalAddresses) { _ipv6LocalAddresses = [[NSMutableArray alloc] init]; } return _ipv6LocalAddresses; } - (NSMutableArray *)ipv6NetworkPrefixLengths { - if (!_ipv6NetworkPrefixLengths) { - _ipv6NetworkPrefixLengths = [[NSMutableArray alloc] init]; - } + if (!_ipv6NetworkPrefixLengths) { _ipv6NetworkPrefixLengths = [[NSMutableArray alloc] init]; } return _ipv6NetworkPrefixLengths; } - (NSMutableArray *)ipv6IncludedRoutes { - if (!_ipv6IncludedRoutes) { - _ipv6IncludedRoutes = [[NSMutableArray alloc] init]; - } + if (!_ipv6IncludedRoutes) { _ipv6IncludedRoutes = [[NSMutableArray alloc] init]; } return _ipv6IncludedRoutes; } - (NSMutableArray *)ipv6ExcludedRoutes { - if (!_ipv6ExcludedRoutes) { - _ipv6ExcludedRoutes = [[NSMutableArray alloc] init]; - } + if (!_ipv6ExcludedRoutes) { _ipv6ExcludedRoutes = [[NSMutableArray alloc] init]; } return _ipv6ExcludedRoutes; } - (NSMutableArray *)dnsServers { - if (!_dnsServers) { - _dnsServers = [[NSMutableArray alloc] init]; - } + if (!_dnsServers) { _dnsServers = [[NSMutableArray alloc] init]; } return _dnsServers; } - (NSMutableArray *)searchDomains { - if (!_searchDomains) { - _searchDomains = [[NSMutableArray alloc] init]; - } + if (!_searchDomains) { _searchDomains = [[NSMutableArray alloc] init]; } return _searchDomains; } - (NSMutableArray *)proxyExceptionList { - if (!_proxyExceptionList) { - _proxyExceptionList = [[NSMutableArray alloc] init]; - } + if (!_proxyExceptionList) { _proxyExceptionList = [[NSMutableArray alloc] init]; } return _proxyExceptionList; } From 51440587ad5ab914841b357dec72b804a3a2752a Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Wed, 17 Jan 2018 11:56:38 +0300 Subject: [PATCH 15/32] Rename a few delegate methods and fix memory warning --- OpenVPN Adapter/OpenVPNClient.h | 14 ++++++++------ OpenVPN Adapter/OpenVPNClient.mm | 6 +++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNClient.h b/OpenVPN Adapter/OpenVPNClient.h index 08cb11c..4ffad1e 100644 --- a/OpenVPN Adapter/OpenVPNClient.h +++ b/OpenVPN Adapter/OpenVPNClient.h @@ -44,20 +44,22 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)establishTunnel; - (CFSocketNativeHandle)socketHandle; -- (void)clientEvent:(NSString *)eventName message:(nullable NSString *)message; -- (void)clientError:(NSString *)errorName fatal:(BOOL)fatal message:(nullable NSString *)message; -- (void)clientLog:(NSString *)logMessage; +- (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 _delegate); + OpenVPNClient(id _Nonnull delegate); bool tun_builder_new() override; @@ -93,7 +95,7 @@ public: void clock_tick() override; private: - __weak id delegate; + __weak id _Nonnull delegate; }; -NS_ASSUME_NONNULL_END + diff --git a/OpenVPN Adapter/OpenVPNClient.mm b/OpenVPN Adapter/OpenVPNClient.mm index efdb96f..9e371a2 100644 --- a/OpenVPN Adapter/OpenVPNClient.mm +++ b/OpenVPN Adapter/OpenVPNClient.mm @@ -153,15 +153,15 @@ void OpenVPNClient::event(const ClientAPI::Event& ev) { NSString *message = [NSString stringWithUTF8String:ev.info.c_str()]; if (ev.error) { - [this->delegate clientError:name fatal:ev.fatal message:message.length ? message : nil]; + [this->delegate clientErrorName:name fatal:ev.fatal message:message.length ? message : nil]; } else { - [this->delegate clientEvent:name message:message.length ? message : nil]; + [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 clientLog:logMessage]; + [this->delegate clientLogMessage:logMessage]; } void OpenVPNClient::clock_tick() { From 4094a097f18d68c7d29be1d4b98e74ab6b25f72a Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Wed, 17 Jan 2018 13:58:19 +0300 Subject: [PATCH 16/32] Add socket setup error --- OpenVPN Adapter/OpenVPNError.h | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenVPN Adapter/OpenVPNError.h b/OpenVPN Adapter/OpenVPNError.h index a8dd13c..02a3331 100644 --- a/OpenVPN Adapter/OpenVPNError.h +++ b/OpenVPN Adapter/OpenVPNError.h @@ -36,6 +36,7 @@ typedef NS_ERROR_ENUM(OpenVPNAdapterErrorDomain, OpenVPNAdapterError) { OpenVPNAdapterErrorBadSrcAddr, OpenVPNAdapterErrorCompressError, OpenVPNAdapterErrorResolveError, + OpenVPNAdapterErrorSocketSetupFailed, OpenVPNAdapterErrorSocketProtectError, OpenVPNAdapterErrorTUNReadError, OpenVPNAdapterErrorTUNWriteError, From a64893cd488e982032af36a71be97cce9a3161b8 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Wed, 17 Jan 2018 13:59:08 +0300 Subject: [PATCH 17/32] Initializer shouldn't return nil, and return socket setup error during socket configuration --- OpenVPN Adapter/OpenVPNPacketFlowBridge.h | 2 +- OpenVPN Adapter/OpenVPNPacketFlowBridge.mm | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNPacketFlowBridge.h b/OpenVPN Adapter/OpenVPNPacketFlowBridge.h index e025354..7f77b42 100644 --- a/OpenVPN Adapter/OpenVPNPacketFlowBridge.h +++ b/OpenVPN Adapter/OpenVPNPacketFlowBridge.h @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) CFSocketRef packetFlowSocket; - (instancetype)init NS_UNAVAILABLE; -- (nullable instancetype)initWithPacketFlow:(id)packetFlow NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithPacketFlow:(id)packetFlow NS_DESIGNATED_INITIALIZER; - (BOOL)configureSocketsWithError:(NSError **)error; - (void)startReading; diff --git a/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm b/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm index a92dc3b..4c0cc9b 100644 --- a/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm +++ b/OpenVPN Adapter/OpenVPNPacketFlowBridge.mm @@ -52,7 +52,7 @@ static void SocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFData }; *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain - code:OpenVPNAdapterErrorTUNSetupFailed + code:OpenVPNAdapterErrorSocketSetupFailed userInfo:userInfo]; } @@ -73,7 +73,7 @@ static void SocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFData }; *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain - code:OpenVPNAdapterErrorTUNSetupFailed + code:OpenVPNAdapterErrorSocketSetupFailed userInfo:userInfo]; } @@ -105,7 +105,7 @@ static void SocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFData }; *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain - code:OpenVPNAdapterErrorTUNSetupFailed + code:OpenVPNAdapterErrorSocketSetupFailed userInfo:userInfo]; } @@ -121,7 +121,7 @@ static void SocketCallback(CFSocketRef socket, CFSocketCallBackType type, CFData }; *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain - code:OpenVPNAdapterErrorTUNSetupFailed + code:OpenVPNAdapterErrorSocketSetupFailed userInfo:userInfo]; } From c47c5a9c3db813fa67c96ffbea0c2be0bbed33bf Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Wed, 17 Jan 2018 13:59:45 +0300 Subject: [PATCH 18/32] Return false if URL is nil --- OpenVPN Adapter/OpenVPNClient.mm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenVPN Adapter/OpenVPNClient.mm b/OpenVPN Adapter/OpenVPNClient.mm index 9e371a2..f33c9bd 100644 --- a/OpenVPN Adapter/OpenVPNClient.mm +++ b/OpenVPN Adapter/OpenVPNClient.mm @@ -106,7 +106,11 @@ bool OpenVPNClient::tun_builder_add_proxy_bypass(const std::string& bypass_host) bool OpenVPNClient::tun_builder_set_proxy_auto_config_url(const std::string& url) { NSURL *configURL = [[NSURL alloc] initWithString:[NSString stringWithUTF8String:url.c_str()]]; - return [this->delegate setProxyAutoConfigurationURL:configURL]; + if (configURL) { + return [this->delegate setProxyAutoConfigurationURL:configURL]; + } else { + return false; + } } bool OpenVPNClient::tun_builder_set_proxy_http(const std::string& host, int port) { From c53f9e0d2f7cafdc444367478c79c9e9a6c5b7cb Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Wed, 17 Jan 2018 14:00:13 +0300 Subject: [PATCH 19/32] Redefine networkSettings as method instead of property --- OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h b/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h index a524938..63903d2 100644 --- a/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h +++ b/OpenVPN Adapter/OpenVPNNetworkSettingsBuilder.h @@ -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 From 96d2ab185004223b1167f089f0ee5c6b4cd3f1a6 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Wed, 17 Jan 2018 14:01:09 +0300 Subject: [PATCH 20/32] Refactor implementation of OpenVPNAdapter class --- OpenVPN Adapter/OpenVPNAdapter.h | 30 +- OpenVPN Adapter/OpenVPNAdapter.mm | 721 +++++++++++++++--------------- 2 files changed, 354 insertions(+), 397 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNAdapter.h b/OpenVPN Adapter/OpenVPNAdapter.h index fb8ec37..45b5ccb 100644 --- a/OpenVPN Adapter/OpenVPNAdapter.h +++ b/OpenVPN Adapter/OpenVPNAdapter.h @@ -14,6 +14,9 @@ typedef NS_ENUM(NSInteger, OpenVPNAdapterEvent); @class NEPacketTunnelFlow; @class NEPacketTunnelNetworkSettings; + +@protocol OpenVPNAdapterPacketFlow; + @class OpenVPNAdapter; @class OpenVPNConfiguration; @class OpenVPNConnectionInfo; @@ -23,33 +26,6 @@ typedef NS_ENUM(NSInteger, OpenVPNAdapterEvent); @class OpenVPNTransportStats; @class OpenVPNSessionToken; -@protocol OpenVPNAdapterPacketFlow - -/** - 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 *packets, NSArray *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 *)packets withProtocols:(NSArray *)protocols; - -@end - @protocol OpenVPNAdapterDelegate /** diff --git a/OpenVPN Adapter/OpenVPNAdapter.mm b/OpenVPN Adapter/OpenVPNAdapter.mm index e7f83d8..b4a367b 100644 --- a/OpenVPN Adapter/OpenVPNAdapter.mm +++ b/OpenVPN Adapter/OpenVPNAdapter.mm @@ -8,265 +8,42 @@ #define OPENVPN_EXTERN extern +#import "OpenVPNAdapter.h" + #import -#import -#import + +#import "OpenVPNClient.h" +#import "OpenVPNError.h" #import "OpenVPNAdapterEvent.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 "OpenVPNAdapterPacketFlow.h" -class Client; +@interface OpenVPNAdapter () -@interface OpenVPNAdapter () - -@property (nonatomic) Client *client; - -@property (nonatomic) NSString *sessionName; - -@property (nonatomic) OpenVPNNetworkSettingsBuilder *networkSettingsBuilder; +@property (nonatomic) OpenVPNClient *vpnClient; @property (nonatomic) OpenVPNPacketFlowBridge *packetFlowBridge; +@property (nonatomic) OpenVPNNetworkSettingsBuilder *networkSettingsBuilder; +- (OpenVPNAdapterEvent)eventByName:(NSString *)eventName; - (OpenVPNAdapterError)errorByName:(NSString *)errorName; -- (OpenVPNAdapterEvent)eventByName:(NSString *)errorName; - (NSString *)reasonForError:(OpenVPNAdapterError)error; @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,16 +51,24 @@ 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]; + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ + NSLocalizedDescriptionKey: @"Failed to apply OpenVPN configuration", + OpenVPNAdapterErrorFatalKey: @YES + }]; - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to apply OpenVPN configuration.", - NSLocalizedFailureReasonErrorKey: errorReason, - OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:eval.message.c_str()], - OpenVPNAdapterErrorFatalKey: @YES }; + NSString *errorReason = [self reasonForError:OpenVPNAdapterErrorConfigurationFailure]; + if (errorReason) { + userInfo[NSLocalizedFailureReasonErrorKey] = errorReason; + } + + NSString *message = [[NSString alloc] initWithUTF8String:eval.message.c_str()]; + if (message.length) { + userInfo[OpenVPNAdapterErrorMessageKey] = message; + } *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:OpenVPNAdapterErrorConfigurationFailure userInfo: userInfo]; } @@ -294,7 +79,7 @@ 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) { @@ -302,12 +87,20 @@ private: [self errorByName:[[NSString alloc] initWithUTF8String:status.status.c_str()]] : OpenVPNAdapterErrorCredentialsFailure; - NSString *errorReason = [self reasonForError:errorCode]; + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ + NSLocalizedDescriptionKey: @"Failed to provide OpenVPN credentials", + OpenVPNAdapterErrorFatalKey: @YES + }]; - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to provide OpenVPN credentials.", - NSLocalizedFailureReasonErrorKey: errorReason, - OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:status.message.c_str()], - OpenVPNAdapterErrorFatalKey: @YES }; + NSString *errorReason = [self reasonForError:errorCode]; + if (errorReason) { + userInfo[NSLocalizedFailureReasonErrorKey] = errorReason; + } + + NSString *message = [[NSString alloc] initWithUTF8String:status.message.c_str()]; + if (message.length) { + userInfo[OpenVPNAdapterErrorMessageKey] = message; + } *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo]; } @@ -320,43 +113,53 @@ 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; + + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ + NSLocalizedDescriptionKey: @"Failed to establish connection with OpenVPN server", + OpenVPNAdapterErrorFatalKey: @YES + }]; + + NSString *errorReason = [self reasonForError:errorCode]; + if (errorReason) { + userInfo[NSLocalizedFailureReasonErrorKey] = errorReason; } - OpenVPNAdapterError errorCode = !status.status.empty() ? [self errorByName:[[NSString alloc] initWithUTF8String:status.status.c_str()]] : OpenVPNAdapterErrorUnknown; - NSString *errorReason = [self reasonForError:errorCode]; - - NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to establish connection with OpenVPN server.", - NSLocalizedFailureReasonErrorKey: errorReason, - OpenVPNAdapterErrorMessageKey: [[NSString alloc] initWithUTF8String:status.message.c_str()], - OpenVPNAdapterErrorFatalKey: @YES }; + NSString *message = [[NSString alloc] initWithUTF8String:status.message.c_str()]; + if (message.length) { + userInfo[OpenVPNAdapterErrorMessageKey] = message; + } NSError *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo]; [self.delegate openVPNAdapter:self handleError:error]; @@ -365,50 +168,52 @@ private: #pragma mark - OpenVPNClient Information + (NSString *)copyright { - return [[NSString alloc] initWithUTF8String:Client::copyright().c_str()]; + return [[NSString alloc] initWithUTF8String:OpenVPNClient::copyright().c_str()]; } + (NSString *)platform { - return [[NSString alloc] initWithUTF8String:Client::platform().c_str()]; + return [[NSString alloc] initWithUTF8String: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()]; + return [[OpenVPNTransportStats alloc] initWithTransportStats:self.vpnClient->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)}; - + 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; } @@ -416,76 +221,79 @@ private: #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)}; + 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; - 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."; @@ -501,6 +309,7 @@ private: 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."; @@ -535,23 +344,23 @@ private: 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 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 @""; - 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 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."; } } @@ -559,16 +368,188 @@ private: #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 _Nullable) = ^(id 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 { + OpenVPNAdapterEvent eventIdentifier = [self eventByName:eventName]; + [self.delegate openVPNAdapter:self handleEvent:eventIdentifier message:message]; +} + +- (void)clientErrorName:(NSString *)errorName fatal:(BOOL)fatal message:(NSString *)message { + OpenVPNAdapterError errorCode = [self errorByName:errorName]; + + NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ + NSLocalizedDescriptionKey: fatal ? @"OpenVPN fatal error occured" : @"OpenVPN error occured", + OpenVPNAdapterErrorFatalKey: @(fatal) + }]; + + NSString *errorReason = [self reasonForError:errorCode]; + if (errorReason) { + userInfo[NSLocalizedFailureReasonErrorKey] = errorReason; + } + + if (message) { + userInfo[OpenVPNAdapterErrorMessageKey] = message; + } + + NSError *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo]; + [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 From e4f7152cbab1d4391c3fa244400b3048f91ff2fa Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Wed, 17 Jan 2018 16:49:44 +0300 Subject: [PATCH 21/32] Refactor generation of OpenVPN adapter errors --- OpenVPN Adapter.xcodeproj/project.pbxproj | 20 ++ OpenVPN Adapter/NSError+OpenVPNError.h | 27 ++ OpenVPN Adapter/NSError+OpenVPNError.m | 181 +++++++++++++ OpenVPN Adapter/OpenVPNAdapter.mm | 308 ++++------------------ 4 files changed, 283 insertions(+), 253 deletions(-) create mode 100644 OpenVPN Adapter/NSError+OpenVPNError.h create mode 100644 OpenVPN Adapter/NSError+OpenVPNError.m diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index 3dddfa9..1dffb4a 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -150,6 +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 */; }; + 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 */; }; 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 */; }; @@ -257,6 +261,8 @@ C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OpenVPNClient.mm; sourceTree = ""; }; 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; }; + C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+OpenVPNError.h"; sourceTree = ""; }; + C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+OpenVPNError.m"; sourceTree = ""; }; C9E4401B1F6086A1001D7C41 /* NSError+Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+Message.h"; sourceTree = ""; }; C9E4401C1F6086A1001D7C41 /* NSError+Message.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+Message.m"; sourceTree = ""; }; C9FD92181E9A667600374FC4 /* ovpncli.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ovpncli.hpp; path = Vendors/openvpn/client/ovpncli.hpp; sourceTree = ""; }; @@ -559,6 +565,15 @@ name = "Certificates and Keys"; sourceTree = ""; }; + C9E350C5200F70CA000820D9 /* Extensions */ = { + isa = PBXGroup; + children = ( + C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */, + C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */, + ); + name = Extensions; + sourceTree = ""; + }; C9E4401A1F6081FF001D7C41 /* Utils */ = { isa = PBXGroup; children = ( @@ -571,6 +586,7 @@ C9FF73B71EB7421600E995AC /* Helpers */ = { isa = PBXGroup; children = ( + C9E350C5200F70CA000820D9 /* Extensions */, C9E4401A1F6081FF001D7C41 /* Utils */, ); name = Helpers; @@ -618,6 +634,7 @@ 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 */, @@ -664,6 +681,7 @@ 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 */, @@ -878,6 +896,7 @@ 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 */, @@ -919,6 +938,7 @@ 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 */, diff --git a/OpenVPN Adapter/NSError+OpenVPNError.h b/OpenVPN Adapter/NSError+OpenVPNError.h new file mode 100644 index 0000000..d10acd7 --- /dev/null +++ b/OpenVPN Adapter/NSError+OpenVPNError.h @@ -0,0 +1,27 @@ +// +// NSError+OpenVPNError.h +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 17.01.2018. +// + +#import + +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 + +NS_ASSUME_NONNULL_END diff --git a/OpenVPN Adapter/NSError+OpenVPNError.m b/OpenVPN Adapter/NSError+OpenVPNError.m new file mode 100644 index 0000000..7281c36 --- /dev/null +++ b/OpenVPN Adapter/NSError+OpenVPNError.m @@ -0,0 +1,181 @@ +// +// NSError+OpenVPNError.m +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 17.01.2018. +// + +#import "NSError+OpenVPNError.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 diff --git a/OpenVPN Adapter/OpenVPNAdapter.mm b/OpenVPN Adapter/OpenVPNAdapter.mm index b4a367b..951d505 100644 --- a/OpenVPN Adapter/OpenVPNAdapter.mm +++ b/OpenVPN Adapter/OpenVPNAdapter.mm @@ -15,16 +15,17 @@ #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 "OpenVPNInterfaceStats+Internal.h" -#import "OpenVPNNetworkSettingsBuilder.h" -#import "OpenVPNPacketFlowBridge.h" #import "OpenVPNProperties+Internal.h" #import "OpenVPNSessionToken+Internal.h" #import "OpenVPNTransportStats+Internal.h" -#import "OpenVPNAdapterPacketFlow.h" +#import "NSError+OpenVPNError.h" @interface OpenVPNAdapter () @@ -33,10 +34,6 @@ @property (nonatomic) OpenVPNPacketFlowBridge *packetFlowBridge; @property (nonatomic) OpenVPNNetworkSettingsBuilder *networkSettingsBuilder; -- (OpenVPNAdapterEvent)eventByName:(NSString *)eventName; -- (OpenVPNAdapterError)errorByName:(NSString *)errorName; -- (NSString *)reasonForError:(OpenVPNAdapterError)error; - @end @implementation OpenVPNAdapter @@ -55,23 +52,13 @@ if (eval.error) { if (error) { - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ - NSLocalizedDescriptionKey: @"Failed to apply OpenVPN configuration", - OpenVPNAdapterErrorFatalKey: @YES - }]; - - NSString *errorReason = [self reasonForError:OpenVPNAdapterErrorConfigurationFailure]; - if (errorReason) { - userInfo[NSLocalizedFailureReasonErrorKey] = errorReason; - } - - NSString *message = [[NSString alloc] initWithUTF8String:eval.message.c_str()]; - if (message.length) { - userInfo[OpenVPNAdapterErrorMessageKey] = message; - } - - *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; } @@ -83,26 +70,11 @@ if (status.error) { if (error) { - OpenVPNAdapterError errorCode = !status.status.empty() ? - [self errorByName:[[NSString alloc] initWithUTF8String:status.status.c_str()]] : - OpenVPNAdapterErrorCredentialsFailure; - - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ - NSLocalizedDescriptionKey: @"Failed to provide OpenVPN credentials", - OpenVPNAdapterErrorFatalKey: @YES - }]; - - NSString *errorReason = [self reasonForError:errorCode]; - if (errorReason) { - userInfo[NSLocalizedFailureReasonErrorKey] = errorReason; - } - - NSString *message = [[NSString alloc] initWithUTF8String:status.message.c_str()]; - if (message.length) { - userInfo[OpenVPNAdapterErrorMessageKey] = message; - } - - *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; @@ -143,36 +115,27 @@ - (void)handleConnectionStatus:(ClientAPI::Status)status { if (!status.error) { return; } - OpenVPNAdapterError errorCode = !status.status.empty() ? - [self errorByName:[[NSString alloc] initWithUTF8String:status.status.c_str()]] : OpenVPNAdapterErrorUnknown; + OpenVPNAdapterError adapterError = !status.status.empty() ? + [NSError ovpn_adapterErrorByName:[NSString stringWithUTF8String:status.status.c_str()]] : + OpenVPNAdapterErrorUnknown; - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ - NSLocalizedDescriptionKey: @"Failed to establish connection with OpenVPN server", - OpenVPNAdapterErrorFatalKey: @YES - }]; - - NSString *errorReason = [self reasonForError:errorCode]; - if (errorReason) { - userInfo[NSLocalizedFailureReasonErrorKey] = errorReason; - } - - NSString *message = [[NSString alloc] initWithUTF8String:status.message.c_str()]; - if (message.length) { - userInfo[OpenVPNAdapterErrorMessageKey] = message; - } - - 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:OpenVPNClient::copyright().c_str()]; + return [NSString stringWithUTF8String:OpenVPNClient::copyright().c_str()]; } + (NSString *)platform { - return [[NSString alloc] initWithUTF8String:OpenVPNClient::platform().c_str()]; + return [NSString stringWithUTF8String:OpenVPNClient::platform().c_str()]; } - (OpenVPNConnectionInfo *)connectionInformation { @@ -193,178 +156,6 @@ return [[OpenVPNTransportStats alloc] initWithTransportStats:self.vpnClient->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 { - 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."; - } -} - #pragma mark - Lazy Initialization - (OpenVPNNetworkSettingsBuilder *)networkSettingsBuilder { @@ -503,28 +294,39 @@ } - (void)clientEventName:(NSString *)eventName message:(NSString *)message { - OpenVPNAdapterEvent eventIdentifier = [self eventByName:eventName]; - [self.delegate openVPNAdapter:self handleEvent:eventIdentifier message: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 errorCode = [self errorByName:errorName]; + OpenVPNAdapterError adapterError = [NSError ovpn_adapterErrorByName:errorName]; + NSString *description = fatal ? @"OpenVPN fatal error occured" : @"OpenVPN error occured"; - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:@{ - NSLocalizedDescriptionKey: fatal ? @"OpenVPN fatal error occured" : @"OpenVPN error occured", - OpenVPNAdapterErrorFatalKey: @(fatal) - }]; - - NSString *errorReason = [self reasonForError:errorCode]; - if (errorReason) { - userInfo[NSLocalizedFailureReasonErrorKey] = errorReason; - } - - if (message) { - userInfo[OpenVPNAdapterErrorMessageKey] = message; - } - - NSError *error = [NSError errorWithDomain:OpenVPNAdapterErrorDomain code:errorCode userInfo:userInfo]; + NSError *error = [NSError ovpn_errorObjectForAdapterError:adapterError + description:description + message:message + fatal:YES]; + [self.delegate openVPNAdapter:self handleError:error]; } From 2b7680a89e3ea435aa4940505a35f6034c1fac60 Mon Sep 17 00:00:00 2001 From: Jonathan Downing Date: Thu, 18 Jan 2018 13:26:27 +0000 Subject: [PATCH 22/32] Add Nullability Annotations to OpenVPNAdapterPacketFlow (#43) * Add Nullability Annotations * Replace self with strongSelf * Revert "Replace self with strongSelf" This reverts commit 9c45dca3da1c86dcffe3f0faf65202da01476912. --- OpenVPN Adapter/OpenVPNAdapterPacketFlow.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenVPN Adapter/OpenVPNAdapterPacketFlow.h b/OpenVPN Adapter/OpenVPNAdapterPacketFlow.h index 958a5ba..3f8b8db 100644 --- a/OpenVPN Adapter/OpenVPNAdapterPacketFlow.h +++ b/OpenVPN Adapter/OpenVPNAdapterPacketFlow.h @@ -7,6 +7,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + @protocol OpenVPNAdapterPacketFlow /** @@ -33,3 +35,5 @@ - (BOOL)writePackets:(NSArray *)packets withProtocols:(NSArray *)protocols; @end + +NS_ASSUME_NONNULL_END From eff0bccfeff5c3414f19ca7013061b1310d7a90f Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Thu, 18 Jan 2018 16:39:41 +0300 Subject: [PATCH 23/32] Refactor generation of mbedTLS errors --- OpenVPN Adapter.xcodeproj/project.pbxproj | 24 ++----------- OpenVPN Adapter/NSError+Message.h | 15 --------- OpenVPN Adapter/NSError+Message.m | 28 ---------------- OpenVPN Adapter/NSError+OpenVPNError.h | 6 ++++ OpenVPN Adapter/NSError+OpenVPNError.m | 22 ++++++++++++ OpenVPN Adapter/OpenVPNCertificate.m | 33 +++++------------- OpenVPN Adapter/OpenVPNPrivateKey.m | 41 +++++++++-------------- 7 files changed, 54 insertions(+), 115 deletions(-) delete mode 100644 OpenVPN Adapter/NSError+Message.h delete mode 100644 OpenVPN Adapter/NSError+Message.m diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index 1dffb4a..d9e593d 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -154,10 +154,6 @@ 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 */; }; - 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 */; }; 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 */ @@ -263,8 +259,6 @@ C9D2ABFF1EA212A3007EDF9D /* OpenVPNAdapterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OpenVPNAdapterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C9E350BF200F6EC0000820D9 /* NSError+OpenVPNError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+OpenVPNError.h"; sourceTree = ""; }; C9E350C0200F6EC0000820D9 /* NSError+OpenVPNError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+OpenVPNError.m"; sourceTree = ""; }; - C9E4401B1F6086A1001D7C41 /* NSError+Message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+Message.h"; sourceTree = ""; }; - C9E4401C1F6086A1001D7C41 /* NSError+Message.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+Message.m"; sourceTree = ""; }; C9FD92181E9A667600374FC4 /* ovpncli.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ovpncli.hpp; path = Vendors/openvpn/client/ovpncli.hpp; sourceTree = ""; }; C9FD92191E9A667600374FC4 /* ovpncli.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ovpncli.cpp; path = Vendors/openvpn/client/ovpncli.cpp; sourceTree = ""; }; /* End PBXFileReference section */ @@ -447,8 +441,6 @@ C93A4F611EE18009004DC561 /* OpenVPNError.m */, C9CDFDD9200781AF00323B73 /* OpenVPNClient.h */, C9CDFDDA200781AF00323B73 /* OpenVPNClient.mm */, - ABD6EF151F8F9C37007D3D90 /* OpenVPNAdapter.h */, - ABD6EF161F8F9C38007D3D90 /* OpenVPNAdapter.mm */, ABD6EF071F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.h */, ABD6EF081F8F8CCD007D3D90 /* OpenVPNNetworkSettingsBuilder.m */, C9C2B2B6200CB42F00CA0FF3 /* OpenVPNAdapterPacketFlow.h */, @@ -456,6 +448,8 @@ C9C2B2BA200CC42A00CA0FF3 /* OpenVPNPacket.mm */, ABD6EF0E1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.h */, ABD6EF0F1F8F93AB007D3D90 /* OpenVPNPacketFlowBridge.mm */, + ABD6EF151F8F9C37007D3D90 /* OpenVPNAdapter.h */, + ABD6EF161F8F9C38007D3D90 /* OpenVPNAdapter.mm */, ); name = Adapter; sourceTree = ""; @@ -574,20 +568,10 @@ name = Extensions; sourceTree = ""; }; - C9E4401A1F6081FF001D7C41 /* Utils */ = { - isa = PBXGroup; - children = ( - C9E4401B1F6086A1001D7C41 /* NSError+Message.h */, - C9E4401C1F6086A1001D7C41 /* NSError+Message.m */, - ); - name = Utils; - sourceTree = ""; - }; C9FF73B71EB7421600E995AC /* Helpers */ = { isa = PBXGroup; children = ( C9E350C5200F70CA000820D9 /* Extensions */, - C9E4401A1F6081FF001D7C41 /* Utils */, ); name = Helpers; sourceTree = ""; @@ -625,7 +609,6 @@ 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 */, @@ -672,7 +655,6 @@ 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 */, @@ -900,7 +882,6 @@ 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 */, @@ -942,7 +923,6 @@ 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 */, diff --git a/OpenVPN Adapter/NSError+Message.h b/OpenVPN Adapter/NSError+Message.h deleted file mode 100644 index 6497c74..0000000 --- a/OpenVPN Adapter/NSError+Message.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// NSError+Message.h -// OpenVPN Adapter -// -// Created by Sergey Abramchuk on 06.09.17. -// -// - -#import - -@interface NSError (Message) - -+ (NSString *)reasonFromResult:(NSInteger)result; - -@end diff --git a/OpenVPN Adapter/NSError+Message.m b/OpenVPN Adapter/NSError+Message.m deleted file mode 100644 index 47e3a66..0000000 --- a/OpenVPN Adapter/NSError+Message.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// NSError+Message.m -// OpenVPN Adapter -// -// Created by Sergey Abramchuk on 06.09.17. -// -// - -#import - -#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 diff --git a/OpenVPN Adapter/NSError+OpenVPNError.h b/OpenVPN Adapter/NSError+OpenVPNError.h index d10acd7..c137a26 100644 --- a/OpenVPN Adapter/NSError+OpenVPNError.h +++ b/OpenVPN Adapter/NSError+OpenVPNError.h @@ -24,4 +24,10 @@ typedef NS_ERROR_ENUM(OpenVPNAdapterErrorDomain, OpenVPNAdapterError); @end +@interface NSError (OpenVPNMbedTLSErrorGeneration) + ++ (NSError *)ovpn_errorObjectForMbedTLSError:(NSInteger)errorCode description:(NSString *)description; + +@end + NS_ASSUME_NONNULL_END diff --git a/OpenVPN Adapter/NSError+OpenVPNError.m b/OpenVPN Adapter/NSError+OpenVPNError.m index 7281c36..3a607d4 100644 --- a/OpenVPN Adapter/NSError+OpenVPNError.m +++ b/OpenVPN Adapter/NSError+OpenVPNError.m @@ -7,6 +7,8 @@ #import "NSError+OpenVPNError.h" +#import + #import "OpenVPNError.h" @implementation NSError (OpenVPNAdapterErrorGeneration) @@ -179,3 +181,23 @@ } @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 diff --git a/OpenVPN Adapter/OpenVPNCertificate.m b/OpenVPN Adapter/OpenVPNCertificate.m index d7412b2..f0c70f7 100644 --- a/OpenVPN Adapter/OpenVPNCertificate.m +++ b/OpenVPN Adapter/OpenVPNCertificate.m @@ -5,13 +5,12 @@ // Created by Sergey Abramchuk on 06.09.17. // // +#import "OpenVPNCertificate.h" #import #import -#import "NSError+Message.h" -#import "OpenVPNError.h" -#import "OpenVPNCertificate.h" +#import "NSError+OpenVPNError.h" @interface OpenVPNCertificate () @@ -39,11 +38,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 +53,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; @@ -80,14 +71,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 +91,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; diff --git a/OpenVPN Adapter/OpenVPNPrivateKey.m b/OpenVPN Adapter/OpenVPNPrivateKey.m index 96100d8..deb4a6a 100644 --- a/OpenVPN Adapter/OpenVPNPrivateKey.m +++ b/OpenVPN Adapter/OpenVPNPrivateKey.m @@ -6,11 +6,11 @@ // // +#import "OpenVPNPrivateKey.h" + #import -#import "NSError+Message.h" -#import "OpenVPNError.h" -#import "OpenVPNPrivateKey.h" +#import "NSError+OpenVPNError.h" @interface OpenVPNPrivateKey () @@ -45,14 +45,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 +64,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; @@ -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); From 7078de3bae334a1771321f7e49fcff9711d41e97 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Thu, 18 Jan 2018 17:00:28 +0300 Subject: [PATCH 24/32] Apply style guide rules to certificate, key and reachability classes --- OpenVPN Adapter/OpenVPNCertificate.h | 10 ++--- OpenVPN Adapter/OpenVPNCertificate.m | 27 ++++++------- OpenVPN Adapter/OpenVPNPrivateKey.h | 12 +++--- OpenVPN Adapter/OpenVPNPrivateKey.m | 40 +++++++++---------- .../OpenVPNReachability+Internal.h | 1 - OpenVPN Adapter/OpenVPNReachability.h | 3 +- OpenVPN Adapter/OpenVPNReachability.mm | 20 +++++----- OpenVPN Adapter/OpenVPNReachabilityTracker.h | 2 +- OpenVPN Adapter/OpenVPNReachabilityTracker.mm | 7 +++- 9 files changed, 63 insertions(+), 59 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNCertificate.h b/OpenVPN Adapter/OpenVPNCertificate.h index 4cbb7bd..fb1c7f1 100644 --- a/OpenVPN Adapter/OpenVPNCertificate.h +++ b/OpenVPN Adapter/OpenVPNCertificate.h @@ -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 diff --git a/OpenVPN Adapter/OpenVPNCertificate.m b/OpenVPN Adapter/OpenVPNCertificate.m index f0c70f7..826792e 100644 --- a/OpenVPN Adapter/OpenVPNCertificate.m +++ b/OpenVPN Adapter/OpenVPNCertificate.m @@ -7,8 +7,8 @@ // #import "OpenVPNCertificate.h" -#import -#import +#include +#include #import "NSError+OpenVPNError.h" @@ -20,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]; @@ -62,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"; @@ -102,8 +101,8 @@ } - (void)dealloc { - mbedtls_x509_crt_free(self.crt); - free(self.crt); + mbedtls_x509_crt_free(_crt); + free(_crt); } @end diff --git a/OpenVPN Adapter/OpenVPNPrivateKey.h b/OpenVPN Adapter/OpenVPNPrivateKey.h index 81ca5f6..61f8727 100644 --- a/OpenVPN Adapter/OpenVPNPrivateKey.h +++ b/OpenVPN Adapter/OpenVPNPrivateKey.h @@ -8,24 +8,24 @@ #import -#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 diff --git a/OpenVPN Adapter/OpenVPNPrivateKey.m b/OpenVPN Adapter/OpenVPNPrivateKey.m index deb4a6a..a941878 100644 --- a/OpenVPN Adapter/OpenVPNPrivateKey.m +++ b/OpenVPN Adapter/OpenVPNPrivateKey.m @@ -8,8 +8,9 @@ #import "OpenVPNPrivateKey.h" -#import +#include +#import "OpenVPNKeyType.h" #import "NSError+OpenVPNError.h" @interface OpenVPNPrivateKey () @@ -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]; @@ -78,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); @@ -123,8 +123,8 @@ } - (void)dealloc { - mbedtls_pk_free(self.ctx); - free(self.ctx); + mbedtls_pk_free(_ctx); + free(_ctx); } @end diff --git a/OpenVPN Adapter/OpenVPNReachability+Internal.h b/OpenVPN Adapter/OpenVPNReachability+Internal.h index d38837a..a13c3bd 100644 --- a/OpenVPN Adapter/OpenVPNReachability+Internal.h +++ b/OpenVPN Adapter/OpenVPNReachability+Internal.h @@ -6,7 +6,6 @@ // // -#import "OpenVPNReachabilityTracker.h" #import "OpenVPNReachability.h" @interface OpenVPNReachability (Internal) diff --git a/OpenVPN Adapter/OpenVPNReachability.h b/OpenVPN Adapter/OpenVPNReachability.h index 8ba4632..123982d 100644 --- a/OpenVPN Adapter/OpenVPNReachability.h +++ b/OpenVPN Adapter/OpenVPNReachability.h @@ -7,7 +7,8 @@ // #import -#import "OpenVPNReachabilityStatus.h" + +typedef NS_ENUM(NSInteger, OpenVPNReachabilityStatus); @interface OpenVPNReachability : NSObject diff --git a/OpenVPN Adapter/OpenVPNReachability.mm b/OpenVPN Adapter/OpenVPNReachability.mm index 360da7b..02d8383 100644 --- a/OpenVPN Adapter/OpenVPNReachability.mm +++ b/OpenVPN Adapter/OpenVPNReachability.mm @@ -6,11 +6,14 @@ // // -#import - #import "OpenVPNReachability.h" #import "OpenVPNReachability+Internal.h" +#include + +#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 diff --git a/OpenVPN Adapter/OpenVPNReachabilityTracker.h b/OpenVPN Adapter/OpenVPNReachabilityTracker.h index 6ac0982..da61403 100644 --- a/OpenVPN Adapter/OpenVPNReachabilityTracker.h +++ b/OpenVPN Adapter/OpenVPNReachabilityTracker.h @@ -6,7 +6,7 @@ // // -#import +#include using namespace openvpn; diff --git a/OpenVPN Adapter/OpenVPNReachabilityTracker.mm b/OpenVPN Adapter/OpenVPNReachabilityTracker.mm index a84cb38..68b4f2f 100644 --- a/OpenVPN Adapter/OpenVPNReachabilityTracker.mm +++ b/OpenVPN Adapter/OpenVPNReachabilityTracker.mm @@ -6,10 +6,13 @@ // // -#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" + +OpenVPNReachabilityTracker::OpenVPNReachabilityTracker(const bool enable_internet, const bool enable_wifi, void* handler) : + ReachabilityTracker(enable_internet, enable_wifi) +{ this->handler = handler; } From cde1208002dd4fae31383167cfcae54fb8697989 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Thu, 18 Jan 2018 17:07:51 +0300 Subject: [PATCH 25/32] Add missing import of reachability status header --- OpenVPN Adapter/OpenVPNReachabilityTracker.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenVPN Adapter/OpenVPNReachabilityTracker.mm b/OpenVPN Adapter/OpenVPNReachabilityTracker.mm index 68b4f2f..259bac4 100644 --- a/OpenVPN Adapter/OpenVPNReachabilityTracker.mm +++ b/OpenVPN Adapter/OpenVPNReachabilityTracker.mm @@ -9,6 +9,7 @@ #import "OpenVPNReachabilityTracker.h" #import "OpenVPNReachability+Internal.h" +#import "OpenVPNReachabilityStatus.h" OpenVPNReachabilityTracker::OpenVPNReachabilityTracker(const bool enable_internet, const bool enable_wifi, void* handler) : ReachabilityTracker(enable_internet, enable_wifi) From 9c6e1fed2a3cf2ca21abfe51be7d4ca74b3b8bc4 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 23 Jan 2018 16:02:16 +0300 Subject: [PATCH 26/32] Apply style guide rules to the openvpn configuration class --- .../OpenVPNConfiguration+Internal.h | 18 +++++++++++------- OpenVPN Adapter/OpenVPNConfiguration.h | 10 +++++----- OpenVPN Adapter/OpenVPNConfiguration.mm | 9 ++++++++- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNConfiguration+Internal.h b/OpenVPN Adapter/OpenVPNConfiguration+Internal.h index 62d01cf..4bd4030 100644 --- a/OpenVPN Adapter/OpenVPNConfiguration+Internal.h +++ b/OpenVPN Adapter/OpenVPNConfiguration+Internal.h @@ -6,29 +6,33 @@ // // -#import - #import "OpenVPNConfiguration.h" +#include + 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 diff --git a/OpenVPN Adapter/OpenVPNConfiguration.h b/OpenVPN Adapter/OpenVPNConfiguration.h index 617593f..4ef4934 100644 --- a/OpenVPN Adapter/OpenVPNConfiguration.h +++ b/OpenVPN Adapter/OpenVPNConfiguration.h @@ -8,11 +8,11 @@ #import -#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 diff --git a/OpenVPN Adapter/OpenVPNConfiguration.mm b/OpenVPN Adapter/OpenVPNConfiguration.mm index da8c049..208f23f 100644 --- a/OpenVPN Adapter/OpenVPNConfiguration.mm +++ b/OpenVPN Adapter/OpenVPNConfiguration.mm @@ -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"; @@ -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))]; From c682c2a325968cd239f462a064306dd355a782e1 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 23 Jan 2018 16:11:30 +0300 Subject: [PATCH 27/32] Update tracking property name regarding style guide --- OpenVPN Adapter/OpenVPNReachability.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenVPN Adapter/OpenVPNReachability.h b/OpenVPN Adapter/OpenVPNReachability.h index 123982d..bb56cad 100644 --- a/OpenVPN Adapter/OpenVPNReachability.h +++ b/OpenVPN Adapter/OpenVPNReachability.h @@ -12,7 +12,7 @@ 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; From badd6d28be06229cd4c79242724e76b74c378943 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 23 Jan 2018 17:04:32 +0300 Subject: [PATCH 28/32] Apply style guide rules to the remaining classes --- OpenVPN Adapter/OpenVPNConnectionInfo+Internal.h | 4 ++-- OpenVPN Adapter/OpenVPNConnectionInfo.mm | 4 ++-- OpenVPN Adapter/OpenVPNCredentials+Internal.h | 5 ++--- OpenVPN Adapter/OpenVPNCredentials.mm | 3 ++- OpenVPN Adapter/OpenVPNInterfaceStats+Internal.h | 4 ++-- OpenVPN Adapter/OpenVPNInterfaceStats.mm | 4 ++-- OpenVPN Adapter/OpenVPNPacket.mm | 4 ++-- OpenVPN Adapter/OpenVPNProperties+Internal.h | 4 ++-- OpenVPN Adapter/OpenVPNProperties.h | 7 +++---- OpenVPN Adapter/OpenVPNProperties.mm | 11 ++++++----- OpenVPN Adapter/OpenVPNServerEntry+Internal.h | 4 ++-- OpenVPN Adapter/OpenVPNServerEntry.h | 2 +- OpenVPN Adapter/OpenVPNServerEntry.mm | 3 +-- OpenVPN Adapter/OpenVPNSessionToken+Internal.h | 4 ++-- OpenVPN Adapter/OpenVPNSessionToken.mm | 5 +++-- OpenVPN Adapter/OpenVPNTransportStats+Internal.h | 4 ++-- OpenVPN Adapter/OpenVPNTransportStats.mm | 11 +++++++---- 17 files changed, 43 insertions(+), 40 deletions(-) diff --git a/OpenVPN Adapter/OpenVPNConnectionInfo+Internal.h b/OpenVPN Adapter/OpenVPNConnectionInfo+Internal.h index 829beea..c03fb21 100644 --- a/OpenVPN Adapter/OpenVPNConnectionInfo+Internal.h +++ b/OpenVPN Adapter/OpenVPNConnectionInfo+Internal.h @@ -6,10 +6,10 @@ // // -#import - #import "OpenVPNConnectionInfo.h" +#include + using namespace openvpn; @interface OpenVPNConnectionInfo (Internal) diff --git a/OpenVPN Adapter/OpenVPNConnectionInfo.mm b/OpenVPN Adapter/OpenVPNConnectionInfo.mm index e3eb83e..d4900a6 100644 --- a/OpenVPN Adapter/OpenVPNConnectionInfo.mm +++ b/OpenVPN Adapter/OpenVPNConnectionInfo.mm @@ -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))]; diff --git a/OpenVPN Adapter/OpenVPNCredentials+Internal.h b/OpenVPN Adapter/OpenVPNCredentials+Internal.h index bd6cb6f..8cb7831 100644 --- a/OpenVPN Adapter/OpenVPNCredentials+Internal.h +++ b/OpenVPN Adapter/OpenVPNCredentials+Internal.h @@ -5,11 +5,10 @@ // Created by Sergey Abramchuk on 24.04.17. // // - -#import - #import "OpenVPNCredentials.h" +#include + using namespace openvpn; @interface OpenVPNCredentials (Internal) diff --git a/OpenVPN Adapter/OpenVPNCredentials.mm b/OpenVPN Adapter/OpenVPNCredentials.mm index 5c7bbf6..4748785 100644 --- a/OpenVPN Adapter/OpenVPNCredentials.mm +++ b/OpenVPN Adapter/OpenVPNCredentials.mm @@ -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 { diff --git a/OpenVPN Adapter/OpenVPNInterfaceStats+Internal.h b/OpenVPN Adapter/OpenVPNInterfaceStats+Internal.h index 9c58773..735e605 100644 --- a/OpenVPN Adapter/OpenVPNInterfaceStats+Internal.h +++ b/OpenVPN Adapter/OpenVPNInterfaceStats+Internal.h @@ -6,10 +6,10 @@ // // -#import - #import "OpenVPNInterfaceStats.h" +#include + using namespace openvpn; @interface OpenVPNInterfaceStats (Internal) diff --git a/OpenVPN Adapter/OpenVPNInterfaceStats.mm b/OpenVPN Adapter/OpenVPNInterfaceStats.mm index 003b2d9..2f9333a 100644 --- a/OpenVPN Adapter/OpenVPNInterfaceStats.mm +++ b/OpenVPN Adapter/OpenVPNInterfaceStats.mm @@ -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))]; diff --git a/OpenVPN Adapter/OpenVPNPacket.mm b/OpenVPN Adapter/OpenVPNPacket.mm index f9344fb..0846016 100644 --- a/OpenVPN Adapter/OpenVPNPacket.mm +++ b/OpenVPN Adapter/OpenVPNPacket.mm @@ -21,7 +21,7 @@ @implementation OpenVPNPacket - (instancetype)initWithVPNData:(NSData *)data { - if ((self = [super init])) { + if (self = [super init]) { #if TARGET_OS_IPHONE // Get network protocol family from data prefix NSUInteger prefix_size = sizeof(uint32_t); @@ -59,7 +59,7 @@ } - (instancetype)initWithPacketFlowData:(NSData *)data protocolFamily:(NSNumber *)protocolFamily { - if ((self = [super init])) { + if (self = [super init]) { _data = data; _protocolFamily = protocolFamily; } diff --git a/OpenVPN Adapter/OpenVPNProperties+Internal.h b/OpenVPN Adapter/OpenVPNProperties+Internal.h index c4f0ea9..d6bee9a 100644 --- a/OpenVPN Adapter/OpenVPNProperties+Internal.h +++ b/OpenVPN Adapter/OpenVPNProperties+Internal.h @@ -6,10 +6,10 @@ // // -#import - #import "OpenVPNProperties.h" +#include + using namespace openvpn; @interface OpenVPNProperties (Internal) diff --git a/OpenVPN Adapter/OpenVPNProperties.h b/OpenVPN Adapter/OpenVPNProperties.h index 1182d2d..8a63975 100644 --- a/OpenVPN Adapter/OpenVPNProperties.h +++ b/OpenVPN Adapter/OpenVPNProperties.h @@ -8,8 +8,7 @@ #import -#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 *servers; -- (nonnull instancetype) __unavailable init; +- (nonnull instancetype) init NS_UNAVAILABLE; @end diff --git a/OpenVPN Adapter/OpenVPNProperties.mm b/OpenVPN Adapter/OpenVPNProperties.mm index 2dca5e5..8a6cdf9 100644 --- a/OpenVPN Adapter/OpenVPNProperties.mm +++ b/OpenVPN Adapter/OpenVPNProperties.mm @@ -6,20 +6,20 @@ // // -#import +#import "OpenVPNProperties.h" +#import "OpenVPNProperties+Internal.h" + +#include #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]; diff --git a/OpenVPN Adapter/OpenVPNServerEntry+Internal.h b/OpenVPN Adapter/OpenVPNServerEntry+Internal.h index e8685f5..b4e44fe 100644 --- a/OpenVPN Adapter/OpenVPNServerEntry+Internal.h +++ b/OpenVPN Adapter/OpenVPNServerEntry+Internal.h @@ -6,10 +6,10 @@ // // -#import - #import "OpenVPNServerEntry.h" +#include + using namespace openvpn; @interface OpenVPNServerEntry (Internal) diff --git a/OpenVPN Adapter/OpenVPNServerEntry.h b/OpenVPN Adapter/OpenVPNServerEntry.h index 75ecb40..4898f52 100644 --- a/OpenVPN Adapter/OpenVPNServerEntry.h +++ b/OpenVPN Adapter/OpenVPNServerEntry.h @@ -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 diff --git a/OpenVPN Adapter/OpenVPNServerEntry.mm b/OpenVPN Adapter/OpenVPNServerEntry.mm index b87e7d0..13f74d8 100644 --- a/OpenVPN Adapter/OpenVPNServerEntry.mm +++ b/OpenVPN Adapter/OpenVPNServerEntry.mm @@ -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; } diff --git a/OpenVPN Adapter/OpenVPNSessionToken+Internal.h b/OpenVPN Adapter/OpenVPNSessionToken+Internal.h index 667bf3b..b1c9026 100644 --- a/OpenVPN Adapter/OpenVPNSessionToken+Internal.h +++ b/OpenVPN Adapter/OpenVPNSessionToken+Internal.h @@ -6,10 +6,10 @@ // // -#import - #import "OpenVPNSessionToken.h" +#include + using namespace openvpn; @interface OpenVPNSessionToken (Internal) diff --git a/OpenVPN Adapter/OpenVPNSessionToken.mm b/OpenVPN Adapter/OpenVPNSessionToken.mm index 462ffb7..9d2f298 100644 --- a/OpenVPN Adapter/OpenVPNSessionToken.mm +++ b/OpenVPN Adapter/OpenVPNSessionToken.mm @@ -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))]; } diff --git a/OpenVPN Adapter/OpenVPNTransportStats+Internal.h b/OpenVPN Adapter/OpenVPNTransportStats+Internal.h index 974d694..df7e129 100644 --- a/OpenVPN Adapter/OpenVPNTransportStats+Internal.h +++ b/OpenVPN Adapter/OpenVPNTransportStats+Internal.h @@ -6,10 +6,10 @@ // // -#import - #import "OpenVPNTransportStats.h" +#include + using namespace openvpn; @interface OpenVPNTransportStats (Internal) diff --git a/OpenVPN Adapter/OpenVPNTransportStats.mm b/OpenVPN Adapter/OpenVPNTransportStats.mm index 4dc4ad7..2a7c554 100644 --- a/OpenVPN Adapter/OpenVPNTransportStats.mm +++ b/OpenVPN Adapter/OpenVPNTransportStats.mm @@ -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; } From f22ffdc4f0e6c4bab6dbadd4b304f6001afd5e43 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 23 Jan 2018 17:14:03 +0300 Subject: [PATCH 29/32] Fix crash if empty data was provided --- OpenVPN Adapter/OpenVPNConfiguration.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenVPN Adapter/OpenVPNConfiguration.mm b/OpenVPN Adapter/OpenVPNConfiguration.mm index 208f23f..3d5dc6b 100644 --- a/OpenVPN Adapter/OpenVPNConfiguration.mm +++ b/OpenVPN Adapter/OpenVPNConfiguration.mm @@ -219,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 *)settings { From c838baef4da05ccffa46480ff8cf3f1b222d6141 Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 23 Jan 2018 17:17:48 +0300 Subject: [PATCH 30/32] Update tests --- OpenVPN Adapter Tests/CustomFlow.swift | 17 +++++------------ OpenVPN Adapter Tests/OpenVPNAdapterTests.swift | 2 +- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/OpenVPN Adapter Tests/CustomFlow.swift b/OpenVPN Adapter Tests/CustomFlow.swift index dbd423f..23e0f58 100644 --- a/OpenVPN Adapter Tests/CustomFlow.swift +++ b/OpenVPN Adapter Tests/CustomFlow.swift @@ -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 } diff --git a/OpenVPN Adapter Tests/OpenVPNAdapterTests.swift b/OpenVPN Adapter Tests/OpenVPNAdapterTests.swift index 0642e45..40a83f6 100644 --- a/OpenVPN Adapter Tests/OpenVPNAdapterTests.swift +++ b/OpenVPN Adapter Tests/OpenVPNAdapterTests.swift @@ -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) } From 2bb3c1ff8e238b3940835e7f1ee7593cf1cc289c Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 23 Jan 2018 17:18:06 +0300 Subject: [PATCH 31/32] Update project settings --- OpenVPN Adapter.xcodeproj/project.pbxproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index d9e593d..c8f9d41 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -1379,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; @@ -1426,7 +1425,6 @@ SDKROOT = macosx; SUPPORTED_PLATFORMS = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.0; VALIDATE_PRODUCT = YES; }; From 32ea25ecd7b25a6c2d27cb71fea15bb2dc52d30a Mon Sep 17 00:00:00 2001 From: Sergey Abramchuk Date: Tue, 23 Jan 2018 17:19:32 +0300 Subject: [PATCH 32/32] Add header guards --- OpenVPN Adapter/Vendors/openvpn/client/ovpncli.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OpenVPN Adapter/Vendors/openvpn/client/ovpncli.hpp b/OpenVPN Adapter/Vendors/openvpn/client/ovpncli.hpp index 3059d09..5aa4bf1 100644 --- a/OpenVPN Adapter/Vendors/openvpn/client/ovpncli.hpp +++ b/OpenVPN Adapter/Vendors/openvpn/client/ovpncli.hpp @@ -24,6 +24,9 @@ // The crux of the API is defined in OpenVPNClient (below) // and TunBuilderBase. +#ifndef OVPNCLI_HPP +#define OVPNCLI_HPP + #include #include #include @@ -600,3 +603,5 @@ namespace openvpn { } } + +#endif