diff --git a/CHANGELOG.md b/CHANGELOG.md
index 61187dc..242a3ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Override DNS servers client side. [#56](https://github.com/keeshux/tunnelkit/pull/56)
+### Changed
+
+- Enable or disable EKU according to `remote-cert-tls server` in .ovpn file. [#64](https://github.com/keeshux/tunnelkit/pull/64)
+
### Fixed
- Compiling errors in demo target.
diff --git a/TunnelKit.xcodeproj/project.pbxproj b/TunnelKit.xcodeproj/project.pbxproj
index 3e899ef..5c16040 100644
--- a/TunnelKit.xcodeproj/project.pbxproj
+++ b/TunnelKit.xcodeproj/project.pbxproj
@@ -1348,7 +1348,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 309;
+ CURRENT_PROJECT_VERSION = 329;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -1412,7 +1412,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 309;
+ CURRENT_PROJECT_VERSION = 329;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -1445,7 +1445,7 @@
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 309;
+ DYLIB_CURRENT_VERSION = 329;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-iOS/Info.plist";
@@ -1468,7 +1468,7 @@
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 309;
+ DYLIB_CURRENT_VERSION = 329;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-iOS/Info.plist";
@@ -1491,7 +1491,7 @@
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 309;
+ DYLIB_CURRENT_VERSION = 329;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-macOS/Info.plist";
@@ -1514,7 +1514,7 @@
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
- DYLIB_CURRENT_VERSION = 309;
+ DYLIB_CURRENT_VERSION = 329;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "$(SRCROOT)/TunnelKit-macOS/Info.plist";
diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift
index f253fc2..83c489f 100644
--- a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift
+++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift
@@ -60,6 +60,7 @@ extension TunnelKitProvider {
ca: CryptoContainer(pem: ""),
clientCertificate: nil,
clientKey: nil,
+ checksEKU: false,
compressionFraming: .disabled,
tlsWrap: nil,
keepAliveInterval: nil,
@@ -465,6 +466,11 @@ extension TunnelKitProvider {
} else {
log.info("\tClient verification: disabled")
}
+ if sessionConfiguration.checksEKU ?? false {
+ log.info("\tServer EKU verification: enabled")
+ } else {
+ log.info("\tServer EKU verification: disabled")
+ }
log.info("\tMTU: \(mtu)")
log.info("\tCompression framing: \(sessionConfiguration.compressionFraming)")
if let keepAliveSeconds = sessionConfiguration.keepAliveInterval, keepAliveSeconds > 0 {
diff --git a/TunnelKit/Sources/Core/ConfigurationParser.swift b/TunnelKit/Sources/Core/ConfigurationParser.swift
index d3eee1b..c80665a 100644
--- a/TunnelKit/Sources/Core/ConfigurationParser.swift
+++ b/TunnelKit/Sources/Core/ConfigurationParser.swift
@@ -87,11 +87,13 @@ public class ConfigurationParser {
static let keyDirection = NSRegularExpression("^key-direction +\\d")
+ static let eku = NSRegularExpression("^remote-cert-tls +server")
+
static let blockBegin = NSRegularExpression("^<[\\w\\-]+>")
static let blockEnd = NSRegularExpression("^<\\/[\\w\\-]+>")
- static let dnsRegexp = NSRegularExpression("dhcp-option DNS6? [\\d\\.a-fA-F:]+")
+ static let dns = NSRegularExpression("^dhcp-option +DNS6? +[\\d\\.a-fA-F:]+")
// unsupported
@@ -139,6 +141,7 @@ public class ConfigurationParser {
var optCA: CryptoContainer?
var clientCertificate: CryptoContainer?
var clientKey: CryptoContainer?
+ var checksEKU = false
var keepAliveSeconds: TimeInterval?
var renegotiateAfterSeconds: TimeInterval?
var keyDirection: StaticKey.Direction?
@@ -218,6 +221,9 @@ public class ConfigurationParser {
continue
}
+ Regex.eku.enumerateComponents(in: line) { (_) in
+ checksEKU = true
+ }
Regex.proto.enumerateArguments(in: line) {
isHandled = true
guard let str = $0.first else {
@@ -319,7 +325,7 @@ public class ConfigurationParser {
}
renegotiateAfterSeconds = TimeInterval(arg)
}
- Regex.dnsRegexp.enumerateArguments(in: line) {
+ Regex.dns.enumerateArguments(in: line) {
isHandled = true
guard $0.count == 2 else {
return
@@ -399,6 +405,7 @@ public class ConfigurationParser {
sessionBuilder.tlsWrap = tlsWrap
sessionBuilder.clientCertificate = clientCertificate
sessionBuilder.clientKey = clientKey
+ sessionBuilder.checksEKU = checksEKU
sessionBuilder.keepAliveInterval = keepAliveSeconds
sessionBuilder.renegotiatesAfter = renegotiateAfterSeconds
sessionBuilder.dnsServers = dnsServers
diff --git a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift
index 9bcd700..742c317 100644
--- a/TunnelKit/Sources/Core/SessionProxy+Configuration.swift
+++ b/TunnelKit/Sources/Core/SessionProxy+Configuration.swift
@@ -150,6 +150,9 @@ extension SessionProxy {
/// The private key for the certificate in `clientCertificate` (PEM format).
public var clientKey: CryptoContainer?
+ /// If true, checks EKU of server certificate.
+ public var checksEKU: Bool?
+
/// Sets compression framing, disabled by default.
public var compressionFraming: CompressionFraming
@@ -175,6 +178,7 @@ extension SessionProxy {
self.ca = ca
clientCertificate = nil
clientKey = nil
+ checksEKU = false
compressionFraming = .disabled
tlsWrap = nil
keepAliveInterval = nil
@@ -195,6 +199,7 @@ extension SessionProxy {
ca: ca,
clientCertificate: clientCertificate,
clientKey: clientKey,
+ checksEKU: checksEKU,
compressionFraming: compressionFraming,
tlsWrap: tlsWrap,
keepAliveInterval: keepAliveInterval,
@@ -223,6 +228,9 @@ extension SessionProxy {
/// - Seealso: `SessionProxy.ConfigurationBuilder.clientKey`
public let clientKey: CryptoContainer?
+ /// - Seealso: `SessionProxy.ConfigurationBuilder.checksEKU`
+ public let checksEKU: Bool?
+
/// - Seealso: `SessionProxy.ConfigurationBuilder.compressionFraming`
public let compressionFraming: CompressionFraming
@@ -252,6 +260,7 @@ extension SessionProxy {
builder.digest = digest
builder.clientCertificate = clientCertificate
builder.clientKey = clientKey
+ builder.checksEKU = checksEKU
builder.compressionFraming = compressionFraming
builder.tlsWrap = tlsWrap
builder.keepAliveInterval = keepAliveInterval
@@ -271,6 +280,7 @@ extension SessionProxy {
(lhs.ca == rhs.ca) &&
(lhs.clientCertificate == rhs.clientCertificate) &&
(lhs.clientKey == rhs.clientKey) &&
+ (lhs.checksEKU == rhs.checksEKU) &&
(lhs.compressionFraming == rhs.compressionFraming) &&
(lhs.keepAliveInterval == rhs.keepAliveInterval) &&
(lhs.renegotiatesAfter == rhs.renegotiatesAfter) &&
diff --git a/TunnelKit/Sources/Core/SessionProxy.swift b/TunnelKit/Sources/Core/SessionProxy.swift
index e045c68..3a45bf3 100644
--- a/TunnelKit/Sources/Core/SessionProxy.swift
+++ b/TunnelKit/Sources/Core/SessionProxy.swift
@@ -771,7 +771,8 @@ public class SessionProxy {
negotiationKey.tlsOptional = TLSBox(
caPath: caURL.path,
clientCertificatePath: (configuration.clientCertificate != nil) ? clientCertificateURL.path : nil,
- clientKeyPath: (configuration.clientKey != nil) ? clientKeyURL.path : nil
+ clientKeyPath: (configuration.clientKey != nil) ? clientKeyURL.path : nil,
+ checksEKU: true
)
do {
try negotiationKey.tls.start()
diff --git a/TunnelKit/Sources/Core/TLSBox.h b/TunnelKit/Sources/Core/TLSBox.h
index 76e6d54..16194f5 100644
--- a/TunnelKit/Sources/Core/TLSBox.h
+++ b/TunnelKit/Sources/Core/TLSBox.h
@@ -55,7 +55,8 @@ extern NSString *const TLSBoxPeerVerificationErrorNotification;
- (instancetype)initWithCAPath:(NSString *)caPath
clientCertificatePath:(nullable NSString *)clientCertificatePath
- clientKeyPath:(nullable NSString *)clientKeyPath;
+ clientKeyPath:(nullable NSString *)clientKeyPath
+ checksEKU:(BOOL)checksEKU;
- (BOOL)startWithError:(NSError **)error;
diff --git a/TunnelKit/Sources/Core/TLSBox.m b/TunnelKit/Sources/Core/TLSBox.m
index 65f9a78..6a7a532 100644
--- a/TunnelKit/Sources/Core/TLSBox.m
+++ b/TunnelKit/Sources/Core/TLSBox.m
@@ -65,6 +65,7 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
@property (nonatomic, strong) NSString *caPath;
@property (nonatomic, strong) NSString *clientCertificatePath;
@property (nonatomic, strong) NSString *clientKeyPath;
+@property (nonatomic, assign) BOOL checksEKU;
@property (nonatomic, assign) BOOL isConnected;
@property (nonatomic, unsafe_unretained) SSL_CTX *ctx;
@@ -105,12 +106,16 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
return nil;
}
-- (instancetype)initWithCAPath:(NSString *)caPath clientCertificatePath:(NSString *)clientCertificatePath clientKeyPath:(NSString *)clientKeyPath
+- (instancetype)initWithCAPath:(NSString *)caPath
+ clientCertificatePath:(NSString *)clientCertificatePath
+ clientKeyPath:(NSString *)clientKeyPath
+ checksEKU:(BOOL)checksEKU
{
if ((self = [super init])) {
self.caPath = caPath;
self.clientCertificatePath = clientCertificatePath;
self.clientKeyPath = clientKeyPath;
+ self.checksEKU = checksEKU;
self.bufferCipherText = allocate_safely(TLSBoxMaxBufferLength);
}
return self;
@@ -196,7 +201,7 @@ int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
if (!self.isConnected && SSL_is_init_finished(self.ssl)) {
self.isConnected = YES;
- if (![self verifyEKUWithSSL:self.ssl]) {
+ if (self.checksEKU && ![self verifyEKUWithSSL:self.ssl]) {
if (error) {
*error = TunnelKitErrorWithCode(TunnelKitErrorCodeTLSBoxServerEKU);
}
diff --git a/TunnelKitHost/Info.plist b/TunnelKitHost/Info.plist
index cf71a3c..312dc08 100644
--- a/TunnelKitHost/Info.plist
+++ b/TunnelKitHost/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 1.4.0
+ 1.4.1
CFBundleVersion
1
LSRequiresIPhoneOS
diff --git a/TunnelKitTests-iOS/Info.plist b/TunnelKitTests-iOS/Info.plist
index 2e93959..9b7344f 100644
--- a/TunnelKitTests-iOS/Info.plist
+++ b/TunnelKitTests-iOS/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 1.4.0
+ 1.4.1
CFBundleVersion
1
diff --git a/TunnelKitTests-macOS/Info.plist b/TunnelKitTests-macOS/Info.plist
index 2e93959..9b7344f 100644
--- a/TunnelKitTests-macOS/Info.plist
+++ b/TunnelKitTests-macOS/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
BNDL
CFBundleShortVersionString
- 1.4.0
+ 1.4.1
CFBundleVersion
1