diff --git a/client/3rd/QtSsh/src/botan/botan.cmake b/client/3rd/QtSsh/src/botan/botan.cmake index a06d07b7..e51ce51f 100644 --- a/client/3rd/QtSsh/src/botan/botan.cmake +++ b/client/3rd/QtSsh/src/botan/botan.cmake @@ -62,4 +62,12 @@ if(IOS) # HEADERS += $$PWD/ios/iphone/botan_all.h # SOURCES += $$PWD/ios/iphone/botan_all.cpp # } + + link_directories(${CMAKE_CURRENT_LIST_DIR}/ios/iphone) + set(HEADERS ${HEADERS} ${CMAKE_CURRENT_LIST_DIR}/ios/iphone/botan_all.h) + set(SOURCES ${SOURCES} ${CMAKE_CURRENT_LIST_DIR}/ios/iphone/botan_all.cpp) + + + + endif() diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 44aa9350..8e8acb2d 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -161,22 +161,61 @@ if(WIN32) ) endif() endif() - -if(APPLE) - add_compile_definitions(MVPN_MACOS) +if(APPLE) + + if(NOT BUILD_OSX_APP_IDENTIFIER) + set(BUILD_OSX_APP_IDENTIFIER org.amnezia.AmneziaVPN CACHE STRING "OSX Application identifier") + endif() + if(NOT BUILD_IOS_APP_IDENTIFIER) + set(BUILD_IOS_APP_IDENTIFIER org.amnezia.AmneziaVPN CACHE STRING "iOS Application identifier") + endif() + if(NOT BUILD_IOS_GROUP_IDENTIFIER) + set(BUILD_IOS_GROUP_IDENTIFIER group.org.amnezia.AmneziaVPN.Guardian CACHE STRING "iOS Group identifier") + endif() + if(NOT BUILD_VPN_DEVELOPMENT_TEAM) + set(BUILD_VPN_DEVELOPMENT_TEAM X7UJ388FXK CACHE STRING "Amnezia VPN Development Team") + endif() + + if(IOS) + message("ios in mac") + #do nothing, IOS is added in below + else() #mac + + message("MAC build") + set(HEADERS ${HEADERS} ${CMAKE_CURRENT_LIST_DIR}/ui/macos_util.h) + set(SOURCES ${SOURCES} ${CMAKE_CURRENT_LIST_DIR}/ui/macos_util.mm) + + # set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14) + add_compile_definitions(MVPN_MACOS) # ICON = $$PWD/images/app.icns - set(HEADERS ${HEADERS} ${CMAKE_CURRENT_LIST_DIR}/ui/macos_util.h) - set(SOURCES ${SOURCES} ${CMAKE_CURRENT_LIST_DIR}/ui/macos_util.mm) - # LIBS += -framework Cocoa -framework ApplicationServices -framework CoreServices -framework Foundation -framework AppKit -framework Security + message(STATUS "test ${PROJECT_SOURCE_DIR}") - # LIBS += $$PWD/3rd/OpenSSL/lib/macos/x86_64/libcrypto.a - # LIBS += $$PWD/3rd/OpenSSL/lib/macos/x86_64/libssl.a + find_library(LIB_LIBCRYPTO NAMES "libcrypto.a" + PATHS ${PROJECT_SOURCE_DIR}/3rd/OpenSSL/lib/macos/x86_64/ NO_DEFAULT_PATH) + + find_library(LIB_SSL NAMES "libssl.a" + PATHS ${PROJECT_SOURCE_DIR}/3rd/OpenSSL/lib/macos/x86_64/ NO_DEFAULT_PATH) + + + find_library(FW_COCOA Cocoa) + find_library(FW_APPLICATIONSERVICES ApplicationServices) + find_library(FW_CORESERVICES CoreServices) + find_library(FW_FOUNDATION Foundation) + find_library(FW_APPKIT AppKit) + find_library(FW_SECURITY Security) + + set(LIBS ${LIBS} FW_COCOA FW_APPLICATIONSERVICES FW_FOUNDATION FW_APPKIT FW_SECURITY FW_CORESERVICES + LIB_LIBCRYPTO LIB_SSL) + + + endif() endif() + if(LINUX AND NOT ANDROID) add_compile_definitions(MVPN_LINUX) @@ -189,7 +228,7 @@ if(LINUX AND NOT ANDROID) link_directories(${CMAKE_CURRENT_LIST_DIR}/platforms/linux) endif() -if(WIN32 OR APPLE OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) message("Client desktop build") add_compile_definitions(AMNEZIA_DESKTOP) @@ -238,20 +277,25 @@ if(ANDROID) ) endif() +qt_add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC}) +qt_add_translations(${PROJECT} TS_FILES + ${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts) + if(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 + find_library(FW_AUTHENTICATIONSERVICES AuthenticationServices) + find_library(FW_UIKIT UIKit) + find_library(FW_FOUNDATION Foundation) + find_library(FW_STOREKIT StoreKit) + find_library(FW_USERNOTIFICATIONS UserNotifications) + + set(LIBS ${LIBS} FW_AUTHENTICATIONSERVICES FW_UIKIT FW_FOUNDATION FW_STOREKIT FW_USERNOTIFICATIONS) add_compile_definitions(MVPN_IOS) @@ -267,7 +311,7 @@ if(IOS) ${CMAKE_CURRENT_LIST_DIR}/platforms/ios/QtAppDelegate-C-Interface.h ) - # i think in cmake it is not necessary? + # i think in cmake it is not necessary? yes in iOS we are using native # SOURCES -= # platforms/ios/QRCodeReaderBase.cpp # platforms/ios/MobileUtils.cpp @@ -284,11 +328,44 @@ if(IOS) ${CMAKE_CURRENT_LIST_DIR}/platforms/ios/MobileUtils.mm ) + + + + set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "NO") + add_subdirectory(ios/networkextension) + add_dependencies(${PROJECT} networkextension) + set_target_properties(${PROJECT} PROPERTIES XCODE_EMBED_APP_EXTENSIONS networkextension) + # Q_ENABLE_BITCODE.value = NO # Q_ENABLE_BITCODE.name = ENABLE_BITCODE # QMAKE_MAC_XCODE_SETTINGS += Q_ENABLE_BITCODE endif() +if(CMAKE_OSX_SYSROOT STREQUAL "iphoneos") + message("Building for iPhone OS") + set(CMAKE_OSX_DEPLOYMENT_TARGET 13.0) + + + + set_target_properties(${PROJECT} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.amnezia.${PROJECT}" + OUTPUT_NAME "AmneziaVPN" + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1" + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "X7UJ388FXK" + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/ios/app/Info.plist + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Development") + + find_library(LIB_LIBCRYPTO NAMES "libcrypto.a" + PATHS ${PROJECT_SOURCE_DIR}/3rd/OpenSSL/lib/ios/iphone/ NO_DEFAULT_PATH) + + find_library(LIB_SSL NAMES "libssl.a" + PATHS ${PROJECT_SOURCE_DIR}/3rd/OpenSSL/lib/ios/iphone/ NO_DEFAULT_PATH) + + # set(LIBS ${LIBS} LIB_LIBCRYPTO LIB_SSL) + + +endif() + + #if(IPHONEOS) # message("Building for iPhone OS") # QMAKE_TARGET_BUNDLE_PREFIX = org.amnezia @@ -296,11 +373,11 @@ endif() # 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_PROVISIONING_PROFILE = f2fefb59-14aa-4aa9-ac14-1d5531b06dcc not added yet # QMAKE_XCODE_CODE_SIGN_IDENTITY = "Apple Distribution" # QMAKE_INFO_PLIST = $$PWD/ios/app/Info.plist - # XCODEBUILD_FLAGS += -allowProvisioningUpdates + # XCODEBUILD_FLAGS += -allowProvisioningUpdates not added yet # DEFINES += iphoneos @@ -318,10 +395,7 @@ endif() # NETWORKEXTENSION=1 -qt_add_executable(${PROJECT} ${SOURCES} ${HEADERS} ${RESOURCES} ${QRC}) -qt_add_translations(${PROJECT} TS_FILES - ${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts) if(ANDROID) add_custom_command( @@ -376,7 +450,7 @@ target_link_libraries(${PROJECT} PRIVATE Qt6::Core5Compat ${LIBS} ) -if(WIN32 OR APPLE OR (LINUX AND NOT ANDROID)) +if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID)) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_interface.rep) qt_add_repc_replicas(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc_process_interface.rep) endif() diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index c86ba303..c7336b62 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -662,6 +662,11 @@ ServerController::Vars ServerController::genVarsForScript(const ServerCredential vars.append({{"$OPENVPN_TA_KEY", "" }}); } + vars.append({{"$OPENVPN_ADDITIONAL_CLIENT_CONFIG", openvpnConfig.value(config_key::additional_client_config). + toString(protocols::openvpn::defaultAdditionalClientConfig) }}); + vars.append({{"$OPENVPN_ADDITIONAL_SERVER_CONFIG", openvpnConfig.value(config_key::additional_server_config). + toString(protocols::openvpn::defaultAdditionalServerConfig) }}); + // ShadowSocks vars vars.append({{"$SHADOWSOCKS_SERVER_PORT", ssConfig.value(config_key::port).toString(protocols::shadowsocks::defaultPort) }}); vars.append({{"$SHADOWSOCKS_LOCAL_PORT", ssConfig.value(config_key::local_port).toString(protocols::shadowsocks::defaultLocalProxyPort) }}); diff --git a/client/ios/networkextension/CMakeLists.txt b/client/ios/networkextension/CMakeLists.txt new file mode 100644 index 00000000..5a8e76fb --- /dev/null +++ b/client/ios/networkextension/CMakeLists.txt @@ -0,0 +1,105 @@ +enable_language(Swift) + +add_executable(networkextension) +set_target_properties(networkextension PROPERTIES + OUTPUT_NAME "AmneziaVPNNetworkExtension" + XCODE_PRODUCT_TYPE com.apple.product-type.app-extension + BUNDLE_EXTENSION appex + MACOSX_BUNDLE ON + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + MACOSX_BUNDLE_BUNDLE_NAME "AmneziaVPNNetworkExtension" + MACOSX_BUNDLE_BUNDLE_VERSION "${BUILD_ID}" + MACOSX_BUNDLE_COPYRIGHT "MPL-2.0" + MACOSX_BUNDLE_GUI_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}.network-extension" + MACOSX_BUNDLE_INFO_STRING "MozillaVPNNetworkExtension" + MACOSX_BUNDLE_LONG_VERSION_STRING "${CMAKE_PROJECT_VERSION}-${BUILD_ID}" + MACOSX_BUNDLE_SHORT_VERSION_STRING "${CMAKE_PROJECT_VERSION}" + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${BUILD_IOS_APP_IDENTIFIER}.network-extension" + XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" + XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES" + XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/WireGuardNetworkExtension-Bridging-Header.h" + XCODE_ATTRIBUTE_SWIFT_PRECOMPILE_BRIDGING_HEADER "NO" + XCODE_ATTRIBUTE_APPLICATION_EXTENSION_API_ONLY "YES" + XCODE_ATTRIBUTE_ENABLE_BITCODE "NO" + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS ${CMAKE_CURRENT_SOURCE_DIR}/AmneziaVPNNetworkExtension.entitlements +) + +find_library(FW_ASSETS_LIBRARY AssetsLibrary) +find_library(FW_MOBILE_CORE MobileCoreServices) +find_library(FW_UI_KIT UIKit) + +target_link_libraries(networkextension PRIVATE ${FW_ASSETS_LIBRARY}) +target_link_libraries(networkextension PRIVATE ${FW_MOBILE_CORE}) +target_link_libraries(networkextension PRIVATE ${FW_UI_KIT}) + +target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\") +target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1) + +set(WG_APPLE_SOURCE_DIR ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources) + +target_sources(networkextension PRIVATE + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/WireGuardAdapter.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PacketTunnelSettingsGenerator.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSResolver.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardNetworkExtension/ErrorNotifier.swift + ${WG_APPLE_SOURCE_DIR}/Shared/Keychain.swift + ${WG_APPLE_SOURCE_DIR}/Shared/Model/TunnelConfiguration+WgQuickConfig.swift + ${WG_APPLE_SOURCE_DIR}/Shared/Model/NETunnelProviderProtocol+Extension.swift + ${WG_APPLE_SOURCE_DIR}/Shared/Model/String+ArrayConversion.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/TunnelConfiguration.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddressRange.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/Endpoint.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/DNSServer.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/InterfaceConfiguration.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PeerConfiguration.swift + ${WG_APPLE_SOURCE_DIR}/Shared/FileManager+Extension.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKitC/x25519.c + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift + ${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift + ${CMAKE_SOURCE_DIR}/platforms/ios/iostunnel.swift + ${CMAKE_SOURCE_DIR}/platforms/ios/iosglue.mm + ${CMAKE_SOURCE_DIR}/platforms/ios/ioslogger.swift +) + +## Build wireguard-go-version.h +execute_process( + COMMAND go list -m golang.zx2c4.com/wireguard + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo + OUTPUT_VARIABLE WG_VERSION_FULL +) +string(REGEX REPLACE ".*v\([0-9.]*\).*" "\\1" WG_VERSION_STRING 1.1.1) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/wireguard-go-version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/wireguard-go-version.h) +target_sources(networkextension PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/wireguard-go-version.h) + +target_include_directories(networkextension PRIVATE ${CMAKE_SOURCE_DIR}) +target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) + +## HACK: Build only the first architecture, this will break universal builds +## for now, but they are already broken for mobile, which uses the arch to +## determine iOS vs. simulator builds :) +if(NOT CMAKE_OSX_ARCHITECTURES) + set(OSXARCH arm64) +else() + list(GET CMAKE_OSX_ARCHITECTURES 0 OSXARCH) +endif() + +## Build the wireguard go library +## TODO: The upstream makefile also makes an attempt to patch the golang runtime +## to provide the boot-time clock instead of an uptime clock. We should probably +## make an attempt to do the same, somehow? +include(${CMAKE_SOURCE_DIR}/src/cmake/golang.cmake) +if(OSXARCH STREQUAL "x86_64") + set(GOARCH amd64) +else() + set(GOARCH ${FIRST_OSX_ARCHITECTURE}) +endif() +add_go_library(libwg-go ${CMAKE_SOURCE_DIR}/3rd/wireguard-apple/Sources/WireGuardKitGo/api-apple.go + GOOS ios + GOARCH ${GOARCH} + CGO_CFLAGS -arch ${OSXARCH} + CGO_LDFLAGS -arch ${OSXARCH} +) +target_link_libraries(networkextension PRIVATE libwg-go) \ No newline at end of file diff --git a/client/ios/networkextension/Info.plist b/client/ios/networkextension/Info.plist new file mode 100644 index 00000000..6941af53 --- /dev/null +++ b/client/ios/networkextension/Info.plist @@ -0,0 +1,52 @@ + + + + + CFBundleExecutable + $(EXECUTABLE_NAME) + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundleName + $(PRODUCT_NAME) + + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + + CFBundleShortVersionString + $(MARKETING_VERSION) + + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + ITSAppUsesNonExemptEncryption + + + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + + CFBundleDisplayName + MozillaVPNNetworkExtension + + NSExtension + + NSExtensionPointIdentifier + com.apple.networkextension.packet-tunnel + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).PacketTunnelProvider + + + com.wireguard.ios.app_group_id + group.$(APP_ID_IOS) + + com.wireguard.macos.app_group_id + $(DEVELOPMENT_TEAM).group.$(APP_ID_MACOS) + + \ No newline at end of file diff --git a/client/ios/networkextension/Info.plist.in b/client/ios/networkextension/Info.plist.in new file mode 100644 index 00000000..54d9d8d9 --- /dev/null +++ b/client/ios/networkextension/Info.plist.in @@ -0,0 +1,46 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + + ITSAppUsesNonExemptEncryption + + + LSMinimumSystemVersion + ${CMAKE_OSX_DEPLOYMENT_TARGET} + + CFBundleDisplayName + ${MACOSX_BUNDLE_INFO_STRING} + + NSExtension + + NSExtensionPointIdentifier + com.apple.networkextension.packet-tunnel + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).PacketTunnelProvider + + + com.wireguard.ios.app_group_id + group.${BUILD_IOS_APP_IDENTIFIER} + + com.wireguard.macos.app_group_id + ${BUILD_VPN_DEVELOPMENT_TEAM}.group.${BUILD_OSX_APP_IDENTIFIER} + + \ No newline at end of file diff --git a/client/ios/networkextension/WireGuardNetworkExtension-Bridging-Header.h b/client/ios/networkextension/WireGuardNetworkExtension-Bridging-Header.h new file mode 100644 index 00000000..03a987ad --- /dev/null +++ b/client/ios/networkextension/WireGuardNetworkExtension-Bridging-Header.h @@ -0,0 +1,21 @@ +#include "wireguard-go-version.h" +#include "3rd/wireguard-apple/Sources/WireGuardKitGo/wireguard.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); diff --git a/client/ios/networkextension/wireguard-go-version.h.in b/client/ios/networkextension/wireguard-go-version.h.in new file mode 100644 index 00000000..860bc3c3 --- /dev/null +++ b/client/ios/networkextension/wireguard-go-version.h.in @@ -0,0 +1,3 @@ +#ifndef WIREGUARD_GO_VERSION +#define WIREGUARD_GO_VERSION "@WG_VERSION_STRING@" +#endif // WIREGUARD_GO_VERSION \ No newline at end of file diff --git a/client/platforms/ios/iostunnel.swift b/client/platforms/ios/iostunnel.swift index 5209306d..b273f9f4 100644 --- a/client/platforms/ios/iostunnel.swift +++ b/client/platforms/ios/iostunnel.swift @@ -2,7 +2,7 @@ import Foundation import NetworkExtension import os import Darwin -import OpenVPNAdapter +//import OpenVPNAdapter //import Tun2socks enum TunnelProtoType: String { @@ -48,11 +48,11 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } }() - private lazy var ovpnAdapter: OpenVPNAdapter = { - let adapter = OpenVPNAdapter() - adapter.delegate = self - return adapter - }() +// private lazy var ovpnAdapter: OpenVPNAdapter = { +// let adapter = OpenVPNAdapter() +// adapter.delegate = self +// return adapter +// }() private var shadowSocksConfig: Data? = nil private var openVPNConfig: Data? = nil @@ -70,7 +70,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { // private var session: NWUDPSession? = nil // private var observer: AnyObject? - let vpnReachability = OpenVPNReachability() +// let vpnReachability = OpenVPNReachability() var startHandler: ((Error?) -> Void)? var stopHandler: (() -> Void)? @@ -97,7 +97,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider { errorNotifier: errorNotifier, completionHandler: completionHandler) case .openvpn: - startOpenVPN(completionHandler: completionHandler) + break + //startOpenVPN(completionHandler: completionHandler) case .shadowsocks: break // startShadowSocks(completionHandler: completionHandler) @@ -111,7 +112,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider { case .wireguard: stopWireguard(with: reason, completionHandler: completionHandler) case .openvpn: - stopOpenVPN(with: reason, completionHandler: completionHandler) + break + // stopOpenVPN(with: reason, completionHandler: completionHandler) case .shadowsocks: break // stopShadowSocks(with: reason, completionHandler: completionHandler) @@ -187,17 +189,17 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } - private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) { - guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol, - let providerConfiguration = protocolConfiguration.providerConfiguration, - let ovpnConfiguration: Data = providerConfiguration[Constants.ovpnConfigKey] as? Data else { - // TODO: handle errors properly - wg_log(.error, message: "Can't start startOpenVPN()") - return - } - - setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler) - } +// private func startOpenVPN(completionHandler: @escaping (Error?) -> Void) { +// guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol, +// let providerConfiguration = protocolConfiguration.providerConfiguration, +// let ovpnConfiguration: Data = providerConfiguration[Constants.ovpnConfigKey] as? Data else { +// // TODO: handle errors properly +// wg_log(.error, message: "Can't start startOpenVPN()") +// return +// } +// +// setupAndlaunchOpenVPN(withConfig: ovpnConfiguration, completionHandler: completionHandler) +// } /* private func startShadowSocks(completionHandler: @escaping (Error?) -> Void) { guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol, @@ -236,13 +238,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } - private func stopOpenVPN(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { - stopHandler = completionHandler - if vpnReachability.isTracking { - vpnReachability.stopTracking() - } - ovpnAdapter.disconnect() - } +// private func stopOpenVPN(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { +// stopHandler = completionHandler +// if vpnReachability.isTracking { +// vpnReachability.stopTracking() +// } +// ovpnAdapter.disconnect() +// } /* private func stopShadowSocks(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { stopOpenVPN(with: reason) { [weak self] in @@ -686,47 +688,47 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } } */ - private func setupAndlaunchOpenVPN(withConfig ovpnConfiguration: Data, withShadowSocks viaSS: Bool = false, completionHandler: @escaping (Error?) -> Void) { - wg_log(.info, message: "Inside setupAndlaunchOpenVPN()") - let str = String(decoding: ovpnConfiguration, as: UTF8.self) - wg_log(.info, message: "OPENVPN config: \(str)") - - let configuration = OpenVPNConfiguration() - configuration.fileContent = ovpnConfiguration - if viaSS { -// configuration.settings = [ -// "remote": "137.74.6.148 1194", -// "proto": "tcp", -// "link-mtu": "1480", -// "tun-mtu": "1460", -// ] - } - let evaluation: OpenVPNConfigurationEvaluation - do { - evaluation = try ovpnAdapter.apply(configuration: configuration) - } catch { - completionHandler(error) - return - } - - if !evaluation.autologin { - wg_log(.info, message: "Implement login with user credentials") - } - - vpnReachability.startTracking { [weak self] status in - guard status == .reachableViaWiFi else { return } - self?.ovpnAdapter.reconnect(afterTimeInterval: 5) - } - - startHandler = completionHandler - ovpnAdapter.connect(using: packetFlow) - - let ifaces = Interface.allInterfaces() - .filter { $0.family == .ipv4 } - .map { iface in iface.name } - - wg_log(.error, message: "Available TUN Interfaces: \(ifaces)") - } +// private func setupAndlaunchOpenVPN(withConfig ovpnConfiguration: Data, withShadowSocks viaSS: Bool = false, completionHandler: @escaping (Error?) -> Void) { +// wg_log(.info, message: "Inside setupAndlaunchOpenVPN()") +// let str = String(decoding: ovpnConfiguration, as: UTF8.self) +// wg_log(.info, message: "OPENVPN config: \(str)") +// +// let configuration = OpenVPNConfiguration() +// configuration.fileContent = ovpnConfiguration +// if viaSS { +//// configuration.settings = [ +//// "remote": "137.74.6.148 1194", +//// "proto": "tcp", +//// "link-mtu": "1480", +//// "tun-mtu": "1460", +//// ] +// } +// let evaluation: OpenVPNConfigurationEvaluation +// do { +// evaluation = try ovpnAdapter.apply(configuration: configuration) +// } catch { +// completionHandler(error) +// return +// } +// +// if !evaluation.autologin { +// wg_log(.info, message: "Implement login with user credentials") +// } +// +// vpnReachability.startTracking { [weak self] status in +// guard status == .reachableViaWiFi else { return } +// self?.ovpnAdapter.reconnect(afterTimeInterval: 5) +// } +// +// startHandler = completionHandler +// ovpnAdapter.connect(using: packetFlow) +// +// let ifaces = Interface.allInterfaces() +// .filter { $0.family == .ipv4 } +// .map { iface in iface.name } +// +// wg_log(.error, message: "Available TUN Interfaces: \(ifaces)") +// } // MARK: -- Network observing methods @@ -796,87 +798,87 @@ extension WireGuardLogLevel { } } -extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow {} +//extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow {} /* extension NEPacketTunnelFlow: ShadowSocksAdapterPacketFlow {} */ -extension PacketTunnelProvider: OpenVPNAdapterDelegate { - - // OpenVPNAdapter calls this delegate method to configure a VPN tunnel. - // `completionHandler` callback requires an object conforming to `OpenVPNAdapterPacketFlow` - // protocol if the tunnel is configured without errors. Otherwise send nil. - // `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so - // you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and - // send `self.packetFlow` to `completionHandler` callback. - func openVPNAdapter( - _ openVPNAdapter: OpenVPNAdapter, - configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, - completionHandler: @escaping (Error?) -> Void - ) { - // In order to direct all DNS queries first to the VPN DNS servers before the primary DNS servers - // send empty string to NEDNSSettings.matchDomains - networkSettings?.dnsSettings?.matchDomains = [""] - - // Set the network settings for the current tunneling session. - setTunnelNetworkSettings(networkSettings, completionHandler: completionHandler) - } - - // Process events returned by the OpenVPN library - func openVPNAdapter( - _ openVPNAdapter: OpenVPNAdapter, - handleEvent event: - OpenVPNAdapterEvent, message: String? - ) { - switch event { - case .connected: - if reasserting { - reasserting = false - } - - guard let startHandler = startHandler else { return } - - startHandler(nil) - self.startHandler = nil - case .disconnected: - guard let stopHandler = stopHandler else { return } - - if vpnReachability.isTracking { - vpnReachability.stopTracking() - } - - stopHandler() - self.stopHandler = nil - case .reconnecting: - reasserting = true - default: - break - } - } - - // Handle errors thrown by the OpenVPN library - func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) { - // Handle only fatal errors - guard let fatal = (error as NSError).userInfo[OpenVPNAdapterErrorFatalKey] as? Bool, - fatal == true else { return } - - if vpnReachability.isTracking { - vpnReachability.stopTracking() - } - - if let startHandler = startHandler { - startHandler(error) - self.startHandler = nil - } else { - cancelTunnelWithError(error) - } - } - - // Use this method to process any log message returned by OpenVPN library. - func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) { - // Handle log messages - wg_log(.info, message: logMessage) - } -} +//extension PacketTunnelProvider: OpenVPNAdapterDelegate { +// +// // OpenVPNAdapter calls this delegate method to configure a VPN tunnel. +// // `completionHandler` callback requires an object conforming to `OpenVPNAdapterPacketFlow` +// // protocol if the tunnel is configured without errors. Otherwise send nil. +// // `OpenVPNAdapterPacketFlow` method signatures are similar to `NEPacketTunnelFlow` so +// // you can just extend that class to adopt `OpenVPNAdapterPacketFlow` protocol and +// // send `self.packetFlow` to `completionHandler` callback. +// func openVPNAdapter( +// _ openVPNAdapter: OpenVPNAdapter, +// configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, +// completionHandler: @escaping (Error?) -> Void +// ) { +// // In order to direct all DNS queries first to the VPN DNS servers before the primary DNS servers +// // send empty string to NEDNSSettings.matchDomains +// networkSettings?.dnsSettings?.matchDomains = [""] +// +// // Set the network settings for the current tunneling session. +// setTunnelNetworkSettings(networkSettings, completionHandler: completionHandler) +// } +// +// // Process events returned by the OpenVPN library +// func openVPNAdapter( +// _ openVPNAdapter: OpenVPNAdapter, +// handleEvent event: +// OpenVPNAdapterEvent, message: String? +// ) { +// switch event { +// case .connected: +// if reasserting { +// reasserting = false +// } +// +// guard let startHandler = startHandler else { return } +// +// startHandler(nil) +// self.startHandler = nil +// case .disconnected: +// guard let stopHandler = stopHandler else { return } +// +// if vpnReachability.isTracking { +// vpnReachability.stopTracking() +// } +// +// stopHandler() +// self.stopHandler = nil +// case .reconnecting: +// reasserting = true +// default: +// break +// } +// } +// +// // Handle errors thrown by the OpenVPN library +// func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) { +// // Handle only fatal errors +// guard let fatal = (error as NSError).userInfo[OpenVPNAdapterErrorFatalKey] as? Bool, +// fatal == true else { return } +// +// if vpnReachability.isTracking { +// vpnReachability.stopTracking() +// } +// +// if let startHandler = startHandler { +// startHandler(error) +// self.startHandler = nil +// } else { +// cancelTunnelWithError(error) +// } +// } +// +// // Use this method to process any log message returned by OpenVPN library. +// func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) { +// // Handle log messages +// wg_log(.info, message: logMessage) +// } +//} /* extension PacketTunnelProvider: Tun2socksTunWriterProtocol { func write(_ p0: Data?, n: UnsafeMutablePointer?) throws { diff --git a/client/protocols/ios_vpnprotocol.h b/client/protocols/ios_vpnprotocol.h index 2b2971f1..7238fc36 100644 --- a/client/protocols/ios_vpnprotocol.h +++ b/client/protocols/ios_vpnprotocol.h @@ -1,9 +1,9 @@ #ifndef IOS_VPNPROTOCOL_H #define IOS_VPNPROTOCOL_H +#include "platforms/ios/json.h" #include "vpnprotocol.h" #include "protocols/protocols_defs.h" -#include "json.h" using namespace amnezia; diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 1994660b..c158822d 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -53,6 +53,9 @@ constexpr char subnet_address[] = "subnet_address"; constexpr char subnet_mask[] = "subnet_mask"; constexpr char subnet_cidr[] = "subnet_cidr"; +constexpr char additional_client_config[] = "additional_client_config"; +constexpr char additional_server_config[] = "additional_server_config"; + // proto config keys constexpr char last_config[] = "last_config"; } @@ -82,6 +85,8 @@ constexpr bool defaultTlsAuth = true; constexpr char ncpDisableString[] = "ncp-disable"; constexpr char tlsAuthString[] = "tls-auth /opt/amnezia/openvpn/ta.key 0"; +constexpr char defaultAdditionalClientConfig[] = ""; +constexpr char defaultAdditionalServerConfig[] = ""; } namespace shadowsocks { diff --git a/client/server_scripts/openvpn/configure_container.sh b/client/server_scripts/openvpn/configure_container.sh index d51d019b..0499b6e8 100644 --- a/client/server_scripts/openvpn/configure_container.sh +++ b/client/server_scripts/openvpn/configure_container.sh @@ -23,4 +23,5 @@ verb 1 tls-server tls-version-min 1.2 $OPENVPN_TLS_AUTH +$OPENVPN_ADDITIONAL_SERVER_CONFIG EOF diff --git a/client/server_scripts/openvpn/template.ovpn b/client/server_scripts/openvpn/template.ovpn index 6ce736c2..c0b4a044 100644 --- a/client/server_scripts/openvpn/template.ovpn +++ b/client/server_scripts/openvpn/template.ovpn @@ -21,6 +21,8 @@ block-outside-dns remote $REMOTE_HOST $OPENVPN_PORT +$OPENVPN_ADDITIONAL_CLIENT_CONFIG + $OPENVPN_CA_CERT diff --git a/client/server_scripts/openvpn_cloak/configure_container.sh b/client/server_scripts/openvpn_cloak/configure_container.sh index 72961810..26b514a4 100644 --- a/client/server_scripts/openvpn_cloak/configure_container.sh +++ b/client/server_scripts/openvpn_cloak/configure_container.sh @@ -23,6 +23,7 @@ verb 1 tls-server tls-version-min 1.2 $OPENVPN_TLS_AUTH +$OPENVPN_ADDITIONAL_SERVER_CONFIG EOF # Cloak config diff --git a/client/server_scripts/openvpn_cloak/template.ovpn b/client/server_scripts/openvpn_cloak/template.ovpn index 98e0e09f..4fc2b2c3 100644 --- a/client/server_scripts/openvpn_cloak/template.ovpn +++ b/client/server_scripts/openvpn_cloak/template.ovpn @@ -22,6 +22,8 @@ block-outside-dns route $REMOTE_HOST 255.255.255.255 net_gateway remote 127.0.0.1 1194 +$OPENVPN_ADDITIONAL_CLIENT_CONFIG + $OPENVPN_CA_CERT diff --git a/client/server_scripts/openvpn_shadowsocks/configure_container.sh b/client/server_scripts/openvpn_shadowsocks/configure_container.sh index 29a5ebf9..db8fe055 100644 --- a/client/server_scripts/openvpn_shadowsocks/configure_container.sh +++ b/client/server_scripts/openvpn_shadowsocks/configure_container.sh @@ -23,6 +23,7 @@ verb 1 tls-server tls-version-min 1.2 $OPENVPN_TLS_AUTH +$OPENVPN_ADDITIONAL_SERVER_CONFIG EOF # ShadowSocks config diff --git a/client/server_scripts/openvpn_shadowsocks/template.ovpn b/client/server_scripts/openvpn_shadowsocks/template.ovpn index 76b755f6..64cbd4be 100644 --- a/client/server_scripts/openvpn_shadowsocks/template.ovpn +++ b/client/server_scripts/openvpn_shadowsocks/template.ovpn @@ -23,6 +23,8 @@ socks-proxy 127.0.0.1 $SHADOWSOCKS_LOCAL_PORT route $REMOTE_HOST 255.255.255.255 net_gateway remote $REMOTE_HOST $OPENVPN_PORT +$OPENVPN_ADDITIONAL_CLIENT_CONFIG + $OPENVPN_CA_CERT diff --git a/client/src/cmake/golang.cmake b/client/src/cmake/golang.cmake new file mode 100644 index 00000000..2e16db70 --- /dev/null +++ b/client/src/cmake/golang.cmake @@ -0,0 +1,72 @@ +# 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/. + +## Find the absolute path to the go build tool. +find_program(GOLANG_BUILD_TOOL NAMES go REQUIRED) + +## Create a library target built from a golang c-archive. +function(add_go_library GOTARGET SOURCE) + cmake_parse_arguments(GOLANG + "" + "GOOS;GOARCH" + "CGO_CFLAGS;CGO_LDFLAGS" + ${ARGN}) + get_filename_component(SRC_NAME ${SOURCE} NAME) + get_filename_component(DIR_NAME ${SOURCE} DIRECTORY) + get_filename_component(DIR_ABSOLUTE ${DIR_NAME} ABSOLUTE) + + file(GLOB_RECURSE SRC_DEPS ${DIR_NAME}/*.go) + set(HEADER_NAME "${GOTARGET}.h") + set(ARCHIVE_NAME "${GOTARGET}${CMAKE_STATIC_LIBRARY_SUFFIX}") + + set(GOCACHE ${CMAKE_BINARY_DIR}/go-cache) + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CMAKE_BINARY_DIR}/go-cache) + set(GOFLAGS -buildmode=c-archive -trimpath -v) + if(IS_DIRECTORY ${DIR_NAME}/vendor) + set(GOFLAGS ${GOFLAGS} -mod vendor) + endif() + + ## Add extras to the CGO compiler and linker flags. + execute_process(OUTPUT_VARIABLE DEFAULT_CGO_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND ${GOLANG_BUILD_TOOL} env CGO_CFLAGS) + execute_process(OUTPUT_VARIABLE DEFAULT_CGO_LDFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND ${GOLANG_BUILD_TOOL} env CGO_LDFLAGS) + separate_arguments(DEFAULT_CGO_CFLAGS NATIVE_COMMAND ${DEFAULT_CGO_CFLAGS}) + separate_arguments(DEFAULT_CGO_LDFLAGS NATIVE_COMMAND ${DEFAULT_CGO_LDFLAGS}) + list(PREPEND GOLANG_CGO_CFLAGS ${DEFAULT_CGO_CFLAGS}) + list(PREPEND GOLANG_CGO_LDFLAGS ${DEFAULT_CGO_LDFLAGS}) + if(NOT GOLANG_GOOS) + execute_process(OUTPUT_VARIABLE GOLANG_GOOS OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND ${GOLANG_BUILD_TOOL} env GOOS) + endif() + if(NOT GOLANG_GOARCH) + execute_process(OUTPUT_VARIABLE GOLANG_GOARCH OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND ${GOLANG_BUILD_TOOL} env GOARCH) + endif() + + if(APPLE AND CMAKE_OSX_SYSROOT) + execute_process(OUTPUT_VARIABLE SDKROOT OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND xcrun --sdk ${CMAKE_OSX_SYSROOT} --show-sdk-path) + list(APPEND GOLANG_CGO_CFLAGS -isysroot ${SDKROOT}) + list(APPEND GOLANG_CGO_LDFLAGS -isysroot ${SDKROOT}) + endif() + + ## The actual commands that do the building. + add_custom_target(golang_${GOTARGET} + BYPRODUCTS ${ARCHIVE_NAME} ${HEADER_NAME} + WORKING_DIRECTORY ${DIR_ABSOLUTE} + SOURCES ${SRC_DEPS} ${DIR_NAME}/go.mod + COMMAND ${CMAKE_COMMAND} -E env GOCACHE=${GOCACHE} + CGO_ENABLED=1 + CGO_CFLAGS="${GOLANG_CGO_CFLAGS}" + CGO_LDFLAGS="${GOLANG_CGO_LDFLAGS}" + GOOS="${GOLANG_GOOS}" + GOARCH="${GOLANG_GOARCH}" + ${GOLANG_BUILD_TOOL} build ${GOFLAGS} -o ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME} ${SRC_NAME} + ) + set_target_properties(golang_${GOTARGET} PROPERTIES FOLDER "Libs") + + ## Wrap up the built library as an imported target. + add_library(${GOTARGET} STATIC IMPORTED GLOBAL) + add_dependencies(${GOTARGET} golang_${GOTARGET}) + set_target_properties(${GOTARGET} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR} + INTERFACE_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${HEADER_NAME} + IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME}) +endfunction(add_go_library) \ No newline at end of file diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp index 3b672747..91f21151 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp @@ -21,6 +21,8 @@ OpenVpnLogic::OpenVpnLogic(UiLogic *logic, QObject *parent): m_checkBoxBlockDnsChecked{false}, m_lineEditPortText{}, m_checkBoxTlsAuthChecked{false}, + m_textAreaAdditionalClientConfig{""}, + m_textAreaAdditionalServerConfig{""}, m_pushButtonSaveVisible{false}, m_progressBarResetVisible{false}, @@ -67,6 +69,14 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo bool isTlsAuth = openvpnConfig.value(config_key::tls_auth).toBool(protocols::openvpn::defaultTlsAuth); set_checkBoxTlsAuthChecked(isTlsAuth); + QString additionalClientConfig = openvpnConfig.value(config_key::additional_client_config). + toString(protocols::openvpn::defaultAdditionalClientConfig); + set_textAreaAdditionalClientConfig(additionalClientConfig); + + QString additionalServerConfig = openvpnConfig.value(config_key::additional_server_config). + toString(protocols::openvpn::defaultAdditionalServerConfig); + set_textAreaAdditionalServerConfig(additionalServerConfig); + if (container == DockerContainer::ShadowSocks) { set_radioButtonUdpEnabled(false); set_radioButtonTcpEnabled(false); @@ -142,5 +152,7 @@ QJsonObject OpenVpnLogic::getProtocolConfigFromPage(QJsonObject oldConfig) oldConfig.insert(config_key::block_outside_dns, checkBoxBlockDnsChecked()); oldConfig.insert(config_key::port, lineEditPortText()); oldConfig.insert(config_key::tls_auth, checkBoxTlsAuthChecked()); + oldConfig.insert(config_key::additional_client_config, textAreaAdditionalClientConfig()); + oldConfig.insert(config_key::additional_server_config, textAreaAdditionalServerConfig()); return oldConfig; } diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.h b/client/ui/pages_logic/protocols/OpenVpnLogic.h index 45141050..23c2dd4d 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.h +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.h @@ -22,6 +22,8 @@ class OpenVpnLogic : public PageProtocolLogicBase AUTO_PROPERTY(bool, checkBoxBlockDnsChecked) AUTO_PROPERTY(QString, lineEditPortText) AUTO_PROPERTY(bool, checkBoxTlsAuthChecked) + AUTO_PROPERTY(QString, textAreaAdditionalClientConfig) + AUTO_PROPERTY(QString, textAreaAdditionalServerConfig) AUTO_PROPERTY(bool, pushButtonSaveVisible) AUTO_PROPERTY(bool, progressBarResetVisible) diff --git a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml index e214836f..8387b9fe 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml @@ -281,7 +281,10 @@ PageProtocolBase { font.styleName: "normal" font.pixelSize: 16 color: "#181922" - + text: logic.textAreaAdditionalClientConfig + onEditingFinished: { + logic.textAreaAdditionalClientConfig = text + } } } @@ -294,7 +297,7 @@ PageProtocolBase { implicitWidth: parent.width height: 21 - text: qsTr("Additional client config commands →") + text: qsTr("Additional server config commands →") background: Item { anchors.fill: parent } @@ -305,7 +308,7 @@ PageProtocolBase { font.styleName: "normal" font.pixelSize: 16 color: "#15CDCB"; - text: pb_client_config.text + text: pb_server_config.text horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter } @@ -331,7 +334,10 @@ PageProtocolBase { font.styleName: "normal" font.pixelSize: 16 color: "#181922" - + text: logic.textAreaAdditionalServerConfig + onEditingFinished: { + logic.textAreaAdditionalServerConfig = text + } } } diff --git a/deploy/build_macos.sh b/deploy/build_macos.sh index 09dd85f7..fa955215 100755 --- a/deploy/build_macos.sh +++ b/deploy/build_macos.sh @@ -3,7 +3,7 @@ echo "Build script started ..." set -o errexit -o nounset -while getopts n: flag +while getopts n flag do case "${flag}" in n) NOTARIZE_APP=1;;