diff --git a/ios/CHANGELOG.md b/ios/CHANGELOG.md index d6a0e9381ce7..a841879ee1d1 100644 --- a/ios/CHANGELOG.md +++ b/ios/CHANGELOG.md @@ -25,6 +25,9 @@ Line wrap the file at 100 chars. Th ### Added - Add DAITA (Defence against AI-guided Traffic Analysis) setting +### Fixed +- Fix IPv6 parsing in API access + ## [2024.5 - 2024-08-19] ### Added - Add multihop, a feature that routes traffic through two diff --git a/ios/MullvadTypes/AnyIPAddress.swift b/ios/MullvadTypes/AnyIPAddress.swift index ca88f73632f8..0bfb9fa2d88f 100644 --- a/ios/MullvadTypes/AnyIPAddress.swift +++ b/ios/MullvadTypes/AnyIPAddress.swift @@ -69,6 +69,10 @@ public enum AnyIPAddress: IPAddress, Codable, Equatable, CustomDebugStringConver } public init?(_ string: String) { + // Arbitrary integers should not be allowed by us and need to be handled separately + // since Apple allows them. + guard Int(string) == nil else { return nil } + if let ipv4Address = IPv4Address(string) { self = .ipv4(ipv4Address) } else if let ipv6Address = IPv6Address(string) { diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index f939a417806e..6f0e0fda0d3f 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -608,6 +608,7 @@ 7AEF7F1A2AD00F52006FE45D /* AppMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEF7F192AD00F52006FE45D /* AppMessageHandler.swift */; }; 7AF10EB22ADE859200C090B9 /* AlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF10EB12ADE859200C090B9 /* AlertViewController.swift */; }; 7AF10EB42ADE85BC00C090B9 /* RelayFilterCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF10EB32ADE85BC00C090B9 /* RelayFilterCoordinator.swift */; }; + 7AF36A9A2CA2964200E1D497 /* AnyIPAddressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF36A992CA2964000E1D497 /* AnyIPAddressTests.swift */; }; 7AF6E5F02A95051E00F2679D /* RouterBlockDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF6E5EF2A95051E00F2679D /* RouterBlockDelegate.swift */; }; 7AF9BE882A30C62100DBFEDB /* SelectableSettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1A264A2A29D65E00B978AA /* SelectableSettingsCell.swift */; }; 7AF9BE8C2A321D1F00DBFEDB /* RelayFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF9BE8A2A321BEF00DBFEDB /* RelayFilter.swift */; }; @@ -1915,6 +1916,7 @@ 7AEF7F192AD00F52006FE45D /* AppMessageHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppMessageHandler.swift; sourceTree = ""; }; 7AF10EB12ADE859200C090B9 /* AlertViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertViewController.swift; sourceTree = ""; }; 7AF10EB32ADE85BC00C090B9 /* RelayFilterCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelayFilterCoordinator.swift; sourceTree = ""; }; + 7AF36A992CA2964000E1D497 /* AnyIPAddressTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyIPAddressTests.swift; sourceTree = ""; }; 7AF6E5EF2A95051E00F2679D /* RouterBlockDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterBlockDelegate.swift; sourceTree = ""; }; 7AF9BE8A2A321BEF00DBFEDB /* RelayFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilter.swift; sourceTree = ""; }; 7AF9BE8D2A331C7B00DBFEDB /* RelayFilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilterViewModel.swift; sourceTree = ""; }; @@ -2471,6 +2473,7 @@ 440E9EF92BDA95FC00B1FD11 /* MullvadTypes */ = { isa = PBXGroup; children = ( + 7AF36A992CA2964000E1D497 /* AnyIPAddressTests.swift */, 58FBFBF0291630700020E046 /* DurationTests.swift */, 58C3FA672A385C89006A450A /* FileCacheTests.swift */, 582A8A3928BCE19B00D0F9FB /* FixedWidthIntegerArithmeticsTests.swift */, @@ -5265,6 +5268,7 @@ A9A5FA3F2ACB05D90083449F /* DeviceCheckRemoteService.swift in Sources */, A9A5FA402ACB05D90083449F /* DeviceCheckRemoteServiceProtocol.swift in Sources */, A9A5FA412ACB05D90083449F /* DeviceStateAccessor.swift in Sources */, + 7AF36A9A2CA2964200E1D497 /* AnyIPAddressTests.swift in Sources */, A9A5FA422ACB05D90083449F /* DeviceStateAccessorProtocol.swift in Sources */, 7A5869C32B5820CE00640D27 /* IPOverrideRepositoryTests.swift in Sources */, A9A5FA392ACB05910083449F /* UIColor+Palette.swift in Sources */, diff --git a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Models/AccessMethodViewModel+Persistent.swift b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Models/AccessMethodViewModel+Persistent.swift index 0d8182b5afb6..c9b8162a0d98 100644 --- a/ios/MullvadVPN/Coordinators/Settings/APIAccess/Models/AccessMethodViewModel+Persistent.swift +++ b/ios/MullvadVPN/Coordinators/Settings/APIAccess/Models/AccessMethodViewModel+Persistent.swift @@ -214,8 +214,7 @@ private enum CommonValidators { return .success(portNumber) } - /// Parse IP address from string by first running the input via regular expression before parsing it using Apple's facilities which are known to accept all kind of - /// malformed input. + /// Parse IP address from string by using Apple's facilities. /// /// - Parameters: /// - value: a string input. @@ -225,12 +224,7 @@ private enum CommonValidators { from value: String, context: AccessMethodFieldValidationError.Context ) -> Result { - let range = NSRange(value.startIndex ..< value.endIndex, in: value) - - let regexMatch = NSRegularExpression.ipv4RegularExpression.firstMatch(in: value, range: range) - ?? NSRegularExpression.ipv6RegularExpression.firstMatch(in: value, range: range) - - if regexMatch?.range == range, let address = AnyIPAddress(value) { + if let address = AnyIPAddress(value) { return .success(address) } else { return .failure(AccessMethodFieldValidationError(kind: .invalidIPAddress, field: .server, context: context)) diff --git a/ios/MullvadVPNTests/MullvadTypes/AnyIPAddressTests.swift b/ios/MullvadVPNTests/MullvadTypes/AnyIPAddressTests.swift new file mode 100644 index 000000000000..c1b662817fea --- /dev/null +++ b/ios/MullvadVPNTests/MullvadTypes/AnyIPAddressTests.swift @@ -0,0 +1,26 @@ +// +// AnyIPAddressTests.swift +// MullvadVPN +// +// Created by Jon Petersson on 2024-09-24. +// Copyright © 2024 Mullvad VPN AB. All rights reserved. +// + +@testable import MullvadTypes +import XCTest + +final class AnyIPAddressTests: XCTestCase { + func testAnyIPAddressFromString() { + XCTAssertNil(AnyIPAddress("000")) + XCTAssertNil(AnyIPAddress("1")) + XCTAssertNil(AnyIPAddress("abcde")) + XCTAssertNil(AnyIPAddress("0.1.2.3.5")) + XCTAssertNil(AnyIPAddress("2a03:1b20:1:f011:bb09")) + + XCTAssertNotNil(AnyIPAddress("0.0")) + XCTAssertNotNil(AnyIPAddress("0.1")) + XCTAssertNotNil(AnyIPAddress("192.168.0.1")) + XCTAssertNotNil(AnyIPAddress("2a03:1b20:1:f011::bb09")) + XCTAssertNotNil(AnyIPAddress("FE80:0000:0000:0000:0202:B3FF:FE1E:8329")) + } +}