diff --git a/.gitignore b/.gitignore index 598965e1..2ead399d 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,30 @@ ui_*.h Makefile* *build-* +# Qt-es +client/Debug-iphoneos/ +client/.xcode/ +client/.qmake.cache +client/.qmake.stash +client/*.pro.user +client/*.pro.user.* +client/*.qbs.user +client/*.qbs.user.* +client/*.moc +client/moc_*.cpp +client/qrc_*.cpp +client/ui_*.h +client/ui_*.cpp +client/Makefile* +client/*build-* +client/AmneziaVPN.xcodeproj +client/Debug-iphonesimulator/ +client/amneziavpn_plugin_import.cpp +client/amneziavpn_qml_plugin_import.cpp +client/qmlcache_loader.cpp +client/rep_ipc_interface_replica.h +client/resources_qmlcache.qrc + # QtCreator *.autosave @@ -37,6 +61,7 @@ CMakeLists.txt.user* # MACOS files .DS_Store +client/.DS_Store ._.DS_Store ._* *.dmg 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/OpenSSL/include/openssl/applink.c b/client/3rd/OpenSSL/include/openssl/applink.c index 238dbff3..903e6d47 100644 --- a/client/3rd/OpenSSL/include/openssl/applink.c +++ b/client/3rd/OpenSSL/include/openssl/applink.c @@ -1,4 +1,4 @@ -/* + /* * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use diff --git a/client/3rd/QtSsh/src/botan/botan.pri b/client/3rd/QtSsh/src/botan/botan.pri index 3ef7a602..6568e154 100644 --- a/client/3rd/QtSsh/src/botan/botan.pri +++ b/client/3rd/QtSsh/src/botan/botan.pri @@ -57,10 +57,16 @@ ios: { ARCH_TAG = "ios_armv7" } } + + CONFIG(iphonesimulator, iphoneos|iphonesimulator) { + INCLUDEPATH += $$PWD/ios/iphone + HEADERS += $$PWD/ios/iphone/botan_all.h + SOURCES += $$PWD/ios/iphone/botan_all.cpp + } - CONFIG(iphonesimulator, iphoneos|iphonesimulator) { - INCLUDEPATH += $$PWD/ios/simulator - HEADERS += $$PWD/ios/simulator/botan_all.h - SOURCES += $$PWD/ios/simulator/botan_all.cpp - } +# CONFIG(iphonesimulator, iphoneos|iphonesimulator) { +# INCLUDEPATH += $$PWD/ios/simulator +# HEADERS += $$PWD/ios/simulator/botan_all.h +# SOURCES += $$PWD/ios/simulator/botan_all.cpp +# } } 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/AmneziaVPN-Swift.h b/client/AmneziaVPN-Swift.h new file mode 100644 index 00000000..c04ce421 --- /dev/null +++ b/client/AmneziaVPN-Swift.h @@ -0,0 +1,247 @@ +#ifndef AmneziaVPN_Swift_h +#define AmneziaVPN_Swift_h +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgcc-compat" + +#if !defined(__has_include) +# define __has_include(x) 0 +#endif +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif +#if !defined(__has_warning) +# define __has_warning(x) 0 +#endif + +#if __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#include +#include +#include +#include + +#if !defined(SWIFT_TYPEDEFS) +# define SWIFT_TYPEDEFS 1 +# if __has_include() +# include +# elif !defined(__cplusplus) +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +# endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); +typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); +typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); +#endif + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif +#if !defined(SWIFT_CLASS_PROPERTY) +# if __has_feature(objc_class_property) +# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ +# else +# define SWIFT_CLASS_PROPERTY(...) +# endif +#endif + +#if __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +#else +# define SWIFT_RUNTIME_NAME(X) +#endif +#if __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +#else +# define SWIFT_COMPILE_NAME(X) +#endif +#if __has_attribute(objc_method_family) +# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) +#else +# define SWIFT_METHOD_FAMILY(X) +#endif +#if __has_attribute(noescape) +# define SWIFT_NOESCAPE __attribute__((noescape)) +#else +# define SWIFT_NOESCAPE +#endif +#if __has_attribute(ns_consumed) +# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed)) +#else +# define SWIFT_RELEASES_ARGUMENT +#endif +#if __has_attribute(warn_unused_result) +# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define SWIFT_WARN_UNUSED_RESULT +#endif +#if __has_attribute(noreturn) +# define SWIFT_NORETURN __attribute__((noreturn)) +#else +# define SWIFT_NORETURN +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif +#if !defined(SWIFT_RESILIENT_CLASS) +# if __has_attribute(objc_class_stub) +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub)) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME) +# else +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME) +# endif +#endif + +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif + +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif + +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM_ATTR) +# if defined(__has_attribute) && __has_attribute(enum_extensibility) +# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) +# else +# define SWIFT_ENUM_ATTR(_extensibility) +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# if __has_feature(generalized_swift_name) +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# else +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) +# endif +#endif +#if !defined(SWIFT_UNAVAILABLE) +# define SWIFT_UNAVAILABLE __attribute__((unavailable)) +#endif +#if !defined(SWIFT_UNAVAILABLE_MSG) +# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) +#endif +#if !defined(SWIFT_AVAILABILITY) +# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) +#endif +#if !defined(SWIFT_WEAK_IMPORT) +# define SWIFT_WEAK_IMPORT __attribute__((weak_import)) +#endif +#if !defined(SWIFT_DEPRECATED) +# define SWIFT_DEPRECATED __attribute__((deprecated)) +#endif +#if !defined(SWIFT_DEPRECATED_MSG) +# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) +#endif +#if __has_feature(attribute_diagnose_if_objc) +# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) +#else +# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) +#endif +#if !defined(IBSegueAction) +# define IBSegueAction +#endif +#if __has_feature(modules) +#if __has_warning("-Watimport-in-framework-header") +#pragma clang diagnostic ignored "-Watimport-in-framework-header" +#endif +@import Foundation; +@import ObjectiveC; +#endif + +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +#if __has_warning("-Wpragma-clang-attribute") +# pragma clang diagnostic ignored "-Wpragma-clang-attribute" +#endif +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wnullability" + +#if __has_attribute(external_source_symbol) +# pragma push_macro("any") +# undef any +# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="AmneziaVPN",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) +# pragma pop_macro("any") +#endif + + +@class NSString; +@class NSData; +enum ConnectionState : NSInteger; +@class NSDate; +@class NSNumber; +@class VPNIPAddressRange; + +SWIFT_CLASS("_TtC10AmneziaVPN18IOSVpnProtocolImpl") +@interface IOSVpnProtocolImpl : NSObject +- (nonnull instancetype)initWithBundleID:(NSString * _Nonnull)bundleID privateKey:(NSData * _Nonnull)privateKey deviceIpv4Address:(NSString * _Nonnull)deviceIpv4Address deviceIpv6Address:(NSString * _Nonnull)deviceIpv6Address closure:(void (^ _Nonnull)(enum ConnectionState, NSDate * _Nullable))closure callback:(void (^ _Nonnull)(BOOL))callback OBJC_DESIGNATED_INITIALIZER; +- (void)connectWithDnsServer:(NSString * _Nonnull)dnsServer serverIpv6Gateway:(NSString * _Nonnull)serverIpv6Gateway serverPublicKey:(NSString * _Nonnull)serverPublicKey presharedKey:(NSString * _Nonnull)presharedKey serverIpv4AddrIn:(NSString * _Nonnull)serverIpv4AddrIn serverPort:(NSInteger)serverPort allowedIPAddressRanges:(NSArray * _Nonnull)allowedIPAddressRanges ipv6Enabled:(Boolean)enabled reason:(NSInteger)reason failureCallback:(void (^ _Nonnull)(void))failureCallback; +- (void)disconnect; +- (void)checkStatusWithCallback:(void (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull, NSString * _Nonnull))callback; +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + +typedef SWIFT_ENUM(NSInteger, ConnectionState, closed) { + ConnectionStateError = 0, + ConnectionStateConnected = 1, + ConnectionStateDisconnected = 2, +}; + + + +SWIFT_CLASS("_TtC10AmneziaVPN17VPNIPAddressRange") +@interface VPNIPAddressRange : NSObject +- (nonnull instancetype)initWithAddress:(NSString * _Nonnull)address networkPrefixLength:(uint8_t)networkPrefixLength isIpv6:(BOOL)isIpv6 OBJC_DESIGNATED_INITIALIZER; +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + +#if __has_attribute(external_source_symbol) +# pragma clang attribute pop +#endif +#pragma clang diagnostic pop +#endif /* AmneziaVPN_Swift_h */ + diff --git a/client/Info.plist b/client/Info.plist new file mode 100644 index 00000000..03ba3e82 --- /dev/null +++ b/client/Info.plist @@ -0,0 +1,39 @@ + + + + + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + ${ASSETCATALOG_COMPILER_APPICON_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${QMAKE_SHORT_VERSION} + CFBundleSignature + ${QMAKE_PKGINFO_TYPEINFO} + CFBundleVersion + ${QMAKE_FULL_VERSION} + LSRequiresIPhoneOS + + MinimumOSVersion + ${IPHONEOS_DEPLOYMENT_TARGET} + NOTE + This file was generated by Qt/QMake. + UILaunchStoryboardName + LaunchScreen + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/client/WireGuard-Bridging-Header.h b/client/WireGuard-Bridging-Header.h new file mode 100644 index 00000000..40b6c89d --- /dev/null +++ b/client/WireGuard-Bridging-Header.h @@ -0,0 +1,29 @@ +/* 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/. */ + +#include "wireguard-go-version.h" +#include "3rd/wireguard-apple/Sources/WireGuardKitC/WireGuardKitC.h" + +#include +#include + +#define WG_KEY_LEN (32) +#define WG_KEY_LEN_BASE64 (45) +#define WG_KEY_LEN_HEX (65) + +void key_to_base64(char base64[WG_KEY_LEN_BASE64], + const uint8_t key[WG_KEY_LEN]); +bool key_from_base64(uint8_t key[WG_KEY_LEN], const char* base64); + +void key_to_hex(char hex[WG_KEY_LEN_HEX], const uint8_t key[WG_KEY_LEN]); +bool key_from_hex(uint8_t key[WG_KEY_LEN], const char* hex); + +bool key_eq(const uint8_t key1[WG_KEY_LEN], const uint8_t key2[WG_KEY_LEN]); + +void write_msg_to_log(const char* tag, const char* msg); + +#import "TargetConditionals.h" +#if TARGET_OS_OSX +# include +#endif diff --git a/client/client.pro b/client/client.pro index 6c20d58c..489edd4f 100644 --- a/client/client.pro +++ b/client/client.pro @@ -70,6 +70,10 @@ HEADERS += \ utils.h \ vpnconnection.h \ protocols/vpnprotocol.h \ + logger.h \ + loghandler.h \ + loglevel.h \ + constants.h SOURCES += \ configurators/cloak_configurator.cpp \ @@ -120,6 +124,9 @@ SOURCES += \ utils.cpp \ vpnconnection.cpp \ protocols/vpnprotocol.cpp \ + logger.cpp \ + loghandler.cpp + RESOURCES += \ resources.qrc @@ -128,6 +135,8 @@ TRANSLATIONS = \ translations/amneziavpn_ru.ts win32 { + DEFINES += MVPN_WINDOWS + OTHER_FILES += platform_win/vpnclient.rc RC_FILE = platform_win/vpnclient.rc @@ -163,6 +172,8 @@ win32 { } macx { + DEFINES += MVPN_MACOS + ICON = $$PWD/images/app.icns HEADERS += ui/macos_util.h @@ -175,6 +186,8 @@ macx { } linux:!android { + DEFINES += MVPN_LINUX + LIBS += /usr/lib/x86_64-linux-gnu/libcrypto.a LIBS += /usr/lib/x86_64-linux-gnu/libssl.a } @@ -200,6 +213,7 @@ win32|macx|linux:!android { android { QT += androidextras + DEFINES += MVPN_ANDROID INCLUDEPATH += platforms/android @@ -251,46 +265,90 @@ 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 + + HEADERS += \ + protocols/ios_vpnprotocol.h \ + platforms/ios/iosnotificationhandler.h \ + platforms/ios/json.h \ + platforms/ios/bigint.h \ + platforms/ios/bigintipv6addr.h \ + platforms/ios/ipaddress.h \ + platforms/ios/ipaddressrange.h + + SOURCES += \ + protocols/ios_vpnprotocol.mm \ + platforms/ios/iosnotificationhandler.mm \ + platforms/ios/json.cpp \ + platforms/ios/iosglue.mm \ + platforms/ios/ipaddress.cpp \ + platforms/ios/ipaddressrange.cpp Q_ENABLE_BITCODE.value = NO Q_ENABLE_BITCODE.name = ENABLE_BITCODE QMAKE_MAC_XCODE_SETTINGS += Q_ENABLE_BITCODE - CONFIG(iphoneos, iphoneos|iphonesimulator) { - message("Building for iPhone OS") - QMAKE_TARGET_BUNDLE_PREFIX = org.amnezia - QMAKE_BUNDLE = AmneziaVPN - QMAKE_IOS_DEPLOYMENT_TARGET = 12.0 - QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 1 - QMAKE_DEVELOPMENT_TEAM = X7UJ388FXK - QMAKE_PROVISIONING_PROFILE = f2fefb59-14aa-4aa9-ac14-1d5531b06dcc - QMAKE_XCODE_CODE_SIGN_IDENTITY = "Apple Distribution" - - XCODEBUILD_FLAGS += -allowProvisioningUpdates - - DEFINES += iphoneos - - contains(QT_ARCH, arm64) { - message("Building for iOS/ARM v8 64-bit architecture") - ARCH_TAG = "ios_armv8_64" - - LIBS += $$PWD/3rd/OpenSSL/lib/ios/iphone/libcrypto.a - LIBS += $$PWD/3rd/OpenSSL/lib/ios/iphone/libssl.a - } else { - message("Building for iOS/ARM v7 (32-bit) architecture") - ARCH_TAG = "ios_armv7" - } +# CONFIG(iphoneos, iphoneos|iphonesimulator) { + iphoneos { + message("Building for iPhone OS") + QMAKE_TARGET_BUNDLE_PREFIX = org.amnezia + QMAKE_BUNDLE = AmneziaVPN + QMAKE_IOS_DEPLOYMENT_TARGET = 12.0 + QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 1 + QMAKE_DEVELOPMENT_TEAM = X7UJ388FXK + QMAKE_PROVISIONING_PROFILE = f2fefb59-14aa-4aa9-ac14-1d5531b06dcc + QMAKE_XCODE_CODE_SIGN_IDENTITY = "Apple Distribution" + QMAKE_INFO_PLIST= $$PWD/ios/app/Info.plist + + XCODEBUILD_FLAGS += -allowProvisioningUpdates + + DEFINES += iphoneos + + contains(QT_ARCH, arm64) { + message("Building for iOS/ARM v8 64-bit architecture") + ARCH_TAG = "ios_armv8_64" + + LIBS += $$PWD/3rd/OpenSSL/lib/ios/iphone/libcrypto.a + LIBS += $$PWD/3rd/OpenSSL/lib/ios/iphone/libssl.a + } else { + message("Building for iOS/ARM v7 (32-bit) architecture") + ARCH_TAG = "ios_armv7" } + } +# } + - CONFIG(iphonesimulator, iphoneos|iphonesimulator) { - message("Building for iPhone Simulator") - ARCH_TAG = "ios_x86_64" +# CONFIG(iphonesimulator, iphoneos|iphonesimulator) { +# iphonesimulator { +# message("Building for iPhone Simulator") +# ARCH_TAG = "ios_x86_64" +# +# DEFINES += iphonesimulator +# +# LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libcrypto.a +# LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libssl.a +# } +# } - DEFINES += iphonesimulator + NETWORKEXTENSION=1 +# ! build_pass: system(ruby $$PWD/scripts/xcode_patcher.rb "$$PWD" "$$OUT_PWD/AmneziaVPN.xcodeproj" "2.0" "2.0.0" "ios" "$$NETWORKEXTENSION"|| echo "Failed to merge xcode with wireguard") - LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libcrypto.a - LIBS += $$PWD/3rd/OpenSSL/lib/ios/simulator/libssl.a - } + + +#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/configurators/vpn_configurator.cpp b/client/configurators/vpn_configurator.cpp index 0b4d9170..d9887f0a 100644 --- a/client/configurators/vpn_configurator.cpp +++ b/client/configurators/vpn_configurator.cpp @@ -18,22 +18,22 @@ Settings &VpnConfigurator::m_settings() } QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentials, - DockerContainer container, const QJsonObject &containerConfig, Protocol proto, ErrorCode *errorCode) + DockerContainer container, const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode) { switch (proto) { - case Protocol::OpenVpn: + case Proto::OpenVpn: return OpenVpnConfigurator::genOpenVpnConfig(credentials, container, containerConfig, errorCode); - case Protocol::ShadowSocks: + case Proto::ShadowSocks: return ShadowSocksConfigurator::genShadowSocksConfig(credentials, container, containerConfig, errorCode); - case Protocol::Cloak: + case Proto::Cloak: return CloakConfigurator::genCloakConfig(credentials, container, containerConfig, errorCode); - case Protocol::WireGuard: + case Proto::WireGuard: return WireguardConfigurator::genWireguardConfig(credentials, container, containerConfig, errorCode); - case Protocol::Ikev2: + case Proto::Ikev2: return Ikev2Configurator::genIkev2Config(credentials, container, containerConfig, errorCode); default: @@ -41,23 +41,23 @@ QString VpnConfigurator::genVpnProtocolConfig(const ServerCredentials &credentia } } -QString VpnConfigurator::processConfigWithLocalSettings(DockerContainer container, Protocol proto, QString config) +QString VpnConfigurator::processConfigWithLocalSettings(DockerContainer container, Proto proto, QString config) { config.replace("$PRIMARY_DNS", m_settings().primaryDns()); config.replace("$SECONDARY_DNS", m_settings().secondaryDns()); - if (proto == Protocol::OpenVpn) { + if (proto == Proto::OpenVpn) { return OpenVpnConfigurator::processConfigWithLocalSettings(config); } return config; } -QString VpnConfigurator::processConfigWithExportSettings(DockerContainer container, Protocol proto, QString config) +QString VpnConfigurator::processConfigWithExportSettings(DockerContainer container, Proto proto, QString config) { config.replace("$PRIMARY_DNS", m_settings().primaryDns()); config.replace("$SECONDARY_DNS", m_settings().secondaryDns()); - if (proto == Protocol::OpenVpn) { + if (proto == Proto::OpenVpn) { return OpenVpnConfigurator::processConfigWithExportSettings(config); } return config; @@ -66,7 +66,7 @@ QString VpnConfigurator::processConfigWithExportSettings(DockerContainer contain void VpnConfigurator::updateContainerConfigAfterInstallation(DockerContainer container, QJsonObject &containerConfig, const QString &stdOut) { - Protocol mainProto = ContainerProps::defaultProtocol(container); + Proto mainProto = ContainerProps::defaultProtocol(container); if (container == DockerContainer::TorWebSite) { QJsonObject protocol = containerConfig.value(ProtocolProps::protoToString(mainProto)).toObject(); diff --git a/client/configurators/vpn_configurator.h b/client/configurators/vpn_configurator.h index 930a6715..b7ced4d6 100644 --- a/client/configurators/vpn_configurator.h +++ b/client/configurators/vpn_configurator.h @@ -13,10 +13,10 @@ class VpnConfigurator public: static QString genVpnProtocolConfig(const ServerCredentials &credentials, DockerContainer container, - const QJsonObject &containerConfig, Protocol proto, ErrorCode *errorCode = nullptr); + const QJsonObject &containerConfig, Proto proto, ErrorCode *errorCode = nullptr); - static QString processConfigWithLocalSettings(DockerContainer container, Protocol proto, QString config); - static QString processConfigWithExportSettings(DockerContainer container, Protocol proto, QString config); + static QString processConfigWithLocalSettings(DockerContainer container, Proto proto, QString config); + static QString processConfigWithExportSettings(DockerContainer container, Proto proto, QString config); // workaround for containers which is not support normal configaration static void updateContainerConfigAfterInstallation(DockerContainer container, 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/containers/containers_defs.cpp b/client/containers/containers_defs.cpp index f6f3415c..63a00e0b 100644 --- a/client/containers/containers_defs.cpp +++ b/client/containers/containers_defs.cpp @@ -27,29 +27,29 @@ QString ContainerProps::containerToString(amnezia::DockerContainer c){ return "amnezia-" + containerKey.toLower(); } -QVector ContainerProps::protocolsForContainer(amnezia::DockerContainer container) +QVector ContainerProps::protocolsForContainer(amnezia::DockerContainer container) { switch (container) { case DockerContainer::None: return { }; case DockerContainer::OpenVpn: - return { Protocol::OpenVpn }; + return { Proto::OpenVpn }; case DockerContainer::ShadowSocks: - return { Protocol::OpenVpn, Protocol::ShadowSocks }; + return { Proto::OpenVpn, Proto::ShadowSocks }; case DockerContainer::Cloak: - return { Protocol::OpenVpn, Protocol::ShadowSocks, Protocol::Cloak }; + return { Proto::OpenVpn, Proto::ShadowSocks, Proto::Cloak }; case DockerContainer::Ipsec: - return { Protocol::Ikev2 /*, Protocol::L2tp */}; + return { Proto::Ikev2 /*, Protocol::L2tp */}; case DockerContainer::Dns: return { }; case DockerContainer::Sftp: - return { Protocol::Sftp}; + return { Proto::Sftp}; default: return { defaultProtocol(container) }; @@ -118,21 +118,21 @@ amnezia::ServiceType ContainerProps::containerService(DockerContainer c) } } -Protocol ContainerProps::defaultProtocol(DockerContainer c) +Proto ContainerProps::defaultProtocol(DockerContainer c) { switch (c) { - case DockerContainer::None : return Protocol::Any; - case DockerContainer::OpenVpn : return Protocol::OpenVpn; - case DockerContainer::Cloak : return Protocol::Cloak; - case DockerContainer::ShadowSocks : return Protocol::ShadowSocks; - case DockerContainer::WireGuard : return Protocol::WireGuard; - case DockerContainer::Ipsec : return Protocol::Ikev2; + case DockerContainer::None : return Proto::Any; + case DockerContainer::OpenVpn : return Proto::OpenVpn; + case DockerContainer::Cloak : return Proto::Cloak; + case DockerContainer::ShadowSocks : return Proto::ShadowSocks; + case DockerContainer::WireGuard : return Proto::WireGuard; + case DockerContainer::Ipsec : return Proto::Ikev2; - case DockerContainer::TorWebSite : return Protocol::TorWebSite; - case DockerContainer::Dns : return Protocol::Dns; + case DockerContainer::TorWebSite : return Proto::TorWebSite; + case DockerContainer::Dns : return Proto::Dns; //case DockerContainer::FileShare : return Protocol::FileShare; - case DockerContainer::Sftp : return Protocol::Sftp; - default: return Protocol::Any; + case DockerContainer::Sftp : return Proto::Sftp; + default: return Proto::Any; } } @@ -140,7 +140,6 @@ bool ContainerProps::isWorkingOnPlatform(DockerContainer c) { #ifdef Q_OS_WINDOWS return true; -#elif defined (Q_OS_MAC) #elif defined (Q_OS_IOS) switch (c) { @@ -148,6 +147,9 @@ bool ContainerProps::isWorkingOnPlatform(DockerContainer c) case DockerContainer::OpenVpn: return true; default: return false; } +#elif defined (Q_OS_MAC) + return false; + #elif defined (Q_OS_ANDROID) switch (c) { case DockerContainer::WireGuard: return true; @@ -156,6 +158,7 @@ bool ContainerProps::isWorkingOnPlatform(DockerContainer c) } #elif defined (Q_OS_LINUX) + return false; #else return false; diff --git a/client/containers/containers_defs.h b/client/containers/containers_defs.h index eced3c32..0fd1ce4a 100644 --- a/client/containers/containers_defs.h +++ b/client/containers/containers_defs.h @@ -46,13 +46,13 @@ public: Q_INVOKABLE static QMap containerDescriptions(); // these protocols will be displayed in container settings - Q_INVOKABLE static QVector protocolsForContainer(DockerContainer container); + Q_INVOKABLE static QVector protocolsForContainer(DockerContainer container); Q_INVOKABLE static ServiceType containerService(DockerContainer c); // binding between Docker container and main protocol of given container // it may be changed fot future containers :) - Q_INVOKABLE static Protocol defaultProtocol(DockerContainer c); + Q_INVOKABLE static Proto defaultProtocol(DockerContainer c); Q_INVOKABLE static bool isWorkingOnPlatform(DockerContainer c); }; diff --git a/client/core/privileged_process.cpp b/client/core/privileged_process.cpp index 3852236f..82a114de 100644 --- a/client/core/privileged_process.cpp +++ b/client/core/privileged_process.cpp @@ -1,5 +1,6 @@ #include "privileged_process.h" +#ifndef Q_OS_IOS PrivilegedProcess::PrivilegedProcess() : IpcProcessInterfaceReplica() { @@ -25,3 +26,4 @@ void PrivilegedProcess::waitForFinished(int msecs) loop->exec(); } +#endif // Q_OS_IOS diff --git a/client/core/privileged_process.h b/client/core/privileged_process.h index bf85fed1..62829bc5 100644 --- a/client/core/privileged_process.h +++ b/client/core/privileged_process.h @@ -20,11 +20,11 @@ public: }; -#endif // PRIVILEGED_PROCESS_H - #else // defined Q_OS_IOS class IpcProcessInterfaceReplica {}; class PrivilegedProcess {}; -#endif +#endif // Q_OS_IOS + +#endif // PRIVILEGED_PROCESS_H diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index 06479316..1e4c9c8d 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -454,7 +454,7 @@ ErrorCode ServerController::updateContainer(const ServerCredentials &credentials QJsonObject ServerController::createContainerInitialConfig(DockerContainer container, int port, TransportProto tp) { - Protocol mainProto = ContainerProps::defaultProtocol(container); + Proto mainProto = ContainerProps::defaultProtocol(container); QJsonObject config { { config_key::container, ContainerProps::containerToString(container) } @@ -621,11 +621,11 @@ ErrorCode ServerController::startupContainerWorker(const ServerCredentials &cred ServerController::Vars ServerController::genVarsForScript(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config) { - const QJsonObject &openvpnConfig = config.value(ProtocolProps::protoToString(Protocol::OpenVpn)).toObject(); - const QJsonObject &cloakConfig = config.value(ProtocolProps::protoToString(Protocol::Cloak)).toObject(); - const QJsonObject &ssConfig = config.value(ProtocolProps::protoToString(Protocol::ShadowSocks)).toObject(); - const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Protocol::WireGuard)).toObject(); - const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Protocol::Sftp)).toObject(); + const QJsonObject &openvpnConfig = config.value(ProtocolProps::protoToString(Proto::OpenVpn)).toObject(); + const QJsonObject &cloakConfig = config.value(ProtocolProps::protoToString(Proto::Cloak)).toObject(); + const QJsonObject &ssConfig = config.value(ProtocolProps::protoToString(Proto::ShadowSocks)).toObject(); + const QJsonObject &wireguarConfig = config.value(ProtocolProps::protoToString(Proto::WireGuard)).toObject(); + const QJsonObject &sftpConfig = config.value(ProtocolProps::protoToString(Proto::Sftp)).toObject(); // Vars vars; @@ -694,7 +694,7 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential // Sftp vars - vars.append({{"$SFTP_PORT", sftpConfig.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Protocol::Sftp))) }}); + vars.append({{"$SFTP_PORT", sftpConfig.value(config_key::port).toString(QString::number(ProtocolProps::defaultPort(Proto::Sftp))) }}); vars.append({{"$SFTP_USER", sftpConfig.value(config_key::userName).toString() }}); vars.append({{"$SFTP_PASSWORD", sftpConfig.value(config_key::password).toString() }}); 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 00000000..1933ed99 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-1024@1x.png differ 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 00000000..c6c1b888 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@1x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@2x-1.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@2x-1.png new file mode 100644 index 00000000..9c9a8f01 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@2x-1.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@2x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@2x.png new file mode 100644 index 00000000..9c9a8f01 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@2x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@3x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@3x.png new file mode 100644 index 00000000..5f43b0d4 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-20@3x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@1x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@1x.png new file mode 100644 index 00000000..b8fa9934 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@1x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@2x-1.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@2x-1.png new file mode 100644 index 00000000..7e27a54d Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@2x-1.png differ 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 00000000..7e27a54d Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@2x.png differ 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 00000000..d408007f Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-29@3x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@1x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@1x.png new file mode 100644 index 00000000..2f241c64 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@1x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@2x-1.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@2x-1.png new file mode 100644 index 00000000..bae292db Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@2x-1.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@2x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@2x.png new file mode 100644 index 00000000..bae292db Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@2x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@3x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@3x.png new file mode 100644 index 00000000..8cc41427 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-40@3x.png differ 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 00000000..8cc41427 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-60@2x.png differ 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 00000000..a60b8ff7 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-60@3x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-76@1x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-76@1x.png new file mode 100644 index 00000000..ddf46a91 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-76@1x.png differ 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 00000000..f26844e1 Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-76@2x.png differ diff --git a/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-83.5@2x.png b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-83.5@2x.png new file mode 100644 index 00000000..03a92fae Binary files /dev/null and b/client/ios/app/Images.xcassets/AppIcon.appiconset/icon-ios-83.5@2x.png differ 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..3c0f289e --- /dev/null +++ b/client/ios/app/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleAllowMixedLocalizations + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + AmneziaVPN + 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 + UIRequiresFullScreen + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIUserInterfaceStyle + Light + + diff --git a/client/ios/app/launch.png b/client/ios/app/launch.png new file mode 100644 index 00000000..33bb9d7d Binary files /dev/null and b/client/ios/app/launch.png differ diff --git a/client/ios/app/main.entitlements b/client/ios/app/main.entitlements new file mode 100644 index 00000000..fa993a87 --- /dev/null +++ b/client/ios/app/main.entitlements @@ -0,0 +1,20 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.security.application-groups + + group.ru.kotit.AmneziaVPN.udev + + com.apple.security.files.user-selected.read-write + + keychain-access-groups + + $(AppIdentifierPrefix)group.ru.kotit.AmneziaVPN.udev + + + diff --git a/client/ios/networkextension/AmneziaVPNNetworkExtension.entitlements b/client/ios/networkextension/AmneziaVPNNetworkExtension.entitlements new file mode 100644 index 00000000..efcee280 --- /dev/null +++ b/client/ios/networkextension/AmneziaVPNNetworkExtension.entitlements @@ -0,0 +1,18 @@ + + + + + com.apple.developer.networking.networkextension + + packet-tunnel-provider + + com.apple.security.application-groups + + group.ru.kotit.AmneziaVPN.udev + + keychain-access-groups + + $(AppIdentifierPrefix)group.ru.kotit.AmneziaVPN.udev + + + 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: