Take a cache URL in SessionProxy to store PEMs

This commit is contained in:
Davide De Rosa 2018-10-25 08:18:31 +02:00
parent 3fd0329736
commit 197d29042c
2 changed files with 57 additions and 51 deletions

View File

@ -83,13 +83,15 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
private let prngSeedLength = 64
private var cachesURL: URL {
return URL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0])
guard let appGroup = appGroup else {
fatalError("Accessing cachesURL before parsing app group")
}
guard let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) else {
fatalError("No access to app group: \(appGroup)")
}
return containerURL.appendingPathComponent("Library/Caches/")
}
private func temporaryURL(forKey key: String) -> URL {
return cachesURL.appendingPathComponent("\(key).pem")
}
// MARK: Tunnel configuration
private var appGroup: String!
@ -181,42 +183,6 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
completionHandler(ProviderConfigurationError.prngInitialization)
return
}
// let caPath: String
// let clientCertificatePath: String?
// let clientKeyPath: String?
// do {
// let url = temporaryURL(forKey: Configuration.Keys.ca)
// try cfg.ca.write(to: url)
// caPath = url.path
// } catch {
// completionHandler(ProviderConfigurationError.certificateSerialization)
// return
// }
// if let clientCertificate = cfg.clientCertificate {
// do {
// let url = temporaryURL(forKey: Configuration.Keys.clientCertificate)
// try clientCertificate.write(to: url)
// clientCertificatePath = url.path
// } catch {
// completionHandler(ProviderConfigurationError.certificateSerialization)
// return
// }
// } else {
// clientCertificatePath = nil
// }
// if let clientKey = cfg.clientKey {
// do {
// let url = temporaryURL(forKey: Configuration.Keys.clientKey)
// try clientKey.write(to: url)
// clientKeyPath = url.path
// } catch {
// completionHandler(ProviderConfigurationError.certificateSerialization)
// return
// }
// } else {
// clientKeyPath = nil
// }
cfg.print(appVersion: appVersion)
@ -239,7 +205,7 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
let proxy: SessionProxy
do {
proxy = try SessionProxy(queue: tunnelQueue, configuration: sessionConfiguration.build())
proxy = try SessionProxy(queue: tunnelQueue, configuration: sessionConfiguration.build(), cachesURL: cachesURL)
} catch let e {
completionHandler(e)
return
@ -382,10 +348,6 @@ open class TunnelKitProvider: NEPacketTunnelProvider {
}
// stopped externally, unrecoverable
else {
let fm = FileManager.default
for key in [Configuration.Keys.ca, Configuration.Keys.clientCertificate, Configuration.Keys.clientKey] {
try? fm.removeItem(at: temporaryURL(forKey: key))
}
cancelTunnelWithError(error)
}
}

View File

@ -69,6 +69,14 @@ public class SessionProxy {
case reconnect
}
private struct Caches {
static let ca = "ca.pem"
static let clientCertificate = "cert.pem"
static let clientKey = "key.pem"
}
// MARK: Configuration
private let configuration: Configuration
@ -143,6 +151,22 @@ public class SessionProxy {
private var authenticator: 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
/**
@ -151,9 +175,10 @@ public class SessionProxy {
- Parameter queue: The `DispatchQueue` where to run the session loop.
- Parameter configuration: The `SessionProxy.Configuration` to use for this session.
*/
public init(queue: DispatchQueue, configuration: Configuration) throws {
public init(queue: DispatchQueue, configuration: Configuration, cachesURL: URL) throws {
self.queue = queue
self.configuration = configuration
self.cachesURL = cachesURL
keys = [:]
oldKeys = []
@ -172,10 +197,29 @@ public class SessionProxy {
} else {
controlChannel = ControlChannel()
}
// cache PEMs locally (mandatory for OpenSSL)
let fm = FileManager.default
try configuration.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 {
cleanup()
let fm = FileManager.default
for url in [caURL, clientCertificateURL, clientKeyURL] {
try? fm.removeItem(at: url)
}
}
// MARK: Public interface
@ -566,7 +610,7 @@ public class SessionProxy {
private func hardResetPayload() -> Data? {
guard !configuration.usesPIAPatches else {
let caMD5 = TLSBox.md5(forCertificatePath: configuration.caPath)
let caMD5 = TLSBox.md5(forCertificatePath: caURL.path)
log.debug("CA MD5 is: \(caMD5)")
return try? PIAHardReset(
caMd5Digest: caMD5,
@ -722,9 +766,9 @@ public class SessionProxy {
log.debug("Start TLS handshake")
negotiationKey.tlsOptional = TLSBox(
caPath: configuration.caPath,
clientCertificatePath: configuration.clientCertificatePath,
clientKeyPath: configuration.clientKeyPath
caPath: caURL.path,
clientCertificatePath: (configuration.clientCertificate != nil) ? clientCertificateURL.path : nil,
clientKeyPath: (configuration.clientKey != nil) ? clientKeyURL.path : nil
)
do {
try negotiationKey.tls.start()