Skip to content

Commit

Permalink
Fix IPv6 parsing in API access methods and custom DNS
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Petersson authored and pinkisemils committed Sep 30, 2024
1 parent fe5092c commit d33909e
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 8 deletions.
1 change: 1 addition & 0 deletions ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Line wrap the file at 100 chars. Th
## Unreleased
### Added
- Add a new access method that uses the encrypted DNS proxy to reach our API.
- Fix IPv6 parsing in API access

## [2024.7 - 2024-09-16]
### Added
Expand Down
4 changes: 4 additions & 0 deletions ios/MullvadTypes/AnyIPAddress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,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 */; };
Expand Down Expand Up @@ -1918,6 +1919,7 @@
7AEF7F192AD00F52006FE45D /* AppMessageHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppMessageHandler.swift; sourceTree = "<group>"; };
7AF10EB12ADE859200C090B9 /* AlertViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertViewController.swift; sourceTree = "<group>"; };
7AF10EB32ADE85BC00C090B9 /* RelayFilterCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelayFilterCoordinator.swift; sourceTree = "<group>"; };
7AF36A992CA2964000E1D497 /* AnyIPAddressTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyIPAddressTests.swift; sourceTree = "<group>"; };
7AF6E5EF2A95051E00F2679D /* RouterBlockDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterBlockDelegate.swift; sourceTree = "<group>"; };
7AF9BE8A2A321BEF00DBFEDB /* RelayFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilter.swift; sourceTree = "<group>"; };
7AF9BE8D2A331C7B00DBFEDB /* RelayFilterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilterViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2482,6 +2484,7 @@
440E9EF92BDA95FC00B1FD11 /* MullvadTypes */ = {
isa = PBXGroup;
children = (
7AF36A992CA2964000E1D497 /* AnyIPAddressTests.swift */,
58FBFBF0291630700020E046 /* DurationTests.swift */,
58C3FA672A385C89006A450A /* FileCacheTests.swift */,
582A8A3928BCE19B00D0F9FB /* FixedWidthIntegerArithmeticsTests.swift */,
Expand Down Expand Up @@ -5288,6 +5291,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 */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,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.
Expand All @@ -227,12 +226,7 @@ private enum CommonValidators {
from value: String,
context: AccessMethodFieldValidationError.Context
) -> Result<AnyIPAddress, AccessMethodFieldValidationError> {
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))
Expand Down
33 changes: 33 additions & 0 deletions ios/MullvadVPNTests/MullvadTypes/AnyIPAddressTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// 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"))
XCTAssertNotNil(AnyIPAddress("2001:db8::42:0:8a2e:370:7334"))
XCTAssertNotNil(AnyIPAddress("::1"))
XCTAssertNotNil(AnyIPAddress("::"))
XCTAssertNotNil(AnyIPAddress("::ffff:192.168.1.1"))
XCTAssertNotNil(AnyIPAddress("fe80::1ff:fe23:4567:890a"))
XCTAssertNotNil(AnyIPAddress("ff02::1"))
XCTAssertNotNil(AnyIPAddress("2001:0db8:85a3::8a2e:0370:7334"))
}
}

0 comments on commit d33909e

Please sign in to comment.