mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
OpenVPN Adapter now can be compiled for both macOS and iOS
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>OpenVPN iOS Tunnel Provider</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.networkextension.packet-tunnel</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// KeychainAccess+Reference.swift
|
||||
// OpenVPN iOS Client
|
||||
//
|
||||
// Created by Sergey Abramchuk on 07.03.17.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import KeychainAccess
|
||||
|
||||
extension Keychain {
|
||||
|
||||
public func get(ref: Data) throws -> String? {
|
||||
guard let data = try getData(ref: ref) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return String(data: data, encoding: .utf8)
|
||||
}
|
||||
|
||||
public func getData(ref: Data) throws -> Data? {
|
||||
let query: [String: Any] = [
|
||||
String(kSecClass): itemClass.rawValue,
|
||||
String(kSecReturnData): kCFBooleanTrue,
|
||||
String(kSecValuePersistentRef): ref as CFData
|
||||
]
|
||||
|
||||
var result: AnyObject?
|
||||
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
||||
|
||||
switch status {
|
||||
case errSecSuccess:
|
||||
guard let data = result as? Data else {
|
||||
throw Status.unexpectedError
|
||||
}
|
||||
return data
|
||||
case errSecItemNotFound:
|
||||
return nil
|
||||
default:
|
||||
throw Status(status: status)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// NEPacketTunnelFlow+OpenVPN.swift
|
||||
// OpenVPN iOS Client
|
||||
//
|
||||
// Created by Sergey Abramchuk on 09.03.17.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import NetworkExtension
|
||||
import OpenVPNAdapter
|
||||
|
||||
extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow { }
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.me.ss-abramchuk.openvpn-ios-client</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// PacketTunnelProvider.swift
|
||||
// OpenVPN Tunnel Provider
|
||||
//
|
||||
// Created by Sergey Abramchuk on 05.02.17.
|
||||
//
|
||||
//
|
||||
|
||||
import NetworkExtension
|
||||
import KeychainAccess
|
||||
import OpenVPNAdapter
|
||||
|
||||
enum PacketTunnelProviderError: Error {
|
||||
case fatalError(message: String)
|
||||
}
|
||||
|
||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
|
||||
let keychain = Keychain(service: "me.ss-abramchuk.openvpn-ios-client", accessGroup: "2TWXCGG7R3.keychain-shared")
|
||||
|
||||
lazy var vpnAdapter: OpenVPNAdapter = {
|
||||
return OpenVPNAdapter().then { $0.delegate = self }
|
||||
}()
|
||||
|
||||
var startHandler: ((Error?) -> Void)?
|
||||
var stopHandler: (() -> Void)?
|
||||
|
||||
override func startTunnel(options: [String : NSObject]? = nil, completionHandler: @escaping (Error?) -> Void) {
|
||||
guard let settings = options?["Settings"] as? Data else {
|
||||
let error = PacketTunnelProviderError.fatalError(message: "Failed to retrieve OpenVPN settings from options")
|
||||
completionHandler(error)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
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.fatalError(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) {
|
||||
stopHandler = completionHandler
|
||||
vpnAdapter.disconnect()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension PacketTunnelProvider: OpenVPNAdapterDelegate {
|
||||
|
||||
func configureTunnel(settings: NEPacketTunnelNetworkSettings, callback: @escaping (OpenVPNAdapterPacketFlow?) -> Void) {
|
||||
setTunnelNetworkSettings(settings) { (error) in
|
||||
callback(error == nil ? self.packetFlow : nil)
|
||||
}
|
||||
}
|
||||
|
||||
func handle(event: OpenVPNEvent, message: String?) {
|
||||
|
||||
}
|
||||
|
||||
func handle(error: Error) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Then.swift
|
||||
// MCPEBot
|
||||
//
|
||||
// Created by Sergey Abramchuk on 27.01.17.
|
||||
// Copyright © 2017 ss-abramchuk. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreGraphics
|
||||
|
||||
public protocol Then {}
|
||||
|
||||
extension Then where Self: Any {
|
||||
|
||||
/// Makes it available to set properties with closures just after initializing and copying the value types.
|
||||
///
|
||||
/// let frame = CGRect().with {
|
||||
/// $0.origin.x = 10
|
||||
/// $0.size.width = 100
|
||||
/// }
|
||||
public func with(_ block: (inout Self) -> Void) -> Self {
|
||||
var copy = self
|
||||
block(©)
|
||||
return copy
|
||||
}
|
||||
|
||||
/// Makes it available to execute something with closures.
|
||||
///
|
||||
/// UserDefaults.standard.do {
|
||||
/// $0.set("devxoul", forKey: "username")
|
||||
/// $0.set("devxoul@gmail.com", forKey: "email")
|
||||
/// $0.synchronize()
|
||||
/// }
|
||||
public func `do`(_ block: (Self) -> Void) {
|
||||
block(self)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Then where Self: AnyObject {
|
||||
|
||||
/// Makes it available to set properties with closures just after initializing.
|
||||
///
|
||||
/// let label = UILabel().then {
|
||||
/// $0.textAlignment = .Center
|
||||
/// $0.textColor = UIColor.blackColor()
|
||||
/// $0.text = "Hello, World!"
|
||||
/// }
|
||||
public func then(_ block: (Self) -> Void) -> Self {
|
||||
block(self)
|
||||
return self
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NSObject: Then {}
|
||||
|
||||
extension CGPoint: Then {}
|
||||
extension CGRect: Then {}
|
||||
extension CGSize: Then {}
|
||||
extension CGVector: Then {}
|
||||
Reference in New Issue
Block a user