128 lines
4.5 KiB
Swift
128 lines
4.5 KiB
Swift
//
|
|
// IntercommOpenVPN.swift
|
|
// io.privado.main.hive
|
|
//
|
|
// Created by Juraldinio on 6/21/20.
|
|
// Copyright © 2020 Privado. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
final class IntercommOpenVPN {
|
|
|
|
enum Constants {
|
|
static let sudoPath = "/usr/bin/sudo"
|
|
}
|
|
|
|
private var command: AsyncCommand?
|
|
private weak var client: HiveIntercommConsole?
|
|
|
|
init(client: HiveIntercommConsole?) {
|
|
self.client = client
|
|
}
|
|
|
|
private static func authenticate(path: String, username: String, password: String, client: Socket? = nil) {
|
|
do {
|
|
|
|
guard let client = client else {
|
|
let socket = try Socket.create(family: .unix, type: .stream, proto: .unix)
|
|
try socket.connect(to: path)
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
Self.authenticate(path: path, username: username, password: password, client: socket)
|
|
}
|
|
return
|
|
}
|
|
|
|
if let data = try client.readString()
|
|
, data.split(separator: "\r\n").map({String($0)}).first(where: {$0.contains(">PASSWORD:Need")}) != nil {
|
|
try client.write(from: "username Auth \(username)\r\n")
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
_ = try? client.write(from: "password Auth \(password)\r\n")
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
|
client.close()
|
|
}
|
|
}
|
|
} else {
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
Self.authenticate(path: path, username: username, password: password, client: client)
|
|
}
|
|
}
|
|
} catch {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
extension IntercommOpenVPN: IntercommOpenVPNType {
|
|
|
|
// swiftlint:disable function_parameter_count
|
|
func connect(type: Int, ovpnPath: String, configPath: String, username: String, password: String, completion: @escaping (Error?) -> Void) {
|
|
|
|
guard self.command == nil else {
|
|
let error = NSError(domain: PrivadoConstants.Hive.error,
|
|
code: PrivadoConstants.Hive.ErrorCode.ovpnAlreadyConnected,
|
|
userInfo: nil)
|
|
completion(error)
|
|
return
|
|
}
|
|
|
|
// Kill previously launched services
|
|
main.run(bash: "\(Constants.sudoPath) killall openvpn")
|
|
|
|
let socketPath = "/tmp/ovpn_privado_\(Int.random(in: 42..<255))"
|
|
let arguments = [ovpnPath,
|
|
"--config", configPath,
|
|
"--management", socketPath, "unix",
|
|
"--management-query-passwords",
|
|
"--mute-replay-warnings"]
|
|
|
|
let command = main.runAsync(Constants.sudoPath, arguments).onCompletion { [weak self] handler in
|
|
// Clean command link for indicate that we already finished process
|
|
self?.command = nil
|
|
print(handler)
|
|
}
|
|
|
|
command.stdout.onStringOutput { [weak self] output in
|
|
guard let client = self?.client else { return }
|
|
|
|
if output.contains("Need password(s) from management interface, waiting") {
|
|
Self.authenticate(path: socketPath, username: username, password: password)
|
|
return
|
|
}
|
|
|
|
client.console(message: "\(PrivadoConstants.Hive.preffixConsole)\(output)")
|
|
}
|
|
|
|
command.stderror.onStringOutput { [weak self] output in
|
|
guard let client = self?.client else { return }
|
|
client.console(message: "\(PrivadoConstants.Hive.preffixError)\(output)")
|
|
}
|
|
|
|
self.command = command
|
|
completion(nil)
|
|
}
|
|
// swiftlint:enable function_parameter_count
|
|
|
|
func disconnect(completion: @escaping (Error?) -> Void) {// sudo killall openvpn
|
|
guard let command = self.command else {
|
|
let error = NSError(domain: PrivadoConstants.Hive.error,
|
|
code: PrivadoConstants.Hive.ErrorCode.ovpnAlreadydisconnected,
|
|
userInfo: nil)
|
|
completion(error)
|
|
return
|
|
}
|
|
|
|
command.interrupt()
|
|
|
|
self.command = nil
|
|
|
|
completion(nil)
|
|
}
|
|
|
|
func isConnected(completion: @escaping (Bool) -> Void) {
|
|
completion(self.command != nil)
|
|
}
|
|
|
|
}
|