diff --git a/OpenVPN Tunnel Provider/PacketTunnelProvider.swift b/OpenVPN Tunnel Provider/PacketTunnelProvider.swift index 60b585d..ce9b648 100644 --- a/OpenVPN Tunnel Provider/PacketTunnelProvider.swift +++ b/OpenVPN Tunnel Provider/PacketTunnelProvider.swift @@ -7,11 +7,61 @@ // import NetworkExtension +import KeychainAccess + +enum PacketTunnelProviderError: Error { + + case startFailure(message: String) + +} class PacketTunnelProvider: NEPacketTunnelProvider { + let keychain = Keychain(service: "me.ss-abramchuk.openvpn-ios-client", accessGroup: "2TWXCGG7R3.keychain-shared") + + var vpnAdapter: OpenVPNAdapter? + + var startHandler: ((Error?) -> Void)? + var stopHandler: (() -> Void)? + override func startTunnel(options: [String : NSObject]? = nil, completionHandler: @escaping (Error?) -> Void) { - // TODO: Some + guard let settings = options?["Settings"] as? Data else { + let error = PacketTunnelProviderError.startFailure(message: "Failed to retrieve OpenVPN settings from options") + completionHandler(error) + + return + } + + vpnAdapter = OpenVPNAdapter() + vpnAdapter?.delegate = self + + if let username = protocolConfiguration.username { + vpnAdapter?.username = username + } + + if let reference = protocolConfiguration.passwordReference { + do { + guard let password = try keychain.get(ref: reference) else { + throw PacketTunnelProviderError.startFailure(message: "Failed to retrieve password from keychain") + } + + vpnAdapter?.password = password + } catch { + completionHandler(error) + return + } + } + + do { + try vpnAdapter?.configure(using: settings) + } catch { + completionHandler(error) + return + } + + startHandler = completionHandler + + vpnAdapter?.connect() } override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { @@ -19,3 +69,21 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } + +extension PacketTunnelProvider: OpenVPNAdapterDelegate { + + func configureTunnel(settings: NEPacketTunnelNetworkSettings, callback: @escaping (NEPacketTunnelFlow?) -> Void) { + setTunnelNetworkSettings(settings) { (error) in + callback(error == nil ? self.packetFlow : nil) + } + } + + func handle(event: OpenVPNEvent, message: String?) { + + } + + func handle(error: Error) { + + } + +}