Restore and fix former PEM caching PR (#235)
This reverts commit 995009121a
.
* Improve error handling
* Trust intermediate CA
* Update CHANGELOG
This commit is contained in:
parent
e8f7778179
commit
7a85d3cac7
|
@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- Revert to OpenSSL. [#233](https://github.com/passepartoutvpn/tunnelkit/pull/233)
|
- Revert to OpenSSL. [#233](https://github.com/passepartoutvpn/tunnelkit/pull/233)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Restore and fix "Avoid caching PEMs on disk" (roop). [#213](https://github.com/passepartoutvpn/tunnelkit/pull/213)
|
||||||
|
|
||||||
## 4.0.1 (2021-11-18)
|
## 4.0.1 (2021-11-18)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -33,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Avoid caching PEMs on disk (roop). [#213](https://github.com/passepartoutvpn/tunnelkit/pull/213)
|
||||||
- Upgrade OpenSSL to 1.1.1l.
|
- Upgrade OpenSSL to 1.1.1l.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -44,13 +44,17 @@ typedef NS_ENUM(NSInteger, OpenVPNErrorCode) {
|
||||||
OpenVPNErrorCodeCryptoHMAC = 102,
|
OpenVPNErrorCodeCryptoHMAC = 102,
|
||||||
OpenVPNErrorCodeCryptoEncryption = 103,
|
OpenVPNErrorCodeCryptoEncryption = 103,
|
||||||
OpenVPNErrorCodeCryptoAlgorithm = 104,
|
OpenVPNErrorCodeCryptoAlgorithm = 104,
|
||||||
OpenVPNErrorCodeTLSCertificateAuthority = 201,
|
OpenVPNErrorCodeTLSCARead = 201,
|
||||||
OpenVPNErrorCodeTLSHandshake = 202,
|
OpenVPNErrorCodeTLSCAUse = 202,
|
||||||
OpenVPNErrorCodeTLSClientCertificate = 204,
|
OpenVPNErrorCodeTLSCAPeerVerification = 203,
|
||||||
OpenVPNErrorCodeTLSClientKey = 205,
|
OpenVPNErrorCodeTLSClientCertificateRead = 204,
|
||||||
OpenVPNErrorCodeTLSServerCertificate = 206,
|
OpenVPNErrorCodeTLSClientCertificateUse = 205,
|
||||||
OpenVPNErrorCodeTLSServerEKU = 207,
|
OpenVPNErrorCodeTLSClientKeyRead = 206,
|
||||||
OpenVPNErrorCodeTLSServerHost = 208,
|
OpenVPNErrorCodeTLSClientKeyUse = 207,
|
||||||
|
OpenVPNErrorCodeTLSHandshake = 210,
|
||||||
|
OpenVPNErrorCodeTLSServerCertificate = 211,
|
||||||
|
OpenVPNErrorCodeTLSServerEKU = 212,
|
||||||
|
OpenVPNErrorCodeTLSServerHost = 213,
|
||||||
OpenVPNErrorCodeDataPathOverflow = 301,
|
OpenVPNErrorCodeDataPathOverflow = 301,
|
||||||
OpenVPNErrorCodeDataPathPeerIdMismatch = 302,
|
OpenVPNErrorCodeDataPathPeerIdMismatch = 302,
|
||||||
OpenVPNErrorCodeDataPathCompression = 303
|
OpenVPNErrorCodeDataPathCompression = 303
|
||||||
|
|
|
@ -50,7 +50,7 @@ static const char *const TLSBoxServerEKU = "TLS Web Server Authentication";
|
||||||
|
|
||||||
int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
int TLSBoxVerifyPeer(int ok, X509_STORE_CTX *ctx) {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
NSError *error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSCertificateAuthority);
|
NSError *error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSCAPeerVerification);
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:TLSBoxPeerVerificationErrorNotification
|
[[NSNotificationCenter defaultCenter] postNotificationName:TLSBoxPeerVerificationErrorNotification
|
||||||
object:nil
|
object:nil
|
||||||
userInfo:@{OpenVPNErrorKey: error}];
|
userInfo:@{OpenVPNErrorKey: error}];
|
||||||
|
@ -62,9 +62,9 @@ const NSInteger TLSBoxDefaultSecurityLevel = 0;
|
||||||
|
|
||||||
@interface TLSBox ()
|
@interface TLSBox ()
|
||||||
|
|
||||||
@property (nonatomic, strong) NSString *caPath;
|
@property (nonatomic, strong) NSString *caPEM;
|
||||||
@property (nonatomic, strong) NSString *clientCertificatePath;
|
@property (nonatomic, strong) NSString *clientCertificatePEM;
|
||||||
@property (nonatomic, strong) NSString *clientKeyPath;
|
@property (nonatomic, strong) NSString *clientKeyPEM;
|
||||||
@property (nonatomic, assign) BOOL checksEKU;
|
@property (nonatomic, assign) BOOL checksEKU;
|
||||||
@property (nonatomic, assign) BOOL checksSANHost;
|
@property (nonatomic, assign) BOOL checksSANHost;
|
||||||
@property (nonatomic, strong) NSString *hostname;
|
@property (nonatomic, strong) NSString *hostname;
|
||||||
|
@ -80,6 +80,10 @@ const NSInteger TLSBoxDefaultSecurityLevel = 0;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
static BIO *create_BIO_from_PEM(NSString *pem) {
|
||||||
|
return BIO_new_mem_buf([pem cStringUsingEncoding:NSASCIIStringEncoding], (int)[pem length]);
|
||||||
|
}
|
||||||
|
|
||||||
@implementation TLSBox
|
@implementation TLSBox
|
||||||
|
|
||||||
+ (NSString *)md5ForCertificatePath:(NSString *)path error:(NSError * _Nullable __autoreleasing * _Nullable)error
|
+ (NSString *)md5ForCertificatePath:(NSString *)path error:(NSError * _Nullable __autoreleasing * _Nullable)error
|
||||||
|
@ -109,6 +113,33 @@ const NSInteger TLSBoxDefaultSecurityLevel = 0;
|
||||||
return hex;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSString *)md5ForCertificatePEM:(NSString *)pem error:(NSError * _Nullable __autoreleasing * _Nullable)error
|
||||||
|
{
|
||||||
|
const EVP_MD *alg = EVP_get_digestbyname("MD5");
|
||||||
|
uint8_t md[16];
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
BIO *bio = create_BIO_from_PEM(pem);
|
||||||
|
if (!bio) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
X509 *cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||||
|
if (!cert) {
|
||||||
|
BIO_free(bio);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
X509_digest(cert, alg, md, &len);
|
||||||
|
X509_free(cert);
|
||||||
|
BIO_free(bio);
|
||||||
|
NSCAssert2(len == sizeof(md), @"Unexpected MD5 size (%d != %lu)", len, sizeof(md));
|
||||||
|
|
||||||
|
NSMutableString *hex = [[NSMutableString alloc] initWithCapacity:2 * sizeof(md)];
|
||||||
|
for (int i = 0; i < sizeof(md); ++i) {
|
||||||
|
[hex appendFormat:@"%02x", md[i]];
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSString *)decryptedPrivateKeyFromPath:(NSString *)path passphrase:(NSString *)passphrase error:(NSError * _Nullable __autoreleasing *)error
|
+ (NSString *)decryptedPrivateKeyFromPath:(NSString *)path passphrase:(NSString *)passphrase error:(NSError * _Nullable __autoreleasing *)error
|
||||||
{
|
{
|
||||||
BIO *bio;
|
BIO *bio;
|
||||||
|
@ -169,17 +200,17 @@ const NSInteger TLSBoxDefaultSecurityLevel = 0;
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithCAPath:(NSString *)caPath
|
- (instancetype)initWithCA:(nonnull NSString *)caPEM
|
||||||
clientCertificatePath:(NSString *)clientCertificatePath
|
clientCertificate:(nullable NSString *)clientCertificatePEM
|
||||||
clientKeyPath:(NSString *)clientKeyPath
|
clientKey:(nullable NSString *)clientKeyPEM
|
||||||
checksEKU:(BOOL)checksEKU
|
checksEKU:(BOOL)checksEKU
|
||||||
checksSANHost:(BOOL)checksSANHost
|
checksSANHost:(BOOL)checksSANHost
|
||||||
hostname:(nullable NSString *)hostname
|
hostname:(nullable NSString *)hostname
|
||||||
{
|
{
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
self.caPath = caPath;
|
self.caPEM = caPEM;
|
||||||
self.clientCertificatePath = clientCertificatePath;
|
self.clientCertificatePEM = clientCertificatePEM;
|
||||||
self.clientKeyPath = clientKeyPath;
|
self.clientKeyPEM = clientKeyPEM;
|
||||||
self.checksEKU = checksEKU;
|
self.checksEKU = checksEKU;
|
||||||
self.checksSANHost = checksSANHost;
|
self.checksSANHost = checksSANHost;
|
||||||
self.bufferCipherText = allocate_safely(TLSBoxMaxBufferLength);
|
self.bufferCipherText = allocate_safely(TLSBoxMaxBufferLength);
|
||||||
|
@ -214,31 +245,89 @@ const NSInteger TLSBoxDefaultSecurityLevel = 0;
|
||||||
SSL_CTX_set_security_level(self.ctx, (int)self.securityLevel);
|
SSL_CTX_set_security_level(self.ctx, (int)self.securityLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SSL_CTX_load_verify_locations(self.ctx, [self.caPath cStringUsingEncoding:NSASCIIStringEncoding], NULL)) {
|
if (self.caPEM) {
|
||||||
ERR_print_errors_fp(stdout);
|
BIO *bio = create_BIO_from_PEM(self.caPEM);
|
||||||
|
if (!bio) {
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSCertificateAuthority);
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSCARead);
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
X509 *ca = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
|
||||||
|
if (!ca) {
|
||||||
|
if (error) {
|
||||||
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSCARead);
|
||||||
|
}
|
||||||
|
BIO_free(bio);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
BIO_free(bio);
|
||||||
|
X509_STORE *trustedStore = SSL_CTX_get_cert_store(self.ctx);
|
||||||
|
X509_STORE_set_flags(trustedStore, X509_V_FLAG_PARTIAL_CHAIN);
|
||||||
|
if (!X509_STORE_add_cert(trustedStore, ca)) {
|
||||||
|
ERR_print_errors_fp(stdout);
|
||||||
|
if (error) {
|
||||||
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSCAUse);
|
||||||
|
}
|
||||||
|
X509_free(ca);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
X509_free(ca);
|
||||||
|
}
|
||||||
|
|
||||||
if (self.clientCertificatePath) {
|
if (self.clientCertificatePEM) {
|
||||||
if (!SSL_CTX_use_certificate_file(self.ctx, [self.clientCertificatePath cStringUsingEncoding:NSASCIIStringEncoding], SSL_FILETYPE_PEM)) {
|
BIO *bio = create_BIO_from_PEM(self.clientCertificatePEM);
|
||||||
ERR_print_errors_fp(stdout);
|
if (!bio) {
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSClientCertificate);
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSClientCertificateRead);
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
X509 *cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||||
|
if (!cert) {
|
||||||
|
if (error) {
|
||||||
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSClientCertificateRead);
|
||||||
|
}
|
||||||
|
BIO_free(bio);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
BIO_free(bio);
|
||||||
|
if (!SSL_CTX_use_certificate(self.ctx, cert)) {
|
||||||
|
ERR_print_errors_fp(stdout);
|
||||||
|
if (error) {
|
||||||
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSClientCertificateUse);
|
||||||
|
}
|
||||||
|
X509_free(cert);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
X509_free(cert);
|
||||||
|
|
||||||
if (self.clientKeyPath) {
|
if (self.clientKeyPEM) {
|
||||||
if (!SSL_CTX_use_PrivateKey_file(self.ctx, [self.clientKeyPath cStringUsingEncoding:NSASCIIStringEncoding], SSL_FILETYPE_PEM)) {
|
BIO *bio = create_BIO_from_PEM(self.clientKeyPEM);
|
||||||
ERR_print_errors_fp(stdout);
|
if (!bio) {
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSClientKey);
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSClientKeyRead);
|
||||||
}
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
||||||
|
if (!pkey) {
|
||||||
|
if (error) {
|
||||||
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSClientKeyRead);
|
||||||
|
}
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
BIO_free(bio);
|
||||||
|
if (!SSL_CTX_use_PrivateKey(self.ctx, pkey)) {
|
||||||
|
ERR_print_errors_fp(stdout);
|
||||||
|
if (error) {
|
||||||
|
*error = OpenVPNErrorWithCode(OpenVPNErrorCodeTLSClientKeyUse);
|
||||||
|
}
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,12 +55,13 @@ extern const NSInteger TLSBoxDefaultSecurityLevel;
|
||||||
@property (nonatomic, assign) NSInteger securityLevel; // TLSBoxDefaultSecurityLevel for default
|
@property (nonatomic, assign) NSInteger securityLevel; // TLSBoxDefaultSecurityLevel for default
|
||||||
|
|
||||||
+ (nullable NSString *)md5ForCertificatePath:(NSString *)path error:(NSError **)error;
|
+ (nullable NSString *)md5ForCertificatePath:(NSString *)path error:(NSError **)error;
|
||||||
|
+ (nullable NSString *)md5ForCertificatePEM:(NSString *)pem error:(NSError **)error;
|
||||||
+ (nullable NSString *)decryptedPrivateKeyFromPath:(NSString *)path passphrase:(NSString *)passphrase error:(NSError **)error;
|
+ (nullable NSString *)decryptedPrivateKeyFromPath:(NSString *)path passphrase:(NSString *)passphrase error:(NSError **)error;
|
||||||
+ (nullable NSString *)decryptedPrivateKeyFromPEM:(NSString *)pem passphrase:(NSString *)passphrase error:(NSError **)error;
|
+ (nullable NSString *)decryptedPrivateKeyFromPEM:(NSString *)pem passphrase:(NSString *)passphrase error:(NSError **)error;
|
||||||
|
|
||||||
- (instancetype)initWithCAPath:(NSString *)caPath
|
- (instancetype)initWithCA:(nonnull NSString *)caPEM
|
||||||
clientCertificatePath:(nullable NSString *)clientCertificatePath
|
clientCertificate:(nullable NSString *)clientCertificatePEM
|
||||||
clientKeyPath:(nullable NSString *)clientKeyPath
|
clientKey:(nullable NSString *)clientKeyPEM
|
||||||
checksEKU:(BOOL)checksEKU
|
checksEKU:(BOOL)checksEKU
|
||||||
checksSANHost:(BOOL)checksSANHost
|
checksSANHost:(BOOL)checksSANHost
|
||||||
hostname:(nullable NSString *)hostname;
|
hostname:(nullable NSString *)hostname;
|
||||||
|
|
|
@ -241,7 +241,7 @@ open class OpenVPNTunnelProvider: NEPacketTunnelProvider {
|
||||||
|
|
||||||
let session: OpenVPNSession
|
let session: OpenVPNSession
|
||||||
do {
|
do {
|
||||||
session = try OpenVPNSession(queue: tunnelQueue, configuration: cfg.sessionConfiguration, cachesURL: cachesURL)
|
session = try OpenVPNSession(queue: tunnelQueue, configuration: cfg.sessionConfiguration)
|
||||||
refreshDataCount()
|
refreshDataCount()
|
||||||
} catch let e {
|
} catch let e {
|
||||||
completionHandler(e)
|
completionHandler(e)
|
||||||
|
@ -903,7 +903,9 @@ extension OpenVPNTunnelProvider {
|
||||||
case .cryptoEncryption, .cryptoHMAC:
|
case .cryptoEncryption, .cryptoHMAC:
|
||||||
return .encryptionData
|
return .encryptionData
|
||||||
|
|
||||||
case .tlsCertificateAuthority, .tlsClientCertificate, .tlsClientKey:
|
case .tlscaRead, .tlscaUse, .tlscaPeerVerification,
|
||||||
|
.tlsClientCertificateRead, .tlsClientCertificateUse,
|
||||||
|
.tlsClientKeyRead, .tlsClientKeyUse:
|
||||||
return .tlsInitialization
|
return .tlsInitialization
|
||||||
|
|
||||||
case .tlsServerCertificate, .tlsServerEKU, .tlsServerHost:
|
case .tlsServerCertificate, .tlsServerEKU, .tlsServerHost:
|
||||||
|
|
|
@ -72,14 +72,6 @@ public class OpenVPNSession: Session {
|
||||||
case reconnect
|
case reconnect
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct Caches {
|
|
||||||
static let ca = "ca.pem"
|
|
||||||
|
|
||||||
static let clientCertificate = "cert.pem"
|
|
||||||
|
|
||||||
static let clientKey = "key.pem"
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Configuration
|
// MARK: Configuration
|
||||||
|
|
||||||
/// The session base configuration.
|
/// The session base configuration.
|
||||||
|
@ -174,22 +166,6 @@ public class OpenVPNSession: Session {
|
||||||
|
|
||||||
private var authenticator: OpenVPN.Authenticator?
|
private var authenticator: OpenVPN.Authenticator?
|
||||||
|
|
||||||
// MARK: Caching
|
|
||||||
|
|
||||||
private let cachesURL: URL
|
|
||||||
|
|
||||||
private var caURL: URL {
|
|
||||||
return cachesURL.appendingPathComponent(Caches.ca)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var clientCertificateURL: URL {
|
|
||||||
return cachesURL.appendingPathComponent(Caches.clientCertificate)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var clientKeyURL: URL {
|
|
||||||
return cachesURL.appendingPathComponent(Caches.clientKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Init
|
// MARK: Init
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,14 +174,13 @@ public class OpenVPNSession: Session {
|
||||||
- Parameter queue: The `DispatchQueue` where to run the session loop.
|
- Parameter queue: The `DispatchQueue` where to run the session loop.
|
||||||
- Parameter configuration: The `Configuration` to use for this session.
|
- Parameter configuration: The `Configuration` to use for this session.
|
||||||
*/
|
*/
|
||||||
public init(queue: DispatchQueue, configuration: OpenVPN.Configuration, cachesURL: URL) throws {
|
public init(queue: DispatchQueue, configuration: OpenVPN.Configuration) throws {
|
||||||
guard let ca = configuration.ca else {
|
guard let _ = configuration.ca else {
|
||||||
throw ConfigurationError.missingConfiguration(option: "ca")
|
throw ConfigurationError.missingConfiguration(option: "ca")
|
||||||
}
|
}
|
||||||
|
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.cachesURL = cachesURL
|
|
||||||
|
|
||||||
withLocalOptions = true
|
withLocalOptions = true
|
||||||
keys = [:]
|
keys = [:]
|
||||||
|
@ -226,25 +201,10 @@ public class OpenVPNSession: Session {
|
||||||
} else {
|
} else {
|
||||||
controlChannel = OpenVPN.ControlChannel()
|
controlChannel = OpenVPN.ControlChannel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache PEMs locally (mandatory for OpenSSL)
|
|
||||||
let fm = FileManager.default
|
|
||||||
try ca.pem.write(to: caURL, atomically: true, encoding: .ascii)
|
|
||||||
if let container = configuration.clientCertificate {
|
|
||||||
try container.pem.write(to: clientCertificateURL, atomically: true, encoding: .ascii)
|
|
||||||
} else {
|
|
||||||
try? fm.removeItem(at: clientCertificateURL)
|
|
||||||
}
|
|
||||||
if let container = configuration.clientKey {
|
|
||||||
try container.pem.write(to: clientKeyURL, atomically: true, encoding: .ascii)
|
|
||||||
} else {
|
|
||||||
try? fm.removeItem(at: clientKeyURL)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
cleanup()
|
cleanup()
|
||||||
cleanupCache()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Session
|
// MARK: Session
|
||||||
|
@ -355,13 +315,6 @@ public class OpenVPNSession: Session {
|
||||||
stopError = nil
|
stopError = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanupCache() {
|
|
||||||
let fm = FileManager.default
|
|
||||||
for url in [caURL, clientCertificateURL, clientKeyURL] {
|
|
||||||
try? fm.removeItem(at: url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Loop
|
// MARK: Loop
|
||||||
|
|
||||||
// Ruby: start
|
// Ruby: start
|
||||||
|
@ -623,9 +576,13 @@ public class OpenVPNSession: Session {
|
||||||
|
|
||||||
private func hardResetPayload() -> Data? {
|
private func hardResetPayload() -> Data? {
|
||||||
guard !(configuration.usesPIAPatches ?? false) else {
|
guard !(configuration.usesPIAPatches ?? false) else {
|
||||||
|
guard let ca = configuration.ca else {
|
||||||
|
log.error("Configuration doesn't have a CA")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
let caMD5: String
|
let caMD5: String
|
||||||
do {
|
do {
|
||||||
caMD5 = try TLSBox.md5(forCertificatePath: caURL.path)
|
caMD5 = try TLSBox.md5(forCertificatePEM: ca.pem)
|
||||||
} catch {
|
} catch {
|
||||||
log.error("CA MD5 could not be computed, skipping custom HARD_RESET")
|
log.error("CA MD5 could not be computed, skipping custom HARD_RESET")
|
||||||
return nil
|
return nil
|
||||||
|
@ -766,6 +723,11 @@ public class OpenVPNSession: Session {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guard let ca = configuration.ca else {
|
||||||
|
log.error("Configuration doesn't have a CA")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// start new TLS handshake
|
// start new TLS handshake
|
||||||
if ((packet.code == .hardResetServerV2) && (negotiationKey.state == .hardReset)) ||
|
if ((packet.code == .hardResetServerV2) && (negotiationKey.state == .hardReset)) ||
|
||||||
((packet.code == .softResetV1) && (negotiationKey.state == .softReset)) {
|
((packet.code == .softResetV1) && (negotiationKey.state == .softReset)) {
|
||||||
|
@ -789,9 +751,9 @@ public class OpenVPNSession: Session {
|
||||||
log.debug("Start TLS handshake")
|
log.debug("Start TLS handshake")
|
||||||
|
|
||||||
let tls = TLSBox(
|
let tls = TLSBox(
|
||||||
caPath: caURL.path,
|
ca: ca.pem,
|
||||||
clientCertificatePath: (configuration.clientCertificate != nil) ? clientCertificateURL.path : nil,
|
clientCertificate: configuration.clientCertificate?.pem,
|
||||||
clientKeyPath: (configuration.clientKey != nil) ? clientKeyURL.path : nil,
|
clientKey: configuration.clientKey?.pem,
|
||||||
checksEKU: configuration.checksEKU ?? false,
|
checksEKU: configuration.checksEKU ?? false,
|
||||||
checksSANHost: configuration.checksSANHost ?? false,
|
checksSANHost: configuration.checksSANHost ?? false,
|
||||||
hostname: configuration.sanHost
|
hostname: configuration.sanHost
|
||||||
|
@ -1253,7 +1215,6 @@ public class OpenVPNSession: Session {
|
||||||
switch method {
|
switch method {
|
||||||
case .shutdown:
|
case .shutdown:
|
||||||
self?.doShutdown(error: error)
|
self?.doShutdown(error: error)
|
||||||
self?.cleanupCache()
|
|
||||||
|
|
||||||
case .reconnect:
|
case .reconnect:
|
||||||
self?.doReconnect(error: error)
|
self?.doReconnect(error: error)
|
||||||
|
|
|
@ -118,6 +118,11 @@ class EncryptionTests: XCTestCase {
|
||||||
let exp = "e2fccccaba712ccc68449b1c56427ac1"
|
let exp = "e2fccccaba712ccc68449b1c56427ac1"
|
||||||
print(md5)
|
print(md5)
|
||||||
XCTAssertEqual(md5, exp)
|
XCTAssertEqual(md5, exp)
|
||||||
|
|
||||||
|
let pem = try! String(contentsOfFile: path, encoding: .ascii)
|
||||||
|
let md5FromPEM = try! TLSBox.md5(forCertificatePEM: pem)
|
||||||
|
print(md5FromPEM)
|
||||||
|
XCTAssertEqual(md5FromPEM, exp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPrivateKeyDecryption() {
|
func testPrivateKeyDecryption() {
|
||||||
|
|
Loading…
Reference in New Issue