Compare commits

..

96 Commits

Author SHA1 Message Date
Jason A. Donenfeld b51113f680 Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-15 16:18:07 +01:00
Andrej Mihajlov be96dea04a WireGuardApp: Refactor TunnelListCell
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Andrej Mihajlov a786f5df60 WireGuardApp: Replace AnyObject with a concrete NSKeyValueObservation
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Andrej Mihajlov 9a483a46fa WireGuardApp: Animate switch control in TunnelListCell
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Andrej Mihajlov 5d2a337332 WireGuardApp: Remove 200ms delay when updating tunnel status switch
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Andrej Mihajlov facf776602 WireGuardApp: Pin status switch to cell margin
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Andrej Mihajlov d3400e3a80 WireGuardApp: Refactor indicator view initialization
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Andrej Mihajlov 92517bd21e WireGuardApp: Use Bundle.forInfoDictionaryKey to access Info.plist fields
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Andrej Mihajlov 761f635e16 WireGuardApp: Refactor indicator initialization
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Andrej Mihajlov 44704ba892 WireGuardApp: Fix window background color to default black
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-15 15:56:22 +01:00
Jason A. Donenfeld 9231c03513 global: support DNS search domains
This has been supported by Windows and Linux for quite some time. Add
support here for iOS and macOS.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-15 15:54:12 +01:00
Jason A. Donenfeld 27b32e60b2 WireGuardKitGo: update to latest wireguard-go tag
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-15 13:16:52 +01:00
Jason A. Donenfeld 9d5b376dcf Revert "[REVERT ME SOON] TunnelsManager: Workaround for macOS Catalina deleting tunnels arbitrarily"
This reverts commit 028e76eb3f.

It's been over a year. I really hope this is fixed by Apple.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-11 12:51:16 +01:00
Jason A. Donenfeld 8fd4883d7e WireGuardApp: modify xcodeproj when syncing translations
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-11 12:39:43 +01:00
Andrej Mihajlov d414cec9aa WireGuardKit: Let wireguard-go backend run in offline on macOS
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-11 11:56:05 +01:00
Jason A. Donenfeld 54e3333b72 WireGuardApp: add CrowdIn syncer and run it
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-11 11:34:19 +01:00
Andrej Mihajlov 9f8d0e24df WireGuardKit: Conditionally turn on/off wireguard-go
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-11 11:15:22 +01:00
Jason A. Donenfeld 3de7c99301 WireGuardGoKit: drop support for armv7
Apple and Go have both dropped it, so we do the same.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-09 15:56:35 +01:00
Jason A. Donenfeld d4fd17cd8f global: fix remaining swiftlint violations
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-09 14:35:21 +01:00
Jason A. Donenfeld d875266db5 WireGuardKitGo: get rid of missing -Wno-unused-command-line-argument flag
Recent toolchains error out on it, and it's no longer needed.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-09 14:25:22 +01:00
Jason A. Donenfeld d696e31b6e WireGuardKitGo: rebase boottime patch onto Go 1.15.6
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-09 14:08:45 +01:00
Jason A. Donenfeld 90acf2b220 global: bump year in header
A bit overdue, but better late than never.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-12-04 12:15:29 +01:00
Andrej Mihajlov 27ef0c6dba WireGuardApp: Update target membership to exclude sources that are only used in network extensions
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 11:50:44 +01:00
Andrej Mihajlov 8f67435d4a WireGuardKit: Delegate IPv*Address initialization to self.init
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 11:50:44 +01:00
Andrej Mihajlov b4ebe2440f WireGuardApp: Remove backend version call in Logger.swift & extract wireguard-go version script from network extension targets
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 11:50:44 +01:00
Andrej Mihajlov d440a91b0e WireGuardKit: Log XLAT resolution errors
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 11:50:43 +01:00
Andrej Mihajlov 9e909a3294 WireGuardApp: Disable SWIFT_PRECOMPILE_BRIDGING_HEADER
Clang automatically picks up module.modulemap files from WireGuardKit directories when precompiling bridging header file, which causes the compiler to fail with obscure error.

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:39:09 +01:00
Andrej Mihajlov 75bcf97ab2 WireGuardApp: Update swift version from 4.2 to 5.0
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:39:09 +01:00
Andrej Mihajlov 0edde8b46f Update checkout path in README
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:39:09 +01:00
Andrej Mihajlov bcc34e0bb6 Keychain: Avoid roundtrip via items when accessing item label (stored in kSecAttrLabel)
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:39:09 +01:00
Andrej Mihajlov 90b41aed89 Keychain: Remove unnecessary cast to String in Keychain queries
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:39:09 +01:00
Andrej Mihajlov 7930b94981 WireGuardApp: Remove WireGuardKit.swift from Xcode source tree
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:39:09 +01:00
Andrej Mihajlov 54a89f6a0e WireGuadKit: Rename WireGuardAdapter.version -> .backendVersion & remove var wireGuardVersion with WireGuardKit.swift
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:39:09 +01:00
Andrej Mihajlov 8976a53b05 WireGuardApp: Add back the wireguard-go version extraction script and use WIREGUARD_GO_VERSION directly
Avoids linking against libwg-go.a in order to access the WireGuard backend version.

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:39:05 +01:00
Andrej Mihajlov 9849dedf1d WireGuardApp: Include headers from WireGuardKitC
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-04 09:38:31 +01:00
Andrej Mihajlov 547077a808 WireGuardApp: integrate WireGuardKit sources directly
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:25 +01:00
Andrej Mihajlov 0b0898dc3c Remove Sources/ in project folder names
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:25 +01:00
Andrej Mihajlov 9f9d1ffed8 WireGuardKit: Rename WireGuardKitSwift -> WireGuardKit
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:25 +01:00
Andrej Mihajlov 5a044e4129 Linter: Fix all linter issues across the codebase
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:25 +01:00
Andrej Mihajlov 35f0ada8a9 WireGuardApp: Fix build working dir for go-bridge targets
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:25 +01:00
Andrej Mihajlov 39e7ee07ac WireGuardNetworkExtension: Remove wireguard.h from bridging header
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:25 +01:00
Andrej Mihajlov 5a1c9598f1 Fix paths pointing to xcconfigs
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:25 +01:00
Andrej Mihajlov 101a45b6f1 WireGuardKit: Add wireguard-go files to exclude list to eliminate SwiftPM warnings
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:25 +01:00
Andrej Mihajlov fd527f73e6 WireGuardKit: Set publicHeadersPath = "." to flatten public headers structure
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:24 +01:00
Andrej Mihajlov de6aa3eb58 WireGuardKit: Fix module map for WireGuardKitC
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:24 +01:00
Andrej Mihajlov c9eafd82ac WireGuardKit: Fix import statements
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:24 +01:00
Andrej Mihajlov ec57408570 Move all source files to Sources/ and rename WireGuardKit targets
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:32:24 +01:00
Andrej Mihajlov 9c38a1b897 WireGuardKit: Assert that resolutionResults must not contain failures
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov b34625f511 WireGuardKit: Only assign self.settingsGenerator upon success to set tunnel network settings to avoid inconsistent state
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov 2e356d3d8f WireGuardKit: Remove handleLogLine from WireGuardAdapter
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov 697d449dc8 WireGuardKit: Remove isStarted: bool from WireGuardAdapter
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov 4f9f61f7a7 WireGuardKit: Fix docs for WireGuardAdapterError
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov bceb0a827d WireGuardKit: Fix docs for WireGuardLogLevel
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov 2329f712cf WireGuardKit: Pass logHandler via constructor
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov d2c38702c8 Packet tunnel: Remove last error in the completion handler given to adapter.stop
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov def921801f WireGuardKit: Rename cannotLocateSocketDescriptor -> cannotLocateTunnelFileDescriptor in WireGuardAdapterError
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov 41e006a407 WireGuardApp: Switch WireGuardKit to master branch
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov 384b514290 WireGuardKit: Add TODO to log the error coming from withReresolvedIP
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov a6858bd126 WireGuardKit: Change getWireGuardVersion() -> wireGuardVersion
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov ef7de2500f Update README
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-03 13:22:52 +01:00
Andrej Mihajlov 6099975b71 Packet tunnel: Implement packet tunnel provider using WireGuardAdapter
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:09 +01:00
Andrej Mihajlov 828756e8ba WireGuardKit: Add WireGuardAdapter
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:09 +01:00
Andrej Mihajlov 4deaf905c1 WireGuardKit: Add wrappers for PrivateKey, PublicKey, PreSharedKey
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:09 +01:00
Andrej Mihajlov 76c8487a56 iOS/macOS: Remove "Extract wireguard-go version" build phase
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:09 +01:00
Andrej Mihajlov a05f1233f9 iOS/macOS: Remove main bundle apps dependence on WireGuardgoBridge.
Main bundle apps do not have to depend on WireGuardGoBridge<PLATFORM> as they depend on network extnesions which in turn depend on WireGuardGoBridge<PLATFORM>.

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:08 +01:00
Andrej Mihajlov 95b833c754 iOS/macOS: Integrate WireGuardKit
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:08 +01:00
Jason A. Donenfeld 8c057bf928 go-bridge: Add context support for wgSetLogger
Cherry picked cda99bf45c3cb95ca56204549689a0ae91ff4813 from jd/loggerCtx with the fix for wgSetLogger signature in the C header file.

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:08 +01:00
Andrej Mihajlov ddf8ade9c6 WireGuardKit: Add WireGuardKitCTarget with private C sources
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:08 +01:00
Andrej Mihajlov 4cb21b5eb0 WireGuardKit: Set public access level for shared structs
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:08 +01:00
Andrej Mihajlov a03df7d8cc WireGuardKit: Move shared structs to WireGuardKit
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:08 +01:00
Andrej Mihajlov 57f66f16f8 WireGuardKit: Add swift package scaffolding
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2020-12-02 11:08:08 +01:00
Jason A. Donenfeld 737f847c0d go-bridge: dup tunFd so as to not confuse NetworkExtension
The extension isn't banking on tunFd being closed ever, so dup it before
handing it to the rest of wireguard-go.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-09-02 17:21:37 +02:00
Andrej Mihajlov 671a594945 Change QoS to .utility
As per comment by eskimo:
https://developer.apple.com/forums/thread/107904?answerId=328525022#328525022

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-06-25 17:50:15 -06:00
Andrej Mihajlov 3646430528 Make sure that the tunnel and path monitor run on the same serial queue
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-06-25 17:50:15 -06:00
Andrej Mihajlov e9bd6e576f Fix retain cycle between NWPathMonitor and PacketTunnelProvider
See: https://www.marisibrothers.com/2017/04/memory-leak-in-swift-assigning-function.html

