From 2cdf896f101e0179dca78146d2ccd935e4591135 Mon Sep 17 00:00:00 2001
From: Bug Magnet <marco.nikic@mullvad.net>
Date: Mon, 14 Oct 2024 15:28:50 +0200
Subject: [PATCH] Check AddressCache as well when overriding hostname for SSL
 validation

---
 ios/MullvadREST/ApiHandlers/RESTURLSession.swift         | 6 ++++--
 .../ApiHandlers/SSLPinningURLSessionDelegate.swift       | 5 ++++-
 .../Transport/ProxyConfigurationTransportProvider.swift  | 2 +-
 ios/MullvadVPN/AppDelegate.swift                         | 2 +-
 ios/MullvadVPN/SceneDelegate.swift                       | 2 +-
 .../MullvadVPN/TunnelManager/TunnelManagerTests.swift    | 9 +++++++--
 .../PacketTunnelProvider/PacketTunnelProvider.swift      | 2 +-
 7 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/ios/MullvadREST/ApiHandlers/RESTURLSession.swift b/ios/MullvadREST/ApiHandlers/RESTURLSession.swift
index 99bafcee3cd2..a1c6431df413 100644
--- a/ios/MullvadREST/ApiHandlers/RESTURLSession.swift
+++ b/ios/MullvadREST/ApiHandlers/RESTURLSession.swift
@@ -7,9 +7,10 @@
 //
 
 import Foundation
