88 lines
2.7 KiB
Swift
88 lines
2.7 KiB
Swift
//
|
|
// Inception.swift
|
|
// PrivadoVPN
|
|
//
|
|
// Created by Juraldinio on 8/18/20.
|
|
// Copyright © 2020 Privado LLC. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
final class Inception {
|
|
|
|
private enum Constants {
|
|
static let authenticate = "auth"
|
|
static let customer = "customer"
|
|
//
|
|
static let suffixLength = 5
|
|
}
|
|
|
|
// Credentials passed from url
|
|
private struct Credentials: Decodable {
|
|
let user: String
|
|
let pass: String
|
|
}
|
|
// privadovpn://auth?yLCUMSNr2bQ5Vq-38Hhw16RhwVGCgMM1ETsYzEXd0P8GBaUGnS65HSfB0Nkm9bz1vQcDw
|
|
|
|
static func handle(url: URL) -> Route? {
|
|
|
|
guard let scheme = url.scheme
|
|
, scheme.localizedCaseInsensitiveCompare(PrivadoConstants.Application.scheme) == .orderedSame
|
|
, let host = url.host else { return nil }
|
|
|
|
switch host {
|
|
case Constants.authenticate:
|
|
return Self.authenticate(components: URLComponents(url: url, resolvingAgainstBaseURL: false))
|
|
case Constants.customer:
|
|
return .customer
|
|
default:
|
|
return nil
|
|
}
|
|
|
|
/*let encoded = host.replacingOccurrences(of: base64, with: "")
|
|
guard let data = Data(base64Encoded: encoded)
|
|
, let credentials = try? JSONDecoder().decode(Credentials.self, from: data) else {
|
|
return nil
|
|
}
|
|
|
|
return .login(type: .authenticate(credentials.user, credentials.pass))*/
|
|
}
|
|
|
|
// MARK: - Static Private
|
|
|
|
private static func authenticate(components: URLComponents?) -> Route? {
|
|
|
|
guard let components = components
|
|
, let urlToken = components.queryItems?.first?.name else { return nil }
|
|
|
|
let token = urlToken
|
|
.replacingOccurrences(of: "-", with: "+")
|
|
.replacingOccurrences(of: "_", with: "/")
|
|
|
|
guard let encrToken = Data(base64Encoded: String(token.suffix(token.count - Constants.suffixLength)))
|
|
, let key = PrivadoConstants.Session.key.data(using: .utf8) else {
|
|
return nil
|
|
}
|
|
|
|
let blockSize = 16
|
|
let iv = encrToken.prefix(upTo: blockSize)
|
|
let message = encrToken.suffix(encrToken.count - blockSize)
|
|
|
|
guard let decriptedToken = CryptoAES(key: key, iv: iv).decrypt(data: message) else { return nil }
|
|
|
|
let credentials = decriptedToken
|
|
.split(separator: ":")
|
|
.map { String($0) }
|
|
|
|
if credentials.count == 2
|
|
, let username = credentials.first
|
|
, let password = credentials.last {
|
|
return .login(type: .authenticate(username, password, true))
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|