Signed-off-by: Andrej Mihajlov <and@mullvad.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-06-25 17:50:15 -06:00
Andrej Mihajlov 35300d1c5f Refactor interface name query
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-06-25 17:50:03 -06:00
Jason A. Donenfeld 112545248e Localization: Update Japanese
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-04-11 23:28:05 -06:00
Roopesh Chander 78e6ecc4bc Localization: macOS: Add translations for 'Edit' button
By copying the 'macMenuEdit' entries to 'macButtonEdit'.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2020-04-11 16:57:51 +05:30
Roopesh Chander 174a6e8e32 Localization: macOS: Fix localization for 'Edit' button
Signed-off-by: Roopesh Chander <roop@roopc.net>
2020-04-11 16:56:54 +05:30
Roopesh Chander 20bcabbca4 Localization: Add German translation
Signed-off-by: Roopesh Chander <roop@roopc.net>
2020-04-11 16:41:45 +05:30
Roopesh Chander 0a3554cedd Localization: Add Italian translation
Signed-off-by: Roopesh Chander <roop@roopc.net>
2020-04-11 16:41:45 +05:30
Roopesh Chander 2acc7db63d Localization: Wire up Japanese translation
By adding the translated Localizable.strings to the Xcode project

Signed-off-by: Roopesh Chander <roop@roopc.net>
2020-04-11 16:41:45 +05:30
Jason A. Donenfeld 31af7049fc highlighter: insist on 256-bit keys, not 257-bit or 258-bit
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-04-03 23:17:56 -06:00
Eiji Tanioka 52062a45c1 Japanese Translation
Translation for wireguard-apple. Checked on Xcode iOS simulator but not
all messages.

Signed-off-by: Eiji Tanioka <tanioka404@gmail.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-02-23 10:02:49 +01:00
Andrej Mihajlov 30406dec6d wireguard-go-bridge: use C string instead of gostring_t
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-02-07 22:35:57 +01:00
Jason A. Donenfeld edde27a0a0 Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-01-27 12:10:53 +01:00
Jason A. Donenfeld cfff596c30 wireguard-go-bridge: bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2020-01-27 12:10:21 +01:00
Jason A. Donenfeld ba1c968cdf Update repo urls
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-12-30 11:54:13 +01:00
Jason A. Donenfeld c48406ac38 wireguard-go-bridge: style
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-11-20 09:59:21 +01:00
Jason A. Donenfeld 14437477e6 README: specify required version in readme
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-11-05 18:59:24 +08:00
Jason A. Donenfeld 68d928192b Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-11-05 17:25:24 +08:00
Roopesh Chander 028e76eb3f [REVERT ME SOON] TunnelsManager: Workaround for macOS Catalina deleting tunnels arbitrarily
In macOS Catalina, for some users, the tunnels get deleted arbitrarily
by the OS. It's not clear what triggers that.

As a workaround, in macOS Catalina, when we realize that tunnels have
been deleted outside the app, we reinstate those tunnels using the
information in the keychain.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-11-05 17:25:21 +08:00
Jason A. Donenfeld cb0c965294 wireguard-go-bridge: update to 1.13.4
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-11-05 17:20:31 +08:00
Jason A. Donenfeld d7ce621cb2 UI: iOS: more dark mode fixes
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-25 10:59:16 +02:00
Jason A. Donenfeld a1ca4f6eb5 wireguard-go-bridge: work around Go 1.13.3 regression
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-25 10:36:58 +02:00
Jason A. Donenfeld 437f0dc46d Revert "NetworkExtension: don't use exit(0) hack on Catalina"
This reverts commit 3619279a65d9a506fb13d7f24909b38a5202fa8f.