+import Network
 
 extension REST {
-    public static func makeURLSession() -> URLSession {
+    public static func makeURLSession(addressCache: AddressCache) -> URLSession {
         let certificatePath = Bundle(for: SSLPinningURLSessionDelegate.self)
             .path(forResource: "le_root_cert", ofType: "cer")!
         let data = FileManager.default.contents(atPath: certificatePath)!
@@ -17,7 +18,8 @@ extension REST {
 
         let sessionDelegate = SSLPinningURLSessionDelegate(
             sslHostname: defaultAPIHostname,
-            trustedRootCertificates: [secCertificate]
+            trustedRootCertificates: [secCertificate],
+            addressCache: addressCache
         )
 
         let sessionConfiguration = URLSessionConfiguration.ephemeral
diff --git a/ios/MullvadREST/ApiHandlers/SSLPinningURLSessionDelegate.swift b/ios/MullvadREST/ApiHandlers/SSLPinningURLSessionDelegate.swift
index 2d0d1ca40625..a5fd86777071 100644
--- a/ios/MullvadREST/ApiHandlers/SSLPinningURLSessionDelegate.swift
+++ b/ios/MullvadREST/ApiHandlers/SSLPinningURLSessionDelegate.swift
@@ -14,12 +14,14 @@ import Security
 final class SSLPinningURLSessionDelegate: NSObject, URLSessionDelegate {
     private let sslHostname: String
     private let trustedRootCertificates: [SecCertificate]
+    private let addressCache: REST.AddressCache
 
     private let logger = Logger(label: "SSLPinningURLSessionDelegate")
 
-    init(sslHostname: String, trustedRootCertificates: [SecCertificate]) {
+    init(sslHostname: String, trustedRootCertificates: [SecCertificate], addressCache: REST.AddressCache) {
         self.sslHostname = sslHostname
         self.trustedRootCertificates = trustedRootCertificates
+        self.addressCache = addressCache
     }
 
     // MARK: - URLSessionDelegate
@@ -40,6 +42,7 @@ final class SSLPinningURLSessionDelegate: NSObject, URLSessionDelegate {
                 "\(IPv4Address.loopback)",
                 "\(IPv6Address.loopback)",
                 "\(REST.defaultAPIEndpoint.ip)",
+                "\(addressCache.getCurrentEndpoint().ip)",
             ]
             if overridenHostnames.contains(hostName) {
                 hostName = sslHostname
diff --git a/ios/MullvadREST/Transport/ProxyConfigurationTransportProvider.swift b/ios/MullvadREST/Transport/ProxyConfigurationTransportProvider.swift
index b17a9bd0430f..6d20fa1440d8 100644
--- a/ios/MullvadREST/Transport/ProxyConfigurationTransportProvider.swift
+++ b/ios/MullvadREST/Transport/ProxyConfigurationTransportProvider.swift
@@ -27,7 +27,7 @@ public class ProxyConfigurationTransportProvider {
     }
 
     public func makeTransport(with configuration: PersistentProxyConfiguration) throws -> RESTTransport {
-        let urlSession = REST.makeURLSession()
+        let urlSession = REST.makeURLSession(addressCache: addressCache)
         switch configuration {
         case .direct:
             return URLSessionTransport(urlSession: urlSession)
diff --git a/ios/MullvadVPN/AppDelegate.swift b/ios/MullvadVPN/AppDelegate.swift
index 30869239238b..5010f71ebd8b 100644
--- a/ios/MullvadVPN/AppDelegate.swift
+++ b/ios/MullvadVPN/AppDelegate.swift
@@ -110,7 +110,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
             accountsProxy: accountsProxy,
             transactionLog: .default
         )
-        let urlSessionTransport = URLSessionTransport(urlSession: REST.makeURLSession())
+        let urlSessionTransport = URLSessionTransport(urlSession: REST.makeURLSession(addressCache: addressCache))
         let shadowsocksCache = ShadowsocksConfigurationCache(cacheDirectory: containerURL)
         let shadowsocksRelaySelector = ShadowsocksRelaySelector(
             relayCache: ipOverrideWrapper
diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift
index 618555f5fe7a..a79e02745a69 100644
--- a/ios/MullvadVPN/SceneDelegate.swift
+++ b/ios/MullvadVPN/SceneDelegate.swift
@@ -74,7 +74,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, SettingsMigrationUIHand
             accountsProxy: appDelegate.accountsProxy,
             outgoingConnectionService: OutgoingConnectionService(
                 outgoingConnectionProxy: OutgoingConnectionProxy(
-                    urlSession: REST.makeURLSession(),
+                    urlSession: REST.makeURLSession(addressCache: appDelegate.addressCache),
                     hostname: ApplicationConfiguration.hostName
                 )
             ),
diff --git a/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift b/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift
index 67a42b18e116..d4bf276f152c 100644
--- a/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift
+++ b/ios/MullvadVPNTests/MullvadVPN/TunnelManager/TunnelManagerTests.swift
@@ -5,7 +5,7 @@
 //  Created by Marco Nikic on 2023-10-02.
 //  Copyright © 2023 Mullvad VPN AB. All rights reserved.
 //
-import MullvadREST
+@testable import MullvadREST
 
 @testable import MullvadMockData
 @testable import MullvadSettings
@@ -24,6 +24,7 @@ class TunnelManagerTests: XCTestCase {
     var accessTokenManager: AccessTokenManagerStub!
     var devicesProxy: DevicesProxyStub!
     var apiProxy: APIProxyStub!
+    var addressCache: REST.AddressCache!
 
     var transportProvider: TransportProvider!
 
@@ -42,9 +43,13 @@ class TunnelManagerTests: XCTestCase {
         accessTokenManager = AccessTokenManagerStub()
         devicesProxy = DevicesProxyStub(deviceResult: .success(Device.mock(publicKey: PrivateKey().publicKey)))
         apiProxy = APIProxyStub()
+        addressCache = REST.AddressCache(
+            canWriteToCache: false,
+            fileCache: MockFileCache(initialState: .fileNotFound)
+        )
 
         transportProvider = TransportProvider(
-            urlSessionTransport: URLSessionTransport(urlSession: REST.makeURLSession()),
+            urlSessionTransport: URLSessionTransport(urlSession: REST.makeURLSession(addressCache: addressCache)),
             addressCache: REST.AddressCache(
                 canWriteToCache: true,
                 cacheDirectory: FileManager.default.temporaryDirectory
diff --git a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
index d99d96642418..92e02e96d547 100644
--- a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
@@ -203,7 +203,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
         ipOverrideWrapper: IPOverrideWrapper,
         addressCache: REST.AddressCache
     ) -> TransportProvider {
-        let urlSession = REST.makeURLSession()
+        let urlSession = REST.makeURLSession(addressCache: addressCache)
         let urlSessionTransport = URLSessionTransport(urlSession: urlSession)
         let shadowsocksCache = ShadowsocksConfigurationCache(cacheDirectory: appContainerURL)