From 7701efc70413ef02f14584b41d6b431df6aa6298 Mon Sep 17 00:00:00 2001 From: pokamest Date: Sat, 23 Oct 2021 04:26:47 -0700 Subject: [PATCH] iOS Wireguard --- .gitmodules | 3 + client/3rd/wireguard-apple | 1 + client/client.pro | 52 ++ client/constants.h | 127 ++++ .../ios/app/AmneziaVPNLaunchScreen.storyboard | 43 ++ .../AppIcon.appiconset/Contents.json | 116 ++++ .../AppIcon.appiconset/icon-ios-1024@1x.png | Bin 0 -> 22976 bytes .../AppIcon.appiconset/icon-ios-20@1x.png | Bin 0 -> 407 bytes .../AppIcon.appiconset/icon-ios-20@2x-1.png | Bin 0 -> 721 bytes .../AppIcon.appiconset/icon-ios-20@2x.png | Bin 0 -> 721 bytes .../AppIcon.appiconset/icon-ios-20@3x.png | Bin 0 -> 1084 bytes .../AppIcon.appiconset/icon-ios-29@1x.png | Bin 0 -> 596 bytes .../AppIcon.appiconset/icon-ios-29@2x-1.png | Bin 0 -> 975 bytes .../AppIcon.appiconset/icon-ios-29@2x.png | Bin 0 -> 975 bytes .../AppIcon.appiconset/icon-ios-29@3x.png | Bin 0 -> 1343 bytes .../AppIcon.appiconset/icon-ios-40@1x.png | Bin 0 -> 744 bytes .../AppIcon.appiconset/icon-ios-40@2x-1.png | Bin 0 -> 1268 bytes .../AppIcon.appiconset/icon-ios-40@2x.png | Bin 0 -> 1268 bytes .../AppIcon.appiconset/icon-ios-40@3x.png | Bin 0 -> 1645 bytes .../AppIcon.appiconset/icon-ios-60@2x.png | Bin 0 -> 1645 bytes .../AppIcon.appiconset/icon-ios-60@3x.png | Bin 0 -> 3101 bytes .../AppIcon.appiconset/icon-ios-76@1x.png | Bin 0 -> 1238 bytes .../AppIcon.appiconset/icon-ios-76@2x.png | Bin 0 -> 2636 bytes .../AppIcon.appiconset/icon-ios-83.5@2x.png | Bin 0 -> 2769 bytes client/ios/app/Images.xcassets/Contents.json | 6 + client/ios/app/Info.plist | 55 ++ client/ios/app/launch.png | Bin 0 -> 12825 bytes client/ios/app/main.entitlements | 16 + .../AmneziaVPNNetworkExtension.entitlements | 14 + client/ios/xcode.xconfig | 13 + client/ios/xcode_patcher.rb | 598 ++++++++++++++++++ client/logger.cpp | 59 ++ client/logger.h | 88 +++ client/loghandler.cpp | 346 ++++++++++ client/loghandler.h | 102 +++ client/loglevel.h | 15 + .../AppIcon.appiconset/128.png | Bin 0 -> 2591 bytes .../AppIcon.appiconset/128@2x.png | Bin 0 -> 5317 bytes .../AppIcon.appiconset/16.png | Bin 0 -> 361 bytes .../AppIcon.appiconset/16@2x.png | Bin 0 -> 623 bytes .../AppIcon.appiconset/256.png | Bin 0 -> 5329 bytes .../AppIcon.appiconset/256@2x.png | Bin 0 -> 11796 bytes .../AppIcon.appiconset/32.png | Bin 0 -> 623 bytes .../AppIcon.appiconset/32@2x.png | Bin 0 -> 1132 bytes .../AppIcon.appiconset/512.png | Bin 0 -> 11819 bytes .../AppIcon.appiconset/512@2x.png | Bin 0 -> 26137 bytes .../AppIcon.appiconset/128.png | Bin 0 -> 1922 bytes .../AppIcon.appiconset/128@2x.png | Bin 0 -> 4593 bytes .../Images.xcassets/AppIcon.appiconset/16.png | Bin 0 -> 336 bytes .../AppIcon.appiconset/16@2x.png | Bin 0 -> 593 bytes .../AppIcon.appiconset/256.png | Bin 0 -> 4611 bytes .../AppIcon.appiconset/256@2x.png | Bin 0 -> 11015 bytes .../Images.xcassets/AppIcon.appiconset/32.png | Bin 0 -> 593 bytes .../AppIcon.appiconset/32@2x.png | Bin 0 -> 1097 bytes .../AppIcon.appiconset/512.png | Bin 0 -> 10991 bytes .../AppIcon.appiconset/512@2x.png | Bin 0 -> 24361 bytes .../AppIcon.appiconset/Contents.json | 68 ++ .../macos/app/Images.xcassets/Contents.json | 6 + client/macos/app/Info.plist | 50 ++ client/macos/app/WireGuard-Bridging-Header.h | 29 + client/macos/app/app.entitlements | 35 + client/macos/app/daemon.entitlements | 27 + client/macos/gobridge/.gitignore | 3 + client/macos/gobridge/api.go | 225 +++++++ client/macos/gobridge/dummy.c | 1 + client/macos/gobridge/go.mod | 8 + client/macos/gobridge/go.sum | 19 + .../goruntime-boottime-over-monotonic.diff | 61 ++ client/macos/gobridge/module.modulemap | 5 + client/macos/gobridge/wireguard-go-version.h | 1 + client/macos/gobridge/wireguard.h | 23 + .../AmneziaVPNNativeMessaging.entitlements | 10 + client/macos/nativemessaging/Info.plist | 30 + .../AmneziaVPNNetworkExtension.entitlements | 38 ++ client/macos/networkextension/Info.plist | 52 ++ ...ireGuardNetworkExtension-Bridging-Header.h | 25 + client/platforms/ios/iosadjusthelper.h | 16 + client/platforms/ios/iosadjusthelper.mm | 37 ++ .../platforms/ios/iosauthenticationlistener.h | 23 + .../ios/iosauthenticationlistener.mm | 139 ++++ client/platforms/ios/ioscontroller.h | 39 ++ client/platforms/ios/ioscontroller.mm | 240 +++++++ client/platforms/ios/ioscontroller.swift | 289 +++++++++ client/platforms/ios/iosdatamigration.h | 15 + client/platforms/ios/iosdatamigration.mm | 172 +++++ client/platforms/ios/iosglue.mm | 249 ++++++++ client/platforms/ios/iosiaphandler.h | 30 + client/platforms/ios/iosiaphandler.mm | 369 +++++++++++ client/platforms/ios/ioslogger.swift | 53 ++ client/platforms/ios/iosnotificationhandler.h | 27 + .../platforms/ios/iosnotificationhandler.mm | 87 +++ client/platforms/ios/iostunnel.swift | 147 +++++ client/platforms/ios/iosutils.h | 17 + client/platforms/ios/iosutils.mm | 63 ++ .../platforms/macos/daemon/dnsutilsmacos.cpp | 222 +++++++ client/platforms/macos/daemon/dnsutilsmacos.h | 51 ++ .../platforms/macos/daemon/iputilsmacos.cpp | 180 ++++++ client/platforms/macos/daemon/iputilsmacos.h | 28 + client/platforms/macos/daemon/macosdaemon.cpp | 74 +++ client/platforms/macos/daemon/macosdaemon.h | 37 ++ .../macos/daemon/macosdaemonserver.cpp | 60 ++ .../macos/daemon/macosdaemonserver.h | 18 + .../macos/daemon/macosroutemonitor.cpp | 354 +++++++++++ .../macos/daemon/macosroutemonitor.h | 54 ++ .../macos/daemon/wireguardutilsmacos.cpp | 309 +++++++++ .../macos/daemon/wireguardutilsmacos.h | 52 ++ client/platforms/macos/macoscryptosettings.mm | 136 ++++ client/platforms/macos/macosmenubar.cpp | 106 ++++ client/platforms/macos/macosmenubar.h | 42 ++ client/platforms/macos/macosnetworkwatcher.h | 25 + client/platforms/macos/macosnetworkwatcher.mm | 131 ++++ client/platforms/macos/macospingsender.cpp | 122 ++++ client/platforms/macos/macospingsender.h | 30 + .../macos/macosstartatbootwatcher.cpp | 28 + .../platforms/macos/macosstartatbootwatcher.h | 22 + client/platforms/macos/macosutils.h | 23 + client/platforms/macos/macosutils.mm | 91 +++ 117 files changed, 6577 insertions(+) create mode 160000 client/3rd/wireguard-apple create mode 100644 client/constants.h create mode 100644 client/ios/app/AmneziaVPNLaunchScreen.storyboard create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-1024@1x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@1x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@2x-1.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@2x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@3x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@1x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@2x-1.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@2x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@3x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@1x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@2x-1.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@2x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@3x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-60@2x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-60@3x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-76@1x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-76@2x.png create mode 100644 client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-83.5@2x.png create mode 100644 client/ios/app/Images.xcassets/Contents.json create mode 100644 client/ios/app/Info.plist create mode 100644 client/ios/app/launch.png create mode 100644 client/ios/app/main.entitlements create mode 100644 client/ios/networkextension/AmneziaVPNNetworkExtension.entitlements create mode 100644 client/ios/xcode.xconfig create mode 100644 client/ios/xcode_patcher.rb create mode 100644 client/logger.cpp create mode 100644 client/logger.h create mode 100644 client/loghandler.cpp create mode 100644 client/loghandler.h create mode 100644 client/loglevel.h create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/128.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/128@2x.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/16.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/16@2x.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/256.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/256@2x.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/32.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/32@2x.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/512.png create mode 100644 client/macos/app/Images-beta.xcassets/AppIcon.appiconset/512@2x.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/128.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/128@2x.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/16.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/16@2x.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/256.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/256@2x.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/32.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/32@2x.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/512.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/512@2x.png create mode 100644 client/macos/app/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 client/macos/app/Images.xcassets/Contents.json create mode 100644 client/macos/app/Info.plist create mode 100644 client/macos/app/WireGuard-Bridging-Header.h create mode 100644 client/macos/app/app.entitlements create mode 100644 client/macos/app/daemon.entitlements create mode 100644 client/macos/gobridge/.gitignore create mode 100755 client/macos/gobridge/api.go create mode 100755 client/macos/gobridge/dummy.c create mode 100755 client/macos/gobridge/go.mod create mode 100755 client/macos/gobridge/go.sum create mode 100755 client/macos/gobridge/goruntime-boottime-over-monotonic.diff create mode 100755 client/macos/gobridge/module.modulemap create mode 100755 client/macos/gobridge/wireguard-go-version.h create mode 100755 client/macos/gobridge/wireguard.h create mode 100644 client/macos/nativemessaging/AmneziaVPNNativeMessaging.entitlements create mode 100644 client/macos/nativemessaging/Info.plist create mode 100644 client/macos/networkextension/AmneziaVPNNetworkExtension.entitlements create mode 100644 client/macos/networkextension/Info.plist create mode 100644 client/macos/networkextension/WireGuardNetworkExtension-Bridging-Header.h create mode 100644 client/platforms/ios/iosadjusthelper.h create mode 100644 client/platforms/ios/iosadjusthelper.mm create mode 100644 client/platforms/ios/iosauthenticationlistener.h create mode 100644 client/platforms/ios/iosauthenticationlistener.mm create mode 100644 client/platforms/ios/ioscontroller.h create mode 100644 client/platforms/ios/ioscontroller.mm create mode 100644 client/platforms/ios/ioscontroller.swift create mode 100644 client/platforms/ios/iosdatamigration.h create mode 100644 client/platforms/ios/iosdatamigration.mm create mode 100644 client/platforms/ios/iosglue.mm create mode 100644 client/platforms/ios/iosiaphandler.h create mode 100644 client/platforms/ios/iosiaphandler.mm create mode 100644 client/platforms/ios/ioslogger.swift create mode 100644 client/platforms/ios/iosnotificationhandler.h create mode 100644 client/platforms/ios/iosnotificationhandler.mm create mode 100644 client/platforms/ios/iostunnel.swift create mode 100644 client/platforms/ios/iosutils.h create mode 100644 client/platforms/ios/iosutils.mm create mode 100644 client/platforms/macos/daemon/dnsutilsmacos.cpp create mode 100644 client/platforms/macos/daemon/dnsutilsmacos.h create mode 100644 client/platforms/macos/daemon/iputilsmacos.cpp create mode 100644 client/platforms/macos/daemon/iputilsmacos.h create mode 100644 client/platforms/macos/daemon/macosdaemon.cpp create mode 100644 client/platforms/macos/daemon/macosdaemon.h create mode 100644 client/platforms/macos/daemon/macosdaemonserver.cpp create mode 100644 client/platforms/macos/daemon/macosdaemonserver.h create mode 100644 client/platforms/macos/daemon/macosroutemonitor.cpp create mode 100644 client/platforms/macos/daemon/macosroutemonitor.h create mode 100644 client/platforms/macos/daemon/wireguardutilsmacos.cpp create mode 100644 client/platforms/macos/daemon/wireguardutilsmacos.h create mode 100644 client/platforms/macos/macoscryptosettings.mm create mode 100644 client/platforms/macos/macosmenubar.cpp create mode 100644 client/platforms/macos/macosmenubar.h create mode 100644 client/platforms/macos/macosnetworkwatcher.h create mode 100644 client/platforms/macos/macosnetworkwatcher.mm create mode 100644 client/platforms/macos/macospingsender.cpp create mode 100644 client/platforms/macos/macospingsender.h create mode 100644 client/platforms/macos/macosstartatbootwatcher.cpp create mode 100644 client/platforms/macos/macosstartatbootwatcher.h create mode 100644 client/platforms/macos/macosutils.h create mode 100644 client/platforms/macos/macosutils.mm diff --git a/.gitmodules b/.gitmodules index 0f203480..30d8d61d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "client/3rd/wireguard-tools"] path = client/3rd/wireguard-tools url = https://github.com/WireGuard/wireguard-tools/ +[submodule "client/3rd/wireguard-apple"] + path = client/3rd/wireguard-apple + url = https://github.com/WireGuard/wireguard-apple diff --git a/client/3rd/wireguard-apple b/client/3rd/wireguard-apple new file mode 160000 index 00000000..23618f99 --- /dev/null +++ b/client/3rd/wireguard-apple @@ -0,0 +1 @@ +Subproject commit 23618f994f17d8ad8f2f65d79b4a1e8a0830b334 diff --git a/client/client.pro b/client/client.pro index 90381c78..3f9bcc51 100644 --- a/client/client.pro +++ b/client/client.pro @@ -68,6 +68,10 @@ HEADERS += \ utils.h \ vpnconnection.h \ protocols/vpnprotocol.h \ + logger.h \ + loghandler.h \ + loglevel.h \ + constants.h SOURCES += \ configurators/cloak_configurator.cpp \ @@ -116,6 +120,9 @@ SOURCES += \ utils.cpp \ vpnconnection.cpp \ protocols/vpnprotocol.cpp \ + logger.cpp \ + loghandler.cpp + RESOURCES += \ resources.qrc @@ -238,6 +245,42 @@ android { ios { message("Client ios build") CONFIG += static + CONFIG += file_copies + + # For the authentication + LIBS += -framework AuthenticationServices + + # For notifications + LIBS += -framework UIKit + LIBS += -framework Foundation + LIBS += -framework StoreKit + LIBS += -framework UserNotifications + + DEFINES += MVPN_IOS + + SOURCES += \ +# platforms/macos/macospingsender.cpp + + OBJECTIVE_SOURCES += \ +# platforms/ios/iosiaphandler.mm \ +# platforms/ios/iosauthenticationlistener.mm \ +# platforms/ios/ioscontroller.mm \ +# platforms/ios/iosdatamigration.mm \ + platforms/ios/iosglue.mm \ +# platforms/ios/iosnotificationhandler.mm \ +# platforms/ios/iosutils.mm \ +# platforms/macos/macoscryptosettings.mm + + HEADERS += \ +# platforms/macos/macospingsender.h + + OBJECTIVE_HEADERS += \ +# platforms/ios/iosiaphandler.h \ +# platforms/ios/iosauthenticationlistener.h \ +# platforms/ios/ioscontroller.h \ +# platforms/ios/iosdatamigration.h \ +# platforms/ios/iosnotificationhandler.h \ +# platforms/ios/iosutils.h Q_ENABLE_BITCODE.value = NO Q_ENABLE_BITCODE.name = ENABLE_BITCODE @@ -278,6 +321,15 @@ ios { LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libcrypto.a LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libssl.a } + + NETWORKEXTENSION=1 + ! build_pass: system(ruby $$PWD/ios/xcode_patcher.rb "$$PWD" "$$OUT_PWD/AmneziaVPN.xcodeproj" "2.0" "2.0.0" "ios" "$$NETWORKEXTENSION"|| echo "Failed to merge xcode with wireguard") + + + +#ruby %{sourceDir}/client/ios/xcode_patcher.rb "%{buildDir}/AmneziaVPN.xcodeproj" "2.0" "2.0.0" "ios" "1" + #cd client/ && /Users/md/Qt/5.15.2/ios/bin/qmake -o Makefile /Users/md/amnezia/desktop-client/client/client.pro -spec macx-ios-clang CONFIG+=iphonesimulator CONFIG+=simulator CONFIG+=qml_debug -after +# %{sourceDir}/client/ios/xcode_patcher.rb %{buildDir}/client/AmneziaVPN.xcodeproj 2.0 2.0.0 ios 1 } diff --git a/client/constants.h b/client/constants.h new file mode 100644 index 00000000..9059eccc --- /dev/null +++ b/client/constants.h @@ -0,0 +1,127 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#include + +namespace Constants { + +// Returns true if we are in a production environment. +bool inProduction(); +void setStaging(); + +// Number of msecs for the captive-portal block alert. +constexpr uint32_t CAPTIVE_PORTAL_ALERT_MSEC = 4000; + +// Number of msecs for the unsecured network alert. +constexpr uint32_t UNSECURED_NETWORK_ALERT_MSEC = 4000; + +// Number of recent connections to retain. +constexpr int RECENT_CONNECTIONS_MAX_COUNT = 5; + +#if defined(UNIT_TEST) +# define CONSTEXPR(type, functionName, releaseValue, debugValue, \ + testingValue) \ + inline type functionName() { return testingValue; } +#else +# define CONSTEXPR(type, functionName, releaseValue, debugValue, \ + testingValue) \ + inline type functionName() { \ + return inProduction() ? releaseValue : debugValue; \ + } +#endif + +// Let's refresh the IP address any 10 minutes (in milliseconds). +CONSTEXPR(uint32_t, ipAddressTimerMsec, 600000, 10000, 0) + +// Let's check the connection status any second. +CONSTEXPR(uint32_t, checkStatusTimerMsec, 1000, 1000, 0) + +// Number of points for the charts. +CONSTEXPR(int, chartsMaxPoints, 30, 30, 30); + +// Any 6 hours, a new check +CONSTEXPR(uint32_t, releaseMonitorMsec, 21600000, 4000, 0) + +// in milliseconds, how often we should fetch the server list and the account. +CONSTEXPR(uint32_t, scheduleAccountAndServersTimerMsec, 3600000, 4000, 0) + +// how often we check the captive portal when the VPN is on. +CONSTEXPR(uint32_t, captivePortalRequestTimeoutMsec, 10000, 4000, 0) + +// How fast the animated icon should move +CONSTEXPR(uint32_t, statusIconAnimationMsec, 200, 200, 0) + +// How often glean pings are sent +CONSTEXPR(uint32_t, gleanTimeoutMsec, 1200000, 1000, 0) + +// How often we check the surveys to be executed (no network requests are done +// for this check) +CONSTEXPR(uint32_t, surveyTimerMsec, 300000, 4000, 0) + +#undef CONSTEXPR + +#define PRODBETAEXPR(type, functionName, prod, beta) \ + inline type functionName() { return inProduction() ? prod : beta; } + +constexpr const char* API_PRODUCTION_URL = "https://vpn.mozilla.org"; +constexpr const char* API_STAGING_URL = + "https://stage-vpn.guardian.nonprod.cloudops.mozgcp.net"; + +constexpr const char* LOGO_URL = ":/ui/resources/logo-dock.png"; + +PRODBETAEXPR(const char*, fxaUrl, "https://api.accounts.firefox.com", + "https://api-accounts.stage.mozaws.net") +PRODBETAEXPR( + const char*, balrogUrl, + "https://aus5.mozilla.org/json/1/FirefoxVPN/%1/%2/release/update.json", + "https://stage.balrog.nonprod.cloudops.mozgcp.net/json/1/FirefoxVPN/%1/%2/" + "release-cdntest/update.json"); +PRODBETAEXPR( + const char*, balrogRootCertFingerprint, + "97e8ba9cf12fb3de53cc42a4e6577ed64df493c247b414fea036818d3823560e", + "3c01446abe9036cea9a09acaa3a520ac628f20a7ae32ce861cb2efb70fa0c745"); + +#undef PRODBETAEXPR + +constexpr const char* PLATFORM_NAME = +#if defined(MVPN_IOS) + "ios" +#elif defined(MVPN_MACOS) + "macos" +#elif defined(MVPN_LINUX) + "linux" +#elif defined(MVPN_ANDROID) + "android" +#elif defined(MVPN_WINDOWS) + "windows" +#elif defined(UNIT_TEST) || defined(MVPN_DUMMY) + "dummy" +#else +# error "Unsupported platform" +#endif + ; + +constexpr const char* PLACEHOLDER_USER_DNS = "127.0.0.1"; + +#if defined(MVPN_ADJUST) +// These are the two auto-generated token from the Adjust dashboard for the +// "Subscription Completed" event. We have two since in the Adjust dashboard we +// have defined two apps for iOS and Android with a event token each. +constexpr const char* ADJUST_SUBSCRIPTION_COMPLETED = +# if defined(MVPN_IOS) + "jl72xm" +# elif defined(MVPN_ANDROID) + "o1mn9m" +# else + "" +# endif + ; +#endif + +}; // namespace Constants + +#endif // CONSTANTS_H diff --git a/client/ios/app/AmneziaVPNLaunchScreen.storyboard b/client/ios/app/AmneziaVPNLaunchScreen.storyboard new file mode 100644 index 00000000..92f79f7e --- /dev/null +++ b/client/ios/app/AmneziaVPNLaunchScreen.storyboard @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/Contents.json b/client/ios/app/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..3b3bcf28 --- /dev/null +++ b/client/ios/app/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images" : [ + { + "filename" : "icon-ios-20@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "icon-ios-20@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "icon-ios-29@2x-1.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "icon-ios-29@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "icon-ios-40@2x-1.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "icon-ios-40@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "icon-ios-60@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "icon-ios-60@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "icon-ios-20@1x.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "icon-ios-20@2x-1.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "icon-ios-29@1x.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "icon-ios-29@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "icon-ios-40@1x.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "icon-ios-40@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "icon-ios-76@1x.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "icon-ios-76@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "icon-ios-83.5@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "icon-ios-1024@1x.png", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-1024@1x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..1933ed99f164fcb2a0f7e1f092e755a903727195 GIT binary patch literal 22976 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 Kn$wb9{MkRU;EOK+ literal 0 HcmV?d00001 diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@1x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c6c1b8880aad60d07fb36f2b87179177fdc4b2a7 GIT binary patch literal 407 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 literal 0 HcmV?d00001 diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@2x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7e27a54d5cc6b11ff5946abef48584c6fa53ef25 GIT binary patch literal 975 zcmV;=12FuFP)U27)UazZKt)@<=lR6v@YO~p> zS0RvWnqY9bTmlpDS+m&`ox}eo_wrt^7uW)_g(Rv~G;qQFehIHK$Ink6%v&BDg1 z^KQ2*7Ex|DL0mhbC%NTvnUJG0znW;b+f5MQ)Dom9`u)BLQIR-`5E94rdJP-JgeVBakv4hy8U1cv5FyI#(r7eF$PI_X1W|71^MZ&?z{66E$Kx3V33v z`G^pOlS#{lOptO!B1A#*csvHKK&TNU8F(f2uqz!x!oQK{-0%0{vkv-7tEbcZ=JPpg z!vKnbs1U$7CG#l&J|z9zSlUssb`Bu<@JJW!1d()` z1~vimv@*d2vnIJ%EUez|SO{bbVY05^NZPdNbm}yYNh7?7nmj1_O}p&lK{095qNU9t z7ouF=3J)1izO^Gs$iV(0HMMP={o~znwdblL%Uw+uKuKk@f|JQ4$QyVk9R~|cwFq;} z;*psGHX4nm=k0dO%IRHJd4oGoLO5HkR!@Djh~SV()HcbMs58VerC#K620AS zPtV$=v!rmsmp2B30ozZS+b~JF@o~TB^{wNvr zVX_=a6bL4DjqKlL?jI3b7a(q-6vN+mnZ`lquEr9~1e9X!b~}7`yiCJ0Vyo}DQXtiA zs}Q=ALT9@&ByDXv4ybCO4zSTU`$Fyt+k*4qa%0%4)O0quZ6tYM{`LUgzsHsiJ~Dn$olz>VC?*AUP-+Va94u_9fxi3$~dAy xf^I4X^2W=E{xqr|J(dj>(Xyc;S~k25(SL`x`DV7-DP{lw002ovPDHLkV1jdP!Gr(+ literal 0 HcmV?d00001 diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@3x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..d408007f94b0c4b46a7d93f1070c1c10537fa880 GIT binary patch literal 1343 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 Q3;Z1bjGMP>9Xj~>KjgzI00000 literal 0 HcmV?d00001 diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-60@2x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8cc414279f84212c78ab507cd43f623564246b7a GIT binary patch literal 1645 zcmah~dpOg382?#w$)!ge(ZMNQki*V|W-ZF1j9gkSX{$(XX=ZNgbWy@0j!q+CM#7j( z=CYceW(hNDZWY;TE}Nk+rH)&j^XtF!$9bOf$LIZg-}n3ZzR&ai@qWIUzTSs*G=J6v z06+)h?urHZ!VhSuff0Fj&j3j4W8H(|0YFRt2ULKfVk5Aq5|2HM2I@p6(_jLPaPe{h z0QN1dwGdSRP=jDxUHmSn%+gc5E_hF+aCdgilU18Jw?-DQmK?y zWBeHsUvetrW;jP2(zalJ&TUeU`vZXJGl{}np~%`eOLxLU3{kx0zc?8cg#a5x;Q170&b zXd8@7CZ~qYkdqoHJ6-{$f#M zu>EPI2pMsf0pqZZ)KP{;M|WywT+nfAs6J|&*XRola|mDHL8A;3PMKMc4;CM9>Ysee z;KMx{N7U^wCP#7EK5Mj=;ZFE|lsPviYpiOhgg-J~LZ=tjY#D?^XBi`dayq_H{gJ`} zgEUokUWGB%HLtqa*%C*td3F6;U|=9~F09JrF)!*~oJB}vYTBo=Q`X6Xg2vh5NN4U6 z>bPl{oJPI#ZJn-Vg!?+>23bZ{L-qL>ou@QZZ?_5CdHMOWX3~_*=foLSpOt-w&9t!y zH&qnoW6A9%Y7j`Cs{xVz9W9DGcIc(oU)1OiIp* zC{*rX=4DWr?f&c;$-VFy!lC+J?VCpq_E!#GgSzCm+$gQkf%q*=;sTOxNQjwtjHP?c$FOP`L z8gqpvCnx`6eQ+~6VGQcTV5AYL4@?iYc7+z$OGBvc)q3kbT^wH#?2gQzc}q=5NXVlc zKzc;_ZtqL^P|$`D!fU(eXfM`nO+^$;&2EnNBGd9^LhJ5WZN^x=cLq&dvHbS*1W#D3 zF~5oR@vsQx)8?4G6AZmadZ~E_WCmIYPtZ z?J#6`Dzh^8W;Bezafq3ZH{foOA5v&!%B%S?1E`XGPL;TKc3@NBSn7nE&-?7Z<4VIb z_%Dl18d)3KCt-K`7YX?ga(ZXgrCnN0eQ&#jMJ7*J8*apm)KQ3Bb82pfYFW#h6S{ao zgL#<3BhBB>jOhRHn89ny5;BeR??sH3*SKpD7A5SybtQ-<) zRJ|JNS`W4$ Q3;Z1bjGMP>9Xj~>KjgzI00000 literal 0 HcmV?d00001 diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-60@3x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a60b8ff765d89187f87a2377be101c88dac60e8d GIT binary patch literal 3101 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 Aga7~l literal 0 HcmV?d00001 diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-76@2x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f26844e1d5394074947586cc18431f5d8f39dfce GIT binary patch literal 2636 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 ZMdzgr70Q?=5*P#uFg3C?#Ou4p{RexkMV0^n literal 0 HcmV?d00001 diff --git a/client/ios/app/Images.xcassets/Contents.json b/client/ios/app/Images.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/client/ios/app/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/client/ios/app/Info.plist b/client/ios/app/Info.plist new file mode 100644 index 00000000..6648ef7b --- /dev/null +++ b/client/ios/app/Info.plist @@ -0,0 +1,55 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleAllowMixedLocalizations + + CFBundleDisplayName + Mozilla VPN + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIcons + + CFBundleIcons~ipad + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${APP_DISPLAY_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + ITSAppUsesNonExemptEncryption + + LSRequiresIPhoneOS + + LSSupportsOpeningDocumentsInPlace + + UILaunchStoryboardName + AmneziaVPNLaunchScreen + UIRequiredDeviceCapabilities + + UIRequiresFullScreen + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIUserInterfaceStyle + Light + com.wireguard.ios.app_group_id + group.org.mozilla.ios.Guardian + ADJUST_SDK_TOKEN + $(ADJUST_SDK_TOKEN) + + diff --git a/client/ios/app/launch.png b/client/ios/app/launch.png new file mode 100644 index 0000000000000000000000000000000000000000..33bb9d7db849940f91d42521def9b93de905375e GIT binary patch literal 12825 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 literal 0 HcmV?d00001 diff --git a/client/ios/app/main.entitlements b/client/ios/app/main.entitlements new file mode 100644 index 00000000..cb13ea2d --- /dev/null +++ b/client/ios/app/main.entitlements @@ -0,0 +1,16 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.security.application-groups + + $(GROUP_ID_IOS) + + com.apple.security.files.user-selected.read-write + + + diff --git a/client/ios/networkextension/AmneziaVPNNetworkExtension.entitlements b/client/ios/networkextension/AmneziaVPNNetworkExtension.entitlements new file mode 100644 index 00000000..eded281a --- /dev/null +++ b/client/ios/networkextension/AmneziaVPNNetworkExtension.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.application-groups + + $(GROUP_ID_IOS) + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + + diff --git a/client/ios/xcode.xconfig b/client/ios/xcode.xconfig new file mode 100644 index 00000000..1b4f1000 --- /dev/null +++ b/client/ios/xcode.xconfig @@ -0,0 +1,13 @@ +DEVELOPMENT_TEAM = + +# MacOS configuration +GROUP_ID_MACOS = <> +APP_ID_MACOS = <> +NETEXT_ID_MACOS = <> +LOGIN_ID_MACOS = <> +NATIVEMESSAGING_ID_MACOS = <> + +# IOS configuration +GROUP_ID_IOS = group.org.mozilla.ios.Guardian +APP_ID_IOS = org.mozilla.ios.FirefoxVPN +NETEXT_ID_IOS = org.mozilla.ios.FirefoxVPN.network-extension diff --git a/client/ios/xcode_patcher.rb b/client/ios/xcode_patcher.rb new file mode 100644 index 00000000..b44b0b56 --- /dev/null +++ b/client/ios/xcode_patcher.rb @@ -0,0 +1,598 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +require 'xcodeproj' + +class XCodeprojPatcher + attr :project + attr :p_root + attr :target_main + attr :target_extension + +# @@project_root +# def self.project_root +# @@project_root +# end + + def run(project_root, file, shortVersion, fullVersion, platform, networkExtension, webExtension, configHash, adjust_sdk_token) + @p_root = project_root + open_project file + open_target_main + + die 'IOS requires networkExtension mode' if not networkExtension and platform == 'ios' + + group = @project.main_group.new_group('Configuration') + @configFile = group.new_file('ios/xcode.xconfig') + + setup_target_main shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token + + if platform == 'macos' + setup_target_loginitem shortVersion, fullVersion, configHash + setup_target_nativemessaging shortVersion, fullVersion, configHash if webExtension + end + + if networkExtension + setup_target_extension shortVersion, fullVersion, platform, configHash + setup_target_gobridge + else + setup_target_wireguardgo + setup_target_wireguardtools + end + + setup_target_balrog if platform == 'macos' + + @project.save + end + + def open_project(file) + @project = Xcodeproj::Project.open(file) + puts 'Failed to open the project file: ' + file if @project.nil? + die 'Failed to open the project file: ' + file if @project.nil? + end + + def open_target_main + @target_main = @project.targets.find { |target| target.to_s == 'AmneziaVPN' } + return @target_main if not @target_main.nil? + + puts 'Unable to open AmneziaVPN target' + die 'Unable to open AmneziaVPN target' + end + + def setup_target_main(shortVersion, fullVersion, platform, networkExtension, configHash, adjust_sdk_token) + @target_main.build_configurations.each do |config| + config.base_configuration_reference = @configFile + + config.build_settings['LD_RUNPATH_SEARCH_PATHS'] ||= '"$(inherited) @executable_path/../Frameworks"' + config.build_settings['SWIFT_VERSION'] ||= '5.0' + config.build_settings['CLANG_ENABLE_MODULES'] ||= 'YES' + config.build_settings['SWIFT_OBJC_BRIDGING_HEADER'] ||= p_root + "/" + 'macos/app/WireGuard-Bridging-Header.h' + config.build_settings['FRAMEWORK_SEARCH_PATHS'] ||= [ + "$(inherited)", + "$(PROJECT_DIR)/3rd" + ] + + # Versions and names + config.build_settings['MARKETING_VERSION'] ||= shortVersion + config.build_settings['CURRENT_PROJECT_VERSION'] ||= fullVersion + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = configHash['APP_ID_MACOS'] if platform == 'macos' + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = configHash['APP_ID_IOS'] if platform == 'ios' + config.build_settings['PRODUCT_NAME'] = 'Mozilla VPN' + + # other config + config.build_settings['INFOPLIST_FILE'] ||= p_root + "/" + platform + '/app/Info.plist' + if platform == 'ios' + config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= p_root + "/" + 'ios/app/main.entitlements' + if adjust_sdk_token != "" + config.build_settings['ADJUST_SDK_TOKEN'] = adjust_sdk_token + end + elsif networkExtension + config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= p_root + "/" + 'macos/app/app.entitlements' + else + config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= p_root + "/" + 'macos/app/daemon.entitlements' + end + + config.build_settings['CODE_SIGN_IDENTITY'] ||= 'Apple Development' + config.build_settings['ENABLE_BITCODE'] ||= 'NO' if platform == 'ios' + config.build_settings['SDKROOT'] = 'iphoneos' if platform == 'ios' + config.build_settings['SWIFT_PRECOMPILE_BRIDGING_HEADER'] = 'NO' if platform == 'ios' + + groupId = ""; + if (platform == 'macos') + groupId = configHash['DEVELOPMENT_TEAM'] + "." + configHash['GROUP_ID_MACOS'] + config.build_settings['APP_ID_MACOS'] ||= configHash['APP_ID_MACOS'] + else + groupId = configHash['GROUP_ID_IOS'] + config.build_settings['GROUP_ID_IOS'] ||= configHash['GROUP_ID_IOS'] + end + + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ + 'GROUP_ID=\"' + groupId + '\"', + "VPN_NE_BUNDLEID=\\\"" + (platform == 'macos' ? configHash['NETEXT_ID_MACOS'] : configHash['NETEXT_ID_IOS']) + "\\\"", + ] + + if config.name == 'Release' + config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] ||= '-Onone' + end + end + + if networkExtension + # WireGuard group + group = @project.main_group.new_group('WireGuard') + + [ + 'macos/gobridge/wireguard-go-version.h', + '3rd/wireguard-apple/Sources/Shared/Keychain.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/IPAddressRange.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/InterfaceConfiguration.swift', + '3rd/wireguard-apple/Sources/Shared/Model/NETunnelProviderProtocol+Extension.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/TunnelConfiguration.swift', + '3rd/wireguard-apple/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/Endpoint.swift', + '3rd/wireguard-apple/Sources/Shared/Model/String+ArrayConversion.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/PeerConfiguration.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/DNSServer.swift', + '3rd/wireguard-apple/Sources/WireGuardApp/LocalizationHelper.swift', + '3rd/wireguard-apple/Sources/Shared/FileManager+Extension.swift', + '3rd/wireguard-apple/Sources/WireGuardKitC/x25519.c', + '3rd/wireguard-apple/Sources/WireGuardKit/PrivateKey.swift', + ].each { |filename| + file = group.new_file(p_root + "/" + filename) + @target_main.add_file_references([file]) + } + + # @target_main + swift integration + group = @project.main_group.new_group('SwiftIntegration') + + [ + 'platforms/ios/ioscontroller.swift', + 'platforms/ios/ioslogger.swift', + ].each { |filename| + file = group.new_file(p_root + "/" + filename) + @target_main.add_file_references([file]) + } + end + + if (platform == 'ios' && adjust_sdk_token != "") + frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' } + frameworks_build_phase = @target_main.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' } + embed_frameworks_build_phase = @target_main.build_phases.find { |build_phase| build_phase.to_s == 'Embed Frameworks' } + + framework_ref = frameworks_group.new_file('3rd/AdjustSdk.framework') + frameworks_build_phase.add_file_reference(framework_ref) + + framework_file = embed_frameworks_build_phase.add_file_reference(framework_ref) + framework_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy', 'CodeSignOnCopy'] } + + framework_ref = frameworks_group.new_file('AdServices.framework') + frameworks_build_phase.add_file_reference(framework_ref) + + framework_ref = frameworks_group.new_file('iAd.framework') + frameworks_build_phase.add_file_reference(framework_ref) + end + end + + def setup_target_extension(shortVersion, fullVersion, platform, configHash) + @target_extension = @project.new_target(:app_extension, 'WireGuardNetworkExtension', platform == 'macos' ? :osx : :ios) + + @target_extension.build_configurations.each do |config| + config.base_configuration_reference = @configFile + + config.build_settings['LD_RUNPATH_SEARCH_PATHS'] ||= '"$(inherited) @executable_path/../Frameworks"' + config.build_settings['SWIFT_VERSION'] ||= '5.0' + config.build_settings['CLANG_ENABLE_MODULES'] ||= 'YES' + config.build_settings['SWIFT_OBJC_BRIDGING_HEADER'] ||= p_root + "/" + 'macos/networkextension/WireGuardNetworkExtension-Bridging-Header.h' + config.build_settings['SWIFT_PRECOMPILE_BRIDGING_HEADER'] = 'NO' + + # Versions and names + config.build_settings['MARKETING_VERSION'] ||= shortVersion + config.build_settings['CURRENT_PROJECT_VERSION'] ||= fullVersion + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] ||= configHash['NETEXT_ID_MACOS'] if platform == 'macos' + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] ||= configHash['NETEXT_ID_IOS'] if platform == 'ios' + config.build_settings['PRODUCT_NAME'] = 'WireGuardNetworkExtension' + + # other configs + config.build_settings['INFOPLIST_FILE'] ||= p_root + "/" + 'macos/networkextension/Info.plist' + config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= p_root + "/" + platform + '/networkextension/AmneziaVPNNetworkExtension.entitlements' + config.build_settings['CODE_SIGN_IDENTITY'] = 'Apple Development' + + if platform == 'ios' + config.build_settings['ENABLE_BITCODE'] ||= 'NO' + config.build_settings['SDKROOT'] = 'iphoneos' + + config.build_settings['OTHER_LDFLAGS'] ||= [ + "-stdlib=libc++", + "-Wl,-rpath,@executable_path/Frameworks", + "-framework", + "AssetsLibrary", + "-framework", + "MobileCoreServices", + "-lm", + "-framework", + "UIKit", + "-lz", + "-framework", + "OpenGLES", + ] + end + + groupId = ""; + if (platform == 'macos') + groupId = configHash['DEVELOPMENT_TEAM'] + "." + configHash['GROUP_ID_MACOS'] + else + groupId = configHash['GROUP_ID_IOS'] + end + + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ + # This is needed to compile the iosglue without Qt. + 'NETWORK_EXTENSION=1', + 'GROUP_ID=\"' + groupId + '\"', + ] + + if config.name == 'Release' + config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] ||= '-Onone' + end + + end + + group = @project.main_group.new_group('WireGuardExtension') + [ + '3rd/wireguard-apple/Sources/WireGuardKit/WireGuardAdapter.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/PacketTunnelSettingsGenerator.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/DNSResolver.swift', + '3rd/wireguard-apple/Sources/WireGuardNetworkExtension/ErrorNotifier.swift', + '3rd/wireguard-apple/Sources/Shared/Keychain.swift', + '3rd/wireguard-apple/Sources/Shared/Model/TunnelConfiguration+WgQuickConfig.swift', + '3rd/wireguard-apple/Sources/Shared/Model/NETunnelProviderProtocol+Extension.swift', + '3rd/wireguard-apple/Sources/Shared/Model/String+ArrayConversion.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/TunnelConfiguration.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/IPAddressRange.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/Endpoint.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/DNSServer.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/InterfaceConfiguration.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/PeerConfiguration.swift', + '3rd/wireguard-apple/Sources/Shared/FileManager+Extension.swift', + '3rd/wireguard-apple/Sources/WireGuardKitC/x25519.c', + '3rd/wireguard-apple/Sources/WireGuardKit/Array+ConcurrentMap.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/IPAddress+AddrInfo.swift', + '3rd/wireguard-apple/Sources/WireGuardKit/PrivateKey.swift', + ].each { |filename| + file = group.new_file(p_root + "/" + filename) + @target_extension.add_file_references([file]) + } + # @target_extension + swift integration + group = @project.main_group.new_group('SwiftIntegration') + + [ + 'platforms/ios/iostunnel.swift', + 'platforms/ios/iosglue.mm', + 'platforms/ios/ioslogger.swift', + ].each { |filename| + file = group.new_file(p_root + "/" + filename) + @target_extension.add_file_references([file]) + } + + frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' } + frameworks_build_phase = @target_extension.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' } + + frameworks_build_phase.clear + + framework_ref = frameworks_group.new_file('libwg-go.a') + frameworks_build_phase.add_file_reference(framework_ref) + + framework_ref = frameworks_group.new_file('NetworkExtension.framework') + frameworks_build_phase.add_file_reference(framework_ref) + + # This fails: @target_main.add_dependency @target_extension + container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) + container_proxy.container_portal = @project.root_object.uuid + container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target] + container_proxy.remote_global_id_string = @target_extension.uuid + container_proxy.remote_info = @target_extension.name + + dependency = @project.new(Xcodeproj::Project::PBXTargetDependency) + dependency.name = @target_extension.name + dependency.target = @target_main + dependency.target_proxy = container_proxy + + @target_main.dependencies << dependency + + copy_appex = @target_main.new_copy_files_build_phase + copy_appex.name = 'Copy Network-Extension plugin' + copy_appex.symbol_dst_subfolder_spec = :plug_ins + + appex_file = copy_appex.add_file_reference @target_extension.product_reference + appex_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] } + end + + def setup_target_gobridge + target_gobridge = legacy_target = @project.new(Xcodeproj::Project::PBXLegacyTarget) + + target_gobridge.build_working_directory = p_root + "/" + 'macos/gobridge' + target_gobridge.build_tool_path = 'make' + target_gobridge.pass_build_settings_in_environment = '1' + target_gobridge.build_arguments_string = '$(ACTION)' + target_gobridge.name = 'WireGuardGoBridge' + target_gobridge.product_name = 'WireGuardGoBridge' + + @project.targets << target_gobridge + @target_extension.add_dependency target_gobridge + end + + def setup_target_balrog + target_balrog = legacy_target = @project.new(Xcodeproj::Project::PBXLegacyTarget) + + target_balrog.build_working_directory = p_root + "/" + 'balrog' + target_balrog.build_tool_path = 'make' + target_balrog.pass_build_settings_in_environment = '1' + target_balrog.build_arguments_string = '$(ACTION)' + target_balrog.name = 'WireGuardBalrog' + target_balrog.product_name = 'WireGuardBalrog' + + @project.targets << target_balrog + + frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' } + frameworks_build_phase = @target_main.build_phases.find { |build_phase| build_phase.to_s == 'FrameworksBuildPhase' } + + framework_ref = frameworks_group.new_file('balrog/balrog.a') + frameworks_build_phase.add_file_reference(framework_ref) + + # This fails: @target_main.add_dependency target_balrog + container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) + container_proxy.container_portal = @project.root_object.uuid + container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target] + container_proxy.remote_global_id_string = target_balrog.uuid + container_proxy.remote_info = target_balrog.name + + dependency = @project.new(Xcodeproj::Project::PBXTargetDependency) + dependency.name = target_balrog.name + dependency.target = @target_main + dependency.target_proxy = container_proxy + + @target_main.dependencies << dependency + end + + def setup_target_wireguardtools + target_wireguardtools = legacy_target = @project.new(Xcodeproj::Project::PBXLegacyTarget) + + target_wireguardtools.build_working_directory = p_root + "/" + '3rd/wireguard-tools/src' + target_wireguardtools.build_tool_path = 'make' + target_wireguardtools.pass_build_settings_in_environment = '1' + target_wireguardtools.build_arguments_string = '$(ACTION)' + target_wireguardtools.name = 'WireGuardTools' + target_wireguardtools.product_name = 'WireGuardTools' + + @project.targets << target_wireguardtools + + # This fails: @target_main.add_dependency target_wireguardtools + container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) + container_proxy.container_portal = @project.root_object.uuid + container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target] + container_proxy.remote_global_id_string = target_wireguardtools.uuid + container_proxy.remote_info = target_wireguardtools.name + + dependency = @project.new(Xcodeproj::Project::PBXTargetDependency) + dependency.name = target_wireguardtools.name + dependency.target = @target_main + dependency.target_proxy = container_proxy + + @target_main.dependencies << dependency + + copy_wireguardTools = @target_main.new_copy_files_build_phase + copy_wireguardTools.name = 'Copy wireguard-tools' + copy_wireguardTools.symbol_dst_subfolder_spec = :wrapper + copy_wireguardTools.dst_path = 'Contents/Resources/utils' + + group = @project.main_group.new_group('WireGuardTools') + file = group.new_file '3rd/wireguard-tools/src/wg' + + wireguardTools_file = copy_wireguardTools.add_file_reference file + wireguardTools_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] } + end + + def setup_target_wireguardgo + target_wireguardgo = legacy_target = @project.new(Xcodeproj::Project::PBXLegacyTarget) + + target_wireguardgo.build_working_directory = p_root + "/" + '3rd/wireguard-go' + target_wireguardgo.build_tool_path = 'make' + target_wireguardgo.pass_build_settings_in_environment = '1' + target_wireguardgo.build_arguments_string = '$(ACTION)' + target_wireguardgo.name = 'WireGuardGo' + target_wireguardgo.product_name = 'WireGuardGo' + + @project.targets << target_wireguardgo + + # This fails: @target_main.add_dependency target_wireguardgo + container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) + container_proxy.container_portal = @project.root_object.uuid + container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target] + container_proxy.remote_global_id_string = target_wireguardgo.uuid + container_proxy.remote_info = target_wireguardgo.name + + dependency = @project.new(Xcodeproj::Project::PBXTargetDependency) + dependency.name = target_wireguardgo.name + dependency.target = @target_main + dependency.target_proxy = container_proxy + + @target_main.dependencies << dependency + + copy_wireguardGo = @target_main.new_copy_files_build_phase + copy_wireguardGo.name = 'Copy wireguard-go' + copy_wireguardGo.symbol_dst_subfolder_spec = :wrapper + copy_wireguardGo.dst_path = 'Contents/Resources/utils' + + group = @project.main_group.new_group('WireGuardGo') + file = group.new_file '3rd/wireguard-go/wireguard-go' + + wireguardGo_file = copy_wireguardGo.add_file_reference file + wireguardGo_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] } + end + + def setup_target_loginitem(shortVersion, fullVersion, configHash) + return + @target_loginitem = @project.new_target(:application, 'AmneziaVPNLoginItem', :osx) + + @target_loginitem.build_configurations.each do |config| + config.base_configuration_reference = @configFile + + config.build_settings['LD_RUNPATH_SEARCH_PATHS'] ||= '"$(inherited) @executable_path/../Frameworks"' + + # Versions and names + config.build_settings['MARKETING_VERSION'] ||= shortVersion + config.build_settings['CURRENT_PROJECT_VERSION'] ||= fullVersion + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] ||= configHash['LOGIN_ID_MACOS'] + config.build_settings['PRODUCT_NAME'] = 'AmneziaVPNLoginItem' + + # other configs + config.build_settings['INFOPLIST_FILE'] ||= 'macos/loginitem/Info.plist' + config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= p_root + "/" + 'macos/loginitem/AmneziaVPNLoginItem.entitlements' + config.build_settings['CODE_SIGN_IDENTITY'] = 'Apple Development' + config.build_settings['SKIP_INSTALL'] = 'YES' + + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ + 'APP_ID=\"' + configHash['APP_ID_MACOS'] + '\"', + ] + + if config.name == 'Release' + config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] ||= '-Onone' + end + end + + group = @project.main_group.new_group('LoginItem') + [ + 'macos/loginitem/main.m', + ].each { |filename| + file = group.new_file(filename) + @target_loginitem.add_file_references([file]) + } + + # This fails: @target_main.add_dependency @target_loginitem + container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) + container_proxy.container_portal = @project.root_object.uuid + container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target] + container_proxy.remote_global_id_string = @target_loginitem.uuid + container_proxy.remote_info = @target_loginitem.name + + dependency = @project.new(Xcodeproj::Project::PBXTargetDependency) + dependency.name = @target_loginitem.name + dependency.target = @target_main + dependency.target_proxy = container_proxy + + @target_main.dependencies << dependency + + copy_app = @target_main.new_copy_files_build_phase + copy_app.name = 'Copy LoginItem' + copy_app.symbol_dst_subfolder_spec = :wrapper + copy_app.dst_path = 'Contents/Library/LoginItems' + + app_file = copy_app.add_file_reference @target_loginitem.product_reference + app_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] } + end + + def setup_target_nativemessaging(shortVersion, fullVersion, configHash) + @target_nativemessaging = @project.new_target(:application, 'AmneziaVPNNativeMessaging', :osx) + + @target_nativemessaging.build_configurations.each do |config| + config.base_configuration_reference = @configFile + + config.build_settings['LD_RUNPATH_SEARCH_PATHS'] ||= '"$(inherited) @executable_path/../Frameworks"' + + # Versions and names + config.build_settings['MARKETING_VERSION'] ||= shortVersion + config.build_settings['CURRENT_PROJECT_VERSION'] ||= fullVersion + config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] ||= configHash['NATIVEMESSAGING_ID_MACOS'] + config.build_settings['PRODUCT_NAME'] = 'AmneziaVPNNativeMessaging' + + # other configs + config.build_settings['INFOPLIST_FILE'] ||= p_root + "/" + 'macos/nativeMessaging/Info.plist' + config.build_settings['CODE_SIGN_ENTITLEMENTS'] ||= p_root + "/" + 'macos/nativeMessaging/AmneziaVPNNativeMessaging.entitlements' + config.build_settings['CODE_SIGN_IDENTITY'] = 'Apple Development' + config.build_settings['SKIP_INSTALL'] = 'YES' + end + + group = @project.main_group.new_group('NativeMessaging') + [ + 'extension/app/constants.h', + 'extension/app/handler.cpp', + 'extension/app/handler.h', + 'extension/app/json.hpp', + 'extension/app/logger.cpp', + 'extension/app/logger.h', + 'extension/app/main.cpp', + 'extension/app/vpnconnection.cpp', + 'extension/app/vpnconnection.h', + ].each { |filename| + file = group.new_file(p_root + "/" + filename) + @target_nativemessaging.add_file_references([file]) + } + + # This fails: @target_main.add_dependency @target_nativemessaging + container_proxy = @project.new(Xcodeproj::Project::PBXContainerItemProxy) + container_proxy.container_portal = @project.root_object.uuid + container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target] + container_proxy.remote_global_id_string = @target_nativemessaging.uuid + container_proxy.remote_info = @target_nativemessaging.name + + dependency = @project.new(Xcodeproj::Project::PBXTargetDependency) + dependency.name = @target_nativemessaging.name + dependency.target = @target_main + dependency.target_proxy = container_proxy + + @target_main.dependencies << dependency + + copy_app = @target_main.new_copy_files_build_phase + copy_app.name = 'Copy LoginItem' + copy_app.symbol_dst_subfolder_spec = :wrapper + copy_app.dst_path = 'Contents/Library/NativeMessaging' + + app_file = copy_app.add_file_reference @target_nativemessaging.product_reference + app_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] } + + copy_nativeMessagingManifest = @target_main.new_copy_files_build_phase + copy_nativeMessagingManifest.name = 'Copy native messaging manifest' + copy_nativeMessagingManifest.symbol_dst_subfolder_spec = :wrapper + copy_nativeMessagingManifest.dst_path = 'Contents/Resources/utils' + + group = @project.main_group.new_group('WireGuardHelper') + file = group.new_file 'extension/app/manifests/macos/mozillavpn.json' + + nativeMessagingManifest_file = copy_nativeMessagingManifest.add_file_reference file + nativeMessagingManifest_file.settings = { "ATTRIBUTES" => ['RemoveHeadersOnCopy'] } + end + + def die(msg) + print $msg + exit 1 + end +end + +if ARGV.length < 4 || (ARGV[4] != "ios" && ARGV[4] != "macos") + puts "Usage: