Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajhilje committed Feb 12, 2024
2 parents 44c7985 + f70ffaa commit c06ca4c
Show file tree
Hide file tree
Showing 33 changed files with 492 additions and 163 deletions.
2 changes: 1 addition & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ In case when there is no issue:
<type>/<short-summary-or-description>
```

Where <type> can be `epic`, `feature`, `task`, `bugfix`, `hotfix` or `release`.
Where `<type>` can be `epic`, `feature`, `task`, `bugfix`, `hotfix` or `release`.

### Branches

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to this project will be documented in this file.

## 2.12.0 - 2024-02-12

[NEW] Device Management
[FIXED] Selecting individual servers with IKEv2
[FIXED] Minor UI issues on the server map

## 2.11.1 - 2023-12-05

[NEW] Option to Block LAN traffic when connected to an untrusted network
Expand Down
2 changes: 1 addition & 1 deletion IVPNClient/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ extension AppDelegate: UIApplicationDelegate {
}
}

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
let endpoint = url.lastPathComponent
handleURLEndpoint(endpoint)
return true
Expand Down
4 changes: 2 additions & 2 deletions IVPNClient/Enums/AddressType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ enum AddressType {
case other

static func validateIpAddress(_ address: String) -> AddressType {
if let _ = IPv4Address(address) {
if IPv4Address(address) != nil {
return .IPv4
} else if let _ = IPv6Address(address) {
} else if IPv6Address(address) != nil {
return .IPv6
} else {
return .other
Expand Down
2 changes: 2 additions & 0 deletions IVPNClient/Enums/ApiResults/ErrorResultSessionNew.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ struct SessionLimitData: Decodable {
let upgradeToPlan: String
let upgradeToUrl: String
let paymentMethod: String
let deviceManagement: Bool
let deviceManagementUrl: String
}

struct ErrorResultSessionNew: Decodable {
Expand Down
1 change: 1 addition & 0 deletions IVPNClient/Enums/ApiResults/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct Session: Decodable {
let token: String?
let vpnUsername: String?
let vpnPassword: String?
let deviceName: String?
let serviceStatus: ServiceStatus
let wireguard: WireGuardResult?
}
1 change: 1 addition & 0 deletions IVPNClient/Enums/ApiResults/SessionStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import Foundation

struct SessionStatus: Decodable {
let status: Int
let deviceName: String?
let serviceStatus: ServiceStatus

var serviceActive: Bool {
Expand Down
10 changes: 6 additions & 4 deletions IVPNClient/Managers/ConnectionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,10 @@ class ConnectionManager {
func connect() {
updateSelectedServer(status: .connecting)

let host = NETunnelProviderProtocol.getHost()
let accessDetails = AccessDetails(
serverAddress: settings.selectedServer.gateway,
ipAddresses: settings.selectedServer.ipAddresses,
ipAddress: host?.host ?? settings.selectedServer.gateway,
gateway: settings.selectedServer.gateway,
username: KeyChain.vpnUsername ?? "",
passwordRef: KeyChain.vpnPasswordRef
)
Expand Down Expand Up @@ -309,9 +310,10 @@ class ConnectionManager {
return
}

let host = NETunnelProviderProtocol.getHost()
let accessDetails = AccessDetails(
serverAddress: Application.shared.settings.selectedServer.gateway,
ipAddresses: Application.shared.settings.selectedServer.ipAddresses,
ipAddress: host?.host ?? settings.selectedServer.gateway,
gateway: settings.selectedServer.gateway,
username: KeyChain.vpnUsername ?? "",
passwordRef: KeyChain.vpnPasswordRef
)
Expand Down
12 changes: 12 additions & 0 deletions IVPNClient/Managers/KeyChain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class KeyChain {
private static let sessionTokenKey = "session_token"
private static let vpnUsernameKey = "vpn_username"
private static let vpnPasswordKey = "vpn_password"
private static let deviceNameKey = "deviceName"

static let bundle: Keychain = {
return Keychain(service: "net.ivpn.clients.ios", accessGroup: "WQXXM75BYN.net.ivpn.IVPN-Client").accessibility(.whenPasscodeSetThisDeviceOnly)
Expand Down Expand Up @@ -149,12 +150,22 @@ class KeyChain {
sessionToken = session.token
vpnUsername = session.vpnUsername
vpnPassword = session.vpnPassword
deviceName = session.deviceName

if let wireguardResult = session.wireguard, let ipAddress = wireguardResult.ipAddress {
KeyChain.wgIpAddress = ipAddress
}
}

class var deviceName: String? {
get {
return KeyChain.bundle[deviceNameKey]
}
set {
KeyChain.bundle[deviceNameKey] = newValue
}
}

static func clearAll() {
username = nil
tempUsername = nil
Expand All @@ -166,6 +177,7 @@ class KeyChain {
sessionToken = nil
vpnUsername = nil
vpnPassword = nil
deviceName = nil
}

}
11 changes: 8 additions & 3 deletions IVPNClient/Managers/NavigationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,16 @@ class NavigationManager {
return viewController
}

static func getLoginViewController() -> UIViewController {
static func getLoginViewController(showLogoutAlert: Bool = false) -> UIViewController {
let storyBoard = UIStoryboard(name: "Signup", bundle: nil)
let viewController = storyBoard.instantiateViewController(withIdentifier: "loginView")
let navController = storyBoard.instantiateViewController(withIdentifier: "loginView") as? UINavigationController
navController?.modalPresentationStyle = .formSheet

return viewController
if let viewController = navController?.topViewController as? LoginViewController {
viewController.showLogoutAlert = showLogoutAlert
}

return navController!
}

static func getChangePlanViewController() -> UIViewController {
Expand Down
6 changes: 4 additions & 2 deletions IVPNClient/Managers/SessionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import Foundation
func createSessionStart()
func createSessionSuccess()
func createSessionFailure(error: Any?)
func createSessionTooManySessions(error: Any?)
func createSessionTooManySessions(error: Any?, isNewStyleAccount: Bool)
func createSessionAuthenticationError()
func createSessionServiceNotActive()
func createSessionAccountNotActivated(error: Any?)
Expand Down Expand Up @@ -67,6 +67,7 @@ class SessionManager {

var kem = KEM()
let params = sessionNewParams(force: force, username: username, confirmation: confirmation, captcha: captcha, captchaId: captchaId, kem: kem)
let isNewStyleAccount = ServiceStatus.isNewStyleAccount(username: username ?? "")
let request = ApiRequestDI(method: .post, endpoint: Config.apiSessionNew, params: params)

ApiService.shared.requestCustomError(request) { (result: ResultCustomError<Session, ErrorResultSessionNew>) in
Expand Down Expand Up @@ -99,7 +100,7 @@ class SessionManager {
return
case 602:
log(.info, message: "Create session error: createSessionTooManySessions")
self.delegate?.createSessionTooManySessions(error: error)
self.delegate?.createSessionTooManySessions(error: error, isNewStyleAccount: isNewStyleAccount)
return
case 11005:
log(.info, message: "Create session error: createSessionAccountNotActivated")
Expand Down Expand Up @@ -141,6 +142,7 @@ class SessionManager {
switch result {
case .success(let model):
Application.shared.serviceStatus = model.serviceStatus
KeyChain.deviceName = model.deviceName
NotificationCenter.default.post(name: Notification.Name.EvaluatePlanUpdate, object: nil)

if model.serviceActive {
Expand Down
11 changes: 5 additions & 6 deletions IVPNClient/Managers/VPNManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,7 @@ class VPNManager {
}

private func setupNEVPNManager(manager: NEVPNManager, accessDetails: AccessDetails, status: NEVPNStatus? = nil, completion: @escaping (Error?) -> Void) {
let serverAddress = accessDetails.ipAddresses.randomElement() ?? accessDetails.serverAddress
self.setupIKEv2Tunnel(manager: manager, accessDetails: accessDetails, serverAddress: serverAddress, status: status)
self.setupIKEv2Tunnel(manager: manager, accessDetails: accessDetails, status: status)
manager.saveToPreferences { error in
if let error = error, error.code == 5 {
manager.isOnDemandEnabled = false
Expand All @@ -141,7 +140,7 @@ class VPNManager {
}

manager.loadFromPreferences { _ in
self.setupIKEv2Tunnel(manager: manager, accessDetails: accessDetails, serverAddress: serverAddress, status: status)
self.setupIKEv2Tunnel(manager: manager, accessDetails: accessDetails, status: status)
manager.saveToPreferences { _ in
completion(nil)
}
Expand Down Expand Up @@ -179,11 +178,11 @@ class VPNManager {
}
}

private func setupIKEv2Tunnel(manager: NEVPNManager, accessDetails: AccessDetails, serverAddress: String, status: NEVPNStatus? = nil) {
private func setupIKEv2Tunnel(manager: NEVPNManager, accessDetails: AccessDetails, status: NEVPNStatus? = nil) {
let configuration = NEVPNProtocolIKEv2()
configuration.remoteIdentifier = accessDetails.serverAddress
configuration.remoteIdentifier = accessDetails.gateway
configuration.localIdentifier = accessDetails.username
configuration.serverAddress = serverAddress
configuration.serverAddress = accessDetails.ipAddress
configuration.username = accessDetails.username
configuration.passwordReference = accessDetails.passwordRef
configuration.authenticationMethod = .none
Expand Down
10 changes: 5 additions & 5 deletions IVPNClient/Models/AccessDetails.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ import Foundation

class AccessDetails {

var serverAddress: String
var ipAddresses: [String]
var ipAddress: String
var gateway: String
var username: String
var passwordRef: Data?

init(serverAddress: String, ipAddresses: [String], username: String, passwordRef: Data?) {
self.serverAddress = serverAddress
self.ipAddresses = ipAddresses
init(ipAddress: String, gateway: String, username: String, passwordRef: Data?) {
self.ipAddress = ipAddress
self.gateway = gateway
self.username = username
self.passwordRef = passwordRef
}
Expand Down
12 changes: 11 additions & 1 deletion IVPNClient/Models/ServiceStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct ServiceStatus: Codable {
let upgradeToUrl: String?
let paymentMethod: String?
let capabilities: [String]?
let deviceManagement: Bool

// MARK: - Initialize -

Expand All @@ -48,6 +49,7 @@ struct ServiceStatus: Codable {
upgradeToUrl = service?.upgradeToUrl ?? nil
paymentMethod = service?.paymentMethod ?? nil
capabilities = service?.capabilities ?? nil
deviceManagement = service?.deviceManagement ?? false
}

// MARK: - Methods -
Expand Down Expand Up @@ -89,7 +91,15 @@ struct ServiceStatus: Codable {
}

func isNewStyleAccount() -> Bool {
return paymentMethod == "prepaid"
guard let username = username else {
return true
}

return username.hasPrefix("i-")
}

static func isNewStyleAccount(username: String) -> Bool {
return username.hasPrefix("i-")
}

func daysUntilSubscriptionExpiration() -> Int {
Expand Down
2 changes: 1 addition & 1 deletion IVPNClient/Models/V2Ray/V2RayConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ struct V2RayConfig: Codable {
let connection: [String]
let pragma: String

enum CodingKeys : String, CodingKey {
enum CodingKeys: String, CodingKey {

Check warning on line 115 in IVPNClient/Models/V2Ray/V2RayConfig.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Nesting Violation: Types should be nested at most 1 level deep (nesting)

Check warning on line 115 in IVPNClient/Models/V2Ray/V2RayConfig.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Nesting Violation: Types should be nested at most 1 level deep (nesting)

Check warning on line 115 in IVPNClient/Models/V2Ray/V2RayConfig.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Nesting Violation: Types should be nested at most 1 level deep (nesting)
case host = "Host"

Check warning on line 116 in IVPNClient/Models/V2Ray/V2RayConfig.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Nesting Violation: Statements should be nested at most 5 levels deep (nesting)
case userAgent = "User-Agent"

Check warning on line 117 in IVPNClient/Models/V2Ray/V2RayConfig.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Nesting Violation: Statements should be nested at most 5 levels deep (nesting)
case acceptEncoding = "Accept-Encoding"
Expand Down
4 changes: 2 additions & 2 deletions IVPNClient/Models/V2Ray/V2RayCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class V2RayCore {

func start() -> Error? {
let _ = close()
var error: Error? = nil
var error: Error?

guard let config = makeConfig() else {
return NSError(domain: "", code: 99, userInfo: [NSLocalizedDescriptionKey: "V2Ray configuration cannot be loaded"])
Expand All @@ -52,7 +52,7 @@ class V2RayCore {
}

func close() -> Error? {
var error: Error? = nil
var error: Error?

if let instance = instance {
var stopError: NSError?
Expand Down
4 changes: 1 addition & 3 deletions IVPNClient/Models/VPNServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,14 @@ class VPNServer {
private (set) var latitude: Double
private (set) var longitude: Double
private (set) var isp: String
private (set) var ipAddresses: [String]
private (set) var hosts: [Host]
private (set) var load: Double?
private (set) var ipv6: IPv6?
var dnsName: String?

// MARK: - Initialize -

init(gateway: String, dnsName: String? = nil, countryCode: String, country: String, city: String, latitude: Double = 0, longitude: Double = 0, isp: String = "", ipAddresses: [String] = [], hosts: [Host] = [], fastest: Bool = false, load: Double = 0, ipv6: IPv6? = nil) {
init(gateway: String, dnsName: String? = nil, countryCode: String, country: String, city: String, latitude: Double = 0, longitude: Double = 0, isp: String = "", hosts: [Host] = [], fastest: Bool = false, load: Double = 0, ipv6: IPv6? = nil) {
self.gateway = gateway
self.dnsName = dnsName
self.countryCode = countryCode
Expand All @@ -115,7 +114,6 @@ class VPNServer {
self.latitude = latitude
self.longitude = longitude
self.isp = isp
self.ipAddresses = ipAddresses
self.hosts = hosts
self.fastest = fastest
self.load = load
Expand Down
14 changes: 1 addition & 13 deletions IVPNClient/Models/VPNServerList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ class VPNServerList {
}

func getServer(byIpAddress ipAddress: String) -> VPNServer? {
return getServers().first { $0.ipAddresses.first { $0 == ipAddress } != nil }
return getServers().first { $0.hosts.first?.host == ipAddress }
}

func getServer(byGateway gateway: String) -> VPNServer? {
Expand Down Expand Up @@ -394,21 +394,10 @@ class VPNServerList {
servers.removeAll()

for server in serversList {
var serverIpList = [String]()
var serverHostsList = [Host]()

if let ipAddressList = server["ip_addresses"] as? [String?] {
for ipAddress in ipAddressList where ipAddress != nil {
serverIpList.append(ipAddress!)
}
}

if let hostsList = server["hosts"] as? [[String: Any]] {
for host in hostsList {
if let hostIp = host["host"] as? String {
serverIpList.append(hostIp)
}

var newHost = Host(
host: host["host"] as? String ?? "",
hostName: host["hostname"] as? String ?? "",
Expand Down Expand Up @@ -438,7 +427,6 @@ class VPNServerList {
latitude: server["latitude"] as? Double ?? 0,
longitude: server["longitude"] as? Double ?? 0,
isp: server["isp"] as? String ?? "",
ipAddresses: serverIpList,
hosts: serverHostsList
)

Expand Down
Loading

0 comments on commit c06ca4c

Please sign in to comment.