Still broken!

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-15 16:51:50 +02:00
234 changed files with 7514 additions and 1229 deletions
+5 -1
View File
@@ -31,6 +31,10 @@ xcuserdata
*.hmap *.hmap
*.ipa *.ipa
# Swift Package Manager
.swiftpm
.build/
# Fastlane # Fastlane
*.app.dSYM.zip *.app.dSYM.zip
*.mobileprovision *.mobileprovision
@@ -41,7 +45,7 @@ Preview.html
output output
# Wireguard specific # Wireguard specific
WireGuard/WireGuard/Config/Developer.xcconfig Sources/WireGuardApp/Config/Developer.xcconfig
# Vim # Vim
.*.sw* .*.sw*
@@ -7,6 +7,7 @@ disabled_rules:
- type_body_length - type_body_length
- function_body_length - function_body_length
- nesting - nesting
- inclusive_language
opt_in_rules: opt_in_rules:
- empty_count - empty_count
- empty_string - empty_string
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
+2 -2
View File
@@ -136,5 +136,5 @@ Here's an example WireGuard configuration payload dictionary:
Configurations added via .mobileconfig will not be migrated into keychain until the WireGuard application is opened once. Configurations added via .mobileconfig will not be migrated into keychain until the WireGuard application is opened once.
[wg-quick(8)]: https://git.zx2c4.com/WireGuard/about/src/tools/man/wg-quick.8 [wg-quick(8)]: https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
[wg(8)]: https://git.zx2c4.com/WireGuard/about/src/tools/man/wg.8 [wg(8)]: https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
+40
View File
@@ -0,0 +1,40 @@
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "WireGuardKit",
platforms: [
.macOS(.v10_14),
.iOS(.v12)
],
products: [
.library(name: "WireGuardKit", targets: ["WireGuardKit"])
],
dependencies: [],
targets: [
.target(
name: "WireGuardKit",
dependencies: ["WireGuardKitGo", "WireGuardKitC"]
),
.target(
name: "WireGuardKitC",
dependencies: [],
publicHeadersPath: "."
),
.target(
name: "WireGuardKitGo",
dependencies: [],
exclude: [
"goruntime-boottime-over-monotonic.diff",
"go.mod",
"go.sum",
"api-ios.go",
"Makefile"
],
publicHeadersPath: ".",
linkerSettings: [.linkedLibrary("wg-go")]
)
]
)
+50 -4
View File
@@ -14,11 +14,11 @@ $ cd wireguard-apple
- Rename and populate developer team ID file: - Rename and populate developer team ID file:
``` ```
$ cp WireGuard/WireGuard/Config/Developer.xcconfig.template WireGuard/WireGuard/Config/Developer.xcconfig $ cp Sources/WireGuardApp/Config/Developer.xcconfig.template Sources/WireGuardApp/Config/Developer.xcconfig
$ vim WireGuard/WireGuard/Config/Developer.xcconfig $ vim Sources/WireGuardApp/Config/Developer.xcconfig
``` ```
- Install swiftlint and go: - Install swiftlint and go 1.15:
``` ```
$ brew install swiftlint go $ brew install swiftlint go
@@ -27,11 +27,57 @@ $ brew install swiftlint go
- Open project in Xcode: - Open project in Xcode:
``` ```
$ open ./WireGuard/WireGuard.xcodeproj $ open WireGuard.xcodeproj
``` ```
- Flip switches, press buttons, and make whirling noises until Xcode builds it. - Flip switches, press buttons, and make whirling noises until Xcode builds it.
## WireGuardKit integration
1. Open your Xcode project and add the Swift package with the following URL:
```
https://git.zx2c4.com/wireguard-apple
```
2. `WireGuardKit` links against `wireguard-go-bridge` library, but it cannot build it automatically
due to Swift package manager limitations. So it needs a little help from a developer.
Please follow the instructions below to create a build target(s) for `wireguard-go-bridge`.
- In Xcode, click File -> New -> Target. Switch to "Other" tab and choose "External Build
System".
- Type in `WireGuardGoBridge<PLATFORM>` under the "Product name", replacing the `<PLATFORM>`
placeholder with the name of the platform. For example, when targeting macOS use `macOS`, or
when targeting iOS use `iOS`.
Make sure the build tool is set to: `/usr/bin/make` (default).
- In the appeared "Info" tab of a newly created target, type in the "Directory" path under
the "External Build Tool Configuration":
```
$BUILD_DIR/../../SourcePackages/checkouts/wireguard-apple/Sources/WireGuardKitGo
```
- Switch to "Build Settings" and find `SDKROOT`.
Type in `macosx` if you target macOS, or type in `iphoneos` if you target iOS.
3. Go to Xcode project settings and locate your network extension target and switch to
"Build Phases" tab.
- Locate "Dependencies" section and hit "+" to add `WireGuardGoBridge<PLATFORM>` replacing
the `<PLATFORM>` placeholder with the name of platform matching the network extension
deployment target (i.e macOS or iOS).
- Locate the "Link with binary libraries" section and hit "+" to add `WireGuardKit`.
4. In Xcode project settings, locate your main bundle app and switch to "Build Phases" tab.
Locate the "Link with binary libraries" section and hit "+" to add `WireGuardKit`.
5. iOS only: Locate Bitcode settings under your application target, Build settings -> Enable Bitcode,
change the corresponding value to "No".
Note that if you ship your app for both iOS and macOS, make sure to repeat the steps 2-4 twice,
once per platform.
## MIT License ## MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
import os.log import os.log
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
import Security import Security
@@ -7,9 +7,9 @@ import Security
class Keychain { class Keychain {
static func openReference(called ref: Data) -> String? { static func openReference(called ref: Data) -> String? {
var result: CFTypeRef? var result: CFTypeRef?
let ret = SecItemCopyMatching([kSecClass as String: kSecClassGenericPassword, let ret = SecItemCopyMatching([kSecClass: kSecClassGenericPassword,
kSecValuePersistentRef as String: ref, kSecValuePersistentRef: ref,
kSecReturnData as String: true] as CFDictionary, kSecReturnData: true] as CFDictionary,
&result) &result)
if ret != errSecSuccess || result == nil { if ret != errSecSuccess || result == nil {
wg_log(.error, message: "Unable to open config from keychain: \(ret)") wg_log(.error, message: "Unable to open config from keychain: \(ret)")
@@ -21,27 +21,28 @@ class Keychain {
static func makeReference(containing value: String, called name: String, previouslyReferencedBy oldRef: Data? = nil) -> Data? { static func makeReference(containing value: String, called name: String, previouslyReferencedBy oldRef: Data? = nil) -> Data? {
var ret: OSStatus var ret: OSStatus
guard var id = Bundle.main.bundleIdentifier else { guard var bundleIdentifier = Bundle.main.bundleIdentifier else {
wg_log(.error, staticMessage: "Unable to determine bundle identifier") wg_log(.error, staticMessage: "Unable to determine bundle identifier")
return nil return nil
} }
if id.hasSuffix(".network-extension") { if bundleIdentifier.hasSuffix(".network-extension") {
id.removeLast(".network-extension".count) bundleIdentifier.removeLast(".network-extension".count)
} }
var items: [String: Any] = [kSecClass as String: kSecClassGenericPassword, let itemLabel = "WireGuard Tunnel: \(name)"
kSecAttrLabel as String: "WireGuard Tunnel: " + name, var items: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount as String: name + ": " + UUID().uuidString, kSecAttrLabel: itemLabel,
kSecAttrDescription as String: "wg-quick(8) config", kSecAttrAccount: name + ": " + UUID().uuidString,
kSecAttrService as String: id, kSecAttrDescription: "wg-quick(8) config",
kSecValueData as String: value.data(using: .utf8) as Any, kSecAttrService: bundleIdentifier,
kSecReturnPersistentRef as String: true] kSecValueData: value.data(using: .utf8) as Any,
kSecReturnPersistentRef: true]
#if os(iOS) #if os(iOS)
items[kSecAttrAccessGroup as String] = FileManager.appGroupId items[kSecAttrAccessGroup] = FileManager.appGroupId
items[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock items[kSecAttrAccessible] = kSecAttrAccessibleAfterFirstUnlock
#elseif os(macOS) #elseif os(macOS)
items[kSecAttrSynchronizable as String] = false items[kSecAttrSynchronizable] = false
items[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly items[kSecAttrAccessible] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
guard let extensionPath = Bundle.main.builtInPlugInsURL?.appendingPathComponent("WireGuardNetworkExtension.appex").path else { guard let extensionPath = Bundle.main.builtInPlugInsURL?.appendingPathComponent("WireGuardNetworkExtension.appex").path else {
wg_log(.error, staticMessage: "Unable to determine app extension path") wg_log(.error, staticMessage: "Unable to determine app extension path")
@@ -60,14 +61,12 @@ class Keychain {
return nil return nil
} }
var access: SecAccess? var access: SecAccess?
ret = SecAccessCreate((items[kSecAttrLabel as String] as? String)! as CFString, ret = SecAccessCreate(itemLabel as CFString, [extensionApp!, mainApp!] as CFArray, &access)
[extensionApp!, mainApp!] as CFArray,
&access)
if ret != errSecSuccess || access == nil { if ret != errSecSuccess || access == nil {
wg_log(.error, message: "Unable to create keychain ACL object: \(ret)") wg_log(.error, message: "Unable to create keychain ACL object: \(ret)")
return nil return nil
} }
items[kSecAttrAccess as String] = access! items[kSecAttrAccess] = access!
#else #else
#error("Unimplemented") #error("Unimplemented")
#endif #endif
@@ -85,7 +84,7 @@ class Keychain {
} }
static func deleteReference(called ref: Data) { static func deleteReference(called ref: Data) {
let ret = SecItemDelete([kSecValuePersistentRef as String: ref] as CFDictionary) let ret = SecItemDelete([kSecValuePersistentRef: ref] as CFDictionary)
if ret != errSecSuccess { if ret != errSecSuccess {
wg_log(.error, message: "Unable to delete config from keychain: \(ret)") wg_log(.error, message: "Unable to delete config from keychain: \(ret)")
} }
@@ -93,10 +92,10 @@ class Keychain {
static func deleteReferences(except whitelist: Set<Data>) { static func deleteReferences(except whitelist: Set<Data>) {
var result: CFTypeRef? var result: CFTypeRef?
let ret = SecItemCopyMatching([kSecClass as String: kSecClassGenericPassword, let ret = SecItemCopyMatching([kSecClass: kSecClassGenericPassword,
kSecAttrService as String: Bundle.main.bundleIdentifier as Any, kSecAttrService: Bundle.main.bundleIdentifier as Any,
kSecMatchLimit as String: kSecMatchLimitAll, kSecMatchLimit: kSecMatchLimitAll,
kSecReturnPersistentRef as String: true] as CFDictionary, kSecReturnPersistentRef: true] as CFDictionary,
&result) &result)
if ret != errSecSuccess || result == nil { if ret != errSecSuccess || result == nil {
return return
@@ -110,8 +109,8 @@ class Keychain {
} }
static func verifyReference(called ref: Data) -> Bool { static func verifyReference(called ref: Data) -> Bool {
return SecItemCopyMatching([kSecClass as String: kSecClassGenericPassword, return SecItemCopyMatching([kSecClass: kSecClassGenericPassword,
kSecValuePersistentRef as String: ref] as CFDictionary, kSecValuePersistentRef: ref] as CFDictionary,
nil) != errSecItemNotFound nil) != errSecItemNotFound
} }
} }
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
import os.log import os.log
@@ -49,8 +49,8 @@ public class Logger {
if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String { if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
appVersion += " (\(appBuild))" appVersion += " (\(appBuild))"
} }
let goBackendVersion = WIREGUARD_GO_VERSION
Logger.global?.log(message: "App version: \(appVersion); Go backend version: \(goBackendVersion)") Logger.global?.log(message: "App version: \(appVersion)")
} }
} }
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT /* SPDX-License-Identifier: MIT
* *
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. * Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
*/ */
#include <string.h> #include <string.h>
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT /* SPDX-License-Identifier: MIT
* *
* Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. * Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
*/ */
#ifndef RINGLOGGER_H #ifndef RINGLOGGER_H
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import NetworkExtension import NetworkExtension
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
@@ -111,7 +111,7 @@ extension TunnelConfiguration {
} }
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray) let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count { if peerPublicKeysArray.count != peerPublicKeysSet.count {
throw ParseError.multiplePeersWithSamePublicKey throw ParseError.multiplePeersWithSamePublicKey
} }
@@ -125,9 +125,7 @@ extension TunnelConfiguration {
func asWgQuickConfig() -> String { func asWgQuickConfig() -> String {
var output = "[Interface]\n" var output = "[Interface]\n"
if let privateKey = interface.privateKey.base64Key() { output.append("PrivateKey = \(interface.privateKey.base64Key)\n")
output.append("PrivateKey = \(privateKey)\n")
}
if let listenPort = interface.listenPort { if let listenPort = interface.listenPort {
output.append("ListenPort = \(listenPort)\n") output.append("ListenPort = \(listenPort)\n")
} }
@@ -135,8 +133,10 @@ extension TunnelConfiguration {
let addressString = interface.addresses.map { $0.stringRepresentation }.joined(separator: ", ") let addressString = interface.addresses.map { $0.stringRepresentation }.joined(separator: ", ")
output.append("Address = \(addressString)\n") output.append("Address = \(addressString)\n")
} }
if !interface.dns.isEmpty { if !interface.dns.isEmpty || !interface.dnsSearch.isEmpty {
let dnsString = interface.dns.map { $0.stringRepresentation }.joined(separator: ", ") var dnsLine = interface.dns.map { $0.stringRepresentation }
dnsLine.append(contentsOf: interface.dnsSearch)
let dnsString = dnsLine.joined(separator: ", ")
output.append("DNS = \(dnsString)\n") output.append("DNS = \(dnsString)\n")
} }
if let mtu = interface.mtu { if let mtu = interface.mtu {
@@ -145,10 +145,8 @@ extension TunnelConfiguration {
for peer in peers { for peer in peers {
output.append("\n[Peer]\n") output.append("\n[Peer]\n")
if let publicKey = peer.publicKey.base64Key() { output.append("PublicKey = \(peer.publicKey.base64Key)\n")
output.append("PublicKey = \(publicKey)\n") if let preSharedKey = peer.preSharedKey?.base64Key {
}
if let preSharedKey = peer.preSharedKey?.base64Key() {
output.append("PresharedKey = \(preSharedKey)\n") output.append("PresharedKey = \(preSharedKey)\n")
} }
if !peer.allowedIPs.isEmpty { if !peer.allowedIPs.isEmpty {
@@ -170,7 +168,7 @@ extension TunnelConfiguration {
guard let privateKeyString = attributes["privatekey"] else { guard let privateKeyString = attributes["privatekey"] else {
throw ParseError.interfaceHasNoPrivateKey throw ParseError.interfaceHasNoPrivateKey
} }
guard let privateKey = Data(base64Key: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else { guard let privateKey = PrivateKey(base64Key: privateKeyString) else {
throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString) throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString)
} }
var interface = InterfaceConfiguration(privateKey: privateKey) var interface = InterfaceConfiguration(privateKey: privateKey)
@@ -192,13 +190,16 @@ extension TunnelConfiguration {
} }
if let dnsString = attributes["dns"] { if let dnsString = attributes["dns"] {
var dnsServers = [DNSServer]() var dnsServers = [DNSServer]()
var dnsSearch = [String]()
for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) {
guard let dnsServer = DNSServer(from: dnsServerString) else { if let dnsServer = DNSServer(from: dnsServerString) {
throw ParseError.interfaceHasInvalidDNS(dnsServerString) dnsServers.append(dnsServer)
} else {
dnsSearch.append(dnsServerString)
} }
dnsServers.append(dnsServer)
} }
interface.dns = dnsServers interface.dns = dnsServers
interface.dnsSearch = dnsSearch
} }
if let mtuString = attributes["mtu"] { if let mtuString = attributes["mtu"] {
guard let mtu = UInt16(mtuString) else { guard let mtu = UInt16(mtuString) else {
@@ -213,12 +214,12 @@ extension TunnelConfiguration {
guard let publicKeyString = attributes["publickey"] else { guard let publicKeyString = attributes["publickey"] else {
throw ParseError.peerHasNoPublicKey throw ParseError.peerHasNoPublicKey
} }
guard let publicKey = Data(base64Key: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else { guard let publicKey = PublicKey(base64Key: publicKeyString) else {
throw ParseError.peerHasInvalidPublicKey(publicKeyString) throw ParseError.peerHasInvalidPublicKey(publicKeyString)
} }
var peer = PeerConfiguration(publicKey: publicKey) var peer = PeerConfiguration(publicKey: publicKey)
if let preSharedKeyString = attributes["presharedkey"] { if let preSharedKeyString = attributes["presharedkey"] {
guard let preSharedKey = Data(base64Key: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength else { guard let preSharedKey = PreSharedKey(base64Key: preSharedKeyString) else {
throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString) throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString)
} }
peer.preSharedKey = preSharedKey peer.preSharedKey = preSharedKey
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// iOS permission prompts // iOS permission prompts
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
// Generic alert action names // Generic alert action names
@@ -349,6 +349,8 @@
"macButtonDeleteTunnels (%d)" = "Delete %d tunnels"; "macButtonDeleteTunnels (%d)" = "Delete %d tunnels";
"macButtonEdit" = "Edit";
// Mac detail/edit view fields // Mac detail/edit view fields
"macFieldKey (%@)" = "%@:"; "macFieldKey (%@)" = "%@:";
@@ -0,0 +1,2 @@
VERSION_NAME = 1.0.10
VERSION_ID = 18
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation

Before

Width:  |  Height:  |  Size: 953 B

After

Width:  |  Height:  |  Size: 953 B

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import NetworkExtension import NetworkExtension
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import NetworkExtension import NetworkExtension
@@ -26,11 +26,11 @@ class MockTunnels {
static func createMockTunnels() -> [NETunnelProviderManager] { static func createMockTunnels() -> [NETunnelProviderManager] {
return tunnelNames.map { tunnelName -> NETunnelProviderManager in return tunnelNames.map { tunnelName -> NETunnelProviderManager in
var interface = InterfaceConfiguration(privateKey: Curve25519.generatePrivateKey()) var interface = InterfaceConfiguration(privateKey: PrivateKey())
interface.addresses = [IPAddressRange(from: String(format: address, Int.random(in: 1 ... 10), Int.random(in: 1 ... 254)))!] interface.addresses = [IPAddressRange(from: String(format: address, Int.random(in: 1 ... 10), Int.random(in: 1 ... 254)))!]
interface.dns = dnsServers.map { DNSServer(from: $0)! } interface.dns = dnsServers.map { DNSServer(from: $0)! }
var peer = PeerConfiguration(publicKey: Curve25519.generatePublicKey(fromPrivateKey: Curve25519.generatePrivateKey())) var peer = PeerConfiguration(publicKey: PrivateKey().publicKey)
peer.endpoint = Endpoint(from: endpoint) peer.endpoint = Endpoint(from: endpoint)
peer.allowedIPs = [IPAddressRange(from: allowedIPs)!] peer.allowedIPs = [IPAddressRange(from: allowedIPs)!]
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
@@ -67,13 +67,14 @@ extension TunnelConfiguration {
} }
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray) let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count { if peerPublicKeysArray.count != peerPublicKeysSet.count {
throw ParseError.multiplePeersWithSamePublicKey throw ParseError.multiplePeersWithSamePublicKey
} }
interfaceConfiguration?.addresses = base?.interface.addresses ?? [] interfaceConfiguration?.addresses = base?.interface.addresses ?? []
interfaceConfiguration?.dns = base?.interface.dns ?? [] interfaceConfiguration?.dns = base?.interface.dns ?? []
interfaceConfiguration?.dnsSearch = base?.interface.dnsSearch ?? []
interfaceConfiguration?.mtu = base?.interface.mtu interfaceConfiguration?.mtu = base?.interface.mtu
if let interfaceConfiguration = interfaceConfiguration { if let interfaceConfiguration = interfaceConfiguration {
@@ -87,7 +88,7 @@ extension TunnelConfiguration {
guard let privateKeyString = attributes["private_key"] else { guard let privateKeyString = attributes["private_key"] else {
throw ParseError.interfaceHasNoPrivateKey throw ParseError.interfaceHasNoPrivateKey
} }
guard let privateKey = Data(hexKey: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else { guard let privateKey = PrivateKey(hexKey: privateKeyString) else {
throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString) throw ParseError.interfaceHasInvalidPrivateKey(privateKeyString)
} }
var interface = InterfaceConfiguration(privateKey: privateKey) var interface = InterfaceConfiguration(privateKey: privateKey)
@@ -106,18 +107,18 @@ extension TunnelConfiguration {
guard let publicKeyString = attributes["public_key"] else { guard let publicKeyString = attributes["public_key"] else {
throw ParseError.peerHasNoPublicKey throw ParseError.peerHasNoPublicKey
} }
guard let publicKey = Data(hexKey: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else { guard let publicKey = PublicKey(hexKey: publicKeyString) else {
throw ParseError.peerHasInvalidPublicKey(publicKeyString) throw ParseError.peerHasInvalidPublicKey(publicKeyString)
} }
var peer = PeerConfiguration(publicKey: publicKey) var peer = PeerConfiguration(publicKey: publicKey)
if let preSharedKeyString = attributes["preshared_key"] { if let preSharedKeyString = attributes["preshared_key"] {
guard let preSharedKey = Data(hexKey: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength else { guard let preSharedKey = PreSharedKey(hexKey: preSharedKeyString) else {
throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString) throw ParseError.peerHasInvalidPreSharedKey(preSharedKeyString)
} }
// TODO(zx2c4): does the compiler optimize this away? // TODO(zx2c4): does the compiler optimize this away?
var accumulator: UInt8 = 0 var accumulator: UInt8 = 0
for index in 0..<preSharedKey.count { for index in 0..<preSharedKey.rawValue.count {
accumulator |= preSharedKey[index] accumulator |= preSharedKey.rawValue[index]
} }
if accumulator != 0 { if accumulator != 0 {
peer.preSharedKey = preSharedKey peer.preSharedKey = preSharedKey
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import NetworkExtension import NetworkExtension
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
import NetworkExtension import NetworkExtension
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
import NetworkExtension import NetworkExtension
@@ -449,8 +449,8 @@ class TunnelsManager {
} }
} }
static func tunnelNameIsLessThan(_ a: String, _ b: String) -> Bool { static func tunnelNameIsLessThan(_ lhs: String, _ rhs: String) -> Bool {
return a.compare(b, options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive, .numeric]) == .orderedAscending return lhs.compare(rhs, options: [.caseInsensitive, .diacriticInsensitive, .widthInsensitive, .numeric]) == .orderedAscending
} }
} }
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
protocol ErrorPresenterProtocol { protocol ErrorPresenterProtocol {
static func showErrorAlert(title: String, message: String, from sourceVC: AnyObject?, onPresented: (() -> Void)?, onDismissal: (() -> Void)?) static func showErrorAlert(title: String, message: String, from sourceVC: AnyObject?, onPresented: (() -> Void)?, onDismissal: (() -> Void)?)
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
import LocalAuthentication import LocalAuthentication
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
@@ -109,9 +109,9 @@ class TunnelViewModel {
scratchpad[field] = stringValue scratchpad[field] = stringValue
} }
if field == .privateKey { if field == .privateKey {
if stringValue.count == TunnelViewModel.keyLengthInBase64, let privateKey = Data(base64Key: stringValue), privateKey.count == TunnelConfiguration.keyLength { if stringValue.count == TunnelViewModel.keyLengthInBase64,
let publicKey = Curve25519.generatePublicKey(fromPrivateKey: privateKey).base64Key() ?? "" let privateKey = PrivateKey(base64Key: stringValue) {
scratchpad[.publicKey] = publicKey scratchpad[.publicKey] = privateKey.publicKey.base64Key
} else { } else {
scratchpad.removeValue(forKey: .publicKey) scratchpad.removeValue(forKey: .publicKey)
} }
@@ -128,8 +128,8 @@ class TunnelViewModel {
private static func createScratchPad(from config: InterfaceConfiguration, name: String) -> [InterfaceField: String] { private static func createScratchPad(from config: InterfaceConfiguration, name: String) -> [InterfaceField: String] {
var scratchpad = [InterfaceField: String]() var scratchpad = [InterfaceField: String]()
scratchpad[.name] = name scratchpad[.name] = name
scratchpad[.privateKey] = config.privateKey.base64Key() ?? "" scratchpad[.privateKey] = config.privateKey.base64Key
scratchpad[.publicKey] = config.publicKey.base64Key() ?? "" scratchpad[.publicKey] = config.privateKey.publicKey.base64Key
if !config.addresses.isEmpty { if !config.addresses.isEmpty {
scratchpad[.addresses] = config.addresses.map { $0.stringRepresentation }.joined(separator: ", ") scratchpad[.addresses] = config.addresses.map { $0.stringRepresentation }.joined(separator: ", ")
} }
@@ -139,8 +139,10 @@ class TunnelViewModel {
if let mtu = config.mtu { if let mtu = config.mtu {
scratchpad[.mtu] = String(mtu) scratchpad[.mtu] = String(mtu)
} }
if !config.dns.isEmpty { if !config.dns.isEmpty || !config.dnsSearch.isEmpty {
scratchpad[.dns] = config.dns.map { $0.stringRepresentation }.joined(separator: ", ") var dns = config.dns.map { $0.stringRepresentation }
dns.append(contentsOf: config.dnsSearch)
scratchpad[.dns] = dns.joined(separator: ", ")
} }
return scratchpad return scratchpad
} }
@@ -158,7 +160,7 @@ class TunnelViewModel {
fieldsWithError.insert(.privateKey) fieldsWithError.insert(.privateKey)
return .error(tr("alertInvalidInterfaceMessagePrivateKeyRequired")) return .error(tr("alertInvalidInterfaceMessagePrivateKeyRequired"))
} }
guard let privateKey = Data(base64Key: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else { guard let privateKey = PrivateKey(base64Key: privateKeyString) else {
fieldsWithError.insert(.privateKey) fieldsWithError.insert(.privateKey)
return .error(tr("alertInvalidInterfaceMessagePrivateKeyInvalid")) return .error(tr("alertInvalidInterfaceMessagePrivateKeyInvalid"))
} }
@@ -194,15 +196,16 @@ class TunnelViewModel {
} }
if let dnsString = scratchpad[.dns] { if let dnsString = scratchpad[.dns] {
var dnsServers = [DNSServer]() var dnsServers = [DNSServer]()
var dnsSearch = [String]()
for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) { for dnsServerString in dnsString.splitToArray(trimmingCharacters: .whitespacesAndNewlines) {
if let dnsServer = DNSServer(from: dnsServerString) { if let dnsServer = DNSServer(from: dnsServerString) {
dnsServers.append(dnsServer) dnsServers.append(dnsServer)
} else { } else {
fieldsWithError.insert(.dns) dnsSearch.append(dnsServerString)
errorMessages.append(tr("alertInvalidInterfaceMessageDNSInvalid"))
} }
} }
config.dns = dnsServers config.dns = dnsServers
config.dnsSearch = dnsSearch
} }
guard errorMessages.isEmpty else { return .error(errorMessages.first!) } guard errorMessages.isEmpty else { return .error(errorMessages.first!) }
@@ -251,12 +254,12 @@ class TunnelViewModel {
var scratchpad = [PeerField: String]() var scratchpad = [PeerField: String]()
var fieldsWithError = Set<PeerField>() var fieldsWithError = Set<PeerField>()
var validatedConfiguration: PeerConfiguration? var validatedConfiguration: PeerConfiguration?
var publicKey: Data? { var publicKey: PublicKey? {
if let validatedConfiguration = validatedConfiguration { if let validatedConfiguration = validatedConfiguration {
return validatedConfiguration.publicKey return validatedConfiguration.publicKey
} }
if let scratchPadPublicKey = scratchpad[.publicKey] { if let scratchPadPublicKey = scratchpad[.publicKey] {
return Data(base64Key: scratchPadPublicKey) return PublicKey(base64Key: scratchPadPublicKey)
} }
return nil return nil
} }
@@ -301,10 +304,8 @@ class TunnelViewModel {
private static func createScratchPad(from config: PeerConfiguration) -> [PeerField: String] { private static func createScratchPad(from config: PeerConfiguration) -> [PeerField: String] {
var scratchpad = [PeerField: String]() var scratchpad = [PeerField: String]()
if let publicKey = config.publicKey.base64Key() { scratchpad[.publicKey] = config.publicKey.base64Key
scratchpad[.publicKey] = publicKey if let preSharedKey = config.preSharedKey?.base64Key {
}
if let preSharedKey = config.preSharedKey?.base64Key() {
scratchpad[.preSharedKey] = preSharedKey scratchpad[.preSharedKey] = preSharedKey
} }
if !config.allowedIPs.isEmpty { if !config.allowedIPs.isEmpty {
@@ -337,14 +338,14 @@ class TunnelViewModel {
fieldsWithError.insert(.publicKey) fieldsWithError.insert(.publicKey)
return .error(tr("alertInvalidPeerMessagePublicKeyRequired")) return .error(tr("alertInvalidPeerMessagePublicKeyRequired"))
} }
guard let publicKey = Data(base64Key: publicKeyString), publicKey.count == TunnelConfiguration.keyLength else { guard let publicKey = PublicKey(base64Key: publicKeyString) else {
fieldsWithError.insert(.publicKey) fieldsWithError.insert(.publicKey)
return .error(tr("alertInvalidPeerMessagePublicKeyInvalid")) return .error(tr("alertInvalidPeerMessagePublicKeyInvalid"))
} }
var config = PeerConfiguration(publicKey: publicKey) var config = PeerConfiguration(publicKey: publicKey)
var errorMessages = [String]() var errorMessages = [String]()
if let preSharedKeyString = scratchpad[.preSharedKey] { if let preSharedKeyString = scratchpad[.preSharedKey] {
if let preSharedKey = Data(base64Key: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength { if let preSharedKey = PreSharedKey(base64Key: preSharedKeyString) {
config.preSharedKey = preSharedKey config.preSharedKey = preSharedKey
} else { } else {
fieldsWithError.insert(.preSharedKey) fieldsWithError.insert(.preSharedKey)
@@ -559,7 +560,7 @@ class TunnelViewModel {
} }
let peerPublicKeysArray = peerConfigurations.map { $0.publicKey } let peerPublicKeysArray = peerConfigurations.map { $0.publicKey }
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray) let peerPublicKeysSet = Set<PublicKey>(peerPublicKeysArray)
if peerPublicKeysArray.count != peerPublicKeysSet.count { if peerPublicKeysArray.count != peerPublicKeysSet.count {
return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated")) return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated"))
} }
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
import os.log import os.log
@@ -21,7 +21,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
} }
let window = UIWindow(frame: UIScreen.main.bounds) let window = UIWindow(frame: UIScreen.main.bounds)
window.backgroundColor = .white
self.window = window self.window = window
let mainVC = MainViewController() let mainVC = MainViewController()
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
import os.log import os.log
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Foundation import Foundation
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,20 +1,20 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
class TunnelListCell: UITableViewCell { class TunnelListCell: UITableViewCell {
var tunnel: TunnelContainer? { var tunnel: TunnelContainer? {
didSet(value) { didSet {
// Bind to the tunnel's name // Bind to the tunnel's name
nameLabel.text = tunnel?.name ?? "" nameLabel.text = tunnel?.name ?? ""
nameObservationToken = tunnel?.observe(\.name) { [weak self] tunnel, _ in nameObservationToken = tunnel?.observe(\.name) { [weak self] tunnel, _ in
self?.nameLabel.text = tunnel.name self?.nameLabel.text = tunnel.name
} }
// Bind to the tunnel's status // Bind to the tunnel's status
update(from: tunnel?.status) update(from: tunnel?.status, animated: false)
statusObservationToken = tunnel?.observe(\.status) { [weak self] tunnel, _ in statusObservationToken = tunnel?.observe(\.status) { [weak self] tunnel, _ in
self?.update(from: tunnel.status) self?.update(from: tunnel.status, animated: true)
} }
} }
} }
@@ -29,94 +29,88 @@ class TunnelListCell: UITableViewCell {
}() }()
let busyIndicator: UIActivityIndicatorView = { let busyIndicator: UIActivityIndicatorView = {
let busyIndicator: UIActivityIndicatorView
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
let busyIndicator = UIActivityIndicatorView(style: .medium) busyIndicator = UIActivityIndicatorView(style: .medium)
busyIndicator.hidesWhenStopped = true
return busyIndicator
} else { } else {
let busyIndicator = UIActivityIndicatorView(style: .gray) busyIndicator = UIActivityIndicatorView(style: .gray)
busyIndicator.hidesWhenStopped = true
return busyIndicator
} }
busyIndicator.hidesWhenStopped = true
return busyIndicator
}() }()
let statusSwitch = UISwitch() let statusSwitch = UISwitch()
private var statusObservationToken: AnyObject? private var statusObservationToken: NSKeyValueObservation?
private var nameObservationToken: AnyObject? private var nameObservationToken: NSKeyValueObservation?
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(statusSwitch) accessoryType = .disclosureIndicator
statusSwitch.translatesAutoresizingMaskIntoConstraints = false
for subview in [statusSwitch, busyIndicator, nameLabel] {
subview.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(subview)
}
nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
let nameLabelBottomConstraint =
contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: nameLabel.bottomAnchor, multiplier: 1)
nameLabelBottomConstraint.priority = .defaultLow
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
statusSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), statusSwitch.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
contentView.trailingAnchor.constraint(equalTo: statusSwitch.trailingAnchor) statusSwitch.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor),
]) statusSwitch.leadingAnchor.constraint(equalToSystemSpacingAfter: busyIndicator.trailingAnchor, multiplier: 1),
contentView.addSubview(busyIndicator)
busyIndicator.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
busyIndicator.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
statusSwitch.leadingAnchor.constraint(equalToSystemSpacingAfter: busyIndicator.trailingAnchor, multiplier: 1)
])
contentView.addSubview(nameLabel)
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
let bottomAnchorConstraint = contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: nameLabel.bottomAnchor, multiplier: 1)
bottomAnchorConstraint.priority = .defaultLow
NSLayoutConstraint.activate([
nameLabel.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 1), nameLabel.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 1),
nameLabelBottomConstraint,
nameLabel.leadingAnchor.constraint(equalToSystemSpacingAfter: contentView.layoutMarginsGuide.leadingAnchor, multiplier: 1), nameLabel.leadingAnchor.constraint(equalToSystemSpacingAfter: contentView.layoutMarginsGuide.leadingAnchor, multiplier: 1),
busyIndicator.leadingAnchor.constraint(equalToSystemSpacingAfter: nameLabel.trailingAnchor, multiplier: 1),
bottomAnchorConstraint
])
accessoryType = .disclosureIndicator busyIndicator.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
busyIndicator.leadingAnchor.constraint(equalToSystemSpacingAfter: nameLabel.trailingAnchor, multiplier: 1)
])
statusSwitch.addTarget(self, action: #selector(switchToggled), for: .valueChanged) statusSwitch.addTarget(self, action: #selector(switchToggled), for: .valueChanged)
} }
@objc func switchToggled() {
onSwitchToggled?(statusSwitch.isOn)
}
private func update(from status: TunnelStatus?) {
guard let status = status else {
reset()
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { [weak statusSwitch, weak busyIndicator] in
guard let statusSwitch = statusSwitch, let busyIndicator = busyIndicator else { return }
statusSwitch.isOn = !(status == .deactivating || status == .inactive)
statusSwitch.isUserInteractionEnabled = (status == .inactive || status == .active)
if status == .inactive || status == .active {
busyIndicator.stopAnimating()
} else {
busyIndicator.startAnimating()
}
}
}
required init?(coder aDecoder: NSCoder) { required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func prepareForReuse() {
super.prepareForReuse()
reset(animated: false)
}
override func setEditing(_ editing: Bool, animated: Bool) { override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated) super.setEditing(editing, animated: animated)
statusSwitch.isEnabled = !editing statusSwitch.isEnabled = !editing
} }
private func reset() { @objc private func switchToggled() {
statusSwitch.isOn = false onSwitchToggled?(statusSwitch.isOn)
}
private func update(from status: TunnelStatus?, animated: Bool) {
guard let status = status else {
reset(animated: animated)
return
}
statusSwitch.setOn(!(status == .deactivating || status == .inactive), animated: animated)
statusSwitch.isUserInteractionEnabled = (status == .inactive || status == .active)
if status == .inactive || status == .active {
busyIndicator.stopAnimating()
} else {
busyIndicator.startAnimating()
}
}
private func reset(animated: Bool) {
statusSwitch.setOn(false, animated: animated)
statusSwitch.isUserInteractionEnabled = false statusSwitch.isUserInteractionEnabled = false
busyIndicator.stopAnimating() busyIndicator.stopAnimating()
} }
override func prepareForReuse() {
super.prepareForReuse()
reset()
}
} }
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -41,7 +41,11 @@ class LogViewController: UIViewController {
override func loadView() { override func loadView() {
view = UIView() view = UIView()
view.backgroundColor = .white if #available(iOS 13.0, *) {
view.backgroundColor = .systemBackground
} else {
view.backgroundColor = .white
}
view.addSubview(textView) view.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false textView.translatesAutoresizingMaskIntoConstraints = false
@@ -87,12 +91,18 @@ class LogViewController: UIViewController {
let richText = NSMutableAttributedString() let richText = NSMutableAttributedString()
let bodyFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body) let bodyFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
let captionFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.caption1) let captionFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.caption1)
let lightGrayColor = UIColor(white: 0.88, alpha: 1.0)
for logEntry in fetchedLogEntries { for logEntry in fetchedLogEntries {
let bgColor = self.isNextLineHighlighted ? lightGrayColor : UIColor.white var bgColor: UIColor
let timestampText = NSAttributedString(string: logEntry.timestamp + "\n", attributes: [.font: captionFont, .backgroundColor: bgColor, .paragraphStyle: self.paragraphStyle]) var fgColor: UIColor
let messageText = NSAttributedString(string: logEntry.message + "\n", attributes: [.font: bodyFont, .backgroundColor: bgColor, .paragraphStyle: self.paragraphStyle]) if #available(iOS 13.0, *) {
bgColor = self.isNextLineHighlighted ? .systemGray3 : .systemBackground
fgColor = .label
} else {
bgColor = self.isNextLineHighlighted ? UIColor(white: 0.88, alpha: 1.0) : UIColor.white
fgColor = .black
}
let timestampText = NSAttributedString(string: logEntry.timestamp + "\n", attributes: [.font: captionFont, .backgroundColor: bgColor, .foregroundColor: fgColor, .paragraphStyle: self.paragraphStyle])
let messageText = NSAttributedString(string: logEntry.message + "\n", attributes: [.font: bodyFont, .backgroundColor: bgColor, .foregroundColor: fgColor, .paragraphStyle: self.paragraphStyle])
richText.append(timestampText) richText.append(timestampText)
richText.append(messageText) richText.append(messageText)
self.isNextLineHighlighted.toggle() self.isNextLineHighlighted.toggle()
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -11,7 +11,11 @@ class MainViewController: UISplitViewController {
init() { init() {
let detailVC = UIViewController() let detailVC = UIViewController()
detailVC.view.backgroundColor = .white if #available(iOS 13.0, *) {
detailVC.view.backgroundColor = .systemBackground
} else {
detailVC.view.backgroundColor = .white
}
let detailNC = UINavigationController(rootViewController: detailVC) let detailNC = UINavigationController(rootViewController: detailVC)
let masterVC = TunnelsListTableViewController() let masterVC = TunnelsListTableViewController()
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import AVFoundation import AVFoundation
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
import SystemConfiguration.CaptiveNetwork import SystemConfiguration.CaptiveNetwork
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
import os.log import os.log
@@ -146,8 +146,8 @@ extension SettingsTableViewController {
cell.copyableGesture = false cell.copyableGesture = false
cell.key = field.localizedUIString cell.key = field.localizedUIString
if field == .iosAppVersion { if field == .iosAppVersion {
var appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown version" var appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "Unknown version"
if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String { if let appBuild = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String {
appVersion += " (\(appBuild))" appVersion += " (\(appBuild))"
} }
cell.value = appVersion cell.value = appVersion
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -152,8 +152,8 @@ class TunnelDetailTableViewController: UITableViewController {
} }
}! }!
let firstPeerSectionIndex = interfaceSectionIndex + 1 let firstPeerSectionIndex = interfaceSectionIndex + 1
var interfaceFieldIsVisible = self.interfaceFieldIsVisible let interfaceFieldIsVisible = self.interfaceFieldIsVisible
var peerFieldIsVisible = self.peerFieldIsVisible let peerFieldIsVisible = self.peerFieldIsVisible
func handleSectionFieldsModified<T>(fields: [T], fieldIsVisible: [Bool], section: Int, changes: [T: TunnelViewModel.Changes.FieldChange]) { func handleSectionFieldsModified<T>(fields: [T], fieldIsVisible: [Bool], section: Int, changes: [T: TunnelViewModel.Changes.FieldChange]) {
for (index, field) in fields.enumerated() { for (index, field) in fields.enumerated() {
@@ -343,10 +343,8 @@ extension TunnelDetailTableViewController {
text = tr("tunnelStatusWaiting") text = tr("tunnelStatusWaiting")
} }
cell.textLabel?.text = text cell.textLabel?.text = text
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { [weak cell] in cell.switchView.isOn = !(status == .deactivating || status == .inactive)
cell?.switchView.isOn = !(status == .deactivating || status == .inactive) cell.switchView.isUserInteractionEnabled = (status == .inactive || status == .active)
cell?.switchView.isUserInteractionEnabled = (status == .inactive || status == .active)
}
cell.isEnabled = status == .active || status == .inactive cell.isEnabled = status == .active || status == .inactive
} }
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
@@ -214,7 +214,7 @@ extension TunnelEditTableViewController {
cell.onTapped = { [weak self] in cell.onTapped = { [weak self] in
guard let self = self else { return } guard let self = self else { return }
self.tunnelViewModel.interfaceData[.privateKey] = Curve25519.generatePrivateKey().base64Key() ?? "" self.tunnelViewModel.interfaceData[.privateKey] = PrivateKey().base64Key
if let privateKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .privateKey), if let privateKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .privateKey),
let publicKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .publicKey) { let publicKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .publicKey) {
let privateKeyIndex = IndexPath(row: privateKeyRow, section: indexPath.section) let privateKeyIndex = IndexPath(row: privateKeyRow, section: indexPath.section)
@@ -266,7 +266,7 @@ extension TunnelEditTableViewController {
guard let self = self else { return } guard let self = self else { return }
let isAllowedIPsChanged = self.tunnelViewModel.updateDNSServersInAllowedIPsIfRequired(oldDNSServers: oldValue, newDNSServers: newValue) let isAllowedIPsChanged = self.tunnelViewModel.updateDNSServersInAllowedIPsIfRequired(oldDNSServers: oldValue, newDNSServers: newValue)
if isAllowedIPsChanged { if isAllowedIPsChanged {
let section = self.sections.firstIndex { if case .peer(_) = $0 { return true } else { return false } } let section = self.sections.firstIndex { if case .peer = $0 { return true } else { return false } }
if let section = section, let row = self.peerFields.firstIndex(of: .allowedIPs) { if let section = section, let row = self.peerFields.firstIndex(of: .allowedIPs) {
self.tableView.reloadRows(at: [IndexPath(row: row, section: section)], with: .none) self.tableView.reloadRows(at: [IndexPath(row: row, section: section)], with: .none)
} }
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import UIKit import UIKit
import MobileCoreServices import MobileCoreServices
@@ -32,15 +32,14 @@ class TunnelsListTableViewController: UIViewController {
}() }()
let busyIndicator: UIActivityIndicatorView = { let busyIndicator: UIActivityIndicatorView = {
let busyIndicator: UIActivityIndicatorView
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
let busyIndicator = UIActivityIndicatorView(style: .medium) busyIndicator = UIActivityIndicatorView(style: .medium)
busyIndicator.hidesWhenStopped = true
return busyIndicator
} else { } else {
let busyIndicator = UIActivityIndicatorView(style: .gray) busyIndicator = UIActivityIndicatorView(style: .gray)
busyIndicator.hidesWhenStopped = true
return busyIndicator
} }
busyIndicator.hidesWhenStopped = true
return busyIndicator
}() }()
var detailDisplayedTunnel: TunnelContainer? var detailDisplayedTunnel: TunnelContainer?
@@ -52,7 +51,11 @@ class TunnelsListTableViewController: UIViewController {
override func loadView() { override func loadView() {
view = UIView() view = UIView()
view.backgroundColor = .white if #available(iOS 13.0, *) {
view.backgroundColor = .systemBackground
} else {
view.backgroundColor = .white
}
tableView.dataSource = self tableView.dataSource = self
tableView.delegate = self tableView.delegate = self
@@ -395,7 +398,11 @@ extension TunnelsListTableViewController: TunnelsManagerListDelegate {
(splitViewController.viewControllers[0] as? UINavigationController)?.popToRootViewController(animated: false) (splitViewController.viewControllers[0] as? UINavigationController)?.popToRootViewController(animated: false)
} else { } else {
let detailVC = UIViewController() let detailVC = UIViewController()
detailVC.view.backgroundColor = .white if #available(iOS 13.0, *) {
detailVC.view.backgroundColor = .systemBackground
} else {
detailVC.view.backgroundColor = .white
}
let detailNC = UINavigationController(rootViewController: detailVC) let detailNC = UINavigationController(rootViewController: detailVC)
splitViewController.showDetailViewController(detailNC, sender: self) splitViewController.showDetailViewController(detailNC, sender: self)
} }
@@ -408,12 +415,12 @@ extension TunnelsListTableViewController: TunnelsManagerListDelegate {
} }
extension UISplitViewController { extension UISplitViewController {
func showDetailViewController(_ vc: UIViewController, sender: Any?, animated: Bool) { func showDetailViewController(_ viewController: UIViewController, sender: Any?, animated: Bool) {
if animated { if animated {
showDetailViewController(vc, sender: sender) showDetailViewController(viewController, sender: sender)
} else { } else {
UIView.performWithoutAnimation { UIView.performWithoutAnimation {
showDetailViewController(vc, sender: sender) showDetailViewController(viewController, sender: sender)
} }
} }
} }
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Cocoa import Cocoa
import ServiceManagement import ServiceManagement
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved. // Copyright © 2018-2020 WireGuard LLC. All Rights Reserved.
import Cocoa import Cocoa

Some files were not shown because too many files have changed in this diff Show More