diff --git a/OpenVPN Adapter.xcodeproj/project.pbxproj b/OpenVPN Adapter.xcodeproj/project.pbxproj index 251bdf0..65ae32b 100644 --- a/OpenVPN Adapter.xcodeproj/project.pbxproj +++ b/OpenVPN Adapter.xcodeproj/project.pbxproj @@ -9,6 +9,10 @@ /* Begin PBXBuildFile section */ C90BAD311E73FF6C00DEFB32 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C90BAD301E73FF6C00DEFB32 /* SystemConfiguration.framework */; }; C912BB251E7C3339002B9414 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C912BB241E7C3339002B9414 /* NetworkExtension.framework */; }; + C93779CE1EAE17F50030A362 /* ConfigurationValues.h in Headers */ = {isa = PBXBuildFile; fileRef = C93779CC1EAE17F50030A362 /* ConfigurationValues.h */; }; + C93779CF1EAE17F50030A362 /* ConfigurationValues.mm in Sources */ = {isa = PBXBuildFile; fileRef = C93779CD1EAE17F50030A362 /* ConfigurationValues.mm */; }; + C93779D01EAE18730030A362 /* ConfigurationValues.h in Headers */ = {isa = PBXBuildFile; fileRef = C93779CC1EAE17F50030A362 /* ConfigurationValues.h */; }; + C93779D11EAE18760030A362 /* ConfigurationValues.mm in Sources */ = {isa = PBXBuildFile; fileRef = C93779CD1EAE17F50030A362 /* ConfigurationValues.mm */; }; C94605E91EAA656B00971516 /* OpenVPNConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C94605E81EAA656B00971516 /* OpenVPNConfigurationTests.swift */; }; C94605EA1EAA65F200971516 /* OpenVPNConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C94605E81EAA656B00971516 /* OpenVPNConfigurationTests.swift */; }; C98467A21EAA559B00272A9A /* local_key_auth.ovpn in Resources */ = {isa = PBXBuildFile; fileRef = C98467A11EAA559B00272A9A /* local_key_auth.ovpn */; }; @@ -80,6 +84,8 @@ C90BAD2F1E73FA7400DEFB32 /* Tests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Tests.xcconfig; sourceTree = ""; }; C90BAD301E73FF6C00DEFB32 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; C912BB241E7C3339002B9414 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; }; + C93779CC1EAE17F50030A362 /* ConfigurationValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigurationValues.h; sourceTree = ""; }; + C93779CD1EAE17F50030A362 /* ConfigurationValues.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ConfigurationValues.mm; sourceTree = ""; }; C94605E81EAA656B00971516 /* OpenVPNConfigurationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNConfigurationTests.swift; sourceTree = ""; }; C98467A11EAA559B00272A9A /* local_key_auth.ovpn */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = local_key_auth.ovpn; sourceTree = ""; }; C98467A41EAA5B7700272A9A /* OpenVPNConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenVPNConfiguration.h; sourceTree = ""; }; @@ -188,6 +194,23 @@ name = Frameworks; sourceTree = ""; }; + C93779CA1EAE15EE0030A362 /* Helpers */ = { + isa = PBXGroup; + children = ( + C93779CB1EAE15F50030A362 /* Constants */, + ); + name = Helpers; + sourceTree = ""; + }; + C93779CB1EAE15F50030A362 /* Constants */ = { + isa = PBXGroup; + children = ( + C93779CC1EAE17F50030A362 /* ConfigurationValues.h */, + C93779CD1EAE17F50030A362 /* ConfigurationValues.mm */, + ); + name = Constants; + sourceTree = ""; + }; C9B376B71EA53CE700B7F423 /* Client */ = { isa = PBXGroup; children = ( @@ -211,6 +234,7 @@ C9BB47641E7169AF00F3F98C /* Libraries */ = { isa = PBXGroup; children = ( + C93779CA1EAE15EE0030A362 /* Helpers */, C9BB47681E716ABF00F3F98C /* Vendors */, ); name = Libraries; @@ -321,6 +345,7 @@ C9BB477F1E7173C700F3F98C /* OpenVPNAdapter.h in Headers */, C98467AB1EAA5BE100272A9A /* OpenVPNConfiguration+Internal.h in Headers */, C98467A61EAA5B7700272A9A /* OpenVPNConfiguration.h in Headers */, + C93779CE1EAE17F50030A362 /* ConfigurationValues.h in Headers */, C9BB47601E71663A00F3F98C /* Umbrella-Header.h in Headers */, C9BB47811E7173C700F3F98C /* OpenVPNAdapter+Public.h in Headers */, C9BB47711E7171A100F3F98C /* OpenVPNError.h in Headers */, @@ -338,6 +363,7 @@ C9D2ABE51EA20F99007EDF9D /* OpenVPNAdapter.h in Headers */, C98467AC1EAA5BE200272A9A /* OpenVPNConfiguration+Internal.h in Headers */, C98467A71EAA5B7700272A9A /* OpenVPNConfiguration.h in Headers */, + C93779D01EAE18730030A362 /* ConfigurationValues.h in Headers */, C9D2ABE61EA20F99007EDF9D /* Umbrella-Header.h in Headers */, C9D2ABE71EA20F99007EDF9D /* OpenVPNAdapter+Public.h in Headers */, C9D2ABE81EA20F99007EDF9D /* OpenVPNError.h in Headers */, @@ -543,6 +569,7 @@ C9BB47821E7173C700F3F98C /* OpenVPNAdapter.mm in Sources */, C98467A81EAA5B7700272A9A /* OpenVPNConfiguration.mm in Sources */, C9BB477A1E7171ED00F3F98C /* OpenVPNClient.mm in Sources */, + C93779CF1EAE17F50030A362 /* ConfigurationValues.mm in Sources */, C9FD921B1E9A667600374FC4 /* ovpncli.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -566,6 +593,7 @@ C98467A91EAA5B7700272A9A /* OpenVPNConfiguration.mm in Sources */, C9D2ABDC1EA20F99007EDF9D /* OpenVPNClient.mm in Sources */, C9D2ABDE1EA20F99007EDF9D /* ovpncli.cpp in Sources */, + C93779D11EAE18760030A362 /* ConfigurationValues.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/OpenVPN Adapter/ConfigurationValues.h b/OpenVPN Adapter/ConfigurationValues.h new file mode 100644 index 0000000..e7b3a06 --- /dev/null +++ b/OpenVPN Adapter/ConfigurationValues.h @@ -0,0 +1,22 @@ +// +// ConfigurationValues.h +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 24.04.17. +// +// + +#import + +extern NSString * __nonnull const OpenVPNMinTLSVersionDisabledValue; +extern NSString * __nonnull const OpenVPNMinTLSVersion10Value; +extern NSString * __nonnull const OpenVPNMinTLSVersion11Value; +extern NSString * __nonnull const OpenVPNMinTLSVersion12Value; +extern NSString * __nonnull const OpenVPNMinTLSVersionDefaultValue; + +extern NSString * __nonnull const OpenVPNTLSCertProfileLegacyValue; +extern NSString * __nonnull const OpenVPNTLSCertProfilePreferredValue; +extern NSString * __nonnull const OpenVPNTLSCertProfileSuiteBValue; +extern NSString * __nonnull const OpenVPNTLSCertProfileLegacyDefaultValue; +extern NSString * __nonnull const OpenVPNTLSCertProfilePreferredDefaultValue; +extern NSString * __nonnull const OpenVPNTLSCertProfileDefaultValue; diff --git a/OpenVPN Adapter/ConfigurationValues.mm b/OpenVPN Adapter/ConfigurationValues.mm new file mode 100644 index 0000000..1ae117c --- /dev/null +++ b/OpenVPN Adapter/ConfigurationValues.mm @@ -0,0 +1,22 @@ +// +// ConfigurationValues.m +// OpenVPN Adapter +// +// Created by Sergey Abramchuk on 24.04.17. +// +// + +#import "ConfigurationValues.h" + +NSString * const OpenVPNMinTLSVersionDisabledValue = @"disabled"; +NSString * const OpenVPNMinTLSVersion10Value = @"tls_1_0"; +NSString * const OpenVPNMinTLSVersion11Value = @"tls_1_1"; +NSString * const OpenVPNMinTLSVersion12Value = @"tls_1_2"; +NSString * const OpenVPNMinTLSVersionDefaultValue = @"default"; + +NSString * const OpenVPNTLSCertProfileLegacyValue = @"legacy"; +NSString * const OpenVPNTLSCertProfilePreferredValue = @"preferred"; +NSString * const OpenVPNTLSCertProfileSuiteBValue = @"suiteb"; +NSString * const OpenVPNTLSCertProfileLegacyDefaultValue = @"legacy-default"; +NSString * const OpenVPNTLSCertProfilePreferredDefaultValue = @"preferred-default"; +NSString * const OpenVPNTLSCertProfileDefaultValue = @"default"; diff --git a/OpenVPN Adapter/OpenVPNConfiguration.h b/OpenVPN Adapter/OpenVPNConfiguration.h index 9e81e8f..df16027 100644 --- a/OpenVPN Adapter/OpenVPNConfiguration.h +++ b/OpenVPN Adapter/OpenVPNConfiguration.h @@ -66,6 +66,21 @@ typedef NS_ENUM(NSInteger, OpenVPNMinTLSVersion) { OpenVPNMinTLSVersionDefault }; +typedef NS_ENUM(NSInteger, OpenVPNTLSCertProfile) { + /// Allow 1024-bit RSA certs signed with SHA1 + OpenVPNTLSCertProfileLegacy, + /// Require at least 2048-bit RSA certs signed with SHA256 or higher + OpenVPNTLSCertProfilePreferred, + /// Require NSA Suite-B + OpenVPNTLSCertProfileSuiteB, + /// Use legacy as the default if profile doesn't specify tls-cert-profile + OpenVPNTLSCertProfileLegacyDefault, + /// Use preferred as the default if profile doesn't specify tls-cert-profile + OpenVPNTLSCertProfilePreferredDefault, + /// Use profile default + OpenVPNTLSCertProfileDefault +}; + @interface OpenVPNConfiguration : NSObject /** @@ -164,4 +179,14 @@ typedef NS_ENUM(NSInteger, OpenVPNMinTLSVersion) { */ @property (nonatomic) OpenVPNMinTLSVersion minTLSVersion; +/** + Override or default the tls-cert-profile setting + */ +@property (nonatomic) OpenVPNTLSCertProfile tlsCertProfile; + +/** + Pass custom key/value pairs to OpenVPN server + */ +@property (nullable, nonatomic) NSDictionary *peerInfo; + @end diff --git a/OpenVPN Adapter/OpenVPNConfiguration.mm b/OpenVPN Adapter/OpenVPNConfiguration.mm index 2626a4a..e15470d 100644 --- a/OpenVPN Adapter/OpenVPNConfiguration.mm +++ b/OpenVPN Adapter/OpenVPNConfiguration.mm @@ -6,6 +6,7 @@ // // +#import "ConfigurationValues.h" #import "OpenVPNConfiguration.h" #import "OpenVPNConfiguration+Internal.h" @@ -92,7 +93,7 @@ using namespace openvpn; NSString *currentValue = [NSString stringWithUTF8String:_config.protoOverride.c_str()]; NSNumber *transportProtocol = options[currentValue]; - NSAssert(transportProtocol != nil, @"Incorrect ipv6 value"); + NSAssert(transportProtocol != nil, @"Incorrect protoOverride value"); return (OpenVPNTransportProtocol)[transportProtocol integerValue]; } @@ -271,48 +272,100 @@ using namespace openvpn; - (OpenVPNMinTLSVersion)minTLSVersion { NSDictionary *options = @{ - @"disabled": @(OpenVPNMinTLSVersionDisabled), - @"tls_1_0": @(OpenVPNMinTLSVersion10), - @"tls_1_1": @(OpenVPNMinTLSVersion11), - @"tls_1_2": @(OpenVPNMinTLSVersion12), - @"default": @(OpenVPNMinTLSVersionDefault), - @"": @(OpenVPNMinTLSVersionDefault) + OpenVPNMinTLSVersionDisabledValue: @(OpenVPNMinTLSVersionDisabled), + OpenVPNMinTLSVersion10Value: @(OpenVPNMinTLSVersion10), + OpenVPNMinTLSVersion11Value: @(OpenVPNMinTLSVersion11), + OpenVPNMinTLSVersion12Value: @(OpenVPNMinTLSVersion12), + OpenVPNMinTLSVersionDefaultValue: @(OpenVPNMinTLSVersionDefault) }; - NSString *currentValue = [NSString stringWithUTF8String:_config.tlsVersionMinOverride.c_str()]; + NSString *currentValue = _config.tlsVersionMinOverride.empty() ? OpenVPNMinTLSVersionDefaultValue : + [NSString stringWithUTF8String:_config.tlsVersionMinOverride.c_str()]; NSNumber *preference = options[currentValue]; - NSAssert(preference != nil, @"Incorrect minTLSVersion value"); + NSAssert(preference != nil, @"Incorrect tlsVersionMinOverride value: %@", currentValue); return (OpenVPNMinTLSVersion)[preference integerValue]; } - (void)setMinTLSVersion:(OpenVPNMinTLSVersion)minTLSVersion { - switch (minTLSVersion) { - case OpenVPNMinTLSVersionDisabled: - _config.tlsVersionMinOverride = "disabled"; - break; - - case OpenVPNMinTLSVersion10: - _config.tlsVersionMinOverride = "tls_1_0"; - break; - - case OpenVPNMinTLSVersion11: - _config.tlsVersionMinOverride = "tls_1_1"; - break; - - case OpenVPNMinTLSVersion12: - _config.tlsVersionMinOverride = "tls_1_2"; - break; - - case OpenVPNMinTLSVersionDefault: - _config.tlsVersionMinOverride = "default"; - break; - - default: - NSAssert(NO, @"Incorrect OpenVPNMinTLSVersion value"); - break; + NSDictionary *options = @{ + @(OpenVPNMinTLSVersionDisabled): OpenVPNMinTLSVersionDisabledValue, + @(OpenVPNMinTLSVersion10): OpenVPNMinTLSVersion10Value, + @(OpenVPNMinTLSVersion11): OpenVPNMinTLSVersion11Value, + @(OpenVPNMinTLSVersion12): OpenVPNMinTLSVersion12Value, + @(OpenVPNMinTLSVersionDefault): OpenVPNMinTLSVersionDefaultValue + }; + + NSString *value = options[@(minTLSVersion)]; + NSAssert(value != nil, @"Incorrect minTLSVersion value: %li", (NSInteger)minTLSVersion); + + _config.tlsVersionMinOverride = [value UTF8String]; +} + +- (OpenVPNTLSCertProfile)tlsCertProfile { + NSDictionary *options = @{ + OpenVPNTLSCertProfileLegacyValue: @(OpenVPNTLSCertProfileLegacy), + OpenVPNTLSCertProfilePreferredValue: @(OpenVPNTLSCertProfilePreferred), + OpenVPNTLSCertProfileSuiteBValue: @(OpenVPNTLSCertProfileSuiteB), + OpenVPNTLSCertProfileLegacyDefaultValue: @(OpenVPNTLSCertProfileLegacyDefault), + OpenVPNTLSCertProfilePreferredDefaultValue: @(OpenVPNTLSCertProfilePreferredDefault), + OpenVPNTLSCertProfileDefaultValue: @(OpenVPNTLSCertProfileDefault), + }; + + NSString *currentValue = _config.tlsCertProfileOverride.empty() ? OpenVPNTLSCertProfileDefaultValue : + [NSString stringWithUTF8String:_config.tlsCertProfileOverride.c_str()]; + + NSNumber *preference = options[currentValue]; + NSAssert(preference != nil, @"Incorrect tlsCertProfileOverride value: %@", currentValue); + + return (OpenVPNTLSCertProfile)[preference integerValue]; +} + +- (void)setTlsCertProfile:(OpenVPNTLSCertProfile)tlsCertProfile { + NSDictionary *options = @{ + @(OpenVPNTLSCertProfileLegacy): OpenVPNTLSCertProfileLegacyValue, + @(OpenVPNTLSCertProfilePreferred): OpenVPNTLSCertProfilePreferredValue, + @(OpenVPNTLSCertProfileSuiteB): OpenVPNTLSCertProfileSuiteBValue, + @(OpenVPNTLSCertProfileLegacyDefault): OpenVPNTLSCertProfileLegacyDefaultValue, + @(OpenVPNTLSCertProfilePreferredDefault): OpenVPNTLSCertProfilePreferredDefaultValue, + @(OpenVPNTLSCertProfileDefault): OpenVPNTLSCertProfileDefaultValue + }; + + NSString *value = options[@(tlsCertProfile)]; + NSAssert(value != nil, @"Incorrect tlsCertProfile value: %li", (NSInteger)tlsCertProfile); + + _config.tlsCertProfileOverride = [value UTF8String]; +} + +- (NSDictionary *)peerInfo { + if (_config.peerInfo.size() == 0) { + return nil; } + + NSMutableDictionary *peerInfo = [NSMutableDictionary new]; + + for (ClientAPI::KeyValue param : _config.peerInfo) { + NSString *key = [NSString stringWithCString:param.key.c_str() encoding:NSUTF8StringEncoding]; + NSString *value = [NSString stringWithCString:param.value.c_str() encoding:NSUTF8StringEncoding]; + + peerInfo[key] = value; + } + + return [peerInfo copy]; +} + +- (void)setPeerInfo:(NSDictionary *)peerInfo { + _config.contentList.clear(); + + if (!peerInfo) { + return; + } + + [peerInfo enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { + ClientAPI::KeyValue param = ClientAPI::KeyValue(std::string([key UTF8String]), std::string([obj UTF8String])); + _config.peerInfo.push_back(param); + }]; } @end